diff --git a/README.md b/README.md index b7ec9d0..3a7c925 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,13 @@ This bot was created for channel and chat management. ### Bun +- Install [Bun](https://bun.sh/) - Install all dependencies: `bun install` - Use command `bun bun:start` ### NodeJS +- Install [NodeJS](https://nodejs.org) - Install all dependencies: `npm install` - Build the bot: `node run build` - Use command `node run start` diff --git a/bun.lockb b/bun.lockb index 038d50b..bbc5a32 100644 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 016b16d..fc66e7b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "msdbot_telegram", - "version": "0.2.4", + "version": "0.3.0", "author": "MasedMSD", "module": "./src/index.ts", "main": "./dist/index.js", @@ -25,20 +25,19 @@ }, "dependencies": { "@roziscoding/grammy-autoquote": "^2.0.6", - "dotenv": "^16.4.5", "drizzle-orm": "^0.36.1", - "grammy": "^1.24.0", + "grammy": "^1.31.2", "moment": "^2.30.1", - "pg": "^8.12.0", - "sagiri": "^4.2.0", + "pg": "^8.13.1", + "sagiri": "^4.2.3", "telegra.ph": "^1.0.1", - "tslib": "^2.6.2" + "tslib": "^2.8.1" }, "devDependencies": { - "@types/bun": "^1.1.11", - "@types/node": "^22.7.5", + "@types/bun": "^1.1.13", + "@types/node": "^22.9.0", "@types/pg": "^8.11.6", - "drizzle-kit": "^0.26.2", + "drizzle-kit": "^0.28.0", "prettier": "^3.3.0", "typegram": "^5.2.0", "typescript": "^5.6.3" diff --git a/src/handlers/autocaching.ts b/src/handlers/autocaching.ts new file mode 100644 index 0000000..9c30714 --- /dev/null +++ b/src/handlers/autocaching.ts @@ -0,0 +1,24 @@ +import type { Context, NextFunction } from "grammy"; +import { Database } from "../structures/database"; + +export const autoCaching = async (ctx: Context & { database: Database }, database: Database, next: NextFunction) => { + ctx.database = database; + await next(); + + const user = ctx.from; + if (!user || user.is_bot || user.id == 777000) return await next(); + + const dbuser = await database.resolveUser(user!, true); + + if ( + user?.first_name !== dbuser?.first_name || + user?.last_name !== dbuser?.last_name || + user?.username !== dbuser?.username + ) { + await database.updateUser(user!, { + first_name: user?.first_name, + last_name: user?.last_name, + username: user?.username, + }); + } +}; diff --git a/src/handlers/dick.composer.ts b/src/handlers/dick.composer.ts index 464ce5d..dffcc43 100644 --- a/src/handlers/dick.composer.ts +++ b/src/handlers/dick.composer.ts @@ -11,14 +11,12 @@ const random = (min: number, max: number, includeMax?: boolean) => export const dickComposer: Composer = new Composer(); -dickComposer.command("dick", async ctx => { +dickComposer.command(["dick", "cock", "dck"], async ctx => { const user = ctx.msg.from!; - const db_user_dick = (await ctx.database.resolveDick(user, true))!; - - const size = db_user_dick.size; + const { size, timestamp } = (await ctx.database.resolveDick(user, true))!; const now = moment().unix(); - const lastUsed = now - db_user_dick.timestamp.getTime(); + const lastUsed = now - timestamp.getTime(); if (lastUsed < timeout) { const timeLeft = moment((timeout - lastUsed) * 1000) diff --git a/src/handlers/eval.command.ts b/src/handlers/eval.command.ts deleted file mode 100644 index 5104f50..0000000 --- a/src/handlers/eval.command.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { config } from "dotenv"; -import type { Context } from "grammy"; -import { resolve } from "path"; -import { inspect } from "util"; - -const envs = config({ path: resolve(process.cwd(), ".env") }).parsed!; - -const clean = async (text: string | Promise) => { - if (text && text.constructor.name == "Promise") text = await text; - if (typeof text !== "string") text = inspect(text, { depth: 1 }); - - text = text.replace(/`/g, "`" + String.fromCharCode(8203)).replace(/@/g, "@" + String.fromCharCode(8203)); - - return text; -}; - -function getCircularReplacer(): (key: string, value: unknown) => unknown { - const seen = new WeakSet(); - - return (_, value) => { - if (typeof value !== "object" || value === null) return value; - if (seen.has(value)) return "[Circular]"; - - seen.add(value); - - return value; - }; -} - -export const evalCommand = async (ctx: Context) => { - if (ctx.from!.id !== 946070039) return; - - const prompt = ctx.match?.toString().replace(/(^`{3}(\w+)?|`{3}$)/gm, "")!; - const res = await eval(await clean(prompt)); - - let JSONed = res == undefined ? "Результата нет" : JSON.stringify(res, getCircularReplacer(), 4).slice(0, 4092); - - Object.values(envs).forEach(value => (JSONed = JSONed.replace(new RegExp(value!, "g"), "*".repeat(value!.length)))); - return ctx.reply(`
${JSONed}
`, { - parse_mode: "HTML", - }); -}; diff --git a/src/handlers/index.ts b/src/handlers/index.ts index b08800d..ed26f21 100644 --- a/src/handlers/index.ts +++ b/src/handlers/index.ts @@ -1,9 +1,10 @@ +export * from "./autocaching"; + export * from "./dick.composer"; export * from "./githubLink.composer"; export * from "./msdincorporated.composer"; -export * from "./randomEmoji.compose"; +export * from "./randomShit.composer"; export * from "./telegraph.composer"; -export * from "./eval.command"; export * from "./exec.command"; export * from "./start.command"; diff --git a/src/handlers/msdincorporated.composer.ts b/src/handlers/msdincorporated.composer.ts index e0a617e..2e5e067 100644 --- a/src/handlers/msdincorporated.composer.ts +++ b/src/handlers/msdincorporated.composer.ts @@ -1,9 +1,11 @@ -import { Composer } from "grammy"; +import { Composer, InputFile } from "grammy"; +import { resolve } from "path"; +import { cwd } from "process"; import sagiri from "sagiri"; import type { Message, MessageEntity } from "typegram"; const channelID = -1001528929804; -const chatChannelID = -1001528929804; +const chatChannelID = -1001705068191; const urlParser = (urls: string[]) => { const sortedURLs: [string, string][] = []; @@ -60,7 +62,7 @@ msdIncorporatedComposer.on(["channel_post::hashtag", "edited_channel_post::hasht }); msdIncorporatedComposer.on(":photo").on(":is_automatic_forward", async ctx => { - if (chatChannelID !== (ctx.message?.forward_origin! as Message).chat.id) return; + if (channelID !== (ctx.message?.forward_origin! as Message).chat.id) return; if (!ctx.message?.caption?.includes("#Hentai")) return; if (ctx.message?.caption?.includes("#RealLife") || ctx.message?.caption?.includes("#Video")) return; if (ctx.message?.media_group_id) return; @@ -94,3 +96,8 @@ msdIncorporatedComposer.on(":photo").on(":is_automatic_forward", async ctx => { } ); }); + +msdIncorporatedComposer.on(":new_chat_members", async ctx => { + if (ctx.chat.id !== chatChannelID) return; + ctx.replyWithAnimation(new InputFile(resolve(cwd(), "src", "media", "welcome.gif"))); +}); diff --git a/src/handlers/randomEmoji.compose.ts b/src/handlers/randomEmoji.compose.ts deleted file mode 100644 index d83c465..0000000 --- a/src/handlers/randomEmoji.compose.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Composer } from "grammy"; - -export const randomEmojiComposer = new Composer(); - -randomEmojiComposer.on("message:text", async (ctx, next) => { - await next(); - - if (ctx.message.from.is_bot) return; - if (Math.random() < 0.01) return ctx.react("👀"); -}); diff --git a/src/handlers/randomShit.composer.ts b/src/handlers/randomShit.composer.ts new file mode 100644 index 0000000..bbb9b37 --- /dev/null +++ b/src/handlers/randomShit.composer.ts @@ -0,0 +1,14 @@ +import { Composer } from "grammy"; + +export const randomShitComposer = new Composer(); + +randomShitComposer.on("message:text", async (ctx, next) => { + await next(); + + if (ctx.message.from.is_bot) return; + if (Math.random() < 0.01) return ctx.react("👀"); +}); + +randomShitComposer.on("::mention", ctx => { + if (ctx.message?.text == `@${ctx.me.username}`) return ctx.reply("Я тут!"); +}); diff --git a/src/index.ts b/src/index.ts index 566108c..634e91f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,3 @@ -import { config } from "dotenv"; -import { resolve } from "path"; import { Client } from "./structures/client"; -config({ path: resolve(process.cwd(), ".env") }); -const client = new Client(); - -client.init(); +new Client().init(); diff --git a/src/structures/client.ts b/src/structures/client.ts index 9f52c30..b336e78 100644 --- a/src/structures/client.ts +++ b/src/structures/client.ts @@ -1,18 +1,16 @@ import { autoQuote } from "@roziscoding/grammy-autoquote"; -import { Bot, InputFile, type Context } from "grammy"; -import { resolve } from "path"; -import { cwd } from "process"; -import type { UserFromGetMe } from "typegram"; +import { Bot, type Context } from "grammy"; import { + autoCaching, dickComposer, - evalCommand, execCommand, githubLinkComposer, msdIncorporatedComposer, - randomEmojiComposer, + randomShitComposer, startCommand, telegraphComposer, -} from "../handlers"; +} from "handlers"; +import type { UserFromGetMe } from "typegram"; import { Database } from "./database"; const onStart = ({ id, username }: UserFromGetMe) => console.log(`${username} [${id}] started!`); @@ -32,53 +30,18 @@ export class Client { await this.database.connect(); this.bot.use(autoQuote()); - this.bot.use(async (ctx, next) => { - ctx.database = this.database; - - await next(); - }); - - this.bot.use(async (ctx, next) => { - const user = ctx.from; - if (!user || user.is_bot || user.id == 777000) return await next(); - - const dbuser = await this.database.resolveUser(user!, true); - - if ( - user?.first_name !== dbuser?.first_name || - user?.last_name !== dbuser?.last_name || - user?.username !== dbuser?.username - ) { - await this.database.updateUser(user!, { - first_name: user?.first_name, - last_name: user?.last_name, - username: user?.username, - }); - } - - await next(); - }); - + this.bot.use(async (ctx, next) => autoCaching(ctx, this.database, next)); this.bot.use(dickComposer); this.bot.use(githubLinkComposer); this.bot.use(msdIncorporatedComposer); - this.bot.use(randomEmojiComposer); + this.bot.use(randomShitComposer); this.bot.use(telegraphComposer); - this.bot.command("eval", evalCommand); this.bot.command("exec", execCommand); this.bot.command("start", startCommand); - this.bot.on("::mention", ctx => { - if (ctx.message?.text == `@${this.bot.botInfo.username}`) return ctx.reply("Я тут!"); - }); - - this.bot.on(":new_chat_members", async ctx => { - if (ctx.chat.id !== -1001705068191) return; - ctx.replyWithAnimation(new InputFile(resolve(cwd(), "src", "media", "welcome.gif"))); - }); - this.bot.catch(console.error); + await this.bot.init(); await this.bot.start({ drop_pending_updates: true, onStart }); }; diff --git a/src/structures/database.ts b/src/structures/database.ts index c188761..27a3269 100644 --- a/src/structures/database.ts +++ b/src/structures/database.ts @@ -1,5 +1,5 @@ import { and, eq, type DBQueryConfig, type ExtractTablesWithRelations } from "drizzle-orm"; -import { drizzle, NodePgDatabase } from "drizzle-orm/node-postgres"; +import { drizzle, type NodePgDatabase } from "drizzle-orm/node-postgres"; import { Client } from "pg"; import type { User as TelegramUser } from "typegram"; import * as schema from "../drizzle/index";