├── .husky ├── .gitignore └── pre-commit ├── .npmrc ├── renovate.json ├── media └── tgsnake.jpg ├── prettier.config.js ├── typedoc.json ├── .yarnrc.yml ├── src ├── Events │ ├── index.ts │ └── SnakeEvents.ts ├── Telegram │ ├── Users │ │ ├── index.ts │ │ └── GetUserPhotos.ts │ ├── index.ts │ ├── Bots │ │ ├── index.ts │ │ ├── AnswerPrecheckoutQuery.ts │ │ ├── AnswerShippingQuery.ts │ │ └── AnswerInlineQuery.ts │ ├── Chats │ │ ├── GetInactiveChannels.ts │ │ ├── index.ts │ │ ├── GetLeftChannels.ts │ │ ├── GetGroupsForDiscussion.ts │ │ ├── GetFullChat.ts │ │ ├── GetChannels.ts │ │ ├── GetAdminedPublicChannels.ts │ │ ├── GetChatMembersCount.ts │ │ ├── GetParticipant.ts │ │ ├── EditTitle.ts │ │ ├── EditAdmin.ts │ │ ├── EditBanned.ts │ │ └── GetParticipants.ts │ ├── Messages │ │ ├── index.ts │ │ ├── ReadMessageContents.ts │ │ ├── ReadMentions.ts │ │ ├── UnpinAllMessages.ts │ │ ├── ExportMessageLink.ts │ │ ├── DeleteUserHistory.ts │ │ ├── ReadHistory.ts │ │ ├── DeleteHistory.ts │ │ ├── DeleteMessages.ts │ │ ├── GetMessagesViews.ts │ │ ├── PinMessage.ts │ │ ├── GetMessages.ts │ │ ├── ForwardMessages.ts │ │ └── sendMessage.ts │ └── Media │ │ ├── index.ts │ │ ├── SendDice.ts │ │ ├── GetFileInfo.ts │ │ ├── SendLocation.ts │ │ ├── SendContact.ts │ │ ├── SendVenue.ts │ │ ├── EditPhoto.ts │ │ ├── UploadFile.ts │ │ └── SendSticker.ts ├── Client │ ├── index.ts │ └── ConvertSession.ts ├── Interface │ ├── CatchError.ts │ ├── index.ts │ ├── reply.ts │ ├── Download.ts │ └── Click.ts ├── Utils │ ├── RestrictionReason.ts │ ├── MigrateTo.ts │ ├── Reactions.ts │ ├── Medias │ │ ├── Dice.ts │ │ ├── Contact.ts │ │ ├── index.ts │ │ ├── Venue.ts │ │ ├── Invoice.ts │ │ ├── Location.ts │ │ ├── Media.ts │ │ ├── WebPage.ts │ │ ├── Poll.ts │ │ └── Game.ts │ ├── AdminRights.ts │ ├── CleanObject.ts │ ├── BannedRight.ts │ ├── ToBigInt.ts │ ├── index.ts │ ├── Payment.ts │ ├── ForwardMessage.ts │ ├── Chat.ts │ └── From.ts ├── index.ts ├── Context │ ├── index.ts │ ├── Error.ts │ └── EntityCache.ts └── Update │ ├── UpdateDeleteMessages.ts │ ├── UpdateMessageID.ts │ ├── UpdateUserName.ts │ ├── UpdateNewMessage.ts │ ├── UpdateNewChannelMessage.ts │ ├── UpdateEditMessage.ts │ ├── UpdateEditChannelMessage.ts │ ├── UpdateShortSentMessage.ts │ ├── UpdateChatParticipants.ts │ ├── UpdateBotShippingQuery.ts │ ├── UpdateUserStatus.ts │ ├── UpdateBotPrecheckoutQuery.ts │ ├── UpdateInlineBotCallbackQuery.ts │ ├── UpdateBotInlineQuery.ts │ ├── UpdateBotCallbackQuery.ts │ ├── UpdateShortMessage.ts │ ├── UpdateShortChatMessage.ts │ ├── UpdateUserTyping.ts │ └── Update.ts ├── tes ├── index.ts └── index.js ├── LICENSE ├── example ├── example_tgsnake.config.js └── custom_context.ts ├── .yarn └── plugins │ └── @yarnpkg │ └── plugin-postinstall.cjs ├── package.json ├── README.md └── .gitignore /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /media/tgsnake.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hamidreza01/tgsnake/HEAD/media/tgsnake.jpg -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx pretty-quick --staged --pattern "src/**/*.*(js|jsx|ts|tsx)" 5 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | semi: true, 3 | singleQuote: true, 4 | printWidth: 100, 5 | tabWidth: 2, 6 | useTabs: false, 7 | trailingComma: 'es5', 8 | bracketSpacing: true, 9 | parser: 'typescript', 10 | }; -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["src/index.ts"], 3 | "out": "beta", 4 | "media" : ["./media"], 5 | "name" : "tgsnake", 6 | "includeVersion" : true, 7 | "hideGenerator": true, 8 | "externalPattern":["./example/*(.js|.ts|.md)"], 9 | "emit" : true, 10 | "logger" : "verbose", 11 | "sort" : "alphabetical" 12 | } -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | plugins: 3 | - path: .yarn/plugins/@yarnpkg/plugin-postinstall.cjs 4 | spec: "https://raw.githubusercontent.com/gravitywelluk/yarn-plugin-postinstall/master/bundles/%40yarnpkg/plugin-postinstall.js" 5 | postinstall: "yarn prepare" 6 | yarnPath: .yarn/releases/yarn-3.2.1.cjs 7 | defaultSemverRangePrefix: "" 8 | lockfileFilename: "yarn.lock" -------------------------------------------------------------------------------- /src/Events/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export { SnakeEvent } from './SnakeEvents'; 9 | export { InterfaceSnakeEvent } from './SnakeEvents'; 10 | -------------------------------------------------------------------------------- /src/Telegram/Users/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export { GetEntity, ResultGetEntity } from './GetEntity'; 9 | export { GetUserPhotos, getUserPhotosMoreParams } from './GetUserPhotos'; 10 | -------------------------------------------------------------------------------- /src/Client/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export { Snake } from './Snake'; 9 | export { ConvertString, ConvertStore } from './ConvertSession'; 10 | export { SnakeSession } from './SnakeSession'; 11 | -------------------------------------------------------------------------------- /src/Interface/CatchError.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import BotError from '../Context/Error'; 9 | import { TypeUpdate } from '../Update'; 10 | export interface CatchError { 11 | (error: BotError, ctx: TypeUpdate); 12 | } 13 | -------------------------------------------------------------------------------- /src/Telegram/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export { Telegram } from './Telegram'; 9 | export * as Users from './Users'; 10 | export * as Bots from './Bots'; 11 | export * as Media from './Media'; 12 | export * as Messages from './Messages'; 13 | export * as Chats from './Chats'; 14 | -------------------------------------------------------------------------------- /src/Telegram/Bots/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export { AnswerInlineQuery, AnswerInlineQueryMoreParams } from './AnswerInlineQuery'; 9 | export { AnswerShippingQuery, ShippingOptions } from './AnswerShippingQuery'; 10 | export { AnswerPrecheckoutQuery } from './AnswerPrecheckoutQuery'; 11 | -------------------------------------------------------------------------------- /src/Interface/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export { ClientOptions, Options } from './Options'; 9 | export { replyMoreParams } from './reply'; 10 | export { CatchError } from './CatchError'; 11 | export { DownloadFileParams, progressCallback } from './Download'; 12 | export { ClickButton } from './Click'; 13 | -------------------------------------------------------------------------------- /tes/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | //import {Snake,GramJs,Composer,Updates} from "../src" 10 | import {Snake,GramJs} from "../src/" 11 | import * as Medias from "../src/Utils/Medias" 12 | import fs from "fs" 13 | import path from "path" 14 | interface MyContext { 15 | hello?:string 16 | } 17 | const bot = new Snake() 18 | bot.log.setLogLevel("debug") 19 | bot.on("message",console.log) 20 | bot.run() -------------------------------------------------------------------------------- /src/Utils/RestrictionReason.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | export class RestrictionReason { 10 | platform!: string; 11 | text!: string; 12 | reason!: string; 13 | constructor(restrictionReason: Api.RestrictionReason) { 14 | this.platform = restrictionReason.platform; 15 | this.text = restrictionReason.text; 16 | this.reason = restrictionReason.reason; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Utils/MigrateTo.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { BigInteger } from 'big-integer'; 10 | import { toString } from './ToBigInt'; 11 | export class MigrateTo { 12 | id!: bigint; 13 | accessHash!: bigint; 14 | constructor(migratedTo: Api.InputChannel) { 15 | this.id = BigInt(toString(migratedTo.channelId) as string); 16 | this.accessHash = BigInt(toString(migratedTo.accessHash) as string); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Utils/Reactions.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | export class Reactions { 10 | chosen?: boolean; 11 | reaction!: string; 12 | count!: number; 13 | constructor(reactions: Api.MessageReactions) { 14 | for (let i = 0; i < reactions.results.length; i++) { 15 | let reaction = reactions.results[i] as Api.ReactionCount; 16 | this.chosen = reaction.chosen; 17 | this.reaction = reaction.reaction; 18 | this.count = reaction.count; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tes/index.js: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2021 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | const {Snake,GramJs} = require("../lib") 10 | const bigInt = require("big-integer") 11 | const bot = new Snake() 12 | bot.log.setLogLevel("debug") 13 | bot.command("start",async (ctx) => { 14 | const msg = await ctx.reply("123456") 15 | await ctx.telegram.editMessage(ctx.chat.id,msg.message.id,"**78901**234",{ 16 | parseMode : "markdown" 17 | /*entities : [{ 18 | type : "bold", 19 | offset : 0, 20 | length : 4 21 | }]*/ 22 | }) 23 | }) 24 | bot.run() -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import BotError from './Context/Error'; 9 | export { Snake } from './Client'; 10 | export { Composer } from './Context/Composer'; 11 | export { BotError }; 12 | 13 | export * as Client from './Client'; 14 | export * as Context from './Context'; 15 | export * as Events from './Events'; 16 | export * as Interface from './Interface'; 17 | export * as Telegram from './Telegram'; 18 | export * as Updates from './Update'; 19 | export * as Utils from './Utils'; 20 | 21 | export * as GramJs from 'telegram'; 22 | -------------------------------------------------------------------------------- /src/Context/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import BotError from './Error'; 9 | export { 10 | MaybeArray, 11 | MaybePromise, 12 | NextFn, 13 | MiddlewareFn, 14 | ErrorHandler, 15 | Middleware, 16 | run, 17 | Composer, 18 | MiddlewareObj, 19 | Combine, 20 | } from './Composer'; 21 | export { MessageContext } from './MessageContext'; 22 | export { BotError }; 23 | export { MainContext } from './MainContext'; 24 | export { EntityCache } from './EntityCache'; 25 | export { Logger, TypeLogLevel, TypeWarningLog, LoggerColor } from './Logger'; 26 | -------------------------------------------------------------------------------- /src/Update/UpdateDeleteMessages.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Update } from './Update'; 10 | import { Api } from 'telegram'; 11 | import { Snake } from '../Client'; 12 | import { Telegram } from '../Telegram'; 13 | 14 | export class UpdateDeleteMessages extends Update { 15 | id!: number[]; 16 | constructor() { 17 | super(); 18 | this['_'] = 'updateDeleteMessages'; 19 | } 20 | async init(update: Api.UpdateDeleteMessages, SnakeClient: Snake) { 21 | SnakeClient.log.debug(`Creating ${this['_']}`); 22 | this.telegram = SnakeClient.telegram; 23 | this.id = update.messages; 24 | return this; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Utils/Medias/Dice.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Media } from './Media'; 10 | import { Snake } from '../../Client'; 11 | import { Cleaning } from '../CleanObject'; 12 | 13 | export class MediaDice extends Media { 14 | emoji!: string; 15 | value!: number; 16 | constructor() { 17 | super(); 18 | this['_'] = 'dice'; 19 | } 20 | async encode(dice: Api.MessageMediaDice, snakeClient: Snake) { 21 | snakeClient.log.debug('Creating MediaDice'); 22 | this.snakeClient = snakeClient; 23 | this.emoji = dice.emoticon; 24 | this.value = dice.value; 25 | await Cleaning(this); 26 | return this; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Update/UpdateMessageID.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Update } from './Update'; 10 | import { Api } from 'telegram'; 11 | import { Snake } from '../Client'; 12 | import { Telegram } from '../Telegram'; 13 | import { BigInteger } from 'big-integer'; 14 | import { toString } from '../Utils/ToBigInt'; 15 | export class UpdateMessageID extends Update { 16 | id!: number; 17 | randomId!: bigint; 18 | constructor() { 19 | super(); 20 | this['_'] = 'updateMessageID'; 21 | } 22 | async init(update: Api.UpdateMessageID, SnakeClient: Snake) { 23 | SnakeClient.log.debug(`Creating ${this['_']}`); 24 | this.telegram = SnakeClient.telegram; 25 | this.id = update.id; 26 | this.randomId = BigInt(toString(update.randomId!) as string); 27 | return this; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Update/UpdateUserName.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Update } from './Update'; 11 | import { From } from '../Utils/From'; 12 | import { Telegram } from '../Telegram'; 13 | import { Snake } from '../Client'; 14 | import { toString } from '../Utils/ToBigInt'; 15 | 16 | export class UpdateUserName extends Update { 17 | user!: From; 18 | constructor() { 19 | super(); 20 | this['_'] = 'updateUserName'; 21 | } 22 | async init(update: Api.UpdateUserName, SnakeClient: Snake) { 23 | SnakeClient.log.debug(`Creating ${this['_']}`); 24 | this.telegram = SnakeClient.telegram; 25 | if (update.userId) { 26 | let user = new From(); 27 | await user.init(BigInt(toString(update.userId!) as string), SnakeClient); 28 | this.user = user; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Utils/Medias/Contact.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Media } from './Media'; 10 | import { Snake } from '../../Client'; 11 | 12 | export class MediaContact extends Media { 13 | phoneNumber!: string; 14 | firstName!: string; 15 | lastName?: string; 16 | vcard!: string; 17 | userId!: bigint; 18 | constructor() { 19 | super(); 20 | this['_'] = 'contact'; 21 | } 22 | encode(contact: Api.MessageMediaContact, snakeClient: Snake) { 23 | snakeClient.log.debug('Creating MediaContact'); 24 | this.snakeClient = snakeClient; 25 | this.phoneNumber = contact.phoneNumber; 26 | this.firstName = contact.firstName; 27 | this.lastName = contact.lastName; 28 | this.vcard = contact.vcard; 29 | this.userId = BigInt(String(contact.userId)); 30 | return this; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 butthx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Telegram/Bots/AnswerPrecheckoutQuery.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import bigInt from 'big-integer'; 12 | import BotError from '../../Context/Error'; 13 | 14 | export async function AnswerPrecheckoutQuery( 15 | snakeClient: Snake, 16 | id: bigint, 17 | ok: boolean, 18 | error?: string 19 | ) { 20 | try { 21 | return await snakeClient.client.invoke( 22 | new Api.messages.SetBotPrecheckoutResults({ 23 | success: ok, 24 | queryId: bigInt(String(id)), 25 | error: error, 26 | }) 27 | ); 28 | } catch (error: any) { 29 | snakeClient.log.error('Failed running telegram.answerPrecheckoutQuery'); 30 | throw new BotError( 31 | error.message, 32 | 'telegram.answerPrecheckoutQuery', 33 | `${id},${ok}${error ? `,${error}` : ''}` 34 | ); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Telegram/Chats/GetInactiveChannels.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import BotError from '../../Context/Error'; 12 | /** 13 | * Get inactive channels and supergroups. 14 | * @param snakeClient - Client 15 | * ```ts 16 | * bot.command("getInactiveChannels",async (ctx) => { 17 | * let results = await ctx.telegram.getInactiveChannels() 18 | * console.log(results) 19 | * }) 20 | * ``` 21 | */ 22 | export async function GetInactiveChannels(snakeClient: Snake) { 23 | try { 24 | snakeClient.log.debug('Running telegram.getInactiveChannels'); 25 | return await snakeClient.client.invoke(new Api.channels.GetInactiveChannels()); 26 | } catch (error: any) { 27 | snakeClient.log.error('Failed to running telegram.getInactiveChannels'); 28 | throw new BotError(error.message, 'telegram.getInactiveChannels', ''); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Telegram/Chats/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export { editAdminMoreParams, EditAdmin } from './EditAdmin'; 9 | export { editBannedMoreParams, EditBanned } from './EditBanned'; 10 | export { EditTitle } from './EditTitle'; 11 | export { GetAdminedPublicChannels } from './GetAdminedPublicChannels'; 12 | export { 13 | ClassResultGetAdminLog, 14 | ClassLogGetAdminLog, 15 | getAdminLogMoreParams, 16 | GetAdminLog, 17 | } from './GetAdminLog'; 18 | export { GetChannels } from './GetChannels'; 19 | export { GetChatMembersCount } from './GetChatMembersCount'; 20 | export { GetFullChat } from './GetFullChat'; 21 | export { GetGroupsForDiscussion } from './GetGroupsForDiscussion'; 22 | export { GetInactiveChannels } from './GetInactiveChannels'; 23 | export { GetLeftChannels } from './GetLeftChannels'; 24 | export { GetParticipant } from './GetParticipant'; 25 | export { GetParticipantMoreParams, GetParticipants } from './GetParticipants'; 26 | -------------------------------------------------------------------------------- /src/Context/Error.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { betterConsoleLog } from '../Utils/CleanObject'; 9 | import { inspect } from 'util'; 10 | export default class BotError extends Error { 11 | functionName!: string; 12 | functionArgs!: string; 13 | message!: string; 14 | date: number = Math.floor(Date.now() / 1000); 15 | /** @hidden */ 16 | _isBotErrorClass: boolean = true; 17 | constructor(message: string, functionName: string, functionArgs: string) { 18 | super(); 19 | this.message = message; 20 | this.functionName = functionName; 21 | this.functionArgs = functionArgs; 22 | return this; 23 | } 24 | /** @hidden */ 25 | [inspect.custom]() { 26 | return betterConsoleLog(this); 27 | } 28 | /** @hidden */ 29 | toJSON() { 30 | let obj = betterConsoleLog(this); 31 | for (let [key, value] of Object.entries(obj)) { 32 | if (typeof value == 'bigint') obj[key] = String(value); 33 | } 34 | return obj; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Update/UpdateNewMessage.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Update } from './Update'; 10 | import { Api } from 'telegram'; 11 | import { Snake } from '../Client'; 12 | import { Telegram } from '../Telegram'; 13 | import { MessageContext } from '../Context/MessageContext'; 14 | export class UpdateNewMessage extends Update { 15 | message!: MessageContext; 16 | constructor() { 17 | super(); 18 | this['_'] = 'updateNewMessage'; 19 | } 20 | async init(update: Api.UpdateNewMessage, SnakeClient: Snake) { 21 | SnakeClient.log.debug(`Creating ${this['_']}`); 22 | this.telegram = SnakeClient.telegram; 23 | let message = new MessageContext(); 24 | if (update.message instanceof Api.Message) { 25 | await message.init(update.message as Api.Message, SnakeClient); 26 | } 27 | if (update.message instanceof Api.MessageService) { 28 | await message.init(update.message as Api.MessageService, SnakeClient); 29 | } 30 | this.message = message; 31 | return this; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Utils/Medias/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export { Media, TypeMessageMediaName } from './Media'; 9 | export { MediaContact } from './Contact'; 10 | export { MediaSticker } from './Sticker'; 11 | export { MediaPoll, IPollAnswer } from './Poll'; 12 | export { MediaDice } from './Dice'; 13 | export { MediaLocation } from './Location'; 14 | export { MediaPhoto } from './Photo'; 15 | export { MediaVenue } from './Venue'; 16 | export { MediaVideoNote } from './VideoNote'; 17 | export { MediaVideo } from './Video'; 18 | export { MediaAnimation } from './Animated'; 19 | export { MediaDocument } from './Document'; 20 | export { MediaAudio } from './Audio'; 21 | export { MediaVoice } from './Voice'; 22 | export { MediaGame } from './Game'; 23 | export { MediaInvoice } from './Invoice'; 24 | export { MediaWebPage } from './WebPage'; 25 | export { MediaChatPhoto } from './ChatPhoto'; 26 | export { 27 | TypeMessageMedia, 28 | GenerateMedia, 29 | TypeMessageMediaDocument, 30 | TypeMessageMediaDownload, 31 | } from './Generator'; 32 | -------------------------------------------------------------------------------- /src/Telegram/Chats/GetLeftChannels.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import BotError from '../../Context/Error'; 12 | /** 13 | * Get a list of channels/supergroups we left. 14 | * @param snakeClient - Client. 15 | * @param {number} offset - offset of pagination. 16 | * ```ts 17 | * bot.command("getLeftChannels",async (ctx) => { 18 | * let results = await ctx.telegram.getLeftChannels() 19 | * console.log(results) 20 | * }) 21 | * ``` 22 | */ 23 | export async function GetLeftChannels(snakeClient: Snake, offset: number = 0) { 24 | try { 25 | snakeClient.log.debug('Running telegram.getLeftChannels'); 26 | return await snakeClient.client.invoke( 27 | new Api.channels.GetLeftChannels({ 28 | offset: offset, 29 | }) 30 | ); 31 | } catch (error: any) { 32 | snakeClient.log.error('Failed to running telegram.getLeftChannels'); 33 | throw new BotError(error.message, 'telegram.getLeftChannels', `${offset}`); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Telegram/Messages/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export { deleteHistoryMoreParams, DeleteHistory } from './DeleteHistory'; 9 | export { ResultAffectedMessages, DeleteMessages } from './DeleteMessages'; 10 | export { DeleteUserHistory } from './DeleteUserHistory'; 11 | export { editMessageMoreParams, EditMessage } from './EditMessage'; 12 | export { exportMessageLinkMoreParams, ExportMessageLink } from './ExportMessageLink'; 13 | export { forwardMessageMoreParams, ForwardMessages } from './ForwardMessages'; 14 | export { GetMessages, ResultsGetMessage } from './GetMessages'; 15 | export { ResultsMessagesViews, Views, GetMessagesViews } from './GetMessagesViews'; 16 | export { pinMessageMoreParams, PinMessage } from './PinMessage'; 17 | export { readHistoryMoreParams, ReadHistory } from './ReadHistory'; 18 | export { ReadMentions } from './ReadMentions'; 19 | export { ReadMessageContents } from './ReadMessageContents'; 20 | export { sendMessageMoreParams, sendMessage } from './sendMessage'; 21 | export { UnpinAllMessages } from './UnpinAllMessages'; 22 | -------------------------------------------------------------------------------- /src/Utils/AdminRights.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | export class AdminRights { 11 | changeInfo?: boolean; 12 | postMessages?: boolean; 13 | editMessages?: boolean; 14 | deleteMessages?: boolean; 15 | banUsers?: boolean; 16 | inviteUsers?: boolean; 17 | pinMessages?: boolean; 18 | addAdmins?: boolean; 19 | anonymous?: boolean; 20 | manageCall?: boolean; 21 | other?: boolean; 22 | constructor(adminRights: Api.ChatAdminRights) { 23 | this.changeInfo = adminRights.changeInfo; 24 | this.postMessages = adminRights.postMessages; 25 | this.editMessages = adminRights.editMessages; 26 | this.deleteMessages = adminRights.deleteMessages; 27 | this.banUsers = adminRights.banUsers; 28 | this.inviteUsers = adminRights.inviteUsers; 29 | this.pinMessages = adminRights.pinMessages; 30 | this.addAdmins = adminRights.addAdmins; 31 | this.anonymous = adminRights.anonymous; 32 | this.manageCall = adminRights.manageCall; 33 | this.other = adminRights.other; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /example/example_tgsnake.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * example config file. (tgsnake.config.js) 3 | * You don't have to create this file. You can put options in ``new Snake({options})`` 4 | */ 5 | module.exports = { 6 | /** 7 | * Set Logger level for gramjs. Default is "none". 8 | */ 9 | logger: "none", 10 | /** 11 | * An api_hash got from my.telegram.org 12 | */ 13 | apiHash: "your api hash here.", 14 | /** 15 | * An api_id got from my.telegram.org 16 | */ 17 | apiId: 123456, 18 | /** 19 | * String sessions. 20 | * if you have the string sessions you can fill this. if not you can fill with blank string. 21 | */ 22 | session: "", 23 | /** 24 | * Bot Token from botFather. If you need to login as bot this required. 25 | * if you need login with user, delete this. 26 | */ 27 | botToken: "paste you bot token in here.", 28 | /** 29 | * Connection Retries for gramjs. Default is 5. 30 | */ 31 | connectionRetries: 5, 32 | /** 33 | * tgsnake console.log 34 | * If set, tgsnake will showing the message in console like welcome to tgsnake or anything. 35 | */ 36 | tgSnakeLog: true, 37 | /** 38 | * session name 39 | * required to save the string session. 40 | */ 41 | sessionName: "tgsnake", 42 | /** 43 | * storeSession 44 | * required to save the session in storage. 45 | */ 46 | storeSession: true 47 | }; -------------------------------------------------------------------------------- /src/Utils/CleanObject.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export function Cleaning(_object: any) { 9 | for (let [key, value] of Object.entries(_object)) { 10 | if (value == null || value == undefined) { 11 | delete _object[key]; 12 | } 13 | } 14 | return _object; 15 | } 16 | export function betterConsoleLog(object: { [key: string]: any }) { 17 | const toPrint: { [key: string]: any } = {}; 18 | for (const key in object) { 19 | if (object.hasOwnProperty(key)) { 20 | if (!key.startsWith('_')) { 21 | toPrint[key] = object[key]; 22 | } else if (key == '_') { 23 | toPrint[key] = object[key]; 24 | } 25 | } 26 | } 27 | return toPrint; 28 | } 29 | export function toJSON(json: any) { 30 | let obj = betterConsoleLog(json); 31 | for (let [key, value] of Object.entries(obj)) { 32 | if (typeof value == 'bigint') obj[key] = String(value); 33 | if (typeof value == 'object' && !Array.isArray(value)) obj[key] = toJSON(value); 34 | if (typeof value == 'object' && Array.isArray(value)) obj[key] = value.map((x) => toJSON(x)); 35 | } 36 | return obj; 37 | } 38 | -------------------------------------------------------------------------------- /src/Update/UpdateNewChannelMessage.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Update } from './Update'; 10 | import { Api } from 'telegram'; 11 | import { Snake } from '../Client'; 12 | import { Telegram } from '../Telegram'; 13 | import { MessageContext } from '../Context/MessageContext'; 14 | import { toString } from '../Utils/ToBigInt'; 15 | 16 | export class UpdateNewChannelMessage extends Update { 17 | message!: MessageContext; 18 | constructor() { 19 | super(); 20 | this['_'] = 'updateNewChannelMessage'; 21 | } 22 | async init(update: Api.UpdateNewChannelMessage, SnakeClient: Snake) { 23 | SnakeClient.log.debug(`Creating ${this['_']}`); 24 | this.telegram = SnakeClient.telegram; 25 | this.message = new MessageContext(); 26 | if (update.message instanceof Api.Message) { 27 | await this.message.init(update.message as Api.Message, SnakeClient); 28 | return this; 29 | } 30 | if (update.message instanceof Api.MessageService) { 31 | await this.message.init(update.message as Api.MessageService, SnakeClient); 32 | return this; 33 | } 34 | return this; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /example/custom_context.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import {Snake} from "tgsnake"; 9 | 10 | interface MyContext { 11 | hello : string, 12 | isMessage : boolean 13 | } 14 | // declare the custom context in Composer. 15 | const bot = new Snake() 16 | // Create the context. 17 | // You can use the Composer.use() 18 | let myContext:MyContext = { 19 | hello : "hello", 20 | isMessage : false 21 | } 22 | // create from the root context to make sure that custom context is effected globally. 23 | bot.context = myContext 24 | // the example using Composer.use() 25 | bot.use((ctx,next)=>{ 26 | myContext.isMessage = true 27 | // re create the custom context from root. 28 | bot.context = myContext 29 | return next() 30 | }) 31 | bot.cmd("start",(ctx)=>{ 32 | // get the custom context 33 | console.log(ctx) 34 | ctx.reply(ctx.hello) 35 | }) 36 | 37 | /** 38 | * FAQ : 39 | * Q: Why we must create from root context not from ctx? 40 | * A: Because we have a different context from Composer.use and Composer.on, so if you custom from ctx, the custom context maybe not appears in other ctx like MessageContext, ResultsGetEntity. 41 | */ -------------------------------------------------------------------------------- /src/Interface/reply.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import Parser, { Entities } from '@tgsnake/parser'; 10 | import { TypeReplyMarkup } from '../Utils/ReplyMarkup'; 11 | export interface replyMoreParams { 12 | /** 13 | * Set this flag to disable generation of the webpage preview 14 | */ 15 | noWebpage?: boolean; 16 | /** 17 | * Send this message silently (no notifications for the receivers) 18 | */ 19 | silent?: boolean; 20 | /** 21 | * Send this message as background message 22 | */ 23 | background?: boolean; 24 | /** 25 | * send message with parse mode. 26 | */ 27 | clearDraft?: boolean; 28 | /** 29 | * The message ID to which this message will reply to 30 | */ 31 | replyToMsgId?: number; 32 | /** 33 | * Reply markup for sending bot buttons 34 | */ 35 | replyMarkup?: TypeReplyMarkup; 36 | /** 37 | * Message entities for sending styled text. 38 | */ 39 | entities?: Entities[]; 40 | /** 41 | * Scheduled message date for scheduled messages. 42 | */ 43 | scheduleDate?: number; 44 | /** 45 | * parse mode 46 | */ 47 | parseMode?: string; 48 | } 49 | -------------------------------------------------------------------------------- /.yarn/plugins/@yarnpkg/plugin-postinstall.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | module.exports = { 3 | name: "@yarnpkg/plugin-postinstall", 4 | factory: function (require) { 5 | var plugin;(()=>{"use strict";var e={d:(t,n)=>{for(var o in n)e.o(n,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{default:()=>c});const n=require("@yarnpkg/core"),o=require("@yarnpkg/shell"),r=require("clipanion"),l={postinstall:{description:"Postinstall hook that will always run in Yarn v2",type:n.SettingsType.STRING,default:""}};var i=function(e,t,n,o){var r,l=arguments.length,i=l<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,n):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,n,o);else for(var a=e.length-1;a>=0;a--)(r=e[a])&&(i=(l<3?r(i):l>3?r(t,n,i):r(t,n))||i);return l>3&&i&&Object.defineProperty(t,n,i),i};class a extends r.Command{async execute(){const e=(await n.Configuration.find(this.context.cwd,this.context.plugins)).get("postinstall");e&&o.execute(e)}}i([r.Command.Path("postinstall")],a.prototype,"execute",null);const c={configuration:l,commands:[a],hooks:{afterAllInstalled:e=>{const t=e.configuration.get("postinstall");t&&(console.log("Running postinstall script..."),o.execute(t))}}};plugin=t})(); 6 | return plugin; 7 | } 8 | }; -------------------------------------------------------------------------------- /src/Update/UpdateEditMessage.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { From } from '../Utils/From'; 11 | import { Update } from './Update'; 12 | import { Telegram } from '../Telegram'; 13 | import { Snake } from '../Client'; 14 | import { BigInteger } from 'big-integer'; 15 | import { MessageContext } from '../Context/MessageContext'; 16 | import Util from 'tg-file-id/dist/Util'; 17 | import { toString } from '../Utils/ToBigInt'; 18 | 19 | export class UpdateEditMessage extends Update { 20 | message!: MessageContext; 21 | constructor() { 22 | super(); 23 | this['_'] = 'updateEditMessage'; 24 | } 25 | async init(update: Api.UpdateEditMessage, SnakeClient: Snake) { 26 | SnakeClient.log.debug(`Creating ${this['_']}`); 27 | this.telegram = SnakeClient.telegram; 28 | let message = new MessageContext(); 29 | if (update.message instanceof Api.Message) { 30 | await message.init(update.message as Api.Message, SnakeClient); 31 | } 32 | if (update.message instanceof Api.MessageService) { 33 | await message.init(update.message as Api.MessageService, SnakeClient); 34 | } 35 | this.message = message; 36 | return this; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Utils/BannedRight.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | export class BannedRights { 10 | viewMessages?: boolean; 11 | sendMessages?: boolean; 12 | sendMedia?: boolean; 13 | sendStickers?: boolean; 14 | sendGifs?: boolean; 15 | sendGames?: boolean; 16 | sendInline?: boolean; 17 | embedLinks?: boolean; 18 | sendPolls?: boolean; 19 | changeInfo?: boolean; 20 | inviteUsers?: boolean; 21 | pinMessages?: boolean; 22 | untilDate: number; 23 | constructor(bannedRights: Api.ChatBannedRights) { 24 | this.viewMessages = bannedRights.viewMessages; 25 | this.sendMessages = bannedRights.sendMessages; 26 | this.sendMedia = bannedRights.sendMedia; 27 | this.sendStickers = bannedRights.sendStickers; 28 | this.sendGifs = bannedRights.sendGifs; 29 | this.sendGames = bannedRights.sendGames; 30 | this.sendInline = bannedRights.sendInline; 31 | this.embedLinks = bannedRights.embedLinks; 32 | this.sendPolls = bannedRights.sendPolls; 33 | this.changeInfo = bannedRights.changeInfo; 34 | this.inviteUsers = bannedRights.inviteUsers; 35 | this.pinMessages = bannedRights.pinMessages; 36 | this.untilDate = bannedRights.untilDate; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Update/UpdateEditChannelMessage.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { From } from '../Utils/From'; 11 | import { Update } from './Update'; 12 | import { Telegram } from '../Telegram'; 13 | import { Snake } from '../Client'; 14 | import { BigInteger } from 'big-integer'; 15 | import { MessageContext } from '../Context/MessageContext'; 16 | import Util from 'tg-file-id/dist/Util'; 17 | import { toString } from '../Utils/ToBigInt'; 18 | 19 | export class UpdateEditChannelMessage extends Update { 20 | message!: MessageContext; 21 | constructor() { 22 | super(); 23 | this['_'] = 'updateEditChannelMessage'; 24 | } 25 | async init(update: Api.UpdateEditChannelMessage, SnakeClient: Snake) { 26 | SnakeClient.log.debug(`Creating ${this['_']}`); 27 | this.telegram = SnakeClient.telegram; 28 | let message = new MessageContext(); 29 | if (update.message instanceof Api.Message) { 30 | await message.init(update.message as Api.Message, SnakeClient); 31 | } 32 | if (update.message instanceof Api.MessageService) { 33 | await message.init(update.message as Api.MessageService, SnakeClient); 34 | } 35 | this.message = message; 36 | return this; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Utils/Medias/Venue.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Media } from './Media'; 10 | import { Snake } from '../../Client'; 11 | import { Cleaning } from '../CleanObject'; 12 | 13 | export class MediaVenue extends Media { 14 | latitude!: number; 15 | longitude!: number; 16 | accessHash!: bigint; 17 | accuracyRadius!: number; 18 | title!: string; 19 | address!: string; 20 | provider!: string; 21 | id!: string; 22 | type!: string; 23 | constructor() { 24 | super(); 25 | this['_'] = 'venue'; 26 | } 27 | async encode(venue: Api.MessageMediaVenue, snakeClient: Snake) { 28 | snakeClient.log.debug('Creating MediaVenue'); 29 | this.snakeClient = snakeClient; 30 | if (venue.geo instanceof Api.GeoPoint) { 31 | const geo = venue.geo as Api.GeoPoint; 32 | this.latitude = geo.lat; 33 | this.longitude = geo.long; 34 | this.accessHash = BigInt(String(geo.accessHash ?? 0)); 35 | this.accuracyRadius = geo.accuracyRadius ?? 0; 36 | } 37 | this.title = venue.title; 38 | this.provider = venue.provider; 39 | this.address = venue.address; 40 | this.id = venue.venueId; 41 | this.type = venue.venueType; 42 | await Cleaning(this); 43 | return this; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Utils/Medias/Invoice.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Media } from './Media'; 10 | import { Snake } from '../../Client'; 11 | import { Cleaning } from '../CleanObject'; 12 | // TODO : 13 | // convert _photo to tgsnake json 14 | export class MediaInvoice extends Media { 15 | /** @hidden */ 16 | _photo?: Api.TypeWebDocument; 17 | shippingAddressRequested?: boolean; 18 | test?: boolean; 19 | receiptMsgId?: number; 20 | title!: string; 21 | description!: string; 22 | currency!: string; 23 | totalAmount!: bigint; 24 | startParam!: string; 25 | constructor() { 26 | super(); 27 | this['_'] = 'invoice'; 28 | } 29 | async encode(invoice: Api.MessageMediaInvoice, snakeClient: Snake) { 30 | snakeClient.log.debug('Creating MediaInvoice'); 31 | this.snakeClient = snakeClient; 32 | this.title = invoice.title; 33 | this.description = invoice.description; 34 | this.currency = invoice.currency; 35 | this.totalAmount = BigInt(String(invoice.totalAmount)); 36 | this.startParam = invoice.startParam; 37 | this._photo = invoice.photo; 38 | this.shippingAddressRequested = invoice.shippingAddressRequested; 39 | this.test = invoice.test; 40 | this.receiptMsgId = invoice.receiptMsgId; 41 | return this; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Telegram/Chats/GetGroupsForDiscussion.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import BotError from '../../Context/Error'; 12 | /** 13 | * Get all groups that can be used as discussion groups.
14 | * Returned legacy group chats must be first upgraded to supergroups before they can be set as a discussion group.
15 | * To set a returned supergroup as a discussion group, access to its old messages must be enabled using channels.togglePreHistoryHidden, first.
16 | * @param snakeClient - client 17 | * ```ts 18 | * bot.command("getGroupsForDiscussion",async (ctx) => { 19 | * let results = await ctx.telegram.getGroupsForDiscussion() 20 | * console.log(results) 21 | * }) 22 | * ``` 23 | */ 24 | export async function GetGroupsForDiscussion(snakeClient: Snake) { 25 | try { 26 | snakeClient.log.debug('Running telegram.getGroupsForDiscussion'); 27 | let results: Api.messages.TypeChats = await snakeClient.client.invoke( 28 | new Api.channels.GetGroupsForDiscussion() 29 | ); 30 | return results; 31 | } catch (error: any) { 32 | snakeClient.log.error('Failed to running telegram.getGroupsForDiscussion'); 33 | throw new BotError(error.message, 'telegram.getGroupsForDiscussion', ''); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Telegram/Media/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export { EditPhoto } from './EditPhoto'; 9 | export { FileInfo, GetFileInfo } from './GetFileInfo'; 10 | export { sendDocumentMoreParams, SendDocument } from './SendDocument'; 11 | export { SendPhoto, sendPhotoMoreParams } from './SendPhoto'; 12 | export { SendMedia, sendMediaMoreParams, defaultSendMediaMoreParams } from './SendMedia'; 13 | export { SendSticker } from './SendSticker'; 14 | export { uploadFileMoreParams, onProgress, inRange, UploadFile } from './UploadFile'; 15 | export { Download } from './Download'; 16 | export { sendVideoMoreParams, SendVideo } from './SendVideo'; 17 | export { sendVideoNoteMoreParams, SendVideoNote } from './SendVideoNote'; 18 | export { sendAnimationMoreParams, SendAnimation } from './SendAnimation'; 19 | export { sendAudioMoreParams, SendAudio } from './SendAudio'; 20 | export { sendVoiceMoreParams, SendVoice } from './SendVoice'; 21 | export { SendDice } from './SendDice'; 22 | export { SendContact, InterfaceContact } from './SendContact'; 23 | export { sendPollMoreParams, SendPoll, InterfacePoll } from './SendPoll'; 24 | export { SendLocation, InterfaceLocation } from './SendLocation'; 25 | export { SendVenue, InterfaceVenue } from './SendVenue'; 26 | export { SendInvoice, sendInvoiceParams, InvoicePricesLabel } from './SendInvoice'; 27 | -------------------------------------------------------------------------------- /src/Update/UpdateShortSentMessage.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Update } from './Update'; 10 | import { Api } from 'telegram'; 11 | import { Snake } from '../Client'; 12 | import { Telegram } from '../Telegram'; 13 | import Parser, { Entities } from '@tgsnake/parser'; 14 | import { TypeMessageMedia, GenerateMedia } from '../Utils/Medias'; 15 | import { MessageContext } from '../Context/MessageContext'; 16 | const parser = new Parser(Api); 17 | export class UpdateShortSentMessage extends Update { 18 | message!: MessageContext; 19 | constructor() { 20 | super(); 21 | this['_'] = 'updateShortSentMessage'; 22 | } 23 | async init(update: Api.UpdateShortSentMessage, SnakeClient: Snake) { 24 | SnakeClient.log.debug(`Creating ${this['_']}`); 25 | this.message = new MessageContext(); 26 | this.telegram = SnakeClient.telegram; 27 | this.message.out = update.out; 28 | this.message.id = update.id; 29 | this.message.date = update.date; 30 | this.message.ttlPeriod = update.ttlPeriod; 31 | if (update.media) { 32 | this.message.media = await GenerateMedia(update.media!, SnakeClient); 33 | } 34 | if (update.entities) { 35 | this.message.entities = parser.fromRaw(update.entities); 36 | } 37 | this.message.SnakeClient = SnakeClient; 38 | return this; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Utils/ToBigInt.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import bigInt, { BigInteger, isInstance } from 'big-integer'; 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../Client'; 11 | export async function toBigInt(Ids: bigint | number | string, SnakeClient: Snake) { 12 | let e = await SnakeClient.telegram.getEntity(Ids, true); 13 | let id = bigInt(String(e.id).replace('-100', '').replace('-', '')); 14 | let d = 15 | e.type == 'channel' || e.type == 'supergroup' 16 | ? new Api.PeerChannel({ 17 | channelId: id, 18 | }) 19 | : e.type == 'chat' 20 | ? new Api.PeerChat({ 21 | chatId: id, 22 | }) 23 | : new Api.PeerUser({ 24 | userId: id, 25 | }); 26 | return [id as BigInteger, e.type, d]; 27 | } 28 | export function toString(Ids: BigInteger | number | null | string) { 29 | if (Ids == null) { 30 | return 0; 31 | } 32 | if (isInstance(Ids)) { 33 | //@ts-ignore 34 | return String(Ids); 35 | } 36 | //@ts-ignore 37 | return String(Ids); 38 | } 39 | export function convertId(ids: bigint | number | string) { 40 | if (typeof ids == 'bigint') { 41 | return bigInt(ids as bigint) as BigInteger; 42 | } 43 | if (typeof ids == 'number') { 44 | return bigInt(String(ids)) as BigInteger; 45 | } 46 | return String(ids) as string; 47 | } 48 | -------------------------------------------------------------------------------- /src/Utils/index.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export { AdminRights } from './AdminRights'; 9 | export { BannedRights } from './BannedRight'; 10 | export { Chat } from './Chat'; 11 | export { 12 | UserStatus, 13 | ChannelParticipant, 14 | ChatParticipant, 15 | ChatParticipantCreator, 16 | ChatParticipantAdmin, 17 | TypeChatParticipant, 18 | ChatParticipantsForbidden, 19 | ChatParticipants, 20 | TypeChatParticipants, 21 | } from './ChatParticipants'; 22 | export { Cleaning, betterConsoleLog, toJSON } from './CleanObject'; 23 | export { ForwardMessage } from './ForwardMessage'; 24 | export { From } from './From'; 25 | export { Message } from './Message'; 26 | export { MessageAction } from './MessageAction'; 27 | export { MigrateTo } from './MigrateTo'; 28 | export { PaymentRequestedInfo, PostAddress, PaymentCharge } from './Payment'; 29 | export { Reactions } from './Reactions'; 30 | export { 31 | TypeReplyMarkup, 32 | forceReplyMarkup, 33 | removeKeyboard, 34 | replyKeyboard, 35 | replyKeyboardButton, 36 | inlineKeyboard, 37 | inlineKeyboardButton, 38 | loginUrl, 39 | BotLoginUrl, 40 | BuildReplyMarkup, 41 | convertReplyMarkup, 42 | } from './ReplyMarkup'; 43 | export { RestrictionReason } from './RestrictionReason'; 44 | export { toBigInt, toString, convertId } from './ToBigInt'; 45 | export * as Medias from './Medias'; 46 | -------------------------------------------------------------------------------- /src/Utils/Medias/Location.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Media } from './Media'; 10 | import { Snake } from '../../Client'; 11 | import { Cleaning } from '../CleanObject'; 12 | 13 | export class MediaLocation extends Media { 14 | latitude!: number; 15 | longitude!: number; 16 | accessHash!: bigint; 17 | accuracyRadius!: number; 18 | constructor() { 19 | super(); 20 | this['_'] = 'location'; 21 | } 22 | async encode(location: Api.MessageMediaGeo | Api.TypeGeoPoint, snakeClient: Snake) { 23 | snakeClient.log.debug('Creating MediaLocation'); 24 | this.snakeClient = snakeClient; 25 | const generate = async (geo: Api.GeoPoint) => { 26 | this.latitude = geo.lat; 27 | this.longitude = geo.long; 28 | this.accessHash = BigInt(String(geo.accessHash ?? 0)); 29 | this.accuracyRadius = geo.accuracyRadius ?? 0; 30 | await Cleaning(this); 31 | return this; 32 | }; 33 | if (location instanceof Api.MessageMediaGeo) { 34 | location as Api.MessageMediaGeo; 35 | if (location.geo instanceof Api.GeoPoint) { 36 | location.geo as Api.GeoPoint; 37 | return generate(location.geo!); 38 | } 39 | } 40 | if (location instanceof Api.GeoPoint) { 41 | location as Api.GeoPoint; 42 | return generate(location!); 43 | } 44 | return this; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Telegram/Messages/ReadMessageContents.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { ResultAffectedMessages } from './DeleteMessages'; 12 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 13 | import BotError from '../../Context/Error'; 14 | /** 15 | * Notifies the sender about the recipient having listened a voice message or watched a video. 16 | * @param snakeClient - Client 17 | * @param {Array} messageId - message ids 18 | * ```ts 19 | * bot.on("message",async (ctx)=>{ 20 | * if(ctx.media){ 21 | * let results = await ctx.telegram.readMessageContents([ctx.id]) 22 | * console.log(results) 23 | * } 24 | * }) 25 | * ``` 26 | */ 27 | export async function ReadMessageContents(snakeClient: Snake, messageId: number[]) { 28 | try { 29 | snakeClient.log.debug('Running telegram.readMessageContents'); 30 | return new ResultAffectedMessages( 31 | await snakeClient.client.invoke( 32 | new Api.messages.ReadMessageContents({ 33 | id: messageId, 34 | }) 35 | ) 36 | ); 37 | } catch (error: any) { 38 | snakeClient.log.error('Failed to running telegram.readMessageContents'); 39 | throw new BotError( 40 | error.message, 41 | 'telegram.readMessageContents', 42 | `${JSON.stringify(messageId)}` 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Update/UpdateChatParticipants.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Snake } from '../Client'; 10 | import { Update } from './Update'; 11 | import { Telegram } from '../Telegram'; 12 | import { 13 | TypeChatParticipants, 14 | ChatParticipants, 15 | ChatParticipantsForbidden, 16 | } from '../Utils/ChatParticipants'; 17 | import { Api } from 'telegram'; 18 | 19 | export class UpdateChatParticipants extends Update { 20 | participants!: TypeChatParticipants; 21 | constructor() { 22 | super(); 23 | this['_'] = 'updateChatParticipants'; 24 | } 25 | async init(update: Api.UpdateChatParticipants, SnakeClient: Snake) { 26 | SnakeClient.log.debug(`Creating ${this['_']}`); 27 | this.telegram = SnakeClient.telegram; 28 | if (update.participants) { 29 | if (update.participants instanceof Api.ChatParticipants) { 30 | let participants = new ChatParticipants(); 31 | await participants.init(update.participants as Api.ChatParticipants, SnakeClient); 32 | this.participants = participants; 33 | } 34 | if (update.participants instanceof Api.ChatParticipantsForbidden) { 35 | let participants = new ChatParticipantsForbidden(); 36 | await participants.init(update.participants as Api.ChatParticipantsForbidden, SnakeClient); 37 | this.participants = participants; 38 | } 39 | } 40 | return this; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Interface/Download.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | export interface progressCallback { 9 | ( 10 | /** float between 0 and 1 */ 11 | progress: number, 12 | /** other args to be passed if needed */ 13 | ...args: any[] 14 | ): void; 15 | /** When this value is set to true the download will stop */ 16 | isCanceled?: boolean; 17 | /** Does nothing for now. */ 18 | acceptsBuffer?: boolean; 19 | } 20 | /** 21 | * Low level interface for downloading files 22 | */ 23 | export interface DownloadFileParams { 24 | /** The dcId that the file belongs to. Used to borrow a sender from that DC */ 25 | dcId?: number; 26 | /** How much to download. The library will download until it reaches this amount.
27 | * can be useful for downloading by chunks */ 28 | fileSize?: number; 29 | /** Used to determine how many download tasks should be run in parallel. anything above 16 is unstable. */ 30 | workers?: number; 31 | /** How much to download in each chunk. The larger the less requests to be made. (max is 512kb). */ 32 | partSizeKb?: number; 33 | /** Where to start downloading. useful for chunk downloading. */ 34 | start?: number; 35 | /** Where to stop downloading. useful for chunk downloading. */ 36 | end?: number; 37 | /** Progress callback accepting one param. (progress :number) which is a float between 0 and 1 */ 38 | progressCallback?: progressCallback; 39 | } 40 | -------------------------------------------------------------------------------- /src/Update/UpdateBotShippingQuery.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { From } from '../Utils/From'; 11 | import { Update } from './Update'; 12 | import { Telegram } from '../Telegram'; 13 | import { Snake } from '../Client'; 14 | import { BigInteger } from 'big-integer'; 15 | import Util from 'tg-file-id/dist/Util'; 16 | import { toString } from '../Utils/ToBigInt'; 17 | import { PostAddress } from '../Utils/Payment'; 18 | import { ShippingOptions } from '../Telegram/Bots'; 19 | export class UpdateBotShippingQuery extends Update { 20 | id!: bigint; 21 | from!: From; 22 | payload!: string; 23 | shippingAddress!: PostAddress; 24 | constructor() { 25 | super(); 26 | this['_'] = 'updateBotShippingQuery'; 27 | } 28 | async init(update: Api.UpdateBotShippingQuery, SnakeClient: Snake) { 29 | SnakeClient.log.debug(`Creating ${this['_']}`); 30 | this.telegram = SnakeClient.telegram; 31 | this.id = BigInt(String(update.queryId)); 32 | this.payload = update.payload.toString('utf8'); 33 | this.shippingAddress = new PostAddress(update.shippingAddress!); 34 | this.from = new From(); 35 | await this.from.init(BigInt(String(update.userId)), SnakeClient); 36 | return this; 37 | } 38 | async answer(options?: Array, error?: string) { 39 | return this.telegram.answerShippingQuery(this.id, options, error); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Utils/Payment.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | 11 | export class PaymentRequestedInfo { 12 | name?: string; 13 | phone?: string; 14 | email?: string; 15 | shippingAddress?: PostAddress; 16 | constructor(paymentRequest: Api.PaymentRequestedInfo) { 17 | if (paymentRequest.name) this.name = paymentRequest.name; 18 | if (paymentRequest.phone) this.phone = paymentRequest.phone; 19 | if (paymentRequest.email) this.email = paymentRequest.email; 20 | if (paymentRequest.shippingAddress) 21 | this.shippingAddress = new PostAddress(paymentRequest.shippingAddress); 22 | } 23 | } 24 | export class PostAddress { 25 | streetLine1!: string; 26 | streetLine2!: string; 27 | city!: string; 28 | state!: string; 29 | countryIso2!: string; 30 | postCode!: string; 31 | constructor(postAddress: Api.PostAddress) { 32 | this.streetLine1 = postAddress.streetLine1; 33 | this.streetLine2 = postAddress.streetLine2; 34 | this.city = postAddress.city; 35 | this.state = postAddress.state; 36 | this.countryIso2 = postAddress.countryIso2; 37 | this.postCode = postAddress.postCode; 38 | return this; 39 | } 40 | } 41 | export class PaymentCharge { 42 | id!: string; 43 | providerChargeId!: string; 44 | constructor(paymentCharge: Api.PaymentCharge) { 45 | this.id = paymentCharge.id; 46 | this.providerChargeId = paymentCharge.providerChargeId; 47 | return this; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tgsnake", 3 | "version": "2.0.0", 4 | "description": "Telegram MTProto framework base gram.js", 5 | "main": "./lib/index.js", 6 | "scripts": { 7 | "dev": "ts-node ./tes/index.ts --project ./tsconfig.json", 8 | "build": "rm -rf ./lib && tsc", 9 | "pretty-quick": "pretty-quick --staged --pattern \"src/**/*.*(js|jsx|ts|tsx)\"", 10 | "prettier": "prettier -w ./src", 11 | "update": "yarn up \"**\" --interactive", 12 | "prepare": "husky install && echo \"🐍 Building snake package.\" && rm -rf ./lib && tsc" 13 | }, 14 | "homepage": "https://tgsnake.js.org", 15 | "keywords": [ 16 | "tgsnake", 17 | "telegram", 18 | "mtproto", 19 | "gramjs", 20 | "userbot" 21 | ], 22 | "bugs": "https://github.com/tgsnake/tgsnake/issues", 23 | "repository": "https://github.com/tgsnake/tgsnake", 24 | "author": "butthx", 25 | "license": "MIT", 26 | "files": [ 27 | "lib/**/*" 28 | ], 29 | "dependencies": { 30 | "@tgsnake/parser": "1.1.1", 31 | "axios": "0.27.2", 32 | "big-integer": "1.6.51", 33 | "chalk": "4.1.2", 34 | "file-type": "16.5.3", 35 | "husky": "8.0.1", 36 | "prompts": "2.4.2", 37 | "telegram": "2.8.4", 38 | "tg-file-id": "https://github.com/butthx/tg-file-id#prebuild", 39 | "util": "^0.12.4" 40 | }, 41 | "devDependencies": { 42 | "@types/node": "17.0.35", 43 | "dotenv": "16.0.1", 44 | "prettier": "2.6.2", 45 | "pretty-quick": "3.1.3", 46 | "ts-node": "10.8.1", 47 | "typedoc": "0.22.15", 48 | "typescript": "4.7.3" 49 | }, 50 | "engineStrict": true, 51 | "engines": { 52 | "node": ">=10.0.0", 53 | "npm": ">=6.0.0", 54 | "yarn": ">=1.0.0" 55 | }, 56 | "packageManager": "yarn@3.2.1" 57 | } 58 | -------------------------------------------------------------------------------- /src/Telegram/Messages/ReadMentions.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { ResultAffectedMessages } from './DeleteMessages'; 12 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 13 | import BotError from '../../Context/Error'; 14 | /** 15 | * Mark mentions as read. 16 | * @param snakeClient - client 17 | * @param {string|number|bigint} chatId - Chat/Groups/Channel id. 18 | * ```ts 19 | * bot.command("readMentions",async (ctx)=>{ 20 | * let results = await ctx.telegram.readMentions(ctx.chat.id) 21 | * console.log(results) 22 | * }) 23 | * ``` 24 | */ 25 | export async function ReadMentions(snakeClient: Snake, chatId: number | string | bigint) { 26 | try { 27 | snakeClient.log.debug('Running telegram.readMentions'); 28 | if (typeof chatId === 'number') 29 | snakeClient.log.warning( 30 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 31 | ); 32 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 33 | return new ResultAffectedMessages( 34 | await snakeClient.client.invoke( 35 | new Api.messages.ReadMentions({ 36 | peer: peer, 37 | }) 38 | ) 39 | ); 40 | } catch (error: any) { 41 | snakeClient.log.error('Failed to running telegram.readMentions'); 42 | throw new BotError(error.message, 'telegram.readMentions', ''); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Client/ConvertSession.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { StringSession, StoreSession } from 'telegram/sessions'; 9 | import { SnakeSession } from './SnakeSession'; 10 | import { Api } from 'telegram'; 11 | import BotError from '../Context/Error'; 12 | import { Snake } from './Snake'; 13 | export async function ConvertString(session: string, sessionName: string, snakeClient: Snake) { 14 | snakeClient.log.debug('Converting string session to store session.'); 15 | let stringsession = new StringSession(session); 16 | if (sessionName !== '' && session !== '') { 17 | let storesession = new SnakeSession(sessionName, snakeClient); 18 | await stringsession.load(); 19 | storesession.setDC(stringsession.dcId, stringsession.serverAddress!, stringsession.port!); 20 | storesession.setAuthKey(stringsession.authKey); 21 | return storesession; 22 | } else { 23 | return stringsession; 24 | } 25 | } 26 | export async function ConvertStore(sessionName: string, snakeClient: Snake) { 27 | snakeClient.log.debug('Converting store session to string session.'); 28 | let stringsession = new StringSession(''); 29 | if (sessionName !== '') { 30 | let storesession = new SnakeSession(sessionName, snakeClient); 31 | await storesession.load(); 32 | stringsession.setDC(storesession.dcId, storesession.serverAddress!, storesession.port!); 33 | stringsession.setAuthKey(storesession.authKey!); 34 | return stringsession; 35 | } 36 | return stringsession; 37 | } 38 | -------------------------------------------------------------------------------- /src/Telegram/Messages/UnpinAllMessages.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { ResultAffectedMessages } from './DeleteMessages'; 12 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 13 | import BotError from '../../Context/Error'; 14 | /** 15 | * Unpin all message in chats. 16 | * @param snakeClient - Client 17 | * @param {string|number|bigint} chatId - Chat/Groups/Channel id. 18 | * ```ts 19 | * bot.command("unpinAll",async (ctx)=>{ 20 | * let results = await ctx.telegram.unpinAllMessages(ctx.chat.id) 21 | * console.log(results) 22 | * }) 23 | * ``` 24 | */ 25 | export async function UnpinAllMessages(snakeClient: Snake, chatId: number | string | bigint) { 26 | try { 27 | snakeClient.log.debug('Running telegram.unpinAllMessages'); 28 | if (typeof chatId === 'number') 29 | snakeClient.log.warning( 30 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 31 | ); 32 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 33 | return new ResultAffectedMessages( 34 | await snakeClient.client.invoke( 35 | new Api.messages.UnpinAllMessages({ 36 | peer: peer, 37 | }) 38 | ) 39 | ); 40 | } catch (error: any) { 41 | snakeClient.log.error('Failed to running telegram.unpinAllMessages'); 42 | throw new BotError(error.message, 'telegram.unpinAllMessages', `${chatId}`); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Update/UpdateUserStatus.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Update } from './Update'; 11 | import { From } from '../Utils/From'; 12 | import { Telegram } from '../Telegram'; 13 | import { Snake } from '../Client'; 14 | import { toString } from '../Utils/ToBigInt'; 15 | 16 | export class UpdateUserStatus extends Update { 17 | user!: From; 18 | status!: string; 19 | constructor() { 20 | super(); 21 | this['_'] = 'updateUserStatus'; 22 | } 23 | async init(update: Api.UpdateUserStatus, SnakeClient: Snake) { 24 | SnakeClient.log.debug(`Creating ${this['_']}`); 25 | this.telegram = SnakeClient.telegram; 26 | if (update.userId) { 27 | let user = new From(); 28 | await user.init(BigInt(toString(update.userId!) as string), SnakeClient); 29 | this.user = user; 30 | } 31 | if (update.status) { 32 | switch (update.status.className) { 33 | case 'UserStatusOnline': 34 | this.status = 'online'; 35 | break; 36 | case 'UserStatusOffline': 37 | this.status = 'offline'; 38 | break; 39 | case 'UserStatusRecently': 40 | this.status = 'recently'; 41 | break; 42 | case 'UserStatusLastWeek': 43 | this.status = 'withinWeek'; 44 | break; 45 | case 'UserStatusLastMonth': 46 | this.status = 'withinMonth'; 47 | break; 48 | default: 49 | this.status = 'longTimeAgo'; 50 | } 51 | } 52 | return this; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Utils/ForwardMessage.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Chat } from './Chat'; 10 | import { From } from './From'; 11 | import { Snake } from '../Client'; 12 | import { Cleaning } from './CleanObject'; 13 | export class ForwardMessage { 14 | imported?: boolean; 15 | from!: From; 16 | fromName?: string; 17 | date!: number | Date; 18 | channelPost?: number; 19 | postAuthor?: string; 20 | savedFromChat?: Chat; 21 | savedFromMsgId?: number; 22 | psaType?: string; 23 | constructor() {} 24 | async init(forwardHeader: Api.MessageFwdHeader, snakeClient: Snake) { 25 | snakeClient.log.debug(`Creating forwardMessage`); 26 | this.imported = forwardHeader.imported; 27 | this.fromName = forwardHeader.fromName; 28 | this.date = forwardHeader.date; 29 | this.channelPost = forwardHeader.channelPost; 30 | this.postAuthor = forwardHeader.postAuthor; 31 | this.savedFromMsgId = forwardHeader.savedFromMsgId; 32 | this.psaType = forwardHeader.psaType; 33 | if (forwardHeader.fromId) { 34 | try { 35 | let from = new From(); 36 | await from.init(forwardHeader.fromId, snakeClient); 37 | this.from = from; 38 | } catch (error) {} 39 | } 40 | if (forwardHeader.savedFromPeer) { 41 | try { 42 | let chat = new Chat(); 43 | await chat.init(forwardHeader.savedFromPeer, snakeClient); 44 | this.savedFromChat = chat; 45 | } catch (error) {} 46 | } 47 | await Cleaning(this); 48 | return this; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Interface/Click.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { inlineKeyboardButton, replyKeyboardButton } from '../Utils'; 10 | import * as Medias from '../Utils/Medias'; 11 | export interface ClickButton { 12 | /** 13 | * Row button position. 14 | * Row index start with zero. 15 | * [ 16 | * row 0 : [ col 0 , col 1], 17 | * row 1 : [ col 0 , col 1] 18 | * ] 19 | */ 20 | row?: number; 21 | /** 22 | * column button position. 23 | * column index start with zero. 24 | * [ 25 | * row 0 : [ col 0 , col 1], 26 | * row 1 : [ col 0 , col 1] 27 | * ] 28 | */ 29 | col?: number; 30 | /** 31 | * find one the button when text of button is matches 32 | */ 33 | text?: string | { (text: string, row: number, col: number): boolean | Promise }; 34 | /** 35 | * Make a filter to get the row,col of button. it must be returned a boolean. 36 | */ 37 | filter?: { 38 | (keyboard: replyKeyboardButton | inlineKeyboardButton, row: number, col: number): 39 | | boolean 40 | | Promise; 41 | }; 42 | /** 43 | * find one the button when callbackData of button is matches 44 | */ 45 | callbackData?: string; 46 | /** 47 | * Phone will be send when button clicked 48 | */ 49 | sharePhone?: boolean | string | Medias.MediaContact; 50 | /** 51 | * Location will be send when button clicked 52 | */ 53 | shareGeo?: { latitude: number; longitude: number } | Medias.MediaLocation; 54 | /** 55 | * Fill your 2fa password when button clicked. 56 | */ 57 | password?: string; 58 | } 59 | -------------------------------------------------------------------------------- /src/Update/UpdateBotPrecheckoutQuery.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { From } from '../Utils/From'; 11 | import { Update } from './Update'; 12 | import { Telegram } from '../Telegram'; 13 | import { Snake } from '../Client'; 14 | import { BigInteger } from 'big-integer'; 15 | import Util from 'tg-file-id/dist/Util'; 16 | import { toString } from '../Utils/ToBigInt'; 17 | import { PaymentRequestedInfo } from '../Utils/Payment'; 18 | export class UpdateBotPrecheckoutQuery extends Update { 19 | id!: bigint; 20 | from!: From; 21 | payload!: string; 22 | info?: PaymentRequestedInfo; 23 | shippingOptionId?: string; 24 | currency!: string; 25 | totalAmount!: bigint; 26 | constructor() { 27 | super(); 28 | this['_'] = 'updateBotPrecheckoutQuery'; 29 | } 30 | async init(update: Api.UpdateBotPrecheckoutQuery, SnakeClient: Snake) { 31 | SnakeClient.log.debug(`Creating ${this['_']}`); 32 | this.telegram = SnakeClient.telegram; 33 | this.id = BigInt(String(update.queryId)); 34 | this.payload = update.payload.toString('utf8'); 35 | this.currency = update.currency; 36 | this.totalAmount = BigInt(String(update.totalAmount)); 37 | this.shippingOptionId = update.shippingOptionId; 38 | this.from = new From(); 39 | if (update.info) { 40 | this.info = new PaymentRequestedInfo(update.info!); 41 | } 42 | await this.from.init(BigInt(String(update.userId)), SnakeClient); 43 | return this; 44 | } 45 | async answer(ok: boolean, error?: string) { 46 | return this.telegram.answerPrecheckoutQuery(this.id, ok, error); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Telegram/Chats/GetFullChat.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published.. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import BotError from '../../Context/Error'; 12 | import { toBigInt } from '../../Utils/ToBigInt'; 13 | import { BigInteger } from 'big-integer'; 14 | /** 15 | * Returns full chat/channel info according to its ID. 16 | * @param snakeClient - Client 17 | * @param {number|string|bigint} chatId - Chat/Groups/Channel id. 18 | * ```ts 19 | * bot.command("getFullChat",async (ctx) => { 20 | * let results = await ctx.telegram.getFullChat(ctx.chat.id) 21 | * }) 22 | * ``` 23 | */ 24 | export async function GetFullChat(snakeClient: Snake, chatId: number | string | bigint) { 25 | try { 26 | snakeClient.log.debug('Running telegram.getFullChat'); 27 | if (typeof chatId === 'number') 28 | snakeClient.log.warning( 29 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 30 | ); 31 | let [id, type] = await toBigInt(chatId, snakeClient); 32 | if (type == 'channel' || type == 'supergroup') { 33 | return snakeClient.client.invoke( 34 | new Api.channels.GetFullChannel({ 35 | channel: id as BigInteger, 36 | }) 37 | ); 38 | } else { 39 | return snakeClient.client.invoke( 40 | new Api.messages.GetFullChat({ 41 | chatId: id as BigInteger, 42 | }) 43 | ); 44 | } 45 | } catch (error: any) { 46 | snakeClient.log.error('Failed to running telegram.getFullChat'); 47 | throw new BotError(error.message, 'telegram.getFullChat', `${chatId}`); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Telegram/Messages/ExportMessageLink.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 12 | import BotError from '../../Context/Error'; 13 | export interface exportMessageLinkMoreParams { 14 | thread?: boolean; 15 | grouped?: boolean; 16 | } 17 | /** 18 | * Get link and embed info of a message in a channel/supergroup 19 | * @param snakeClient - client 20 | * @param {number|string|bigint} chatId - supergroup/channel id. 21 | * @param {number} messageId - message id. 22 | * @param {Object} more - more paramaters to use. 23 | */ 24 | export async function ExportMessageLink( 25 | snakeClient: Snake, 26 | chatId: number | string | bigint, 27 | messageId: number, 28 | more?: exportMessageLinkMoreParams 29 | ) { 30 | try { 31 | snakeClient.log.debug('Running telegram.exportMessageLink'); 32 | if (typeof chatId === 'number') 33 | snakeClient.log.warning( 34 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 35 | ); 36 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 37 | return snakeClient.client.invoke( 38 | new Api.channels.ExportMessageLink({ 39 | channel: peer, 40 | id: messageId, 41 | ...more, 42 | }) 43 | ); 44 | } catch (error: any) { 45 | snakeClient.log.error('Failed to running telegram.exportMessageLink'); 46 | throw new BotError( 47 | error.message, 48 | 'telegram.exportMessageLink', 49 | `${chatId},${messageId}${more ? ',' + JSON.stringify(more) : ''}` 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Events/SnakeEvents.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { 10 | _intoIdSet, 11 | DefaultEventInterface, 12 | EventBuilder, 13 | EventCommon, 14 | } from 'telegram/events/common'; 15 | import { Api } from 'telegram'; 16 | import { Snake } from '../Client'; 17 | import { TelegramClient } from 'telegram'; 18 | import bigInt, { BigInteger } from 'big-integer'; 19 | import { ResultGetEntity } from '../Telegram/Users/GetEntity'; 20 | import type { Entity, EntityLike } from 'telegram/define'; 21 | 22 | export interface InterfaceSnakeEvent extends DefaultEventInterface { 23 | func?: { (event: Api.TypeUpdate | Api.TypeUpdates): any }; 24 | } 25 | 26 | export class SnakeEvent extends EventBuilder { 27 | /** @hidden */ 28 | private _SnakeClient!: Snake; 29 | constructor(SnakeClient: Snake, eventParams: InterfaceSnakeEvent) { 30 | let { chats, blacklistChats, func } = eventParams; 31 | super({ chats, blacklistChats, func }); 32 | this._SnakeClient = SnakeClient; 33 | } 34 | async build(update: Api.TypeUpdate | Api.TypeUpdates, callback: undefined, selfId: BigInteger) { 35 | //@ts-ignore 36 | if (update._entities && update._entities.size) { 37 | //@ts-ignore 38 | for (let [key, value] of update._entities.entries()) { 39 | let entities = new ResultGetEntity(); 40 | await entities.init(value!, this._SnakeClient); 41 | this._SnakeClient.log.debug(`Add or Update Entities (${entities.id}) to cache.`); 42 | this._SnakeClient.entityCache.set(entities.id!, entities!); 43 | if (entities.username) this._SnakeClient.entityCache.set(entities.username!, entities!); 44 | } 45 | } 46 | return update; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Telegram/Bots/AnswerShippingQuery.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import bigInt from 'big-integer'; 12 | import BotError from '../../Context/Error'; 13 | import { toJSON } from '../../Utils/CleanObject'; 14 | 15 | export interface ShippingOptions { 16 | id: string; 17 | title: string; 18 | prices: Array<{ amount: bigint; label: string }>; 19 | } 20 | export async function AnswerShippingQuery( 21 | snakeClient: Snake, 22 | id: bigint, 23 | options?: Array, 24 | error?: string 25 | ) { 26 | try { 27 | return await snakeClient.client.invoke( 28 | new Api.messages.SetBotShippingResults({ 29 | queryId: bigInt(String(id)), 30 | error: error, 31 | shippingOptions: options 32 | ? options.map( 33 | (option) => 34 | new Api.ShippingOption({ 35 | id: option.id, 36 | title: option.title, 37 | prices: option.prices.map( 38 | (price) => 39 | new Api.LabeledPrice({ 40 | amount: bigInt(String(price.amount)), 41 | label: price.label, 42 | }) 43 | ), 44 | }) 45 | ) 46 | : undefined, 47 | }) 48 | ); 49 | } catch (error: any) { 50 | snakeClient.log.error('Failed running telegram.answerShippingQuery'); 51 | throw new BotError( 52 | error.message, 53 | 'telegram.answerShippingQuery', 54 | `${id}${options ? `,${JSON.stringify(toJSON(options))}` : ''}${error ? `,${error}` : ''}` 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Telegram/Users/GetUserPhotos.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import bigInt from 'big-integer'; 12 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 13 | import BotError from '../../Context/Error'; 14 | export interface getUserPhotosMoreParams { 15 | offset?: number; 16 | maxId?: bigint; 17 | limit?: number; 18 | } 19 | /** 20 | * Getting all user profile photos. 21 | * @param snakeClient - Client 22 | * @param {number|string|bigint} userId - id of user. 23 | * @param {Object} more - more object for getUserPhotos 24 | * ```ts 25 | * bot.command("getUserPhotos",async (ctx)=>{ 26 | * let results = await ctx.telegram.getUserPhotos(ctx.from.id) 27 | * console.log(results) 28 | * }) 29 | * ``` 30 | */ 31 | export async function GetUserPhotos( 32 | snakeClient: Snake, 33 | userId: number | string | bigint, 34 | more?: getUserPhotosMoreParams 35 | ) { 36 | try { 37 | snakeClient.log.debug('Running telegram.getUserPhotos'); 38 | let [id, type, peer] = await toBigInt(userId, snakeClient); 39 | let results: Api.photos.TypePhotos = await snakeClient.client.invoke( 40 | new Api.photos.GetUserPhotos({ 41 | userId: peer, 42 | offset: more ? more.offset : undefined, 43 | maxId: more ? bigInt(String(more.maxId)) : undefined, 44 | limit: more ? more.limit : undefined, 45 | }) 46 | ); 47 | return results; 48 | } catch (error: any) { 49 | snakeClient.log.error('Failed to running telegram.getUserPhotos'); 50 | throw new BotError( 51 | error.message, 52 | 'telegram.getUserPhotos', 53 | `${userId}${more ? ',' + JSON.stringify(more) : ''}` 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Telegram/Media/SendDice.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { SendMedia, defaultSendMediaMoreParams } from './SendMedia'; 12 | import { TypeReplyMarkup, BuildReplyMarkup } from '../../Utils/ReplyMarkup'; 13 | import * as Medias from '../../Utils/Medias'; 14 | import BotError from '../../Context/Error'; 15 | /** 16 | * Sending Dice 17 | * @param snakeClient - Client 18 | * @param {string|number|bigint} chatId - Chat/Groups/Channel id. 19 | * @param {string|Object} dice - dice emoticon . 20 | * @param {Object} more - more parameters to use. 21 | * ```ts 22 | * bot.command("dice",async (ctx) => { 23 | * let results = await ctx.telegram.sendDice(ctx.chat.id,"🎯") 24 | * }) 25 | * ``` 26 | */ 27 | export async function SendDice( 28 | snakeClient: Snake, 29 | chatId: number | string | bigint, 30 | dice: string | Medias.MediaDice, 31 | more?: defaultSendMediaMoreParams 32 | ) { 33 | try { 34 | snakeClient.log.debug('Running telegram.sendDice'); 35 | if (typeof chatId === 'number') 36 | snakeClient.log.warning( 37 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 38 | ); 39 | //@ts-ignore 40 | let emoji = typeof dice == 'string' ? dice : dice.emoji; 41 | return await SendMedia( 42 | snakeClient, 43 | chatId, 44 | new Api.InputMediaDice({ 45 | emoticon: emoji, 46 | }), 47 | more! 48 | ); 49 | } catch (error: any) { 50 | snakeClient.log.error('Failed to running telegram.sendDice'); 51 | throw new BotError( 52 | error.message, 53 | 'telegram.sendDice', 54 | `${chatId},${dice}${more ? ',' + JSON.stringify(more) : ''}` 55 | ); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Telegram/Chats/GetChannels.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import BotError from '../../Context/Error'; 12 | import bigInt, { BigInteger } from 'big-integer'; 13 | /** 14 | * Get info about channels/supergroups. 15 | * @param snakeClient - Client 16 | * @param {Array} chatId - List of channel ids. 17 | * ```ts 18 | * bot.command("getChannels",async (ctx) => { 19 | * let results = await ctx.telegram.getChannels([ctx.chat.id]) 20 | * console.log(results) 21 | * }) 22 | * ``` 23 | */ 24 | export async function GetChannels(snakeClient: Snake, chatId: number[] | string[] | bigint[]) { 25 | try { 26 | snakeClient.log.debug('Running telegram.GetChannels'); 27 | let id: BigInteger[] | string[] = []; 28 | for (let ids of chatId) { 29 | if (typeof ids == 'string') { 30 | //@ts-ignore 31 | id.push(ids as string); 32 | } 33 | if (typeof ids == 'bigint') { 34 | //@ts-ignore 35 | id.push(bigInt(ids as bigint) as BigInteger); 36 | } 37 | if (typeof ids == 'number') { 38 | snakeClient.log.warning( 39 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 40 | ); 41 | //@ts-ignore 42 | id.push(bigInt(ids as number) as BigInteger); 43 | } 44 | } 45 | let results: Api.messages.TypeChats = await snakeClient.client.invoke( 46 | new Api.channels.GetChannels({ 47 | id: id, 48 | }) 49 | ); 50 | //todo 51 | //change the json results. 52 | return results; 53 | } catch (error: any) { 54 | snakeClient.log.error('Failed to running telegram.getChannels'); 55 | throw new BotError(error.message, 'telegram.getChannels', `${chatId}`); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Update/UpdateInlineBotCallbackQuery.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { From } from '../Utils/From'; 11 | import { Update } from './Update'; 12 | import { Telegram } from '../Telegram'; 13 | import { Snake } from '../Client'; 14 | import { BigInteger } from 'big-integer'; 15 | import { MessageContext } from '../Context/MessageContext'; 16 | import Util from 'tg-file-id/dist/Util'; 17 | import { toString } from '../Utils/ToBigInt'; 18 | export class UpdateInlineBotCallbackQuery extends Update { 19 | id!: bigint; 20 | data?: string; 21 | message?: MessageContext; 22 | from!: From; 23 | chatInstance!: bigint; 24 | inlineMessageId?: string; 25 | gameShortName?: string; 26 | constructor() { 27 | super(); 28 | this['_'] = 'updateInlineBotCallbackQuery'; 29 | } 30 | async init(update: Api.UpdateInlineBotCallbackQuery, SnakeClient: Snake) { 31 | SnakeClient.log.debug(`Creating ${this['_']}`); 32 | this.telegram = SnakeClient.telegram; 33 | this.data = update.data?.toString('utf8'); 34 | this.id = BigInt(toString(update.queryId!) as string); 35 | this.gameShortName = update.gameShortName; 36 | this.chatInstance = BigInt(toString(update.chatInstance) as string); 37 | this.inlineMessageId = ''; 38 | this.inlineMessageId += Util.to32bitBuffer(update.msgId.dcId); 39 | let id = BigInt(String(update.msgId.id)); 40 | let accessHash = BigInt(String(update.msgId.accessHash)); 41 | this.inlineMessageId += Util.to64bitBuffer(accessHash); 42 | this.inlineMessageId += Util.to64bitBuffer(id); 43 | this.inlineMessageId = Util.base64UrlEncode(Util.rleEncode(this.inlineMessageId)); 44 | this.from = new From(); 45 | await this.from.init(BigInt(toString(update.userId) as string), SnakeClient); 46 | return this; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/Telegram/Bots/AnswerInlineQuery.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import bigInt from 'big-integer'; 12 | import BotError from '../../Context/Error'; 13 | 14 | export interface AnswerInlineQueryMoreParams { 15 | gallery?: boolean; 16 | cacheTime?: number; 17 | isPersonal?: boolean; 18 | nextOffset?: string; 19 | switchPmText?: string; 20 | switchPmParameter?: string; 21 | } 22 | let defaultParam: AnswerInlineQueryMoreParams = { 23 | cacheTime: 300, 24 | }; 25 | export async function AnswerInlineQuery( 26 | snakeClient: Snake, 27 | id: bigint, 28 | results: Array, 29 | more: AnswerInlineQueryMoreParams = defaultParam 30 | ) { 31 | try { 32 | snakeClient.log.debug('Running telegram.answerInlineQuery'); 33 | let final = await snakeClient.client.invoke( 34 | new Api.messages.SetInlineBotResults({ 35 | queryId: bigInt(String(id)), 36 | results: results, 37 | gallery: more.gallery, 38 | nextOffset: more.nextOffset, 39 | ...(more.switchPmText || more.switchPmParameter 40 | ? { 41 | switchPm: new Api.InlineBotSwitchPM({ 42 | text: String(more.switchPmText), 43 | startParam: String(more.switchPmParameter), 44 | }), 45 | } 46 | : {}), 47 | cacheTime: more.cacheTime, 48 | private: more.isPersonal, 49 | }) 50 | ); 51 | return final; 52 | } catch (error: any) { 53 | snakeClient.log.error('Failed running telegram.answerInlineQuery'); 54 | throw new BotError( 55 | error.message, 56 | 'telegram.answerInlineQuery', 57 | `${id},${JSON.stringify(results, null, 2)}${more ? ',' + JSON.stringify(more) : ''}` 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Update/UpdateBotInlineQuery.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { From } from '../Utils/From'; 11 | import { Update } from './Update'; 12 | import { Telegram } from '../Telegram'; 13 | import { Snake } from '../Client'; 14 | import { BigInteger } from 'big-integer'; 15 | import * as Medias from '../Utils/Medias'; 16 | import { toString } from '../Utils/ToBigInt'; 17 | export class UpdateBotInlineQuery extends Update { 18 | id!: bigint; 19 | from!: From; 20 | query!: string; 21 | location?: Medias.MediaLocation; 22 | chatType?: string; 23 | offset!: string; 24 | constructor() { 25 | super(); 26 | this['_'] = 'updateBotInlineQuery'; 27 | } 28 | async init(update: Api.UpdateBotInlineQuery, SnakeClient: Snake) { 29 | SnakeClient.log.debug(`Creating ${this['_']}`); 30 | this.telegram = SnakeClient.telegram; 31 | this.id = BigInt(toString(update.queryId!) as string); 32 | this.query = update.query; 33 | this.offset = update.offset; 34 | if (update.peerType instanceof Api.InlineQueryPeerTypeSameBotPM) { 35 | this.chatType = 'sender'; 36 | } 37 | if (update.peerType instanceof Api.InlineQueryPeerTypePM) { 38 | this.chatType = 'private'; 39 | } 40 | if (update.peerType instanceof Api.InlineQueryPeerTypeChat) { 41 | this.chatType = 'group'; 42 | } 43 | if (update.peerType instanceof Api.InlineQueryPeerTypeMegagroup) { 44 | this.chatType = 'superGroup'; 45 | } 46 | if (update.peerType instanceof Api.InlineQueryPeerTypeBroadcast) { 47 | this.chatType = 'channel'; 48 | } 49 | if (update.geo) { 50 | this.location = new Medias.MediaLocation(); 51 | await this.location.encode(update.geo!, SnakeClient); 52 | } 53 | this.from = new From(); 54 | await this.from.init(BigInt(toString(update.userId!) as string), SnakeClient); 55 | return this; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Utils/Medias/Media.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Snake } from '../../Client'; 9 | import { inspect } from 'util'; 10 | import { betterConsoleLog } from '../CleanObject'; 11 | import { FileId, decodeFileId } from 'tg-file-id'; 12 | import { DownloadFileParams } from '../../Interface/Download'; 13 | import BotError from '../../Context/Error'; 14 | export type TypeMessageMediaName = 15 | | 'sticker' //done 16 | | 'document' //done 17 | | 'photo' // done 18 | | 'location' //done 19 | | 'dice' //done 20 | | 'contact' //done 21 | | 'animation' //done 22 | | 'video' //done 23 | | 'poll' //done 24 | | 'venue' // done 25 | | 'videoNote' //done 26 | | 'voice' // done 27 | | 'audio' // done 28 | | 'webPage' //done 29 | | 'game' // done 30 | | 'invoice' // done 31 | | 'chatPhoto'; //done 32 | export class Media { 33 | _!: TypeMessageMediaName; 34 | date!: Date | number; 35 | /** @hidden */ 36 | private _SnakeClient!: Snake; 37 | constructor() { 38 | this.date = Math.floor(Date.now() / 1000); 39 | } 40 | get snakeClient() { 41 | return this._SnakeClient; 42 | } 43 | get SnakeClient() { 44 | return this._SnakeClient; 45 | } 46 | set snakeClient(client: Snake) { 47 | this._SnakeClient = client; 48 | } 49 | set SnakeClient(client: Snake) { 50 | this._SnakeClient = client; 51 | } 52 | decode(fileId?: string) { 53 | //@ts-ignore 54 | let file = fileId ?? this.fileId; 55 | if (!file) throw new BotError(`FileId not found!`, 'Media.decode', ''); 56 | return decodeFileId(String(file)); 57 | } 58 | /** @hidden */ 59 | [inspect.custom]() { 60 | return betterConsoleLog(this); 61 | } 62 | /** @hidden */ 63 | toJSON() { 64 | let obj = betterConsoleLog(this); 65 | for (let [key, value] of Object.entries(obj)) { 66 | if (typeof value == 'bigint') obj[key] = String(value); 67 | } 68 | return obj; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Utils/Medias/WebPage.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Media } from './Media'; 10 | import { Snake } from '../../Client'; 11 | import { Cleaning } from '../CleanObject'; 12 | import { MediaPhoto } from './Photo'; 13 | // TODO: 14 | // convert field document,cachedPage to tgsnake json 15 | export class MediaWebPage extends Media { 16 | id!: bigint; 17 | url!: string; 18 | displayUrl!: string; 19 | hash!: number; 20 | type?: string; 21 | siteName?: string; 22 | title?: string; 23 | description?: string; 24 | photo?: MediaPhoto; 25 | embedUrl?: string; 26 | embedType?: string; 27 | embedWidth?: number; 28 | embedHeight?: number; 29 | duration?: number; 30 | author?: string; 31 | constructor() { 32 | super(); 33 | this['_'] = 'webPage'; 34 | } 35 | async encode(webPage: Api.TypeWebPage, snakeClient: Snake) { 36 | snakeClient.log.debug('Creating MediaWebPage'); 37 | this.snakeClient = snakeClient; 38 | //@ts-ignore 39 | if (webPage.id !== undefined) this.id = BigInt(String(webPage.id!)); 40 | if (webPage instanceof Api.WebPage) { 41 | webPage as Api.WebPage; 42 | this.url = webPage.url; 43 | this.displayUrl = webPage.displayUrl; 44 | this.hash = webPage.hash; 45 | this.type = webPage.type; 46 | this.siteName = webPage.siteName; 47 | this.title = webPage.title; 48 | this.description = webPage.description; 49 | this.embedUrl = webPage.embedUrl; 50 | this.embedType = webPage.embedType; 51 | this.embedWidth = webPage.embedWidth; 52 | this.embedHeight = webPage.embedHeight; 53 | this.duration = webPage.duration; 54 | this.author = webPage.author; 55 | if (webPage.photo) { 56 | this.photo = new MediaPhoto(); 57 | await this.photo.encode(webPage.photo!, snakeClient); 58 | } 59 | } 60 | return this; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Telegram/Chats/GetAdminedPublicChannels.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Snake } from '../../Client'; 10 | import BotError from '../../Context/Error'; 11 | /** 12 | * Get channels/supergroups/geogroups we're admin in. Usually called when the user exceeds the limit for owned public channels/supergroups/geogroups, and the user is given the choice to remove one of his channels/supergroups/geogroups. 13 | * @param snakeClient - client 14 | * @param {boolean} byLocation - Get geogroups. 15 | * @param {boolean} checkLimit - If set and the user has reached the limit of owned public channels/supergroups/geogroups, instead of returning the channel list one of the specified errors will be returned.
16 | * Useful to check if a new public channel can indeed be created, even before asking the user to enter a channel username to use in channels.checkUsername/channels.updateUsername. 17 | * ```ts 18 | * bot.command("getAdminedPublicChannels",async (ctx) => { 19 | * if(!ctx.chat.private){ 20 | * let results = await ctx.telegram.getAdminedPublicChannels() 21 | * console.log(results) 22 | * } 23 | * }) 24 | * ``` 25 | */ 26 | export async function GetAdminedPublicChannels( 27 | snakeClient: Snake, 28 | byLocation: boolean = true, 29 | checkLimit: boolean = true 30 | ) { 31 | try { 32 | snakeClient.log.debug('Running telegram.getAdminedPublicChannels'); 33 | let results: Api.messages.TypeChats = await snakeClient.client.invoke( 34 | new Api.channels.GetAdminedPublicChannels({ 35 | byLocation: byLocation, 36 | checkLimit: checkLimit, 37 | }) 38 | ); 39 | // todo 40 | // change the json results 41 | return results; 42 | } catch (error: any) { 43 | snakeClient.log.error('Failed to running telegram.getAdminedPublicChannels'); 44 | throw new BotError( 45 | error.message, 46 | 'telegram.getAdminedPublicChannels', 47 | `${byLocation},${checkLimit}` 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Telegram/Media/GetFileInfo.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { CustomFile } from 'telegram/client/uploads'; 12 | import path from 'path'; 13 | import fs from 'fs'; 14 | import axios from 'axios'; 15 | import { fromBuffer, fromFile } from 'file-type'; 16 | export interface FileInfo { 17 | mime?: string; 18 | ext?: string; 19 | source: Buffer | string; 20 | fileName?: string; 21 | } 22 | export async function GetFileInfo(file: string | Buffer) { 23 | if (Buffer.isBuffer(file)) { 24 | let fileInfo = await fromBuffer(file); 25 | let r: FileInfo = Object.assign(fileInfo || {}, { 26 | source: file as Buffer, 27 | }); 28 | return r; 29 | } 30 | if (typeof file == 'string') { 31 | file as string; 32 | let basename = path.basename(file); 33 | if (/^http/i.exec(file)) { 34 | let res = await axios.get(file, { 35 | responseType: 'arraybuffer', 36 | }); 37 | let data: any = res.data; 38 | let basebuffer = Buffer.from(data, 'utf-8'); 39 | let fileInfo = await fromBuffer(basebuffer); 40 | let file_name = basename; 41 | let match = /\.([0-9a-z]+)(?=[?#])|(\.)(?:[\w]+)$/gim.exec(file_name); 42 | if (!match) { 43 | file_name = `${file_name}.${fileInfo?.ext}`; 44 | } 45 | let r: FileInfo = Object.assign(fileInfo || {}, { 46 | source: basebuffer as Buffer, 47 | fileName: file_name, 48 | }); 49 | return r; 50 | } 51 | if (/^(\/|\.\.?\/|~\/)/i.exec(file)) { 52 | let fileInfo = await fromFile(file); 53 | let file_name = basename; 54 | let match = /\.([0-9a-z]+)(?=[?#])|(\.)(?:[\w]+)$/gim.exec(file_name); 55 | if (!match) { 56 | file_name = `${file_name}.${fileInfo?.ext}`; 57 | } 58 | let r: FileInfo = Object.assign(fileInfo || {}, { 59 | source: file as string, 60 | fileName: file_name, 61 | }); 62 | return r; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Telegram/Messages/DeleteUserHistory.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Snake } from '../../Client'; 10 | import { Api } from 'telegram'; 11 | import { ResultAffectedMessages } from './DeleteMessages'; 12 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 13 | import BotError from '../../Context/Error'; 14 | 15 | /** 16 | * Delete all messages sent by a certain user in a supergroup 17 | * @param snakeClient - client. 18 | * @param {number|string|bigint} chatId - supergroup id. 19 | * @param {number|string|bigint} userId - User whose messages should be deleted. 20 | * ```ts 21 | * bot.command("deleteMe", async (ctx) => { 22 | * let results = await ctx.telegram.deleteUserHistory(ctx.chat.id,ctx.from.id) 23 | * return console.log(results) 24 | * }) 25 | * ``` 26 | */ 27 | export async function DeleteUserHistory( 28 | snakeClient: Snake, 29 | chatId: number | string | bigint, 30 | userId: number | string | bigint 31 | ) { 32 | try { 33 | snakeClient.log.debug('Running telegram.deleteUserHistory'); 34 | if (typeof chatId === 'number') 35 | snakeClient.log.warning( 36 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 37 | ); 38 | if (typeof userId === 'number') 39 | snakeClient.log.warning( 40 | 'Type of userId is number, please switch to BigInt or String for security Ids 64 bit int.' 41 | ); 42 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 43 | let [uId, uType, uPeer] = await toBigInt(userId, snakeClient); 44 | return new ResultAffectedMessages( 45 | await snakeClient.client.invoke( 46 | new Api.channels.DeleteParticipantHistory({ 47 | channel: peer, 48 | participant: uPeer, 49 | }) 50 | ) 51 | ); 52 | } catch (error: any) { 53 | snakeClient.log.error('Failed to running telegram.deleteUserHistory'); 54 | throw new BotError(error.message, 'telegram.deleteUserHistory', `${chatId}${userId}`); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Telegram/Media/SendLocation.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { SendMedia, defaultSendMediaMoreParams } from './SendMedia'; 12 | import * as Medias from '../../Utils/Medias'; 13 | import BotError from '../../Context/Error'; 14 | import bigInt from 'big-integer'; 15 | 16 | export interface InterfaceLocation { 17 | latitude: number; 18 | longitude: number; 19 | accuracyRadius?: number; 20 | } 21 | /** 22 | * Sending Location 23 | * @param snakeClient - Client 24 | * @param {string|number|bigint} chatId - Chat/Groups/Channel id. 25 | * @param {Object} location - location 26 | * @param {Object} more - more parameters to use. 27 | * ```ts 28 | * bot.command("loc",async (ctx) => { 29 | * let results = await ctx.telegram.sendLocation(ctx.chat.id,{ 30 | * latitude : 0, 31 | * longitude : 0 32 | * }) 33 | * }) 34 | * ``` 35 | */ 36 | export async function SendLocation( 37 | snakeClient: Snake, 38 | chatId: number | string | bigint, 39 | location: InterfaceLocation | Medias.MediaLocation, 40 | more?: defaultSendMediaMoreParams 41 | ) { 42 | try { 43 | snakeClient.log.debug('Running telegram.sendLocation'); 44 | if (typeof chatId === 'number') 45 | snakeClient.log.warning( 46 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 47 | ); 48 | return await SendMedia( 49 | snakeClient, 50 | chatId, 51 | new Api.InputMediaGeoPoint({ 52 | geoPoint: new Api.InputGeoPoint({ 53 | lat: location.latitude, 54 | long: location.longitude, 55 | accuracyRadius: location.accuracyRadius, 56 | }), 57 | }), 58 | more 59 | ); 60 | } catch (error: any) { 61 | snakeClient.log.error('Failed to running telegram.sendLocation'); 62 | throw new BotError( 63 | error.message, 64 | 'telegram.sendLocation', 65 | `${chatId},${JSON.stringify(location)}${more ? ',' + JSON.stringify(more) : ''}` 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Telegram/Messages/ReadHistory.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { ResultAffectedMessages } from './DeleteMessages'; 10 | import { Api } from 'telegram'; 11 | import { Snake } from '../../Client'; 12 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 13 | import BotError from '../../Context/Error'; 14 | export interface readHistoryMoreParams { 15 | maxId?: number; 16 | } 17 | /** 18 | * Marks message history as read. 19 | * @param snakeClient - Client 20 | * @param {bigint|number|string} chatId - Target user or group. 21 | * @param {Object} more - more parameter for ReadHistory. 22 | * ```ts 23 | * bot.command("readHistory",async (ctx)=>{ 24 | * let results = await ctx.telegram.readHistory(ctx.chat.id,ctx.id) 25 | * console.log(results) 26 | * }) 27 | * ``` 28 | */ 29 | export async function ReadHistory( 30 | snakeClient: Snake, 31 | chatId: number | string | bigint, 32 | more?: readHistoryMoreParams 33 | ) { 34 | try { 35 | snakeClient.log.debug('Running telegram.readHistory'); 36 | if (typeof chatId === 'number') 37 | snakeClient.log.warning( 38 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 39 | ); 40 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 41 | if (type == 'channel') { 42 | let results = await snakeClient.client.invoke( 43 | new Api.channels.ReadHistory({ 44 | channel: peer, 45 | ...more, 46 | }) 47 | ); 48 | return new ResultAffectedMessages(results); 49 | } else { 50 | let results = await snakeClient.client.invoke( 51 | new Api.messages.ReadHistory({ 52 | peer: peer, 53 | ...more, 54 | }) 55 | ); 56 | return new ResultAffectedMessages(results); 57 | } 58 | } catch (error: any) { 59 | snakeClient.log.error('Failed to running telegram.readHistory'); 60 | throw new BotError( 61 | error.message, 62 | 'telegram.readHistory', 63 | `${chatId}${more ? ',' + JSON.stringify(more) : ''}` 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Telegram/Messages/DeleteHistory.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { ResultAffectedMessages } from './DeleteMessages'; 12 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 13 | import BotError from '../../Context/Error'; 14 | export interface deleteHistoryMoreParams { 15 | maxId?: number; 16 | revoke?: boolean; 17 | justClear?: boolean; 18 | } 19 | /** 20 | * This method allow you to deletes communication history. 21 | * @param snakeClient - Client 22 | * @param {string|number|bigint} chatId - User or chat, communication history of which will be deleted. 23 | * @param {Object} more - more parameters to use. 24 | * ```ts 25 | * bot.command("clear", async (ctx) => { 26 | * let results = await ctx.telegram.deleteHistory(ctx.chat.id) 27 | * return console.log(results) 28 | * }) 29 | * ``` 30 | */ 31 | export async function DeleteHistory( 32 | snakeClient: Snake, 33 | chatId: number | string | bigint, 34 | more?: deleteHistoryMoreParams 35 | ) { 36 | try { 37 | snakeClient.log.debug('Running telegram.deleteHistory'); 38 | if (typeof chatId === 'number') 39 | snakeClient.log.warning( 40 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 41 | ); 42 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 43 | if (type == 'channel' || type == 'supergroup') { 44 | return snakeClient.client.invoke( 45 | new Api.channels.DeleteHistory({ 46 | channel: peer, 47 | ...more, 48 | }) 49 | ); 50 | } else { 51 | return new ResultAffectedMessages( 52 | await snakeClient.client.invoke( 53 | new Api.messages.DeleteHistory({ 54 | peer: peer, 55 | ...more, 56 | }) 57 | ) 58 | ); 59 | } 60 | } catch (error: any) { 61 | snakeClient.log.error('Failed to running telegram.deleteHistory'); 62 | throw new BotError( 63 | error.message, 64 | 'telegram.deleteHistory', 65 | `${chatId}${more ? ',' + JSON.stringify(more) : ''}` 66 | ); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![tgsnakeicon-flaticon](./media/tgsnake.jpg) 2 | Hi, **tgsnake** is a framework developed based on gram.js 3 | [![github-repo](https://img.shields.io/badge/Github-butthx-blue.svg?style=for-the-badge&logo=github)](https://github.com/butthx/tgsnake) 4 | [![telegram-chat](https://img.shields.io/badge/Telegram-Chat-blue.svg?style=for-the-badge&logo=telegram)](https://t.me/tgsnakechat) 5 | [![telegram-channel](https://img.shields.io/badge/Telegram-Channel-blue.svg?style=for-the-badge&logo=telegram)](https://t.me/tgsnake) 6 | 7 | > WARNING!
8 | > Maybe your account will be banned if you login using this framework. I don't know what caused it to happen. I am not responsible if your account is banned! 9 | 10 | ### Example : 11 | 12 | - Installation : 13 | 14 | ```bash 15 | yarn add tgsnake@latest 16 | ``` 17 | - Simple Hello World : 18 | 19 | ```javascript 20 | const {Snake} = require("tgsnake") 21 | // import {Snake} from "tgsnake" 22 | const bot = new Snake({ 23 | apiHash : "abcde", //your api hash 24 | apiId : 123456, // your api id 25 | logger:"none" // gramjs logger 26 | }) 27 | bot.run() //snake running 28 | bot.on("message",(ctx)=>{ //handle new message event. 29 | ctx.reply("Hello World") // reply with "Hello World" 30 | //console.log(ctx) // see json of message. 31 | }) 32 | ``` 33 | More example you can found in example folder or in website. 34 | 35 | ### Contribution 36 | Welcome, You can contribute to this project. 37 | #### Guide 38 | - Fork this repo to your account. 39 | - Clone your fork repo using git. 40 | ```bash 41 | git clone -b "dev" 42 | ``` 43 | Cloning branch dev in your repo. 44 | - Edit and make something. 45 | - Pull new update from branch `dev` original repo (this repo). 46 | - Push update to your branch `dev` in fork repo. 47 | - Create pull request to branch `dev` original repo from branch `dev` frok repo. 48 | 49 | ### Reference 50 | - [Pyrogram](https://github.com/pyrogram/pyrogram) 51 | - [Telethon](https://github.com/LonamiWebs/Telethon) 52 | - [GramJs](https://github.com/gram-js/gramjs) 53 | - [Telegram Api](https://core.telegram.org/schema) 54 | - [Grammy](https://github.com/grammyjs/grammyjs) 55 | - [Telegraf](https://github.com/telegraf/telegraf) 56 | 57 | Thanks to all the frameworks and references that I use, several people who helped in developing this framework that I cannot mention one by one. 58 | 59 | Build with ♥️ by [tgsnake dev](https://t.me/+Fdu8unNApTg3ZGU1). -------------------------------------------------------------------------------- /src/Telegram/Media/SendContact.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { SendMedia, defaultSendMediaMoreParams } from './SendMedia'; 12 | import { TypeReplyMarkup, BuildReplyMarkup } from '../../Utils/ReplyMarkup'; 13 | import * as Medias from '../../Utils/Medias'; 14 | import BotError from '../../Context/Error'; 15 | export interface InterfaceContact { 16 | firstName: string; 17 | lastName: string; 18 | phoneNumber: string; 19 | vcard: string; 20 | } 21 | /** 22 | * Sending Contact 23 | * @param snakeClient - Client 24 | * @param {string|number|bigint} chatId - Chat/Groups/Channel id. 25 | * @param {Object} contact - contact. 26 | * @param {Object} more - more parameters to use. 27 | * ```ts 28 | * bot.command("contact",async (ctx) => { 29 | * let results = await ctx.telegram.sendContact(ctx.chat.id,{ 30 | * firstName : "someone", 31 | * lastName : "", 32 | * phoneNumber : "1234567890", 33 | * vcard : "something info" 34 | * }) 35 | * }) 36 | * ``` 37 | */ 38 | export async function SendContact( 39 | snakeClient: Snake, 40 | chatId: number | string | bigint, 41 | contact: InterfaceContact | Medias.MediaContact, 42 | more?: defaultSendMediaMoreParams 43 | ) { 44 | try { 45 | snakeClient.log.debug('Running telegram.sendContact'); 46 | if (typeof chatId === 'number') 47 | snakeClient.log.warning( 48 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 49 | ); 50 | //@ts-ignore 51 | let emoji = typeof dice == 'string' ? dice : dice.emoji; 52 | return await SendMedia( 53 | snakeClient, 54 | chatId, 55 | new Api.InputMediaContact({ 56 | firstName: contact.firstName, 57 | lastName: contact.lastName ?? '', 58 | phoneNumber: contact.phoneNumber, 59 | vcard: contact.vcard, 60 | }), 61 | more! 62 | ); 63 | } catch (error: any) { 64 | snakeClient.log.error('Failed to running telegram.sendContact'); 65 | throw new BotError( 66 | error.message, 67 | 'telegram.sendContact', 68 | `${chatId},${JSON.stringify(contact)}${more ? ',' + JSON.stringify(more) : ''}` 69 | ); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | /.yarn/* 53 | !/.yarn/patches 54 | !/.yarn/plugins 55 | !/.yarn/releases 56 | !/.yarn/sdks 57 | # Swap the comments on the following lines if you don't wish to use zero-installs 58 | # Documentation here: https://yarnpkg.com/features/zero-installs 59 | # !/.yarn/cache 60 | # Optional eslint cache 61 | .eslintcache 62 | 63 | # Microbundle cache 64 | .rpt2_cache/ 65 | .rts2_cache_cjs/ 66 | .rts2_cache_es/ 67 | .rts2_cache_umd/ 68 | 69 | # Optional REPL history 70 | .node_repl_history 71 | 72 | # Output of 'npm pack' 73 | *.tgz 74 | !tg-file-id-1.1.3.tgz 75 | # Yarn Integrity file 76 | .yarn-integrity 77 | 78 | # dotenv environment variables file 79 | .env 80 | .env.test 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | 85 | # Next.js build output 86 | .next 87 | 88 | # Nuxt.js build / generate output 89 | .nuxt 90 | dist 91 | 92 | # Gatsby files 93 | .cache/ 94 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 95 | # https://nextjs.org/blog/next-9-1#public-directory-support 96 | # public 97 | 98 | # vuepress build output 99 | .vuepress/dist 100 | 101 | # Serverless directories 102 | .serverless/ 103 | 104 | # FuseBox cache 105 | .fusebox/ 106 | 107 | # DynamoDB Local files 108 | .dynamodb/ 109 | 110 | # TernJS port file 111 | .tern-port 112 | 113 | # build 114 | /lib 115 | # tgsnake session 116 | /tgsnake 117 | /tgsnake* 118 | # tgsnake config 119 | tgsnake.config.js -------------------------------------------------------------------------------- /src/Update/UpdateBotCallbackQuery.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { From } from '../Utils/From'; 11 | import { Update } from './Update'; 12 | import { Telegram } from '../Telegram'; 13 | import { Snake } from '../Client'; 14 | import { BigInteger } from 'big-integer'; 15 | import { MessageContext } from '../Context/MessageContext'; 16 | import Util from 'tg-file-id/dist/Util'; 17 | import { toString } from '../Utils/ToBigInt'; 18 | export class UpdateBotCallbackQuery extends Update { 19 | id!: bigint; 20 | data?: string; 21 | message?: MessageContext; 22 | from!: From; 23 | chatInstance!: bigint; 24 | inlineMessageId?: string; 25 | gameShortName?: string; 26 | constructor() { 27 | super(); 28 | this['_'] = 'updateBotCallbackQuery'; 29 | } 30 | async init(update: Api.UpdateBotCallbackQuery, SnakeClient: Snake) { 31 | SnakeClient.log.debug(`Creating ${this['_']}`); 32 | this.telegram = SnakeClient.telegram; 33 | this.data = update.data?.toString('utf8'); 34 | this.id = BigInt(toString(update.queryId!) as string); 35 | this.gameShortName = update.gameShortName; 36 | this.chatInstance = BigInt(toString(update.chatInstance) as string); 37 | this.message = new MessageContext(); 38 | if (update.peer instanceof Api.PeerChat) { 39 | update.peer as Api.PeerChat; 40 | let msg = await SnakeClient.telegram.getMessages( 41 | BigInt(`-${toString(update.peer.chatId!)}` as string), 42 | [update.msgId] 43 | ); 44 | this.message = msg.messages[0]; 45 | } 46 | if (update.peer instanceof Api.PeerChannel) { 47 | update.peer as Api.PeerChannel; 48 | let msg = await SnakeClient.telegram.getMessages( 49 | BigInt(`-100${toString(update.peer.channelId!)}` as string), 50 | [update.msgId] 51 | ); 52 | this.message = msg.messages[0]; 53 | } 54 | if (update.peer instanceof Api.PeerUser) { 55 | update.peer as Api.PeerUser; 56 | let msg = await SnakeClient.telegram.getMessages( 57 | BigInt(toString(update.peer.userId!) as string), 58 | [update.msgId] 59 | ); 60 | this.message = msg.messages[0]; 61 | } 62 | this.from = new From(); 63 | await this.from.init(BigInt(toString(update.userId!) as string), SnakeClient); 64 | return this; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/Telegram/Chats/GetChatMembersCount.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Snake } from '../../Client'; 10 | import { ResultGetEntity } from '../Users/GetEntity'; 11 | import { Api } from 'telegram'; 12 | import BotError from '../../Context/Error'; 13 | import bigInt from 'big-integer'; 14 | /** 15 | * Get the number of members in a chat. 16 | * @param snakeClient - client 17 | * @param {number|string|bigint} chatId - Chat or channels id to getting the number of members. 18 | * ```ts 19 | * bot.command("getChatMembersCount",async (ctx) => { 20 | * let results = await ctx.telegram.getChatMembersCount(ctx.chat.id) 21 | * console.log(results) 22 | * }) 23 | * ``` 24 | */ 25 | export async function GetChatMembersCount(snakeClient: Snake, chatId: number | string | bigint) { 26 | try { 27 | snakeClient.log.debug('Running telegram.getChatMembersCount'); 28 | let chat = await snakeClient.telegram.getEntity(chatId, true); 29 | if (chat.type === 'user') { 30 | throw new Error('Typeof chatId must be channel or chat, not a user.'); 31 | } 32 | if (chat.participantsCount && chat.participantsCount !== null) { 33 | return chat.participantsCount; 34 | } 35 | if (chat.type == 'chat') { 36 | let r = await snakeClient.client.invoke( 37 | new Api.messages.GetChats({ 38 | id: [bigInt(chat.id!)], 39 | }) 40 | ); 41 | let s: Api.Chat = r.chats[0] as Api.Chat; 42 | snakeClient.entityCache.set(chat.id, await new ResultGetEntity().init(s!, snakeClient)); 43 | return s.participantsCount; 44 | } 45 | if (chat.type == 'channel' || chat.type == 'supergroup') { 46 | let r: Api.messages.ChatFull = await snakeClient.client.invoke( 47 | new Api.channels.GetFullChannel({ 48 | channel: bigInt(chat.id!), 49 | }) 50 | ); 51 | let fc: Api.ChannelFull = r.fullChat as Api.ChannelFull; 52 | let s: Api.Channel = r.chats[0] as Api.Channel; 53 | s.participantsCount = fc.participantsCount; 54 | snakeClient.entityCache.set(chat.id, await new ResultGetEntity().init(s, snakeClient)); 55 | return s.participantsCount; 56 | } 57 | } catch (error: any) { 58 | snakeClient.log.error('Failed to running telegram.getChatMembersCount'); 59 | throw new BotError(error.message, 'telegram.getChatMembersCount', `${chatId}`); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Telegram/Media/SendVenue.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { SendMedia, defaultSendMediaMoreParams } from './SendMedia'; 12 | import * as Medias from '../../Utils/Medias'; 13 | import BotError from '../../Context/Error'; 14 | import bigInt from 'big-integer'; 15 | 16 | export interface InterfaceVenue { 17 | latitude: number; 18 | longitude: number; 19 | accuracyRadius?: number; 20 | title: string; 21 | address: string; 22 | provider: string; 23 | id: string; 24 | type: string; 25 | } 26 | /** 27 | * Sending Venue 28 | * @param snakeClient - Client 29 | * @param {string|number|bigint} chatId - Chat/Groups/Channel id. 30 | * @param {Object} venue - venue 31 | * @param {Object} more - more parameters to use. 32 | * ```ts 33 | * bot.command("venue",async (ctx) => { 34 | * let results = await ctx.telegram.sendVenue(ctx.chat.id,{ 35 | * latitude : 0, 36 | * longitude : 0, 37 | * title : "title", 38 | * address : "address", 39 | * provider : "provider", 40 | * id : "some id here", 41 | * type : "some type here" 42 | * }) 43 | * }) 44 | * ``` 45 | */ 46 | export async function SendVenue( 47 | snakeClient: Snake, 48 | chatId: number | string | bigint, 49 | venue: InterfaceVenue | Medias.MediaVenue, 50 | more?: defaultSendMediaMoreParams 51 | ) { 52 | try { 53 | snakeClient.log.debug('Running telegram.sendVenue'); 54 | if (typeof chatId === 'number') 55 | snakeClient.log.warning( 56 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 57 | ); 58 | return await SendMedia( 59 | snakeClient, 60 | chatId, 61 | new Api.InputMediaVenue({ 62 | geoPoint: new Api.InputGeoPoint({ 63 | lat: venue.latitude, 64 | long: venue.longitude, 65 | accuracyRadius: venue.accuracyRadius, 66 | }), 67 | title: venue.title, 68 | address: venue.address, 69 | provider: venue.provider, 70 | venueId: venue.id, 71 | venueType: venue.type, 72 | }), 73 | more 74 | ); 75 | } catch (error: any) { 76 | snakeClient.log.error('Failed to running telegram.sendVenue'); 77 | throw new BotError( 78 | error.message, 79 | 'telegram.sendVenue', 80 | `${chatId},${JSON.stringify(venue)}${more ? ',' + JSON.stringify(more) : ''}` 81 | ); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Utils/Medias/Poll.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Media } from './Media'; 10 | import { Snake } from '../../Client'; 11 | import Parser, { Entities } from '@tgsnake/parser'; 12 | import { Cleaning } from '../CleanObject'; 13 | const parser = new Parser(Api); 14 | export interface IPollAnswer { 15 | text: string; 16 | chosen: boolean; 17 | correct: boolean; 18 | voters: number; 19 | option: string; 20 | } 21 | export class MediaPoll extends Media { 22 | id!: bigint; 23 | closed!: boolean; 24 | publicVoters!: boolean; 25 | multipleChoice!: boolean; 26 | quiz!: boolean; 27 | question!: string; 28 | answers!: Array; 29 | closePeriod!: number; 30 | closeDate!: number; 31 | min!: boolean; 32 | totalVoters!: number; 33 | recentVoters!: any; 34 | solution?: string; 35 | solutionEntities?: Array; 36 | constructor() { 37 | super(); 38 | this['_'] = 'poll'; 39 | } 40 | async encode(poll: Api.MessageMediaPoll, snakeClient: Snake) { 41 | snakeClient.log.debug('Creating MediaPoll'); 42 | this.snakeClient = snakeClient; 43 | this.closed = poll.poll.closed ?? false; 44 | this.publicVoters = poll.poll.publicVoters ?? false; 45 | this.multipleChoice = poll.poll.multipleChoice ?? false; 46 | this.quiz = poll.poll.quiz ?? false; 47 | this.question = poll.poll.question; 48 | this.id = BigInt(String(poll.poll.id)); 49 | this.closeDate = poll.poll.closeDate ?? 0; 50 | this.closePeriod = poll.poll.closePeriod ?? 0; 51 | this.min = poll.results.min ?? false; 52 | this.totalVoters = poll.results.totalVoters ?? 0; 53 | this.solution = poll.results.solution; 54 | this.solutionEntities = await parser.fromRaw(poll.results.solutionEntities ?? []); 55 | this.recentVoters = poll.results.recentVoters; 56 | let asn: Array = []; 57 | for (let index in poll.poll.answers) { 58 | //@ts-ignore 59 | let answer = poll.poll.answers[index]; 60 | //@ts-ignore 61 | let results = poll.results.results[index]; 62 | if (!answer && !results) continue; 63 | asn.push({ 64 | text: answer.text, 65 | chosen: results.chosen ?? false, 66 | correct: results.correct ?? false, 67 | voters: results.voters ?? 0, 68 | option: answer.option.toString('utf8'), 69 | }); 70 | } 71 | this.answers = asn; 72 | await Cleaning(this); 73 | return this; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Telegram/Chats/GetParticipant.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Snake } from '../../Client'; 10 | import { ResultGetEntity } from '../Users/GetEntity'; 11 | import { Api } from 'telegram'; 12 | import { ChatParticipants } from '../../Utils/ChatParticipants'; 13 | import BotError from '../../Context/Error'; 14 | import bigInt from 'big-integer'; 15 | /** 16 | * Get info about a channel/supergroup participant. 17 | * @param snakeClient - Client. 18 | * @param {number|string|bigint} - Chat or channels id to getting the list of members. 19 | * @param {number|string|bigint} - Participant to get info about. 20 | * ```ts 21 | * bot.command("getChatMember",async (ctx) => { 22 | * let results = await ctx.telegram.getParticipant(ctx.chat.id,ctx.from.id) // getChatMember and getParticipant.is same methods. 23 | * console.log(results) 24 | * }) 25 | * ``` 26 | */ 27 | export async function GetParticipant( 28 | snakeClient: Snake, 29 | chatId: number | string | bigint, 30 | userId: number | string | bigint 31 | ) { 32 | try { 33 | snakeClient.log.debug('Running telegram.getParticipant'); 34 | if (typeof chatId === 'number') 35 | snakeClient.log.warning( 36 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 37 | ); 38 | if (typeof userId === 'number') 39 | snakeClient.log.warning( 40 | 'Type of userId is number, please switch to BigInt or String for security Ids 64 bit int.' 41 | ); 42 | let { client } = snakeClient; 43 | let result: Api.channels.ChannelParticipant = await client.invoke( 44 | new Api.channels.GetParticipant({ 45 | channel: 46 | typeof chatId == 'string' 47 | ? (chatId as string) 48 | : typeof chatId == 'number' 49 | ? bigInt(chatId as number) 50 | : bigInt(chatId as bigint), 51 | participant: 52 | typeof userId == 'string' 53 | ? (userId as string) 54 | : typeof userId == 'number' 55 | ? bigInt(userId as number) 56 | : bigInt(userId as bigint), 57 | }) 58 | ); 59 | snakeClient.log.debug('Creating results telegram.getParticipant'); 60 | let _results = new ChatParticipants(); 61 | await _results.init(result, snakeClient); 62 | return _results.participants[0]; 63 | } catch (error: any) { 64 | snakeClient.log.error('Failed to running telegram.getParticipant'); 65 | throw new BotError(error.message, 'telegram.getParticipant', `${chatId},${userId}`); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Update/UpdateShortMessage.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Update } from './Update'; 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../Client'; 11 | import { Telegram } from '../Telegram'; 12 | import Parser, { Entities } from '@tgsnake/parser'; 13 | import { ForwardMessage } from '../Utils/ForwardMessage'; 14 | import { From } from '../Utils/From'; 15 | import { Chat } from '../Utils/Chat'; 16 | import { MessageContext } from '../Context/MessageContext'; 17 | import { toString } from '../Utils/ToBigInt'; 18 | const parser = new Parser(Api); 19 | export class UpdateShortMessage extends Update { 20 | message!: MessageContext; 21 | constructor() { 22 | super(); 23 | this['_'] = 'updateShortMessage'; 24 | } 25 | async init(update: Api.UpdateShortMessage, SnakeClient: Snake) { 26 | SnakeClient.log.debug(`Creating ${this['_']}`); 27 | this.message = new MessageContext(); 28 | this.telegram = SnakeClient.telegram; 29 | this.message.out = update.out; 30 | this.message.mentioned = update.mentioned; 31 | this.message.mediaUnread = update.mediaUnread; 32 | this.message.silent = update.silent; 33 | this.message.id = update.id; 34 | this.message.text = update.message; 35 | this.message.date = update.date; 36 | this.message.ttlPeriod = update.ttlPeriod; 37 | this.message.viaBotId = BigInt(toString(update.viaBotId!) as string); 38 | this.message.SnakeClient = SnakeClient; 39 | if (update.userId) { 40 | let chat = new Chat(); 41 | let from = new From(); 42 | await chat.init(BigInt(toString(update.userId!) as string), SnakeClient); 43 | if (!update.out) { 44 | await from.init(BigInt(toString(update.userId!) as string), SnakeClient); 45 | } else { 46 | await from.init(SnakeClient.aboutMe.id, SnakeClient); 47 | } 48 | this.message.chat = chat; 49 | this.message.from = from; 50 | } 51 | if (update.replyTo) { 52 | this.SnakeClient.log.debug(`Creating replyToMessage`); 53 | let replyTo = await this.SnakeClient.telegram.getMessages( 54 | this.message.chat.id, 55 | [update.replyTo.replyToMsgId], 56 | false 57 | ); 58 | this.message.replyToMessage = replyTo.messages[0]; 59 | } 60 | if (update.fwdFrom) { 61 | let fwd = new ForwardMessage(); 62 | await fwd.init(update.fwdFrom, SnakeClient); 63 | this.message.fwdFrom = fwd; 64 | } 65 | if (update.entities) { 66 | this.message.entities = parser.fromRaw(update.entities); 67 | } 68 | return this; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Update/UpdateShortChatMessage.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Update } from './Update'; 10 | import { Api } from 'telegram'; 11 | import { Snake } from '../Client'; 12 | import { Telegram } from '../Telegram'; 13 | import Parser, { Entities } from '@tgsnake/parser'; 14 | import { ForwardMessage } from '../Utils/ForwardMessage'; 15 | import { From } from '../Utils/From'; 16 | import { Chat } from '../Utils/Chat'; 17 | import { MessageContext } from '../Context/MessageContext'; 18 | import { toString } from '../Utils/ToBigInt'; 19 | const parser = new Parser(Api); 20 | export class UpdateShortChatMessage extends Update { 21 | message!: MessageContext; 22 | constructor() { 23 | super(); 24 | this['_'] = 'updateShortChatMessage'; 25 | } 26 | async init(update: Api.UpdateShortChatMessage, SnakeClient: Snake) { 27 | SnakeClient.log.debug(`Creating ${this['_']}`); 28 | this.telegram = SnakeClient.telegram; 29 | this.message = new MessageContext(); 30 | this.message.out = update.out; 31 | this.message.mentioned = update.mentioned; 32 | this.message.mediaUnread = update.mediaUnread; 33 | this.message.silent = update.silent; 34 | this.message.id = update.id; 35 | this.message.text = update.message; 36 | this.message.date = update.date; 37 | this.message.viaBotId = BigInt(toString(update.viaBotId!) as string); 38 | this.message.ttlPeriod = update.ttlPeriod; 39 | this.message.SnakeClient = SnakeClient; 40 | if (update.fromId) { 41 | let from = new From(); 42 | if (!update.out) { 43 | await from.init(BigInt(toString(update.fromId!) as string), SnakeClient); 44 | } else { 45 | await from.init(SnakeClient.aboutMe.id, SnakeClient); 46 | } 47 | this.message.from = from; 48 | } 49 | if (update.chatId) { 50 | let chat = new Chat(); 51 | await chat.init(BigInt(toString(update.chatId!) as string), SnakeClient); 52 | this.message.chat = chat; 53 | } 54 | if (update.fwdFrom) { 55 | let fwd = new ForwardMessage(); 56 | await fwd.init(update.fwdFrom, SnakeClient); 57 | this.message.fwdFrom = fwd; 58 | } 59 | if (update.replyTo) { 60 | this.SnakeClient.log.debug(`Creating replyToMessage`); 61 | let replyTo = await this.SnakeClient.telegram.getMessages( 62 | this.message.chat.id, 63 | [update.replyTo.replyToMsgId], 64 | false 65 | ); 66 | this.message.replyToMessage = replyTo.messages[0]; 67 | } 68 | if (update.entities) { 69 | this.message.entities = parser.fromRaw(update.entities!); 70 | } 71 | return this; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Telegram/Messages/DeleteMessages.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Snake } from '../../Client'; 10 | import { Api } from 'telegram'; 11 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 12 | import BotError from '../../Context/Error'; 13 | export class ResultAffectedMessages { 14 | pts?: number = 0; 15 | ptsCount?: number = 0; 16 | offset?: number; 17 | date: Date | number = Math.floor(Date.now() / 1000); 18 | constructor(results: Api.messages.AffectedMessages | Api.messages.AffectedHistory | boolean) { 19 | if (results instanceof Api.messages.AffectedMessages) { 20 | if (results.pts) this.pts = results.pts; 21 | if (results.ptsCount) this.ptsCount = results.ptsCount; 22 | } 23 | if (results instanceof Api.messages.AffectedHistory) { 24 | if (results.pts) this.pts = results.pts; 25 | if (results.ptsCount) this.ptsCount = results.ptsCount; 26 | if (results.offset) this.offset = results.offset; 27 | } 28 | } 29 | } 30 | /** 31 | * This method allow you to deletes messages by their identifiers 32 | * @param snakeClient - Client 33 | * @param {number|string|bigint} chatId - User or chat, where is the message located. 34 | * @param {Array} messageId - Message ID list which will be deleted. 35 | * ```ts 36 | * bot.command("delete", async (ctx) => { 37 | * let results = await ctx.telegram.deleteMessages(ctx.chat.id,[ctx.id]) 38 | * return console.log(results) 39 | * }) 40 | * ``` 41 | */ 42 | export async function DeleteMessages( 43 | snakeClient: Snake, 44 | chatId: number | string | bigint, 45 | messageId: number[] 46 | ) { 47 | try { 48 | snakeClient.log.debug('Running telegram.deleteMessages'); 49 | if (typeof chatId === 'number') 50 | snakeClient.log.warning( 51 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 52 | ); 53 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 54 | if (type == 'channel' || type == 'supergroup') { 55 | return new ResultAffectedMessages( 56 | await snakeClient.client.invoke( 57 | new Api.channels.DeleteMessages({ 58 | channel: peer, 59 | id: messageId, 60 | }) 61 | ) 62 | ); 63 | } else { 64 | return new ResultAffectedMessages( 65 | await snakeClient.client.invoke( 66 | new Api.messages.DeleteMessages({ 67 | revoke: true, 68 | id: messageId, 69 | }) 70 | ) 71 | ); 72 | } 73 | } catch (error: any) { 74 | snakeClient.log.error('Failed to running telegram.deleteMessages'); 75 | throw new BotError( 76 | error.message, 77 | 'telegram.deleteMessages', 78 | `${chatId},${JSON.stringify(messageId)}` 79 | ); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/Telegram/Messages/GetMessagesViews.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 12 | import BotError from '../../Context/Error'; 13 | export class ResultsMessagesViews { 14 | views?: Views[]; 15 | date: Date | number = Math.floor(Date.now() / 1000); 16 | constructor(results: Api.messages.MessageViews) { 17 | if (results?.views.length > 0) { 18 | let tempViews: Views[] = new Array(); 19 | for (let i = 0; i < results.views.length; i++) { 20 | let msg = results.views[i] as Api.MessageViews; 21 | tempViews.push(new Views(msg)); 22 | } 23 | this.views = tempViews; 24 | } 25 | } 26 | } 27 | export class Views { 28 | views?: number; 29 | forwards?: number; 30 | replies?: Api.MessageReplies; 31 | constructor(getMessagesViews: Api.MessageViews) { 32 | if (getMessagesViews.views) { 33 | this.views = getMessagesViews.views; 34 | } 35 | if (getMessagesViews.forwards) { 36 | this.forwards = getMessagesViews.forwards; 37 | } 38 | if (getMessagesViews.replies) { 39 | this.replies = getMessagesViews.replies; 40 | } 41 | } 42 | } 43 | /** 44 | * Get and increase the view counter of a message sent or forwarded from a channel. 45 | * @param snakeClient - Client 46 | * @param {number|string|bigint} chatId - Where the message was found. 47 | * @param {Array} messageId - IDs of message. 48 | * @param {boolean} increment - Whether to mark the message as viewed and increment the view counter 49 | * ```ts 50 | * bot.command("getMessagesViews",async (ctx)=>{ 51 | * let results = await ctx.telegram.getMessagesViews(ctx.chat.id,[ctx.id]) 52 | * console.log(results) 53 | * }) 54 | * ``` 55 | */ 56 | export async function GetMessagesViews( 57 | snakeClient: Snake, 58 | chatId: number | string | bigint, 59 | messageId: number[], 60 | increment: boolean = false 61 | ) { 62 | try { 63 | snakeClient.log.debug('Running telegram.getMessagesViews'); 64 | if (typeof chatId === 'number') 65 | snakeClient.log.warning( 66 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 67 | ); 68 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 69 | return new ResultsMessagesViews( 70 | await snakeClient.client.invoke( 71 | new Api.messages.GetMessagesViews({ 72 | peer: peer, 73 | id: messageId, 74 | increment: increment, 75 | }) 76 | ) 77 | ); 78 | } catch (error: any) { 79 | snakeClient.log.error('Failed to running telegram.getMessagesViews'); 80 | throw new BotError( 81 | error.message, 82 | 'telegram.getMessagesViews', 83 | `${chatId},${JSON.stringify(messageId)},${increment}` 84 | ); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/Telegram/Chats/EditTitle.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Snake } from '../../Client'; 10 | import { Api } from 'telegram'; 11 | import * as Updates from '../../Update'; 12 | import BotError from '../../Context/Error'; 13 | import { convertId, toBigInt } from '../../Utils/ToBigInt'; 14 | import { BigInteger } from 'big-integer'; 15 | /** 16 | * edit chat/group/channel title. 17 | * @param snakeClient - Client 18 | * @param {bigint|number|string} chatId - Chat/Groups/Channel id. 19 | * @param {string} title - New title. 20 | * ```ts 21 | * bot.command("editTitle",async (ctx) => { 22 | * if(!ctx.chat.private){ 23 | * let results = await ctx.telegram.editTitle(ctx.chat.id,"hey new title") 24 | * console.log(results) 25 | * } 26 | * }) 27 | * ``` 28 | * This method will return UpdateNewMessage or UpdateNewChannelMessage. if success. 29 | */ 30 | export async function EditTitle( 31 | snakeClient: Snake, 32 | chatId: bigint | number | string, 33 | title: string 34 | ) { 35 | try { 36 | snakeClient.log.debug('Running telegram.editTitle'); 37 | if (typeof chatId === 'number') 38 | snakeClient.log.warning( 39 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 40 | ); 41 | let [id, type] = await toBigInt(chatId, snakeClient); 42 | if (type == 'channel') { 43 | let results: Api.TypeUpdates = await snakeClient.client.invoke( 44 | new Api.channels.EditTitle({ 45 | channel: id as BigInteger, 46 | title: title, 47 | }) 48 | ); 49 | snakeClient.log.debug('Creating results telegram.editTitle'); 50 | return await generateResults(results, snakeClient); 51 | } else { 52 | return snakeClient.client.invoke( 53 | new Api.messages.EditChatTitle({ 54 | chatId: id as BigInteger, 55 | title: title, 56 | }) 57 | ); 58 | } 59 | } catch (error: any) { 60 | snakeClient.log.error('Failed to running telegram.editTitle'); 61 | throw new BotError(error.message, 'telegram.editTitle', `${chatId},${title}`); 62 | } 63 | } 64 | async function generateResults(results: Api.TypeUpdates, SnakeClient: Snake) { 65 | if (results instanceof Api.Updates) { 66 | results as Api.Updates; 67 | if (results.updates.length > 0) { 68 | for (let i = 0; i < results.updates.length; i++) { 69 | let update = results.updates[i]; 70 | if (update instanceof Api.UpdateNewMessage) { 71 | update as Api.UpdateNewMessage; 72 | let res = new Updates.UpdateNewMessage(); 73 | await res.init(update, SnakeClient); 74 | return res; 75 | } 76 | if (update instanceof Api.UpdateNewChannelMessage) { 77 | update as Api.UpdateNewChannelMessage; 78 | let res = new Updates.UpdateNewChannelMessage(); 79 | await res.init(update, SnakeClient); 80 | return res; 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/Context/EntityCache.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import fs from 'fs'; 9 | import { ResultGetEntity } from '../Telegram/Users/GetEntity'; 10 | import { betterConsoleLog } from '../Utils/CleanObject'; 11 | import { inspect } from 'util'; 12 | export class EntityCache { 13 | /** @hidden */ 14 | private _cache: Map = new Map(); 15 | /** @hidden */ 16 | private _sessionName!: string; 17 | constructor(sessionName: string) { 18 | this._sessionName = sessionName; 19 | } 20 | /** @hidden */ 21 | [inspect.custom]() { 22 | return betterConsoleLog(this); 23 | } 24 | /** @hidden */ 25 | toJSON() { 26 | let obj = betterConsoleLog(this); 27 | for (let [key, value] of Object.entries(obj)) { 28 | if (typeof value == 'bigint') obj[key] = String(value); 29 | } 30 | return obj; 31 | } 32 | set(key: bigint | string, value: ResultGetEntity) { 33 | return this._cache.set(key, value); 34 | } 35 | get(key: string | bigint) { 36 | return this._cache.get(key); 37 | } 38 | has(key: string | bigint) { 39 | return this._cache.has(key); 40 | } 41 | clear() { 42 | return this._cache.clear(); 43 | } 44 | delete(key: string | bigint) { 45 | return this._cache.delete(key); 46 | } 47 | get size() { 48 | return this._cache.size; 49 | } 50 | entries() { 51 | return this._cache.entries(); 52 | } 53 | load() { 54 | if (!fs.existsSync(`${process.cwd()}/${this._sessionName}`)) { 55 | fs.mkdirSync(`${process.cwd()}/${this._sessionName}`); 56 | } 57 | if (fs.existsSync(`${process.cwd()}/${this._sessionName}/cache.json`)) { 58 | let file = JSON.parse( 59 | fs.readFileSync(`${process.cwd()}/${this._sessionName}/cache.json`, 'utf8') 60 | ); 61 | for (let [k, v] of file) { 62 | let g = new ResultGetEntity(); 63 | for (let [kk, vv] of Object.entries(v)) { 64 | if (typeof vv == 'string') { 65 | if (vv.startsWith(':bigint:')) { 66 | let vvv = vv.replace(':bigint:', ''); 67 | if (!isNaN(Number(vvv))) { 68 | g[kk] = BigInt(vvv); 69 | } 70 | } else { 71 | g[kk] = vv; 72 | } 73 | // remove the null entities 74 | } else if (vv !== null) { 75 | g[kk] = vv; 76 | } 77 | } 78 | if (k && typeof k === 'string') { 79 | this._cache.set(k.startsWith(':bigint:') ? BigInt(k.replace(':bigint:', '')) : k, g); 80 | } 81 | // skip when array is null/undefined 82 | } 83 | } 84 | return this; 85 | } 86 | save() { 87 | if (!fs.existsSync(`${process.cwd()}/${this._sessionName}`)) { 88 | fs.mkdirSync(`${process.cwd()}/${this._sessionName}`); 89 | } 90 | fs.writeFileSync( 91 | `${process.cwd()}/${this._sessionName}/cache.json`, 92 | JSON.stringify([...this._cache.entries()], (k, v) => { 93 | return typeof v == 'bigint' ? `:bigint:${v}` : v; 94 | }) 95 | ); 96 | return this; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/Telegram/Media/EditPhoto.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { UploadFile } from './UploadFile'; 12 | import * as Updates from '../../Update'; 13 | import { toBigInt, toString, convertId } from '../../Utils/ToBigInt'; 14 | import BotError from '../../Context/Error'; 15 | import bigInt, { BigInteger } from 'big-integer'; 16 | /** 17 | * Change the profile picture of chat. 18 | * @param snakeClient - Client 19 | * @param {number|string|bigint} chatId - Chat/Groups/Channel which will change the profile picture. 20 | * @param {string|Buffer} photo - The location where the file is located/Url/The buffer of the file. 21 | * ```ts 22 | * bot.command("editPhoto", async (ctx)=>{ 23 | * if(!ctx.chat.private){ 24 | * let results = await ctx.telegram.editPhoto(ctx.chat.id,"https://tgsnake.js.org/images/tgsnake.jpg") 25 | * console.log(results) 26 | * } 27 | * }) 28 | * ``` 29 | */ 30 | export async function EditPhoto( 31 | snakeClient: Snake, 32 | chatId: number | string | bigint, 33 | photo: string | Buffer 34 | ) { 35 | try { 36 | snakeClient.log.debug('Running telegram.editPhoto'); 37 | if (typeof chatId === 'number') 38 | snakeClient.log.warning( 39 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 40 | ); 41 | let rr = await UploadFile(snakeClient, photo); 42 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 43 | if (type == 'channel' || type == 'supergroup') { 44 | let results: Api.TypeUpdates = await snakeClient.client.invoke( 45 | new Api.channels.EditPhoto({ 46 | channel: id as BigInteger, 47 | photo: new Api.InputChatUploadedPhoto({ 48 | file: rr!, 49 | }), 50 | }) 51 | ); 52 | return await generateResults(results, snakeClient); 53 | } else { 54 | return snakeClient.client.invoke( 55 | new Api.messages.EditChatPhoto({ 56 | chatId: id as BigInteger, 57 | photo: new Api.InputChatUploadedPhoto({ 58 | file: rr!, 59 | }), 60 | }) 61 | ); 62 | } 63 | } catch (error: any) { 64 | snakeClient.log.error('Failed to running telegram.editPhoto'); 65 | throw new BotError( 66 | error.message, 67 | 'telegram.editPhoto', 68 | `${chatId}${Buffer.isBuffer(photo) ? `` : photo}` 69 | ); 70 | } 71 | } 72 | async function generateResults(results: Api.TypeUpdates, SnakeClient: Snake) { 73 | SnakeClient.log.debug('Creating results telegram.editPhoto'); 74 | if (results instanceof Api.Updates) { 75 | results as Api.Updates; 76 | if (results.updates.length > 0) { 77 | for (let i = 0; i < results.updates.length; i++) { 78 | let update = results.updates[i]; 79 | if (update instanceof Api.UpdateNewMessage) { 80 | update as Api.UpdateNewMessage; 81 | let res = new Updates.UpdateNewMessage(); 82 | await res.init(update, SnakeClient); 83 | return res; 84 | } 85 | if (update instanceof Api.UpdateNewChannelMessage) { 86 | update as Api.UpdateNewChannelMessage; 87 | let res = new Updates.UpdateNewChannelMessage(); 88 | await res.init(update, SnakeClient); 89 | return res; 90 | } 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/Utils/Chat.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { BannedRights } from './BannedRight'; 10 | import { MediaChatPhoto } from './Medias'; 11 | import { Snake } from '../Client'; 12 | import { Api } from 'telegram'; 13 | import { toBigInt, toString } from './ToBigInt'; 14 | import { BigInteger, isInstance } from 'big-integer'; 15 | import { Cleaning, betterConsoleLog } from './CleanObject'; 16 | export class Chat { 17 | id!: bigint; 18 | title?: string; 19 | firstName?: string; 20 | lastName?: string; 21 | username?: string; 22 | private?: boolean; 23 | photo?: MediaChatPhoto; 24 | defaultBannedRights?: BannedRights; 25 | participantsCount?: number; 26 | dcId?: number; 27 | fake!: boolean; 28 | scam!: boolean; 29 | type!: string; 30 | noforward?: boolean; 31 | accessHash!: bigint; 32 | constructor() {} 33 | async init(peer: Api.TypePeer | number | bigint, snakeClient: Snake) { 34 | if (typeof peer !== 'number' && typeof peer !== 'bigint') { 35 | if (peer instanceof Api.PeerUser) { 36 | peer as Api.PeerUser; 37 | if (isInstance(peer.userId)) { 38 | //@ts-ignore 39 | this.id = BigInt(toString(peer.userId)); 40 | } else { 41 | //@ts-ignore 42 | this.id = BigInt(peer.userId); 43 | } 44 | } 45 | if (peer instanceof Api.PeerChat) { 46 | peer as Api.PeerChat; 47 | if (isInstance(peer.chatId)) { 48 | //@ts-ignore 49 | this.id = BigInt(`-${toString(peer.chatId)}`); 50 | } else { 51 | //@ts-ignore 52 | this.id = BigInt(`-${peer.chatId}`); 53 | } 54 | } 55 | if (peer instanceof Api.PeerChannel) { 56 | peer as Api.PeerChannel; 57 | if (isInstance(peer.channelId)) { 58 | //@ts-ignore 59 | this.id = BigInt(`-100${toString(peer.channelId)}`); 60 | } else { 61 | //@ts-ignore 62 | this.id = BigInt(`-100${peer.channelId}`); 63 | } 64 | } 65 | } else { 66 | this.id = typeof peer == 'number' ? BigInt(peer) : peer; 67 | } 68 | if (this.id) { 69 | snakeClient.log.debug(`Creating Chat ${this.id}`); 70 | let tg = snakeClient.telegram; 71 | try { 72 | let entity = await tg.getEntity(this.id, true); 73 | this.id = entity.id; 74 | this.noforward = entity.noforward; 75 | this.username = entity.username!; 76 | this.firstName = entity.firstName!; 77 | this.lastName = entity.lastName!; 78 | this.title = entity.title!; 79 | this.photo = entity.photo!; 80 | this.defaultBannedRights = entity.defaultBannedRights; 81 | this.participantsCount = entity.participantsCount; 82 | this.dcId = entity.dcId; 83 | this.fake = entity.fake !== undefined ? entity.fake : false; 84 | this.scam = entity.scam !== undefined ? entity.scam : false; 85 | this.private = Boolean(entity.type === 'user'); 86 | this.type = entity.type as string; 87 | this.accessHash = entity.accessHash!; 88 | } catch (error) { 89 | return this; 90 | } 91 | } 92 | await Cleaning(this); 93 | return this; 94 | } 95 | /** @hidden */ 96 | toJSON() { 97 | let obj = betterConsoleLog(this); 98 | for (let [key, value] of Object.entries(obj)) { 99 | if (typeof value == 'bigint') obj[key] = String(value); 100 | } 101 | return obj; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Utils/From.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../Client'; 11 | import { MediaChatPhoto } from './Medias'; 12 | import { ResultGetEntity } from '../Telegram/Users/GetEntity'; 13 | import { RestrictionReason } from './RestrictionReason'; 14 | import { toBigInt, toString } from './ToBigInt'; 15 | import bigInt, { BigInteger, isInstance } from 'big-integer'; 16 | import { Cleaning, betterConsoleLog } from './CleanObject'; 17 | export class From { 18 | id!: bigint; 19 | firstName?: string; 20 | lastName?: string; 21 | username?: string; 22 | status?: string; 23 | self?: boolean; 24 | deleted?: boolean; 25 | fake?: boolean; 26 | scam?: boolean; 27 | bot?: boolean; 28 | verified?: boolean; 29 | restricted?: boolean; 30 | dcId?: number; 31 | photo?: MediaChatPhoto; 32 | restrictionReason?: RestrictionReason[]; 33 | accessHash?: bigint; 34 | constructor() {} 35 | async init(peer: Api.TypePeer | number | bigint | string, snakeClient: Snake) { 36 | let id: bigint | string | number | undefined; 37 | if (typeof peer !== 'number' && typeof peer !== 'bigint' && typeof peer !== 'string') { 38 | if (peer instanceof Api.PeerUser) { 39 | peer as Api.PeerUser; 40 | if (isInstance(peer.userId)) { 41 | //@ts-ignore 42 | id = BigInt(toString(peer.userId)); 43 | } else { 44 | //@ts-ignore 45 | id = BigInt(peer.userId); 46 | } 47 | } 48 | if (peer instanceof Api.PeerChat) { 49 | peer as Api.PeerChat; 50 | if (isInstance(peer.chatId)) { 51 | //@ts-ignore 52 | id = BigInt(Number(`-${toString(peer.chatId)}`)); 53 | } else { 54 | //@ts-ignore 55 | id = BigInt(Number(`-${peer.chatId}`)); 56 | } 57 | } 58 | if (peer instanceof Api.PeerChannel) { 59 | peer as Api.PeerChannel; 60 | if (isInstance(peer.channelId)) { 61 | //@ts-ignore 62 | id = BigInt(Number(`-100${toString(peer.channelId)}`)); 63 | } else { 64 | //@ts-ignore 65 | id = BigInt(Number(`-100${peer.channelId}`)); 66 | } 67 | } 68 | } else { 69 | id = typeof peer == 'number' ? BigInt(peer) : peer; 70 | } 71 | if (id) { 72 | snakeClient.log.debug(`Creating User ${id}`); 73 | try { 74 | let entity = await snakeClient.telegram.getEntity(id, true); 75 | this.id = entity.id; 76 | this.username = entity.username; 77 | this.firstName = entity.firstName; 78 | this.lastName = entity.lastName; 79 | this.status = entity.status; 80 | this.self = entity.self; 81 | this.deleted = entity.deleted; 82 | this.fake = entity.fake; 83 | this.scam = entity.scam; 84 | this.bot = entity.bot; 85 | this.verified = entity.verified; 86 | this.restricted = entity.restricted; 87 | this.dcId = entity.dcId; 88 | this.photo = entity.photo; 89 | this.restrictionReason = entity.restrictionReason; 90 | this.accessHash = entity.accessHash; 91 | } catch (error) { 92 | return this; 93 | } 94 | } 95 | await Cleaning(this); 96 | return this; 97 | } 98 | /** @hidden */ 99 | toJSON() { 100 | let obj = betterConsoleLog(this); 101 | for (let [key, value] of Object.entries(obj)) { 102 | if (typeof value == 'bigint') obj[key] = String(value); 103 | } 104 | return obj; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/Telegram/Messages/PinMessage.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import * as Updates from '../../Update'; 12 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 13 | import BotError from '../../Context/Error'; 14 | export interface pinMessageMoreParams { 15 | silent?: boolean; 16 | unpin?: boolean; 17 | pmOneside?: boolean; 18 | } 19 | /** 20 | * Pin or unpin a message. 21 | * @param snakeClient - Client 22 | * @param {number|string|bigint} chatId - where to pin or unpin the message. 23 | * @param {number} messageId - The message to pin or unpin 24 | * @param {Object} more - more parameter for PinMessage 25 | * ```ts 26 | * bot.command("pin",async (ctx)=>{ 27 | * let results = await ctx.telegram.pinMessage(ctx.chat.id,ctx.id) 28 | * console.log(results) 29 | * }) 30 | * // unpin a message 31 | * bot.command("unpin",async (ctx)=>{ 32 | * if(ctx.replyToMessage){ 33 | * let results = await ctx.telegram.unpinMessage(ctx.chat.id,ctx.replyToMessage.id) 34 | * console.log(results) 35 | * } 36 | * }) 37 | * ``` 38 | */ 39 | export async function PinMessage( 40 | snakeClient: Snake, 41 | chatId: number | string | bigint, 42 | messageId: number, 43 | more?: pinMessageMoreParams 44 | ) { 45 | try { 46 | snakeClient.log.debug('Running telegram.pinMessage'); 47 | if (typeof chatId === 'number') 48 | snakeClient.log.warning( 49 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 50 | ); 51 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 52 | let results: Api.TypeUpdates = await snakeClient.client.invoke( 53 | new Api.messages.UpdatePinnedMessage({ 54 | peer: peer, 55 | id: messageId, 56 | ...more, 57 | }) 58 | ); 59 | return await generateResults(results, snakeClient); 60 | } catch (error: any) { 61 | snakeClient.log.error('Failed to running telegram.pinMessage'); 62 | throw new BotError( 63 | error.message, 64 | 'telegram.pinMessage', 65 | `${chatId},${messageId}${more ? ',' + JSON.stringify(more) : ''}` 66 | ); 67 | } 68 | } 69 | async function generateResults(results: Api.TypeUpdates, SnakeClient: Snake) { 70 | SnakeClient.log.debug('Running telegram.pinMessage'); 71 | if (results instanceof Api.Updates) { 72 | results as Api.Updates; 73 | if (results.updates.length > 0) { 74 | for (let i = 0; i < results.updates.length; i++) { 75 | let update = results.updates[i]; 76 | if (update instanceof Api.UpdateNewMessage) { 77 | update as Api.UpdateNewMessage; 78 | let res = new Updates.UpdateNewMessage(); 79 | await res.init(update, SnakeClient); 80 | return res; 81 | } 82 | if (update instanceof Api.UpdateNewChannelMessage) { 83 | update as Api.UpdateNewChannelMessage; 84 | let res = new Updates.UpdateNewChannelMessage(); 85 | await res.init(update, SnakeClient); 86 | return res; 87 | } 88 | if (update instanceof Api.UpdatePinnedMessages) { 89 | update as Api.UpdatePinnedMessages; 90 | //todo 91 | // using Updates.UpdatePinnedMessages 92 | return update; 93 | } 94 | if (update instanceof Api.UpdatePinnedChannelMessages) { 95 | update as Api.UpdatePinnedChannelMessages; 96 | //todo 97 | //using Updates.UpdatePinnedChannelMessage 98 | return update; 99 | } 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Utils/Medias/Game.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Snake } from '../../Client'; 10 | import bigInt, { BigInteger } from 'big-integer'; 11 | import { Cleaning } from '../CleanObject'; 12 | import BotError from '../../Context/Error'; 13 | import * as Medias from './'; 14 | 15 | export class MediaGame extends Medias.Media { 16 | id!: bigint; 17 | accessHash!: bigint; 18 | shortName!: string; 19 | title!: string; 20 | description!: string; 21 | photo!: Medias.MediaPhoto; 22 | document!: Medias.TypeMessageMediaDocument; 23 | constructor() { 24 | super(); 25 | this['_'] = 'game'; 26 | } 27 | async encode(game: Api.MessageMediaGame | Api.Game, snakeClient: Snake) { 28 | snakeClient.log.debug('Creating MediaGame'); 29 | this.snakeClient = snakeClient; 30 | const create = async (media: Api.Game) => { 31 | this.id = BigInt(String(media.id)); 32 | this.accessHash = BigInt(String(media.accessHash)); 33 | this.shortName = media.shortName; 34 | this.description = media.description; 35 | this.title = media.title; 36 | this.photo = new Medias.MediaPhoto(); 37 | await this.photo.encode(media.photo!, snakeClient); 38 | if (media.document) { 39 | if (media.document instanceof Api.Document) { 40 | let document = media.document as Api.Document; 41 | let animatedIndex = document.attributes.findIndex((attribute) => 42 | Boolean(attribute instanceof Api.DocumentAttributeAnimated) 43 | ); 44 | for (let attribute of document.attributes) { 45 | // sticker 46 | if (attribute instanceof Api.DocumentAttributeSticker) { 47 | this.document = new Medias.MediaSticker(); 48 | await this.document.encode(document, snakeClient); 49 | return this; 50 | } 51 | if (attribute instanceof Api.DocumentAttributeAudio) { 52 | attribute as Api.DocumentAttributeAudio; 53 | // voice 54 | if (attribute.voice) { 55 | this.document = new Medias.MediaVoice(); 56 | await this.document.encode(document, snakeClient); 57 | return this; 58 | } 59 | // audio 60 | this.document = new Medias.MediaAudio(); 61 | await this.document.encode(document, snakeClient); 62 | return this; 63 | } 64 | if (attribute instanceof Api.DocumentAttributeVideo && animatedIndex < 0) { 65 | attribute as Api.DocumentAttributeVideo; 66 | // video note 67 | if (attribute.roundMessage) { 68 | this.document = new Medias.MediaVideoNote(); 69 | await this.document.encode(document, snakeClient); 70 | return this; 71 | } 72 | // video 73 | this.document = new Medias.MediaVideo(); 74 | await this.document.encode(document, snakeClient); 75 | return this; 76 | } 77 | // gif 78 | if (attribute instanceof Api.DocumentAttributeAnimated) { 79 | this.document = new Medias.MediaAnimation(); 80 | await this.document.encode(document, snakeClient); 81 | return this; 82 | } 83 | } 84 | // document 85 | this.document = new Medias.MediaDocument(); 86 | await this.document.encode(document, snakeClient); 87 | return this; 88 | } 89 | } 90 | return this; 91 | }; 92 | if (game instanceof Api.MessageMediaGame) { 93 | return create(game.game as Api.Game); 94 | } 95 | return create(game as Api.Game); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/Telegram/Media/UploadFile.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { CustomFile } from 'telegram/client/uploads'; 11 | import path from 'path'; 12 | import fs from 'fs'; 13 | import axios from 'axios'; 14 | import { Snake } from '../../Client'; 15 | import BotError from '../../Context/Error'; 16 | import { fromBuffer, fromFile } from 'file-type'; 17 | export interface uploadFileMoreParams { 18 | fileName?: string; 19 | workers?: number; 20 | onProgress?: onProgress; 21 | } 22 | export interface onProgress { 23 | (progress: number): void; 24 | isCanceled?: boolean; 25 | } 26 | export function inRange(x: number, min: number, max: number) { 27 | return (x - min) * (x - max) <= 0; 28 | } 29 | export async function UploadFile( 30 | snakeClient: Snake, 31 | file: string | Buffer, 32 | more?: uploadFileMoreParams 33 | ): Promise { 34 | try { 35 | snakeClient.log.debug('Running telegram.uploadFile'); 36 | if (more?.workers !== undefined) { 37 | if (!inRange(more?.workers!, 1, 16)) { 38 | snakeClient.log.warning( 39 | `Workers (${more.workers}) out of range (1 <= workers <= 16). Chances are this will make tgsnake unstable.` 40 | ); 41 | } 42 | } 43 | if (Buffer.isBuffer(file)) { 44 | let fileInfo = await fromBuffer(file); 45 | //if (fileInfo) { 46 | let file_name = more?.fileName || `${Date.now() / 1000}.${fileInfo?.ext}`; 47 | let toUpload = new CustomFile(file_name, Buffer.byteLength(file), '', file); 48 | return snakeClient.client.uploadFile({ 49 | file: toUpload, 50 | workers: more?.workers || 1, 51 | onProgress: more?.onProgress, 52 | }); 53 | //} 54 | } else { 55 | let basename = path.basename(file); 56 | if (/^http/i.exec(file)) { 57 | let res = await axios.get(file, { 58 | responseType: 'arraybuffer', 59 | }); 60 | let data: any = res.data; 61 | let basebuffer = Buffer.from(data, 'utf-8'); 62 | let file_name = more?.fileName || basename; 63 | let match = /\.([0-9a-z]+)(?=[?#])|(\.)(?:[\w]+)$/gim.exec(file_name); 64 | if (!match) { 65 | let fileInfo = await fromBuffer(basebuffer); 66 | if (fileInfo) { 67 | file_name = `${file_name}.${fileInfo.ext}`; 68 | } 69 | } 70 | let toUpload = new CustomFile(file_name, Buffer.byteLength(basebuffer), '', basebuffer); 71 | return await snakeClient.client.uploadFile({ 72 | file: toUpload, 73 | workers: more?.workers || 1, 74 | onProgress: more?.onProgress, 75 | }); 76 | } 77 | if (/^(\/|\.\.?\/|~\/)/i.exec(file)) { 78 | let file_name = more?.fileName || basename; 79 | let match = /\.([0-9a-z]+)(?=[?#])|(\.)(?:[\w]+)$/gim.exec(file_name); 80 | if (!match) { 81 | let fileInfo = await fromFile(file); 82 | if (fileInfo) { 83 | file_name = `${file_name}.${fileInfo.ext}`; 84 | } 85 | } 86 | let toUpload = new CustomFile(file_name, fs.statSync(file).size, file); 87 | return await snakeClient.client.uploadFile({ 88 | file: toUpload, 89 | workers: more?.workers || 1, 90 | onProgress: more?.onProgress, 91 | }); 92 | } 93 | } 94 | } catch (error: any) { 95 | snakeClient.log.error('Failed to running telegram.uploadFile'); 96 | throw new BotError( 97 | error.message, 98 | 'telegram.uploadFile', 99 | `${Buffer.isBuffer(file) ? `` : file}${ 100 | more ? ',' + JSON.stringify(more) : '' 101 | }` 102 | ); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/Telegram/Messages/GetMessages.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Snake } from '../../Client'; 10 | import BigInt from 'big-integer'; 11 | import { MessageContext } from '../../Context/MessageContext'; 12 | import * as Update from '../../Update'; 13 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 14 | import BotError from '../../Context/Error'; 15 | /** 16 | * Returns the list of messages by their IDs. 17 | * @param snakeClient - Client 18 | * @param {bigint|number|string} chatId - Chat/Groups/Channel id. 19 | * @param {Array} messageId - Message Id. 20 | * @param {boolean} replies - if `true` it will getting the nested reply. and will making floodwait. 21 | * ```ts 22 | * bot.command("getMessages",async (ctx)=>{ 23 | * let results = await ctx.telegram.getMessages(ctx.chat.id,[ctx.id]) 24 | * console.log(results) 25 | * }) 26 | * ``` 27 | */ 28 | export async function GetMessages( 29 | snakeClient: Snake, 30 | chatId: number | string | bigint, 31 | messageId: number[], 32 | replies: boolean = false 33 | ) { 34 | try { 35 | snakeClient.log.debug('Running telegram.getMessages'); 36 | if (typeof chatId === 'number') 37 | snakeClient.log.warning( 38 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 39 | ); 40 | let messageIds: any = messageId; 41 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 42 | if (type == 'channel' || type == 'supergroup') { 43 | let results: Api.messages.TypeMessages = await snakeClient.client.invoke( 44 | new Api.channels.GetMessages({ 45 | channel: peer, 46 | id: messageIds, 47 | }) 48 | ); 49 | let final: ResultsGetMessage = new ResultsGetMessage(); 50 | await final.init(results, snakeClient, replies); 51 | return final; 52 | } else { 53 | let results: Api.messages.TypeMessages = await snakeClient.client.invoke( 54 | new Api.messages.GetMessages({ 55 | id: messageIds, 56 | }) 57 | ); 58 | let final: ResultsGetMessage = new ResultsGetMessage(); 59 | await final.init(results, snakeClient, replies); 60 | return final; 61 | } 62 | } catch (error: any) { 63 | snakeClient.log.error('Failed to running telegram.getMessages'); 64 | throw new BotError( 65 | error.message, 66 | 'telegram.getMessages', 67 | `${chatId},${JSON.stringify(messageId)}` 68 | ); 69 | } 70 | } 71 | export class ResultsGetMessage { 72 | messages!: MessageContext[]; 73 | date: number | Date = Math.floor(Date.now() / 1000); 74 | constructor() {} 75 | async init(results: Api.messages.TypeMessages, SnakeClient: Snake, replies: boolean = false) { 76 | SnakeClient.log.debug('Creating results telegram.getMessages'); 77 | let tempMessages: MessageContext[] = []; 78 | if (results instanceof Api.messages.ChannelMessages) { 79 | for (let i = 0; i < results.messages.length; i++) { 80 | let msg = results.messages[i] as Api.Message; 81 | if (!replies) { 82 | delete msg.replyTo; 83 | } 84 | let msgc = new MessageContext(); 85 | await msgc.init(msg, SnakeClient); 86 | tempMessages.push(msgc); 87 | } 88 | } 89 | if (results instanceof Api.messages.Messages) { 90 | for (let i = 0; i < results.messages.length; i++) { 91 | let msg = results.messages[i] as Api.Message; 92 | if (!replies) { 93 | delete msg.replyTo; 94 | } 95 | let msgc = new MessageContext(); 96 | await msgc.init(msg, SnakeClient); 97 | tempMessages.push(msgc); 98 | } 99 | } 100 | this.messages = tempMessages; 101 | return this; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/Telegram/Messages/ForwardMessages.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Api } from 'telegram'; 9 | import { Snake } from '../../Client'; 10 | import { TypeReplyMarkup, BuildReplyMarkup } from '../../Utils/ReplyMarkup'; 11 | import Parser, { Entities } from '@tgsnake/parser'; 12 | import bigInt from 'big-integer'; 13 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 14 | import * as Update from '../../Update'; 15 | import BotError from '../../Context/Error'; 16 | 17 | export interface forwardMessageMoreParams { 18 | withMyScore?: boolean; 19 | silent?: boolean; 20 | background?: boolean; 21 | scheduleDate?: number; 22 | noforwards?: boolean; 23 | sendAs?: string; 24 | dropAuthor?: boolean; 25 | dropMediaCaptions?: boolean; 26 | } 27 | /** 28 | * Forwards messages by their IDs. 29 | * @param snakeClient - client 30 | * @param {number|string|bigint} chatId - Destination. 31 | * @param {number|string|bigint} fromChatId - Source of messages. 32 | * @param {Array} messageId - IDs of messages which will forwarded. 33 | * @param {Object} more - more paramaters to use. 34 | * ```ts 35 | * bot.command("forward", async (ctx) => { 36 | * let results = await ctx.telegram.forwardMessages(ctx.chat.id,ctx.chat.id,[ctx.id]) 37 | * return console.log(results) 38 | * }) 39 | * ``` 40 | */ 41 | export async function ForwardMessages( 42 | snakeClient: Snake, 43 | chatId: number | string | bigint, 44 | fromChatId: number | string | bigint, 45 | messageId: number[], 46 | more?: forwardMessageMoreParams 47 | ) { 48 | try { 49 | snakeClient.log.debug('Running telegram.forwardMessages'); 50 | if (typeof chatId === 'number') 51 | snakeClient.log.warning( 52 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 53 | ); 54 | if (typeof fromChatId === 'number') 55 | snakeClient.log.warning( 56 | 'Type of fromChatId is number, please switch to BigInt or String for security Ids 64 bit int.' 57 | ); 58 | let randomId: any = []; 59 | for (let i = 0; i < messageId.length; i++) { 60 | snakeClient.log.debug('Building randomId'); 61 | randomId.push(bigInt(Math.floor(Math.random() * 10000000000000))); 62 | } 63 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 64 | let [fId, fType, fPeer] = await toBigInt(fromChatId, snakeClient); 65 | let results: Api.TypeUpdates = await snakeClient.client.invoke( 66 | new Api.messages.ForwardMessages({ 67 | fromPeer: fPeer, 68 | toPeer: peer, 69 | id: messageId, 70 | randomId: randomId, 71 | ...more, 72 | }) 73 | ); 74 | return await createResults(results, snakeClient); 75 | } catch (error: any) { 76 | snakeClient.log.error('Failed to running telegram.forwardMessages'); 77 | throw new BotError( 78 | error.message, 79 | 'telegram.forwardMessages', 80 | `${chatId},${fromChatId},${JSON.stringify(messageId)},${ 81 | more ? JSON.stringify(more, null, 2) : '' 82 | }` 83 | ); 84 | } 85 | } 86 | async function createResults(results: Api.TypeUpdates, snakeClient: Snake) { 87 | snakeClient.log.debug('Creating results telegram.forwardMessages'); 88 | if (results instanceof Api.Updates) { 89 | results as Api.Updates; 90 | if (results.updates?.length > 0) { 91 | for (let i = 0; i < results.updates.length; i++) { 92 | if (results.updates[i] instanceof Api.UpdateNewMessage) { 93 | let arc = results.updates[i] as Api.UpdateNewMessage; 94 | let update = new Update.UpdateNewMessage(); 95 | await update.init(arc, snakeClient); 96 | return update; 97 | } 98 | if (results.updates[i] instanceof Api.UpdateNewChannelMessage) { 99 | let arc = results.updates[i] as Api.UpdateNewChannelMessage; 100 | let res = new Update.UpdateNewChannelMessage(); 101 | await res.init(arc, snakeClient); 102 | return res; 103 | } 104 | } 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/Telegram/Chats/EditAdmin.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Snake } from '../../Client'; 10 | import { Api } from 'telegram'; 11 | import BotError from '../../Context/Error'; 12 | import * as Updates from '../../Update'; 13 | import bigInt, { BigInteger } from 'big-integer'; 14 | import { convertId } from '../../Utils/ToBigInt'; 15 | 16 | export interface editAdminMoreParams { 17 | changeInfo?: boolean; 18 | postMessages?: boolean; 19 | editMessages?: boolean; 20 | deleteMessages?: boolean; 21 | banUsers?: boolean; 22 | inviteUsers?: boolean; 23 | pinMessages?: boolean; 24 | addAdmins?: boolean; 25 | anonymous?: boolean; 26 | manageCall?: boolean; 27 | rank?: string; 28 | } 29 | /** 30 | * Modify the admin rights of a user in a supergroup/channel. 31 | * @param snakeClient - Client 32 | * @param {bigint|number|string} chatId - Chat/Channel/Group id. 33 | * @param {bigint|number|string} userId - User id. 34 | * @param {Object} - more parameters to use. 35 | *```ts 36 | * bot.command("promote",async (ctx) => { 37 | * if((!ctx.chat.private) && ctx.replyToMessage){ 38 | * let results = await ctx.telegram.editAdmin(ctx.chat.id,ctx.replyToMessage.from.id) 39 | * console.log(results) 40 | * } 41 | * }) 42 | *``` 43 | * This method will return UpdateNewMessage or UpdateNewChannelMessage if success. 44 | */ 45 | export async function EditAdmin( 46 | snakeClient: Snake, 47 | chatId: bigint | number | string, 48 | userId: bigint | number | string, 49 | more?: editAdminMoreParams 50 | ) { 51 | try { 52 | snakeClient.log.debug('Running telegram.editAdmin'); 53 | if (typeof userId === 'number') 54 | snakeClient.log.warning( 55 | 'Type of userId is number, please switch to BigInt or String for security Ids 64 bit int.' 56 | ); 57 | if (typeof chatId === 'number') 58 | snakeClient.log.warning( 59 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 60 | ); 61 | let results: Api.TypeUpdates = await snakeClient.client.invoke( 62 | new Api.channels.EditAdmin({ 63 | channel: convertId(chatId), 64 | userId: convertId(userId), 65 | adminRights: new Api.ChatAdminRights( 66 | Object.assign( 67 | { 68 | changeInfo: true, 69 | postMessages: true, 70 | editMessages: true, 71 | deleteMessages: true, 72 | banUsers: true, 73 | inviteUsers: true, 74 | pinMessages: true, 75 | addAdmins: false, 76 | anonymous: false, 77 | manageCall: true, 78 | }, 79 | more 80 | ) 81 | ), 82 | rank: more?.rank || '', 83 | }) 84 | ); 85 | snakeClient.log.debug('Creating results telegram.editAdmin'); 86 | return await generateResults(results, snakeClient); 87 | } catch (error: any) { 88 | snakeClient.log.error('Failed to running telegram.editAdmin'); 89 | throw new BotError( 90 | error.message, 91 | 'telegram.editAdmin', 92 | `${chatId},${userId}${more ? ',' + JSON.stringify(more) : ''}` 93 | ); 94 | } 95 | } 96 | async function generateResults(results: Api.TypeUpdates, SnakeClient: Snake) { 97 | if (results instanceof Api.Updates) { 98 | results as Api.Updates; 99 | if (results.updates.length > 0) { 100 | for (let i = 0; i < results.updates.length; i++) { 101 | let update = results.updates[i]; 102 | if (update instanceof Api.UpdateNewMessage) { 103 | update as Api.UpdateNewMessage; 104 | let res = new Updates.UpdateNewMessage(); 105 | await res.init(update, SnakeClient); 106 | return res; 107 | } 108 | if (update instanceof Api.UpdateNewChannelMessage) { 109 | update as Api.UpdateNewChannelMessage; 110 | let res = new Updates.UpdateNewChannelMessage(); 111 | await res.init(update, SnakeClient); 112 | return res; 113 | } 114 | } 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/Telegram/Chats/EditBanned.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Snake } from '../../Client'; 10 | import { Api } from 'telegram'; 11 | import BotError from '../../Context/Error'; 12 | import * as Updates from '../../Update'; 13 | import { convertId } from '../../Utils/ToBigInt'; 14 | export interface editBannedMoreParams { 15 | untilDate?: number; 16 | viewMessages?: boolean; 17 | sendMessages?: boolean; 18 | sendMedia?: boolean; 19 | sendStickers?: boolean; 20 | sendGifs?: boolean; 21 | sendGames?: boolean; 22 | sendInline?: boolean; 23 | sendPolls?: boolean; 24 | changeInfo?: boolean; 25 | inviteUsers?: boolean; 26 | pinMessages?: boolean; 27 | embedLinks?: boolean; 28 | } 29 | /** 30 | * Ban/unban/kick a user in a supergroup/channel. 31 | * @param snakeClient - Client 32 | * @param {number|bigint|string} chatId - Chat/Group/Channel id. 33 | * @param {number|bigint|string} userId - User id. 34 | * @param {Object} more - more parameters to use. 35 | * ```ts 36 | * bot.command("ban",async (ctx) => { 37 | * if((!ctx.chat.private) && ctx.replyToMessage){ 38 | * let results = await ctx.telegram.editBanned(ctx.chat.id,ctx.replyToMessage.from.id) 39 | * console.log(results) 40 | * } 41 | * }) 42 | * ``` 43 | * This method will return UpdateNewMessage or UpdateNewChannelMessage. if success. 44 | */ 45 | export async function EditBanned( 46 | snakeClient: Snake, 47 | chatId: bigint | number | string, 48 | userId: bigint | number | string, 49 | more?: editBannedMoreParams 50 | ) { 51 | try { 52 | snakeClient.log.debug('Running telegram.editBanned'); 53 | if (typeof userId === 'number') 54 | snakeClient.log.warning( 55 | 'Type of userId is number, please switch to BigInt or String for security Ids 64 bit int.' 56 | ); 57 | if (typeof chatId === 'number') 58 | snakeClient.log.warning( 59 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 60 | ); 61 | let results: Api.TypeUpdates = await snakeClient.client.invoke( 62 | new Api.channels.EditBanned({ 63 | channel: convertId(chatId), 64 | participant: convertId(userId), 65 | bannedRights: new Api.ChatBannedRights( 66 | Object.assign( 67 | { 68 | untilDate: 0, 69 | viewMessages: true, 70 | sendMessages: true, 71 | sendMedia: true, 72 | sendStickers: true, 73 | sendGifs: true, 74 | sendGames: true, 75 | sendInline: true, 76 | sendPolls: true, 77 | changeInfo: true, 78 | inviteUsers: true, 79 | pinMessages: true, 80 | embedLinks: true, 81 | }, 82 | more 83 | ) 84 | ), 85 | }) 86 | ); 87 | snakeClient.log.debug('Creating results telegram.editBanned'); 88 | return await generateResults(results, snakeClient); 89 | } catch (error: any) { 90 | snakeClient.log.error('Failed to running telegram.editBanned'); 91 | throw new BotError( 92 | error.message, 93 | 'telegram.editBanned', 94 | `${chatId},${userId}${more ? ',' + JSON.stringify(more) : ''}` 95 | ); 96 | } 97 | } 98 | async function generateResults(results: Api.TypeUpdates, SnakeClient: Snake) { 99 | if (results instanceof Api.Updates) { 100 | results as Api.Updates; 101 | if (results.updates.length > 0) { 102 | for (let i = 0; i < results.updates.length; i++) { 103 | let update = results.updates[i]; 104 | if (update instanceof Api.UpdateNewMessage) { 105 | update as Api.UpdateNewMessage; 106 | let res = new Updates.UpdateNewMessage(); 107 | await res.init(update, SnakeClient); 108 | return res; 109 | } 110 | if (update instanceof Api.UpdateNewChannelMessage) { 111 | update as Api.UpdateNewChannelMessage; 112 | let res = new Updates.UpdateNewChannelMessage(); 113 | await res.init(update, SnakeClient); 114 | return res; 115 | } 116 | } 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/Update/UpdateUserTyping.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { From } from '../Utils/From'; 11 | import { Update } from './Update'; 12 | import { Telegram } from '../Telegram'; 13 | import { Snake } from '../Client'; 14 | import { toString } from '../Utils/ToBigInt'; 15 | export class UpdateUserTyping extends Update { 16 | user!: From; 17 | action!: string; 18 | progress!: number; 19 | messageId!: number; 20 | emoticon!: string; 21 | interaction!: any; 22 | constructor() { 23 | super(); 24 | this['_'] = 'updateUserTyping'; 25 | } 26 | async init(update: Api.UpdateUserTyping, SnakeClient: Snake) { 27 | SnakeClient.log.debug(`Creating ${this['_']}`); 28 | this.telegram = SnakeClient.telegram; 29 | if (update.userId) { 30 | let user = new From(); 31 | await user.init(BigInt(toString(update.userId!) as string), SnakeClient); 32 | this.user = user; 33 | } 34 | if (update.action instanceof Api.SendMessageTypingAction) { 35 | this.action = 'typing'; 36 | } 37 | if (update.action instanceof Api.SendMessageCancelAction) { 38 | this.action = 'cancel'; 39 | } 40 | if (update.action instanceof Api.SendMessageRecordVideoAction) { 41 | this.action = 'recordVideo'; 42 | } 43 | if (update.action instanceof Api.SendMessageUploadVideoAction) { 44 | update.action as Api.SendMessageUploadVideoAction; 45 | this.action = 'uploadVideo'; 46 | this.progress = update.action.progress; 47 | } 48 | if (update.action instanceof Api.SendMessageRecordAudioAction) { 49 | this.action = 'recordAudio'; 50 | } 51 | if (update.action instanceof Api.SendMessageUploadAudioAction) { 52 | update.action as Api.SendMessageUploadAudioAction; 53 | this.action = 'uploadAudio'; 54 | this.progress = update.action.progress; 55 | } 56 | if (update.action instanceof Api.SendMessageUploadPhotoAction) { 57 | update.action as Api.SendMessageUploadPhotoAction; 58 | this.action = 'uploadPhoto'; 59 | this.progress = update.action.progress; 60 | } 61 | if (update.action instanceof Api.SendMessageUploadDocumentAction) { 62 | update.action as Api.SendMessageUploadDocumentAction; 63 | this.action = 'uploadDocument'; 64 | this.progress = update.action.progress; 65 | } 66 | if (update.action instanceof Api.SendMessageGeoLocationAction) { 67 | this.action = 'geoLocation'; 68 | } 69 | if (update.action instanceof Api.SendMessageChooseContactAction) { 70 | this.action = 'chooseContact'; 71 | } 72 | if (update.action instanceof Api.SendMessageGamePlayAction) { 73 | this.action = 'gamePlay'; 74 | } 75 | if (update.action instanceof Api.SendMessageRecordRoundAction) { 76 | this.action = 'recordRound'; 77 | } 78 | if (update.action instanceof Api.SendMessageUploadRoundAction) { 79 | update.action as Api.SendMessageUploadRoundAction; 80 | this.action = 'uploadRound'; 81 | this.progress = update.action.progress; 82 | } 83 | if (update.action instanceof Api.SpeakingInGroupCallAction) { 84 | this.action = 'speakingInGroupCall'; 85 | } 86 | if (update.action instanceof Api.SendMessageHistoryImportAction) { 87 | update.action as Api.SendMessageHistoryImportAction; 88 | this.action = 'historyImport'; 89 | this.progress = update.action.progress; 90 | } 91 | if (update.action instanceof Api.SendMessageChooseStickerAction) { 92 | update.action as Api.SendMessageChooseStickerAction; 93 | this.action = 'chooseSticker'; 94 | } 95 | if (update.action instanceof Api.SendMessageEmojiInteraction) { 96 | update.action as Api.SendMessageEmojiInteraction; 97 | this.action = 'emojiInteraction'; 98 | this.emoticon = update.action.emoticon; 99 | this.messageId = update.action.msgId; 100 | this.interaction = update.action.interaction; 101 | } 102 | if (update.action instanceof Api.SendMessageEmojiInteractionSeen) { 103 | this.action = 'emojiInteractionSeen'; 104 | this.emoticon = update.action.emoticon; 105 | } 106 | return this; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/Telegram/Media/SendSticker.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { SendMedia, sendMediaMoreParams } from './SendMedia'; 12 | import { UploadFile } from './UploadFile'; 13 | import { decodeFileId } from 'tg-file-id'; 14 | import * as Medias from '../../Utils/Medias'; 15 | import bigInt from 'big-integer'; 16 | import BotError from '../../Context/Error'; 17 | /** 18 | * Sending sticker with fileId/file location/url/buffer. 19 | * @param snakeClient - client 20 | * @param {bigint|number|string} chatId - Chat/Groups/Channel id. 21 | * @param {string|Buffer|Object} fileId - Path file/FileId/Buffer. 22 | * ```ts 23 | * bot.on("message",async (ctx) => { 24 | * if(ctx.media && ctx.media._ == "sticker"){ 25 | * let results = await ctx.telegram.sendSticker(ctx.chat.id,ctx.media.fileId) 26 | * console.log(results) 27 | * } 28 | * }) 29 | * ``` 30 | */ 31 | export async function SendSticker( 32 | snakeClient: Snake, 33 | chatId: number | string | bigint, 34 | fileId: string | Buffer | Medias.MediaSticker 35 | ) { 36 | try { 37 | snakeClient.log.debug('Running telegram.sendSticker'); 38 | if (typeof chatId === 'number') 39 | snakeClient.log.warning( 40 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 41 | ); 42 | switch (fileId.constructor) { 43 | case Buffer: 44 | fileId as Buffer; 45 | return await SendMedia( 46 | snakeClient, 47 | chatId, 48 | new Api.InputMediaUploadedDocument({ 49 | //@ts-ignore 50 | file: await UploadFile(snakeClient, fileId), 51 | mimeType: 'image/webp', 52 | attributes: [ 53 | new Api.DocumentAttributeFilename({ 54 | fileName: `sticker.webp`, 55 | }), 56 | ], 57 | }) 58 | ); 59 | break; 60 | case Medias.MediaSticker: 61 | fileId as Medias.MediaSticker; 62 | return await SendMedia( 63 | snakeClient, 64 | chatId, 65 | new Api.InputMediaDocument({ 66 | id: new Api.InputDocument({ 67 | //@ts-ignore 68 | id: bigInt(String(fileId._id)), 69 | //@ts-ignore 70 | accessHash: bigInt(String(fileId._accessHash)), 71 | //@ts-ignore 72 | fileReference: Buffer.from(fileId._fileReference, 'hex'), 73 | }), 74 | }) 75 | ); 76 | break; 77 | case String: 78 | fileId as string; 79 | //@ts-ignore 80 | if (/^http/i.test(fileId) || /^(\/|\.\.?\/|~\/)/i.test(fileId)) { 81 | return await SendMedia( 82 | snakeClient, 83 | chatId, 84 | new Api.InputMediaUploadedDocument({ 85 | //@ts-ignore 86 | file: await UploadFile(snakeClient, fileId), 87 | mimeType: 'image/webp', 88 | attributes: [ 89 | new Api.DocumentAttributeFilename({ 90 | fileName: `sticker.webp`, 91 | }), 92 | ], 93 | }) 94 | ); 95 | } else { 96 | //@ts-ignore 97 | let file = await decodeFileId(fileId); 98 | if (file.typeId !== 8) throw new Error(`Invalid fileId. This fileId not for sticker`); 99 | return await SendMedia( 100 | snakeClient, 101 | chatId, 102 | new Api.InputMediaDocument({ 103 | id: new Api.InputDocument({ 104 | id: bigInt(String(file.id)), 105 | accessHash: bigInt(String(file.access_hash)), 106 | fileReference: Buffer.from(file.fileReference, 'hex'), 107 | }), 108 | }) 109 | ); 110 | } 111 | break; 112 | default: 113 | throw new Error(`Couldn't resolve this fileId.`); 114 | } 115 | } catch (error: any) { 116 | snakeClient.log.error('Failed to running telegram.sendSticker'); 117 | throw new BotError( 118 | error.message, 119 | 'telegram.sendSticker', 120 | `${chatId},${ 121 | Buffer.isBuffer(fileId) ? `` : JSON.stringify(fileId) 122 | }` 123 | ); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/Telegram/Messages/sendMessage.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published.. 8 | 9 | import { Api } from 'telegram'; 10 | import { Snake } from '../../Client'; 11 | import { TypeReplyMarkup, BuildReplyMarkup } from '../../Utils/ReplyMarkup'; 12 | import Parser, { Entities } from '@tgsnake/parser'; 13 | import bigInt from 'big-integer'; 14 | import * as Update from '../../Update'; 15 | import { toBigInt, toString } from '../../Utils/ToBigInt'; 16 | import BotError from '../../Context/Error'; 17 | const parser = new Parser(Api); 18 | export interface sendMessageMoreParams { 19 | noWebpage?: boolean; 20 | silent?: boolean; 21 | background?: boolean; 22 | parseMode?: string; 23 | clearDraft?: boolean; 24 | replyToMsgId?: number; 25 | replyMarkup?: TypeReplyMarkup; 26 | entities?: Entities[]; 27 | scheduleDate?: number; 28 | noforwards?: boolean; 29 | sendAs?: string; 30 | } 31 | export async function sendMessage( 32 | snakeClient: Snake, 33 | chatId: number | string | bigint, 34 | text: string, 35 | more?: sendMessageMoreParams 36 | ) { 37 | try { 38 | snakeClient.log.debug('Running telegram.sendMessage'); 39 | if (typeof chatId === 'number') 40 | snakeClient.log.warning( 41 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 42 | ); 43 | let parseMode = ''; 44 | let replyMarkup; 45 | let parseText = text; 46 | let entities: Api.TypeMessageEntity[] = []; 47 | let [id, type, peer] = await toBigInt(chatId, snakeClient); 48 | if (more) { 49 | if (more.parseMode) { 50 | parseMode = more.parseMode.toLowerCase(); 51 | delete more.parseMode; 52 | } 53 | if (more.replyMarkup) { 54 | snakeClient.log.debug('Building replyMarkup'); 55 | replyMarkup = await BuildReplyMarkup(more.replyMarkup!, snakeClient); 56 | delete more.replyMarkup; 57 | } 58 | if (more.entities) { 59 | snakeClient.log.debug('Building Entities'); 60 | entities = (await parser.toRaw( 61 | snakeClient.client!, 62 | more.entities! 63 | )) as Array; 64 | } 65 | } 66 | if (!more?.entities) { 67 | snakeClient.log.debug('Building Entities'); 68 | //@ts-ignore 69 | let [t, e] = parseMode !== '' ? parser.parse(text, parseMode) : [text, []]; 70 | parseText = t; 71 | entities = (await parser.toRaw(snakeClient.client!, e!)) as Array; 72 | } 73 | let results: Api.TypeUpdates = await snakeClient.client.invoke( 74 | new Api.messages.SendMessage({ 75 | peer: peer, 76 | message: parseText, 77 | randomId: bigInt(-Math.floor(Math.random() * 10000000000000)), 78 | //@ts-ignore 79 | entities: entities, 80 | replyMarkup: replyMarkup, 81 | ...more, 82 | }) 83 | ); 84 | return await createResults(results, snakeClient); 85 | } catch (error: any) { 86 | snakeClient.log.error('Failed to running telegram.sendMessage'); 87 | throw new BotError( 88 | error.message, 89 | 'telegram.sendMessage', 90 | `${chatId},${text},${more ? JSON.stringify(more, null, 2) : ''}` 91 | ); 92 | } 93 | } 94 | async function createResults(results: Api.TypeUpdates, snakeClient: Snake) { 95 | snakeClient.log.debug('Creating results telegram.sendMessage'); 96 | if (results instanceof Api.UpdateShortSentMessage) { 97 | results as Api.UpdateShortSentMessage; 98 | let update = new Update.UpdateShortSentMessage(); 99 | await update.init(results, snakeClient); 100 | return update; 101 | } 102 | if (results instanceof Api.Updates) { 103 | results as Api.Updates; 104 | if (results.updates.length > 0) { 105 | for (let i = 0; i < results.updates.length; i++) { 106 | if (results.updates[i] instanceof Api.UpdateNewMessage) { 107 | let arc = results.updates[i] as Api.UpdateNewMessage; 108 | let update = new Update.UpdateNewMessage(); 109 | await update.init(arc, snakeClient); 110 | return update; 111 | } 112 | if (results.updates[i] instanceof Api.UpdateNewChannelMessage) { 113 | let arc = results.updates[i] as Api.UpdateNewChannelMessage; 114 | let update = new Update.UpdateNewChannelMessage(); 115 | await update.init(arc, snakeClient); 116 | return update; 117 | } 118 | } 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/Telegram/Chats/GetParticipants.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Snake } from '../../Client'; 9 | import { Api } from 'telegram'; 10 | import { ResultGetEntity } from '../Users/GetEntity'; 11 | import { ChatParticipants } from '../../Utils/ChatParticipants'; 12 | import BotError from '../../Context/Error'; 13 | import { toBigInt } from '../../Utils/ToBigInt'; 14 | import bigInt from 'big-integer'; 15 | export interface GetParticipantMoreParams { 16 | offset?: number; 17 | limit?: number; 18 | query?: string; 19 | filter?: 'all' | 'kicked' | 'restricted' | 'bots' | 'recents' | 'administrators'; 20 | } 21 | /** 22 | * Getting list from all participants in channel or chats. 23 | * @param snakeClient - Client 24 | * @param {number|string|bigint} chatId - Chat or channels id to getting the list of members. 25 | * @param {Object} more - more parameters to use. 26 | * ```ts 27 | * bot.command("getChatMembers",async (ctx) => { 28 | * let results = await ctx.telegram.getParticipants(ctx.chat.id) // getChatMembers and getParticipants is same methods. 29 | * console.log(results) 30 | * }) 31 | * ``` 32 | */ 33 | export async function GetParticipants( 34 | snakeClient: Snake, 35 | chatId: number | string | bigint, 36 | more?: GetParticipantMoreParams 37 | ): Promise { 38 | try { 39 | snakeClient.log.debug('Running telegram.getParticipants'); 40 | if (typeof chatId === 'number') 41 | snakeClient.log.warning( 42 | 'Type of chatId is number, please switch to BigInt or String for security Ids 64 bit int.' 43 | ); 44 | let options = Object.assign( 45 | { 46 | offset: 0, 47 | limit: 200, 48 | query: '', 49 | filter: 'all', 50 | }, 51 | more || {} 52 | ); 53 | let chat: ResultGetEntity = await snakeClient.telegram.getEntity(chatId, true); 54 | if (chat.type == 'user') { 55 | throw new Error('Typeof chatId must be channel or chat, not a user.'); 56 | } 57 | if (chat.type == 'chat') { 58 | let r: Api.messages.ChatFull = await snakeClient.client.invoke( 59 | new Api.messages.GetFullChat({ 60 | chatId: bigInt(String(chat.id * BigInt(-1)) as string), 61 | }) 62 | ); 63 | let cf: Api.ChatFull = r.fullChat as Api.ChatFull; 64 | let part: Api.ChatParticipants = cf.participants as Api.ChatParticipants; 65 | snakeClient.log.debug('Creating results telegram.getParticipants'); 66 | let participant: ChatParticipants = new ChatParticipants(); 67 | await participant.init(part, snakeClient); 68 | return participant; 69 | } 70 | if (chat.type == 'channel' || chat.type == 'supergroup') { 71 | let filter: Api.TypeChannelParticipantsFilter = new Api.ChannelParticipantsSearch({ 72 | q: options.query, 73 | }); 74 | switch (options.filter) { 75 | case 'kicked': 76 | filter = new Api.ChannelParticipantsKicked({ q: options.query }); 77 | break; 78 | case 'restricted': 79 | filter = new Api.ChannelParticipantsBanned({ q: options.query }); 80 | break; 81 | case 'bots': 82 | filter = new Api.ChannelParticipantsBots(); 83 | break; 84 | case 'recents': 85 | filter = new Api.ChannelParticipantsRecent(); 86 | break; 87 | case 'administrators': 88 | filter = new Api.ChannelParticipantsAdmins(); 89 | break; 90 | default: 91 | } 92 | let r: Api.channels.ChannelParticipants = (await snakeClient.client.invoke( 93 | new Api.channels.GetParticipants({ 94 | channel: bigInt(chat.id as bigint), 95 | filter: filter, 96 | offset: options.offset, 97 | limit: options.limit, 98 | hash: bigInt(0), 99 | }) 100 | )) as Api.channels.ChannelParticipants; 101 | snakeClient.log.debug('Creating results telegram.getParticipants'); 102 | let participant: ChatParticipants = new ChatParticipants(); 103 | //@ts-ignore 104 | await participant.init(r as Api.ChannelParticipants, snakeClient); 105 | return participant; 106 | } 107 | } catch (error: any) { 108 | snakeClient.log.error('Failed to running telegram.getParticipants'); 109 | throw new BotError( 110 | error.message, 111 | 'telegram.getParticipants', 112 | `${chatId},${JSON.stringify(more)}` 113 | ); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/Update/Update.ts: -------------------------------------------------------------------------------- 1 | // Tgsnake - Telegram MTProto framework developed based on gram.js. 2 | // Copyright (C) 2022 Butthx 3 | // 4 | // This file is part of Tgsnake 5 | // 6 | // Tgsnake is a free software : you can redistribute it and/or modify 7 | // it under the terms of the MIT License as published. 8 | import { Telegram } from '../Telegram'; 9 | import { sendMessageMoreParams } from '../Telegram/Messages/sendMessage'; 10 | import { betterConsoleLog } from '../Utils/CleanObject'; 11 | import { inspect } from 'util'; 12 | export type TypeUpdates = 13 | | 'updateNewMessage' // done 14 | | 'updateMessageID' // done 15 | | 'updateDeleteMessages' // done 16 | | 'updateUserTyping' // done 17 | | 'updateChatUserTyping' // done 18 | | 'updateChatParticipants' // done 19 | | 'updateUserStatus' // done 20 | | 'updateUserName' // done 21 | | 'updateUserPhoto' 22 | | 'updateNewEncryptedMessage' 23 | | 'updateEncryptedChatTyping' 24 | | 'updateEncryption' 25 | | 'updateEncryptedMessagesRead' 26 | | 'updateChatParticipantAdd' 27 | | 'updateChatParticipantDelete' 28 | | 'updateDcOptions' 29 | | 'updateNotifySettings' 30 | | 'updateServiceNotification' 31 | | 'updatePrivacy' 32 | | 'updateUserPhone' 33 | | 'updateReadHistoryInbox' 34 | | 'updateReadHistoryOutbox' 35 | | 'updateWebPage' 36 | | 'updateReadMessagesContents' 37 | | 'updateChannelTooLong' 38 | | 'updateChannel' 39 | | 'updateNewChannelMessage' // done 40 | | 'updateReadChannelInbox' 41 | | 'updateDeleteChannelMessages' 42 | | 'updateChannelMessageViews' 43 | | 'updateChatParticipantAdmin' 44 | | 'updateNewStickerSet' 45 | | 'updateStickerSetsOrder' 46 | | 'updateStickerSets' 47 | | 'updateSavedGifs' 48 | | 'updateBotInlineQuery' // done 49 | | 'updateBotInlineSend' 50 | | 'updateEditChannelMessage' // done 51 | | 'updateBotCallbackQuery' // done 52 | | 'updateEditMessage' // done 53 | | 'updateInlineBotCallbackQuery' // done 54 | | 'updateReadChannelOutbox' 55 | | 'updateDraftMessage' 56 | | 'updateReadFeaturedStickers' 57 | | 'updateRecentStickers' 58 | | 'updateConfig' 59 | | 'updatePtsChanged' 60 | | 'updateChannelWebPage' 61 | | 'updateDialogPinned' 62 | | 'updatePinnedDialogs' 63 | | 'updateBotWebhookJSON' 64 | | 'updateBotWebhookJSONQuery' 65 | | 'updateBotShippingQuery' 66 | | 'updateBotPrecheckoutQuery' 67 | | 'updatePhoneCall' 68 | | 'updateLangPackTooLong' 69 | | 'updateLangPack' 70 | | 'updateFavedStickers' 71 | | 'updateChannelReadMessagesContents' 72 | | 'updateContactsReset' 73 | | 'updateChannelAvailableMessages' 74 | | 'updateDialogUnreadMark' 75 | | 'updateMessagePoll' 76 | | 'updateChatDefaultBannedRights' 77 | | 'updateFolderPeers' 78 | | 'updatePeerSettings' 79 | | 'updatePeerLocated' 80 | | 'updateNewScheduledMessage' 81 | | 'updateDeleteScheduledMessages' 82 | | 'updateTheme' 83 | | 'updateGeoLiveViewed' 84 | | 'updateLoginToken' 85 | | 'updateMessagePollVote' 86 | | 'updateDialogFilter' 87 | | 'updateDialogFilterOrder' 88 | | 'updateDialogFilters' 89 | | 'updatePhoneCallSignalingData' 90 | | 'updateChannelMessageForwards' 91 | | 'updateReadChannelDiscussionInbox' 92 | | 'updateReadChannelDiscussionOutbox' 93 | | 'updatePeerBlocked' 94 | | 'updateChannelUserTyping' 95 | | 'updatePinnedMessages' 96 | | 'updatePinnedChannelMessages' 97 | | 'updateChat' 98 | | 'updateGroupCallParticipants' 99 | | 'updateGroupCall' 100 | | 'updatePeerHistoryTTL' 101 | | 'updateChatParticipant' 102 | | 'updateChannelParticipant' 103 | | 'updateBotStopped' 104 | | 'updateGroupCallConnection' 105 | | 'updateBotCommands' 106 | | 'updatesTooLong' 107 | | 'updateShortMessage' // done 108 | | 'updateShortChatMessage' // done 109 | | 'updateShort' 110 | | 'updatesCombined' 111 | | 'updates' 112 | | 'updateShortSentMessage'; // done 113 | 114 | export class Update { 115 | '_'!: TypeUpdates; 116 | /** @hidden */ 117 | private _telegram!: Telegram; 118 | constructor() {} 119 | /** @hidden */ 120 | [inspect.custom]() { 121 | return betterConsoleLog(this); 122 | } 123 | /** @hidden */ 124 | toJSON() { 125 | let obj = betterConsoleLog(this); 126 | for (let [key, value] of Object.entries(obj)) { 127 | if (typeof value == 'bigint') obj[key] = String(value); 128 | } 129 | return obj; 130 | } 131 | get telegram() { 132 | return this._telegram; 133 | } 134 | set telegram(tg: Telegram) { 135 | this._telegram = tg; 136 | } 137 | get SnakeClient() { 138 | //@ts-ignore 139 | return this._telegram.SnakeClient; 140 | } 141 | get snakeClient() { 142 | //@ts-ignore 143 | return this._telegram.SnakeClient; 144 | } 145 | } 146 | --------------------------------------------------------------------------------