mirror of
https://github.com/Lightcord/Lightcord.git
synced 2025-04-12 00:55:40 +02:00
Modifying LightcordApi
Adding category in settings for lightcordapi making module alias Fixing a little bit the minimal mode
This commit is contained in:
parent
d3494666a2
commit
22ff405d40
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -6,6 +6,7 @@ export const minimumDiscordVersion = "0.0.306";
|
||||
export const currentDiscordVersion = (window.DiscordNative && window.DiscordNative.remoteApp && window.DiscordNative.remoteApp.getVersion && window.DiscordNative.remoteApp.getVersion()) || "0.0.306";
|
||||
export const minSupportedVersion = "0.3.0";
|
||||
export const bbdVersion = "0.3.4";
|
||||
/*
|
||||
export const LCChanelog = {
|
||||
description: "Lightcord's changelog",
|
||||
changes: [
|
||||
@ -36,7 +37,7 @@ export const LCChanelog = {
|
||||
const supportLink = Anchor ? BDV2.React.createElement(Anchor, {onClick: joinSupportServer}, "Join our Discord Server.") : BDV2.React.createElement("a", {className: `${AnchorClasses.anchor} ${AnchorClasses.anchorUnderlineOnHover}`, onClick: joinSupportServer}, "Join our Discord Server.");
|
||||
return BDV2.React.createElement(TextElement, {size: TextElement.Sizes.SMALL, color: TextElement.Colors.STANDARD}, "Need support? ", supportLink);
|
||||
})()
|
||||
}
|
||||
}*/
|
||||
export const bbdChangelog = {
|
||||
description: "BBD's changelog.",
|
||||
changes: [
|
||||
@ -91,7 +92,7 @@ export const settings = {
|
||||
"Disable BetterDiscord": {id: "bd-disable", info: "Disable Betterdiscord (plugins, themes, etc) (Not implemented).", implemented: false, hidden: false, cat: "lightcord", category: "Lightcord"},
|
||||
"Blur Personal Information": {id: "lightcord-6", info: "Blur sensitive informations like email, payment infos and more.", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord"},
|
||||
"Calling Ring Beat": {id: "lightcord-2", info: "Enable Discord's special calling beat.", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord"},
|
||||
"Developer Options": {id: "lightcord-1", info: "Enable Discord's & Lightcord's Internal Developer Options. This allow the \"Experiments\" tab, the \"Developer Options\" tab and the \"Api Components\" tab.", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord"},
|
||||
"Developer Options": {id: "lightcord-1", info: "Enable Discord's & Lightcord's Internal Developer Options. This allow the \"Experiments\" tab, the \"Developer Options\" tab and the \"Lightcord Api\" section.", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord"},
|
||||
"Ad Block": {id: "lightcord-4", info: "Block any BOT that dms you with an invite link. Even in an embed.", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord"},
|
||||
"Enable Lightcord Servers": {id: "lightcord-5", info: "Enable Lightcord's servers. Disabling this will disable custom badges.", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord"},
|
||||
"Disable typing": {id: "lightcord-7", info: "Don't let other see you're typing.", implemented: true, hidden: false, cat: "lightcord", category: "Lightcord"},
|
||||
|
@ -54,8 +54,9 @@ window.BdApi = BdApi;
|
||||
import Core from "./modules/core";
|
||||
deprecateGlobal("mainCore", Core);
|
||||
export default class CoreWrapper {
|
||||
constructor(bdConfig) {
|
||||
constructor(bdConfig, methods) {
|
||||
Core.setConfig(bdConfig);
|
||||
Core.setMethods(methods);
|
||||
}
|
||||
|
||||
init() {
|
||||
|
@ -25,10 +25,16 @@ function Core() {
|
||||
// this.init();
|
||||
}
|
||||
|
||||
let methods
|
||||
|
||||
Core.prototype.setConfig = function(config) {
|
||||
Object.assign(bdConfig, config);
|
||||
};
|
||||
|
||||
Core.prototype.setMethods = function(m) {
|
||||
methods = m
|
||||
};
|
||||
|
||||
Core.prototype.init = async function() {
|
||||
if (!Array.prototype.flat) {
|
||||
Utils.alert("Not Supported", "BetterDiscord v" + bbdVersion + " does not support this old version (" + currentDiscordVersion + ") of Discord. Please update your Discord installation before proceeding.");
|
||||
|
@ -47,6 +47,8 @@ class BDSidebarHeader extends React.PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
let isClearingCache = false
|
||||
|
||||
export default new class V2_SettingsPanel {
|
||||
|
||||
constructor() {
|
||||
@ -331,7 +333,7 @@ export default new class V2_SettingsPanel {
|
||||
return BDV2.react.createElement(SectionedSettingsPanel, {key: "cspanel", onChange: this.onChange, sections: this.coreSettings})
|
||||
}
|
||||
|
||||
lightcordComponent(sidebar) {
|
||||
lightcordComponent(sidebar, forceUpdate) {
|
||||
let appSettings = remote.getGlobal("appSettings")
|
||||
return [
|
||||
this.lightcordSettings.map((section, i) => {
|
||||
@ -379,7 +381,38 @@ export default new class V2_SettingsPanel {
|
||||
remote.app.quit()
|
||||
},
|
||||
wrapper: true
|
||||
}, "Relaunch without BetterDiscord")
|
||||
}, "Relaunch without BetterDiscord"),
|
||||
React.createElement(Lightcord.Api.Components.inputs.Button, {
|
||||
color: "yellow",
|
||||
look: "ghost",
|
||||
size: "medium",
|
||||
hoverColor: "red",
|
||||
onClick: () => {
|
||||
if(isClearingCache)return
|
||||
isClearingCache = true
|
||||
Utils.showToast("Clearing cache...", {
|
||||
type: "info"
|
||||
})
|
||||
forceUpdate()
|
||||
remote.getCurrentWebContents().session.clearCache()
|
||||
.then(() => {
|
||||
Utils.showToast("Cache is cleared !", {
|
||||
type: "success"
|
||||
})
|
||||
isClearingCache = false
|
||||
forceUpdate()
|
||||
}).catch(err => {
|
||||
console.error(err)
|
||||
Utils.showToast("An error occured. Check console for more informations.", {
|
||||
type: "error"
|
||||
})
|
||||
isClearingCache = false
|
||||
forceUpdate()
|
||||
})
|
||||
},
|
||||
wrapper: true,
|
||||
disabled: isClearingCache
|
||||
}, "Clear cache")
|
||||
]
|
||||
}
|
||||
|
||||
@ -444,7 +477,7 @@ export default new class V2_SettingsPanel {
|
||||
function makeComponent(children){
|
||||
class SettingComponent extends React.Component {
|
||||
render(){
|
||||
return children(sidebar)
|
||||
return children(sidebar, () => this.forceUpdate())
|
||||
}
|
||||
}
|
||||
let sidebar
|
||||
|
@ -41,10 +41,25 @@ export default class V2_SettingsPanel_Sidebar {
|
||||
id: "accountinfo"
|
||||
}
|
||||
]
|
||||
if(window.Lightcord.Settings.devMode)items.push({
|
||||
text: "Api Components Preview",
|
||||
id: "lcapipreview"
|
||||
})
|
||||
return items
|
||||
}
|
||||
|
||||
get LCDevItems(){
|
||||
let items = []
|
||||
if(!window.Lightcord.Settings.devMode)return items
|
||||
items.push(...[
|
||||
{
|
||||
section: "DIVIDER"
|
||||
},
|
||||
{
|
||||
section: "HEADER",
|
||||
label: "Lightcord Api"
|
||||
},
|
||||
{
|
||||
text: "Components Preview",
|
||||
id: "lcapipreview"
|
||||
}
|
||||
])
|
||||
return items
|
||||
}
|
||||
|
||||
@ -61,6 +76,14 @@ export default class V2_SettingsPanel_Sidebar {
|
||||
element: this.getComponent(e.id, sidebar)
|
||||
}
|
||||
}),
|
||||
...this.LCDevItems.map(e => {
|
||||
if(e.section)return e
|
||||
return {
|
||||
section: e.id,
|
||||
label: e.text,
|
||||
element: this.getComponent(e.id, sidebar)
|
||||
}
|
||||
}),
|
||||
{
|
||||
section: "DIVIDER"
|
||||
},
|
||||
|
File diff suppressed because one or more lines are too long
10
LightcordApi/package-lock.json
generated
10
LightcordApi/package-lock.json
generated
@ -1101,6 +1101,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/bandagedbd__bdapi": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/bandagedbd__bdapi/-/bandagedbd__bdapi-0.2.2.tgz",
|
||||
"integrity": "sha512-igNQMnEticrue5LYXkKZGP6pGoN/mQTzUDJ2Jjr5T7wghgmkePTyk8r09N9Dm7fTjHH1aEmQmSSRv9s4Ce35bQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*"
|
||||
}
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz",
|
||||
|
@ -18,6 +18,7 @@
|
||||
"@babel/preset-env": "^7.3.4",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"@babel/register": "^7.0.0",
|
||||
"@types/bandagedbd__bdapi": "^0.2.2",
|
||||
"@types/react": "^16.9.36",
|
||||
"@types/react-dom": "^16.9.8",
|
||||
"@types/uuid": "^8.0.0",
|
||||
|
@ -1,39 +1,35 @@
|
||||
/**
|
||||
* @name LightcordApiExemple
|
||||
*/
|
||||
|
||||
module.exports = class LightcordApiExemple {
|
||||
getName() {return "LightcordApiExemple";} // Name of your plugin to show on the plugins page
|
||||
getDescription() {return "Describe the basic functions. Maybe a support server link.";} // Description to show on the plugins page
|
||||
getVersion() {return "0.0.1";} // Current version. I recommend following semantic versioning <http://semver.org/> (e.g. 0.0.1)
|
||||
getAuthor() {return "Not Thomiz";} // Your name
|
||||
|
||||
load() {} // Called when the plugin is loaded in to memory
|
||||
|
||||
start() {
|
||||
if(!("Lightcord" in window) || !("Api" in window.Lightcord)){
|
||||
bdApi.showToast("This plugin only works in Lightcord.")
|
||||
return
|
||||
}
|
||||
|
||||
console.log(`LightcordAPI is availaible !`)
|
||||
} // Called when the plugin is activated (including after reloads)
|
||||
stop() {} // Called when the plugin is deactivated
|
||||
|
||||
observer(changes) {} // Observer for the `document`. Better documentation than I can provide is found here: <https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver>
|
||||
|
||||
getSettingsPanel(){
|
||||
let settings = [
|
||||
{
|
||||
component: "inputs.Button",
|
||||
props: {
|
||||
children: [
|
||||
"sltsv"
|
||||
],
|
||||
color: "red"
|
||||
}
|
||||
}
|
||||
]
|
||||
return windows.Lightcord.Api.Utils.PluginUtils.renderSettings(settings)
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @name LightcordApiExemple
|
||||
*/
|
||||
|
||||
module.exports = class LightcordApiExemple {
|
||||
getName() {return "LightcordApiExemple";} // Name of your plugin to show on the plugins page
|
||||
getDescription() {return "Describe the basic functions. Maybe a support server link.";} // Description to show on the plugins page
|
||||
getVersion() {return "0.0.1";} // Current version. I recommend following semantic versioning <http://semver.org/> (e.g. 0.0.1)
|
||||
getAuthor() {return "Not Thomiz";} // Your name
|
||||
|
||||
load() {} // Called when the plugin is loaded in to memory
|
||||
|
||||
start() {
|
||||
if(!("Lightcord" in window) || !("Api" in window.Lightcord)){
|
||||
bdApi.showToast("This plugin only works in Lightcord.")
|
||||
return
|
||||
}
|
||||
|
||||
console.log(`LightcordAPI is availaible !`)
|
||||
} // Called when the plugin is activated (including after reloads)
|
||||
stop() {} // Called when the plugin is deactivated
|
||||
|
||||
observer(changes) {} // Observer for the `document`. Better documentation than I can provide is found here: <https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver>
|
||||
|
||||
getSettingsPanel(){
|
||||
const Markdown = BDModules.get(e => e.default && e.default.displayName === "Markdown")[0].default
|
||||
let settings = Markdown.prototype.render.call({
|
||||
props: Object.assign({
|
||||
className: "",
|
||||
children: "> warn\n> sltsv"
|
||||
}, Markdown.defaultProps)
|
||||
})
|
||||
return window.Lightcord.Api.Utils.ReactToHTML(settings)
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,11 @@ type ColorPickerProps = {
|
||||
|
||||
let ColorPickerModules
|
||||
let isFetching = null
|
||||
|
||||
/**
|
||||
* This componennt needs to be loaded. As a result, you may experience 100-300ms loading the first time.
|
||||
* Render will return `null` before loaded.
|
||||
*/
|
||||
export default class ColorPicker extends React.PureComponent<ColorPickerProps, {value?:string,lastColor:any}> {
|
||||
constructor(props:ColorPickerProps){
|
||||
super(props)
|
||||
@ -50,6 +55,13 @@ export default class ColorPicker extends React.PureComponent<ColorPickerProps, {
|
||||
this.onChange = this.onChange.bind(this)
|
||||
}
|
||||
|
||||
/** Preload the component. */
|
||||
static preload(){
|
||||
if(ColorPicker.prototype.modules[0])return
|
||||
if(isFetching)return
|
||||
new ColorPicker({}).render()
|
||||
}
|
||||
|
||||
onChange(val){
|
||||
this.props.onChange(val)
|
||||
this.setState({
|
||||
@ -79,7 +91,10 @@ export default class ColorPicker extends React.PureComponent<ColorPickerProps, {
|
||||
] = this.modules
|
||||
|
||||
if(!ColorPickerComponent){
|
||||
if(isFetching)isFetching.then(e => this.forceUpdate()) // support for multiple color picker
|
||||
if(isFetching){ // support for multiple color picker
|
||||
isFetching.then(() => this.forceUpdate())
|
||||
return null
|
||||
}
|
||||
ColorPickerModules = null
|
||||
let resolve
|
||||
isFetching = new Promise(res => (resolve = res))
|
||||
@ -160,7 +175,8 @@ export default class ColorPicker extends React.PureComponent<ColorPickerProps, {
|
||||
}
|
||||
|
||||
static help = {
|
||||
info: "To convert hex colors to decimal, you can do `Lightcord.Api.Utils.HexColorToDecimal('#yourcolor')` and go back with `Lightcord.Api.Utils.DecimalColorToHex(7506394)`"
|
||||
info: "To convert hex colors to decimal, you can do `Lightcord.Api.Utils.HexColorToDecimal('#yourcolor')` and go back with `Lightcord.Api.Utils.DecimalColorToHex(7506394)`",
|
||||
warn: "The component may not appear instantly. The component need to be loaded, so you could experience 50-300ms loading time depending on your internet connection."
|
||||
}
|
||||
}
|
||||
let AllPreviews
|
51
LightcordApi/src/components/private/Notice.tsx
Normal file
51
LightcordApi/src/components/private/Notice.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
import WebpackLoader from "../../modules/WebpackLoader"
|
||||
import { notice, notices, events } from "./Notices"
|
||||
import NOOP from "../../modules/noop"
|
||||
|
||||
let NoticeModules
|
||||
export const defaultNotice:notice = {
|
||||
text: "",
|
||||
id: "unknown id",
|
||||
onClick: NOOP,
|
||||
buttonText: null,
|
||||
type: "default"
|
||||
}
|
||||
export default class Notice extends React.Component<notice> {
|
||||
static displayName = "LightcordNotice"
|
||||
static defaultProps:notice = defaultNotice
|
||||
|
||||
get modules(){
|
||||
return NoticeModules || (NoticeModules = [
|
||||
WebpackLoader.find(e => e.noticeInfo)
|
||||
])
|
||||
}
|
||||
|
||||
render(){
|
||||
const [
|
||||
noticeClasses
|
||||
] = this.modules
|
||||
|
||||
const className = noticeClasses["notice"+this.props.type.slice(0, 1).toUpperCase()+this.props.type.slice(1)]
|
||||
|
||||
if(!className){
|
||||
notices.pop()
|
||||
setImmediate(() => {
|
||||
events.emit("noticeUpdate")
|
||||
})
|
||||
return null
|
||||
}
|
||||
const button = this.props.buttonText ? <button className={noticeClasses.button} onClick={() => {
|
||||
notices.pop()
|
||||
this.props.onClick()
|
||||
events.emit("noticeUpdate")
|
||||
}}>{this.props.buttonText}</button> : null
|
||||
return <div className={className}>
|
||||
<div className={noticeClasses.dismiss} role="button" tabIndex={0} onClick={() => {
|
||||
notices.pop()
|
||||
events.emit("noticeUpdate")
|
||||
}} />
|
||||
{this.props.text}
|
||||
{button}
|
||||
</div>
|
||||
}
|
||||
}
|
50
LightcordApi/src/components/private/Notices.tsx
Normal file
50
LightcordApi/src/components/private/Notices.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import Notice from "./Notice"
|
||||
import uuid from "../../modules/uuid"
|
||||
import { EventEmitter } from "events"
|
||||
|
||||
export const events = new EventEmitter()
|
||||
|
||||
export default class Notices extends React.Component<{container: any}> {
|
||||
static displayName = "LightcordNotices"
|
||||
static defaultProps = {}
|
||||
constructor(props: Readonly<{ container: any }>){
|
||||
super(props)
|
||||
|
||||
this.noticeHandler = this.noticeHandler.bind(this)
|
||||
}
|
||||
|
||||
noticeHandler(){
|
||||
this.forceUpdate()
|
||||
}
|
||||
|
||||
componentWillMount(){
|
||||
events.on("noticeUpdate", this.noticeHandler)
|
||||
}
|
||||
|
||||
componentWillUnmount(){
|
||||
events.off("noticeUpdate", this.noticeHandler)
|
||||
}
|
||||
|
||||
render(){
|
||||
if(!this.hasNotice)return null
|
||||
const notice = notices[0]
|
||||
return <Notice {...notice}></Notice>
|
||||
}
|
||||
|
||||
get hasNotice(){
|
||||
return notices.length > 0
|
||||
}
|
||||
}
|
||||
|
||||
export const notices:notice[] = []
|
||||
|
||||
export type noticeWithoutID = {
|
||||
text: string,
|
||||
buttonText?: string,
|
||||
onClick?: () => void,
|
||||
type: "default"|"info"|"success"|"danger"|"streamerMode"|"download"|"notification"|"premium"|"richPresence"|"premiumTier1"|"premiumTier2"|"facebook"|"brand"|"survey"|"spotify"
|
||||
}
|
||||
|
||||
export type notice = {
|
||||
id: string
|
||||
} & noticeWithoutID
|
@ -1,65 +1,69 @@
|
||||
import WebpackLoader from "./modules/WebpackLoader"
|
||||
import Components from "./components/components"
|
||||
import uuid from "./modules/uuid"
|
||||
import Utils from "./modules/Utils"
|
||||
|
||||
const LightcordApi = {
|
||||
WebpackLoader: WebpackLoader,
|
||||
Components: Components,
|
||||
uuid: uuid,
|
||||
Utils: Utils
|
||||
}
|
||||
|
||||
declare global {
|
||||
var React:typeof import("react")
|
||||
interface Window {
|
||||
Lightcord: LightcordGlobal,
|
||||
BDModules: {
|
||||
modules:any[],
|
||||
get(filter:(mod:any)=>boolean, modules?:any[]):any[],
|
||||
get(id:number, modules?:any[]):any,
|
||||
get(ids: [number|((mod:any)=>boolean)], modules?:any[]):any
|
||||
}
|
||||
}
|
||||
var Lightcord:LightcordGlobal
|
||||
}
|
||||
|
||||
export default LightcordApi
|
||||
|
||||
Object.assign(window.Lightcord.Api, LightcordApi)
|
||||
|
||||
/**
|
||||
* The main Lightcord exports. Can be accessed with `window.Lightcord`
|
||||
*/
|
||||
export interface LightcordGlobal {
|
||||
DiscordModules: {
|
||||
/**
|
||||
* Internal Discord's dispatcher - can be used to subscribe to gateway events / client events.
|
||||
*/
|
||||
dispatcher: import("./types/DiscordDispatcherTypes").default,
|
||||
constants: import("./types/DiscordConstantsTypes").default
|
||||
},
|
||||
Settings: {
|
||||
devMode: boolean,
|
||||
callRingingBeat: boolean
|
||||
},
|
||||
Api: LightcordApiGlobal
|
||||
}
|
||||
|
||||
/**
|
||||
* The main Api. Can be accessed with `window.Lightcord.Api`
|
||||
*/
|
||||
type LightcordApiGlobal = lightcordApiMainExports & typeof LightcordApi
|
||||
|
||||
type lightcordApiMainExports = {
|
||||
/**
|
||||
* Waits until the first module that match the filter gets exported
|
||||
* @param filter The filter that specifies the module to match.
|
||||
*/
|
||||
ensureExported(filter: (mod:any) => boolean):Promise<any>,
|
||||
/**
|
||||
* Recreate the object without the `__proto__` and `prototype` properties - usefull for better formatting in console.
|
||||
* @param obj The object to recreate
|
||||
*/
|
||||
cloneNullProto<Obj = any>(obj:Obj):Obj
|
||||
import WebpackLoader from "./modules/WebpackLoader"
|
||||
import Components from "./components/components"
|
||||
import uuid from "./modules/uuid"
|
||||
import Utils from "./modules/Utils"
|
||||
import DiscordTools from "./modules/DiscordTools"
|
||||
import * as patchers from "./modules/patchers"
|
||||
patchers.patch()
|
||||
|
||||
const LightcordApi = {
|
||||
WebpackLoader: WebpackLoader,
|
||||
Components: Components,
|
||||
uuid: uuid,
|
||||
Utils: Utils,
|
||||
DiscordTools: DiscordTools
|
||||
}
|
||||
|
||||
declare global {
|
||||
var React:typeof import("react")
|
||||
interface Window {
|
||||
Lightcord: LightcordGlobal,
|
||||
BDModules: {
|
||||
modules:any[],
|
||||
get(filter:(mod:any)=>boolean, modules?:any[]):any[],
|
||||
get(id:number, modules?:any[]):any,
|
||||
get(ids: [number|((mod:any)=>boolean)], modules?:any[]):any
|
||||
}
|
||||
}
|
||||
var Lightcord:LightcordGlobal
|
||||
}
|
||||
|
||||
export default LightcordApi
|
||||
|
||||
Object.assign(window.Lightcord.Api, LightcordApi)
|
||||
|
||||
/**
|
||||
* The main Lightcord exports. Can be accessed with `window.Lightcord`
|
||||
*/
|
||||
export interface LightcordGlobal {
|
||||
DiscordModules: {
|
||||
/**
|
||||
* Internal Discord's dispatcher - can be used to subscribe to gateway events / client events.
|
||||
*/
|
||||
dispatcher: import("./types/DiscordDispatcherTypes").default,
|
||||
constants: import("./types/DiscordConstantsTypes").default
|
||||
},
|
||||
Settings: {
|
||||
devMode: boolean,
|
||||
callRingingBeat: boolean
|
||||
},
|
||||
Api: LightcordApiGlobal
|
||||
}
|
||||
|
||||
/**
|
||||
* The main Api. Can be accessed with `window.Lightcord.Api`
|
||||
*/
|
||||
type LightcordApiGlobal = lightcordApiMainExports & typeof LightcordApi
|
||||
|
||||
type lightcordApiMainExports = {
|
||||
/**
|
||||
* Waits until the first module that match the filter gets exported
|
||||
* @param filter The filter that specifies the module to match.
|
||||
*/
|
||||
ensureExported(filter: (mod:any) => boolean):Promise<any>,
|
||||
/**
|
||||
* Recreate the object without the `__proto__` and `prototype` properties - usefull for better formatting in console.
|
||||
* @param obj The object to recreate
|
||||
*/
|
||||
cloneNullProto<Obj = any>(obj:Obj):Obj
|
||||
}
|
163
LightcordApi/src/modules/DiscordTools.ts
Normal file
163
LightcordApi/src/modules/DiscordTools.ts
Normal file
@ -0,0 +1,163 @@
|
||||
import { notices, noticeWithoutID, notice, events as noticeEvents } from "../components/private/Notices";
|
||||
import Utils from "./Utils";
|
||||
import uuid from "./uuid";
|
||||
import cloneNullProto from "./cloneNullProto";
|
||||
import { EventEmitter } from "events";
|
||||
import { defaultNotice } from "../components/private/Notice";
|
||||
import excludeProperties from "./excludeProperties";
|
||||
import NOOP from "./noop";
|
||||
import WebpackLoader, { WebpackLoaderError } from "./WebpackLoader";
|
||||
|
||||
let soundModule
|
||||
export default new class DiscordTools {
|
||||
showNotice(data:NoticeData):Notice{
|
||||
if(typeof data !== "object" || typeof data.text !== "string")throw new Error(`This notice is not valid. Given: ${Utils.formatJSObject(data)}`)
|
||||
let newData = cloneNullProto(Object.assign({}, defaultNotice, data)) as notice
|
||||
newData.id = uuid()
|
||||
notices.push(newData)
|
||||
noticeEvents.emit("noticeUpdate")
|
||||
const notice = new Notice(newData)
|
||||
return notice
|
||||
}
|
||||
|
||||
get notices():Notice[]{
|
||||
return notices.map(data => new Notice(data))
|
||||
}
|
||||
|
||||
/**
|
||||
* Quickly send notification (Even when no focused.)
|
||||
* @param data The notification. Be sure to include all properties except functions cause they're optional.
|
||||
* Notifications have a timeout of 3-5 seconds.
|
||||
* They look like this: https://i.imgur.com/jzuxKKu.png
|
||||
*/
|
||||
showNotification(data:NotificationData):Notification{
|
||||
const notification = new window.Notification(data.title, excludeProperties(data, [
|
||||
"title",
|
||||
"onClick",
|
||||
"onClose",
|
||||
"onShow"
|
||||
]))
|
||||
notification.onclick = data.onClick || NOOP
|
||||
notification.onshow = data.onShow || NOOP
|
||||
notification.onclose = data.onClose || NOOP
|
||||
return notification
|
||||
}
|
||||
|
||||
playSound(sound:Sound){
|
||||
soundModule = soundModule || WebpackLoader.findByUniqueProperties(["createSound"])
|
||||
if(!soundModule)throw new WebpackLoaderError("Couldn't find soundModule here.")
|
||||
const created = soundModule.createSound(sound)
|
||||
created.play()
|
||||
return created
|
||||
}
|
||||
}
|
||||
|
||||
export type Sound = "call_calling"|"call_ringing"|"call_ringing_beat"|"ddr-down"|"ddr-left"|"ddr-right"|"ddr-up"|"deafen"|"discodo"|"disconnect"|"human_man"|"mention1"|"mention2"|"mention3"|"message1"|"message2"|"message3"|"mute"|"overlayunlock"|"ptt_start"|"ptt_stop"|"reconnect"|"robot_man"|"stream_ended"|"stream_started"|"stream_user_joined"|"stream_user_left"|"undeafen"|"unmute"|"user_join"|"user_leave"|"user_moved"
|
||||
|
||||
export type NotificationData = {
|
||||
title: string,
|
||||
body: string,
|
||||
icon: string,
|
||||
onShow?: () => void,
|
||||
onClick?: () => void,
|
||||
onClose?: () => void
|
||||
}
|
||||
|
||||
export type NoticeData = noticeWithoutID
|
||||
|
||||
const EventHandler = function(){
|
||||
if(this.removed !== this.state.removed){
|
||||
if(this.removed){
|
||||
this.emit("removed")
|
||||
}
|
||||
}
|
||||
if(this.showing !== this.state.showing){
|
||||
if(this.showing){
|
||||
this.emit("showing", true)
|
||||
}else{
|
||||
this.emit("showing", false)
|
||||
}
|
||||
}
|
||||
if(this.index !== this.state.index){
|
||||
this.emit("index", this.index)
|
||||
}
|
||||
}
|
||||
|
||||
/** A notice interface for modifying it and subscribing to events. */
|
||||
export class Notice extends EventEmitter {
|
||||
constructor(data){
|
||||
super()
|
||||
this.data = data
|
||||
|
||||
this.state = {
|
||||
removed: this.removed,
|
||||
showing: this.showing,
|
||||
index: this.index
|
||||
}
|
||||
|
||||
let eventFunc = EventHandler.bind(this)
|
||||
noticeEvents.on("noticeUpdate", eventFunc)
|
||||
this.on("removed", () => {
|
||||
noticeEvents.off("noticeUpdate", eventFunc)
|
||||
})
|
||||
}
|
||||
|
||||
state:{
|
||||
removed:boolean,
|
||||
showing:boolean,
|
||||
index:number
|
||||
}
|
||||
|
||||
get removed():boolean{
|
||||
return !notices.find(e => e.id === this.id)
|
||||
}
|
||||
get showing():boolean{
|
||||
return this.index === 0
|
||||
}
|
||||
|
||||
get index():number{
|
||||
return notices.findIndex(e => e.id === this.id)
|
||||
}
|
||||
get id(){
|
||||
return this.data.id
|
||||
}
|
||||
|
||||
get text(){
|
||||
return this.data.text
|
||||
}
|
||||
set text(text){
|
||||
this.data.text = text
|
||||
noticeEvents.emit("noticeUpdate")
|
||||
}
|
||||
|
||||
get type(){
|
||||
return this.data.type
|
||||
}
|
||||
set type(type){
|
||||
this.data.type = type
|
||||
noticeEvents.emit("noticeUpdate")
|
||||
}
|
||||
|
||||
get buttonText(){
|
||||
return this.data.buttonText
|
||||
}
|
||||
set buttonText(buttonText:string){
|
||||
this.data.buttonText = buttonText
|
||||
noticeEvents.emit("noticeUpdate")
|
||||
}
|
||||
|
||||
get onClick(){
|
||||
return this.data.onClick
|
||||
}
|
||||
set onClick(onClick){
|
||||
this.data.onClick = onClick
|
||||
noticeEvents.emit("noticeUpdate")
|
||||
}
|
||||
|
||||
remove(){
|
||||
if(this.removed)return
|
||||
notices.splice(this.index, 1)
|
||||
noticeEvents.emit("noticeUpdate")
|
||||
}
|
||||
data:notice
|
||||
}
|
@ -31,4 +31,80 @@ export default new class Utils {
|
||||
if(isNaN(res))throw new Error(`Invalid color: ${color}`)
|
||||
return res
|
||||
}
|
||||
|
||||
removeDa(className:string):string{
|
||||
if(!className)return className
|
||||
return className.split(" ").filter(e => !e.startsWith("da-")).join(" ")
|
||||
}
|
||||
|
||||
FindReact(dom:Element, traverseUp:number = 0):React.Component|React.PureComponent{
|
||||
/** took from https://stackoverflow.com/questions/29321742/react-getting-a-component-from-a-dom-element-for-debugging */
|
||||
const key = Object.keys(dom).find(key=>key.startsWith("__reactInternalInstance$"));
|
||||
const domFiber = dom[key];
|
||||
if (domFiber == null) return null;
|
||||
|
||||
// react <16
|
||||
if (domFiber._currentElement) {
|
||||
let compFiber = domFiber._currentElement._owner;
|
||||
for (let i = 0; i < traverseUp; i++) {
|
||||
compFiber = compFiber._currentElement._owner;
|
||||
}
|
||||
return compFiber._instance;
|
||||
}
|
||||
|
||||
// react 16+
|
||||
const GetCompFiber = fiber=>{
|
||||
//return fiber._debugOwner; // this also works, but is __DEV__ only
|
||||
let parentFiber = fiber.return;
|
||||
while (typeof parentFiber.type == "string") {
|
||||
parentFiber = parentFiber.return;
|
||||
}
|
||||
return parentFiber;
|
||||
};
|
||||
let compFiber = GetCompFiber(domFiber);
|
||||
for (let i = 0; i < traverseUp; i++) {
|
||||
compFiber = GetCompFiber(compFiber);
|
||||
}
|
||||
return compFiber.stateNode;
|
||||
}
|
||||
|
||||
hasClass(classNames:string, className:string):boolean{
|
||||
if(!classNames || !className)return false
|
||||
const classnames = classNames.split(" ")
|
||||
for(let classname of this.removeDa(className).split(" ")){
|
||||
if(!classnames.includes(classname))return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
formatJSObject(obj:any):string{
|
||||
if(["string", "number", "boolean", "bigint", "undefined"].includes(typeof obj))return JSON.stringify(obj)
|
||||
if(obj === null)return "null"
|
||||
if(typeof obj === "function")return String(obj)
|
||||
if(typeof obj === "symbol")return String(obj)
|
||||
|
||||
if(Array.isArray(obj)){
|
||||
if(!obj.length)return "[]"
|
||||
return `[\n ${obj.map(e => this.formatJSObject(e)).join(",\n ")}\n]`
|
||||
}else{
|
||||
const keys = Object.keys(obj)
|
||||
if(keys.length === 0)return "{}"
|
||||
return `{\n ${keys.map(key => {
|
||||
let original = key
|
||||
if(typeof key === "symbol")key = "["+String(key)+"]"
|
||||
else{
|
||||
if(typeof key === "number")key = String(key)
|
||||
else{
|
||||
console.log(key)
|
||||
if(isNaN(parseInt(key[0]))){
|
||||
key = this.formatJSObject(key)
|
||||
}else if(/[^\w\d_$]/g.test(key)){
|
||||
key = this.formatJSObject(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
return `${key}: ${this.formatJSObject(obj[original])}`
|
||||
})}\n}`
|
||||
}
|
||||
}
|
||||
}
|
@ -46,4 +46,12 @@ export default new class WebpackLoader {
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class WebpackLoaderError extends Error {
|
||||
constructor(message:string = ""){
|
||||
message += "\n\tThis error is related to Lightcord not being able to find a WebpackModule. \n\tPlease show this error and a few lines of logs above this error. \n\tOpen an issue on https://github.com/Lightcord/Lightcord or in their discord server."
|
||||
super(message)
|
||||
this.name = "WebpackLoaderError"
|
||||
}
|
||||
}
|
61
LightcordApi/src/modules/patchers.ts
Normal file
61
LightcordApi/src/modules/patchers.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import Utils from "./Utils"
|
||||
import Notices, { notices } from "../components/private/Notices"
|
||||
|
||||
export function patch(){
|
||||
/** START NOTICE */
|
||||
getModule(e => e.default && e.default.displayName === "ConnectedAppView")
|
||||
.then(async (mod) => {
|
||||
const appClasses = await getModule(e => e.hasNotice);
|
||||
const buildRender = original => {
|
||||
return function render(){
|
||||
const returnValue = original.call(this, ...arguments)
|
||||
const newchildren = []
|
||||
let children = returnValue.props.children[1].props.children
|
||||
if(!Array.isArray(children))children = [children]
|
||||
|
||||
newchildren.push(children[0])
|
||||
newchildren.push(React.createElement(Notices, {container: this}))
|
||||
newchildren.push(children[1])
|
||||
returnValue.props.children[1].props.children = newchildren
|
||||
|
||||
returnValue.props.children[1].props.children[2].props.children[0].props.render = buildRenderChannelSidebar(returnValue.props.children[1].props.children[2].props.children[0].props.render)
|
||||
|
||||
return returnValue
|
||||
}
|
||||
}
|
||||
const buildRenderChannelSidebar = original => {
|
||||
return function renderChannelSidebar(){
|
||||
const returnValue = original.call(this, ...arguments)
|
||||
|
||||
const hasNotice = notices.length > 0
|
||||
if(!hasNotice)return returnValue
|
||||
if(!Utils.hasClass(returnValue.props.className, appClasses.hasNotice)){
|
||||
returnValue.props.className += " "+Utils.removeDa(appClasses.hasNotice)
|
||||
}
|
||||
|
||||
return returnValue
|
||||
}
|
||||
}
|
||||
mod.default.prototype.render = buildRender(mod.default.prototype.render);
|
||||
(async function(){
|
||||
const base = document.querySelector("."+Utils.removeDa(appClasses.base))
|
||||
if(!base)throw new Error(`Could not find base here`)
|
||||
const elem = Utils.FindReact(base) as any
|
||||
elem.render = buildRender(elem.render)
|
||||
elem.forceUpdate()
|
||||
})()
|
||||
})
|
||||
/** END NOTICE */
|
||||
|
||||
|
||||
}
|
||||
|
||||
function getModule(filter: (mod:any) => boolean):Promise<any>{
|
||||
return new Promise((resolve) => {
|
||||
window.Lightcord.Api.ensureExported(filter)
|
||||
.then(resolve)
|
||||
.catch(err => {
|
||||
console.error("[LIGHTCORD]", err, filter)
|
||||
})
|
||||
})
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
|
||||
}
|
@ -47,22 +47,11 @@ async function privateInit(){
|
||||
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
|
||||
}
|
||||
const React = ModuleLoader.get(e => !["Component", "PureComponent", "Children", "createElement", "cloneElement"].map(c => !!e[c]).includes(false))[0]
|
||||
window.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
|
||||
}
|
||||
const ReactDOM = ModuleLoader.get(e => e.findDOMNode)[0]
|
||||
window.ReactDOM = ReactDOM
|
||||
|
||||
//stop here if betterdiscord is disabled.
|
||||
if(electron.remote.process.argv.includes("--disable-betterdiscord")){
|
||||
@ -290,7 +279,7 @@ async function privateInit(){
|
||||
DiscordNative.ipc.send("UPDATE_THEME", data.settings.theme)
|
||||
})
|
||||
|
||||
require("../../../../../LightcordApi/js/main.js")
|
||||
require("lightcordapi/js/main.js")
|
||||
|
||||
/*
|
||||
if(shouldShowPrompt){
|
||||
@ -363,7 +352,7 @@ async function privateInit(){
|
||||
dispatcher.subscribe(constants.ActionTypes.CONNECTION_OPEN || "CONNECTION_OPEN", onConn)
|
||||
}*/
|
||||
|
||||
const BetterDiscord = window.BetterDiscord = window.mainCore = new(require("../../../../../BetterDiscordApp/js/main.js").default)(BetterDiscordConfig)
|
||||
const BetterDiscord = window.BetterDiscord = window.mainCore = new(require("../../../../../BetterDiscordApp/js/main.js").default)(BetterDiscordConfig, require("./betterdiscord"))
|
||||
|
||||
const Utils = window.Lightcord.BetterDiscord.Utils
|
||||
const DOMTools = window.Lightcord.BetterDiscord.DOM
|
||||
@ -1247,6 +1236,10 @@ require.extensions[".jsbr"] = (m, filename) => {
|
||||
fs.writeFileSync(tmpFile.name+".js", zlib.brotliDecompressSync(fs.readFileSync(filename)))
|
||||
return require.extensions[".js"](m, tmpFile.name+".js")
|
||||
}
|
||||
require.extensions[".txt"] = (m, filename) => {
|
||||
m.exports = fs.readFileSync(filename, "utf8")
|
||||
return m.exports
|
||||
}
|
||||
|
||||
const LightcordBDFolder = path.join(electron.remote.app.getPath("appData"), "Lightcord_BD")
|
||||
|
||||
@ -1337,7 +1330,7 @@ path.originalResolve = originalResolve
|
||||
|
||||
let blacklist
|
||||
function isBlacklisted(id){
|
||||
if(!blacklist)blacklist = fs.readFileSync(path.join(__dirname, "blacklist.txt"), "utf8").split(/[\n\r]+/g).map((line, index, lines) => {
|
||||
if(!blacklist)blacklist = require("./blacklist.txt").split(/[\n\r]+/g).map((line, index, lines) => {
|
||||
let id = ""
|
||||
let comment = ""
|
||||
line.split("#").forEach((idOrComment, index, array) => {
|
||||
|
@ -0,0 +1,253 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018, Nick Gavrilov
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* From https://github.com/ilearnio/module-alias
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
var BuiltinModule = require('module')
|
||||
|
||||
// Guard against poorly mocked module constructors
|
||||
var Module = module.constructor.length > 1
|
||||
? module.constructor
|
||||
: BuiltinModule
|
||||
|
||||
var nodePath = require('path')
|
||||
|
||||
var modulePaths = []
|
||||
var moduleAliases = {}
|
||||
var moduleAliasNames = []
|
||||
|
||||
var oldNodeModulePaths = Module._nodeModulePaths
|
||||
Module._nodeModulePaths = function (from) {
|
||||
var paths = oldNodeModulePaths.call(this, from)
|
||||
|
||||
// Only include the module path for top-level modules
|
||||
// that were not installed:
|
||||
if (from.indexOf('node_modules') === -1) {
|
||||
paths = modulePaths.concat(paths)
|
||||
}
|
||||
|
||||
return paths
|
||||
}
|
||||
|
||||
var oldResolveFilename = Module._resolveFilename
|
||||
Module._resolveFilename = function (request, parentModule, isMain, options) {
|
||||
for (var i = moduleAliasNames.length; i-- > 0;) {
|
||||
var alias = moduleAliasNames[i]
|
||||
if (isPathMatchesAlias(request, alias)) {
|
||||
var aliasTarget = moduleAliases[alias]
|
||||
// Custom function handler
|
||||
if (typeof moduleAliases[alias] === 'function') {
|
||||
var fromPath = parentModule.filename
|
||||
aliasTarget = moduleAliases[alias](fromPath, request, alias)
|
||||
if (!aliasTarget || typeof aliasTarget !== 'string') {
|
||||
throw new Error('[module-alias] Expecting custom handler function to return path.')
|
||||
}
|
||||
}
|
||||
request = nodePath.join(aliasTarget, request.substr(alias.length))
|
||||
// Only use the first match
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return oldResolveFilename.call(this, request, parentModule, isMain, options)
|
||||
}
|
||||
|
||||
function isPathMatchesAlias (path, alias) {
|
||||
// Matching /^alias(\/|$)/
|
||||
if (path.indexOf(alias) === 0) {
|
||||
if (path.length === alias.length) return true
|
||||
if (path[alias.length] === '/') return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
function addPathHelper (path, targetArray) {
|
||||
path = nodePath.normalize(path)
|
||||
if (targetArray && targetArray.indexOf(path) === -1) {
|
||||
targetArray.unshift(path)
|
||||
}
|
||||
}
|
||||
|
||||
function removePathHelper (path, targetArray) {
|
||||
if (targetArray) {
|
||||
var index = targetArray.indexOf(path)
|
||||
if (index !== -1) {
|
||||
targetArray.splice(index, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addPath (path) {
|
||||
var parent
|
||||
path = nodePath.normalize(path)
|
||||
|
||||
if (modulePaths.indexOf(path) === -1) {
|
||||
modulePaths.push(path)
|
||||
// Enable the search path for the current top-level module
|
||||
var mainModule = getMainModule()
|
||||
if (mainModule) {
|
||||
addPathHelper(path, mainModule.paths)
|
||||
}
|
||||
parent = module.parent
|
||||
|
||||
// Also modify the paths of the module that was used to load the
|
||||
// app-module-paths module and all of it's parents
|
||||
while (parent && parent !== mainModule) {
|
||||
addPathHelper(path, parent.paths)
|
||||
parent = parent.parent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addAliases (aliases) {
|
||||
for (var alias in aliases) {
|
||||
addAlias(alias, aliases[alias])
|
||||
}
|
||||
}
|
||||
|
||||
function addAlias (alias, target) {
|
||||
moduleAliases[alias] = target
|
||||
// Cost of sorting is lower here than during resolution
|
||||
moduleAliasNames = Object.keys(moduleAliases)
|
||||
moduleAliasNames.sort()
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset any changes maded (resets all registered aliases
|
||||
* and custom module directories)
|
||||
* The function is undocumented and for testing purposes only
|
||||
*/
|
||||
function reset () {
|
||||
var mainModule = getMainModule()
|
||||
|
||||
// Reset all changes in paths caused by addPath function
|
||||
modulePaths.forEach(function (path) {
|
||||
if (mainModule) {
|
||||
removePathHelper(path, mainModule.paths)
|
||||
}
|
||||
|
||||
// Delete from require.cache if the module has been required before.
|
||||
// This is required for node >= 11
|
||||
Object.getOwnPropertyNames(require.cache).forEach(function (name) {
|
||||
if (name.indexOf(path) !== -1) {
|
||||
delete require.cache[name]
|
||||
}
|
||||
})
|
||||
|
||||
var parent = module.parent
|
||||
while (parent && parent !== mainModule) {
|
||||
removePathHelper(path, parent.paths)
|
||||
parent = parent.parent
|
||||
}
|
||||
})
|
||||
|
||||
modulePaths = []
|
||||
moduleAliases = {}
|
||||
moduleAliasNames = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Import aliases from package.json
|
||||
* @param {object} options
|
||||
*/
|
||||
function init (options) {
|
||||
if (typeof options === 'string') {
|
||||
options = { base: options }
|
||||
}
|
||||
|
||||
options = options || {}
|
||||
|
||||
var candidatePackagePaths
|
||||
if (options.base) {
|
||||
candidatePackagePaths = [nodePath.resolve(options.base.replace(/\/package\.json$/, ''))]
|
||||
} else {
|
||||
// There is probably 99% chance that the project root directory in located
|
||||
// above the node_modules directory,
|
||||
// Or that package.json is in the node process' current working directory (when
|
||||
// running a package manager script, e.g. `yarn start` / `npm run start`)
|
||||
candidatePackagePaths = [nodePath.join(__dirname, '../..'), process.cwd()]
|
||||
}
|
||||
|
||||
var npmPackage
|
||||
var base
|
||||
for (var i in candidatePackagePaths) {
|
||||
try {
|
||||
base = candidatePackagePaths[i]
|
||||
|
||||
npmPackage = require(nodePath.join(base, 'package.json'))
|
||||
break
|
||||
} catch (e) {
|
||||
// noop
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof npmPackage !== 'object') {
|
||||
var pathString = candidatePackagePaths.join(',\n')
|
||||
throw new Error('Unable to find package.json in any of:\n[' + pathString + ']')
|
||||
}
|
||||
|
||||
//
|
||||
// Import aliases
|
||||
//
|
||||
|
||||
var aliases = npmPackage._moduleAliases || {}
|
||||
|
||||
for (var alias in aliases) {
|
||||
if (aliases[alias][0] !== '/') {
|
||||
aliases[alias] = nodePath.join(base, aliases[alias])
|
||||
}
|
||||
}
|
||||
|
||||
addAliases(aliases)
|
||||
|
||||
//
|
||||
// Register custom module directories (like node_modules)
|
||||
//
|
||||
|
||||
if (npmPackage._moduleDirectories instanceof Array) {
|
||||
npmPackage._moduleDirectories.forEach(function (dir) {
|
||||
if (dir === 'node_modules') return
|
||||
|
||||
var modulePath = nodePath.join(base, dir)
|
||||
addPath(modulePath)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getMainModule () {
|
||||
return require.main._simulateRepl ? undefined : require.main
|
||||
}
|
||||
|
||||
module.exports = init
|
||||
module.exports.addPath = addPath
|
||||
module.exports.addAlias = addAlias
|
||||
module.exports.addAliases = addAliases
|
||||
module.exports.isPathMatchesAlias = isPathMatchesAlias
|
||||
module.exports.reset = reset
|
||||
module.exports.setMain = function(main){
|
||||
require.main = main
|
||||
}
|
@ -0,0 +1 @@
|
||||
An alias for react-dom
|
1
modules/discord_desktop_core/core/app/BetterDiscord/modules/react-dom/index.js
vendored
Normal file
1
modules/discord_desktop_core/core/app/BetterDiscord/modules/react-dom/index.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = window.ReactDOM
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "react-dom",
|
||||
"version": "1.0.0",
|
||||
"description": "An alias for react-dom",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
@ -0,0 +1 @@
|
||||
An alias for the react module.
|
@ -0,0 +1 @@
|
||||
module.exports = window.React
|
@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "react",
|
||||
"version": "1.0.0",
|
||||
"description": "An alias for the react module.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
@ -7,8 +7,16 @@ process.on("uncaughtException", console.error)
|
||||
|
||||
const ipcRenderer = require('./discord_native/ipc');
|
||||
const electron = require("electron")
|
||||
const moduleAlias = require("./BetterDiscord/loaders/module-alias")
|
||||
const path = require("path")
|
||||
|
||||
electron.remote.getCurrentWindow().setBackgroundColor("#2f3136")
|
||||
|
||||
moduleAlias.setMain(module)
|
||||
moduleAlias.addAlias("@lightcord/api", path.join(__dirname, "../../../../LightcordApi"))
|
||||
moduleAlias.addAlias("lightcordapi", path.join(__dirname, "../../../../LightcordApi"))
|
||||
moduleAlias.addPath(path.join(__dirname, "BetterDiscord", "modules"))
|
||||
|
||||
const TRACK_ANALYTICS_EVENT = 'TRACK_ANALYTICS_EVENT';
|
||||
const TRACK_ANALYTICS_EVENT_COMMIT = 'TRACK_ANALYTICS_EVENT_COMMIT';
|
||||
|
||||
|
73
package-lock.json
generated
73
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "lightcord",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -721,12 +721,6 @@
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
|
||||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||
@ -789,15 +783,6 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"lowercase-keys": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
|
||||
@ -884,12 +869,6 @@
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||
"dev": true
|
||||
},
|
||||
"object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
@ -962,17 +941,6 @@
|
||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||
"dev": true
|
||||
},
|
||||
"prop-types": {
|
||||
"version": "15.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||
"integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.4.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"react-is": "^16.8.1"
|
||||
}
|
||||
},
|
||||
"proto-list": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
|
||||
@ -1005,35 +973,6 @@
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||
},
|
||||
"react": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz",
|
||||
"integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2"
|
||||
}
|
||||
},
|
||||
"react-dom": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz",
|
||||
"integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"scheduler": "^0.19.1"
|
||||
}
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"dev": true
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
@ -1127,16 +1066,6 @@
|
||||
"truncate-utf8-bytes": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"scheduler": {
|
||||
"version": "0.19.1",
|
||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
|
||||
"integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
|
||||
|
@ -40,8 +40,6 @@
|
||||
"@types/yauzl": "^2.9.1",
|
||||
"cross-spawn": "^7.0.3",
|
||||
"electron": "^8.4.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"terser": "^4.7.0",
|
||||
"yazl": "^2.5.1"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user