Greasy Fork镜像 还支持 简体中文。

Camamba Chat Helpers

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

目前為 2021-03-26 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.gf.qytechs.cn/scripts/423722/915087/Camamba%20Chat%20Helpers.js

  1. // ==UserScript==
  2. // @name Camamba Chat Helpers
  3. // @namespace dannysaurus.camamba
  4. // @version 0.1.4
  5. // @description decorates "knownUsers" and "rooms" objects with functions useful for console and other scripts
  6. // @license MIT License
  7. // @include https://www.camamba.com/chat/
  8. // @include https://www.de.camamba.com/chat/
  9. // @include https://www.camamba.com/chat/
  10. // @include https://www.de.camamba.com/chat/
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. /* jslint esversion: 9 */
  15. /* global me, camData, rooms, blockList, friendList, friendRequests, adminMessages, jsLang, byId, myRooms, knownUsers, activeRoom, selectedUser, settings, onMessageHandlers, postMessageHandlers */
  16.  
  17. (function() {
  18. function decorateUsers(users = {}) {
  19. const isUser = (user) => {
  20. return user.id;
  21. };
  22.  
  23. const toArray = () => {
  24. if (Array.isArray(users)) {
  25. return [...users];
  26. }
  27.  
  28. if (users.id && users.name) {
  29. return [ users ];
  30. }
  31.  
  32. return Object.values(users);
  33. };
  34.  
  35. const toString = () => {
  36. return toArray().map(u => {
  37.  
  38. return Object.entries(u)
  39. .map(([prop, val]) => prop + ':' + val)
  40. .join('\t');
  41.  
  42. }).join('\n');
  43. };
  44.  
  45. const by = (userPredicateFnc) => {
  46. const result = [], excluded = [];
  47.  
  48. Object.values(users).filter(u => isUser(u)).forEach(u => {
  49. if(userPredicateFnc(u)) {
  50. result.push(u);
  51. } else {
  52. excluded.push(u);
  53. }
  54. });
  55.  
  56. if (excluded.length) {
  57. result.excluded = decorateUsers(excluded);
  58. result.excludedAll = decorateUsers([ ...excluded, ...users.excludedAll ]);
  59. }
  60.  
  61. return decorateUsers(result);
  62. };
  63.  
  64. const byId = (id) => {
  65. return by(user => user.id == id);
  66. };
  67.  
  68. const byName = (name) => {
  69. const nameLower = String(name).toLowerCase();
  70. return by(user => {
  71. return user.name.toLowerCase().includes(nameLower);
  72. });
  73. };
  74.  
  75. const byGender = (gender) => {
  76. const genderLower = String(gender).toLowerCase();
  77. return by(user => {
  78. return user.gender.toLowerCase().startsWIth(genderLower);
  79. });
  80. };
  81. const bySelected = () => {
  82. const selectedUserId = selectedUser ? selectedUser.dataset.id : 0;
  83. if (!selectedUserId) {
  84. return by(user => false);
  85. }
  86. return byId(selectedUserId);
  87. };
  88.  
  89. const byIsCammed = () => {
  90. if (!camData) return false;
  91.  
  92. const camDataUserIds = new Set(
  93. Object.values(camData)
  94. .filter(cd => cd.user)
  95. .map(cd => String(cd.user))
  96. );
  97.  
  98. return by(user => {
  99. return camDataUserIds.has(String(user.id));
  100. });
  101. };
  102.  
  103. const byViewing = () => {
  104. return users.by(user => {
  105. return user.viewing;
  106. });
  107. };
  108. const byPos = (pos) => {
  109. return toArray()[pos];
  110. };
  111.  
  112. const stopViewing = () => {
  113. return byViewing().forEach(user => {
  114. janusSend('remove', user.id);
  115. });
  116. };
  117.  
  118. const save = () => toArray().forEach(user => {
  119. user.original = {...user};
  120. });
  121.  
  122. const restore = () => by(user => user.original).forEach(user => {
  123. Object.assign(user, user.original);
  124. delete user.original;
  125. });
  126.  
  127. return Object.defineProperties(users, Object.fromEntries(Object.entries({
  128. excluded: users.excluded || [],
  129. excludedAll: users.excludedAll || [],
  130. toArray,
  131. toString,
  132. by,
  133. byId,
  134. bySelected,
  135. byName,
  136. byGender,
  137. byPos,
  138. byIsCammed,
  139. byIsNotCammed: () => byIsCammed().excluded,
  140. byViewing,
  141. stopViewing,
  142. save,
  143. restore
  144. }).map(([propName, value]) => {
  145. return [propName, { value, configurable: true }];
  146. })));
  147. }
  148.  
  149. function decorateRooms(rooms = {}) {
  150. const roomsByName = (name) => {
  151. const nameLower = String(name).toLowerCase();
  152.  
  153. const result = {};
  154.  
  155. Object.entries(rooms).forEach(([roomId, roomName]) => {
  156.  
  157. if (roomName.toLowerCase().includes(nameLower)) {
  158. result[roomId] = roomName;
  159. }
  160. });
  161.  
  162. return result;
  163. };
  164.  
  165. return Object.defineProperties(rooms, {
  166. byName: { value: roomsByName, configurable: true },
  167. });
  168. }
  169.  
  170. const patchObject = function(getExpectedObjFnc, patchFnc, timeOutRetryMillis = 200, maxPeriodTryMillis = 5000) {
  171. const expectedObj = getExpectedObjFnc();
  172.  
  173. if (!expectedObj && timeOutRetryMillis <= maxPeriodTryMillis) {
  174. setTimeout(() => patchObject(getExpectedObjFnc, patchFnc, timeOutRetryMillis), maxPeriodTryMillis - timeOutRetryMillis);
  175. return;
  176. }
  177. patchFnc(expectedObj);
  178. };
  179.  
  180. patchObject(() => knownUsers, users => decorateUsers(users));
  181. patchObject(() => rooms, rooms => decorateRooms(rooms));
  182. })();

QingJ © 2025

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