Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kody/telegram

src/smoke-test.ts

85 lines · 2.4 KB · TypeScript
import { kody } from 'kody:runtime'
import getMe from './get-me.ts'
import { secretNameFrom, secretSetupUrl } from './validation.ts'

function secretEntries(
	result: unknown,
): Array<{ name?: string; scope?: string }> {
	if (
		result &&
		typeof result === 'object' &&
		Array.isArray((result as { secrets?: unknown }).secrets)
	) {
		return (result as { secrets: Array<{ name?: string; scope?: string }> })
			.secrets
	}
	return Array.isArray(result) ? result : []
}

/**
 * Read-only smoke test: local setup check, plus live getMe when
 * telegramBotToken is saved.
 *
 * Without the secret this still returns `{ ok: true, live: false }` and the
 * prefilled setup URL so the package is forkable before anyone connects a
 * bot. With the secret it proves host approval and that the token belongs
 * to a bot — without sending any messages.
 *
 * @example
 * import smokeTest from 'kody:@kody/telegram/smoke-test'
 * const result = await smokeTest()
 */
export default async function smokeTest(params: Record<string, unknown> = {}) {
	const secretName = secretNameFrom(params)
	const listed = await kody.secret_list({ scope: 'user' })
	const names = new Set<string>()
	for (const entry of secretEntries(listed)) {
		if (entry?.name && (entry.scope === 'user' || !entry.scope)) {
			names.add(entry.name)
		}
	}

	const setupUrl = secretSetupUrl(secretName)
	if (!names.has(secretName)) {
		return {
			ok: true,
			live: false,
			method: 'getMe',
			host: 'api.telegram.org',
			isBot: null,
			username: null,
			setup: {
				secrets: { [secretName]: false },
				nextSteps: [
					'Create a bot with @BotFather (/newbot or /token). Do not paste the token into chat.',
					setupUrl,
					'Approve host api.telegram.org after the secret is saved.',
				],
			},
		}
	}

	const result = await getMe(params)
	if (result.bot.isBot !== true) {
		throw new Error(
			secretName +
				' must be a Telegram bot token from @BotFather. User tokens and Telegram Login Widget OAuth (https://kody.codes/connect/oauth?provider=telegram) cannot call the Bot API. Save a bot token at ' +
				setupUrl,
		)
	}
	return {
		ok: true,
		live: true,
		method: 'getMe',
		host: 'api.telegram.org',
		isBot: true,
		hasUsername: result.bot.hasUsername,
		canJoinGroups: result.bot.canJoinGroups,
		canReadAllGroupMessages: result.bot.canReadAllGroupMessages,
		username: result.bot.username,
		setup: {
			secrets: { [secretName]: true },
			nextSteps: [],
		},
	}
}