@stack.thefennec.dev/telegram-export-parser
Version:
TypeScript library for parsing Telegram Desktop's data export with full type safety
541 lines • 16.2 kB
TypeScript
import type { TelegramMessage } from './messages';
import type { TelegramEvent } from './events';
/**
* Message type identifiers used to distinguish between user messages and service events.
*
* @example
* ```typescript
* if (item.type === MESSAGE_TYPES.MESSAGE) {
* // Handle user message
* } else if (item.type === MESSAGE_TYPES.SERVICE) {
* // Handle service event
* }
* ```
*/
export declare const MESSAGE_TYPES: {
/** Regular user-generated message */
readonly MESSAGE: "message";
/** System-generated service event */
readonly SERVICE: "service";
};
/**
* Union type for all possible message types.
* Used to differentiate between user content and system events.
*/
export type MessageType = typeof MESSAGE_TYPES.MESSAGE | typeof MESSAGE_TYPES.SERVICE;
/**
* Media type identifiers for different kinds of file attachments.
*
* These constants correspond to the media_type field in Telegram exports
* and help identify the specific type of media content.
*
* @example
* ```typescript
* if (mediaMessage.mediaType === MEDIA_TYPES.VIDEO_FILE) {
* // Handle video file
* }
* ```
*/
export declare const MEDIA_TYPES: {
/** Static or animated sticker image */
readonly STICKER: "sticker";
/** Animated GIF or short video loop */
readonly ANIMATION: "animation";
/** Music or audio file with metadata */
readonly AUDIO_FILE: "audio_file";
/** Regular video file with full controls */
readonly VIDEO_FILE: "video_file";
/** Circular video message (video note) */
readonly VIDEO_NOTE: "video_message";
/** Voice message recording */
readonly VOICE_NOTE: "voice_message";
/** Generic document or file attachment */
readonly FILE: "file";
};
/**
* Union type for all supported media types.
* Used to type-check and validate media message content.
*/
export type MediaType = typeof MEDIA_TYPES[keyof typeof MEDIA_TYPES];
/**
* Actor type identifiers for different kinds of message senders.
*
* Actors represent who sent a message, from regular users to bots,
* channels, and special cases like deleted accounts.
*
* @example
* ```typescript
* if (actor.type === 'bot') {
* console.log(`Bot message from ${actor.displayName}`)
* }
* ```
*/
export declare const ACTOR_TYPES: readonly ["user", "bot", "channel", "channel_author", "deleted_user"];
/**
* Union type for all possible actor types.
* Used to identify the nature of message senders.
*/
export type ActorType = typeof ACTOR_TYPES[number];
/**
* Represents any entity that can send messages in Telegram.
*
* Actors include users, bots, channels, and special cases like
* deleted accounts. Contains identification and display information.
*
* @example
* ```typescript
* const formatSender = (actor: Actor): string => {
* const name = actor.displayName || 'Unknown'
* const username = actor.username ? `@${actor.username}` : ''
* return `${name} ${username}`.trim()
* }
* ```
*/
export interface Actor {
/** Numeric Telegram ID (undefined for some edge cases) */
id: number | undefined;
/** Type of actor (user, bot, channel, etc.) */
type: ActorType;
/** Telegram username without @ symbol (if available) */
username: string | undefined;
/** Display name or fallback for deleted/unknown users */
displayName: string | "Deleted User" | "Unknown";
/** For channel authors, the original author name */
authoredBy: string | undefined;
}
/**
* Represents a file reference from Telegram export.
* Can be a URL, null, or undefined depending on export format and availability.
*/
export type ExportedFile = URL | null | undefined;
/**
* Reaction type identifiers for message reactions.
*
* @example
* ```typescript
* if (reaction.type === 'custom_emoji') {
* // Handle custom emoji reaction
* }
* ```
*/
export declare const REACTION_TYPES: readonly ["emoji", "custom_emoji"];
/**
* Union type for reaction types.
*/
export type ReactionType = typeof REACTION_TYPES[number];
/**
* Represents a user reaction to a message.
*
* Contains the reaction emoji/sticker, count, and information about
* recent users who added this reaction.
*
* @example
* ```typescript
* const formatReaction = (reaction: Reaction): string => {
* return `${reaction.emoji} (${reaction.count})`
* }
* ```
*/
export interface Reaction {
/** The emoji or reaction identifier */
emoji: string;
/** URL to custom emoji file (if applicable) */
documentURL: ExportedFile;
/** Total number of users who added this reaction */
count: number;
/** Recent users who added this reaction (up to a limit) */
recent: Array<{
/** User who added the reaction */
sender: Actor;
/** When the reaction was added */
date: Date;
}>;
}
/**
* Conversation type identifiers for different kinds of Telegram chats.
*
* @example
* ```typescript
* if (conversation.type === 'public_channel') {
* // Handle public channel
* }
* ```
*/
export declare const CONVERSATION_TYPES: readonly ["personal_chat", "private_group", "private_supergroup", "public_supergroup", "public_channel", "private_channel"];
/**
* Union type for all conversation types.
* Used to identify the nature and privacy level of chats.
*/
export type ConversationType = typeof CONVERSATION_TYPES[number];
/**
* Represents a Telegram chat or conversation.
*
* Contains basic metadata about the chat including its type,
* name, and unique identifier.
*
* @example
* ```typescript
* const isGroupChat = (conv: Conversation): boolean => {
* return conv.type.includes('group')
* }
* ```
*/
export interface Conversation {
/** Unique Telegram chat identifier */
id: number;
/** Display name of the chat (undefined for some personal chats) */
name: string | undefined;
/** Type of conversation (personal, group, channel, etc.) */
type: ConversationType;
}
/**
* Complete parsed Telegram chat export data.
*
* This is the main data structure returned by the parser, containing
* all messages, participants, and metadata for a chat export.
*
* @example
* ```typescript
* const analyzeExport = (export: TelegramChatExport) => {
* console.log(`Chat: ${export.conversation.name}`)
* console.log(`Messages: ${export.totalMessages}`)
* console.log(`Participants: ${export.participants.size}`)
* console.log(`Date range: ${export.dateRange.earliest} to ${export.dateRange.latest}`)
* }
* ```
*/
export interface TelegramChatExport {
/** Information about the chat/conversation */
conversation: Conversation;
/** Map of user IDs to Actor objects for all participants */
participants: Map<number, Actor>;
/** All messages and events in chronological order */
messages: (TelegramMessage | TelegramEvent)[];
/** Total count of messages for quick reference */
totalMessages: number;
/** Time span covered by the export */
dateRange: {
/** Oldest message timestamp */
earliest: Date;
/** Newest message timestamp */
latest: Date;
};
}
/**
* Inline button type identifiers for bot interaction buttons.
*
* These buttons appear below messages and provide various interaction
* methods like URLs, callbacks, and payment flows.
*
* @example
* ```typescript
* if (button.type === 'url') {
* // Handle URL button
* window.open(button.url)
* }
* ```
*/
export declare const INLINE_BUTTON_TYPES: readonly ["url", "callback", "switch_inline", "switch_inline_query", "switch_inline_query_current_chat", "callback_game", "pay"];
/**
* Union type for all inline button types.
*/
export type InlineButtonType = typeof INLINE_BUTTON_TYPES[number];
/**
* Represents an interactive button attached to a bot message.
*
* Inline buttons provide rich interaction capabilities including
* web links, bot callbacks, payments, and game launches.
*
* @example
* ```typescript
* const handleButton = (button: InlineButton) => {
* switch (button.type) {
* case 'url':
* return `<a href="${button.url}">${button.text}</a>`
* case 'callback':
* return `<button data-callback="${button.data}">${button.text}</button>`
* }
* }
* ```
*/
export interface InlineButton {
/** Type of button interaction */
type: InlineButtonType;
/** Display text on the button */
text: string;
/** Callback data sent to bot (for callback buttons) */
data?: string;
/** Base64 encoded callback data */
dataBase64?: string;
/** URL to open (for URL buttons) */
url?: string;
/** Unique button identifier */
button_id?: string;
}
/**
* Geographical location coordinates.
*
* Used for location messages and venue information.
* Coordinates follow standard WGS84 format.
*
* @example
* ```typescript
* const formatLocation = (location: LocationInfo): string => {
* return `${location.latitude}, ${location.longitude}`
* }
* ```
*/
export interface LocationInfo {
/** Latitude coordinate (-90 to 90) */
latitude: number;
/** Longitude coordinate (-180 to 180) */
longitude: number;
}
/**
* Contact information for a person.
*
* Represents structured contact data that can be imported
* into address book applications.
*
* @example
* ```typescript
* const formatContact = (contact: ContactInfo): string => {
* const name = `${contact.first_name} ${contact.last_name}`.trim()
* return `${name} (${contact.phone_number})`
* }
* ```
*/
export interface ContactInfo {
/** Contact's first/given name */
first_name: string;
/** Contact's last/family name */
last_name: string;
/** Phone number in international format */
phone_number: string;
}
/**
* Single answer option in a poll.
*
* Contains the answer text, vote count, and whether the
* current user selected this option.
*
* @example
* ```typescript
* const formatAnswer = (answer: PollAnswer): string => {
* const selected = answer.chosen ? '✓ ' : ''
* return `${selected}${answer.text} (${answer.voters} votes)`
* }
* ```
*/
export interface PollAnswer {
/** Answer option text */
text: string;
/** Number of users who selected this answer */
voters: number;
/** Whether the current user chose this answer */
chosen: boolean;
}
/**
* Complete poll/survey data.
*
* Includes the question, all answer options with vote counts,
* and poll state information.
*
* @example
* ```typescript
* const analyzePoll = (poll: Poll): string => {
* const status = poll.closed ? 'Closed' : 'Active'
* const participation = `${poll.total_voters} voters`
* return `${poll.question} - ${status} (${participation})`
* }
* ```
*/
export interface Poll {
/** The poll question text */
question: string;
/** Whether voting is still allowed */
closed: boolean;
/** Total number of users who participated */
total_voters: number;
/** All answer options with vote counts */
answers: PollAnswer[];
}
/**
* Payment invoice information.
*
* Contains details for Telegram payment requests including
* price, currency, and item description.
*
* @example
* ```typescript
* const formatInvoice = (invoice: InvoiceInfo): string => {
* return `${invoice.title} - ${invoice.amount} ${invoice.currency}`
* }
* ```
*/
export interface InvoiceInfo {
/** Product or service name */
title: string;
/** Detailed description of the item */
description: string;
/** Currency code (e.g., 'USD', 'EUR') */
currency: string;
/** Price amount in smallest currency unit (cents) */
amount: number;
}
/**
* Type guard to validate Actor objects.
*
* Ensures the object has all required Actor properties with correct types
* and validates the actor type against known values.
*
* @param obj - The value to validate
* @returns True if the value is a valid Actor
*
* @example
* ```typescript
* if (isActor(data)) {
* // TypeScript now knows data is Actor
* console.log(`Actor: ${data.displayName} (${data.type})`)
* }
* ```
*/
export declare function isActor(obj: unknown): obj is Actor;
/**
* Type guard to validate Reaction objects.
*
* Validates reaction structure including emoji, count, and recent users array.
* Also performs deep validation of the recent users array structure.
*
* @param obj - The value to validate
* @returns True if the value is a valid Reaction
*
* @example
* ```typescript
* if (isReaction(data)) {
* console.log(`${data.emoji}: ${data.count} reactions`)
* }
* ```
*/
export declare function isReaction(obj: unknown): obj is Reaction;
/**
* Type guard to validate Conversation objects.
*
* Ensures the conversation has a valid ID and type from the known conversation types.
*
* @param obj - The value to validate
* @returns True if the value is a valid Conversation
*
* @example
* ```typescript
* if (isConversation(data)) {
* console.log(`Chat: ${data.name} (${data.type})`)
* }
* ```
*/
export declare function isConversation(obj: unknown): obj is Conversation;
/**
* Type guard to validate InlineButton objects.
*
* Validates button type and text, with optional validation of type-specific
* properties like URLs and callback data.
*
* @param obj - The value to validate
* @returns True if the value is a valid InlineButton
*
* @example
* ```typescript
* if (isInlineButton(data)) {
* if (data.type === 'url' && data.url) {
* console.log(`URL Button: ${data.text} -> ${data.url}`)
* }
* }
* ```
*/
export declare function isInlineButton(obj: unknown): obj is InlineButton;
/**
* Type guard to validate LocationInfo objects.
*
* Ensures latitude and longitude are valid numbers within expected ranges.
*
* @param obj - The value to validate
* @returns True if the value is valid LocationInfo
*
* @example
* ```typescript
* if (isLocationInfo(data)) {
* console.log(`Location: ${data.latitude}, ${data.longitude}`)
* }
* ```
*/
export declare function isLocationInfo(obj: unknown): obj is LocationInfo;
/**
* Type guard to validate ContactInfo objects.
*
* Ensures all name and phone number fields are present and non-empty strings.
*
* @param obj - The value to validate
* @returns True if the value is valid ContactInfo
*
* @example
* ```typescript
* if (isContactInfo(data)) {
* const fullName = `${data.first_name} ${data.last_name}`.trim()
* console.log(`Contact: ${fullName} (${data.phone_number})`)
* }
* ```
*/
export declare function isContactInfo(obj: unknown): obj is ContactInfo;
/**
* Type guard to validate Poll objects.
*
* Validates poll structure including question, state, and answers array.
* Performs deep validation of all poll answers.
*
* @param obj - The value to validate
* @returns True if the value is a valid Poll
*
* @example
* ```typescript
* if (isPoll(data)) {
* const totalVotes = data.answers.reduce((sum, answer) => sum + answer.voters, 0)
* console.log(`Poll: ${data.question} (${totalVotes} votes)`)
* }
* ```
*/
export declare function isPoll(obj: unknown): obj is Poll;
/**
* Type guard to validate InvoiceInfo objects.
*
* Validates payment invoice data including title, description, currency, and amount.
* Ensures amount is a positive number representing the price.
*
* @param obj - The value to validate
* @returns True if the value is valid InvoiceInfo
*
* @example
* ```typescript
* if (isInvoiceInfo(data)) {
* console.log(`Invoice: ${data.title} - ${data.amount} ${data.currency}`)
* }
* ```
*/
export declare function isInvoiceInfo(obj: unknown): obj is InvoiceInfo;
/**
* Type guard to validate TelegramChatExport objects.
*
* Validates the complete export structure including conversation data,
* participants map, messages array, and metadata.
*
* @param obj - The value to validate
* @returns True if the value is a valid TelegramChatExport
*
* @example
* ```typescript
* if (isTelegramChatExport(data)) {
* console.log(`Export: ${data.totalMessages} messages from ${data.conversation.name}`)
* }
* ```
*/
export declare function isTelegramChatExport(obj: unknown): obj is TelegramChatExport;
//# sourceMappingURL=shared.d.ts.map