A Day With ChatGPT

A wonderful day spent with ChatGPT

当前为 2023-03-06 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name A Day With ChatGPT
  3. // @namespace https://github.com/mefengl
  4. // @version 0.2.3
  5. // @description A wonderful day spent with ChatGPT
  6. // @icon https://www.google.com/s2/favicons?sz=64&domain=openai.com
  7. // @author mefengl
  8. // @match https://book.douban.com/*
  9. // @match https://www.zhihu.com/*
  10. // @match https://github.com/*
  11. // @match https://chat.openai.com/chat
  12. // @require https://cdn.staticfile.org/jquery/3.6.1/jquery.min.js
  13. // @grant GM_openInTab
  14. // @grant GM_registerMenuCommand
  15. // @grant GM_unregisterMenuCommand
  16. // @grant GM_getValue
  17. // @grant GM_setValue
  18. // @grant GM_addValueChangeListener
  19. // @license MIT
  20. // ==/UserScript==
  21.  
  22. (function () {
  23. 'use strict';
  24.  
  25. const default_menu_all = {
  26. };
  27. const menu_all = GM_getValue("menu_all", default_menu_all);
  28. // 菜单更新的逻辑
  29. // 使用 douban 开启
  30. $(() => location.href.includes("book.douban") && GM_setValue("douban-book", true) && console.log("开启 douban读书 菜单"));
  31. if (GM_getValue("douban-book") == true) {
  32. default_menu_all.douban_book = false;
  33. }
  34. // 使用 zhihu 开启
  35. $(() => location.href.includes("zhihu") && GM_setValue("zhihu", true) && console.log("开启 zhihu 菜单"));
  36. if (GM_getValue("zhihu") == true) {
  37. default_menu_all.zhihu = false;
  38. }
  39. // 使用 github 开启
  40. $(() => location.href.includes("github") && GM_setValue("github", true) && console.log("开启 github 菜单"));
  41. if (GM_getValue("github") == true) {
  42. default_menu_all.github = false;
  43. }
  44. // 检查是否有新增菜单
  45. for (let name in default_menu_all) {
  46. console.log(name);
  47. if (!(name in menu_all)) {
  48. menu_all[name] = default_menu_all[name];
  49. }
  50. }
  51. const menu_id = GM_getValue("menu_id", {});
  52. function update_menu() {
  53. for (let name in menu_all) {
  54. const value = menu_all[name];
  55. // 卸载原来的
  56. if (menu_id[name]) {
  57. GM_unregisterMenuCommand(menu_id[name]);
  58. }
  59. switch (name) {
  60. case "douban_book":
  61. // 添加新的
  62. menu_id[name] = GM_registerMenuCommand(
  63. " douban读书:" + (value ? "✅" : "❌"),
  64. () => {
  65. menu_all[name] = !menu_all[name];
  66. GM_setValue("menu_all", menu_all);
  67. // 调用时触发,刷新菜单
  68. update_menu();
  69. // 该设置需刷新生效
  70. location.reload();
  71. }
  72. );
  73. break;
  74. case "zhihu":
  75. // 添加新的
  76. menu_id[name] = GM_registerMenuCommand(
  77. " zhihu:" + (value ? "✅" : "❌"),
  78. () => {
  79. menu_all[name] = !menu_all[name];
  80. GM_setValue("menu_all", menu_all);
  81. // 调用时触发,刷新菜单
  82. update_menu();
  83. // 该设置需刷新生效
  84. location.reload();
  85. }
  86. );
  87. break;
  88. case "github":
  89. // 添加新的
  90. menu_id[name] = GM_registerMenuCommand(
  91. " github:" + (value ? "✅" : "❌"),
  92. () => {
  93. menu_all[name] = !menu_all[name];
  94. GM_setValue("menu_all", menu_all);
  95. // 调用时触发,刷新菜单
  96. update_menu();
  97. // 该设置需刷新生效
  98. location.reload();
  99. }
  100. );
  101. break;
  102. default:
  103. break;
  104. }
  105. };
  106. GM_setValue("menu_id", menu_id);
  107. }
  108. update_menu();
  109.  
  110. // douban_book
  111. const douban_book_prompts = [
  112. (title, author) => `${author}的《${title}》简要介绍会是:`,
  113. (title, author) => `《${title}》的作者${author}简要介绍会是:`,
  114. (title, author) => `${author}的《${title}》的主要观点列成表格会是:`,
  115. (title, author) => `${author}的《${title}》的类似书籍或文章和它们的区别会是:`,
  116. (title, author) => `${author}的《${title}》的观点相反的书籍或文章和对应的观点会是:`,
  117. (title, author) => `${author}的《${title}》的正面评论会是:`,
  118. (title, author) => `${author}的《${title}》的负面评论会是:`,
  119. (title, author) => `${author}的《${title}》在哪些方面是有争议的会是:`,
  120. (title, author) => `${author}的《${title}》当人们生活在不同的时代时,会有什么不同的观点会是:`,
  121. (title, author) => `${author}的《${title}》当人们生活在火星时,会有什么不同的观点会是:`,
  122. (title, author) => `${author}的《${title}》综合Goodreads评分和豆瓣等各种评分和评价会是:`,
  123. (title, author) => `${author}的《${title}》比较重要的章节会是:`,
  124. (title, author) => `${author}的《${title}》可以和这些书籍或文章进行比较阅读:`,
  125. (title, author) => `${author}的《${title}》可以和这些书籍或文章进行主题阅读:`,
  126. ]
  127. // a cache for lastest 10 title-author
  128. menu_all.douban_book && $(() => {
  129. if (location.href.includes("book.douban.com/subject")) {
  130. const title = $("meta[property='og:title']").attr("content");
  131. const author = $("meta[property='book:author']").attr("content");
  132. const douban_book_cache = GM_getValue("douban_book_cache", []);
  133. // if not in cache, add it, or return
  134. // if (!douban_book_cache.some(item => item.title == title && item.author == author)) {
  135. if (true) {
  136. douban_book_cache.push({ title, author });
  137. if (douban_book_cache.length > 10) {
  138. douban_book_cache.shift();
  139. }
  140. GM_setValue("douban_book_cache", douban_book_cache);
  141.  
  142. // trigger ChatGPT
  143. const prompt_texts = douban_book_prompts.map(prompt => prompt(title, author));
  144. GM_setValue("prompt_texts", prompt_texts);
  145. } else { return; }
  146. }
  147. });
  148. // zhihu
  149. const zhihu_prompts = [
  150. (question) => `问题:${question},这么问可能会更好:`,
  151. (question) => `问题:${question},暗含的观点是:`,
  152. (question) => `问题:${question},提问者和提问者的目的是:`,
  153. (question) => `问题:${question},问题的相关背景是:`,
  154. (question) => `问题:${question},问题的相关历史是:`,
  155. (question) => `问题:${question},问题的相关法律是:`,
  156. (question) => `问题:${question},问题的相关政策是:`,
  157. (question) => `问题:${question},问题的相关经济是:`,
  158. (question) => `问题:${question},问题的相关科学是:`,
  159. (question) => `问题:${question},问题的相关文化是:`,
  160. (question) => `问题:${question},问题的责任方是:`,
  161. (question) => `问题:${question},不同的职业对这个问题的看法会是:`,
  162. (question) => `问题:${question},不同的年龄段对这个问题的看法会是:`,
  163. (question) => `问题:${question},不同的性别对这个问题的看法会是:`,
  164. (question) => `问题:${question},不同的国家对这个问题的看法会是:`,
  165. (question) => `问题:${question},火星人对这个问题的看法会是:`,
  166. (question) => `问题:${question},在火星上,这个问题:`,
  167. (question) => `问题:${question},类似问题和它们的区别会是:`,
  168. (question) => `问题:${question},观点相反的问题和对应的观点会是:`,
  169. (question) => `问题:${question},正面回答会是:`,
  170. (question) => `问题:${question},反面回答会是:`,
  171. (question) => `问题:${question},有趣的回答会是:`,
  172. (question) => `问题:${question},主要观点列成表格会是:`,
  173. (question) => `问题:${question},相关书籍、文章、视频或网站会是:`,
  174. (question) => `从这个问题:${question},可以引申出这些问题:`,
  175. (question) => `问题:${question},可以和这些问题进行比较阅读:`,
  176. (question) => `问题:${question},应该去反思:`,
  177. (question) => `问题:${question},想要改进或解决它,可以从这些方面入手:`,
  178. ]
  179.  
  180. menu_all.zhihu && $(() => {
  181. if (location.href.includes("zhihu.com/question")) {
  182. const question = $('meta[itemprop="name"]').attr('content');
  183. const zhihu_cache = GM_getValue("zhihu_cache", []);
  184. // if not in cache, add it, or return
  185. // if (!zhihu_cache.some(item => item.question == question)) {
  186. if (true) {
  187. zhihu_cache.push({ question });
  188. if (zhihu_cache.length > 10) {
  189. zhihu_cache.shift();
  190. }
  191. GM_setValue("zhihu_cache", zhihu_cache);
  192. // trigger ChatGPT
  193. const prompt_texts = zhihu_prompts.map(prompt => prompt(question));
  194. GM_setValue("prompt_texts", prompt_texts);
  195. } else { return; }
  196. }
  197. });
  198.  
  199. // github
  200. const github_prompts = [
  201. (website) => `${website}的简要介绍是:`,
  202. (website) => `${website}的主要功能列成表格是:`,
  203. (website) => `${website}的维护情况是:`,
  204. (website) => `${website}的安装方法和最小使用样例是:`,
  205. (website) => `${website}的最佳实践是:`,
  206. (website) => `${website}的类似项目是:`,
  207. (website) => `${website}的不同之处是:`,
  208. (website) => `${website}的正面评论是:`,
  209. (website) => `${website}的负面评论是:`,
  210. (website) => `${website}的相关书籍、文章、视频或网站是:`,
  211. (website) => `${website}的上一代项目是:`,
  212. (website) => `${website}的下一代项目是:`,
  213. (website) => `${website}的应用场景是:`,
  214. (website) => `${website}的不适用场景是:`,
  215. (website) => `${website}可以解决的问题是:`,
  216. (website) => `我应该用这个项目,因为:`,
  217. (website) => `我不应该用这个项目,因为:`,
  218. (website) => `如果我想改进${website},我可以从这些项目入手:`,
  219. ]
  220. menu_all.github && $(() => {
  221. // github repo?
  222. if (!location.href.includes("github.com")) { return; }
  223. const parts = location.href.split("/");
  224. if (parts.length >= 5 && parts[parts.length - 2] && parts[parts.length - 1]) {
  225. const github_cache = GM_getValue("github_cache", []);
  226. // if (!github_cache.some(item => item.website == location.href)) {
  227. if (true) {
  228. github_cache.push({ website: location.href });
  229. if (github_cache.length > 10) {
  230. github_cache.shift();
  231. }
  232. GM_setValue("github_cache", github_cache);
  233. // trigger ChatGPT
  234. const prompt_texts = github_prompts.map(prompt => prompt(location.href));
  235. GM_setValue("prompt_texts", prompt_texts);
  236. } else { return; }
  237. }
  238. });
  239.  
  240. /* ************************************************************************* */
  241. // ChatGPT response to prompt_texts
  242. const get_submit_button = () => {
  243. const form = document.querySelector('form');
  244. const buttons = form.querySelectorAll('button');
  245. const result = buttons[buttons.length - 1]; // by textContent maybe better
  246. return result;
  247. };
  248. const get_textarea = () => {
  249. const form = document.querySelector('form');
  250. const textareas = form.querySelectorAll('textarea');
  251. const result = textareas[0];
  252. return result;
  253. };
  254. const get_regenerate_button = () => {
  255. const form = document.querySelector('form');
  256. const buttons = form.querySelectorAll('button');
  257. for (let i = 0; i < buttons.length; i++) {
  258. const buttonText = buttons[i].textContent.trim().toLowerCase();
  259. if (buttonText.includes('regenerate')) {
  260. return buttons[i];
  261. }
  262. }
  263. };
  264.  
  265. let last_trigger_time = +new Date();
  266. $(() => {
  267. if (location.href.includes("chat.openai")) {
  268. console.log("ChatGPT");
  269. GM_addValueChangeListener("prompt_texts", (name, old_value, new_value) => {
  270. if (+new Date() - last_trigger_time < 500) {
  271. return;
  272. }
  273. last_trigger_time = new Date();
  274. setTimeout(async () => {
  275. console.log("ChatGPT页面响应prompt_texts");
  276. const prompt_texts = new_value;
  277. console.log(prompt_texts);
  278. if (prompt_texts.length > 0) {
  279. console.log("进入处理");
  280. // get prompt_texts from local
  281. let firstTime = true;
  282. while (prompt_texts.length > 0) {
  283. if (!firstTime) {
  284. await new Promise(resolve => setTimeout(resolve, 2000));
  285. }
  286. if (!firstTime && get_regenerate_button() == undefined) {
  287. continue;
  288. }
  289. firstTime = false;
  290. const prompt_text = prompt_texts.shift();
  291. console.log(prompt_text);
  292. // write the prompt_text
  293. get_textarea().value = prompt_text;
  294. // submit
  295. get_submit_button().click();
  296. }
  297. }
  298. }, 0);
  299. GM_setValue("prompt_texts", []);
  300. });
  301. }
  302. });
  303. })();