Twitter - 为用户添加备注(别名/标签)

为用户添加备注(别名/标签)功能,以帮助识别和搜索

当前为 2022-04-03 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Twitter - Add notes to the user
  3. // @name:zh-CN Twitter - 为用户添加备注(别名/标签)
  4. // @name:zh-TW Twitter - 為用戶添加備註(別名/標籤)
  5. // @name:ja Twitter - ユーザーへのメモの追加(エイリアス/ラベル)
  6. // @name:ko Twitter - 사용자에게 메모 추가 (별칭/라벨)
  7. // @name:fr Twitter - ajouter des notes aux utilisateurs (alias/tag)
  8. // @namespace https://gf.qytechs.cn/zh-CN/users/193133-pana
  9. // @homepage https://gf.qytechs.cn/zh-CN/users/193133-pana
  10. // @icon data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9Im5ld0ljb25UaXRsZSIgc3Ryb2tlPSJyZ2JhKDI5LDE2MSwyNDIsMS4wMCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYmEoMjksMTYxLDI0MiwxLjAwKSI+IDx0aXRsZSBpZD0ibmV3SWNvblRpdGxlIj5OZXc8L3RpdGxlPiA8cGF0aCBkPSJNMTkgMTRWMjJIMi45OTk5N1Y0SDEzIi8+IDxwYXRoIGQ9Ik0xNy40NjA4IDQuMDM5MjFDMTguMjQxOCAzLjI1ODE3IDE5LjUwODIgMy4yNTgxNiAyMC4yODkyIDQuMDM5MjFMMjAuOTYwOCA0LjcxMDc5QzIxLjc0MTggNS40OTE4NCAyMS43NDE4IDYuNzU4MTcgMjAuOTYwOCA3LjUzOTIxTDExLjU4NTggMTYuOTE0MkMxMS4yMTA3IDE3LjI4OTMgMTAuNzAyIDE3LjUgMTAuMTcxNiAxNy41TDcuNSAxNy41TDcuNSAxNC44Mjg0QzcuNSAxNC4yOTggNy43MTA3MSAxMy43ODkzIDguMDg1NzkgMTMuNDE0MkwxNy40NjA4IDQuMDM5MjFaIi8+IDxwYXRoIGQ9Ik0xNi4yNSA1LjI1TDE5Ljc1IDguNzUiLz4gPC9zdmc+
  11. // @version 4.3.0
  12. // @description Add a note(alias/tag) for users to help identify and search
  13. // @description:zh-CN 为用户添加备注(别名/标签)功能,以帮助识别和搜索
  14. // @description:zh-TW 為用戶添加備註(別名/標籤)功能,以幫助識別和搜尋
  15. // @description:ja ユーザーが識別と検索に役立つメモ(エイリアス/タグ)機能を追加する
  16. // @description:ko 사용자 식별 및 검색에 도움이되는 메모 (별칭/태그) 기능 추가
  17. // @description:fr Ajouter une fonction de notes (alias/tag) pour les utilisateurs pour aider à identifier et rechercher
  18. // @author pana
  19. // @license GNU General Public License v3.0 or later
  20. // @compatible chrome
  21. // @compatible firefox
  22. // @match *://*twitter.com/*
  23. // @require https://cdn.jsdelivr.net/npm/arrive@2.4.1/minified/arrive.min.js
  24. // @require https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.min.js
  25. // @require https://cdn.jsdelivr.net/gh/LightAPIs/greasy-fork-library@c5961e56c4461790de3a52f1502e6c007ff64b4a/Note_Obj.js
  26. // @noframes
  27. // @grant GM_info
  28. // @grant GM.info
  29. // @grant GM_getValue
  30. // @grant GM.getValue
  31. // @grant GM_setValue
  32. // @grant GM.setValue
  33. // @grant GM_deleteValue
  34. // @grant GM.deleteValue
  35. // @grant GM_listValues
  36. // @grant GM.listValues
  37. // @grant GM_openInTab
  38. // @grant GM.openInTab
  39. // @grant GM_registerMenuCommand
  40. // @grant GM_unregisterMenuCommand
  41. // @grant GM_addValueChangeListener
  42. // @grant GM_removeValueChangeListener
  43. // ==/UserScript==
  44.  
  45. (async function () {
  46. 'use strict';
  47. if (typeof Note_Obj !== 'function') {
  48. alert('Note_Obj.js was not loaded successfully!');
  49. }
  50. const UPDATED = '2022-04-03';
  51. const TWITTER_ICON = {
  52. NOTE_GRAY:
  53. 'url(data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9Im5ld0ljb25UaXRsZSIgc3Ryb2tlPSJyZ2IoMTAxLCAxMTksIDEzNCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYigxMDEsIDExOSwgMTM0KSI+IDx0aXRsZSBpZD0ibmV3SWNvblRpdGxlIj5OZXc8L3RpdGxlPiA8cGF0aCBkPSJNMTkgMTRWMjJIMi45OTk5N1Y0SDEzIi8+IDxwYXRoIGQ9Ik0xNy40NjA4IDQuMDM5MjFDMTguMjQxOCAzLjI1ODE3IDE5LjUwODIgMy4yNTgxNiAyMC4yODkyIDQuMDM5MjFMMjAuOTYwOCA0LjcxMDc5QzIxLjc0MTggNS40OTE4NCAyMS43NDE4IDYuNzU4MTcgMjAuOTYwOCA3LjUzOTIxTDExLjU4NTggMTYuOTE0MkMxMS4yMTA3IDE3LjI4OTMgMTAuNzAyIDE3LjUgMTAuMTcxNiAxNy41TDcuNSAxNy41TDcuNSAxNC44Mjg0QzcuNSAxNC4yOTggNy43MTA3MSAxMy43ODkzIDguMDg1NzkgMTMuNDE0MkwxNy40NjA4IDQuMDM5MjFaIi8+IDxwYXRoIGQ9Ik0xNi4yNSA1LjI1TDE5Ljc1IDguNzUiLz4gPC9zdmc+)',
  54. NOTE_BLUE:
  55. 'url(data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9Im5ld0ljb25UaXRsZSIgc3Ryb2tlPSJyZ2JhKDI5LDE2MSwyNDIsMS4wMCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYmEoMjksMTYxLDI0MiwxLjAwKSI+IDx0aXRsZSBpZD0ibmV3SWNvblRpdGxlIj5OZXc8L3RpdGxlPiA8cGF0aCBkPSJNMTkgMTRWMjJIMi45OTk5N1Y0SDEzIi8+IDxwYXRoIGQ9Ik0xNy40NjA4IDQuMDM5MjFDMTguMjQxOCAzLjI1ODE3IDE5LjUwODIgMy4yNTgxNiAyMC4yODkyIDQuMDM5MjFMMjAuOTYwOCA0LjcxMDc5QzIxLjc0MTggNS40OTE4NCAyMS43NDE4IDYuNzU4MTcgMjAuOTYwOCA3LjUzOTIxTDExLjU4NTggMTYuOTE0MkMxMS4yMTA3IDE3LjI4OTMgMTAuNzAyIDE3LjUgMTAuMTcxNiAxNy41TDcuNSAxNy41TDcuNSAxNC44Mjg0QzcuNSAxNC4yOTggNy43MTA3MSAxMy43ODkzIDguMDg1NzkgMTMuNDE0MkwxNy40NjA4IDQuMDM5MjFaIi8+IDxwYXRoIGQ9Ik0xNi4yNSA1LjI1TDE5Ljc1IDguNzUiLz4gPC9zdmc+)',
  56. };
  57. const TWITTER_STYLE = `
  58. .note-obj-twitter-blue-tag {
  59. background-color: #3c81df;
  60. color: #fff;
  61. display: inline-flex;
  62. align-items: center;
  63. padding: 2px 10px;
  64. line-height: 100%;
  65. border-radius: 50px;
  66. }
  67. .note-obj-twitter-note-btn {
  68. background-image: ${TWITTER_ICON.NOTE_GRAY};
  69. background-repeat: no-repeat;
  70. background-position: center;
  71. background-color: rgba(0, 0, 0, 0);
  72. border-bottom-left-radius: 9999px;
  73. border-bottom-right-radius: 9999px;
  74. border-top-left-radius: 9999px;
  75. border-top-right-radius: 9999px;
  76. transition-property: background-color, box-shadow;
  77. transition-duration: 0.2s;
  78. }
  79. .note-obj-twitter-note-btn:hover {
  80. background-image: ${TWITTER_ICON.NOTE_BLUE};
  81. background-color: rgba(29, 161, 242, .1);
  82. }
  83. .note-obj-twitter-panel-btn {
  84. height: 32px;
  85. width: 32px;
  86. margin: 5px 0px 0px 0px;
  87. background-size: 28px auto;
  88. cursor: pointer !important;
  89. border-radius: 0px;
  90. }
  91. .note-obj-twitter-panel-btn:hover::after {
  92. content: "";
  93. display: flex;
  94. position: relative;
  95. background-color: rgba(29, 161, 242, .1);
  96. width: 48px;
  97. height: 48px;
  98. top: -8px;
  99. left: -8px;
  100. border-radius: 99px;
  101. }
  102. .note-obj-twitter-before-follow-note-btn {
  103. height: 36px;
  104. width: 36px;
  105. background-image: ${TWITTER_ICON.NOTE_BLUE};
  106. background-repeat: no-repeat;
  107. background-size: 19px auto;
  108. background-position: center;
  109. margin-bottom: 12px;
  110. margin-right: 12px;
  111. cursor: pointer;
  112. border: 1px solid rgba(29, 161, 242, 1);
  113. border-bottom-left-radius: 9999px;
  114. border-bottom-right-radius: 9999px;
  115. border-top-left-radius: 9999px;
  116. border-top-right-radius: 9999px;
  117. background-color: rgba(0, 0, 0, 0);
  118. transition-property: background-color, box-shadow;
  119. transition-duration: 0.2s;
  120. }
  121. .note-obj-twitter-before-follow-note-btn:hover {
  122. background-color: rgba(29, 161, 242, .1);
  123. }
  124. .note-obj-twitter-base-tool-bar-btn {
  125. height: 18px;
  126. width: 18px;
  127. margin: 0px -40px 0px 0px;
  128. background-size: 20px auto;
  129. border-radius: 0px;
  130. }
  131. .note-obj-twitter-base-tool-bar-btn:hover::after {
  132. content: "";
  133. position: absolute;
  134. background-color: rgba(29, 161, 242, .1);
  135. width: 34px;
  136. height: 34px;
  137. top: -8px;
  138. left: -8px;
  139. border-radius: 99px;
  140. }
  141. .note-obj-twitter-comment-tool-bar-btn {
  142. height: 24px;
  143. width: 24px;
  144. margin: 12px 0px 0px 0px;
  145. background-size: 24px auto;
  146. border-radius: 0px;
  147. cursor: pointer;
  148. }
  149. .note-obj-twitter-comment-tool-bar-btn:hover::after {
  150. content: "";
  151. position: absolute;
  152. background-color: rgba(29, 161, 242, .1);
  153. width: 38px;
  154. height: 38px;
  155. top: -8px;
  156. left: -8px;
  157. border-radius: 99px;
  158. }
  159. .note-obj-twitter-left-box {
  160. height: 50%;
  161. }
  162. `;
  163. const selector = {
  164. root: '#react-root div .r-13awgt0.r-12vffkv',
  165. homepage: {
  166. id: '.css-901oao.css-bfa6kz.r-18u37iz.r-37j5jr.r-16dba41.r-bcqeeo.r-qvutc0 > span',
  167. article: 'article',
  168. toolBar: '.css-1dbjc4n.r-18u37iz.r-1wtj0ep.r-1mdbhws',
  169. showName: '.css-901oao.css-bfa6kz.r-bcqeeo.r-poiln3.r-qvutc0 > span',
  170. reprintA: '.css-1dbjc4n.r-1habvwh.r-16y2uox a',
  171. reprintName: ':scope > span:first-of-type > span',
  172. at: 'a.css-4rbku5.css-18t94o4.css-901oao.css-16my406.r-1loqt21.r-bcqeeo.r-qvutc0',
  173. userFrame: '.css-18t94o4.css-1dbjc4n.r-1loqt21.r-1wbh5a2.r-dnmrzs.r-1ny4l3l',
  174. blockquote: 'div[role="blockquote"]',
  175. },
  176. userpage: {
  177. main: '.css-1dbjc4n.r-1ifxtd0.r-ymttw5.r-ttdzmv',
  178. id: '[data-testid="UserName"] .css-1dbjc4n.r-18u37iz.r-1wbh5a2 span',
  179. showName: '[data-testid="UserName"] .css-901oao.r-1vr29t4.r-bcqeeo.r-qvutc0 > span',
  180. follow: '.css-1dbjc4n.r-obd0qt.r-18u37iz.r-1w6e6rj.r-1h0z5md.r-dnmrzs',
  181. },
  182. comment: {
  183. toolBar: '.css-1dbjc4n.r-1oszu61.r-1efd50x.r-5kkj8d.r-18u37iz.r-a2tzq0',
  184. },
  185. hover: {
  186. panel: 'div.css-1dbjc4n.r-nsbfu8',
  187. followBtn: '.css-1dbjc4n.r-bcqeeo',
  188. id: '.css-1dbjc4n.r-18u37iz.r-1wbh5a2',
  189. showName: '.css-1dbjc4n.r-14gqq1x .css-901oao.css-bfa6kz.r-bcqeeo.r-poiln3.r-qvutc0 > span',
  190. },
  191. modal: {
  192. cell: '[aria-labelledby="modal-header"] [data-testid="UserCell"]',
  193. },
  194. };
  195. const noteObj = new Note_Obj('myTwitterNote');
  196. await noteObj.init({
  197. style: selector.homepage.showName + ' { white-space: normal; }\n' + TWITTER_STYLE,
  198. changeEvent: changeEvent,
  199. settings: {
  200. showToolbarButton: {
  201. type: 'checkbox',
  202. lang: {
  203. en: 'Display the "Add Note" button in the toolbar below each tweet (if there is no such button in the user\'s hover information panel, this option can be turned on)',
  204. zh_cn: '在每条推特下方的工具栏里显示"添加备注"按钮 (如果在用户的悬停信息面板里没有此按钮时,可以打开此选项)',
  205. zh_tw: '在每條推特下方的工具欄裡顯示"添加備註"按鈕 (如果在用戶的懸停資訊面板裡沒有此按鈕時,可以打開此選項)',
  206. ja: '各Twitterの下のツールバーに“備考追加”ボタンが表示されます(ユーザのホバリング情報パネルにこのボタンがない場合は、このオプションを開くことができます)',
  207. ko: '각 트위터 아래의 도구 모음에 "메모 추가" 단추가 표시됩니다(사용자의 롤오버 정보 패널에 이 단추가 없는 경우 이 옵션을 설정할 수 있음)',
  208. fr: "Afficher le bouton \"Ajouter une note\" dans la barre d'outils sous chaque tweet (S'il n'y a pas de bouton de ce type dans le panneau d'informations de survol de l'utilisateur, vous pouvez activer cette option)",
  209. },
  210. default: false,
  211. event: insertToolbarButtonEvent,
  212. },
  213. disableInTweets: {
  214. type: 'checkbox',
  215. lang: {
  216. en: 'Disable replaces peoples @username to @note in tweets',
  217. zh_cn: '禁止将推文中的用户 @username 替换为 @note',
  218. zh_tw: '禁止將推文中的使用者 @username 替换为 @note',
  219. ja: '無効にすると、ツイート内のユーザーの@usernameが@noteに置き換えられます',
  220. ko: '비활성화는 트윗에서 @username을 @note로 대체합니다',
  221. fr: "Désactiver remplace le @nom d'utilisateur par @note dans les tweets",
  222. },
  223. default: false,
  224. event: disableInTweetsEvent,
  225. },
  226. },
  227. script: {
  228. author: {
  229. name: 'pana',
  230. homepage: 'https://gf.qytechs.cn/zh-CN/users/193133-pana',
  231. },
  232. address: 'https://gf.qytechs.cn/scripts/404587',
  233. updated: UPDATED,
  234. library: [
  235. {
  236. name: 'arrive.js',
  237. version: '2.4.1',
  238. url: 'https://github.com/uzairfarooq/arrive',
  239. },
  240. ],
  241. },
  242. leftBtnBoxClassName: 'note-obj-twitter-left-box',
  243. });
  244. function disableInTweetsEvent(status) {
  245. for (const ele of document.querySelectorAll(selector.homepage.article)) {
  246. for (const atUser of ele.querySelectorAll(selector.homepage.at)) {
  247. const atUserId = Note_Obj.fn.getUserIdFromLink(atUser.href, value => /^[^/]+$/i.test(value));
  248. noteObj.judgeUsers(atUserId) &&
  249. noteObj.handler(atUserId, atUser, null, {
  250. symbol: {
  251. prefix: '@',
  252. },
  253. restore: status,
  254. });
  255. }
  256. }
  257. }
  258. function insertToolbarButtonEvent(status) {
  259. document.querySelectorAll(selector.homepage.article).forEach(ele => {
  260. if (ele.querySelector(selector.homepage.id)) {
  261. const eleId = ele.querySelector(selector.homepage.id).textContent.replace(/^@/, '');
  262. const eleName = ele.querySelector(selector.homepage.showName).textContent;
  263. const toolBar = ele.querySelector(selector.homepage.toolBar);
  264. const commentToolBar = ele.querySelector(selector.comment.toolBar);
  265. if (status) {
  266. toolBar &&
  267. !toolBar.querySelector('.note-obj-add-note-btn') &&
  268. toolBar.appendChild(
  269. noteObj.createNoteBtn(eleId, eleName, ['note-obj-twitter-note-btn', 'note-obj-twitter-base-tool-bar-btn', 'css-1dbjc4n'])
  270. );
  271. commentToolBar &&
  272. !commentToolBar.querySelector('.note-obj-add-note-btn') &&
  273. commentToolBar.appendChild(
  274. noteObj.createNoteBtn(eleId, eleName, ['note-obj-twitter-note-btn', 'note-obj-twitter-comment-tool-bar-btn', 'css-1dbjc4n'])
  275. );
  276. } else {
  277. toolBar && toolBar.querySelector('.note-obj-add-note-btn') && toolBar.querySelector('.note-obj-add-note-btn').remove();
  278. commentToolBar &&
  279. commentToolBar.querySelector('.note-obj-add-note-btn') &&
  280. commentToolBar.querySelector('.note-obj-add-note-btn').remove();
  281. }
  282. }
  283. });
  284. }
  285. function changeEvent(noteObj, userId = null) {
  286. for (const ele of document.querySelectorAll(selector.homepage.article)) {
  287. if (ele.querySelector(selector.homepage.id)) {
  288. const eleId = ele.querySelector(selector.homepage.id).textContent.replace(/^@/, '');
  289. (!userId || userId == eleId) &&
  290. noteObj.handler(eleId, ele, selector.homepage.showName, {
  291. add: 'span',
  292. classname: 'note-obj-twitter-blue-tag',
  293. });
  294. }
  295. const reprintA = ele.querySelector(selector.homepage.reprintA);
  296. if (reprintA) {
  297. const reprintId = Note_Obj.fn.getUserIdFromLink(reprintA.href);
  298. (!userId || userId == reprintId) &&
  299. noteObj.handler(reprintId, reprintA, selector.homepage.reprintName, {
  300. add: 'span',
  301. classname: 'note-obj-twitter-blue-tag',
  302. symbol: {
  303. offsetWidth: 30,
  304. },
  305. });
  306. }
  307. const blockquoteUser = ele.querySelector(selector.homepage.blockquote);
  308. if (blockquoteUser) {
  309. const blockquoteUserId = blockquoteUser.querySelector(selector.homepage.id).textContent.replace(/^@/, '');
  310. if (blockquoteUserId == userId) {
  311. noteObj.handler(userId, blockquoteUser, selector.homepage.showName);
  312. }
  313. (!userId || userId == blockquoteUserId) &&
  314. noteObj.handler(blockquoteUserId, blockquoteUser, selector.homepage.showName, {
  315. add: 'span',
  316. classname: 'note-obj-twitter-blue-tag',
  317. });
  318. }
  319. for (const atUser of ele.querySelectorAll(selector.homepage.at)) {
  320. const atUserId = Note_Obj.fn.getUserIdFromLink(atUser.href, value => /^[^/]+$/i.test(value));
  321. (!userId || userId == atUserId) &&
  322. noteObj.judgeUsers(atUserId) &&
  323. noteObj.handler(atUserId, atUser, null, {
  324. symbol: {
  325. prefix: '@',
  326. },
  327. restore: noteObj.getConfig().other.disableInTweets,
  328. });
  329. }
  330. }
  331. for (const ele of document.querySelectorAll(selector.userpage.main)) {
  332. const user = ele.querySelector(selector.userpage.id);
  333. if (user) {
  334. const eleId = user.textContent.replace(/^@/, '');
  335. (!userId || userId == eleId) &&
  336. noteObj.handler(eleId, ele, selector.userpage.showName, {
  337. add: 'span',
  338. classname: 'note-obj-twitter-blue-tag',
  339. });
  340. }
  341. }
  342. for (const ele of document.querySelectorAll(selector.homepage.userFrame)) {
  343. const user = ele.querySelector(selector.userpage.id);
  344. if (user) {
  345. const eleId = user.textContent.replace(/^@/, '');
  346. (!userId || userId == eleId) &&
  347. noteObj.handler(eleId, ele, selector.homepage.showName, {
  348. add: 'span',
  349. class: 'note-obj-twitter-blue-tag',
  350. });
  351. }
  352. }
  353. for (const ele of document.querySelectorAll(selector.modal.cell)) {
  354. const user = ele.querySelector(selector.homepage.id);
  355. if (user) {
  356. const eleId = user.textContent.replace(/^@/, '');
  357. (!userId || userId == eleId) &&
  358. noteObj.handler(eleId, ele, selector.homepage.showName, {
  359. add: 'span',
  360. class: 'note-obj-twitter-blue-tag',
  361. });
  362. }
  363. }
  364. }
  365. function init() {
  366. const arriveOption = {
  367. fireOnAttributesModification: true,
  368. existing: true,
  369. };
  370. document.querySelector(selector.root).arrive(selector.homepage.article, arriveOption, ele => {
  371. if (ele.querySelector(selector.homepage.id)) {
  372. const eleId = ele.querySelector(selector.homepage.id).textContent.replace(/^@/, '');
  373. const eleName = ele.querySelector(selector.homepage.showName).textContent;
  374. noteObj.getConfig().other.showToolbarButton &&
  375. ele.querySelector(selector.homepage.toolBar) &&
  376. ele
  377. .querySelector(selector.homepage.toolBar)
  378. .appendChild(
  379. noteObj.createNoteBtn(eleId, eleName, ['note-obj-twitter-note-btn', 'note-obj-twitter-base-tool-bar-btn', 'css-1dbjc4n'])
  380. );
  381. noteObj.getConfig().other.showToolbarButton &&
  382. ele.querySelector(selector.comment.toolBar) &&
  383. ele
  384. .querySelector(selector.comment.toolBar)
  385. .appendChild(
  386. noteObj.createNoteBtn(eleId, eleName, ['note-obj-twitter-note-btn', 'note-obj-twitter-comment-tool-bar-btn', 'css-1dbjc4n'])
  387. );
  388. noteObj.judgeUsers(eleId) &&
  389. noteObj.handler(
  390. eleId,
  391. ele,
  392. selector.homepage.showName,
  393. {
  394. add: 'span',
  395. classname: 'note-obj-twitter-blue-tag',
  396. },
  397. eleName
  398. );
  399. }
  400. const reprintA = ele.querySelector(selector.homepage.reprintA);
  401. if (reprintA) {
  402. const reprintId = Note_Obj.fn.getUserIdFromLink(reprintA.href);
  403. noteObj.judgeUsers(reprintId) &&
  404. noteObj.handler(reprintId, reprintA, selector.homepage.reprintName, {
  405. add: 'span',
  406. classname: 'note-obj-twitter-blue-tag',
  407. symbol: {
  408. offsetWidth: 30,
  409. },
  410. });
  411. }
  412. const blockquoteUser = ele.querySelector(selector.homepage.blockquote);
  413. if (blockquoteUser) {
  414. const blockquoteUserId = blockquoteUser.querySelector(selector.homepage.id).textContent.replace(/^@/, '');
  415. noteObj.judgeUsers(blockquoteUserId) &&
  416. noteObj.handler(blockquoteUserId, blockquoteUser, selector.homepage.showName, {
  417. add: 'span',
  418. classname: 'note-obj-twitter-blue-tag',
  419. });
  420. }
  421. if (!noteObj.getConfig().other.disableInTweets) {
  422. for (const atUser of ele.querySelectorAll(selector.homepage.at)) {
  423. const atUserId = Note_Obj.fn.getUserIdFromLink(atUser.href, value => /^[^/]+$/i.test(value));
  424. noteObj.judgeUsers(atUserId) &&
  425. noteObj.handler(atUserId, atUser, null, {
  426. symbol: {
  427. prefix: '@',
  428. },
  429. });
  430. }
  431. }
  432. });
  433. document.querySelector(selector.root).arrive(selector.userpage.main, arriveOption, ele => {
  434. const eleId = ele.querySelector(selector.userpage.id).textContent.replace(/^@/, '');
  435. const eleName = ele.querySelector(selector.userpage.showName).textContent;
  436. let followNoteBtn;
  437. if (ele.querySelector(selector.userpage.follow)) {
  438. followNoteBtn = noteObj.createNoteBtn(eleId, eleName, ['note-obj-twitter-before-follow-note-btn', 'css-901oao']);
  439. ele.querySelector(selector.userpage.follow).insertAdjacentElement('afterbegin', followNoteBtn);
  440. }
  441. noteObj.judgeUsers(eleId) &&
  442. noteObj.handler(
  443. eleId,
  444. ele,
  445. selector.userpage.showName,
  446. {
  447. add: 'span',
  448. classname: 'note-obj-twitter-blue-tag',
  449. },
  450. eleName
  451. );
  452. const userIdChange = new MutationObserver(() => {
  453. const newUserId = ele.querySelector(selector.userpage.id).textContent.replace(/^@/, '');
  454. noteObj.handler('', ele, selector.userpage.showName, {
  455. add: 'span',
  456. classname: 'note-obj-twitter-blue-tag',
  457. });
  458. const newUserName = ele.querySelector(selector.userpage.showName).textContent;
  459. if (followNoteBtn) {
  460. followNoteBtn.remove();
  461. followNoteBtn = noteObj.createNoteBtn(newUserId, newUserName, ['note-obj-twitter-before-follow-note-btn', 'css-901oao']);
  462. ele.querySelector(selector.userpage.follow).insertAdjacentElement('afterbegin', followNoteBtn);
  463. }
  464. noteObj.judgeUsers(newUserId) &&
  465. noteObj.handler(
  466. newUserId,
  467. ele,
  468. selector.userpage.showName,
  469. {
  470. add: 'span',
  471. classname: 'note-obj-twitter-blue-tag',
  472. },
  473. newUserName
  474. );
  475. });
  476. userIdChange.observe(ele.querySelector(selector.userpage.id), {
  477. subtree: true,
  478. characterData: true,
  479. });
  480. });
  481. document.querySelector(selector.root).arrive(selector.homepage.userFrame, arriveOption, ele => {
  482. const eleId = ele.querySelector(selector.userpage.id) ? ele.querySelector(selector.userpage.id).textContent.replace(/^@/, '') : null;
  483. noteObj.judgeUsers(eleId) &&
  484. noteObj.handler(eleId, ele, selector.homepage.showName, {
  485. add: 'span',
  486. class: 'note-obj-twitter-blue-tag',
  487. });
  488. });
  489. document.querySelector(selector.root).arrive(selector.hover.panel, arriveOption, ele => {
  490. const user = ele.querySelector(selector.hover.id);
  491. if (user) {
  492. const eleId = user.textContent.replace(/^@/, '');
  493. const userShowName = ele.querySelector(selector.hover.showName);
  494. if (userShowName) {
  495. const userShowNameText = userShowName.textContent;
  496. ele.querySelector(selector.hover.followBtn) &&
  497. ele
  498. .querySelector(selector.hover.followBtn)
  499. .insertAdjacentElement(
  500. 'beforebegin',
  501. noteObj.createNoteBtn(eleId, userShowNameText, ['note-obj-twitter-note-btn', 'note-obj-twitter-panel-btn'])
  502. );
  503. noteObj.judgeUsers(eleId) &&
  504. noteObj.handler(
  505. eleId,
  506. ele,
  507. selector.hover.showName,
  508. {
  509. add: 'span',
  510. class: 'note-obj-twitter-blue-tag',
  511. },
  512. userShowNameText
  513. );
  514. }
  515. }
  516. });
  517. document.querySelector(selector.root).arrive(selector.modal.cell, arriveOption, ele => {
  518. const eleId = ele.querySelector(selector.homepage.id) ? ele.querySelector(selector.homepage.id).textContent.replace(/^@/, '') : null;
  519. noteObj.judgeUsers(eleId) &&
  520. noteObj.handler(eleId, ele, selector.homepage.showName, {
  521. add: 'span',
  522. class: 'note-obj-twitter-blue-tag',
  523. });
  524. });
  525. }
  526. init();
  527. })();

QingJ © 2025

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