ogi-addon 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/EventResponse.cjs +10 -0
- package/build/EventResponse.cjs.map +1 -1
- package/build/EventResponse.d.cts +11 -0
- package/build/EventResponse.d.ts +11 -0
- package/build/EventResponse.js +10 -0
- package/build/EventResponse.js.map +1 -1
- package/build/SearchEngine.cjs.map +1 -1
- package/build/SearchEngine.d.cts +1 -0
- package/build/SearchEngine.d.ts +1 -0
- package/build/config/Configuration.cjs +5 -0
- package/build/config/Configuration.cjs.map +1 -1
- package/build/config/Configuration.js +5 -0
- package/build/config/Configuration.js.map +1 -1
- package/build/config/ConfigurationBuilder.cjs +5 -0
- package/build/config/ConfigurationBuilder.cjs.map +1 -1
- package/build/config/ConfigurationBuilder.d.cts +2 -0
- package/build/config/ConfigurationBuilder.d.ts +2 -0
- package/build/config/ConfigurationBuilder.js +5 -0
- package/build/config/ConfigurationBuilder.js.map +1 -1
- package/build/main.cjs +58 -4
- package/build/main.cjs.map +1 -1
- package/build/main.d.cts +21 -5
- package/build/main.d.ts +21 -5
- package/build/main.js +58 -4
- package/build/main.js.map +1 -1
- package/package.json +49 -49
- package/src/EventResponse.ts +15 -0
- package/src/SearchEngine.ts +1 -0
- package/src/config/ConfigurationBuilder.ts +6 -0
- package/src/main.ts +63 -8
package/build/main.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/main.ts","../src/config/ConfigurationBuilder.ts","../src/config/Configuration.ts","../src/EventResponse.ts"],"sourcesContent":["import ws, { WebSocket } from 'ws';\r\nimport events from 'node:events';\r\nimport { ConfigurationBuilder, ConfigurationFile } from './config/ConfigurationBuilder';\r\nimport { Configuration } from './config/Configuration';\r\nimport EventResponse from './EventResponse';\r\nimport { SearchResult } from './SearchEngine';\r\n\r\nexport type OGIAddonEvent = 'connect' | 'disconnect' | 'configure' | 'authenticate' | 'search' | 'setup';\r\nexport type OGIAddonClientSentEvent = 'response' | 'authenticate' | 'configure' | 'defer-update' | 'notification';\r\n\r\nexport type OGIAddonServerSentEvent = 'authenticate' | 'configure' | 'config-update' | 'search' | 'setup';\r\nexport { ConfigurationBuilder, Configuration, EventResponse, SearchResult };\r\nconst defaultPort = 7654;\r\n\r\nexport interface ClientSentEventTypes {\r\n response: any;\r\n authenticate: any;\r\n configure: ConfigurationFile;\r\n 'defer-update': {\r\n logs: string[], \r\n progress: number\r\n };\r\n notification: Notification;\r\n}\r\n\r\nexport interface EventListenerTypes {\r\n connect: (socket: ws) => void;\r\n disconnect: (reason: string) => void;\r\n configure: (config: ConfigurationBuilder) => ConfigurationBuilder;\r\n response: (response: any) => void;\r\n authenticate: (config: any) => void;\r\n search: (query: string, event: EventResponse<SearchResult[]>) => void;\r\n setup: (\r\n data: { \r\n path: string, \r\n type: 'direct' | 'torrent' | 'magnet',\r\n name: string,\r\n usedRealDebrid: boolean, \r\n multiPartFiles?: {\r\n name: string,\r\n downloadURL: string\r\n }[],\r\n }, event: EventResponse<undefined | null>\r\n ) => void;\r\n}\r\n\r\nexport interface WebsocketMessageClient {\r\n event: OGIAddonClientSentEvent;\r\n id?: string;\r\n args: any;\r\n}\r\nexport interface WebsocketMessageServer {\r\n event: OGIAddonServerSentEvent;\r\n id?: string;\r\n args: any;\r\n}\r\nexport interface OGIAddonConfiguration {\r\n name: string;\r\n id: string;\r\n description: string;\r\n version: string;\r\n\r\n author: string;\r\n repository: string;\r\n}\r\nexport default class OGIAddon {\r\n public eventEmitter = new events.EventEmitter();\r\n public addonWSListener: OGIAddonWSListener;\r\n public addonInfo: OGIAddonConfiguration;\r\n public config: Configuration = new Configuration({});\r\n\r\n constructor(addonInfo: OGIAddonConfiguration) {\r\n this.addonInfo = addonInfo;\r\n this.addonWSListener = new OGIAddonWSListener(this, this.eventEmitter);\r\n }\r\n \r\n public on<T extends OGIAddonEvent>(event: T, listener: EventListenerTypes[T]) {\r\n this.eventEmitter.on(event, listener);\r\n }\r\n\r\n public emit<T extends OGIAddonEvent>(event: T, ...args: Parameters<EventListenerTypes[T]>) {\r\n this.eventEmitter.emit(event, ...args);\r\n }\r\n\r\n public notify(notification: Notification) {\r\n this.addonWSListener.send('notification', [ notification ]);\r\n }\r\n}\r\ninterface Notification {\r\n type: 'warning' | 'error' | 'info' | 'success';\r\n message: string;\r\n id: string\r\n}\r\nclass OGIAddonWSListener {\r\n private socket: WebSocket;\r\n public eventEmitter: events.EventEmitter;\r\n public addon: OGIAddon;\r\n\r\n constructor(ogiAddon: OGIAddon, eventEmitter: events.EventEmitter) {\r\n if (process.argv[process.argv.length - 1].split('=')[0] !== '--addonSecret') {\r\n throw new Error('No secret provided. This usually happens because the addon was not started by the OGI Addon Server.');\r\n }\r\n this.addon = ogiAddon;\r\n this.eventEmitter = eventEmitter;\r\n this.socket = new ws('ws://localhost:' + defaultPort);\r\n this.socket.on('open', () => {\r\n console.log('Connected to OGI Addon Server');\r\n\r\n // Authenticate with OGI Addon Server\r\n this.socket.send(JSON.stringify({\r\n event: 'authenticate',\r\n args: {\r\n ...this.addon.addonInfo,\r\n secret: process.argv[process.argv.length - 1].split('=')[1]\r\n }\r\n }));\r\n\r\n this.eventEmitter.emit('connect');\r\n\r\n // send a configuration request\r\n let configBuilder = new ConfigurationBuilder();\r\n this.eventEmitter.emit('configure', configBuilder);\r\n \r\n this.socket.send(JSON.stringify({\r\n event: 'configure',\r\n args: configBuilder.build(false) \r\n }));\r\n this.addon.config = new Configuration(configBuilder.build(true));\r\n });\r\n\r\n this.socket.on('error', (error) => {\r\n if (error.message.includes('Failed to connect')) {\r\n throw new Error('OGI Addon Server is not running/is unreachable. Please start the server and try again.');\r\n }\r\n console.error('An error occurred:', error);\r\n })\r\n\r\n this.socket.on('close', (code, reason) => {\r\n if (code === 1008) {\r\n console.error('Authentication failed:', reason);\r\n return;\r\n }\r\n this.eventEmitter.emit('disconnect', reason);\r\n console.log(\"Disconnected from OGI Addon Server\")\r\n this.socket.close();\r\n });\r\n\r\n this.registerMessageReceiver();\r\n }\r\n\r\n private registerMessageReceiver() {\r\n this.socket.on('message', async (data: string) => {\r\n const message: WebsocketMessageServer = JSON.parse(data);\r\n switch (message.event) {\r\n case 'config-update':\r\n const result = this.addon.config.updateConfig(message.args);\r\n if (!result[0]) {\r\n this.respondToMessage(message.id!!, { success: false, error: result[1] });\r\n }\r\n else {\r\n this.respondToMessage(message.id!!, { success: true });\r\n }\r\n break \r\n case 'search':\r\n let searchResultEvent = new EventResponse<SearchResult[]>();\r\n this.eventEmitter.emit('search', message.args, searchResultEvent);\r\n const searchResult = await this.waitForEventToRespond(searchResultEvent); \r\n console.log(searchResult.data)\r\n this.respondToMessage(message.id!!, searchResult.data);\r\n break\r\n case 'setup':\r\n let setupEvent = new EventResponse<undefined | null>();\r\n this.eventEmitter.emit('setup', { path: message.args.path, type: message.args.type, name: message.args.name, usedRealDebrid: message.args.usedRealDebrid, multiPartFiles: message.args.multiPartFiles }, setupEvent);\r\n const interval = setInterval(() => {\r\n if (setupEvent.resolved) {\r\n clearInterval(interval);\r\n return;\r\n }\r\n this.send('defer-update', { \r\n logs: setupEvent.logs,\r\n deferID: message.args.deferID,\r\n progress: setupEvent.progress\r\n } as any);\r\n }, 100);\r\n const setupResult = await this.waitForEventToRespond(setupEvent);\r\n this.respondToMessage(message.id!!, setupResult.data);\r\n break\r\n }\r\n });\r\n }\r\n\r\n private waitForEventToRespond<T>(event: EventResponse<T>): Promise<EventResponse<T>> {\r\n return new Promise((resolve, reject) => {\r\n const dataGet = setInterval(() => {\r\n if (event.resolved) {\r\n resolve(event);\r\n clearTimeout(timeout);\r\n }\r\n }, 5); \r\n\r\n const timeout = setTimeout(() => {\r\n if (event.deffered) {\r\n clearInterval(dataGet);\r\n const interval = setInterval(() => {\r\n if (event.resolved) {\r\n clearInterval(interval);\r\n resolve(event);\r\n }\r\n }, 100);\r\n }\r\n else {\r\n reject('Event did not respond in time');\r\n }\r\n }, 5000)\r\n });\r\n }\r\n\r\n public respondToMessage(messageID: string, response: any) {\r\n this.socket.send(JSON.stringify({\r\n event: 'response',\r\n id: messageID,\r\n args: response\r\n }));\r\n console.log(\"dispatched response to \" + messageID)\r\n }\r\n\r\n public send(event: OGIAddonClientSentEvent, args: Parameters<ClientSentEventTypes[OGIAddonClientSentEvent]>) {\r\n this.socket.send(JSON.stringify({\r\n event,\r\n args\r\n }));\r\n }\r\n\r\n public close() {\r\n this.socket.close();\r\n }\r\n\r\n \r\n}","import z, { ZodError } from \"zod\"\r\n\r\nexport interface ConfigurationFile {\r\n [key: string]: ConfigurationOption\r\n}\r\n\r\nconst configValidation = z.object({\r\n name: z.string().min(1),\r\n displayName: z.string().min(1),\r\n description: z.string().min(1),\r\n})\r\n\r\nexport function isStringOption(option: ConfigurationOption): option is StringOption {\r\n return option.type === 'string';\r\n }\r\n\r\nexport function isNumberOption(option: ConfigurationOption): option is NumberOption {\r\n return option.type === 'number';\r\n}\r\n\r\nexport function isBooleanOption(option: ConfigurationOption): option is BooleanOption {\r\n return option.type === 'boolean';\r\n}\r\n\r\nexport class ConfigurationBuilder {\r\n private options: ConfigurationOption[] = [];\r\n public addNumberOption(option: (option: NumberOption) => NumberOption): ConfigurationBuilder {\r\n let newOption = new NumberOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public addStringOption(option: (option: StringOption) => StringOption) {\r\n let newOption = new StringOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public addBooleanOption(option: (option: BooleanOption) => BooleanOption) {\r\n let newOption = new BooleanOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public build(includeFunctions: boolean): ConfigurationFile {\r\n let config: ConfigurationFile = {};\r\n this.options.forEach(option => {\r\n // remove all functions from the option object\r\n if (!includeFunctions) {\r\n option = JSON.parse(JSON.stringify(option));\r\n const optionData = configValidation.safeParse(option)\r\n if (!optionData.success) {\r\n throw new ZodError(optionData.error.errors)\r\n }\r\n\r\n config[option.name] = option;\r\n }\r\n else {\r\n config[option.name] = option;\r\n }\r\n });\r\n return config;\r\n }\r\n}\r\n\r\nexport type ConfigurationOptionType = 'string' | 'number' | 'boolean' | 'unset'\r\nexport class ConfigurationOption {\r\n public name: string = '';\r\n public defaultValue: unknown = '';\r\n public displayName: string = '';\r\n public description: string = '';\r\n public type: ConfigurationOptionType = 'unset'\r\n \r\n setName(name: string) {\r\n this.name = name;\r\n return this;\r\n }\r\n\r\n setDisplayName(displayName: string) {\r\n this.displayName = displayName;\r\n return this;\r\n }\r\n\r\n setDescription(description: string) {\r\n this.description = description;\r\n return this;\r\n }\r\n\r\n\r\n validate(input: unknown): [ boolean, string ] {\r\n throw new Error('Validation code not implemented. Value: ' + input)\r\n };\r\n}\r\n\r\nexport class StringOption extends ConfigurationOption {\r\n public allowedValues: string[] = [];\r\n public minTextLength: number = 0;\r\n public maxTextLength: number = Number.MAX_SAFE_INTEGER;\r\n public defaultValue: string = '';\r\n public type: ConfigurationOptionType = 'string'\r\n\r\n setAllowedValues(allowedValues: string[]): this {\r\n this.allowedValues = allowedValues;\r\n return this;\r\n }\r\n\r\n setDefaultValue(defaultValue: string): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n setMinTextLength(minTextLength: number): this {\r\n this.minTextLength = minTextLength;\r\n return this;\r\n }\r\n\r\n setMaxTextLength(maxTextLength: number): this {\r\n this.maxTextLength = maxTextLength;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (typeof input !== 'string') {\r\n return [ false, 'Input is not a string' ];\r\n }\r\n if (this.allowedValues.length === 0 && input.length !== 0)\r\n return [ true, '' ];\r\n if (input.length < this.minTextLength || input.length > this.maxTextLength) {\r\n return [ false, 'Input is not within the text length ' + this.minTextLength + ' and ' + this.maxTextLength + ' characters (currently ' + input.length + ' characters)' ];\r\n }\r\n\r\n return [ this.allowedValues.includes(input), 'Input is not an allowed value' ];\r\n }\r\n}\r\n\r\nexport class NumberOption extends ConfigurationOption {\r\n public min: number = 0;\r\n public max: number = Number.MAX_SAFE_INTEGER;\r\n public defaultValue: number = 0;\r\n public type: ConfigurationOptionType = 'number'\r\n public inputType: 'range' | 'number' = 'number';\r\n setMin(min: number): this {\r\n this.min = min;\r\n return this;\r\n }\r\n\r\n setInputType(type: 'range' | 'number'): this {\r\n this.inputType = type;\r\n return this;\r\n }\r\n\r\n setMax(max: number): this {\r\n this.max = max;\r\n return this\r\n }\r\n\r\n setDefaultValue(defaultValue: number): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (isNaN(Number(input))) {\r\n return [ false, 'Input is not a number' ];\r\n }\r\n if (Number(input) < this.min || Number(input) > this.max) {\r\n return [ false, 'Input is not within the range of ' + this.min + ' and ' + this.max ];\r\n }\r\n return [ true, '' ];\r\n }\r\n\r\n}\r\n\r\nexport class BooleanOption extends ConfigurationOption {\r\n public type: ConfigurationOptionType = 'boolean'\r\n public defaultValue: boolean = false;\r\n\r\n setDefaultValue(defaultValue: boolean): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (typeof input !== 'boolean') {\r\n return [ false, 'Input is not a boolean' ];\r\n }\r\n return [ true, '' ];\r\n }\r\n\r\n}","import { ConfigurationFile, ConfigurationBuilder, BooleanOption, ConfigurationOption, ConfigurationOptionType, NumberOption, StringOption, isBooleanOption, isNumberOption, isStringOption } from \"./ConfigurationBuilder\";\r\n\r\ninterface DefiniteConfig {\r\n [key: string]: string | number | boolean;\r\n}\r\nexport class Configuration {\r\n readonly storedConfigTemplate: ConfigurationFile;\r\n definiteConfig: DefiniteConfig = {};\r\n constructor(configTemplate: ConfigurationFile) {\r\n this.storedConfigTemplate = configTemplate;\r\n }\r\n\r\n updateConfig(config: DefiniteConfig, validate: boolean = true): [ boolean, { [key: string]: string } ] {\r\n this.definiteConfig = config;\r\n if (validate) {\r\n const result = this.validateConfig();\r\n return result;\r\n }\r\n return [ true, {} ];\r\n }\r\n // provides falsey or truthy value, and an error message if falsey\r\n private validateConfig(): [ boolean, { [key: string]: string } ] {\r\n const erroredKeys = new Map<string, string>();\r\n for (const key in this.storedConfigTemplate) {\r\n if (this.definiteConfig[key] === null || this.definiteConfig[key] === undefined) {\r\n console.warn('Option ' + key + ' is not defined. Using default value Value: ' + this.definiteConfig[key]);\r\n this.definiteConfig[key] = this.storedConfigTemplate[key].defaultValue as string | number | boolean;\r\n }\r\n if (this.storedConfigTemplate[key].type !== typeof this.definiteConfig[key]) {\r\n throw new Error('Option ' + key + ' is not of the correct type');\r\n }\r\n\r\n const result = this.storedConfigTemplate[key].validate(this.definiteConfig[key]);\r\n if (!result[0]) {\r\n erroredKeys.set(key, result[1]);\r\n }\r\n }\r\n\r\n for (const key in this.definiteConfig) {\r\n if (!this.storedConfigTemplate[key]) {\r\n throw new Error('Option ' + key + ' is not defined in the configuration template');\r\n }\r\n }\r\n\r\n if (erroredKeys.size > 0) {\r\n return [ false, Object.fromEntries(erroredKeys) ];\r\n }\r\n\r\n return [ true, Object.fromEntries(erroredKeys) ];\r\n }\r\n\r\n getStringValue(optionName: string): string {\r\n if (!this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'string') {\r\n throw new Error('Option ' + optionName + ' is not a string');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n\r\n getNumberValue(optionName: string): number {\r\n if (!this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'number') {\r\n throw new Error('Option ' + optionName + ' is not a number');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n\r\n getBooleanValue(optionName: string): boolean {\r\n if (this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'boolean') {\r\n throw new Error('Option ' + optionName + ' is not a boolean');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n}\r\n\r\nexport { ConfigurationFile, ConfigurationBuilder, BooleanOption, ConfigurationOption, ConfigurationOptionType, NumberOption, StringOption, isBooleanOption, isNumberOption, isStringOption };","export default class EventResponse<T> {\r\n data: T | undefined = undefined;\r\n deffered: boolean = false;\r\n resolved: boolean = false;\r\n progress: number = 0;\r\n logs: string[] = [];\r\n\r\n public defer() {\r\n this.deffered = true;\r\n }\r\n\r\n public resolve(data: T) {\r\n this.resolved = true;\r\n this.data = data;\r\n }\r\n\r\n public complete() {\r\n this.resolved = true;\r\n }\r\n\r\n public log(message: string) {\r\n this.logs.push(message);\r\n }\r\n\r\n \r\n}"],"mappings":"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","names":["z","events","ws"]}
|
|
1
|
+
{"version":3,"sources":["../src/main.ts","../src/config/ConfigurationBuilder.ts","../src/config/Configuration.ts","../src/EventResponse.ts"],"sourcesContent":["import ws, { WebSocket } from 'ws';\r\nimport events from 'node:events';\r\nimport { ConfigurationBuilder, ConfigurationFile } from './config/ConfigurationBuilder';\r\nimport { Configuration } from './config/Configuration';\r\nimport EventResponse from './EventResponse';\r\nimport { SearchResult } from './SearchEngine';\r\n\r\nexport type OGIAddonEvent = 'connect' | 'disconnect' | 'configure' | 'authenticate' | 'search' | 'setup';\r\nexport type OGIAddonClientSentEvent = 'response' | 'authenticate' | 'configure' | 'defer-update' | 'notification' | 'input-asked';\r\n\r\nexport type OGIAddonServerSentEvent = 'authenticate' | 'configure' | 'config-update' | 'search' | 'setup' | 'response';\r\nexport { ConfigurationBuilder, Configuration, EventResponse, SearchResult };\r\nconst defaultPort = 7654;\r\nconst version = process.env.npm_package_version;\r\n\r\nexport interface ClientSentEventTypes {\r\n response: any;\r\n authenticate: any;\r\n configure: ConfigurationFile;\r\n 'defer-update': {\r\n logs: string[], \r\n progress: number\r\n };\r\n notification: Notification;\r\n 'input-asked': ConfigurationBuilder;\r\n}\r\n\r\nexport interface EventListenerTypes {\r\n connect: (socket: ws) => void;\r\n disconnect: (reason: string) => void;\r\n configure: (config: ConfigurationBuilder) => ConfigurationBuilder;\r\n response: (response: any) => void;\r\n authenticate: (config: any) => void;\r\n search: (query: { type: 'steamapp', text: string }, event: EventResponse<SearchResult[]>) => void;\r\n setup: (\r\n data: { \r\n path: string, \r\n type: 'direct' | 'torrent' | 'magnet',\r\n name: string,\r\n usedRealDebrid: boolean, \r\n multiPartFiles?: {\r\n name: string,\r\n downloadURL: string\r\n }[],\r\n steamAppID: number\r\n }, event: EventResponse<LibraryInfo>\r\n ) => void;\r\n}\r\n\r\nexport interface WebsocketMessageClient {\r\n event: OGIAddonClientSentEvent;\r\n id?: string;\r\n args: any;\r\n}\r\nexport interface WebsocketMessageServer {\r\n event: OGIAddonServerSentEvent;\r\n id?: string;\r\n args: any;\r\n}\r\nexport interface OGIAddonConfiguration {\r\n name: string;\r\n id: string;\r\n description: string;\r\n version: string;\r\n\r\n author: string;\r\n repository: string;\r\n}\r\nexport default class OGIAddon {\r\n public eventEmitter = new events.EventEmitter();\r\n public addonWSListener: OGIAddonWSListener;\r\n public addonInfo: OGIAddonConfiguration;\r\n public config: Configuration = new Configuration({});\r\n\r\n constructor(addonInfo: OGIAddonConfiguration) {\r\n this.addonInfo = addonInfo;\r\n this.addonWSListener = new OGIAddonWSListener(this, this.eventEmitter);\r\n }\r\n \r\n public on<T extends OGIAddonEvent>(event: T, listener: EventListenerTypes[T]) {\r\n this.eventEmitter.on(event, listener);\r\n }\r\n\r\n public emit<T extends OGIAddonEvent>(event: T, ...args: Parameters<EventListenerTypes[T]>) {\r\n this.eventEmitter.emit(event, ...args);\r\n }\r\n\r\n public notify(notification: Notification) {\r\n this.addonWSListener.send('notification', [ notification ]);\r\n }\r\n}\r\n\r\nexport interface LibraryInfo {\r\n name: string;\r\n version: string;\r\n cwd: string;\r\n steamAppID: number;\r\n launchExecutable: string;\r\n launchArguments?: string;\r\n capsuleImage: string;\r\n}\r\ninterface Notification {\r\n type: 'warning' | 'error' | 'info' | 'success';\r\n message: string;\r\n id: string\r\n}\r\nclass OGIAddonWSListener {\r\n private socket: WebSocket;\r\n public eventEmitter: events.EventEmitter;\r\n public addon: OGIAddon;\r\n\r\n constructor(ogiAddon: OGIAddon, eventEmitter: events.EventEmitter) {\r\n if (process.argv[process.argv.length - 1].split('=')[0] !== '--addonSecret') {\r\n throw new Error('No secret provided. This usually happens because the addon was not started by the OGI Addon Server.');\r\n }\r\n this.addon = ogiAddon;\r\n this.eventEmitter = eventEmitter;\r\n this.socket = new ws('ws://localhost:' + defaultPort);\r\n this.socket.on('open', () => {\r\n console.log('Connected to OGI Addon Server');\r\n console.log('OGI Addon Server Version:', version);\r\n\r\n // Authenticate with OGI Addon Server\r\n this.socket.send(JSON.stringify({\r\n event: 'authenticate',\r\n args: {\r\n ...this.addon.addonInfo,\r\n secret: process.argv[process.argv.length - 1].split('=')[1],\r\n ogiVersion: version\r\n }\r\n }));\r\n\r\n this.eventEmitter.emit('connect');\r\n\r\n // send a configuration request\r\n let configBuilder = new ConfigurationBuilder();\r\n this.eventEmitter.emit('configure', configBuilder);\r\n \r\n this.socket.send(JSON.stringify({\r\n event: 'configure',\r\n args: configBuilder.build(false) \r\n }));\r\n this.addon.config = new Configuration(configBuilder.build(true));\r\n });\r\n\r\n this.socket.on('error', (error) => {\r\n if (error.message.includes('Failed to connect')) {\r\n throw new Error('OGI Addon Server is not running/is unreachable. Please start the server and try again.');\r\n }\r\n console.error('An error occurred:', error);\r\n })\r\n\r\n this.socket.on('close', (code, reason) => {\r\n if (code === 1008) {\r\n console.error('Authentication failed:', reason);\r\n return;\r\n }\r\n this.eventEmitter.emit('disconnect', reason);\r\n console.log(\"Disconnected from OGI Addon Server\")\r\n console.log(reason.toString())\r\n this.socket.close();\r\n });\r\n\r\n this.registerMessageReceiver();\r\n }\r\n\r\n private async userInputAsked(configBuilt: ConfigurationBuilder, name: string, description: string, socket: WebSocket): Promise<{ [key: string]: number | boolean | string }> {\r\n const config = configBuilt.build(false);\r\n const id = Math.random().toString(36).substring(7);\r\n if (!socket) {\r\n return {};\r\n }\r\n socket.send(JSON.stringify({\r\n event: 'input-asked',\r\n args: {\r\n config,\r\n name,\r\n description\r\n },\r\n id: id\r\n }));\r\n return await this.waitForResponseFromServer(id);\r\n }\r\n\r\n private registerMessageReceiver() {\r\n this.socket.on('message', async (data: string) => {\r\n const message: WebsocketMessageServer = JSON.parse(data);\r\n switch (message.event) {\r\n case 'config-update':\r\n const result = this.addon.config.updateConfig(message.args);\r\n if (!result[0]) {\r\n this.respondToMessage(message.id!!, { success: false, error: result[1] });\r\n }\r\n else {\r\n this.respondToMessage(message.id!!, { success: true });\r\n }\r\n break \r\n case 'search':\r\n let searchResultEvent = new EventResponse<SearchResult[]>((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));\r\n this.eventEmitter.emit('search', message.args, searchResultEvent);\r\n const searchResult = await this.waitForEventToRespond(searchResultEvent); \r\n console.log(searchResult.data)\r\n this.respondToMessage(message.id!!, searchResult.data);\r\n break\r\n case 'setup':\r\n let setupEvent = new EventResponse<LibraryInfo>((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));\r\n this.eventEmitter.emit('setup', { path: message.args.path, steamAppID: message.args.steamAppID, type: message.args.type, name: message.args.name, usedRealDebrid: message.args.usedRealDebrid, multiPartFiles: message.args.multiPartFiles }, setupEvent);\r\n const interval = setInterval(() => {\r\n if (setupEvent.resolved) {\r\n clearInterval(interval);\r\n return;\r\n }\r\n this.send('defer-update', { \r\n logs: setupEvent.logs,\r\n deferID: message.args.deferID,\r\n progress: setupEvent.progress\r\n } as any);\r\n }, 100);\r\n const setupResult = await this.waitForEventToRespond(setupEvent);\r\n this.respondToMessage(message.id!!, setupResult.data);\r\n break\r\n }\r\n });\r\n }\r\n\r\n private waitForEventToRespond<T>(event: EventResponse<T>): Promise<EventResponse<T>> {\r\n return new Promise((resolve, reject) => {\r\n const dataGet = setInterval(() => {\r\n if (event.resolved) {\r\n resolve(event);\r\n clearTimeout(timeout);\r\n }\r\n }, 5); \r\n\r\n const timeout = setTimeout(() => {\r\n if (event.deffered) {\r\n clearInterval(dataGet);\r\n const interval = setInterval(() => {\r\n if (event.resolved) {\r\n clearInterval(interval);\r\n resolve(event);\r\n }\r\n }, 100);\r\n }\r\n else {\r\n reject('Event did not respond in time');\r\n }\r\n }, 5000)\r\n });\r\n }\r\n\r\n public respondToMessage(messageID: string, response: any) {\r\n this.socket.send(JSON.stringify({\r\n event: 'response',\r\n id: messageID,\r\n args: response\r\n }));\r\n console.log(\"dispatched response to \" + messageID)\r\n }\r\n\r\n public waitForResponseFromServer<T>(messageID: string): Promise<T> {\r\n return new Promise((resolve) => {\r\n const waiter = (data: string) => {\r\n const message: WebsocketMessageClient = JSON.parse(data);\r\n if (message.event !== 'response') {\r\n this.socket.once('message', waiter);\r\n return;\r\n }\r\n console.log(\"received response from \" + messageID)\r\n\r\n if (message.id === messageID) {\r\n resolve(message.args);\r\n }\r\n else {\r\n this.socket.once('message', waiter);\r\n }\r\n }\r\n this.socket.once('message', waiter);\r\n });\r\n }\r\n\r\n public send(event: OGIAddonClientSentEvent, args: Parameters<ClientSentEventTypes[OGIAddonClientSentEvent]>) {\r\n this.socket.send(JSON.stringify({\r\n event,\r\n args\r\n }));\r\n }\r\n\r\n public close() {\r\n this.socket.close();\r\n }\r\n\r\n \r\n}","import z, { ZodError } from \"zod\"\r\n\r\nexport interface ConfigurationFile {\r\n [key: string]: ConfigurationOption\r\n}\r\n\r\nconst configValidation = z.object({\r\n name: z.string().min(1),\r\n displayName: z.string().min(1),\r\n description: z.string().min(1),\r\n})\r\n\r\nexport function isStringOption(option: ConfigurationOption): option is StringOption {\r\n return option.type === 'string';\r\n }\r\n\r\nexport function isNumberOption(option: ConfigurationOption): option is NumberOption {\r\n return option.type === 'number';\r\n}\r\n\r\nexport function isBooleanOption(option: ConfigurationOption): option is BooleanOption {\r\n return option.type === 'boolean';\r\n}\r\n\r\nexport class ConfigurationBuilder {\r\n private options: ConfigurationOption[] = [];\r\n public addNumberOption(option: (option: NumberOption) => NumberOption): ConfigurationBuilder {\r\n let newOption = new NumberOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public addStringOption(option: (option: StringOption) => StringOption) {\r\n let newOption = new StringOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public addBooleanOption(option: (option: BooleanOption) => BooleanOption) {\r\n let newOption = new BooleanOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public build(includeFunctions: boolean): ConfigurationFile {\r\n let config: ConfigurationFile = {};\r\n this.options.forEach(option => {\r\n // remove all functions from the option object\r\n if (!includeFunctions) {\r\n option = JSON.parse(JSON.stringify(option));\r\n const optionData = configValidation.safeParse(option)\r\n if (!optionData.success) {\r\n throw new ZodError(optionData.error.errors)\r\n }\r\n\r\n config[option.name] = option;\r\n }\r\n else {\r\n config[option.name] = option;\r\n }\r\n });\r\n return config;\r\n }\r\n}\r\n\r\nexport type ConfigurationOptionType = 'string' | 'number' | 'boolean' | 'unset'\r\nexport class ConfigurationOption {\r\n public name: string = '';\r\n public defaultValue: unknown = '';\r\n public displayName: string = '';\r\n public description: string = '';\r\n public type: ConfigurationOptionType = 'unset'\r\n \r\n setName(name: string) {\r\n this.name = name;\r\n return this;\r\n }\r\n\r\n setDisplayName(displayName: string) {\r\n this.displayName = displayName;\r\n return this;\r\n }\r\n\r\n setDescription(description: string) {\r\n this.description = description;\r\n return this;\r\n }\r\n\r\n\r\n validate(input: unknown): [ boolean, string ] {\r\n throw new Error('Validation code not implemented. Value: ' + input)\r\n };\r\n}\r\n\r\nexport class StringOption extends ConfigurationOption {\r\n public allowedValues: string[] = [];\r\n public minTextLength: number = 0;\r\n public maxTextLength: number = Number.MAX_SAFE_INTEGER;\r\n public defaultValue: string = '';\r\n public inputType: 'text' | 'file' | 'password' | 'folder' = 'text';\r\n public type: ConfigurationOptionType = 'string'\r\n\r\n setAllowedValues(allowedValues: string[]): this {\r\n this.allowedValues = allowedValues;\r\n return this;\r\n }\r\n\r\n setDefaultValue(defaultValue: string): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n setMinTextLength(minTextLength: number): this {\r\n this.minTextLength = minTextLength;\r\n return this;\r\n }\r\n\r\n setMaxTextLength(maxTextLength: number): this {\r\n this.maxTextLength = maxTextLength;\r\n return this;\r\n }\r\n\r\n setInputType(inputType: 'text' | 'file' | 'password' | 'folder'): this {\r\n this.inputType = inputType;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (typeof input !== 'string') {\r\n return [ false, 'Input is not a string' ];\r\n }\r\n if (this.allowedValues.length === 0 && input.length !== 0)\r\n return [ true, '' ];\r\n if (input.length < this.minTextLength || input.length > this.maxTextLength) {\r\n return [ false, 'Input is not within the text length ' + this.minTextLength + ' and ' + this.maxTextLength + ' characters (currently ' + input.length + ' characters)' ];\r\n }\r\n\r\n return [ this.allowedValues.includes(input), 'Input is not an allowed value' ];\r\n }\r\n}\r\n\r\nexport class NumberOption extends ConfigurationOption {\r\n public min: number = 0;\r\n public max: number = Number.MAX_SAFE_INTEGER;\r\n public defaultValue: number = 0;\r\n public type: ConfigurationOptionType = 'number'\r\n public inputType: 'range' | 'number' = 'number';\r\n setMin(min: number): this {\r\n this.min = min;\r\n return this;\r\n }\r\n\r\n setInputType(type: 'range' | 'number'): this {\r\n this.inputType = type;\r\n return this;\r\n }\r\n\r\n setMax(max: number): this {\r\n this.max = max;\r\n return this\r\n }\r\n\r\n setDefaultValue(defaultValue: number): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (isNaN(Number(input))) {\r\n return [ false, 'Input is not a number' ];\r\n }\r\n if (Number(input) < this.min || Number(input) > this.max) {\r\n return [ false, 'Input is not within the range of ' + this.min + ' and ' + this.max ];\r\n }\r\n return [ true, '' ];\r\n }\r\n\r\n}\r\n\r\nexport class BooleanOption extends ConfigurationOption {\r\n public type: ConfigurationOptionType = 'boolean'\r\n public defaultValue: boolean = false;\r\n\r\n setDefaultValue(defaultValue: boolean): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (typeof input !== 'boolean') {\r\n return [ false, 'Input is not a boolean' ];\r\n }\r\n return [ true, '' ];\r\n }\r\n\r\n}","import { ConfigurationFile, ConfigurationBuilder, BooleanOption, ConfigurationOption, ConfigurationOptionType, NumberOption, StringOption, isBooleanOption, isNumberOption, isStringOption } from \"./ConfigurationBuilder\";\r\n\r\ninterface DefiniteConfig {\r\n [key: string]: string | number | boolean;\r\n}\r\nexport class Configuration {\r\n readonly storedConfigTemplate: ConfigurationFile;\r\n definiteConfig: DefiniteConfig = {};\r\n constructor(configTemplate: ConfigurationFile) {\r\n this.storedConfigTemplate = configTemplate;\r\n }\r\n\r\n updateConfig(config: DefiniteConfig, validate: boolean = true): [ boolean, { [key: string]: string } ] {\r\n this.definiteConfig = config;\r\n if (validate) {\r\n const result = this.validateConfig();\r\n return result;\r\n }\r\n return [ true, {} ];\r\n }\r\n // provides falsey or truthy value, and an error message if falsey\r\n private validateConfig(): [ boolean, { [key: string]: string } ] {\r\n const erroredKeys = new Map<string, string>();\r\n for (const key in this.storedConfigTemplate) {\r\n if (this.definiteConfig[key] === null || this.definiteConfig[key] === undefined) {\r\n console.warn('Option ' + key + ' is not defined. Using default value Value: ' + this.definiteConfig[key]);\r\n this.definiteConfig[key] = this.storedConfigTemplate[key].defaultValue as string | number | boolean;\r\n }\r\n if (this.storedConfigTemplate[key].type !== typeof this.definiteConfig[key]) {\r\n throw new Error('Option ' + key + ' is not of the correct type');\r\n }\r\n\r\n const result = this.storedConfigTemplate[key].validate(this.definiteConfig[key]);\r\n if (!result[0]) {\r\n erroredKeys.set(key, result[1]);\r\n }\r\n }\r\n\r\n for (const key in this.definiteConfig) {\r\n if (!this.storedConfigTemplate[key]) {\r\n throw new Error('Option ' + key + ' is not defined in the configuration template');\r\n }\r\n }\r\n\r\n if (erroredKeys.size > 0) {\r\n return [ false, Object.fromEntries(erroredKeys) ];\r\n }\r\n\r\n return [ true, Object.fromEntries(erroredKeys) ];\r\n }\r\n\r\n getStringValue(optionName: string): string {\r\n if (!this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'string') {\r\n throw new Error('Option ' + optionName + ' is not a string');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n\r\n getNumberValue(optionName: string): number {\r\n if (!this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'number') {\r\n throw new Error('Option ' + optionName + ' is not a number');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n\r\n getBooleanValue(optionName: string): boolean {\r\n if (this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'boolean') {\r\n throw new Error('Option ' + optionName + ' is not a boolean');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n}\r\n\r\nexport { ConfigurationFile, ConfigurationBuilder, BooleanOption, ConfigurationOption, ConfigurationOptionType, NumberOption, StringOption, isBooleanOption, isNumberOption, isStringOption };","import { ConfigurationBuilder } from \"./main\";\r\n\r\nexport default class EventResponse<T> {\r\n data: T | undefined = undefined;\r\n deffered: boolean = false;\r\n resolved: boolean = false;\r\n progress: number = 0;\r\n logs: string[] = [];\r\n onInputAsked?: (screen: ConfigurationBuilder, name: string, description: string) => Promise<{ [key: string]: boolean | string | number }>;\r\n\r\n constructor(onInputAsked?: (screen: ConfigurationBuilder, name: string, description: string) => Promise<{ [key: string]: boolean | string | number }>) {\r\n this.onInputAsked = onInputAsked;\r\n }\r\n \r\n\r\n public defer() {\r\n this.deffered = true;\r\n }\r\n\r\n public resolve(data: T) {\r\n this.resolved = true;\r\n this.data = data;\r\n }\r\n\r\n public complete() {\r\n this.resolved = true;\r\n }\r\n\r\n public log(message: string) {\r\n this.logs.push(message);\r\n }\r\n\r\n public async askForInput(name: string, description: string, screen: ConfigurationBuilder) {\r\n if (!this.onInputAsked) {\r\n throw new Error('No input asked callback');\r\n }\r\n return await this.onInputAsked(screen, name, description);\r\n }\r\n\r\n \r\n}"],"mappings":"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","names":["z","events","ws"]}
|
package/build/main.d.cts
CHANGED
|
@@ -6,8 +6,8 @@ import EventResponse from './EventResponse.cjs';
|
|
|
6
6
|
import { SearchResult } from './SearchEngine.cjs';
|
|
7
7
|
|
|
8
8
|
type OGIAddonEvent = 'connect' | 'disconnect' | 'configure' | 'authenticate' | 'search' | 'setup';
|
|
9
|
-
type OGIAddonClientSentEvent = 'response' | 'authenticate' | 'configure' | 'defer-update' | 'notification';
|
|
10
|
-
type OGIAddonServerSentEvent = 'authenticate' | 'configure' | 'config-update' | 'search' | 'setup';
|
|
9
|
+
type OGIAddonClientSentEvent = 'response' | 'authenticate' | 'configure' | 'defer-update' | 'notification' | 'input-asked';
|
|
10
|
+
type OGIAddonServerSentEvent = 'authenticate' | 'configure' | 'config-update' | 'search' | 'setup' | 'response';
|
|
11
11
|
|
|
12
12
|
interface ClientSentEventTypes {
|
|
13
13
|
response: any;
|
|
@@ -18,6 +18,7 @@ interface ClientSentEventTypes {
|
|
|
18
18
|
progress: number;
|
|
19
19
|
};
|
|
20
20
|
notification: Notification;
|
|
21
|
+
'input-asked': ConfigurationBuilder;
|
|
21
22
|
}
|
|
22
23
|
interface EventListenerTypes {
|
|
23
24
|
connect: (socket: ws) => void;
|
|
@@ -25,7 +26,10 @@ interface EventListenerTypes {
|
|
|
25
26
|
configure: (config: ConfigurationBuilder) => ConfigurationBuilder;
|
|
26
27
|
response: (response: any) => void;
|
|
27
28
|
authenticate: (config: any) => void;
|
|
28
|
-
search: (query:
|
|
29
|
+
search: (query: {
|
|
30
|
+
type: 'steamapp';
|
|
31
|
+
text: string;
|
|
32
|
+
}, event: EventResponse<SearchResult[]>) => void;
|
|
29
33
|
setup: (data: {
|
|
30
34
|
path: string;
|
|
31
35
|
type: 'direct' | 'torrent' | 'magnet';
|
|
@@ -35,7 +39,8 @@ interface EventListenerTypes {
|
|
|
35
39
|
name: string;
|
|
36
40
|
downloadURL: string;
|
|
37
41
|
}[];
|
|
38
|
-
|
|
42
|
+
steamAppID: number;
|
|
43
|
+
}, event: EventResponse<LibraryInfo>) => void;
|
|
39
44
|
}
|
|
40
45
|
interface WebsocketMessageClient {
|
|
41
46
|
event: OGIAddonClientSentEvent;
|
|
@@ -65,6 +70,15 @@ declare class OGIAddon {
|
|
|
65
70
|
emit<T extends OGIAddonEvent>(event: T, ...args: Parameters<EventListenerTypes[T]>): void;
|
|
66
71
|
notify(notification: Notification): void;
|
|
67
72
|
}
|
|
73
|
+
interface LibraryInfo {
|
|
74
|
+
name: string;
|
|
75
|
+
version: string;
|
|
76
|
+
cwd: string;
|
|
77
|
+
steamAppID: number;
|
|
78
|
+
launchExecutable: string;
|
|
79
|
+
launchArguments?: string;
|
|
80
|
+
capsuleImage: string;
|
|
81
|
+
}
|
|
68
82
|
interface Notification {
|
|
69
83
|
type: 'warning' | 'error' | 'info' | 'success';
|
|
70
84
|
message: string;
|
|
@@ -75,11 +89,13 @@ declare class OGIAddonWSListener {
|
|
|
75
89
|
eventEmitter: events.EventEmitter;
|
|
76
90
|
addon: OGIAddon;
|
|
77
91
|
constructor(ogiAddon: OGIAddon, eventEmitter: events.EventEmitter);
|
|
92
|
+
private userInputAsked;
|
|
78
93
|
private registerMessageReceiver;
|
|
79
94
|
private waitForEventToRespond;
|
|
80
95
|
respondToMessage(messageID: string, response: any): void;
|
|
96
|
+
waitForResponseFromServer<T>(messageID: string): Promise<T>;
|
|
81
97
|
send(event: OGIAddonClientSentEvent, args: Parameters<ClientSentEventTypes[OGIAddonClientSentEvent]>): void;
|
|
82
98
|
close(): void;
|
|
83
99
|
}
|
|
84
100
|
|
|
85
|
-
export { type ClientSentEventTypes, Configuration, ConfigurationBuilder, type EventListenerTypes, EventResponse, type OGIAddonClientSentEvent, type OGIAddonConfiguration, type OGIAddonEvent, type OGIAddonServerSentEvent, SearchResult, type WebsocketMessageClient, type WebsocketMessageServer, OGIAddon as default };
|
|
101
|
+
export { type ClientSentEventTypes, Configuration, ConfigurationBuilder, type EventListenerTypes, EventResponse, type LibraryInfo, type OGIAddonClientSentEvent, type OGIAddonConfiguration, type OGIAddonEvent, type OGIAddonServerSentEvent, SearchResult, type WebsocketMessageClient, type WebsocketMessageServer, OGIAddon as default };
|
package/build/main.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ import EventResponse from './EventResponse.js';
|
|
|
6
6
|
import { SearchResult } from './SearchEngine.js';
|
|
7
7
|
|
|
8
8
|
type OGIAddonEvent = 'connect' | 'disconnect' | 'configure' | 'authenticate' | 'search' | 'setup';
|
|
9
|
-
type OGIAddonClientSentEvent = 'response' | 'authenticate' | 'configure' | 'defer-update' | 'notification';
|
|
10
|
-
type OGIAddonServerSentEvent = 'authenticate' | 'configure' | 'config-update' | 'search' | 'setup';
|
|
9
|
+
type OGIAddonClientSentEvent = 'response' | 'authenticate' | 'configure' | 'defer-update' | 'notification' | 'input-asked';
|
|
10
|
+
type OGIAddonServerSentEvent = 'authenticate' | 'configure' | 'config-update' | 'search' | 'setup' | 'response';
|
|
11
11
|
|
|
12
12
|
interface ClientSentEventTypes {
|
|
13
13
|
response: any;
|
|
@@ -18,6 +18,7 @@ interface ClientSentEventTypes {
|
|
|
18
18
|
progress: number;
|
|
19
19
|
};
|
|
20
20
|
notification: Notification;
|
|
21
|
+
'input-asked': ConfigurationBuilder;
|
|
21
22
|
}
|
|
22
23
|
interface EventListenerTypes {
|
|
23
24
|
connect: (socket: ws) => void;
|
|
@@ -25,7 +26,10 @@ interface EventListenerTypes {
|
|
|
25
26
|
configure: (config: ConfigurationBuilder) => ConfigurationBuilder;
|
|
26
27
|
response: (response: any) => void;
|
|
27
28
|
authenticate: (config: any) => void;
|
|
28
|
-
search: (query:
|
|
29
|
+
search: (query: {
|
|
30
|
+
type: 'steamapp';
|
|
31
|
+
text: string;
|
|
32
|
+
}, event: EventResponse<SearchResult[]>) => void;
|
|
29
33
|
setup: (data: {
|
|
30
34
|
path: string;
|
|
31
35
|
type: 'direct' | 'torrent' | 'magnet';
|
|
@@ -35,7 +39,8 @@ interface EventListenerTypes {
|
|
|
35
39
|
name: string;
|
|
36
40
|
downloadURL: string;
|
|
37
41
|
}[];
|
|
38
|
-
|
|
42
|
+
steamAppID: number;
|
|
43
|
+
}, event: EventResponse<LibraryInfo>) => void;
|
|
39
44
|
}
|
|
40
45
|
interface WebsocketMessageClient {
|
|
41
46
|
event: OGIAddonClientSentEvent;
|
|
@@ -65,6 +70,15 @@ declare class OGIAddon {
|
|
|
65
70
|
emit<T extends OGIAddonEvent>(event: T, ...args: Parameters<EventListenerTypes[T]>): void;
|
|
66
71
|
notify(notification: Notification): void;
|
|
67
72
|
}
|
|
73
|
+
interface LibraryInfo {
|
|
74
|
+
name: string;
|
|
75
|
+
version: string;
|
|
76
|
+
cwd: string;
|
|
77
|
+
steamAppID: number;
|
|
78
|
+
launchExecutable: string;
|
|
79
|
+
launchArguments?: string;
|
|
80
|
+
capsuleImage: string;
|
|
81
|
+
}
|
|
68
82
|
interface Notification {
|
|
69
83
|
type: 'warning' | 'error' | 'info' | 'success';
|
|
70
84
|
message: string;
|
|
@@ -75,11 +89,13 @@ declare class OGIAddonWSListener {
|
|
|
75
89
|
eventEmitter: events.EventEmitter;
|
|
76
90
|
addon: OGIAddon;
|
|
77
91
|
constructor(ogiAddon: OGIAddon, eventEmitter: events.EventEmitter);
|
|
92
|
+
private userInputAsked;
|
|
78
93
|
private registerMessageReceiver;
|
|
79
94
|
private waitForEventToRespond;
|
|
80
95
|
respondToMessage(messageID: string, response: any): void;
|
|
96
|
+
waitForResponseFromServer<T>(messageID: string): Promise<T>;
|
|
81
97
|
send(event: OGIAddonClientSentEvent, args: Parameters<ClientSentEventTypes[OGIAddonClientSentEvent]>): void;
|
|
82
98
|
close(): void;
|
|
83
99
|
}
|
|
84
100
|
|
|
85
|
-
export { type ClientSentEventTypes, Configuration, ConfigurationBuilder, type EventListenerTypes, EventResponse, type OGIAddonClientSentEvent, type OGIAddonConfiguration, type OGIAddonEvent, type OGIAddonServerSentEvent, SearchResult, type WebsocketMessageClient, type WebsocketMessageServer, OGIAddon as default };
|
|
101
|
+
export { type ClientSentEventTypes, Configuration, ConfigurationBuilder, type EventListenerTypes, EventResponse, type LibraryInfo, type OGIAddonClientSentEvent, type OGIAddonConfiguration, type OGIAddonEvent, type OGIAddonServerSentEvent, SearchResult, type WebsocketMessageClient, type WebsocketMessageServer, OGIAddon as default };
|
package/build/main.js
CHANGED
|
@@ -73,6 +73,7 @@ var StringOption = class extends ConfigurationOption {
|
|
|
73
73
|
minTextLength = 0;
|
|
74
74
|
maxTextLength = Number.MAX_SAFE_INTEGER;
|
|
75
75
|
defaultValue = "";
|
|
76
|
+
inputType = "text";
|
|
76
77
|
type = "string";
|
|
77
78
|
setAllowedValues(allowedValues) {
|
|
78
79
|
this.allowedValues = allowedValues;
|
|
@@ -90,6 +91,10 @@ var StringOption = class extends ConfigurationOption {
|
|
|
90
91
|
this.maxTextLength = maxTextLength;
|
|
91
92
|
return this;
|
|
92
93
|
}
|
|
94
|
+
setInputType(inputType) {
|
|
95
|
+
this.inputType = inputType;
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
93
98
|
validate(input) {
|
|
94
99
|
if (typeof input !== "string") {
|
|
95
100
|
return [false, "Input is not a string"];
|
|
@@ -226,6 +231,10 @@ var EventResponse = class {
|
|
|
226
231
|
resolved = false;
|
|
227
232
|
progress = 0;
|
|
228
233
|
logs = [];
|
|
234
|
+
onInputAsked;
|
|
235
|
+
constructor(onInputAsked) {
|
|
236
|
+
this.onInputAsked = onInputAsked;
|
|
237
|
+
}
|
|
229
238
|
defer() {
|
|
230
239
|
this.deffered = true;
|
|
231
240
|
}
|
|
@@ -239,10 +248,17 @@ var EventResponse = class {
|
|
|
239
248
|
log(message) {
|
|
240
249
|
this.logs.push(message);
|
|
241
250
|
}
|
|
251
|
+
async askForInput(name, description, screen) {
|
|
252
|
+
if (!this.onInputAsked) {
|
|
253
|
+
throw new Error("No input asked callback");
|
|
254
|
+
}
|
|
255
|
+
return await this.onInputAsked(screen, name, description);
|
|
256
|
+
}
|
|
242
257
|
};
|
|
243
258
|
|
|
244
259
|
// src/main.ts
|
|
245
260
|
var defaultPort = 7654;
|
|
261
|
+
var version = process.env.npm_package_version;
|
|
246
262
|
var OGIAddon = class {
|
|
247
263
|
eventEmitter = new events.EventEmitter();
|
|
248
264
|
addonWSListener;
|
|
@@ -275,11 +291,13 @@ var OGIAddonWSListener = class {
|
|
|
275
291
|
this.socket = new ws("ws://localhost:" + defaultPort);
|
|
276
292
|
this.socket.on("open", () => {
|
|
277
293
|
console.log("Connected to OGI Addon Server");
|
|
294
|
+
console.log("OGI Addon Server Version:", version);
|
|
278
295
|
this.socket.send(JSON.stringify({
|
|
279
296
|
event: "authenticate",
|
|
280
297
|
args: {
|
|
281
298
|
...this.addon.addonInfo,
|
|
282
|
-
secret: process.argv[process.argv.length - 1].split("=")[1]
|
|
299
|
+
secret: process.argv[process.argv.length - 1].split("=")[1],
|
|
300
|
+
ogiVersion: version
|
|
283
301
|
}
|
|
284
302
|
}));
|
|
285
303
|
this.eventEmitter.emit("connect");
|
|
@@ -304,10 +322,28 @@ var OGIAddonWSListener = class {
|
|
|
304
322
|
}
|
|
305
323
|
this.eventEmitter.emit("disconnect", reason);
|
|
306
324
|
console.log("Disconnected from OGI Addon Server");
|
|
325
|
+
console.log(reason.toString());
|
|
307
326
|
this.socket.close();
|
|
308
327
|
});
|
|
309
328
|
this.registerMessageReceiver();
|
|
310
329
|
}
|
|
330
|
+
async userInputAsked(configBuilt, name, description, socket) {
|
|
331
|
+
const config = configBuilt.build(false);
|
|
332
|
+
const id = Math.random().toString(36).substring(7);
|
|
333
|
+
if (!socket) {
|
|
334
|
+
return {};
|
|
335
|
+
}
|
|
336
|
+
socket.send(JSON.stringify({
|
|
337
|
+
event: "input-asked",
|
|
338
|
+
args: {
|
|
339
|
+
config,
|
|
340
|
+
name,
|
|
341
|
+
description
|
|
342
|
+
},
|
|
343
|
+
id
|
|
344
|
+
}));
|
|
345
|
+
return await this.waitForResponseFromServer(id);
|
|
346
|
+
}
|
|
311
347
|
registerMessageReceiver() {
|
|
312
348
|
this.socket.on("message", async (data) => {
|
|
313
349
|
const message = JSON.parse(data);
|
|
@@ -321,15 +357,15 @@ var OGIAddonWSListener = class {
|
|
|
321
357
|
}
|
|
322
358
|
break;
|
|
323
359
|
case "search":
|
|
324
|
-
let searchResultEvent = new EventResponse();
|
|
360
|
+
let searchResultEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
|
|
325
361
|
this.eventEmitter.emit("search", message.args, searchResultEvent);
|
|
326
362
|
const searchResult = await this.waitForEventToRespond(searchResultEvent);
|
|
327
363
|
console.log(searchResult.data);
|
|
328
364
|
this.respondToMessage(message.id, searchResult.data);
|
|
329
365
|
break;
|
|
330
366
|
case "setup":
|
|
331
|
-
let setupEvent = new EventResponse();
|
|
332
|
-
this.eventEmitter.emit("setup", { path: message.args.path, type: message.args.type, name: message.args.name, usedRealDebrid: message.args.usedRealDebrid, multiPartFiles: message.args.multiPartFiles }, setupEvent);
|
|
367
|
+
let setupEvent = new EventResponse((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));
|
|
368
|
+
this.eventEmitter.emit("setup", { path: message.args.path, steamAppID: message.args.steamAppID, type: message.args.type, name: message.args.name, usedRealDebrid: message.args.usedRealDebrid, multiPartFiles: message.args.multiPartFiles }, setupEvent);
|
|
333
369
|
const interval = setInterval(() => {
|
|
334
370
|
if (setupEvent.resolved) {
|
|
335
371
|
clearInterval(interval);
|
|
@@ -378,6 +414,24 @@ var OGIAddonWSListener = class {
|
|
|
378
414
|
}));
|
|
379
415
|
console.log("dispatched response to " + messageID);
|
|
380
416
|
}
|
|
417
|
+
waitForResponseFromServer(messageID) {
|
|
418
|
+
return new Promise((resolve) => {
|
|
419
|
+
const waiter = (data) => {
|
|
420
|
+
const message = JSON.parse(data);
|
|
421
|
+
if (message.event !== "response") {
|
|
422
|
+
this.socket.once("message", waiter);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
console.log("received response from " + messageID);
|
|
426
|
+
if (message.id === messageID) {
|
|
427
|
+
resolve(message.args);
|
|
428
|
+
} else {
|
|
429
|
+
this.socket.once("message", waiter);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
this.socket.once("message", waiter);
|
|
433
|
+
});
|
|
434
|
+
}
|
|
381
435
|
send(event, args) {
|
|
382
436
|
this.socket.send(JSON.stringify({
|
|
383
437
|
event,
|
package/build/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/main.ts","../src/config/ConfigurationBuilder.ts","../src/config/Configuration.ts","../src/EventResponse.ts"],"sourcesContent":["import ws, { WebSocket } from 'ws';\r\nimport events from 'node:events';\r\nimport { ConfigurationBuilder, ConfigurationFile } from './config/ConfigurationBuilder';\r\nimport { Configuration } from './config/Configuration';\r\nimport EventResponse from './EventResponse';\r\nimport { SearchResult } from './SearchEngine';\r\n\r\nexport type OGIAddonEvent = 'connect' | 'disconnect' | 'configure' | 'authenticate' | 'search' | 'setup';\r\nexport type OGIAddonClientSentEvent = 'response' | 'authenticate' | 'configure' | 'defer-update' | 'notification';\r\n\r\nexport type OGIAddonServerSentEvent = 'authenticate' | 'configure' | 'config-update' | 'search' | 'setup';\r\nexport { ConfigurationBuilder, Configuration, EventResponse, SearchResult };\r\nconst defaultPort = 7654;\r\n\r\nexport interface ClientSentEventTypes {\r\n response: any;\r\n authenticate: any;\r\n configure: ConfigurationFile;\r\n 'defer-update': {\r\n logs: string[], \r\n progress: number\r\n };\r\n notification: Notification;\r\n}\r\n\r\nexport interface EventListenerTypes {\r\n connect: (socket: ws) => void;\r\n disconnect: (reason: string) => void;\r\n configure: (config: ConfigurationBuilder) => ConfigurationBuilder;\r\n response: (response: any) => void;\r\n authenticate: (config: any) => void;\r\n search: (query: string, event: EventResponse<SearchResult[]>) => void;\r\n setup: (\r\n data: { \r\n path: string, \r\n type: 'direct' | 'torrent' | 'magnet',\r\n name: string,\r\n usedRealDebrid: boolean, \r\n multiPartFiles?: {\r\n name: string,\r\n downloadURL: string\r\n }[],\r\n }, event: EventResponse<undefined | null>\r\n ) => void;\r\n}\r\n\r\nexport interface WebsocketMessageClient {\r\n event: OGIAddonClientSentEvent;\r\n id?: string;\r\n args: any;\r\n}\r\nexport interface WebsocketMessageServer {\r\n event: OGIAddonServerSentEvent;\r\n id?: string;\r\n args: any;\r\n}\r\nexport interface OGIAddonConfiguration {\r\n name: string;\r\n id: string;\r\n description: string;\r\n version: string;\r\n\r\n author: string;\r\n repository: string;\r\n}\r\nexport default class OGIAddon {\r\n public eventEmitter = new events.EventEmitter();\r\n public addonWSListener: OGIAddonWSListener;\r\n public addonInfo: OGIAddonConfiguration;\r\n public config: Configuration = new Configuration({});\r\n\r\n constructor(addonInfo: OGIAddonConfiguration) {\r\n this.addonInfo = addonInfo;\r\n this.addonWSListener = new OGIAddonWSListener(this, this.eventEmitter);\r\n }\r\n \r\n public on<T extends OGIAddonEvent>(event: T, listener: EventListenerTypes[T]) {\r\n this.eventEmitter.on(event, listener);\r\n }\r\n\r\n public emit<T extends OGIAddonEvent>(event: T, ...args: Parameters<EventListenerTypes[T]>) {\r\n this.eventEmitter.emit(event, ...args);\r\n }\r\n\r\n public notify(notification: Notification) {\r\n this.addonWSListener.send('notification', [ notification ]);\r\n }\r\n}\r\ninterface Notification {\r\n type: 'warning' | 'error' | 'info' | 'success';\r\n message: string;\r\n id: string\r\n}\r\nclass OGIAddonWSListener {\r\n private socket: WebSocket;\r\n public eventEmitter: events.EventEmitter;\r\n public addon: OGIAddon;\r\n\r\n constructor(ogiAddon: OGIAddon, eventEmitter: events.EventEmitter) {\r\n if (process.argv[process.argv.length - 1].split('=')[0] !== '--addonSecret') {\r\n throw new Error('No secret provided. This usually happens because the addon was not started by the OGI Addon Server.');\r\n }\r\n this.addon = ogiAddon;\r\n this.eventEmitter = eventEmitter;\r\n this.socket = new ws('ws://localhost:' + defaultPort);\r\n this.socket.on('open', () => {\r\n console.log('Connected to OGI Addon Server');\r\n\r\n // Authenticate with OGI Addon Server\r\n this.socket.send(JSON.stringify({\r\n event: 'authenticate',\r\n args: {\r\n ...this.addon.addonInfo,\r\n secret: process.argv[process.argv.length - 1].split('=')[1]\r\n }\r\n }));\r\n\r\n this.eventEmitter.emit('connect');\r\n\r\n // send a configuration request\r\n let configBuilder = new ConfigurationBuilder();\r\n this.eventEmitter.emit('configure', configBuilder);\r\n \r\n this.socket.send(JSON.stringify({\r\n event: 'configure',\r\n args: configBuilder.build(false) \r\n }));\r\n this.addon.config = new Configuration(configBuilder.build(true));\r\n });\r\n\r\n this.socket.on('error', (error) => {\r\n if (error.message.includes('Failed to connect')) {\r\n throw new Error('OGI Addon Server is not running/is unreachable. Please start the server and try again.');\r\n }\r\n console.error('An error occurred:', error);\r\n })\r\n\r\n this.socket.on('close', (code, reason) => {\r\n if (code === 1008) {\r\n console.error('Authentication failed:', reason);\r\n return;\r\n }\r\n this.eventEmitter.emit('disconnect', reason);\r\n console.log(\"Disconnected from OGI Addon Server\")\r\n this.socket.close();\r\n });\r\n\r\n this.registerMessageReceiver();\r\n }\r\n\r\n private registerMessageReceiver() {\r\n this.socket.on('message', async (data: string) => {\r\n const message: WebsocketMessageServer = JSON.parse(data);\r\n switch (message.event) {\r\n case 'config-update':\r\n const result = this.addon.config.updateConfig(message.args);\r\n if (!result[0]) {\r\n this.respondToMessage(message.id!!, { success: false, error: result[1] });\r\n }\r\n else {\r\n this.respondToMessage(message.id!!, { success: true });\r\n }\r\n break \r\n case 'search':\r\n let searchResultEvent = new EventResponse<SearchResult[]>();\r\n this.eventEmitter.emit('search', message.args, searchResultEvent);\r\n const searchResult = await this.waitForEventToRespond(searchResultEvent); \r\n console.log(searchResult.data)\r\n this.respondToMessage(message.id!!, searchResult.data);\r\n break\r\n case 'setup':\r\n let setupEvent = new EventResponse<undefined | null>();\r\n this.eventEmitter.emit('setup', { path: message.args.path, type: message.args.type, name: message.args.name, usedRealDebrid: message.args.usedRealDebrid, multiPartFiles: message.args.multiPartFiles }, setupEvent);\r\n const interval = setInterval(() => {\r\n if (setupEvent.resolved) {\r\n clearInterval(interval);\r\n return;\r\n }\r\n this.send('defer-update', { \r\n logs: setupEvent.logs,\r\n deferID: message.args.deferID,\r\n progress: setupEvent.progress\r\n } as any);\r\n }, 100);\r\n const setupResult = await this.waitForEventToRespond(setupEvent);\r\n this.respondToMessage(message.id!!, setupResult.data);\r\n break\r\n }\r\n });\r\n }\r\n\r\n private waitForEventToRespond<T>(event: EventResponse<T>): Promise<EventResponse<T>> {\r\n return new Promise((resolve, reject) => {\r\n const dataGet = setInterval(() => {\r\n if (event.resolved) {\r\n resolve(event);\r\n clearTimeout(timeout);\r\n }\r\n }, 5); \r\n\r\n const timeout = setTimeout(() => {\r\n if (event.deffered) {\r\n clearInterval(dataGet);\r\n const interval = setInterval(() => {\r\n if (event.resolved) {\r\n clearInterval(interval);\r\n resolve(event);\r\n }\r\n }, 100);\r\n }\r\n else {\r\n reject('Event did not respond in time');\r\n }\r\n }, 5000)\r\n });\r\n }\r\n\r\n public respondToMessage(messageID: string, response: any) {\r\n this.socket.send(JSON.stringify({\r\n event: 'response',\r\n id: messageID,\r\n args: response\r\n }));\r\n console.log(\"dispatched response to \" + messageID)\r\n }\r\n\r\n public send(event: OGIAddonClientSentEvent, args: Parameters<ClientSentEventTypes[OGIAddonClientSentEvent]>) {\r\n this.socket.send(JSON.stringify({\r\n event,\r\n args\r\n }));\r\n }\r\n\r\n public close() {\r\n this.socket.close();\r\n }\r\n\r\n \r\n}","import z, { ZodError } from \"zod\"\r\n\r\nexport interface ConfigurationFile {\r\n [key: string]: ConfigurationOption\r\n}\r\n\r\nconst configValidation = z.object({\r\n name: z.string().min(1),\r\n displayName: z.string().min(1),\r\n description: z.string().min(1),\r\n})\r\n\r\nexport function isStringOption(option: ConfigurationOption): option is StringOption {\r\n return option.type === 'string';\r\n }\r\n\r\nexport function isNumberOption(option: ConfigurationOption): option is NumberOption {\r\n return option.type === 'number';\r\n}\r\n\r\nexport function isBooleanOption(option: ConfigurationOption): option is BooleanOption {\r\n return option.type === 'boolean';\r\n}\r\n\r\nexport class ConfigurationBuilder {\r\n private options: ConfigurationOption[] = [];\r\n public addNumberOption(option: (option: NumberOption) => NumberOption): ConfigurationBuilder {\r\n let newOption = new NumberOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public addStringOption(option: (option: StringOption) => StringOption) {\r\n let newOption = new StringOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public addBooleanOption(option: (option: BooleanOption) => BooleanOption) {\r\n let newOption = new BooleanOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public build(includeFunctions: boolean): ConfigurationFile {\r\n let config: ConfigurationFile = {};\r\n this.options.forEach(option => {\r\n // remove all functions from the option object\r\n if (!includeFunctions) {\r\n option = JSON.parse(JSON.stringify(option));\r\n const optionData = configValidation.safeParse(option)\r\n if (!optionData.success) {\r\n throw new ZodError(optionData.error.errors)\r\n }\r\n\r\n config[option.name] = option;\r\n }\r\n else {\r\n config[option.name] = option;\r\n }\r\n });\r\n return config;\r\n }\r\n}\r\n\r\nexport type ConfigurationOptionType = 'string' | 'number' | 'boolean' | 'unset'\r\nexport class ConfigurationOption {\r\n public name: string = '';\r\n public defaultValue: unknown = '';\r\n public displayName: string = '';\r\n public description: string = '';\r\n public type: ConfigurationOptionType = 'unset'\r\n \r\n setName(name: string) {\r\n this.name = name;\r\n return this;\r\n }\r\n\r\n setDisplayName(displayName: string) {\r\n this.displayName = displayName;\r\n return this;\r\n }\r\n\r\n setDescription(description: string) {\r\n this.description = description;\r\n return this;\r\n }\r\n\r\n\r\n validate(input: unknown): [ boolean, string ] {\r\n throw new Error('Validation code not implemented. Value: ' + input)\r\n };\r\n}\r\n\r\nexport class StringOption extends ConfigurationOption {\r\n public allowedValues: string[] = [];\r\n public minTextLength: number = 0;\r\n public maxTextLength: number = Number.MAX_SAFE_INTEGER;\r\n public defaultValue: string = '';\r\n public type: ConfigurationOptionType = 'string'\r\n\r\n setAllowedValues(allowedValues: string[]): this {\r\n this.allowedValues = allowedValues;\r\n return this;\r\n }\r\n\r\n setDefaultValue(defaultValue: string): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n setMinTextLength(minTextLength: number): this {\r\n this.minTextLength = minTextLength;\r\n return this;\r\n }\r\n\r\n setMaxTextLength(maxTextLength: number): this {\r\n this.maxTextLength = maxTextLength;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (typeof input !== 'string') {\r\n return [ false, 'Input is not a string' ];\r\n }\r\n if (this.allowedValues.length === 0 && input.length !== 0)\r\n return [ true, '' ];\r\n if (input.length < this.minTextLength || input.length > this.maxTextLength) {\r\n return [ false, 'Input is not within the text length ' + this.minTextLength + ' and ' + this.maxTextLength + ' characters (currently ' + input.length + ' characters)' ];\r\n }\r\n\r\n return [ this.allowedValues.includes(input), 'Input is not an allowed value' ];\r\n }\r\n}\r\n\r\nexport class NumberOption extends ConfigurationOption {\r\n public min: number = 0;\r\n public max: number = Number.MAX_SAFE_INTEGER;\r\n public defaultValue: number = 0;\r\n public type: ConfigurationOptionType = 'number'\r\n public inputType: 'range' | 'number' = 'number';\r\n setMin(min: number): this {\r\n this.min = min;\r\n return this;\r\n }\r\n\r\n setInputType(type: 'range' | 'number'): this {\r\n this.inputType = type;\r\n return this;\r\n }\r\n\r\n setMax(max: number): this {\r\n this.max = max;\r\n return this\r\n }\r\n\r\n setDefaultValue(defaultValue: number): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (isNaN(Number(input))) {\r\n return [ false, 'Input is not a number' ];\r\n }\r\n if (Number(input) < this.min || Number(input) > this.max) {\r\n return [ false, 'Input is not within the range of ' + this.min + ' and ' + this.max ];\r\n }\r\n return [ true, '' ];\r\n }\r\n\r\n}\r\n\r\nexport class BooleanOption extends ConfigurationOption {\r\n public type: ConfigurationOptionType = 'boolean'\r\n public defaultValue: boolean = false;\r\n\r\n setDefaultValue(defaultValue: boolean): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (typeof input !== 'boolean') {\r\n return [ false, 'Input is not a boolean' ];\r\n }\r\n return [ true, '' ];\r\n }\r\n\r\n}","import { ConfigurationFile, ConfigurationBuilder, BooleanOption, ConfigurationOption, ConfigurationOptionType, NumberOption, StringOption, isBooleanOption, isNumberOption, isStringOption } from \"./ConfigurationBuilder\";\r\n\r\ninterface DefiniteConfig {\r\n [key: string]: string | number | boolean;\r\n}\r\nexport class Configuration {\r\n readonly storedConfigTemplate: ConfigurationFile;\r\n definiteConfig: DefiniteConfig = {};\r\n constructor(configTemplate: ConfigurationFile) {\r\n this.storedConfigTemplate = configTemplate;\r\n }\r\n\r\n updateConfig(config: DefiniteConfig, validate: boolean = true): [ boolean, { [key: string]: string } ] {\r\n this.definiteConfig = config;\r\n if (validate) {\r\n const result = this.validateConfig();\r\n return result;\r\n }\r\n return [ true, {} ];\r\n }\r\n // provides falsey or truthy value, and an error message if falsey\r\n private validateConfig(): [ boolean, { [key: string]: string } ] {\r\n const erroredKeys = new Map<string, string>();\r\n for (const key in this.storedConfigTemplate) {\r\n if (this.definiteConfig[key] === null || this.definiteConfig[key] === undefined) {\r\n console.warn('Option ' + key + ' is not defined. Using default value Value: ' + this.definiteConfig[key]);\r\n this.definiteConfig[key] = this.storedConfigTemplate[key].defaultValue as string | number | boolean;\r\n }\r\n if (this.storedConfigTemplate[key].type !== typeof this.definiteConfig[key]) {\r\n throw new Error('Option ' + key + ' is not of the correct type');\r\n }\r\n\r\n const result = this.storedConfigTemplate[key].validate(this.definiteConfig[key]);\r\n if (!result[0]) {\r\n erroredKeys.set(key, result[1]);\r\n }\r\n }\r\n\r\n for (const key in this.definiteConfig) {\r\n if (!this.storedConfigTemplate[key]) {\r\n throw new Error('Option ' + key + ' is not defined in the configuration template');\r\n }\r\n }\r\n\r\n if (erroredKeys.size > 0) {\r\n return [ false, Object.fromEntries(erroredKeys) ];\r\n }\r\n\r\n return [ true, Object.fromEntries(erroredKeys) ];\r\n }\r\n\r\n getStringValue(optionName: string): string {\r\n if (!this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'string') {\r\n throw new Error('Option ' + optionName + ' is not a string');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n\r\n getNumberValue(optionName: string): number {\r\n if (!this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'number') {\r\n throw new Error('Option ' + optionName + ' is not a number');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n\r\n getBooleanValue(optionName: string): boolean {\r\n if (this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'boolean') {\r\n throw new Error('Option ' + optionName + ' is not a boolean');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n}\r\n\r\nexport { ConfigurationFile, ConfigurationBuilder, BooleanOption, ConfigurationOption, ConfigurationOptionType, NumberOption, StringOption, isBooleanOption, isNumberOption, isStringOption };","export default class EventResponse<T> {\r\n data: T | undefined = undefined;\r\n deffered: boolean = false;\r\n resolved: boolean = false;\r\n progress: number = 0;\r\n logs: string[] = [];\r\n\r\n public defer() {\r\n this.deffered = true;\r\n }\r\n\r\n public resolve(data: T) {\r\n this.resolved = true;\r\n this.data = data;\r\n }\r\n\r\n public complete() {\r\n this.resolved = true;\r\n }\r\n\r\n public log(message: string) {\r\n this.logs.push(message);\r\n }\r\n\r\n \r\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/main.ts","../src/config/ConfigurationBuilder.ts","../src/config/Configuration.ts","../src/EventResponse.ts"],"sourcesContent":["import ws, { WebSocket } from 'ws';\r\nimport events from 'node:events';\r\nimport { ConfigurationBuilder, ConfigurationFile } from './config/ConfigurationBuilder';\r\nimport { Configuration } from './config/Configuration';\r\nimport EventResponse from './EventResponse';\r\nimport { SearchResult } from './SearchEngine';\r\n\r\nexport type OGIAddonEvent = 'connect' | 'disconnect' | 'configure' | 'authenticate' | 'search' | 'setup';\r\nexport type OGIAddonClientSentEvent = 'response' | 'authenticate' | 'configure' | 'defer-update' | 'notification' | 'input-asked';\r\n\r\nexport type OGIAddonServerSentEvent = 'authenticate' | 'configure' | 'config-update' | 'search' | 'setup' | 'response';\r\nexport { ConfigurationBuilder, Configuration, EventResponse, SearchResult };\r\nconst defaultPort = 7654;\r\nconst version = process.env.npm_package_version;\r\n\r\nexport interface ClientSentEventTypes {\r\n response: any;\r\n authenticate: any;\r\n configure: ConfigurationFile;\r\n 'defer-update': {\r\n logs: string[], \r\n progress: number\r\n };\r\n notification: Notification;\r\n 'input-asked': ConfigurationBuilder;\r\n}\r\n\r\nexport interface EventListenerTypes {\r\n connect: (socket: ws) => void;\r\n disconnect: (reason: string) => void;\r\n configure: (config: ConfigurationBuilder) => ConfigurationBuilder;\r\n response: (response: any) => void;\r\n authenticate: (config: any) => void;\r\n search: (query: { type: 'steamapp', text: string }, event: EventResponse<SearchResult[]>) => void;\r\n setup: (\r\n data: { \r\n path: string, \r\n type: 'direct' | 'torrent' | 'magnet',\r\n name: string,\r\n usedRealDebrid: boolean, \r\n multiPartFiles?: {\r\n name: string,\r\n downloadURL: string\r\n }[],\r\n steamAppID: number\r\n }, event: EventResponse<LibraryInfo>\r\n ) => void;\r\n}\r\n\r\nexport interface WebsocketMessageClient {\r\n event: OGIAddonClientSentEvent;\r\n id?: string;\r\n args: any;\r\n}\r\nexport interface WebsocketMessageServer {\r\n event: OGIAddonServerSentEvent;\r\n id?: string;\r\n args: any;\r\n}\r\nexport interface OGIAddonConfiguration {\r\n name: string;\r\n id: string;\r\n description: string;\r\n version: string;\r\n\r\n author: string;\r\n repository: string;\r\n}\r\nexport default class OGIAddon {\r\n public eventEmitter = new events.EventEmitter();\r\n public addonWSListener: OGIAddonWSListener;\r\n public addonInfo: OGIAddonConfiguration;\r\n public config: Configuration = new Configuration({});\r\n\r\n constructor(addonInfo: OGIAddonConfiguration) {\r\n this.addonInfo = addonInfo;\r\n this.addonWSListener = new OGIAddonWSListener(this, this.eventEmitter);\r\n }\r\n \r\n public on<T extends OGIAddonEvent>(event: T, listener: EventListenerTypes[T]) {\r\n this.eventEmitter.on(event, listener);\r\n }\r\n\r\n public emit<T extends OGIAddonEvent>(event: T, ...args: Parameters<EventListenerTypes[T]>) {\r\n this.eventEmitter.emit(event, ...args);\r\n }\r\n\r\n public notify(notification: Notification) {\r\n this.addonWSListener.send('notification', [ notification ]);\r\n }\r\n}\r\n\r\nexport interface LibraryInfo {\r\n name: string;\r\n version: string;\r\n cwd: string;\r\n steamAppID: number;\r\n launchExecutable: string;\r\n launchArguments?: string;\r\n capsuleImage: string;\r\n}\r\ninterface Notification {\r\n type: 'warning' | 'error' | 'info' | 'success';\r\n message: string;\r\n id: string\r\n}\r\nclass OGIAddonWSListener {\r\n private socket: WebSocket;\r\n public eventEmitter: events.EventEmitter;\r\n public addon: OGIAddon;\r\n\r\n constructor(ogiAddon: OGIAddon, eventEmitter: events.EventEmitter) {\r\n if (process.argv[process.argv.length - 1].split('=')[0] !== '--addonSecret') {\r\n throw new Error('No secret provided. This usually happens because the addon was not started by the OGI Addon Server.');\r\n }\r\n this.addon = ogiAddon;\r\n this.eventEmitter = eventEmitter;\r\n this.socket = new ws('ws://localhost:' + defaultPort);\r\n this.socket.on('open', () => {\r\n console.log('Connected to OGI Addon Server');\r\n console.log('OGI Addon Server Version:', version);\r\n\r\n // Authenticate with OGI Addon Server\r\n this.socket.send(JSON.stringify({\r\n event: 'authenticate',\r\n args: {\r\n ...this.addon.addonInfo,\r\n secret: process.argv[process.argv.length - 1].split('=')[1],\r\n ogiVersion: version\r\n }\r\n }));\r\n\r\n this.eventEmitter.emit('connect');\r\n\r\n // send a configuration request\r\n let configBuilder = new ConfigurationBuilder();\r\n this.eventEmitter.emit('configure', configBuilder);\r\n \r\n this.socket.send(JSON.stringify({\r\n event: 'configure',\r\n args: configBuilder.build(false) \r\n }));\r\n this.addon.config = new Configuration(configBuilder.build(true));\r\n });\r\n\r\n this.socket.on('error', (error) => {\r\n if (error.message.includes('Failed to connect')) {\r\n throw new Error('OGI Addon Server is not running/is unreachable. Please start the server and try again.');\r\n }\r\n console.error('An error occurred:', error);\r\n })\r\n\r\n this.socket.on('close', (code, reason) => {\r\n if (code === 1008) {\r\n console.error('Authentication failed:', reason);\r\n return;\r\n }\r\n this.eventEmitter.emit('disconnect', reason);\r\n console.log(\"Disconnected from OGI Addon Server\")\r\n console.log(reason.toString())\r\n this.socket.close();\r\n });\r\n\r\n this.registerMessageReceiver();\r\n }\r\n\r\n private async userInputAsked(configBuilt: ConfigurationBuilder, name: string, description: string, socket: WebSocket): Promise<{ [key: string]: number | boolean | string }> {\r\n const config = configBuilt.build(false);\r\n const id = Math.random().toString(36).substring(7);\r\n if (!socket) {\r\n return {};\r\n }\r\n socket.send(JSON.stringify({\r\n event: 'input-asked',\r\n args: {\r\n config,\r\n name,\r\n description\r\n },\r\n id: id\r\n }));\r\n return await this.waitForResponseFromServer(id);\r\n }\r\n\r\n private registerMessageReceiver() {\r\n this.socket.on('message', async (data: string) => {\r\n const message: WebsocketMessageServer = JSON.parse(data);\r\n switch (message.event) {\r\n case 'config-update':\r\n const result = this.addon.config.updateConfig(message.args);\r\n if (!result[0]) {\r\n this.respondToMessage(message.id!!, { success: false, error: result[1] });\r\n }\r\n else {\r\n this.respondToMessage(message.id!!, { success: true });\r\n }\r\n break \r\n case 'search':\r\n let searchResultEvent = new EventResponse<SearchResult[]>((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));\r\n this.eventEmitter.emit('search', message.args, searchResultEvent);\r\n const searchResult = await this.waitForEventToRespond(searchResultEvent); \r\n console.log(searchResult.data)\r\n this.respondToMessage(message.id!!, searchResult.data);\r\n break\r\n case 'setup':\r\n let setupEvent = new EventResponse<LibraryInfo>((screen, name, description) => this.userInputAsked(screen, name, description, this.socket));\r\n this.eventEmitter.emit('setup', { path: message.args.path, steamAppID: message.args.steamAppID, type: message.args.type, name: message.args.name, usedRealDebrid: message.args.usedRealDebrid, multiPartFiles: message.args.multiPartFiles }, setupEvent);\r\n const interval = setInterval(() => {\r\n if (setupEvent.resolved) {\r\n clearInterval(interval);\r\n return;\r\n }\r\n this.send('defer-update', { \r\n logs: setupEvent.logs,\r\n deferID: message.args.deferID,\r\n progress: setupEvent.progress\r\n } as any);\r\n }, 100);\r\n const setupResult = await this.waitForEventToRespond(setupEvent);\r\n this.respondToMessage(message.id!!, setupResult.data);\r\n break\r\n }\r\n });\r\n }\r\n\r\n private waitForEventToRespond<T>(event: EventResponse<T>): Promise<EventResponse<T>> {\r\n return new Promise((resolve, reject) => {\r\n const dataGet = setInterval(() => {\r\n if (event.resolved) {\r\n resolve(event);\r\n clearTimeout(timeout);\r\n }\r\n }, 5); \r\n\r\n const timeout = setTimeout(() => {\r\n if (event.deffered) {\r\n clearInterval(dataGet);\r\n const interval = setInterval(() => {\r\n if (event.resolved) {\r\n clearInterval(interval);\r\n resolve(event);\r\n }\r\n }, 100);\r\n }\r\n else {\r\n reject('Event did not respond in time');\r\n }\r\n }, 5000)\r\n });\r\n }\r\n\r\n public respondToMessage(messageID: string, response: any) {\r\n this.socket.send(JSON.stringify({\r\n event: 'response',\r\n id: messageID,\r\n args: response\r\n }));\r\n console.log(\"dispatched response to \" + messageID)\r\n }\r\n\r\n public waitForResponseFromServer<T>(messageID: string): Promise<T> {\r\n return new Promise((resolve) => {\r\n const waiter = (data: string) => {\r\n const message: WebsocketMessageClient = JSON.parse(data);\r\n if (message.event !== 'response') {\r\n this.socket.once('message', waiter);\r\n return;\r\n }\r\n console.log(\"received response from \" + messageID)\r\n\r\n if (message.id === messageID) {\r\n resolve(message.args);\r\n }\r\n else {\r\n this.socket.once('message', waiter);\r\n }\r\n }\r\n this.socket.once('message', waiter);\r\n });\r\n }\r\n\r\n public send(event: OGIAddonClientSentEvent, args: Parameters<ClientSentEventTypes[OGIAddonClientSentEvent]>) {\r\n this.socket.send(JSON.stringify({\r\n event,\r\n args\r\n }));\r\n }\r\n\r\n public close() {\r\n this.socket.close();\r\n }\r\n\r\n \r\n}","import z, { ZodError } from \"zod\"\r\n\r\nexport interface ConfigurationFile {\r\n [key: string]: ConfigurationOption\r\n}\r\n\r\nconst configValidation = z.object({\r\n name: z.string().min(1),\r\n displayName: z.string().min(1),\r\n description: z.string().min(1),\r\n})\r\n\r\nexport function isStringOption(option: ConfigurationOption): option is StringOption {\r\n return option.type === 'string';\r\n }\r\n\r\nexport function isNumberOption(option: ConfigurationOption): option is NumberOption {\r\n return option.type === 'number';\r\n}\r\n\r\nexport function isBooleanOption(option: ConfigurationOption): option is BooleanOption {\r\n return option.type === 'boolean';\r\n}\r\n\r\nexport class ConfigurationBuilder {\r\n private options: ConfigurationOption[] = [];\r\n public addNumberOption(option: (option: NumberOption) => NumberOption): ConfigurationBuilder {\r\n let newOption = new NumberOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public addStringOption(option: (option: StringOption) => StringOption) {\r\n let newOption = new StringOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public addBooleanOption(option: (option: BooleanOption) => BooleanOption) {\r\n let newOption = new BooleanOption();\r\n newOption = option(newOption);\r\n this.options.push(newOption);\r\n return this;\r\n }\r\n\r\n public build(includeFunctions: boolean): ConfigurationFile {\r\n let config: ConfigurationFile = {};\r\n this.options.forEach(option => {\r\n // remove all functions from the option object\r\n if (!includeFunctions) {\r\n option = JSON.parse(JSON.stringify(option));\r\n const optionData = configValidation.safeParse(option)\r\n if (!optionData.success) {\r\n throw new ZodError(optionData.error.errors)\r\n }\r\n\r\n config[option.name] = option;\r\n }\r\n else {\r\n config[option.name] = option;\r\n }\r\n });\r\n return config;\r\n }\r\n}\r\n\r\nexport type ConfigurationOptionType = 'string' | 'number' | 'boolean' | 'unset'\r\nexport class ConfigurationOption {\r\n public name: string = '';\r\n public defaultValue: unknown = '';\r\n public displayName: string = '';\r\n public description: string = '';\r\n public type: ConfigurationOptionType = 'unset'\r\n \r\n setName(name: string) {\r\n this.name = name;\r\n return this;\r\n }\r\n\r\n setDisplayName(displayName: string) {\r\n this.displayName = displayName;\r\n return this;\r\n }\r\n\r\n setDescription(description: string) {\r\n this.description = description;\r\n return this;\r\n }\r\n\r\n\r\n validate(input: unknown): [ boolean, string ] {\r\n throw new Error('Validation code not implemented. Value: ' + input)\r\n };\r\n}\r\n\r\nexport class StringOption extends ConfigurationOption {\r\n public allowedValues: string[] = [];\r\n public minTextLength: number = 0;\r\n public maxTextLength: number = Number.MAX_SAFE_INTEGER;\r\n public defaultValue: string = '';\r\n public inputType: 'text' | 'file' | 'password' | 'folder' = 'text';\r\n public type: ConfigurationOptionType = 'string'\r\n\r\n setAllowedValues(allowedValues: string[]): this {\r\n this.allowedValues = allowedValues;\r\n return this;\r\n }\r\n\r\n setDefaultValue(defaultValue: string): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n setMinTextLength(minTextLength: number): this {\r\n this.minTextLength = minTextLength;\r\n return this;\r\n }\r\n\r\n setMaxTextLength(maxTextLength: number): this {\r\n this.maxTextLength = maxTextLength;\r\n return this;\r\n }\r\n\r\n setInputType(inputType: 'text' | 'file' | 'password' | 'folder'): this {\r\n this.inputType = inputType;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (typeof input !== 'string') {\r\n return [ false, 'Input is not a string' ];\r\n }\r\n if (this.allowedValues.length === 0 && input.length !== 0)\r\n return [ true, '' ];\r\n if (input.length < this.minTextLength || input.length > this.maxTextLength) {\r\n return [ false, 'Input is not within the text length ' + this.minTextLength + ' and ' + this.maxTextLength + ' characters (currently ' + input.length + ' characters)' ];\r\n }\r\n\r\n return [ this.allowedValues.includes(input), 'Input is not an allowed value' ];\r\n }\r\n}\r\n\r\nexport class NumberOption extends ConfigurationOption {\r\n public min: number = 0;\r\n public max: number = Number.MAX_SAFE_INTEGER;\r\n public defaultValue: number = 0;\r\n public type: ConfigurationOptionType = 'number'\r\n public inputType: 'range' | 'number' = 'number';\r\n setMin(min: number): this {\r\n this.min = min;\r\n return this;\r\n }\r\n\r\n setInputType(type: 'range' | 'number'): this {\r\n this.inputType = type;\r\n return this;\r\n }\r\n\r\n setMax(max: number): this {\r\n this.max = max;\r\n return this\r\n }\r\n\r\n setDefaultValue(defaultValue: number): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (isNaN(Number(input))) {\r\n return [ false, 'Input is not a number' ];\r\n }\r\n if (Number(input) < this.min || Number(input) > this.max) {\r\n return [ false, 'Input is not within the range of ' + this.min + ' and ' + this.max ];\r\n }\r\n return [ true, '' ];\r\n }\r\n\r\n}\r\n\r\nexport class BooleanOption extends ConfigurationOption {\r\n public type: ConfigurationOptionType = 'boolean'\r\n public defaultValue: boolean = false;\r\n\r\n setDefaultValue(defaultValue: boolean): this {\r\n this.defaultValue = defaultValue;\r\n return this;\r\n }\r\n\r\n override validate(input: unknown): [ boolean, string ] {\r\n if (typeof input !== 'boolean') {\r\n return [ false, 'Input is not a boolean' ];\r\n }\r\n return [ true, '' ];\r\n }\r\n\r\n}","import { ConfigurationFile, ConfigurationBuilder, BooleanOption, ConfigurationOption, ConfigurationOptionType, NumberOption, StringOption, isBooleanOption, isNumberOption, isStringOption } from \"./ConfigurationBuilder\";\r\n\r\ninterface DefiniteConfig {\r\n [key: string]: string | number | boolean;\r\n}\r\nexport class Configuration {\r\n readonly storedConfigTemplate: ConfigurationFile;\r\n definiteConfig: DefiniteConfig = {};\r\n constructor(configTemplate: ConfigurationFile) {\r\n this.storedConfigTemplate = configTemplate;\r\n }\r\n\r\n updateConfig(config: DefiniteConfig, validate: boolean = true): [ boolean, { [key: string]: string } ] {\r\n this.definiteConfig = config;\r\n if (validate) {\r\n const result = this.validateConfig();\r\n return result;\r\n }\r\n return [ true, {} ];\r\n }\r\n // provides falsey or truthy value, and an error message if falsey\r\n private validateConfig(): [ boolean, { [key: string]: string } ] {\r\n const erroredKeys = new Map<string, string>();\r\n for (const key in this.storedConfigTemplate) {\r\n if (this.definiteConfig[key] === null || this.definiteConfig[key] === undefined) {\r\n console.warn('Option ' + key + ' is not defined. Using default value Value: ' + this.definiteConfig[key]);\r\n this.definiteConfig[key] = this.storedConfigTemplate[key].defaultValue as string | number | boolean;\r\n }\r\n if (this.storedConfigTemplate[key].type !== typeof this.definiteConfig[key]) {\r\n throw new Error('Option ' + key + ' is not of the correct type');\r\n }\r\n\r\n const result = this.storedConfigTemplate[key].validate(this.definiteConfig[key]);\r\n if (!result[0]) {\r\n erroredKeys.set(key, result[1]);\r\n }\r\n }\r\n\r\n for (const key in this.definiteConfig) {\r\n if (!this.storedConfigTemplate[key]) {\r\n throw new Error('Option ' + key + ' is not defined in the configuration template');\r\n }\r\n }\r\n\r\n if (erroredKeys.size > 0) {\r\n return [ false, Object.fromEntries(erroredKeys) ];\r\n }\r\n\r\n return [ true, Object.fromEntries(erroredKeys) ];\r\n }\r\n\r\n getStringValue(optionName: string): string {\r\n if (!this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'string') {\r\n throw new Error('Option ' + optionName + ' is not a string');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n\r\n getNumberValue(optionName: string): number {\r\n if (!this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'number') {\r\n throw new Error('Option ' + optionName + ' is not a number');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n\r\n getBooleanValue(optionName: string): boolean {\r\n if (this.definiteConfig[optionName] === null) {\r\n throw new Error('Option ' + optionName + ' is not defined');\r\n }\r\n if (typeof this.definiteConfig[optionName] !== 'boolean') {\r\n throw new Error('Option ' + optionName + ' is not a boolean');\r\n }\r\n return this.definiteConfig[optionName];\r\n }\r\n}\r\n\r\nexport { ConfigurationFile, ConfigurationBuilder, BooleanOption, ConfigurationOption, ConfigurationOptionType, NumberOption, StringOption, isBooleanOption, isNumberOption, isStringOption };","import { ConfigurationBuilder } from \"./main\";\r\n\r\nexport default class EventResponse<T> {\r\n data: T | undefined = undefined;\r\n deffered: boolean = false;\r\n resolved: boolean = false;\r\n progress: number = 0;\r\n logs: string[] = [];\r\n onInputAsked?: (screen: ConfigurationBuilder, name: string, description: string) => Promise<{ [key: string]: boolean | string | number }>;\r\n\r\n constructor(onInputAsked?: (screen: ConfigurationBuilder, name: string, description: string) => Promise<{ [key: string]: boolean | string | number }>) {\r\n this.onInputAsked = onInputAsked;\r\n }\r\n \r\n\r\n public defer() {\r\n this.deffered = true;\r\n }\r\n\r\n public resolve(data: T) {\r\n this.resolved = true;\r\n this.data = data;\r\n }\r\n\r\n public complete() {\r\n this.resolved = true;\r\n }\r\n\r\n public log(message: string) {\r\n this.logs.push(message);\r\n }\r\n\r\n public async askForInput(name: string, description: string, screen: ConfigurationBuilder) {\r\n if (!this.onInputAsked) {\r\n throw new Error('No input asked callback');\r\n }\r\n return await this.onInputAsked(screen, name, description);\r\n }\r\n\r\n \r\n}"],"mappings":"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","names":[]}
|