您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
decorates "knownUsers" and "rooms" objects with functions useful for console and other scripts
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/423722/913799/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 ]); if (users.excludedAll) { result.excludedAll.push(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; user = {...user, ...user.original}; delete user.original; }); }; const descriptors = Object.defineProperties(users, Object.fromEntries(Object.entries({ toArray, toString, by, byId, byName, byGender, byPos, byIsCammed, 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 => decoratUsersObj(users)); patchObject(() => rooms, rooms => decorateRoomsObj(rooms)); })();