Lightcord/modules/discord_desktop_core/core/app/BetterDiscord/index.js

913 lines
38 KiB
JavaScript

const ModuleLoader = require("./loaders/modules")
const { EventEmitter } = require("events")
const Logger = require("./Logger")
const fs = require("fs")
const path = require("path")
const electron = require("electron")
const fetch = require("node-fetch").default
const uuid = require("uuid/v4")
const events = exports.events = new EventEmitter()
const logger = exports.logger = new Logger("LightCord")
let hasInit = false
let tries = 0
exports.init = function(){
if(hasInit == true){
console.warn(new Error("LightCord has already inited."))
return
}
hasInit = true
let readyInterval = setInterval(()=>{
events.emit("debug", `[INIT] try ${tries++} loading LightCord`)
try{
if(!global.webpackJsonp)return
if(!ModuleLoader.get(4))return
clearInterval(readyInterval)
privateInit()
.then(() => {
console.log("Finished loading Lightcord.")
})
}catch(e){
console.error(e)
}
}, 100)
}
let hasPrivateInit = false
async function privateInit(){
if(!hasInit)return
if(hasPrivateInit)return
hasPrivateInit = true
//disabling sentry
ModuleLoader.get(e => e.getCurrentHub)[0].getCurrentHub().getClient().getOptions().enabled = false
// setting react in require cache
try{
window.React = require("react")
}catch(e){
const React = ModuleLoader.get(e => !["Component", "PureComponent", "Children", "createElement", "cloneElement"].map(c => !!e[c]).includes(false))[0]
window.React = React
require.cache["react"] = React
}
try{
window.ReactDOM = require("react-dom")
}catch(e){
const ReactDOM = ModuleLoader.get(e => e.findDOMNode)[0]
window.ReactDOM = ReactDOM
require.cache["react-dom"] = ReactDOM
}
let original = ModuleLoader.get((e) => e.createSound)[0].createSound
ModuleLoader.get((e) => e.createSound)[0].createSound = function(sound){
let isCalling = sound === "call_ringing_beat" || sound === "call_ringing"
if(isCalling){
let returned = original(...arguments)
Object.defineProperty(returned, "name", {
get(){
return window.Lightcord.Settings.callRingingBeat ? "call_ringing_beat" : "call_ringing"
},
set(data){
console.log("Attempting to set call_ringing value. Canceling "+data)
},
configurable: false
})
return returned
}else{
return original(...arguments)
}
}
let constants = ModuleLoader.get(m=>m.API_HOST)[0]
let dispatcher = ModuleLoader.get(m=>m.Dispatcher&&m.default&&m.default.dispatch)[0].default
require("../../../../../BetterDiscordApp/css/main.css")
require("./lightcord.css")
window.$ = window.jQuery = require("./jquery.min.js")
require("./ace.js")
if(!fs.existsSync(BetterDiscordConfig.dataPath))fs.mkdirSync(BetterDiscordConfig.dataPath, {recursive: true})
let pluginPath = path.join(BetterDiscordConfig.dataPath, "plugins")
let themePath = path.join(BetterDiscordConfig.dataPath, "themes")
console.log(`Plugins: ${pluginPath}\nThemes: ${themePath}`)
if(!fs.existsSync(pluginPath)){
fs.mkdirSync(pluginPath, {recursive: true})
/** Downloads Util Plugins So the user don't have to install it manually */
/** ZeresPluginLibrary */
const ZeresPluginLibraryPath = path.join(pluginPath, "0PluginLibrary.plugin.js")
fetch("https://raw.githubusercontent.com/rauenzi/BDPluginLibrary/master/release/0PluginLibrary.plugin.js")
.then(async res => {
if(res.status !== 200)return
const content = await res.buffer()
fs.writeFileSync(ZeresPluginLibraryPath, content)
})
// Should we download 1XenoLib and BDFDB too ?
BetterDiscordConfig.haveInstalledDefault = true // Inform User about what we just did
}
if(!fs.existsSync(themePath)){
fs.mkdirSync(themePath, {recursive: true})
/** Downloads Basic Themes to guide user and showcase features */
/** Discord Dark */
const DiscordDarkPath = path.join(themePath, "DiscordDark.theme.css")
const themeContent = fs.readFileSync(path.join(__dirname, "assets", "DiscordDark.theme.css"), "utf8")
fs.writeFileSync(DiscordDarkPath, themeContent, "utf8")
/** Glasscord Example */
const GlasscordExamplePath = path.join(themePath, "glasscord_example.theme.css")
fetch("https://raw.githubusercontent.com/AryToNeX/Glasscord/master/extras/discord_example.theme.css")
.then(async res => {
if(res.status !== 200)return
const content = await res.buffer()
fs.writeFileSync(GlasscordExamplePath, content)
})
BetterDiscordConfig.haveInstalledDefault = true // Inform User about what we just did
}
// setting Discord Internal Developer Mode for developement and test purposes.
Object.defineProperty(ModuleLoader.get(e => e.default && typeof e.default === "object" && ("isDeveloper" in e.default))[0].default, "isDeveloper", {
get(){return !!window.Lightcord.Settings.devMode},
set(data){return !!window.Lightcord.Settings.devMode}
})
/**
* @type {typeof import("../../../../../DiscordJS").default}
*/
let DiscordJS
try{
DiscordJS = require("../../../../../DiscordJS").default
}catch(err){
console.error(err)
DiscordJS = null
}
const appSettings = electron.remote.getGlobal("appSettings")
let Authorization = appSettings.get("LIGHTCORD_AUTH", false)
let shouldShowPrompt = Authorization === false
if(typeof Authorization !== "string"){
Authorization = null
appSettings.set("LIGHTCORD_AUTH", null)
appSettings.save()
}
window.Lightcord = {
DiscordModules: {
dispatcher,
constants
},
Settings: {
devMode: false,
callRingingBeat: true
},
Api: {
get Authorization(){
return Authorization
},
set Authorization(data){
if(typeof data !== "string" && data !== null)return Authorization
appSettings.set("LIGHTCORD_AUTH", Authorization = data)
appSettings.save()
}
},
BetterDiscord: { // Global BetterDiscord's exported modules
}
}
if(shouldShowPrompt){
let onConn = (ev) => {
console.log(`Showing auth window.`, ev)
shouldShowPrompt = false
dispatcher.unsubscribe(constants.ActionTypes.CONNECTION_OPEN || "CONNECTION_OPEN", onConn)
const options = {
width: 500,
height: 550,
backgroundColor: "#202225",
show: true,
resizable: false,
maximizable: false,
minimizable: false,
frame: false,
center: false,
webPreferences: {
nodeIntegration: false,
preload: path.join(__dirname, "auth", "preload.js"),
webviewTag: true
},
parent: electron.remote.getCurrentWindow()
};
options.x = Math.round(window.screenX + window.innerWidth / 2 - options.width / 2);
options.y = Math.round(window.screenY + window.innerHeight / 2 - options.height / 2);
const authWindow = new electron.remote.BrowserWindow(options)
authWindow.webContents.session.protocol.registerFileProtocol("lightcord", (req, callback) => {
const parsedURL = new URL("http://lightcord.xyz/"+req.url.split("://")[1])
let file
if(req.method !== "GET"){
file = "404.html"
}else{
if(parsedURL.pathname === "/index.html"){
file = "index.html"
}else if(parsedURL.pathname === "/index.css"){
file = "index.css"
}else if(parsedURL.pathname === "/login/callback"){
authWindow.close()
console.log(parsedURL.searchParams)
Authorization = parsedURL.searchParams.get("auth")
authWindow = null
return
}
}
if(!file){
file = "404.html"
}
callback(path.join(__dirname, "auth", file))
}, (err) => {
if(err)console.error(err)
})
electron.remote.getCurrentWindow().webContents.on("devtools-reload-page", () => {
electron.remote.protocol.unregisterProtocol("lightcord")
})
authWindow.on("close", () => {
electron.remote.protocol.unregisterProtocol("lightcord")
})
authWindow.loadURL("lightcord://index.html")
}
dispatcher.subscribe(constants.ActionTypes.CONNECTION_OPEN || "CONNECTION_OPEN", onConn)
}
const BetterDiscord = window.BetterDiscord = window.mainCore = new(require("../../../../../BetterDiscordApp/js/main.js").default)(BetterDiscordConfig)
const Utils = window.Lightcord.BetterDiscord.Utils
// security delete
delete window.Lightcord.BetterDiscord.Utils
delete window.Lightcord.BetterDiscord.Utils
let isBot = false
;(async function(){
const gatewayModule = await ensureExported(e => e.default && e.default.prototype && e.default.prototype._handleDispatch)
if(!gatewayModule)return
let _handleDispatch = gatewayModule.default.prototype._handleDispatch
gatewayModule.default.prototype._handleDispatch = function(data, event, props){
if(event === "READY"){
console.log(...arguments)
isBot = data.user.bot
if(data.user.bot){
logger.log(`Logged in as a bot, spoofing user...`)
data.user.bot = false
data.user.premium = true
data.user.premium_type = 1
data.user.email = data.user.email || uuid()+"@lightcord.xyz" // filler email, not a real one
data.experiments = data.experiments ||[]
data.guild_experiments = data.guild_experiments || [];
data.connected_accounts = data.connected_accounts || [];
data.user_guild_settings = data.user_guild_settings || [];
data.relationships = data.relationships || [];
data.notes = data.notes || {};
data.user_feed_settings = data.user_feed_settings || [];
data.analytics_tokens = data.analytics_tokens || [];
data.analytics_token = data.analytics_token || ""
data.private_channels = data.private_channels || [];
data.read_state = data.read_state || {
entries: [],
partial: false,
version: 19438
}
data.consents = data.consents || {
personalization: false
}
data.tutorial = data.tutorial || null
data.user_settings = Object.assign(data.user_settings || {}, {
afk_timeout: 600,
allow_accessibility_detection: false,
animate_emoji: true,
contact_sync_enabled: false,
convert_emoticons: true,
custom_status: null,
default_guilds_restricted: false,
detect_platform_accounts: false,
developer_mode: true,
disable_games_tab: true,
enable_tts_command: true,
explicit_content_filter: 0,
friend_source_flags: {
all: false,
mutual_friends: false,
mutual_guilds: false
},
gif_auto_play: true,
guild_folders: [],
guild_positions: [],
inline_attachment_media: true,
inline_embed_media: true,
message_display_compact: false,
native_phone_integration_enabled: false,
render_embeds: true,
render_reactions: true,
restricted_guilds: [],
show_current_game: false,
stream_notifications_enabled: false
}, data.user_settings || {})
data.user_guild_settings = data.user_guild_settings || {
entries: [],
version: 0,
partial: false
}
data.friend_suggestion_count = data.friend_suggestion_count || 0
data.presences = data.presences || []
console.log(data)
}else{
logger.log(`Logged in as an user. Skipping`)
}
}
return _handleDispatch.call(this, ...arguments)
}
function cancelPrototype(methodName){
if(gatewayModule.default.prototype[methodName]){
const original = gatewayModule.default.prototype[methodName]
gatewayModule.default.prototype[methodName] = function(){
if(!isBot)return original.call(this, ...arguments)
}
}
}
cancelPrototype("updateGuildSubscriptions")
cancelPrototype("callConnect")
cancelPrototype("lobbyConnect")
cancelPrototype("lobbyDisconnect")
cancelPrototype("lobbyVoiceStatesUpdate")
cancelPrototype("guildStreamCreate")
cancelPrototype("streamWatch")
cancelPrototype("streamPing")
cancelPrototype("streamDelete")
cancelPrototype("streamSetPaused")
const hasUnreadModules = BDModules.get(e => e.default && e.default.hasUnread)
hasUnreadModules.forEach((mod) => {
const original = mod.default.hasUnread
mod.default.hasUnread = function(){
if(isBot)return false
return original.call(this, ...arguments)
}
for (const fName of ['ack']) {
console.log(fName, mod[fName])
if(!mod || !mod[fName])continue
let original = mod[fName]
mod[fName] = function(){
if(!isBot)return original.call(this, ...arguments)
}
}
if(mod.getAckTimestamp){
let getAckTimestamp = mod.getAckTimestamp
mod.getAckTimestamp = function(){
if(!isBot)return getAckTimestamp.call(this, ...arguments)
return NaN
}
}
})
const ackModule = BDModules.get(e => e.ackCategory)[0]
if(ackModule){
for (const fName of ['ack', 'ackCategory', 'localAck', 'ackGuild']) {
console.log(fName, ackModule[fName])
if(!ackModule || !ackModule[fName])continue
let original = ackModule[fName]
ackModule[fName] = function(){
if(!isBot)return original.call(this, ...arguments)
}
}
}
const getTokenModule = BDModules.get(e => e.default && e.default.getToken)[0]
if(getTokenModule){
const getToken = getTokenModule.default.getToken
getTokenModule.default.getToken = function(){
const token = getToken.call(this)
if(!token)return token
if(isBot)return token.startsWith("Bot ") ? token : "Bot " + token
return token
}
}
const relationshipsModule = BDModules.get(e => e.default && e.default.fetchRelationships)[0]
if(relationshipsModule){
const fetchRelationships = relationshipsModule.default.fetchRelationships
relationshipsModule.default.fetchRelationships = function(){
if(!isBot)return fetchRelationships.call(this, ...arguments)
setImmediate(() => {
dispatcher.dispatch({
type: constants.ActionTypes.LOAD_RELATIONSHIPS_SUCCESS,
relationships: []
})
})
}
}
const consentModule = BDModules.get(e => e.fetchConsents)[0]
if(consentModule){
const fetchConsents = consentModule.fetchConsents
consentModule.fetchConsents = function(){
if(!isBot)return fetchConsents.call(this, ...arguments)
setImmediate(()=>{
dispatcher.dispatch({
type: constants.ActionTypes.UPDATE_CONSENTS,
consents: {
personalization: false,
usage_statistics: false
}
})
})
}
const setConsents = consentModule.setConsents
consentModule.setConsents = function(){
if(!isBot)return setConsents.call(this, ...arguments)
return Promise.reject(new Error("Lightcord bot emulation cannot change this setting."))
}
}
const harvestModule = BDModules.get(e => e.getHarvestStatus)[0]
if(harvestModule){
const getHarvestStatus = harvestModule.getHarvestStatus
harvestModule.getHarvestStatus = function(){
if(!isBot)return getHarvestStatus.call(this, ...arguments)
return Promise.resolve({
requestingHarvest: false,
currentHarvestRequest: null
})
}
const requestHarvest = harvestModule.requestHarvest
harvestModule.requestHarvest = function(){
if(!isBot)return requestHarvest.call(this, ...arguments)
return Promise.reject()
}
}
const harvestDisabledModule = BDModules.get(e => e.getSanitizedRestrictedGuilds)[0]
if(harvestDisabledModule){
const harvestDisabled = harvestDisabledModule.harvestDisabled
harvestDisabledModule.harvestDisabled = function(){
if(!isBot)return harvestDisabled.call(this, ...arguments)
}
}
const settingModule = BDModules.get(e => e.default && e.default.updateRemoteSettings)[0]
if(settingModule){
const updateRemoteSettings = settingModule.default.updateRemoteSettings
settingModule.default.updateRemoteSettings = function(){
if(isBot)return Promise.resolve()
return updateRemoteSettings.call(this, ...arguments)
}
}
const oauth2Module = BDModules.get(e => e.default && Object.keys(e.default).length === 2 && e.default.fetch && e.default.delete)[0]
if(oauth2Module){
const fetch = oauth2Module.default.fetch
oauth2Module.default.fetch = function(){
if(!isBot)return fetch.call(this, ...arguments)
setImmediate(()=>{
dispatcher.dispatch({
type: constants.ActionTypes.USER_AUTHORIZED_APPS_UPDATE,
apps: []
})
})
}
const deleteFunc = oauth2Module.delete
oauth2Module.delete = function(){
if(!isBot)return deleteFunc.call(this, ...arguments)
oauth2Module.fetch()
}
}
const paymentModule = BDModules.get(e => e.fetchPaymentSources)[0]
if(paymentModule){
const fetchPaymentSources = paymentModule.fetchPaymentSources
paymentModule.fetchPaymentSources = function(){
if(!isBot)return fetchPaymentSources.call(this, ...arguments)
setImmediate(() => {
dispatcher.dispatch({
type: constants.ActionTypes.BILLING_PAYMENT_SOURCES_FETCH_START
})
setImmediate(() => {
dispatcher.dispatch({
type: constants.ActionTypes.BILLING_PAYMENT_SOURCES_FETCH_SUCCESS,
paymentSources: []
})
})
})
}
const fetchPayments = paymentModule.fetchPayments
paymentModule.fetchPayments = function(){
if(!isBot)return fetchPayments.call(this, ...arguments)
setImmediate(() => {
dispatcher.dispatch({
type: constants.ActionTypes.BILLING_PAYMENTS_FETCH_START
})
setImmediate(() => {
dispatcher.dispatch({
type: constants.ActionTypes.BILLING_PAYMENTS_FETCH_SUCCESS,
payments: []
})
})
})
}
const fetchSubscriptions = paymentModule.fetchSubscriptions
paymentModule.fetchSubscriptions = function(){
if(!isBot)return fetchSubscriptions.call(this, ...arguments)
setImmediate(() => {
dispatcher.dispatch({
type: constants.ActionTypes.BILLING_SUBSCRIPTION_FETCH_START
})
setImmediate(() => {
const subs = [
{
"id": "123456789",
"type": 1,
"created_at": "2020-06-00T00:00:00.000000",
"canceled_at": null,
"current_period_start": "2020-06-00:00:00.000000",
"current_period_end": "2100-06-00:00:00.000000",
"status": 1,
"payment_source_id": null,
"payment_gateway": null,
"payment_gateway_plan_id": "premium_year",
"plan_id": "511651860671627264",
"items": [
{
"id": "123456789",
"plan_id": "511651860671627264",
"quantity": 1
}
],
"currency": "usd"
}
]
resolve({
body: subs
})
dispatcher.dispatch({
type: constants.ActionTypes.BILLING_SUBSCRIPTION_FETCH_SUCCESS,
subscriptions: subs
})
})
})
let resolve
return new Promise((res) => (resolve = res))
}
}
const markServerReadShortcut = BDModules.get(e => e.MARK_SERVER_READ)[0]
if(markServerReadShortcut){
let action = markServerReadShortcut.MARK_SERVER_READ.action
markServerReadShortcut.MARK_SERVER_READ.action = function(){
if(isBot)return
return action.call(this, ...arguments)
}
markServerReadShortcut.default && markServerReadShortcut.default.MARK_SERVER_READ && (markServerReadShortcut.default.MARK_SERVER_READ.action = markServerReadShortcut.MARK_SERVER_READ.action)
}
const applicationStatisticModule = BDModules.get(e => e.fetchActivityStatistics)[0]
if(applicationStatisticModule){
const fetchActivityStatistics = applicationStatisticModule.fetchActivityStatistics
applicationStatisticModule.fetchActivityStatistics = function(){
if(!isBot)return fetchActivityStatistics.call(this, ...arguments)
setImmediate(() => {
dispatcher.dispatch({
type: constants.ActionTypes.USER_ACTIVITY_STATISTICS_FETCH_SUCCESS,
statistics: []
})
})
}
}
const subsInvoiceModule = BDModules.get(e => e.fetchSubscriptionInvoicePreview)[0]
if(subsInvoiceModule){
function adapt(data){
return {
id: data.id,
invoiceItems: data.invoice_items.map(function(e) {
return {
id: e.id,
subscriptionPlanId: e.subscription_plan_id,
subscriptionPlanPrice: e.subscription_plan_price,
amount: e.amount,
quantity: e.quantity,
discounts: e.discounts
}
}),
total: data.total,
subtotal: data.subtotal,
currency: data.currency,
tax: data.tax,
taxInclusive: data.tax_inclusive,
subscriptionPeriodStart: new Date(data.subscription_period_start),
subscriptionPeriodEnd: new Date(data.subscription_period_end)
}
}
const fetchSubscriptionInvoicePreview = subsInvoiceModule.fetchSubscriptionInvoicePreview
subsInvoiceModule.fetchSubscriptionInvoicePreview = function(){
if(!isBot)return fetchSubscriptionInvoicePreview.call(this, ...arguments)
const arg1 = arguments[0]
if(!arg1 || !arg1.subscriptionId || arg1.subscriptionId === "123456789"){
return new Promise((resolve, reject) => {
let data = adapt({
"id": "123456789",
"invoice_items": [{
"id": "123456789",
"amount": 0,
"discounts": [],
"subscription_plan_id": "511651860671627264",
"subscription_plan_price": 0,
"quantity": 1,
"proration": false
}],
"total": 100,
"subtotal": 100,
"currency": "usd",
"tax": 0,
"tax_inclusive": true,
"subscription_period_start": "2020-06-00:00:00.000000",
"subscription_period_end": "2100-06-00:00:00.000000"
})
console.log(data)
resolve(data)
})
}
return fetchSubscriptionInvoicePreview.call(this, ...arguments)
}
const useSubscriptionInvoice = subsInvoiceModule.useSubscriptionInvoice
subsInvoiceModule.useSubscriptionInvoice = function(){
if(!isBot)return useSubscriptionInvoice.call(this, ...arguments)
return useSubscriptionInvoice.call(this, Object.assign(arguments[0], {preventFetch: true}), ...Array.from(arguments).slice(1))
}
}
const subsModule = BDModules.get(e => e.fetchUserPremiumGuildSubscriptionSlots)[0]
if(subsModule){
const fetchUserPremiumGuildSubscriptionSlots = subsModule.fetchUserPremiumGuildSubscriptionSlots
subsModule.fetchUserPremiumGuildSubscriptionSlots = function(){
if(!isBot)return fetchUserPremiumGuildSubscriptionSlots.call(this, ...arguments)
setImmediate(()=>{
dispatcher.dispatch({
type: constants.ActionTypes.USER_PREMIUM_GUILD_SUBSCRIPTION_SLOTS_FETCH_SUCCESS,
userPremiumGuildSubscriptionSlots: []
})
})
}
const fetchPremiumSubscriptionCooldown = subsModule.fetchPremiumSubscriptionCooldown
subsModule.fetchPremiumSubscriptionCooldown = function(){
if(!isBot)return fetchPremiumSubscriptionCooldown.call(this, ...arguments)
return new Promise((resolve, reject) => {
reject(new Error("Lightcord bot emulation cannot use Server Boosts"))
})
}
const fetchPremiumSubscriptions = subsModule.fetchPremiumSubscriptions
subsModule.fetchPremiumSubscriptions = function(){
if(!isBot)return fetchPremiumSubscriptions.call(this, ...arguments)
return new Promise((resolve, reject) => {
reject(new Error("Lightcord bot emulation cannot use Server Boosts"))
})
}
}
const entitlementsModule = BDModules.get(e => e.fetchUserEntitlementsForApplication)[0]
if(entitlementsModule){
const fetchUserEntitlementsForApplication = entitlementsModule.fetchUserEntitlementsForApplication
entitlementsModule.fetchUserEntitlementsForApplication = function(){
if(!isBot)return fetchUserEntitlementsForApplication.call(this, ...arguments)
let resolve
setImmediate(()=>{
dispatcher.dispatch({
type: constants.ActionTypes.ENTITLEMENT_FETCH_APPLICATION_START,
applicationId: arguments[0]
})
setImmediate(()=>{
resolve([])
dispatcher.dispatch({
type: constants.ActionTypes.ENTITLEMENT_FETCH_APPLICATION_SUCCESS,
applicationId: arguments[0],
entitlements: []
})
})
})
return new Promise((res) => (resolve = res))
}
}
const giftModule1 = BDModules.get(e => e.fetchGiftableEntitlements)[0]
if(giftModule1){
const fetchGiftableEntitlements = giftModule1.fetchGiftableEntitlements
giftModule1.fetchGiftableEntitlements = function(){
if(!isBot)return fetchGiftableEntitlements.call(this, ...arguments)
dispatcher.dispatch({
type: constants.ActionTypes.ENTITLEMENTS_GIFTABLE_FETCH
})
setImmediate(() => {
dispatcher.dispatch({
type: constants.ActionTypes.ENTITLEMENTS_GIFTABLE_FETCH_SUCCESS,
entitlements: []
})
})
}
}
const libraryModule = BDModules.get(e => e.fetchLibrary)[0]
if(libraryModule){
const fetchLibrary = libraryModule.fetchLibrary
libraryModule.fetchLibrary = function(){
if(!isBot)return fetchLibrary.call(this, ...arguments)
setImmediate(() => {
dispatcher.dispatch({
type: constants.ActionTypes.LIBRARY_FETCH_SUCCESS,
libraryApplications: []
})
})
}
}
const hypesquadModule = BDModules.get(e => e.default && e.default.joinHypeSquadOnline)[0]
if(hypesquadModule){
const joinHypeSquadOnline = hypesquadModule.default.joinHypeSquadOnline
hypesquadModule.default.joinHypeSquadOnline = function(){
if(!isBot)return joinHypeSquadOnline.call(this, ...arguments)
return Promise.reject(new Error("Lightcord bot emulation cannot join hypesquad."))
}
}
const mentionModule = BDModules.get(e => e.default && e.default.fetchRecentMentions)[0]
if(mentionModule){
const fetchRecentMentions = mentionModule.default.fetchRecentMentions
mentionModule.default.fetchRecentMentions = function(e, t, n, i, s){
if(!isBot)return fetchRecentMentions.call(this, ...arguments)
if(!n)n = null
dispatcher.dirtyDispatch({
type: constants.ActionTypes.LOAD_RECENT_MENTIONS,
guildId: n
})
setImmediate(() => {
dispatcher.dispatch({
type: constants.ActionTypes.LOAD_RECENT_MENTIONS_SUCCESS,
messages: [],
isAfter: null != e,
hasMoreAfter: false
})
})
}
}
const templateModule = BDModules.get(e => e.default && e.default.loadTemplatesForGuild)[0]
if(templateModule){
const loadTemplatesForGuild = templateModule.default.loadTemplatesForGuild
templateModule.default.loadTemplatesForGuild = function(){
if(!isBot)return loadTemplatesForGuild.call(this, ...arguments)
return Promise.reject(new Error("Lightcord bot emulation cannot use Guild Templates"))
}
}
const searchModule = BDModules.get(e => e.default && e.default.prototype && e.default.prototype.retryLater)[0]
if(searchModule){
const fetch = searchModule.default.prototype.fetch
searchModule.default.prototype.fetch = function(e, t, n){
if(!isBot)return fetch.call(this, ...arguments)
n(new Error("Lightcord bot emulation cannot search in guild."))
}
}
})().catch(() => {})
Utils.monkeyPatch(await ensureExported(e => e.default && e.default.displayName == "AuthBox"), "default", {after: (data) => {
const children = Utils.getNestedProp(data.returnValue, "props.children.props.children.props.children")
children.push(React.createElement(require("./tokenLogin").default, {}))
}})
await ensureGuildClasses()
BetterDiscord.init()
events.emit("ready")
if(DiscordJS)DiscordJS.client.emit("ready")
}
require.extensions[".css"] = (m, filename) => {
let content = fs.readFileSync(filename, "binary")
let style = document.createElement("style")
style.id = btoa(filename)
style.innerText = content
document.head.appendChild(style)
m.exports = {
id: style.id,
remove(){
return style.remove()
}
}
return m.exports
}
let zlib = require("zlib")
let tmp = require("tmp")
require.extensions[".jsbr"] = (m, filename) => {
if(!zlib)zlib = require("zlib")
if(!tmp)tmp = require("tmp")
let tmpFile = tmp.fileSync()
fs.writeFileSync(tmpFile.name+".js", zlib.brotliDecompressSync(fs.readFileSync(filename)))
return require.extensions[".js"](m, tmpFile.name+".js")
}
const LightcordBDFolder = path.join(electron.remote.app.getPath("appData"), "Lightcord_BD")
const BetterDiscordConfig = window.BetterDiscordConfig = {
"branch": "lightcord",
dataPath: LightcordBDFolder+"/",
os: process.platform,
latestVersion: "0.3.4",
version: "0.3.4"
}
function ensureGuildClasses(){
return new Promise((resolve) => {
let classs = getGuildClasses()
if(classs && classs.wrapper)return resolve()
let intergay = setInterval(() => {
classs = getGuildClasses()
if(classs && classs.wrapper){
clearInterval(intergay)
resolve()
return
}
}, 200);
})
}
function ensureExported(filter){
return new Promise((resolve) => {
let mod = ModuleLoader.get(filter)[0]
if(mod)return resolve(mod)
let intergay = setInterval(() => {
mod = ModuleLoader.get(filter)[0]
if(mod){
clearInterval(intergay)
resolve(mod)
return
}
}, 100);
})
}
function getGuildClasses() {
const guildsWrapper = ModuleLoader.get(e => e.wrapper && e.unreadMentionsBar)[0];
const guilds = ModuleLoader.get(e => e.guildsError && e.selected)[0]
const pill = ModuleLoader.get(e => e.blobContainer)[0]
return Object.assign({}, guildsWrapper, guilds, pill);
}
const originalResolve = path.resolve
const originalJoin = path.join
const BetterDiscordFolder = function() {
if (process.env.injDir) return path.resolve(process.env.injDir);
switch (process.platform) {
case "win32":
return path.resolve(process.env.appdata, "BetterDiscord/");
case "darwin":
return path.resolve(process.env.HOME, "Library/Preferences/", "BetterDiscord/");
default:
return path.resolve(process.env.XDG_CONFIG_HOME ? process.env.XDG_CONFIG_HOME : process.env.HOME + "/.config", "BetterDiscord/");
}
}()
path.resolve = (...args) => { // Patching BetterDiscord folder by Lightcord's BetterDiscord folder
let resp = originalResolve.call(path, ...args)
if(resp.startsWith(BetterDiscordFolder))resp = resp.replace(BetterDiscordFolder, LightcordBDFolder)
return resp
}
path.join = (...args) => { // Patching BetterDiscord folder by Lightcord's BetterDiscord folder
let resp = originalJoin.call(path, ...args)
if(resp.startsWith(BetterDiscordFolder))resp = resp.replace(BetterDiscordFolder, LightcordBDFolder)
return resp
}
path.originalResolve = originalResolve
window.ohgodohfuck = function(){
let style=document.createElement("style");style.innerHTML=`html:after{content:"";position:absolute;top:0;left:0 ;width:100vw;height:100vh;background-image:url("https://media.giphy.com/media/l378vg4Pm9LGnmD6M/giphy.gif");background-size:cover;background-position:center;background-color:transparent !important;opacity:0.9;mix-blend-mode:hue;z-index:999999999999;pointer-events:none}@keyframes ohgodohfuck{from{transform:rotateZ(0deg)}to{transform:rotateZ(360deg)}}#app-mount{animation:ohgodohfuck 5s infinite alternate}`;document.body.append(style);setTimeout(()=>document.body.removeChild(style),5000);
}