Instagram - 為使用者新增備註(別名/標籤)

為使用者新增備註(別名/標籤)功能,以幫助識別和搜尋

目前為 2023-02-26 提交的版本,檢視 最新版本

// ==UserScript==
// @name                Instagram - Add notes to the user
// @name:en             Instagram - Add notes to the user
// @name:zh-CN          Instagram - 为用户添加备注(别名/标签)
// @name:zh-TW          Instagram - 為使用者新增備註(別名/標籤)
// @namespace           https://gf.qytechs.cn/zh-CN/users/193133-pana
// @homepage            https://gf.qytechs.cn/zh-CN/users/193133-pana
// @icon                data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9Im5ld0ljb25UaXRsZSIgc3Ryb2tlPSJyZ2JhKDI5LDE2MSwyNDIsMS4wMCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYmEoMjksMTYxLDI0MiwxLjAwKSI+IDx0aXRsZSBpZD0ibmV3SWNvblRpdGxlIj5OZXc8L3RpdGxlPiA8cGF0aCBkPSJNMTkgMTRWMjJIMi45OTk5N1Y0SDEzIi8+IDxwYXRoIGQ9Ik0xNy40NjA4IDQuMDM5MjFDMTguMjQxOCAzLjI1ODE3IDE5LjUwODIgMy4yNTgxNiAyMC4yODkyIDQuMDM5MjFMMjAuOTYwOCA0LjcxMDc5QzIxLjc0MTggNS40OTE4NCAyMS43NDE4IDYuNzU4MTcgMjAuOTYwOCA3LjUzOTIxTDExLjU4NTggMTYuOTE0MkMxMS4yMTA3IDE3LjI4OTMgMTAuNzAyIDE3LjUgMTAuMTcxNiAxNy41TDcuNSAxNy41TDcuNSAxNC44Mjg0QzcuNSAxNC4yOTggNy43MTA3MSAxMy43ODkzIDguMDg1NzkgMTMuNDE0MkwxNy40NjA4IDQuMDM5MjFaIi8+IDxwYXRoIGQ9Ik0xNi4yNSA1LjI1TDE5Ljc1IDguNzUiLz4gPC9zdmc+
// @version             6.0.1
// @description         Add notes (aliases/tags) for users to help identify and search
// @description:en      Add notes (aliases/tags) for users to help identify and search
// @description:zh-CN   为用户添加备注(别名/标签)功能,以帮助识别和搜索
// @description:zh-TW   為使用者新增備註(別名/標籤)功能,以幫助識別和搜尋
// @license             GNU General Public License v3.0 or later
// @compatible          chrome
// @compatible          firefox
// @author              pana
// @match               *://*.instagram.com/*
// @require             https://gcore.jsdelivr.net/npm/[email protected]/minified/arrive.min.js
// @require             https://gcore.jsdelivr.net/gh/LightAPIs/greasy-fork-library@fd5c9360dd6db517c47e8e1dd25f3ff92a537938/Note_Obj.js
// @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-02-26';
    const INS_ICON = {
        NOTE_BLACK: 'url(data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0cHgiIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiBhcmlhLWxhYmVsbGVkYnk9Im5ld0ljb25UaXRsZSIgc3Ryb2tlPSJyZ2IoMzgsIDM4LCAzOCkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InNxdWFyZSIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgZmlsbD0ibm9uZSIgY29sb3I9InJnYigzOCwgMzgsIDM4KSI+IDx0aXRsZSBpZD0ibmV3SWNvblRpdGxlIj5OZXc8L3RpdGxlPiA8cGF0aCBkPSJNMTkgMTRWMjJIMi45OTk5N1Y0SDEzIi8+IDxwYXRoIGQ9Ik0xNy40NjA4IDQuMDM5MjFDMTguMjQxOCAzLjI1ODE3IDE5LjUwODIgMy4yNTgxNiAyMC4yODkyIDQuMDM5MjFMMjAuOTYwOCA0LjcxMDc5QzIxLjc0MTggNS40OTE4NCAyMS43NDE4IDYuNzU4MTcgMjAuOTYwOCA3LjUzOTIxTDExLjU4NTggMTYuOTE0MkMxMS4yMTA3IDE3LjI4OTMgMTAuNzAyIDE3LjUgMTAuMTcxNiAxNy41TDcuNSAxNy41TDcuNSAxNC44Mjg0QzcuNSAxNC4yOTggNy43MTA3MSAxMy43ODkzIDguMDg1NzkgMTMuNDE0MkwxNy40NjA4IDQuMDM5MjFaIi8+IDxwYXRoIGQ9Ik0xNi4yNSA1LjI1TDE5Ljc1IDguNzUiLz4gPC9zdmc+)',
    };
    const INS_STYLE = `
    .note-obj-ins-background-box {
        display: inline-block;
        align-items: center;
        white-space: nowrap;
        border-radius: 50px;
        padding: 0px 10px;
        background-color: #336699;
        color: #fff;
    }
    .note-obj-ins-add-btn {
        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;
    }
    .note-obj-ins-homepage-btn {
        margin: 6px !important;
    }
    .note-obj-ins-homepage-btn:hover {
      opacity: 0.5;
    }
    .note-obj-ins-userpage-btn {
        margin-top: 2px;
    }
    .note-obj-ins-userpage-tag {
        display: block;
        font-size: 20px;
        margin-bottom: 20px;
        white-space: nowrap;
    }
    .note-obj-ins-font-bold {
        font-weight: bold;
    }
    .note-obj-veryins-blue-tag {
        background-color: #3c81df;
        color: #fff;
        display: inline-flex;
        align-items: center;
        padding: 0px 10px;
        white-space: nowrap;
        line-height: 100%;
        border-radius: 50px;
        padding: 2px 10px;
    }
    .note-obj-veryins-userpage-btn {
        display: inline-block;
        vertical-align: middle;
    }
    .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 {
      color: #000;
    }`;
    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 noteObj = new Note_Obj({
        id: 'myInstagramNote',
        script: {
            author: {
                name: 'pana',
                homepage: 'https://gf.qytechs.cn/zh-CN/users/193133-pana',
            },
            url: 'https://gf.qytechs.cn/scripts/387871',
            updated: UPDATED,
            library: [
                {
                    name: 'arrive.js',
                    version: '2.4.1',
                    url: 'https://github.com/uzairfarooq/arrive',
                },
            ],
        },
        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, userId) {
        const user = Note_Obj.fn.queryAnchor(ele, selector.homepage.id);
        if (user) {
            const replaceHomepageID = noteObj.getOtherConfig().replaceHomepageID === true;
            const eleId = Note_Obj.fn.getIdFromUrl(user.href);
            if ((userId && userId === eleId) || (!userId && noteObj.judgeUsers(eleId))) {
                noteObj.handler(eleId, user, undefined, {
                    add: replaceHomepageID ? undefined : 'sapn',
                    className: replaceHomepageID ? undefined : ['note-obj-ins-background-box'],
                });
            }
        }
    }
    function homepageCommentNote(ele, userId) {
        for (const comment of Note_Obj.fn.queryAllAnchor(ele, selector.homepage.commentId, 'info')) {
            const commentId = Note_Obj.fn.getIdFromUrl(comment.href);
            if ((userId && userId === commentId) || (!userId && noteObj.judgeUsers(commentId))) {
                noteObj.handler(commentId, comment, undefined, {});
            }
        }
    }
    function homepageCommentAtNote(ele, userId) {
        const commentAtId = Note_Obj.fn.getIdFromUrl(ele.href);
        if ((userId && userId === commentAtId) || (!userId && noteObj.judgeUsers(commentAtId))) {
            noteObj.handler(commentAtId, ele, undefined, {
                prefix: '@',
                title: true,
            });
        }
    }
    function dialogCommentNote(ele, userId) {
        const picCommentId = Note_Obj.fn.getIdFromUrl(ele.href);
        if ((userId && userId === picCommentId) || (!userId && noteObj.judgeUsers(picCommentId))) {
            noteObj.handler(picCommentId, ele);
        }
    }
    function dialogCommentAtNote(ele, userId) {
        if (!ele.classList.contains(selector.homepage.commentId.replace(/^\.|\s+.*$/g, ''))) {
            const picCommentAtId = Note_Obj.fn.getIdFromUrl(ele.href);
            if ((userId && userId === picCommentAtId) || (!userId && noteObj.judgeUsers(picCommentAtId))) {
                noteObj.handler(picCommentAtId, ele, undefined, {
                    prefix: '@',
                    title: true,
                });
            }
        }
    }
    function homepageStoriesNote(ele, userId) {
        const homepageStoriesId = Note_Obj.fn.getText(ele, selector.homepageStories.id);
        if ((userId && userId === homepageStoriesId) || (!userId && noteObj.judgeUsers(homepageStoriesId))) {
            ele.title = noteObj.getUserTag(homepageStoriesId);
        }
    }
    function anchorElementNote(ele, userId) {
        const itemId = Note_Obj.fn.getIdFromUrl(ele.href);
        if ((userId && userId === itemId) || (!userId && noteObj.judgeUsers(itemId))) {
            noteObj.handler(itemId, ele);
        }
    }
    function userPageNote(ele, userId) {
        const userPageId = Note_Obj.fn.getText(ele, selector.userPage.id);
        const userPageBox = Note_Obj.fn.query(ele, selector.userPage.box);
        if (userPageId && userPageBox) {
            if (userId) {
                if (userId === userPageId) {
                    noteObj.handler(userPageId, ele, undefined, {
                        add: 'div',
                        after: userPageBox,
                        maskSecondaryColor: true,
                        offsetWidth: -20,
                        className: ['note-obj-ins-userpage-tag', 'note-obj-ins-font-bold'],
                    });
                }
            }
            else {
                const userNameText = Note_Obj.fn.getText(ele, selector.userPage.userName, 'warn');
                noteObj.handler(userPageId, ele, undefined, {
                    add: 'div',
                    after: userPageBox,
                    maskSecondaryColor: true,
                    offsetHeight: -20,
                    className: ['note-obj-ins-userpage-tag', 'note-obj-ins-font-bold'],
                }, userNameText);
            }
        }
    }
    function userPageCommonNote(ele, userId) {
        for (const commonUser of Note_Obj.fn.queryAll(ele, selector.userPage.common, 'info')) {
            const commonUserId = commonUser.textContent?.trim();
            if (commonUserId) {
                if ((userId && userId === commonUserId) || (!userId && noteObj.judgeUsers(commonUserId)))
                    noteObj.handler(commonUserId, commonUser, undefined, {
                        title: true,
                        notModify: true,
                    });
            }
        }
    }
    function userPageInfoAtNote(ele, userId) {
        for (const infoAtUser of Note_Obj.fn.queryAllAnchor(ele, selector.userPage.infoAt, 'info')) {
            const infoAtUserId = Note_Obj.fn.getIdFromUrl(infoAtUser.href);
            if ((userId && userId === infoAtUserId) || (!userId && noteObj.judgeUsers(infoAtUserId))) {
                noteObj.handler(infoAtUserId, infoAtUser, undefined, {
                    prefix: '@',
                    title: true,
                });
            }
        }
    }
    function storiesNote(ele, userId) {
        itemNote(ele, selector.stories.id, userId);
        Note_Obj.fn.docQueryAll(selector.stories.cardId).forEach(item => {
            const itemId = item.textContent?.trim() || '';
            if ((userId && userId === itemId) || (!userId && noteObj.judgeUsers(itemId))) {
                noteObj.handler(itemId, item, undefined, {
                    notModify: true,
                    title: true,
                });
            }
        });
    }
    function watchListItemNote(ele, userId) {
        itemNote(ele, selector.watchList.id, userId);
    }
    function itemNote(ele, idSelector, userId) {
        const item = Note_Obj.fn.queryAnchor(ele, idSelector);
        if (item) {
            const itemId = Note_Obj.fn.getIdFromUrl(item.href);
            if ((userId && userId === itemId) || (!userId && noteObj.judgeUsers(itemId))) {
                noteObj.handler(itemId, item);
            }
        }
    }
    function instagramChangeEvent(userId) {
        for (const article of Note_Obj.fn.docQueryAll(selector.homepage.article, 'none')) {
            homepageNote(article, userId);
            homepageCommentNote(article, userId);
            for (const commentAt of Note_Obj.fn.docQueryAllAnchor(selector.homepage.commentAt, 'none')) {
                homepageCommentAtNote(commentAt, userId);
            }
            for (const picCommentUser of Note_Obj.fn.docQueryAllAnchor(selector.dialog.commentId, 'none')) {
                dialogCommentNote(picCommentUser, userId);
            }
            for (const picCommentAt of Note_Obj.fn.docQueryAllAnchor(selector.dialog.commentAt, 'none')) {
                dialogCommentAtNote(picCommentAt, userId);
            }
        }
        for (const homepageStories of Note_Obj.fn.docQueryAll(selector.homepageStories.idShell, 'none')) {
            homepageStoriesNote(homepageStories, userId);
        }
        for (const homepageRecommend of Note_Obj.fn.docQueryAllAnchor(selector.homepageRecommend.id, 'none')) {
            anchorElementNote(homepageRecommend, userId);
        }
        for (const userPage of Note_Obj.fn.docQueryAll(selector.userPage.frame, 'none')) {
            userPageNote(userPage, userId);
            userPageCommonNote(userPage, userId);
            userPageInfoAtNote(userPage, userId);
        }
        for (const storiesShell of Note_Obj.fn.docQueryAll(selector.stories.idShell, 'none')) {
            storiesNote(storiesShell, userId);
        }
        for (const initial of Note_Obj.fn.docQueryAll(selector.watchList.initialItem, 'none')) {
            watchListItemNote(initial, userId);
        }
        for (const later of Note_Obj.fn.docQueryAll(selector.watchList.laterItem, 'none')) {
            watchListItemNote(later, userId);
        }
        for (const dialog of Note_Obj.fn.docQueryAll(selector.dialog.frame, 'none')) {
            homepageNote(dialog, userId);
            homepageCommentNote(dialog, userId);
            for (const commentUser of Note_Obj.fn.docQueryAllAnchor(selector.dialog.commentId, 'none')) {
                dialogCommentNote(commentUser, userId);
            }
            for (const commentAt of Note_Obj.fn.docQueryAllAnchor(selector.dialog.commentAt, 'none')) {
                dialogCommentAtNote(commentAt, userId);
            }
        }
        for (const follow of Note_Obj.fn.docQueryAllAnchor(selector.request.follow, 'none')) {
            anchorElementNote(follow, userId);
        }
        for (const suggestUser of Note_Obj.fn.docQueryAllAnchor(selector.suggest.user, 'none')) {
            anchorElementNote(suggestUser, userId);
        }
        for (const suggest of Note_Obj.fn.docQueryAllAnchor(selector.userPage.suggest, 'none')) {
            anchorElementNote(suggest, userId);
        }
    }
    function instagramHomepageEvent(newValue, oldValue) {
        for (const article of Note_Obj.fn.docQueryAll(selector.homepage.article)) {
            const articleUser = Note_Obj.fn.queryAnchor(article, selector.homepage.id);
            if (articleUser) {
                const articleUserId = Note_Obj.fn.getIdFromUrl(articleUser.href);
                noteObj.handler(articleUserId, articleUser, undefined, {
                    add: oldValue ? undefined : 'span',
                    className: oldValue ? undefined : ['note-obj-ins-background-box'],
                    title: oldValue,
                    restore: true,
                });
                noteObj.handler(articleUserId, articleUser, undefined, {
                    add: newValue ? undefined : 'span',
                    className: newValue ? undefined : ['note-obj-ins-background-box'],
                    title: newValue,
                });
            }
        }
    }
    function initInstagram() {
        const arriveOption = {
            fireOnAttributesModification: true,
            existing: true,
        };
        document.body.arrive(selector.homepage.article, arriveOption, article => {
            const homepageIcon = Note_Obj.fn.query(article, selector.homepage.icon);
            const articleUserId = Note_Obj.fn.getUrlId(article, selector.homepage.id);
            if (homepageIcon && articleUserId) {
                homepageIcon.insertAdjacentElement('beforebegin', noteObj.createNoteBtn(articleUserId, undefined, ['note-obj-ins-add-btn', 'note-obj-ins-homepage-btn'], 'span'));
            }
            homepageNote(article);
            homepageCommentNote(article);
            article.arrive(selector.homepage.commentAt, arriveOption, commentAt => {
                homepageCommentAtNote(commentAt);
            });
            article.arrive(selector.dialog.commentId, arriveOption, picCommentUser => {
                dialogCommentNote(picCommentUser);
            });
            article.arrive(selector.dialog.commentAt, arriveOption, picCommentAt => {
                dialogCommentAtNote(picCommentAt);
            });
        });
        document.body.arrive(selector.homepageStories.idShell, arriveOption, homepageStories => {
            homepageStoriesNote(homepageStories);
        });
        document.body.arrive(selector.homepageRecommend.id, arriveOption, homepageRecommend => {
            anchorElementNote(homepageRecommend);
        });
        document.body.arrive(selector.userPage.frame, arriveOption, userPage => {
            const userPageBar = Note_Obj.fn.query(userPage, selector.userPage.bar);
            const userPageId = Note_Obj.fn.getText(userPage, selector.userPage.id);
            if (userPageBar && userPageId) {
                const userNameText = Note_Obj.fn.getText(userPage, selector.userPage.userName, 'info');
                userPageBar.after(noteObj.createNoteBtn(userPageId, userNameText, ['note-obj-ins-add-btn', 'note-obj-ins-userpage-btn']));
            }
            userPageNote(userPage);
            userPageCommonNote(userPage);
            userPageInfoAtNote(userPage);
        });
        document.body.arrive(selector.stories.idShell, arriveOption, storiesShell => {
            storiesNote(storiesShell);
            const stories = Note_Obj.fn.queryAnchor(storiesShell, selector.stories.id);
            if (stories) {
                const userIdChange = new MutationObserver(() => {
                    const newUserId = Note_Obj.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'],
                });
            }
        });
        document.body.arrive(selector.watchList.initialItem, arriveOption, initial => {
            watchListItemNote(initial);
        });
        document.body.arrive(selector.watchList.laterItem, arriveOption, later => {
            watchListItemNote(later);
        });
        document.body.arrive(selector.dialog.frame, arriveOption, dialog => {
            const homepageIcon = Note_Obj.fn.query(dialog, selector.homepage.icon);
            const dialogUserId = Note_Obj.fn.getUrlId(dialog, selector.homepage.id);
            if (homepageIcon && dialogUserId) {
                homepageIcon.insertAdjacentElement('beforebegin', noteObj.createNoteBtn(dialogUserId, undefined, ['note-obj-ins-add-btn', 'note-obj-ins-homepage-btn'], 'span'));
            }
            homepageNote(dialog);
            homepageCommentNote(dialog);
            dialog.arrive(selector.dialog.commentId, arriveOption, commentUser => {
                dialogCommentNote(commentUser);
            });
            dialog.arrive(selector.dialog.commentAt, arriveOption, commentAt => {
                dialogCommentAtNote(commentAt);
            });
        });
        document.body.arrive(selector.request.follow, arriveOption, follow => {
            anchorElementNote(follow);
        });
        document.body.arrive(selector.suggest.user, arriveOption, suggestUser => {
            anchorElementNote(suggestUser);
        });
        document.body.arrive(selector.userPage.suggest, arriveOption, suggest => {
            anchorElementNote(suggest);
        });
    }
    initInstagram();
})();

QingJ © 2025

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