Merge pull request #249 from JsSucks/builtin-refactor
Merge for now for e2ee fix.
This commit is contained in:
commit
7d05d0c884
|
@ -9,29 +9,32 @@
|
|||
*/
|
||||
|
||||
import BuiltinModule from './BuiltinModule';
|
||||
import { Patcher, MonkeyPatch, Reflection, ReactComponents } from 'modules';
|
||||
import { Reflection } from 'modules';
|
||||
|
||||
const twelveHour = new RegExp(`([0-9]{1,2}):([0-9]{1,2})\\s(AM|PM)`);
|
||||
|
||||
export default new class TwentyFourHour extends BuiltinModule {
|
||||
|
||||
get settingPath() {
|
||||
return ['ui', 'default', '24-hour'];
|
||||
}
|
||||
/* Getters */
|
||||
get moduleName() { return 'TwentyFourHour' }
|
||||
|
||||
async enabled(e) {
|
||||
if (Patcher.getPatchesByCaller('BD:TwentyFourHour').length) return;
|
||||
get settingPath() { return ['ui', 'default', '24-hour'] }
|
||||
|
||||
/* Patches */
|
||||
applyPatches() {
|
||||
if (this.patches.length) return;
|
||||
const { TimeFormatter } = Reflection.modules;
|
||||
MonkeyPatch('BD:TwentyFourHour', TimeFormatter).after('calendarFormat', (thisObject, args, returnValue) => {
|
||||
const matched = returnValue.match(twelveHour);
|
||||
if (!matched || matched.length != 4) return;
|
||||
if (matched[3] == 'AM') return returnValue.replace(matched[0], `${matched[1] == '12' ? '00' : matched[1].padStart(2, '0')}:${matched[2]}`)
|
||||
return returnValue.replace(matched[0], `${parseInt(matched[1]) + 12}:${matched[2]}`)
|
||||
});
|
||||
this.patch(TimeFormatter, 'calendarFormat', this.convertTimeStamps);
|
||||
}
|
||||
|
||||
disabled(e) {
|
||||
Patcher.unpatchAll('BD:TwentyFourHour');
|
||||
/**
|
||||
* Convert 12 hours timestamps to 24 hour timestamps
|
||||
*/
|
||||
convertTimeStamps(that, args, returnValue) {
|
||||
const matched = returnValue.match(twelveHour);
|
||||
if (!matched || matched.length !== 4) return;
|
||||
if (matched[3] === 'AM') return returnValue.replace(matched[0], `${matched[1] === '12' ? '00' : matched[1].padStart(2, '0')}:${matched[2]}`)
|
||||
return returnValue.replace(matched[0], `${parseInt(matched[1]) + 12}:${matched[2]}`)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -9,41 +9,48 @@
|
|||
*/
|
||||
|
||||
import BuiltinModule from './BuiltinModule';
|
||||
import { Patcher, MonkeyPatch, Reflection, ReactComponents } from 'modules';
|
||||
import { Reflection } from 'modules';
|
||||
|
||||
export default new class BlockedMessages extends BuiltinModule {
|
||||
|
||||
get settingPath() {
|
||||
return ['ui', 'default', 'blocked-messages'];
|
||||
}
|
||||
/* Getters */
|
||||
get moduleName() { return 'BlockedMessages' }
|
||||
|
||||
static isBlocked(id) {
|
||||
const { RelationshipStore } = Reflection.modules;
|
||||
return RelationshipStore.isBlocked(id);
|
||||
}
|
||||
get settingPath() { return ['ui', 'default', 'blocked-messages'] }
|
||||
|
||||
async enabled(e) {
|
||||
if (Patcher.getPatchesByCaller('BD:BlockedMessages').length) return;
|
||||
const { MessageActions } = Reflection.modules;
|
||||
MonkeyPatch('BD:BlockedMessages', MessageActions).instead('receiveMessage', this.processMessage);
|
||||
|
||||
const MessageListComponents = Reflection.module.byProps('BlockedMessageGroup');
|
||||
MessageListComponents.OriginalBlockedMessageGroup = MessageListComponents.BlockedMessageGroup;
|
||||
MessageListComponents.BlockedMessageGroup = () => {return null;};
|
||||
MessageListComponents.BlockedMessageGroup = () => { return null; };
|
||||
this.cancelBlockedMessages = () => {
|
||||
MessageListComponents.BlockedMessageGroup = MessageListComponents.OriginalBlockedMessageGroup;
|
||||
delete MessageListComponents.OriginalBlockedMessageGroup;
|
||||
}
|
||||
}
|
||||
|
||||
processMessage(thisObject, args, originalFunction) {
|
||||
disabled(e) {
|
||||
if (this.cancelBlockedMessages) this.cancelBlockedMessages();
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
static isBlocked(id) {
|
||||
const { RelationshipStore } = Reflection.modules;
|
||||
return RelationshipStore.isBlocked(id);
|
||||
}
|
||||
|
||||
/* Patches */
|
||||
applyPatches() {
|
||||
if (this.patches.length) return;
|
||||
const { MessageActions } = Reflection.modules;
|
||||
this.patch(MessageActions, 'receiveMessage', this.processMessage, 'instead');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignore blocked messages completely
|
||||
*/
|
||||
processMessage(that, args, originalFunction) {
|
||||
if (args[1] && args[1].author && args[1].author.id && BlockedMessages.isBlocked(args[1].author.id)) return;
|
||||
return originalFunction(...args);
|
||||
}
|
||||
|
||||
disabled(e) {
|
||||
Patcher.unpatchAll('BD:BlockedMessages');
|
||||
if (this.cancelBlockedMessages) this.cancelBlockedMessages();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,58 +11,57 @@
|
|||
import BuiltinModule from './BuiltinModule';
|
||||
|
||||
import { Utils } from 'common';
|
||||
import { Settings, Patcher, MonkeyPatch, Reflection, ReactComponents, DiscordApi } from 'modules';
|
||||
import { Settings, Reflection, ReactComponents, DiscordApi } from 'modules';
|
||||
|
||||
export default new class ColoredText extends BuiltinModule {
|
||||
|
||||
/* Getters */
|
||||
get moduleName() { return 'ColoredText' }
|
||||
|
||||
get settingPath() { return ['ui', 'default', 'colored-text'] }
|
||||
|
||||
get intensityPath() { return ['ui', 'advanced', 'colored-text-intensity'] }
|
||||
|
||||
get intensitySetting() { return Settings.getSetting(...this.intensityPath) }
|
||||
|
||||
get intensity() { return 100 - this.intensitySetting.value }
|
||||
|
||||
get defaultColor() { return DiscordApi.UserSettings.theme == 'light' ? '#747f8d' : '#dcddde' }
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this._intensityUpdated = this._intensityUpdated.bind(this);
|
||||
this.injectColoredText = this.injectColoredText.bind(this);
|
||||
}
|
||||
|
||||
get settingPath() {
|
||||
return ['ui', 'default', 'colored-text'];
|
||||
async enabled(e) {
|
||||
this.intensitySetting.off('setting-updated', this._intensityUpdated);
|
||||
this.intensitySetting.on('setting-updated', this._intensityUpdated);
|
||||
}
|
||||
|
||||
get intensityPath() {
|
||||
return ['ui', 'advanced', 'colored-text-intensity'];
|
||||
}
|
||||
|
||||
get intensitySetting() {
|
||||
return Settings.getSetting(...this.intensityPath);
|
||||
}
|
||||
|
||||
get intensity() {
|
||||
return 100 - this.intensitySetting.value;
|
||||
disabled(e) {
|
||||
this.intensitySetting.off('setting-updated', this._intensityUpdated);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
_intensityUpdated() {
|
||||
this.MessageContent.forceUpdateAll();
|
||||
}
|
||||
|
||||
async enabled(e) {
|
||||
if (Patcher.getPatchesByCaller('BD:ColoredText').length) return;
|
||||
this.intensitySetting.on('setting-updated', this._intensityUpdated);
|
||||
/* Patches */
|
||||
async applyPatches() {
|
||||
if (this.patches.length) return;
|
||||
this.MessageContent = await ReactComponents.getComponent('MessageContent', { selector: Reflection.resolve('container', 'containerCozy', 'containerCompact', 'edited').selector });
|
||||
MonkeyPatch('BD:ColoredText', this.MessageContent.component.prototype).after('render', this.injectColoredText);
|
||||
this.patch(this.MessageContent.component.prototype, 'render', this.injectColoredText);
|
||||
this.MessageContent.forceUpdateAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set markup text colour to match role colour
|
||||
*/
|
||||
injectColoredText(thisObject, args, returnValue) {
|
||||
const { TinyColor } = Reflection.modules;
|
||||
const markup = Utils.findInReactTree(returnValue, m => m && m.props && m.props.className && m.props.className.includes('da-markup'));
|
||||
const roleColor = thisObject.props.message.colorString;
|
||||
if (markup && roleColor) markup.props.style = {color: TinyColor.mix(roleColor, this.defaultColor, this.intensity)};
|
||||
}
|
||||
|
||||
get defaultColor() {
|
||||
return DiscordApi.UserSettings.theme == 'light' ? '#747f8d' : '#dcddde';
|
||||
}
|
||||
|
||||
disabled(e) {
|
||||
Patcher.unpatchAll('BD:ColoredText');
|
||||
this.intensitySetting.off('setting-updated', this._intensityUpdated);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ export default new class E2EE extends BuiltinModule {
|
|||
const items = Settings.getSetting('security', 'e2eedb', 'e2ekvps').items;
|
||||
const index = items.findIndex(kvp => kvp.value.key === channelId);
|
||||
if (index > -1) {
|
||||
items[index].value = {key: channelId, value: key};
|
||||
items[index].value = { key: channelId, value: key };
|
||||
return;
|
||||
}
|
||||
Settings.getSetting('security', 'e2eedb', 'e2ekvps').addItem({ value: { key: channelId, value: key } });
|
||||
|
@ -223,7 +223,7 @@ export default new class E2EE extends BuiltinModule {
|
|||
const parsed = MessageParser.parse(currentChannel, decrypt).content;
|
||||
|
||||
if (userMentionPattern.test(parsed))
|
||||
event.message.mentions = parsed.match(userMentionPattern).map(m => {return {id: m.replace(/[^0-9]/g, '')}});
|
||||
event.message.mentions = parsed.match(userMentionPattern).map(m => { return { id: m.replace(/[^0-9]/g, '') } });
|
||||
if (roleMentionPattern.test(parsed))
|
||||
event.message.mention_roles = parsed.match(roleMentionPattern).map(m => m.replace(/[^0-9]/g, ''));
|
||||
if (everyoneMentionPattern.test(parsed))
|
||||
|
@ -245,7 +245,8 @@ export default new class E2EE extends BuiltinModule {
|
|||
const key = this.getKey(component.props.message.channel_id);
|
||||
if (!key) return; // We don't have a key for this channel
|
||||
|
||||
const { Message, MessageParser, Permissions, DiscordConstants } = Reflection.modules;
|
||||
const Message = Reflection.module.byPrototypes('isMentioned');
|
||||
const { MessageParser, Permissions, DiscordConstants } = Reflection.modules;
|
||||
const currentChannel = DiscordApi.Channel.fromId(component.props.message.channel_id).discordObject;
|
||||
|
||||
if (typeof component.props.message.content !== 'string') return; // Ignore any non string content
|
||||
|
@ -261,7 +262,7 @@ export default new class E2EE extends BuiltinModule {
|
|||
const message = MessageParser.createMessage(currentChannel.id, MessageParser.parse(currentChannel, decrypt).content);
|
||||
|
||||
if (userMentionPattern.test(message.content))
|
||||
message.mentions = message.content.match(userMentionPattern).map(m => {return {id: m.replace(/[^0-9]/g, '')}});
|
||||
message.mentions = message.content.match(userMentionPattern).map(m => { return { id: m.replace(/[^0-9]/g, '') } });
|
||||
if (roleMentionPattern.test(message.content))
|
||||
message.mention_roles = message.content.match(roleMentionPattern).map(m => m.replace(/[^0-9]/g, ''));
|
||||
if (everyoneMentionPattern.test(message.content))
|
||||
|
|
|
@ -13,6 +13,7 @@ import { Settings } from 'modules';
|
|||
import BuiltinModule from './BuiltinModule';
|
||||
import EmoteModule from './EmoteModule';
|
||||
import GlobalAc from '../ui/autocomplete';
|
||||
import { BdContextMenu } from 'ui';
|
||||
|
||||
const EMOTE_SOURCES = [
|
||||
'https://static-cdn.jtvnw.net/emoticons/v1/:id/1.0',
|
||||
|
@ -22,14 +23,46 @@ const EMOTE_SOURCES = [
|
|||
|
||||
export default new class EmoteAc extends BuiltinModule {
|
||||
|
||||
/* Getters */
|
||||
get moduleName() { return 'EmoteAC' }
|
||||
get settingPath() { return ['emotes', 'default', 'emoteac'] }
|
||||
|
||||
async enabled(e) {
|
||||
GlobalAc.add(';', this);
|
||||
window.removeEventListener('contextmenu', this.acCm);
|
||||
window.addEventListener('contextmenu', this.acCm);
|
||||
}
|
||||
|
||||
disabled(e) {
|
||||
GlobalAc.remove(';');
|
||||
window.removeEventListener('contextmenu', this.acCm);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
acCm(e) {
|
||||
const row = e.target.closest('.bd-emotAc');
|
||||
if (!row) return;
|
||||
const img = row.querySelector('img');
|
||||
if (!img || !img.alt) return;
|
||||
|
||||
BdContextMenu.show(e, [
|
||||
{
|
||||
text: 'Test',
|
||||
items: [
|
||||
{
|
||||
text: 'Favourite',
|
||||
type: 'toggle',
|
||||
checked: EmoteModule.isFavourite(img.alt.replace(/;/g, '')),
|
||||
onChange: checked => {
|
||||
if (!img || !img.alt) return;
|
||||
const emote = img.alt.replace(/;/g, '');
|
||||
if (!checked) return EmoteModule.removeFavourite(emote), false;
|
||||
return EmoteModule.addFavourite(emote), true;
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,7 +84,8 @@ export default new class EmoteAc extends BuiltinModule {
|
|||
hint: mu.useCount ? `Used ${mu.useCount} times` : null
|
||||
}
|
||||
}
|
||||
})
|
||||
}),
|
||||
extraClasses: ['bd-emotAc']
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +97,8 @@ export default new class EmoteAc extends BuiltinModule {
|
|||
result.value.src = EMOTE_SOURCES[result.value.type].replace(':id', result.value.id);
|
||||
result.value.replaceWith = `;${result.key};`;
|
||||
return result;
|
||||
})
|
||||
}),
|
||||
extraClasses: ['bd-emotAc']
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,9 @@ import BuiltinModule from './BuiltinModule';
|
|||
import path from 'path';
|
||||
import { request } from 'vendor';
|
||||
|
||||
import { Utils, FileUtils, ClientLogger as Logger } from 'common';
|
||||
import { DiscordApi, Settings, Globals, Reflection, ReactComponents, MonkeyPatch, Cache, Patcher, Database } from 'modules';
|
||||
import { VueInjector, DiscordContextMenu } from 'ui';
|
||||
import { Utils, FileUtils } from 'common';
|
||||
import { DiscordApi, Settings, Globals, Reflection, ReactComponents, Database } from 'modules';
|
||||
import { DiscordContextMenu } from 'ui';
|
||||
|
||||
import Emote from './EmoteComponent.js';
|
||||
import Autocomplete from '../ui/components/common/Autocomplete.vue';
|
||||
|
@ -29,6 +29,10 @@ const EMOTE_SOURCES = [
|
|||
|
||||
export default new class EmoteModule extends BuiltinModule {
|
||||
|
||||
/* Getters */
|
||||
|
||||
get moduleName() { return 'EmoteModule' }
|
||||
|
||||
/**
|
||||
* @returns {String} Path to local emote database
|
||||
*/
|
||||
|
@ -76,13 +80,14 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
|
||||
// Read favourites and most used from database
|
||||
await this.loadUserData();
|
||||
|
||||
this.patchMessageContent();
|
||||
this.patchSendAndEdit();
|
||||
const ImageWrapper = await ReactComponents.getComponent('ImageWrapper', { selector: Reflection.resolve('imageWrapper').selector });
|
||||
MonkeyPatch('BD:EMOTEMODULE', ImageWrapper.component.prototype).after('render', this.beforeRenderImageWrapper.bind(this));
|
||||
}
|
||||
|
||||
async disabled() {
|
||||
DiscordContextMenu.remove(this.favCm);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
* Adds an emote to favourites.
|
||||
* @param {Object|String} emote
|
||||
|
@ -115,12 +120,6 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
return !!this.favourites.find(e => e.name === emote || e.name === emote.name);
|
||||
}
|
||||
|
||||
async disabled() {
|
||||
// Unpatch all patches
|
||||
for (const patch of Patcher.getPatchesByCaller('BD:EMOTEMODULE')) patch.unpatch();
|
||||
DiscordContextMenu.remove(this.favCm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load emotes from local database
|
||||
*/
|
||||
|
@ -151,15 +150,96 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/update emote to most used
|
||||
* @param {Object} emote emote to add/update
|
||||
* @return {Promise}
|
||||
*/
|
||||
addToMostUsed(emote) {
|
||||
const isMostUsed = this.mostUsed.find(mu => mu.key === emote.name);
|
||||
if (isMostUsed) {
|
||||
isMostUsed.useCount += 1;
|
||||
} else {
|
||||
this.mostUsed.push({
|
||||
key: emote.name,
|
||||
id: emote.id,
|
||||
type: emote.type,
|
||||
useCount: 1
|
||||
});
|
||||
}
|
||||
// Save most used to database
|
||||
// TODO only save first n
|
||||
return this.saveUserData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an emote by name
|
||||
* @param {String} name Emote name
|
||||
* @param {Boolean} simple Simple object or Emote instance
|
||||
* @returns {Object|Emote}
|
||||
*/
|
||||
findByName(name, simple = false) {
|
||||
const emote = this.database.get(name);
|
||||
if (!emote) return null;
|
||||
return this.parseEmote(name, emote, simple);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse emote object
|
||||
* @param {String} name Emote name
|
||||
* @param {Object} emote Emote object
|
||||
* @param {Boolean} simple Simple object or Emote instance
|
||||
* @returns {Object|Emote}
|
||||
*/
|
||||
parseEmote(name, emote, simple = false) {
|
||||
const { type, id } = emote;
|
||||
if (type < 0 || type > 2) return null;
|
||||
return simple ? { type, id, name } : new Emote(type, id, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for anything else
|
||||
* @param {any} regex
|
||||
* @param {any} limit
|
||||
*/
|
||||
search(regex, limit = 10) {
|
||||
if (typeof regex === 'string') regex = new RegExp(regex, 'i');
|
||||
const matching = [];
|
||||
|
||||
for (const [key, value] of this.database.entries()) {
|
||||
if (matching.length >= limit) break;
|
||||
if (regex.test(key)) matching.push({ key, value })
|
||||
}
|
||||
|
||||
return matching;
|
||||
}
|
||||
|
||||
/* Patches */
|
||||
async applyPatches() {
|
||||
this.patchMessageContent();
|
||||
this.patchSendAndEdit();
|
||||
const ImageWrapper = await ReactComponents.getComponent('ImageWrapper', { selector: Reflection.resolve('imageWrapper').selector });
|
||||
this.patch(ImageWrapper.component.prototype, 'render', this.beforeRenderImageWrapper, 'before');
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches MessageContent render method
|
||||
*/
|
||||
async patchMessageContent() {
|
||||
const MessageContent = await ReactComponents.getComponent('MessageContent', { selector: Reflection.resolve('container', 'containerCozy', 'containerCompact', 'edited').selector });
|
||||
MonkeyPatch('BD:EMOTEMODULE', MessageContent.component.prototype).after('render', this.afterRenderMessageContent.bind(this));
|
||||
this.patch(MessageContent.component.prototype, 'render', this.afterRenderMessageContent);
|
||||
MessageContent.forceUpdateAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches MessageActions send and edit
|
||||
*/
|
||||
patchSendAndEdit() {
|
||||
const { MessageActions } = Reflection.modules;
|
||||
this.patch(MessageActions, 'sendMessage', this.handleSendMessage, 'instead');
|
||||
this.patch(MessageActions, 'editMessage', this.handleEditMessage, 'instead');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle message render
|
||||
*/
|
||||
|
@ -173,15 +253,6 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
markup.children[1] = this.processMarkup(markup.children[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches MessageActions send and edit
|
||||
*/
|
||||
patchSendAndEdit() {
|
||||
const { MessageActions } = Reflection.modules;
|
||||
MonkeyPatch('BD:EMOTEMODULE', MessageActions).instead('sendMessage', this.handleSendMessage.bind(this));
|
||||
MonkeyPatch('BD:EMOTEMODULE', MessageActions).instead('editMessage', this.handleEditMessage.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle send message
|
||||
*/
|
||||
|
@ -253,28 +324,6 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
retVal.props.children = emote.render();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/update emote to most used
|
||||
* @param {Object} emote emote to add/update
|
||||
* @return {Promise}
|
||||
*/
|
||||
addToMostUsed(emote) {
|
||||
const isMostUsed = this.mostUsed.find(mu => mu.key === emote.name);
|
||||
if (isMostUsed) {
|
||||
isMostUsed.useCount += 1;
|
||||
} else {
|
||||
this.mostUsed.push({
|
||||
key: emote.name,
|
||||
id: emote.id,
|
||||
type: emote.type,
|
||||
useCount: 1
|
||||
});
|
||||
}
|
||||
// Save most used to database
|
||||
// TODO only save first n
|
||||
return this.saveUserData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject emotes into markup
|
||||
*/
|
||||
|
@ -330,46 +379,4 @@ export default new class EmoteModule extends BuiltinModule {
|
|||
return newMarkup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an emote by name
|
||||
* @param {String} name Emote name
|
||||
* @param {Boolean} simple Simple object or Emote instance
|
||||
* @returns {Object|Emote}
|
||||
*/
|
||||
findByName(name, simple = false) {
|
||||
const emote = this.database.get(name);
|
||||
if (!emote) return null;
|
||||
return this.parseEmote(name, emote, simple);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse emote object
|
||||
* @param {String} name Emote name
|
||||
* @param {Object} emote Emote object
|
||||
* @param {Boolean} simple Simple object or Emote instance
|
||||
* @returns {Object|Emote}
|
||||
*/
|
||||
parseEmote(name, emote, simple = false) {
|
||||
const { type, id } = emote;
|
||||
if (type < 0 || type > 2) return null;
|
||||
return simple ? { type, id, name } : new Emote(type, id, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for anything else
|
||||
* @param {any} regex
|
||||
* @param {any} limit
|
||||
*/
|
||||
search(regex, limit = 10) {
|
||||
if (typeof regex === 'string') regex = new RegExp(regex, 'i');
|
||||
const matching = [];
|
||||
|
||||
for (const [key, value] of this.database.entries()) {
|
||||
if (matching.length >= limit) break;
|
||||
if (regex.test(key)) matching.push({ key, value })
|
||||
}
|
||||
|
||||
return matching;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,22 +9,20 @@
|
|||
*/
|
||||
|
||||
import BuiltinModule from './BuiltinModule';
|
||||
import { Patcher, MonkeyPatch, Reflection } from 'modules';
|
||||
import { Reflection } from 'modules';
|
||||
|
||||
export default new class KillClyde extends BuiltinModule {
|
||||
|
||||
get settingPath() {
|
||||
return ['ui', 'default', 'kill-clyde'];
|
||||
}
|
||||
/* Getters */
|
||||
get moduleName() { return 'KillClyde' }
|
||||
|
||||
async enabled(e) {
|
||||
if (Patcher.getPatchesByCaller('BD:KillClyde').length) return;
|
||||
get settingPath() { return ['ui', 'default', 'kill-clyde'] }
|
||||
|
||||
/* Patches */
|
||||
applyPatches() {
|
||||
if (this.patches.length) return;
|
||||
const { MessageActions } = Reflection.modules;
|
||||
MonkeyPatch('BD:KillClyde', MessageActions).instead('sendBotMessage', void 0);
|
||||
}
|
||||
|
||||
disabled(e) {
|
||||
Patcher.unpatchAll('BD:KillClyde');
|
||||
this.patch(MessageActions, 'sendBotMessage', () => void 0, 'instead');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,15 +18,16 @@ import { Toasts } from 'ui';
|
|||
|
||||
export default new class ReactDevtoolsModule extends BuiltinModule {
|
||||
|
||||
/* Getters */
|
||||
get moduleName() { return 'ReactDevTools' }
|
||||
|
||||
get settingPath() { return ['core', 'advanced', 'react-devtools'] }
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.devToolsOpened = this.devToolsOpened.bind(this);
|
||||
}
|
||||
|
||||
get settingPath() {
|
||||
return ['core', 'advanced', 'react-devtools'];
|
||||
}
|
||||
|
||||
enabled(e) {
|
||||
electron.remote.getCurrentWindow().webContents.on('devtools-opened', this.devToolsOpened);
|
||||
if (electron.remote.getCurrentWindow().isDevToolsOpened) this.devToolsOpened();
|
||||
|
|
|
@ -10,27 +10,27 @@
|
|||
|
||||
import BuiltinModule from './BuiltinModule';
|
||||
|
||||
import { Patcher, MonkeyPatch, Reflection } from 'modules';
|
||||
import { Reflection } from 'modules';
|
||||
|
||||
export default new class E2EE extends BuiltinModule {
|
||||
|
||||
get settingPath() {
|
||||
return ['security', 'default', 'tracking-protection'];
|
||||
/* Getters */
|
||||
get moduleName() { return 'TrackingProtection' }
|
||||
|
||||
get settingPath() { return ['security', 'default', 'tracking-protection'] }
|
||||
|
||||
/* Patches */
|
||||
applyPatches() {
|
||||
if (this.patches.length) return;
|
||||
const TrackingModule = Reflection.module.byProps('track');
|
||||
if (!TrackingModule) {
|
||||
this.warn('Tracking module not found!');
|
||||
return;
|
||||
}
|
||||
this.patch(TrackingModule, 'track', this.track, 'instead');
|
||||
}
|
||||
|
||||
track(e) {
|
||||
// console.log('Blocked Tracking');
|
||||
this.debug('Tracking blocked');
|
||||
}
|
||||
|
||||
enabled(e) {
|
||||
if (Patcher.getPatchesByCaller('BD:TrackingProtection').length) return;
|
||||
const trackingModule = Reflection.module.byProps('track');
|
||||
if (!trackingModule) return; // TODO Log it
|
||||
MonkeyPatch('BD:TrackingProtection', trackingModule).instead('track', this.track);
|
||||
}
|
||||
|
||||
disabled(e) {
|
||||
for (const patch of Patcher.getPatchesByCaller('BD:TrackingProtection')) patch.unpatch();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,21 +13,23 @@ import { Reflection } from 'modules';
|
|||
|
||||
export default new class VoiceDisconnect extends BuiltinModule {
|
||||
|
||||
get settingPath() {
|
||||
return ['core', 'default', 'voice-disconnect'];
|
||||
}
|
||||
/* Getters */
|
||||
get moduleName() { return 'VoiceDisconnect' }
|
||||
|
||||
get settingPath() { return ['core', 'default', 'voice-disconnect'] }
|
||||
|
||||
async enabled(e) {
|
||||
window.addEventListener('beforeunload', this.listener);
|
||||
}
|
||||
|
||||
listener() {
|
||||
const { VoiceChannelActions } = Reflection.modules;
|
||||
VoiceChannelActions.selectVoiceChannel(null, null);
|
||||
}
|
||||
|
||||
disabled(e) {
|
||||
window.removeEventListener('beforeunload', this.listener);
|
||||
}
|
||||
|
||||
/* Methods */
|
||||
listener() {
|
||||
const { VoiceChannelActions } = Reflection.modules;
|
||||
VoiceChannelActions.selectVoiceChannel(null, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,15 +18,16 @@ import { Toasts } from 'ui';
|
|||
|
||||
export default new class VueDevtoolsModule extends BuiltinModule {
|
||||
|
||||
/* Getters */
|
||||
get moduleName() { return 'VueDevTools' }
|
||||
|
||||
get settingPath() { return ['core', 'advanced', 'vue-devtools'] }
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.devToolsOpened = this.devToolsOpened.bind(this);
|
||||
}
|
||||
|
||||
get settingPath() {
|
||||
return ['core', 'advanced', 'vue-devtools'];
|
||||
}
|
||||
|
||||
enabled(e) {
|
||||
electron.remote.getCurrentWindow().webContents.on('devtools-opened', this.devToolsOpened);
|
||||
if (electron.remote.getCurrentWindow().isDevToolsOpened) this.devToolsOpened();
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="bd-acScroller" ref="scroller">
|
||||
<div v-for="(item, index) in search.items" class="bd-acRow" @mouseover="selectedIndex = index" @click="inject">
|
||||
<div v-for="(item, index) in search.items" class="bd-acRow" :class="search.extraClasses" @mouseover="selectedIndex = index" @click="inject">
|
||||
<div class="bd-acSelector bd-selectable" :class="{'bd-selected': index === selectedIndex}">
|
||||
<div class="bd-acField">
|
||||
<img v-if="search.type === 'imagetext'" :src="item.src || item.value.src" :alt="item.key || item.text || item.alt" />
|
||||
|
|
Loading…
Reference in New Issue