- // ==UserScript==
- // @name Instagram - Add notes to the user
- // @name:zh-CN Instagram - 为用户添加备注(别名/标签)
- // @name:zh-TW Instagram - 為使用者新增備註(別名/標籤)
- // @namespace https://greasyfork.org/zh-CN/users/193133-pana
- // @homepage https://greasyfork.org/zh-CN/users/193133-pana
- // @icon data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9Im5ld0ljb25UaXRsZSIgc3Ryb2tlPSJyZ2JhKDI5LDE2MSwyNDIsMS4wMCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYmEoMjksMTYxLDI0MiwxLjAwKSI+IDx0aXRsZSBpZD0ibmV3SWNvblRpdGxlIj5OZXc8L3RpdGxlPiA8cGF0aCBkPSJNMTkgMTRWMjJIMi45OTk5N1Y0SDEzIi8+IDxwYXRoIGQ9Ik0xNy40NjA4IDQuMDM5MjFDMTguMjQxOCAzLjI1ODE3IDE5LjUwODIgMy4yNTgxNiAyMC4yODkyIDQuMDM5MjFMMjAuOTYwOCA0LjcxMDc5QzIxLjc0MTggNS40OTE4NCAyMS43NDE4IDYuNzU4MTcgMjAuOTYwOCA3LjUzOTIxTDExLjU4NTggMTYuOTE0MkMxMS4yMTA3IDE3LjI4OTMgMTAuNzAyIDE3LjUgMTAuMTcxNiAxNy41TDcuNSAxNy41TDcuNSAxNC44Mjg0QzcuNSAxNC4yOTggNy43MTA3MSAxMy43ODkzIDguMDg1NzkgMTMuNDE0MkwxNy40NjA4IDQuMDM5MjFaIi8+IDxwYXRoIGQ9Ik0xNi4yNSA1LjI1TDE5Ljc1IDguNzUiLz4gPC9zdmc+
- // @version 6.1.8
- // @description Add notes (aliases/tags) for users to help identify and search, and support WebDAV sync
- // @description:zh-CN 为用户添加备注(别名/标签)功能,以帮助识别和搜索,并支持 WebDAV 同步功能
- // @description:zh-TW 為使用者新增備註(別名/標籤)功能,以幫助識別和搜尋,並支援 WebDAV 同步功能
- // @license GNU General Public License v3.0 or later
- // @compatible chrome
- // @compatible firefox
- // @author pana
- // @match *://*.instagram.com/*
- // @require https://gcore.jsdelivr.net/gh/LightAPIs/greasy-fork-library@da0437e6a856e05158df61225f2b9ea9943ad9ef/Note_Obj.js
- // @connect *
- // @noframes
- // @grant GM_info
- // @grant GM_getValue
- // @grant GM_setValue
- // @grant GM_deleteValue
- // @grant GM_listValues
- // @grant GM_openInTab
- // @grant GM_addStyle
- // @grant GM_registerMenuCommand
- // @grant GM_unregisterMenuCommand
- // @grant GM_addValueChangeListener
- // @grant GM_removeValueChangeListener
- // ==/UserScript==
-
- (function () {
- 'use strict';
- const UPDATED = '2023-04-21';
- const INS_ICON = {
- NOTE_BLACK: 'url(data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9Im5ld0ljb25UaXRsZSIgc3Ryb2tlPSJyZ2IoMzgsIDM4LCAzOCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYigzOCwgMzgsIDM4KSI+IDx0aXRsZSBpZD0ibmV3SWNvblRpdGxlIj5OZXc8L3RpdGxlPiA8cGF0aCBkPSJNMTkgMTRWMjJIMi45OTk5N1Y0SDEzIi8+IDxwYXRoIGQ9Ik0xNy40NjA4IDQuMDM5MjFDMTguMjQxOCAzLjI1ODE3IDE5LjUwODIgMy4yNTgxNiAyMC4yODkyIDQuMDM5MjFMMjAuOTYwOCA0LjcxMDc5QzIxLjc0MTggNS40OTE4NCAyMS43NDE4IDYuNzU4MTcgMjAuOTYwOCA3LjUzOTIxTDExLjU4NTggMTYuOTE0MkMxMS4yMTA3IDE3LjI4OTMgMTAuNzAyIDE3LjUgMTAuMTcxNiAxNy41TDcuNSAxNy41TDcuNSAxNC44Mjg0QzcuNSAxNC4yOTggNy43MTA3MSAxMy43ODkzIDguMDg1NzkgMTMuNDE0MkwxNy40NjA4IDQuMDM5MjFaIi8+IDxwYXRoIGQ9Ik0xNi4yNSA1LjI1TDE5Ljc1IDguNzUiLz4gPC9zdmc+)'
- };
- const selector = {
- homepage: {
- article: '[role="main"] article',
- id: '._aaqt a',
- icon: 'span._aamz',
- commentId: '._ab8x .xt0psk2 a.notranslate',
- commentAt: '._ab8x ._aacl a.notranslate'
- },
- homepageStories: {
- id: '._aad6',
- idShell: 'li [role="menuitem"]'
- },
- homepageRecommend: {
- id: '._aak3 ._ab8x .xt0psk2 a'
- },
- userPage: {
- frame: '._aa_y',
- id: 'h2',
- bar: '.x8j4wrb',
- box: 'ul',
- common: 'span._aaai',
- suggest: '._acj1 a.notranslate',
- infoAt: '.notranslate',
- userName: '._aa_c > span'
- },
- watchList: {
- initialItem: '[role="dialog"] [aria-labelledby]',
- laterItem: '._aaei',
- id: '._ab8w a.notranslate'
- },
- stories: {
- id: 'a.notranslate',
- idShell: '._ac0o',
- cardId: '._afgd ._aacw'
- },
- dialog: {
- frame: '[role="dialog"] article',
- commentId: '._a9zc ._ab8w a, ._aacx._aacu a',
- commentAt: '._a9zs .notranslate'
- },
- request: {
- follow: '._aajc ._ab8x .xt0psk2 a'
- },
- suggest: {
- user: '._aa0- ._ab8x .xt0psk2 a'
- }
- };
- const nameSet = {
- backgroundBox: 'note-obj-ins-background-box',
- userpageTag: 'note-obj-ins-userpage-tag',
- fontBold: 'note-obj-ins-font-bold',
- addBtn: 'note-obj-ins-add-btn',
- homepageBtn: 'note-obj-ins-homepage-btn',
- userpageBtn: 'note-obj-ins-userpage-btn'
- };
- const INS_STYLE = `
- .${nameSet.backgroundBox} {
- display: inline-block;
- align-items: center;
- white-space: nowrap;
- border-radius: 50px;
- padding: 0px 10px;
- background-color: #336699;
- color: #fff;
- }
- .${nameSet.addBtn} {
- background-image: ${INS_ICON.NOTE_BLACK};
- background-size: 24px;
- background-repeat: no-repeat;
- background-position: center;
- margin-left: 5px;
- cursor: pointer;
- width: 24px;
- height: 24px;
- }
- .${nameSet.homepageBtn} {
- margin: 6px !important;
- }
- .${nameSet.homepageBtn}:hover {
- opacity: 0.5;
- }
- .${nameSet.userpageBtn} {
- margin-top: 2px;
- }
- .${nameSet.userpageTag} {
- display: block;
- font-size: 20px;
- margin-bottom: 20px;
- white-space: nowrap;
- }
- .${nameSet.fontBold} {
- font-weight: bold;
- }
- .note-obj-settings-frame-card label {
- color: #2f2f2f;
- }
- .note-obj-interface-dark .note-obj-settings-frame-card label {
- color: #fff;
- }
- .note-obj-group-frame-tbody input,
- .note-obj-webdav-frame-form-item input {
- color: #000;
- }`;
- const noteObj = new Note_Obj({
- id: 'myInstagramNote',
- script: {
- author: {
- name: 'pana',
- homepage: 'https://greasyfork.org/zh-CN/users/193133-pana'
- },
- url: 'https://greasyfork.org/scripts/387871',
- updated: UPDATED
- },
- style: INS_STYLE,
- primaryColor: '#336699',
- settings: {
- replaceHomepageID: {
- type: 'checkbox',
- lang: {
- en: 'Allow replacing user IDs on the home page',
- zhHans: '允许替换首页上的用户 ID',
- zhHant: '允許替換首頁上的使用者 ID'
- },
- default: true,
- event: instagramHomepageEvent
- }
- },
- changeEvent: instagramChangeEvent
- });
- function homepageNote(ele, changeId) {
- const user = noteObj.fn.queryAnchor(ele, selector.homepage.id);
- if (user) {
- const replaceHomepageID = noteObj.getOtherConfig().replaceHomepageID === true;
- const eleId = noteObj.fn.getIdFromUrl(user.href);
- if (!changeId || changeId === eleId) {
- noteObj.handler(eleId, user, undefined, {
- add: replaceHomepageID ? undefined : 'sapn',
- className: replaceHomepageID ? undefined : [nameSet.backgroundBox]
- });
- }
- }
- }
- function homepageCommentNote(ele, changeId) {
- for (const comment of noteObj.fn.queryAllAnchor(ele, selector.homepage.commentId, 'info')) {
- const commentId = noteObj.fn.getIdFromUrl(comment.href);
- if (!changeId || changeId === commentId) {
- noteObj.handler(commentId, comment);
- }
- }
- }
- function homepageCommentAtNote(ele, changeId) {
- const commentAtId = noteObj.fn.getIdFromUrl(ele.href);
- if (!changeId || changeId === commentAtId) {
- noteObj.handler(commentAtId, ele, undefined, {
- prefix: '@',
- title: true
- });
- }
- }
- function dialogCommentNote(ele, chagneId) {
- const picCommentId = noteObj.fn.getIdFromUrl(ele.href);
- if (!chagneId || chagneId === picCommentId) {
- noteObj.handler(picCommentId, ele);
- }
- }
- function dialogCommentAtNote(ele, changeId) {
- if (!ele.classList.contains(selector.homepage.commentId.replace(/^\.|\s+.*$/g, ''))) {
- const picCommentAtId = noteObj.fn.getIdFromUrl(ele.href);
- if (!changeId || changeId === picCommentAtId) {
- noteObj.handler(picCommentAtId, ele, undefined, {
- prefix: '@',
- title: true
- });
- }
- }
- }
- function homepageStoriesNote(ele, changeId) {
- const homepageStoriesId = noteObj.fn.getText(ele, selector.homepageStories.id);
- if (!changeId || changeId === homepageStoriesId) {
- ele.title = noteObj.getUserTag(homepageStoriesId);
- }
- }
- function anchorElementNote(ele, changeId) {
- const itemId = noteObj.fn.getIdFromUrl(ele.href);
- if (!changeId || changeId === itemId) {
- noteObj.handler(itemId, ele);
- }
- }
- function userPageNote(ele, changeId) {
- const userPageId = noteObj.fn.getText(ele, selector.userPage.id);
- const userPageBox = noteObj.fn.query(ele, selector.userPage.box);
- if (userPageId && userPageBox) {
- if (changeId) {
- if (changeId === userPageId) {
- noteObj.handler(userPageId, ele, undefined, {
- add: 'div',
- after: userPageBox,
- maskSecondaryColor: true,
- offsetWidth: -20,
- className: [nameSet.userpageTag, nameSet.fontBold]
- });
- }
- } else {
- const userNameText = noteObj.fn.getText(ele, selector.userPage.userName, 'warn');
- noteObj.handler(userPageId, ele, undefined, {
- add: 'div',
- after: userPageBox,
- maskSecondaryColor: true,
- offsetHeight: -20,
- className: [nameSet.userpageTag, nameSet.fontBold]
- }, userNameText);
- }
- }
- }
- function userPageCommonNote(ele, changeId) {
- for (const commonUser of noteObj.fn.queryAll(ele, selector.userPage.common, 'info')) {
- const commonUserId = commonUser.textContent?.trim();
- if (commonUserId) {
- if (!changeId || changeId === commonUserId) noteObj.handler(commonUserId, commonUser, undefined, {
- title: true,
- notModify: true
- });
- }
- }
- }
- function userPageInfoAtNote(ele, changeId) {
- for (const infoAtUser of noteObj.fn.queryAllAnchor(ele, selector.userPage.infoAt, 'info')) {
- const infoAtUserId = noteObj.fn.getIdFromUrl(infoAtUser.href);
- if (!changeId || changeId === infoAtUserId) {
- noteObj.handler(infoAtUserId, infoAtUser, undefined, {
- prefix: '@',
- title: true
- });
- }
- }
- }
- function storiesNote(ele, changeId) {
- itemNote(ele, selector.stories.id, changeId);
- noteObj.fn.queryAll(selector.stories.cardId).forEach(item => {
- const itemId = item.textContent?.trim() || '';
- if (!changeId || changeId === itemId) {
- noteObj.handler(itemId, item, undefined, {
- notModify: true,
- title: true
- });
- }
- });
- }
- function watchListItemNote(ele, changeId) {
- itemNote(ele, selector.watchList.id, changeId);
- }
- function itemNote(ele, idSelector, changeId) {
- const item = noteObj.fn.queryAnchor(ele, idSelector);
- if (item) {
- const itemId = noteObj.fn.getIdFromUrl(item.href);
- if (!changeId || changeId === itemId) {
- noteObj.handler(itemId, item);
- }
- }
- }
- function instagramChangeEvent(changeId) {
- for (const article of noteObj.fn.queryAll(selector.homepage.article, 'none')) {
- homepageNote(article, changeId);
- homepageCommentNote(article, changeId);
- for (const commentAt of noteObj.fn.queryAllAnchor(selector.homepage.commentAt, 'none')) {
- homepageCommentAtNote(commentAt, changeId);
- }
- for (const picCommentUser of noteObj.fn.queryAllAnchor(selector.dialog.commentId, 'none')) {
- dialogCommentNote(picCommentUser, changeId);
- }
- for (const picCommentAt of noteObj.fn.queryAllAnchor(selector.dialog.commentAt, 'none')) {
- dialogCommentAtNote(picCommentAt, changeId);
- }
- }
- for (const homepageStories of noteObj.fn.queryAll(selector.homepageStories.idShell, 'none')) {
- homepageStoriesNote(homepageStories, changeId);
- }
- for (const homepageRecommend of noteObj.fn.queryAllAnchor(selector.homepageRecommend.id, 'none')) {
- anchorElementNote(homepageRecommend, changeId);
- }
- for (const userPage of noteObj.fn.queryAll(selector.userPage.frame, 'none')) {
- userPageNote(userPage, changeId);
- userPageCommonNote(userPage, changeId);
- userPageInfoAtNote(userPage, changeId);
- }
- for (const storiesShell of noteObj.fn.queryAll(selector.stories.idShell, 'none')) {
- storiesNote(storiesShell, changeId);
- }
- for (const initial of noteObj.fn.queryAll(selector.watchList.initialItem, 'none')) {
- watchListItemNote(initial, changeId);
- }
- for (const later of noteObj.fn.queryAll(selector.watchList.laterItem, 'none')) {
- watchListItemNote(later, changeId);
- }
- for (const dialog of noteObj.fn.queryAll(selector.dialog.frame, 'none')) {
- homepageNote(dialog, changeId);
- homepageCommentNote(dialog, changeId);
- for (const commentUser of noteObj.fn.queryAllAnchor(selector.dialog.commentId, 'none')) {
- dialogCommentNote(commentUser, changeId);
- }
- for (const commentAt of noteObj.fn.queryAllAnchor(selector.dialog.commentAt, 'none')) {
- dialogCommentAtNote(commentAt, changeId);
- }
- }
- for (const follow of noteObj.fn.queryAllAnchor(selector.request.follow, 'none')) {
- anchorElementNote(follow, changeId);
- }
- for (const suggestUser of noteObj.fn.queryAllAnchor(selector.suggest.user, 'none')) {
- anchorElementNote(suggestUser, changeId);
- }
- for (const suggest of noteObj.fn.queryAllAnchor(selector.userPage.suggest, 'none')) {
- anchorElementNote(suggest, changeId);
- }
- }
- function instagramHomepageEvent(newValue, oldValue) {
- for (const article of noteObj.fn.queryAll(selector.homepage.article)) {
- const articleUser = noteObj.fn.queryAnchor(article, selector.homepage.id);
- if (articleUser) {
- const articleUserId = noteObj.fn.getIdFromUrl(articleUser.href);
- noteObj.handler(articleUserId, articleUser, undefined, {
- add: oldValue ? undefined : 'span',
- className: oldValue ? undefined : [nameSet.backgroundBox],
- title: oldValue,
- restore: true
- });
- noteObj.handler(articleUserId, articleUser, undefined, {
- add: newValue ? undefined : 'span',
- className: newValue ? undefined : [nameSet.backgroundBox],
- title: newValue
- });
- }
- }
- }
- function initInstagram() {
- const arriveOption = {
- fireOnAttributesModification: true,
- existing: true
- };
- noteObj.arrive(document.body, selector.homepage.article, arriveOption, article => {
- const homepageIcon = noteObj.fn.query(article, selector.homepage.icon);
- const articleUserId = noteObj.fn.getUrlId(article, selector.homepage.id);
- if (homepageIcon && articleUserId) {
- homepageIcon.insertAdjacentElement('beforebegin', noteObj.createNoteBtn(articleUserId, undefined, [nameSet.addBtn, nameSet.homepageBtn], 'span'));
- }
- homepageNote(article);
- homepageCommentNote(article);
- noteObj.arrive(article, selector.homepage.commentAt, arriveOption, commentAt => {
- homepageCommentAtNote(commentAt);
- });
- noteObj.arrive(article, selector.dialog.commentId, arriveOption, picCommentUser => {
- dialogCommentNote(picCommentUser);
- });
- noteObj.arrive(article, selector.dialog.commentAt, arriveOption, picCommentAt => {
- dialogCommentAtNote(picCommentAt);
- });
- });
- noteObj.arrive(document.body, selector.homepageStories.idShell, arriveOption, homepageStories => {
- homepageStoriesNote(homepageStories);
- });
- noteObj.arrive(document.body, selector.homepageRecommend.id, arriveOption, homepageRecommend => {
- anchorElementNote(homepageRecommend);
- });
- noteObj.arrive(document.body, selector.userPage.frame, arriveOption, userPage => {
- const userPageBar = noteObj.fn.query(userPage, selector.userPage.bar);
- const userPageId = noteObj.fn.getText(userPage, selector.userPage.id);
- if (userPageBar && userPageId) {
- const userNameText = noteObj.fn.getText(userPage, selector.userPage.userName, 'info');
- userPageBar.after(noteObj.createNoteBtn(userPageId, userNameText, [nameSet.addBtn, nameSet.userpageBtn]));
- }
- userPageNote(userPage);
- userPageCommonNote(userPage);
- userPageInfoAtNote(userPage);
- });
- noteObj.arrive(document.body, selector.stories.idShell, arriveOption, storiesShell => {
- storiesNote(storiesShell);
- const stories = noteObj.fn.queryAnchor(storiesShell, selector.stories.id);
- if (stories) {
- const userIdChange = new MutationObserver(() => {
- const newUserId = noteObj.fn.getIdFromUrl(stories.href);
- if (noteObj.judgeUsers(newUserId)) {
- noteObj.handler(newUserId, stories);
- } else {
- noteObj.handler(newUserId, stories, undefined, {
- restore: true
- });
- }
- });
- userIdChange.observe(stories, {
- attributeFilter: ['href']
- });
- }
- });
- noteObj.arrive(document.body, selector.watchList.initialItem, arriveOption, initial => {
- watchListItemNote(initial);
- });
- noteObj.arrive(document.body, selector.watchList.laterItem, arriveOption, later => {
- watchListItemNote(later);
- });
- noteObj.arrive(document.body, selector.dialog.frame, arriveOption, dialog => {
- const homepageIcon = noteObj.fn.query(dialog, selector.homepage.icon);
- const dialogUserId = noteObj.fn.getUrlId(dialog, selector.homepage.id);
- if (homepageIcon && dialogUserId) {
- homepageIcon.insertAdjacentElement('beforebegin', noteObj.createNoteBtn(dialogUserId, undefined, [nameSet.addBtn, nameSet.homepageBtn], 'span'));
- }
- homepageNote(dialog);
- homepageCommentNote(dialog);
- noteObj.arrive(dialog, selector.dialog.commentId, arriveOption, commentUser => {
- dialogCommentNote(commentUser);
- });
- noteObj.arrive(dialog, selector.dialog.commentAt, arriveOption, commentAt => {
- dialogCommentAtNote(commentAt);
- });
- });
- noteObj.arrive(document.body, selector.request.follow, arriveOption, follow => {
- anchorElementNote(follow);
- });
- noteObj.arrive(document.body, selector.suggest.user, arriveOption, suggestUser => {
- anchorElementNote(suggestUser);
- });
- noteObj.arrive(document.body, selector.userPage.suggest, arriveOption, suggest => {
- anchorElementNote(suggest);
- });
- }
- initInstagram();
- })();