搜索结果侧栏显示 ChatGPT 回答

在搜索结果侧栏显示 ChatGPT 回答(Google、Bing、百度和DuckDuckGo)

当前为 2022-12-09 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name chat-gpt-search-sidebar
  3. // @name:zh-CN 搜索结果侧栏显示 ChatGPT 回答
  4. // @version 0.3.5
  5. // @description Display ChatGPT response alongside Search results(Google/Bing/Baidu/DuckDuckGo)
  6. // @description:zh-CN 在搜索结果侧栏显示 ChatGPT 回答(Google、Bing、百度和DuckDuckGo)
  7. // @author Zheng Bang-Bo(https://github.com/zhengbangbo)
  8. // @match https://www.google.com/search*
  9. // @match https://www.google.com.hk/search*
  10. // @match https://www.google.co.jp/search*
  11. // @match https://www.bing.com/search*
  12. // @match https://cn.bing.com/search*
  13. // @match https://www.baidu.com/s*
  14. // @match https://duckduckgo.com/*
  15. // @grant GM_xmlhttpRequest
  16. // @grant GM_log
  17. // @grant GM_setValue
  18. // @grant GM_getValue
  19. // @grant GM_deleteValue
  20. // @grant GM_addStyle
  21. // @namespace https://gf.qytechs.cn/scripts/456077
  22. // @require https://cdn.jsdelivr.net/npm/uuid@8.3.2/dist/umd/uuidv4.min.js
  23. // @connect chat.openai.com
  24. // @license MIT
  25. // ==/UserScript==
  26.  
  27. const container = document.createElement("div");
  28.  
  29. function getSearchEngine() {
  30. if (location.hostname.startsWith("www.google.")){
  31. return 'google'
  32. }
  33. switch (location.hostname) {
  34. case 'www.bing.com':
  35. case 'cn.bing.com':
  36. return 'bing'
  37. case 'www.baidu.com':
  38. return 'baidu'
  39. case 'duckduckgo.com':
  40. return 'duckduckgo'
  41. default:
  42. return 'unknow'
  43. }
  44. }
  45.  
  46. function getQuestion() {
  47. switch (getSearchEngine()) {
  48. case 'baidu':
  49. return new URL(window.location.href).searchParams.get("wd");
  50. default:
  51. return new URL(window.location.href).searchParams.get("q");
  52. }
  53. }
  54.  
  55. function initField() {
  56. container.className = "chat-gpt-container";
  57. container.innerHTML = '<p class="loading">Waiting for ChatGPT response...</p>';
  58. let siderbarContainer = ''
  59.  
  60. switch (getSearchEngine()) {
  61. case 'google':
  62. siderbarContainer = document.getElementById("rhs");
  63. if (siderbarContainer) {
  64. siderbarContainer.prepend(container);
  65. } else {
  66. container.classList.add("sidebar-free");
  67. document.getElementById("rcnt").appendChild(container);
  68. }
  69. break
  70. case 'bing':
  71. siderbarContainer = document.getElementById("b_context");
  72. siderbarContainer.prepend(container);
  73. break
  74. case 'baidu':
  75. siderbarContainer = document.getElementById("content_right");
  76. siderbarContainer.prepend(container);
  77. break
  78. case 'duckduckgo':
  79. siderbarContainer = document.getElementsByClassName("results--sidebar")[0]
  80. siderbarContainer.prepend(container);
  81. break
  82. }
  83.  
  84. GM_addStyle(`
  85. .chat-gpt-container {
  86. max-width: 369px;
  87. margin-bottom: 30px;
  88. border-radius: 8px;
  89. border: 1px solid #dadce0;
  90. padding: 15px;
  91. flex-basis: 0;
  92. flex-grow: 1;
  93. }
  94.  
  95. .chat-gpt-container p {
  96. margin: 0;
  97. }
  98.  
  99. .chat-gpt-container .prefix {
  100. font-weight: bold;
  101. }
  102.  
  103. .chat-gpt-container .loading {
  104. color: #b6b8ba;
  105. animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  106. }
  107.  
  108. @keyframes pulse {
  109. 0%,
  110. 100% {
  111. opacity: 1;
  112. }
  113. 50% {
  114. opacity: 0.5;
  115. }
  116. }
  117.  
  118. .chat-gpt-container.sidebar-free {
  119. margin-left: 60px;
  120. height: fit-content;
  121. }
  122.  
  123. .chat-gpt-container pre {
  124. white-space: pre-wrap;
  125. min-width: 0;
  126. margin-bottom: 0;
  127. line-height: 20px;
  128. }
  129. `)
  130. }
  131.  
  132. function refreshFiled(answer) {
  133. container.innerHTML = '<p><span class="prefix">Chat GPT</span><pre></pre></p>';
  134. container.querySelector("pre").textContent = answer;
  135. }
  136.  
  137. function getAccessToken() {
  138. return new Promise((resolve, rejcet) => {
  139. let accessToken = GM_getValue("accessToken")
  140. if (!accessToken) {
  141. GM_xmlhttpRequest({
  142. url: "https://chat.openai.com/api/auth/session",
  143. onload: function (response) {
  144. const accessToken = JSON.parse(response.responseText).accessToken
  145. if (!accessToken) {
  146. rejcet("UNAUTHORIZED")
  147. }
  148. GM_setValue("accessToken", accessToken)
  149. resolve(accessToken)
  150. },
  151. onerror: function (error) {
  152. rejcet(error)
  153. },
  154. ontimeout: () => {
  155. GM_log("getAccessToken timeout!")
  156. }
  157. })
  158. } else {
  159. resolve(accessToken)
  160. }
  161. })
  162. }
  163.  
  164. async function getAnswer(question) {
  165. try {
  166. const accessToken = await getAccessToken()
  167. GM_xmlhttpRequest({
  168. method: "POST",
  169. url: "https://chat.openai.com/backend-api/conversation",
  170. headers: {
  171. "Content-Type": " application/json",
  172. Authorization: `Bearer ${accessToken}`,
  173. },
  174. data: JSON.stringify({
  175. action: "next",
  176. messages: [
  177. {
  178. id: uuidv4(),
  179. role: "user",
  180. content: {
  181. content_type: "text",
  182. parts: [question],
  183. },
  184. },
  185. ],
  186. model: "text-davinci-002-render",
  187. parent_message_id: uuidv4(),
  188. }),
  189. // onloadstart: function (event) {
  190. // GM_log("getAnswer onloadstart: ", event)
  191. // },
  192. onloadend: function (event) {
  193. // GM_log("getAnswer onloadend: ", event)
  194. if (event.status === 401) {
  195. GM_deleteValue("accessToken")
  196. location.reload()
  197. }
  198. if (event.status != 401 && event.status != 200) {
  199. GM_log('Oops, maybe it is a bug, please submit https://github.com/zhengbangbo/chat-gpt-userscript/issues with follow log of event')
  200. GM_log('event: ', event)
  201. }
  202. if (event.response) {
  203. const answer = JSON.parse(event.response.split("\n\n").slice(-3, -2)[0].slice(6)).message.content.parts[0]
  204. refreshFiled(answer)
  205. }
  206. },
  207. // onprogress: function (event) {
  208. // GM_log("getAnswer onprogress: ", event)
  209. // },
  210. // onreadystatechange: function (event) {
  211. // GM_log("getAnswer onreadystatechange: ", event)
  212. // },
  213. // onload: function (event) {
  214. // GM_log("getAnswer onload: ", event)
  215. // },
  216. onerror: function (event) {
  217. GM_log("getAnswer onerror: ", event)
  218. },
  219. ontimeout: function (event) {
  220. GM_log("getAnswer ontimeout: ", event)
  221. }
  222. })
  223. } catch (error) {
  224. if (error === "UNAUTHORIZED") {
  225. container.innerHTML =
  226. '<p>Please login at <a href="https://chat.openai.com" target="_blank">chat.openai.com</a> first</p>';
  227. }
  228. GM_log("getAccessToken error: ", error)
  229. }
  230. }
  231.  
  232. (async function () {
  233. initField()
  234. getAnswer(getQuestion())
  235. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址