From fce24e6a6a4c242d9a5599fdee147694593dc246 Mon Sep 17 00:00:00 2001 From: Jiiks Date: Fri, 2 Feb 2018 14:45:06 +0200 Subject: [PATCH] Eventhook base, structures, add lodash --- client/src/index.js | 14 +- client/src/modules/eventhook.js | 143 ++++++++++++++++++ client/src/modules/globals.js | 16 +- client/src/modules/modulemanager.js | 9 +- client/src/modules/modules.js | 4 +- client/src/modules/socketproxy.js | 39 +++++ client/src/modules/vendor.js | 9 ++ client/src/structs/socketstructs.js | 4 + client/src/structs/socketstructs/channel.js | 28 ++++ .../src/structs/socketstructs/discordevent.js | 18 +++ client/src/structs/socketstructs/generic.js | 50 ++++++ client/src/structs/socketstructs/guild.js | 83 ++++++++++ client/src/structs/socketstructs/message.js | 51 +++++++ common/modules/utils.js | 21 ++- package.json | 1 + 15 files changed, 472 insertions(+), 18 deletions(-) create mode 100644 client/src/modules/eventhook.js create mode 100644 client/src/modules/socketproxy.js create mode 100644 client/src/structs/socketstructs.js create mode 100644 client/src/structs/socketstructs/channel.js create mode 100644 client/src/structs/socketstructs/discordevent.js create mode 100644 client/src/structs/socketstructs/generic.js create mode 100644 client/src/structs/socketstructs/guild.js create mode 100644 client/src/structs/socketstructs/message.js diff --git a/client/src/index.js b/client/src/index.js index 55183a4d..ca2e448a 100644 --- a/client/src/index.js +++ b/client/src/index.js @@ -10,21 +10,31 @@ import { DOM, BdUI } from 'ui'; import BdCss from './styles/index.scss'; -import { Events, CssEditor, Globals, PluginManager, ThemeManager, ModuleManager } from 'modules'; +import { Events, CssEditor, Globals, PluginManager, ThemeManager, ModuleManager, WebpackModules } from 'modules'; import { ClientLogger as Logger } from 'common'; class BetterDiscord { constructor() { + window.events = Events; + window.wpm = WebpackModules; DOM.injectStyle(BdCss, 'bdmain'); Events.on('global-ready', this.globalReady.bind(this)); } async init() { + await ModuleManager.initModules(); await PluginManager.loadAllPlugins(); await ThemeManager.loadAllThemes(); - ModuleManager.initModules(); Events.emit('ready'); + Events.emit('discord-ready'); + /* var count = 0; + const waitForDiscord = setInterval(() => { + if (!window.__require) return; + clearInterval(waitForDiscord); + console.log(`waited ${count * 100}ms`); + Events.emit('discord-ready'); + }, 100);*/ } globalReady() { diff --git a/client/src/modules/eventhook.js b/client/src/modules/eventhook.js new file mode 100644 index 00000000..47df759a --- /dev/null +++ b/client/src/modules/eventhook.js @@ -0,0 +1,143 @@ +/** + * BetterDiscord WebpackModules Module + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + +import EventListener from './eventlistener'; +import { Utils } from 'common'; +import Events from './events'; + +import { + MESSAGE_CREATE + } from '../structs/socketstructs'; + + +export default class extends EventListener { + + bindings() { + this.hook = this.hook.bind(this); + } + + get eventBindings() { + return [ + { id: 'discord-ready', callback: this.hook } + ]; + } + + hook() { + + } + + get eventsModule() { + + } + + emit(e, action, data) { + switch(e) { + case 'dispatch': + return this.dispatch(action, data); + } + } + + dispatch(e, d) { + + Events.emit('raw-event', { type: e, data: d }); + + switch (e) { + case this.actions.READ: + Events.emit('discord-ready'); + break; + case this.actions.RESUMED: + Events.emit('discord-resumed'); + break; + case this.actions.TYPING_START: + Events.emit('discord-event', { + type: e, + channelId: d.channel_id, + userId: d.user_id + }); + break; + case this.actions.MESSAGE_CREATE: + Events.emit('discord-event', { type: e, data: new MESSAGE_CREATE(d) }); + break; + case 'k': + Events.emit('discord-event', { + + }); + break; + case this.actions.ACTIVITY_START: + Events.emit('discord-event', this.construct(e, d)); + break; + + } + } + + get actions() { + return { + READY: 'READY', // Socket ready + RESUMED: 'RESUMED', // Socket resumed + TYPING_START: 'TYPING_START', // User typing start + ACTIVITY_START: 'ACTIVITY_START', // ?? + MESSAGE_CREATE: 'MESSAGE_CREATE', // New message + MESSAGE_UPDATE: 'MESSAGE_UPDATE', // Edit + MESSAGE_DELETE: 'MESSAGE_DELETE', // Message deleted + MESSAGE_DELETE_BULK: 'MESSAGE_DELETE_BULK', // Bulk messages deleted + MESSAGE_ACK: 'MESSAGE_ACK', // Message fetch + MESSAGE_REACTION_ADD: 'MESSAGE_REACTION_ADD', // eww reactions + MESSAGE_REACTION_REMOVE: 'MESSAGE_REACTION_REMOVE', // ^^ + MESSAGE_REACTION_REMOVE_ALL: 'MESSAGE_REACTION_REMOVE_ALL', // ^^ + CHANNEL_PINS_ACK: 'CHANNEL_PINS_ACK', // Pinned messages fetch + CHANNEL_PINS_UPDATE: 'CHANNEL_PINS_UPDATE', // Message pinned/unpinned, does not trigger when message is deleted + CHANNEL_CREATE: 'CHANNEL_CREATE', // Channel created + CHANNEL_DELETE: 'CHANNEL_DELETE', // Channel deleted + CHANNEL_UPDATE: 'CHANNEL_UPDATE', // Channel updated + GUILD_CREATE: 'GUILD_CREATE', // Guild create + GUILD_DELETE: 'GUILD_DELETE', // Guild delete + GUILD_SYNC: 'GUILD_SYNC', // Synced when switching to server that's not loaded + GUILD_MEMBERS_CHUNK: 'GUILD_MEMBERS_CHUNK', // ?? + GUILD_BAN_ADD: 'GUILD_BAN_ADD', // User banned + GUILD_BAN_REMOVE: 'GUILD_BAN_REMOVE', // User unbanned + GUILD_MEMBER_ADD: 'GUILD_MEMBER_ADD', // User joins guild + GUILD_MEMBER_UPDATE: 'GUILD_MEMBER_UPDATE', // Roles etc + GUILD_MEMBER_REMOVE: 'GUILD_MEMBER_REMOVE', // Kick + GUILD_ROLE_CREATE: 'GUILD_ROLE_CREATE', // Roles + GUILD_ROLE_UPDATE: 'GUILD_ROLE_UPDATE', // Roles + GUILD_ROLE_DELETE: 'GUILD_ROLE_DELETE', // Roles, + GUILD_EMOJIS_UPDATE: 'GUILD_EMOJIS_UPDATE', // No emojis pls + GUILD_INTEGRATIONS_UPDATE: 'GUILD_INTEGRATIONS_UPDATE', // Twitch etc? + USER_UPDATE: 'USER_UPDATE', // Name change etc? + USER_SETTINGS_UPDATE: 'USER_SETTINGS_UPDATE', // Any setting change + USER_GUILD_SETTINGS_UPDATE: 'USER_GUILD_SETTINGS_UPDATE', // Guild notification/privacy etc + USER_CONNECTIONS_UPDATE: 'USER_CONNECTIONS_UPDATE', // Steam etc + USER_REQUIRED_ACTION_UPDATE: 'USER_REQUIRED_ACTION_UPDATE', // ?? + USER_NOTE_UPDATE: 'USER_NOTE_UPDATE', // Not edits + RELATIONSHIP_ADD: 'RELATIONSHIP_ADD', // Friends + RELATIONSHIP_REMOVE: 'RELATIONSHIP_REMOVE', // Friends + PRESENCE_UPDATE: 'PRESENCE_UPDATE', // Status + PRESENCES_REPLACE: 'PRESENCES_REPLACE', // ?? + VOICE_STATE_UPDATE: 'VOICE_STATE_UPDATE', // Speaking? + VOICE_SERVER_UPDATE: 'VOICE_SERVER_UPDATE', // ?? + CALL_CREATE: 'CALL_CREATE', // Don't call me + CALL_UPDATE: 'CALL_UPDATE', // ^^^^^^^^^^^^ + CALL_DELETE: 'CALL_DELETE', // ^^^^^^^^^^^^ + OAUTH2_TOKEN_REVOKE: 'OAUTH2_TOKEN_REVOKE', // Logged out elsewhere? + RECENT_MENTION_DELETE: 'RECENT_MENTION_DELETE', // No idea what triggers this? + FRIEND_SUGGESTION_CREATE: 'FRIEND_SUGGESTION_CREATE', // Connected account stuff? + FRIEND_SUGGESTION_DELETE: 'FRIEND_SUGGESTION_DELETE', // ^^ + WEBHOOKS_UPDATE: 'WEBHOOKS_UPDATE', // Any webhook change on any server + USER_PAYMENTS_UPDATE: 'USER_PAYMENTS_UPDATE', // Won't test + USER_BILLING_PROFILE_UPDATE: 'USER_BILLING_PROFILE_UPDATE', // Won't test + ACTIVITY_JOIN_REQUEST: 'ACTIVITY_JOIN_REQUEST', // Nothing seems to trigger this + ACTIVITY_JOIN_INVITE: 'ACTIVITY_JOIN_INVITE', // Same + LFG_LISTING_CREATE: 'LFG_LISTING_CREATE', // No groups here + LFG_LISTING_DELETE: 'LFG_LISTING_DELETE', // Thank you + BRAINTREE_POPUP_BRIDGE_CALLBACK: 'BRAINTREE_POPUP_BRIDGE_CALLBACK' // What + } + } + +} diff --git a/client/src/modules/globals.js b/client/src/modules/globals.js index 824baef3..adc1cc71 100644 --- a/client/src/modules/globals.js +++ b/client/src/modules/globals.js @@ -37,16 +37,16 @@ export default new class extends Module { }; window.jQuery = {}; - Events.emit('global-ready'); - })(); - - if (window.__bd) { - this.setState(window.__bd); - window.__bd = { - setWS: this.setWS + if (window.__bd) { + this.setState(window.__bd); + window.__bd = { + setWS: this.setWS + } } + + Events.emit('global-ready'); Events.emit('socket-created', this.state.wsHook); - } + })(); } setWS(wSocket) { diff --git a/client/src/modules/modulemanager.js b/client/src/modules/modulemanager.js index c2ff7d14..da62132a 100644 --- a/client/src/modules/modulemanager.js +++ b/client/src/modules/modulemanager.js @@ -10,18 +10,20 @@ /*Module Manager initializes all modules when everything is ready*/ -import { Events } from 'modules'; +import { Events, SocketProxy, EventHook } from 'modules'; import { ProfileBadges } from 'ui'; export default class { static get modules() { return this._modules ? this._modules : (this._modules = [ - new ProfileBadges() + new ProfileBadges(), + new SocketProxy(), + new EventHook() ]); } - static initModules() { + static async initModules() { for (let module of this.modules) { try { if (module.init && module.init instanceof Function) module.init(); @@ -29,6 +31,7 @@ export default class { console.log(`Failed to initialize module: ${err}`); } } + return true; } } diff --git a/client/src/modules/modules.js b/client/src/modules/modules.js index 07419b56..3744f96b 100644 --- a/client/src/modules/modules.js +++ b/client/src/modules/modules.js @@ -7,4 +7,6 @@ export { default as Globals } from './globals'; export { default as Vendor } from './vendor'; export { default as WebpackModules } from './webpackmodules'; export { default as ModuleManager } from './modulemanager'; -export { default as EventListener } from './eventlistener'; \ No newline at end of file +export { default as EventListener } from './eventlistener'; +export { default as SocketProxy } from './socketproxy'; +export { default as EventHook } from './eventhook'; diff --git a/client/src/modules/socketproxy.js b/client/src/modules/socketproxy.js new file mode 100644 index 00000000..745d32a8 --- /dev/null +++ b/client/src/modules/socketproxy.js @@ -0,0 +1,39 @@ +/** + * BetterDiscord Discord Socket Proxy Module + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + +import EventListener from './eventlistener'; + +export default class SocketProxy extends EventListener { + + bindings() { + this.socketCreated = this.socketCreated.bind(this); + this.onMessage = this.onMessage.bind(this); + } + + get eventBindings() { + return [ + { id: 'socket-created', 'callback': this.socketCreated } + ]; + } + + get socket() { + return this.activeSocket; + } + + socketCreated(socket) { + this.activeSocket = socket; + // socket.addEventListener('message', this.onMessage); + } + + onMessage(e) { + console.info(e); + } + +} diff --git a/client/src/modules/vendor.js b/client/src/modules/vendor.js index 7df208b1..b0439811 100644 --- a/client/src/modules/vendor.js +++ b/client/src/modules/vendor.js @@ -10,6 +10,7 @@ import WebpackModules from './webpackmodules'; import jQuery from 'jquery'; +import lodash from 'lodash'; export default class { @@ -21,6 +22,14 @@ export default class { return this.jQuery; } + static get lodash() { + return lodash; + } + + static get _() { + return this.lodash; + } + static get moment() { return WebpackModules.getModuleByName('Moment'); } diff --git a/client/src/structs/socketstructs.js b/client/src/structs/socketstructs.js new file mode 100644 index 00000000..09079155 --- /dev/null +++ b/client/src/structs/socketstructs.js @@ -0,0 +1,4 @@ +export * from './socketstructs/channel'; +export * from './socketstructs/generic'; +export * from './socketstructs/guild'; +export * from './socketstructs/message'; diff --git a/client/src/structs/socketstructs/channel.js b/client/src/structs/socketstructs/channel.js new file mode 100644 index 00000000..899b3a71 --- /dev/null +++ b/client/src/structs/socketstructs/channel.js @@ -0,0 +1,28 @@ +/** + * BetterDiscord Channel Event Structs + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + +import DiscordEvent from './discordevent'; + +export class CHANNEL_PINS_UPDATE extends DiscordEvent { + get channelId() { return this.args.channelId } + get lastPinTimestamp() { return this.args.lastPinTimestamp } +} + +// TODO +export class CHANNEL_CREATE extends DiscordEvent {} + +export class CHANNEL_DELETE extends DiscordEvent {} + +export class CHANNEL_UPDATE extends DiscordEvent {} + +export class CHANNEL_PINS_ACK { + get channelId() { return this.args.channelId } + get timestamp() { return this.args.timestamp } +} diff --git a/client/src/structs/socketstructs/discordevent.js b/client/src/structs/socketstructs/discordevent.js new file mode 100644 index 00000000..bae63e59 --- /dev/null +++ b/client/src/structs/socketstructs/discordevent.js @@ -0,0 +1,18 @@ +/** + * BetterDiscord Discord Event Base + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + +import { Utils } from 'common'; + +export default class DiscordEvent { + constructor(args) { + this.args = Utils.toCamelCase(args); + Object.freeze(this.args); + } +} diff --git a/client/src/structs/socketstructs/generic.js b/client/src/structs/socketstructs/generic.js new file mode 100644 index 00000000..f9770123 --- /dev/null +++ b/client/src/structs/socketstructs/generic.js @@ -0,0 +1,50 @@ +/** + * BetterDiscord Generic Event Structs + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + + +import DiscordEvent from './discordevent'; + +export class TYPING_START extends DiscordEvent { + get channelId() { return this.args.channelId } + get userId() { return this.args.userId } +} + +export class PRESENCE_UPDATE extends DiscordEvent { + get game() { return this.args.game } + get guildId() { return this.args.guildId } + get nick() { return this.args.nick } + get roles() { return this.args.roles } + get status() { return this.args.status } + get user() { return this.args.user } + get lastModified() { return this.args.lastModified } +} + +export class VOICE_STATE_UPDATE extends DiscordEvent { + get channelId() { return this.args.channelId } + get deaf() { return this.args.deaf } + get guildId() { return this.args.guildId } + get mute() { return this.args.mute } + get selfDeaf() { return this.args.selfDeaf } + get selfMute() { return this.args.selfMute } + get selfVideo() { return this.args.selfVideo } + get sessionId() { return this.args.sessionId } + get suppress() { return this.args.suppress } + get userId() { return this.args.userId } +} + +// Doesn't have everything +export class USER_SETTINGS_UPDATE extends DiscordEvent { + get status() { return this.args.status } + get messageDisplayCompact() { return this.args.messageDisplayCompact } + get theme() { return this.args.theme } +} + +export class USER_GUILD_SETTINGS_UPDATE extends DiscordEvent { } +export class ACTIVITY_START extends DiscordEvent {} diff --git a/client/src/structs/socketstructs/guild.js b/client/src/structs/socketstructs/guild.js new file mode 100644 index 00000000..8da5ac50 --- /dev/null +++ b/client/src/structs/socketstructs/guild.js @@ -0,0 +1,83 @@ +/** + * BetterDiscord Guild Event Structs + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + +import DiscordEvent from './discordevent'; + +export class GUILD_CREATE extends DiscordEvent { + get afkChannelId() { return this.args.afkChannelId } + get afkTimeout() { return this.args.afkTimeout } + get applicationId() { return this.args.applicationId } + get defaultMessageNotifications() { return this.args.defaultMessageNotifications } + get emojis() { return this.args.emojis } + get explicitContentFilter() { return this.args.explicitContentFilter } + get features() { return this.args.features } + get icon() { return this.args.icon } + get id() { return this.args.id } + get joinedAt() { return this.args.joinedAt } + get large() { return this.args.large } + get memberCount() { return this.args.memberCount } + get mfaLevel() { return this.args.mfaLevel } + get name() { return this.args.name } + get ownerId() { return this.args.ownerId } + get presences() { return this.args.presences } + get region() { return this.args.region } + get roles() { return this.args.roles } + get splash() { return this.args.splash } + get systemChannelId() { return this.args.systemChannelId } + get unavailable() { return this.args.unavailable } + get verificationLevel() { return this.args.verificationLevel } + get voiceStates() { return this.args.voiceStates } + get channels() { return this.args.channels } + get members() { return this.args.members } +} + +export class GUILD_DELETE extends DiscordEvent { + get id() { return this.args.id } + get unavailable() { return this.args.unavailable } +} + +export class GUILD_SYNC extends DiscordEvent { + get id() { return this.args.id } + get large() { return this.args.large } + get members() { return this.args.members } + get presences() { return this.args.presences } +} + +export class GUILD_MEMBERS_CHUNK extends DiscordEvent {} + +export class GUILD_BAN_ADD extends DiscordEvent {} + +export class GUILD_BAN_REMOVE extends DiscordEvent {} + +export class GUILD_MEMBER_ADD extends DiscordEvent { + get guildId() { return this.args.guildId } + get joinedAt() { return this.args.joinedAt } + get mute() { return this.args.mute } + get deaf() { return this.args.deaf } + get roles() { return this.args.roles } + get user() { return this.args.user } +} + +export class GUILD_MEMBER_UPDATE extends DiscordEvent {} + +export class GUILD_MEMBER_REMOVE extends DiscordEvent { + get guildId() { return this.args.guildId } + get user() { return this.args.user } +} + +export class GUILD_ROLE_CREATE extends DiscordEvent {} + +export class GUILD_ROLE_UPDATE extends DiscordEvent {} + +export class GUILD_ROLE_DELETE extends DiscordEvent {} + +export class GUILD_EMOJIS_UPDATE extends DiscordEvent {} + +export class GUILD_INTEGRATIONS_UPDATE extends DiscordEvent {} diff --git a/client/src/structs/socketstructs/message.js b/client/src/structs/socketstructs/message.js new file mode 100644 index 00000000..fc1c02c4 --- /dev/null +++ b/client/src/structs/socketstructs/message.js @@ -0,0 +1,51 @@ +/** + * BetterDiscord Message Event Structs + * Copyright (c) 2015-present Jiiks/JsSucks - https://github.com/Jiiks / https://github.com/JsSucks + * All rights reserved. + * https://betterdiscord.net + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. +*/ + +import DiscordEvent from './discordevent'; + +export class MESSAGE_UPDATE extends MESSAGE_CREATE {} +export class MESSAGE_CREATE extends DiscordEvent { + get author() { return this.args.author } + get channelId() { return this.args.channelId } + get content() { return this.args.content } + get attachments() { return this.args.attachments } + get editedTimestamp() { return this.args.editedTimestamp } + get embeds() { return this.args.embeds } + get id() { return this.args.id } + get mentionEveryone() { return this.args.mentionEveryone } + get mentionRoles() { return this.args.mentionRoles } + get mentions() { return this.args.mentions } + get nonce() { return this.args.nonce } + get pinned() { return this.args.pinned } + get timestamp() { return this.args.timestamp } + get tts() { return this.args.tts } + get type() { return this.args.type } +} + +export class MESSAGE_DELETE extends DiscordEvent { + get channelId() { return this.args.channelId } + get messageId() { return this.args.messageId } +} + +// TODO +export class MESSAGE_DELETE_BULK extends DiscordEvent {} + +export class MESSAGE_ACK extends DiscordEvent { + get channelId() { return this.args.channelId } + get messageId() { return this.args.messageId } +} + +export class MESSAGE_REACTION_REMOVE extends MESSAGE_REACTION_ADD {} +export class MESSAGE_REACTION_ADD extends DiscordEvent { + get channelId() { return this.args.channelId } + get messageId() { return this.args.messageId } + get userId() { return this.args.userId } + get emoji() { return this.args.emoji } +} diff --git a/common/modules/utils.js b/common/modules/utils.js index 915e44c4..afcaec73 100644 --- a/common/modules/utils.js +++ b/common/modules/utils.js @@ -10,16 +10,18 @@ const path = require('path'), - fs = require('fs'); + fs = require('fs'), + _ = require('lodash'); import { Vendor } from 'modules'; export class Utils { - static overload(fn, cb) { + static overload(fn, cb, p) { const orig = fn; return function (...args) { - orig(...args); - cb(...args); + orig.call(p, ...args); + // cb.apply(...args); + // cb(...args); } } @@ -33,6 +35,17 @@ export class Utils { }); } } + + static toCamelCase(o) { + const camelCased = {}; + _.forEach(o, (value, key) => { + if (_.isPlainObject(value) || _.isArray(value)) { + value = this.toCamelCase(value); + } + camelCased[_.camelCase(key)] = value; + }); + return camelCased; + } } export class FileUtils { diff --git a/package.json b/package.json index 855c6af4..7f1d0164 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "gulp-plumber": "^1.2.0", "gulp-watch": "^5.0.0", "jquery": "^3.2.1", + "lodash": "^4.17.4", "node-sass": "^4.7.2", "pump": "^2.0.0", "sass-loader": "^6.0.6",