diff --git a/packages/core/scripts/generate-client.cjs b/packages/core/scripts/generate-client.cjs index 3568a816..548f24f3 100644 --- a/packages/core/scripts/generate-client.cjs +++ b/packages/core/scripts/generate-client.cjs @@ -264,6 +264,8 @@ async function addSingleMethod(state, fileName) { } else if (stmt.kind === ts.SyntaxKind.FunctionDeclaration) { const name = stmt.name.escapedText + if (checkForFlag(stmt, '@skip')) { continue } + if (stmt.body && name in state.methods.used) { throwError( stmt.name, @@ -345,40 +347,38 @@ async function addSingleMethod(state, fileName) { state.methods.used[name] = relPath } - if (isExported || isDeclare) { - const isPrivate = checkForFlag(stmt, '@internal') - const isManual = checkForFlag(stmt, '@manual') - const isNoemit = checkForFlag(stmt, '@noemit') - const shouldEmit = !isNoemit && !(isPrivate && !isOverload && !Object.keys(hasOverloads).length) + const isPrivate = checkForFlag(stmt, '@internal') + const isManual = checkForFlag(stmt, '@manual') + const isNoemit = checkForFlag(stmt, '@noemit') + const shouldEmit = !isNoemit && !(isPrivate && !isOverload && !Object.keys(hasOverloads).length) - if (shouldEmit) { - state.methods.list.push({ - from: relPath, - module, - name, - isPrivate, - isManual, - isNoemit, - isDeclare, - shouldEmit, - func: stmt, - comment: getLeadingComments(stmt), - aliases, - available, - rawApiMethods, - dependencies, - overload: isOverload, - hasOverloads: hasOverloads[name] && !isOverload, - }) + if (shouldEmit) { + state.methods.list.push({ + from: relPath, + module, + name, + isPrivate, + isManual, + isNoemit, + isDeclare, + shouldEmit, + func: stmt, + comment: getLeadingComments(stmt), + aliases, + available, + rawApiMethods, + dependencies, + overload: isOverload, + hasOverloads: hasOverloads[name] && !isOverload, + }) - if (!isDeclare) { - if (!(module in state.imports)) { - state.imports[module] = new Set() - } + if (!isDeclare) { + if (!(module in state.imports)) { + state.imports[module] = new Set() + } - if (!isManual || isManual.split('=')[1] !== 'noemit') { - state.imports[module].add(name) - } + if (!isManual || isManual.split('=')[1] !== 'noemit') { + state.imports[module].add(name) } } } @@ -482,6 +482,7 @@ async function main() { if (!items.length) return output.write(`import { ${items.sort().join(', ')} } from '${module}'\n`) }) + output.write("import { withParams } from './methods/misc/with-params.js'") output.write('\n') @@ -518,7 +519,15 @@ on(name: '${type.typeName}', handler: ((upd: ${type.updateType}) => void)): this output.write(` // eslint-disable-next-line @typescript-eslint/no-explicit-any -on(name: string, handler: (...args: any[]) => void): this\n`) +on(name: string, handler: (...args: any[]) => void): this\n + +/** + * Wrap this client so that all RPC calls will use the specified parameters. + * + * @param params Parameters to use + * @returns Wrapped client + */ +withParams(params: RpcCallOptions): this\n`) const printer = ts.createPrinter() @@ -703,7 +712,13 @@ on(name: string, handler: (...args: any[]) => void): this\n`) output.write('}\n') classContents.forEach((line) => output.write(line + '\n')) + + output.write(` withParams(params: RpcCallOptions): this { + return withParams(this, params) + }\n`) + output.write('}\n') + classProtoDecls.forEach((line) => output.write(line + '\n')) // proxied methods ;[ diff --git a/packages/core/src/highlevel/client.ts b/packages/core/src/highlevel/client.ts index 0fe778ab..e1c28777 100644 --- a/packages/core/src/highlevel/client.ts +++ b/packages/core/src/highlevel/client.ts @@ -7,6 +7,7 @@ import Long from 'long' import { tdFileId } from '@mtcute/file-id' import { tl } from '@mtcute/tl' +import { RpcCallOptions } from '../network/index.js' import { MaybeArray, MaybePromise, MtUnsupportedError, PartialExcept, PartialOnly } from '../types/index.js' import { BaseTelegramClient, BaseTelegramClientOptions } from './base.js' import { ITelegramClient } from './client.types.js' @@ -169,6 +170,7 @@ import { unpinAllMessages } from './methods/messages/unpin-all-messages.js' import { unpinMessage } from './methods/messages/unpin-message.js' import { initTakeoutSession } from './methods/misc/init-takeout-session.js' import { _normalizePrivacyRules } from './methods/misc/normalize-privacy-rules.js' +import { withParams } from './methods/misc/with-params.js' import { changeCloudPassword } from './methods/password/change-cloud-password.js' import { enableCloudPassword } from './methods/password/enable-cloud-password.js' import { cancelPasswordEmail, resendPasswordEmail, verifyPasswordEmail } from './methods/password/password-email.js' @@ -313,7 +315,6 @@ import { } from './types/index.js' import { makeParsedUpdateHandler, ParsedUpdateHandlerParams } from './updates/parsed.js' import { StringSessionData } from './utils/string-session.js' - // from methods/_init.ts // @copy type TelegramClientOptions = ( @@ -512,6 +513,14 @@ export interface TelegramClient extends ITelegramClient { // eslint-disable-next-line @typescript-eslint/no-explicit-any on(name: string, handler: (...args: any[]) => void): this + + /** + * Wrap this client so that all RPC calls will use the specified parameters. + * + * @param params Parameters to use + * @returns Wrapped client + */ + withParams(params: RpcCallOptions): this /** * Check your Two-Step verification password and log in * @@ -5177,6 +5186,9 @@ export class TelegramClient extends EventEmitter implements ITelegramClient { }), ) } + withParams(params: RpcCallOptions): this { + return withParams(this, params) + } } TelegramClient.prototype.checkPassword = function (...args) { diff --git a/packages/core/src/highlevel/methods/_imports.ts b/packages/core/src/highlevel/methods/_imports.ts index a8f01698..2f2029c0 100644 --- a/packages/core/src/highlevel/methods/_imports.ts +++ b/packages/core/src/highlevel/methods/_imports.ts @@ -5,6 +5,8 @@ import { tdFileId } from '@mtcute/file-id' // @copy import { tl } from '@mtcute/tl' +// @copy +import { RpcCallOptions } from '../../network/index.js' // @copy import { MaybeArray, MaybePromise, MtUnsupportedError, PartialExcept, PartialOnly } from '../../types/index.js' // @copy diff --git a/packages/core/src/highlevel/methods/misc/with-params.ts b/packages/core/src/highlevel/methods/misc/with-params.ts new file mode 100644 index 00000000..248254b2 --- /dev/null +++ b/packages/core/src/highlevel/methods/misc/with-params.ts @@ -0,0 +1,37 @@ +import { tl } from '@mtcute/tl' + +import { RpcCallOptions } from '../../../network/index.js' +import { ITelegramClient } from '../../client.types.js' + +// @skip +/** + * Wrap a client so that all RPC calls will use the specified parameters. + * + * @param client Client to wrap + * @param params RPC call parameters to use by default + * @returns The wrapped client + */ +export function withParams(client: T, params: RpcCallOptions): T { + const wrappedCall = (message: tl.RpcMethod, extraParams?: RpcCallOptions) => + client.call(message, extraParams ? { ...params, ...extraParams } : params) + + const proxy: T = new Proxy(client, { + get: (target, prop, receiver) => { + if (prop === 'call') { + return wrappedCall + } + + if (prop === '_client') { + // ideally we would wrap it as well, but it's not really needed, since TelegramClient + // TelegramClient stores underlying client in _client + // itself implements ITelegramClient + // very much a hack, but i dont care :D + return proxy + } + + return Reflect.get(target, prop, receiver) + }, + }) + + return proxy +}