decorates "knownUsers" and "rooms" objects with functions useful for console and other scripts
Versión del día
Este script no debería instalarse directamente. Es una biblioteca que utilizan otros scripts mediante la meta-directiva de inclusión // @require https://update.greatest.deepsurf.us/scripts/423722/916211/Camamba%20Chat%20Helpers.js
// ==UserScript==
// @name Camamba Chat Helpers
// @namespace dannysaurus.camamba
// @version 0.1.8
// @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, janusSend, wsSend, activeMainRoom, postToSite */
(function() {
function decorateUsers(users = {}) {
const isUser = (user) => {
return user.id;
};
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).filter(u => isUser(u)).forEach(u => {
if(userPredicateFnc(u)) {
result.push(u);
} else {
excluded.push(u);
}
});
if (excluded.length) {
result.excluded = decorateUsers(excluded);
result.excludedAll = decorateUsers([ ...excluded, ...users.excludedAll ]);
}
return decorateUsers(result);
};
const byId = (id) => {
return by(user => user.id == id);
};
const byName = (name) => {
const nameLower = String(name).toLowerCase();
return by(user => {
return user.name.toLowerCase().includes(nameLower);
});
};
const byGender = (gender) => {
const genderLower = String(gender).toLowerCase();
return by(user => {
return user.gender.toLowerCase().startsWith(genderLower);
});
};
const bySelected = () => {
const selectedUserId = selectedUser ? selectedUser.dataset.id : 0;
if (!selectedUserId) {
return by(user => false);
}
return byId(selectedUserId);
};
const byIsCammed = () => {
if (!camData) return false;
const camDataUserIds = new Set(
Object.values(camData)
.filter(cd => cd.user)
.map(cd => String(cd.user))
);
return by(user => {
return camDataUserIds.has(String(user.id));
});
};
const byViewing = () => {
return users.by(user => {
return user.viewing;
});
};
const byPos = (pos) => {
return toArray()[pos];
};
const stopViewing = () => {
return byViewing().forEach(user => {
janusSend('remove', user.id);
});
};
const save = () => toArray().forEach(user => {
user.original = {...user};
});
const restore = () => by(user => user.original).forEach(user => {
Object.assign(user, user.original);
delete user.original;
});
const ban = (text, time, config = { isPublic: false, isPerma: false, suppressBanLog: false }) => {
const { isPublic, isPerma, suppressBanLog } = config;
if (me.admin && toArray(users).length === 1) {
const currentAdminTarget = users[0].id;
// ban
wsSend( { command: "ban", target: currentAdminTarget, reason: text, time: time * 3600 } );
// notify user
wsSend( { command: "admin", type: "admin", msg: { text: knownUsers[me.id].name + " banned " + knownUsers[currentAdminTarget].name+" for "+time+" hours.", room: activeMainRoom, notify: true }} );
// to banlog
if (!suppressBanLog) {
postToSite("/adm_banned.php", "duration="+time+"&myname="+escape(knownUsers[me.id].name)+"&banname="+escape(knownUsers[currentAdminTarget].name)+"&roomname="+escape(activeMainRoom)+"&reason="+escape(text));
}
// to chat
if (isPublic) {
wsSend( { command: "admin", type: "room", msg: { text: knownUsers[currentAdminTarget].name+" has been banned.", room: activeMainRoom }} );
}
// do perma
if (isPerma) {
postToSite("/adm_set.php", "uID="+currentAdminTarget+"&ban=-1");
}
}
};
return Object.defineProperties(users, Object.fromEntries(Object.entries({
excluded: users.excluded || [],
excludedAll: users.excludedAll || [],
toArray,
toString,
by,
byId,
bySelected,
byName,
byGender,
byPos,
byIsCammed,
byIsNotCammed: () => byIsCammed().excluded,
byViewing,
stopViewing,
ban,
banPerma: (text, time) => ban(text, time, { isPublic: false, isPerma: true, suppressBanLog: false }),
banSilent: (text, time) => ban(text, time, { isPublic: false, isPerma: false, suppressBanLog: true }),
banSilentPerma: (text, time) => ban(text, time, { isPublic: false, isPerma: true, suppressBanLog: true }),
save,
restore
}).map(([propName, value]) => {
return [propName, { value, configurable: true }];
})));
}
function decorateRooms(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 = ({ getExpected, doPatch, confirmAvailable = null, timeOutRetryMillis = 200, maxPeriodTryMillis = 5000 }) => {
const expected = getExpected();
const isAvailable = confirmAvailable ? confirmAvailable(expected) : !!expected;
if (!isAvailable) {
if (timeOutRetryMillis <= maxPeriodTryMillis) {
setTimeout(() => {
maxPeriodTryMillis -= timeOutRetryMillis;
patchObject({ getExpected, doPatch, confirmAvailable, timeOutRetryMillis, maxPeriodTryMillis });
}, timeOutRetryMillis);
}
return;
}
doPatch(expected);
};
patchObject({
getExpected: () => {
return knownUsers;
},
doPatch: (users) => {
decorateUsers(users);
}
});
patchObject({
getExpected: () => {
return rooms;
},
doPatch: (rooms) => {
decorateRooms(rooms);
}
});
})();