Greasy Fork

Camamba Chat Helpers

decorates "knownUsers" and "rooms" objects with functions useful for console and other scripts

目前为 2021-03-22 提交的版本。查看 最新版本

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.greasyfork.icu/scripts/423722/913809/Camamba%20Chat%20Helpers.js

// ==UserScript==
// @name         Camamba Chat Helpers
// @namespace    dannysaurus.camamba
// @version      0.1
// @description  decorates "knownUsers" and "rooms" objects with functions useful for console and other scripts
// @license      MIT License
// @include      https://www.camamba.com/chat/
// @include      https://www.de.camamba.com/chat/
// @include      https://www.camamba.com/chat/
// @include      https://www.de.camamba.com/chat/
// @grant        none
// ==/UserScript==

/* jslint esversion: 9 */
/* global me, camData, rooms, blockList, friendList, friendRequests, adminMessages, jsLang, byId, myRooms, knownUsers, activeRoom, selectedUser, settings, onMessageHandlers, postMessageHandlers */

(function() {
    function decorateUsersObj(users = {}) {

        const toArray = () => {
            if (Array.isArray(users)) {
                return [...users];
            }

            if (users.id && users.name) {
                return [ users ];
            }

            return Object.values(users);
        };

        const toString = () => {
            return toArray().map(u => {

                return Object.entries(u)
                    .map(([prop, val]) => prop + ':' + val)
                    .join('\t');

            }).join('\n');
        };

        const by = (userPredicateFnc) => {
            const result = [], excluded = [];

            Object.values(users).forEach(u => {
                if(userPredicateFnc(u)) {
                    result.push(u);
                } else {
                    excluded.push(u);
                }
            });

            if (excluded.length) {
                result.excluded = decorateUsersObj(excluded);
                result.excludedAll = decorateUsersObj([ ...excluded, ...users.excludedAll ]);
            }

            return decorateUsersObj(result);
        };

        const byId = (id) => by(u => u.id == id);

        const byName = (name) => {
            const nameLower = String(name).toLowerCase();
            return by(u => u.name.toLowerCase().includes(nameLower));
        };

        const byGender = (gender) => {
            const genderLower = String(gender).toLowerCase();
            return by(u => u.gender.toLowerCase().startsWIth(genderLower));
        };

        const byIsCammed = (user, takeWhenFalse = false) => {
            if (!camData) return false;

            const cammedUsersIds = new Set(Object.values(camData).map(camData => String(camData.user)));

            return (u => cammedUsersIds.has(String(u.id)), takeWhenFalse);
        };

        const byPos = (pos) => toArray()[pos];

        const save = () => {
            toArray().forEach(user => {
                user.original = {...user};
            });
        };

        const restore = () => {
            toArray().forEach(user => {
                if (!user.original) return;

                Object.assign(user, user.original);
                delete user.original;
            });
        };

        return Object.defineProperties(users, Object.fromEntries(Object.entries({
            excluded: users.excluded || [],
            excludedAll: users.excludedAll || [],
            toArray,
            toString,
            by,
            byId,
            byName,
            byGender,
            byPos,
            byIsCammed,
            byIsNotCammed: () => byIsCammed().excluded,
            save,
            restore
        }).map(([propName, value]) => {
            return [propName, { value, configurable: true }];
        })));
    }

    function decorateRoomsObj(rooms = {}) {
        const roomsByName = (name) => {
            const nameLower = String(name).toLowerCase();

            const result = {};

            Object.entries(rooms).forEach(([roomId, roomName]) => {

                if (roomName.toLowerCase().includes(nameLower)) {
                    result[roomId] = roomName;
                }
            });

            return result;
        };

        return Object.defineProperties(rooms, {
            byName: { value: roomsByName, configurable: true },
        });
    }

    const patchObject = function(getExpectedObjFnc, patchFnc, timeOutRetryMillis = 200, maxPeriodTryMillis = 5000) {
        const expectedObj = getExpectedObjFnc();

        if (!expectedObj && timeOutRetryMillis <= maxPeriodTryMillis) {
            setTimeout(() => patchObject(getExpectedObjFnc, patchFnc, timeOutRetryMillis), maxPeriodTryMillis - timeOutRetryMillis);
            return;
        }
        patchFnc(expectedObj);
    };

    patchObject(() => knownUsers, users => decorateUsersObj(users));
    patchObject(() => rooms, rooms => decorateRoomsObj(rooms));
})();