Fixes
This commit is contained in:
parent
06f395d6ec
commit
c7e82c8212
@ -1,10 +1,11 @@
|
|||||||
FROM denoland/deno:2.0.2
|
FROM denoland/deno:1.46.3
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN deno cache ./main.ts --allow-import
|
RUN deno cache ./main.ts
|
||||||
|
# RUN deno cache ./main.ts --allow-import
|
||||||
RUN mkdir bin
|
RUN mkdir bin
|
||||||
|
|
||||||
# Not working
|
# Not working
|
||||||
|
@ -13,7 +13,6 @@ class BotUnknownOnStartErr extends Err {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const runBot = async (cfg: config.BotConfig, initMode: (bot: Bot<Ctx>) => void) => {
|
export const runBot = async (cfg: config.BotConfig, initMode: (bot: Bot<Ctx>) => void) => {
|
||||||
// Bot initialization & setup
|
|
||||||
const bot = new Bot<Ctx>(cfg.bot_token)
|
const bot = new Bot<Ctx>(cfg.bot_token)
|
||||||
bot.use(session({ initial: defaultSessionData }))
|
bot.use(session({ initial: defaultSessionData }))
|
||||||
bot.catch((err: BotError<Context>) => {
|
bot.catch((err: BotError<Context>) => {
|
||||||
@ -22,8 +21,9 @@ export const runBot = async (cfg: config.BotConfig, initMode: (bot: Bot<Ctx>) =>
|
|||||||
})
|
})
|
||||||
|
|
||||||
initMode(bot)
|
initMode(bot)
|
||||||
|
await bot.init()
|
||||||
|
|
||||||
console.log("Starting bot")
|
console.log(`starting bot ${bot.botInfo.username}`)
|
||||||
await bot.start().catch(err => {
|
await bot.start().catch(err => {
|
||||||
throw new BotUnknownOnStartErr("Unknown error while starting the bot",
|
throw new BotUnknownOnStartErr("Unknown error while starting the bot",
|
||||||
{ cause: err })
|
{ cause: err })
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Filter } from "https://deno.land/x/grammy@v1.30.0/mod.ts";
|
import { Filter } from "https://deno.land/x/grammy@v1.30.0/mod.ts";
|
||||||
import { BotConfig } from "../../cfg/bot.ts"
|
import { BotConfig } from "../../cfg/config.ts";
|
||||||
import { Ctx } from "../ctx.ts";
|
import { Ctx } from "../ctx.ts";
|
||||||
import { LangManager } from "../lang/export.ts";
|
import { LangManager } from "../lang/export.ts";
|
||||||
import { Kysely } from "npm:kysely";
|
import { Kysely } from 'npm:kysely';
|
||||||
import { Database } from "../../repo/exports.ts";
|
import { Database } from "../../repo/exports.ts";
|
||||||
import { checkUserRestrictions, getActiveInviteLink } from "../../core/users.ts";
|
import { checkUserRestrictions, getActiveInviteLink } from "../../core/users.ts";
|
||||||
import { CheckUserOut } from "./user_managment.ts";
|
import { CheckUserOut } from "./user_managment.ts";
|
||||||
@ -128,6 +128,7 @@ const checkCaptchaSolution = async (ctx: Filter<Ctx, "message:text">, db: Kysely
|
|||||||
ctx.reply(LangManager.getLang(ctx.msg.from.language_code)
|
ctx.reply(LangManager.getLang(ctx.msg.from.language_code)
|
||||||
.replies.captcha.failed(TIMEOUT_AFTER_FAIL_MINS))
|
.replies.captcha.failed(TIMEOUT_AFTER_FAIL_MINS))
|
||||||
ctx.api.deleteMessage(ctx.chatId, ctx.session.captcha_data!.message_id).catch()
|
ctx.api.deleteMessage(ctx.chatId, ctx.session.captcha_data!.message_id).catch()
|
||||||
|
// TODO: Add timeout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Bot } from "https://deno.land/x/grammy/mod.ts";
|
import { Bot } from "https://deno.land/x/grammy/mod.ts";
|
||||||
import { Kysely } from "npm:kysely";
|
import { Kysely } from 'npm:kysely';
|
||||||
import { Ctx } from "../ctx.ts";
|
import { Ctx } from "../ctx.ts";
|
||||||
import { CompiledConfig } from "../../cfg/config.ts";
|
import { CompiledConfig } from "../../cfg/config.ts";
|
||||||
import { Database } from "../../repo/exports.ts";
|
import { Database } from "../../repo/exports.ts";
|
||||||
@ -9,6 +9,7 @@ import { checkUserOnStart } from "./user_managment.ts";
|
|||||||
|
|
||||||
|
|
||||||
export const init = (bot: Bot<Ctx>, db: Kysely<Database>, cfg: CompiledConfig) => {
|
export const init = (bot: Bot<Ctx>, db: Kysely<Database>, cfg: CompiledConfig) => {
|
||||||
|
console.log(`initializing normal mode`)
|
||||||
const { botCfg } = cfg
|
const { botCfg } = cfg
|
||||||
|
|
||||||
bot.on('message', ctx => {
|
bot.on('message', ctx => {
|
||||||
@ -26,13 +27,14 @@ export const init = (bot: Bot<Ctx>, db: Kysely<Database>, cfg: CompiledConfig) =
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
bot.on('message:text', ctx => {
|
bot.on('message:text', async ctx => {
|
||||||
|
console.log(`From: ${ctx.from.id} Message: ${ctx.msg.text}`)
|
||||||
if (ctx.from.is_bot || ctx.hasCommand('start')) return
|
if (ctx.from.is_bot || ctx.hasCommand('start')) return
|
||||||
|
|
||||||
if (ctx.chat.id === botCfg.chat_id) {
|
if (ctx.chat.id === botCfg.chat_id) {
|
||||||
checkUser(ctx, db, botCfg, true)
|
await checkUser(ctx, db, botCfg, true)
|
||||||
} else if (ctx.message.chat.type == "private" && ctx.session.captcha_data) {
|
} else if (ctx.message.chat.type == "private" && ctx.session.captcha_data) {
|
||||||
checkCaptchaSolution(ctx, db, botCfg)
|
await checkCaptchaSolution(ctx, db, botCfg)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -41,6 +43,8 @@ export const init = (bot: Bot<Ctx>, db: Kysely<Database>, cfg: CompiledConfig) =
|
|||||||
if (!ctx.from || ctx.from.is_bot) return
|
if (!ctx.from || ctx.from.is_bot) return
|
||||||
if (ctx.chat.type !== 'private') return
|
if (ctx.chat.type !== 'private') return
|
||||||
|
|
||||||
|
console.log(`Start called by ${ctx.from.id}`)
|
||||||
|
|
||||||
const userInfo = await checkUserOnStart(ctx, db)
|
const userInfo = await checkUserOnStart(ctx, db)
|
||||||
if (userInfo.isBlocked || userInfo.isTimeout) return
|
if (userInfo.isBlocked || userInfo.isTimeout) return
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { CommandContext, Filter } from "https://deno.land/x/grammy/mod.ts";
|
import { CommandContext, Filter } from "https://deno.land/x/grammy/mod.ts";
|
||||||
import { Kysely, Transaction } from "npm:kysely";
|
import { Kysely, Transaction } from 'npm:kysely';
|
||||||
import { Ctx } from "../ctx.ts";
|
import { Ctx } from "../ctx.ts";
|
||||||
import { Database } from "../../repo/exports.ts";
|
import { Database } from "../../repo/exports.ts";
|
||||||
import { checkUserRestrictions } from "../../core/users.ts";
|
import { checkUserRestrictions } from "../../core/users.ts";
|
||||||
import { UserCheckedRestrictions } from "../../core/entities.ts";
|
import { UserCheckedRestrictions } from "../../core/entities.ts";
|
||||||
import { BotConfig } from "../../cfg/bot.ts";
|
import { BotConfig } from "../../cfg/config.ts";
|
||||||
|
|
||||||
|
|
||||||
export interface CheckUserOut extends UserCheckedRestrictions {
|
export interface CheckUserOut extends UserCheckedRestrictions {
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
export enum BotMode{ setup, normal }
|
|
||||||
export type BotConfig = {
|
|
||||||
mode: BotMode,
|
|
||||||
bot_token: string,
|
|
||||||
chat_id: number,
|
|
||||||
admin_ids: number[],
|
|
||||||
}
|
|
@ -1,16 +1,23 @@
|
|||||||
import type { PoolConfig } from "npm:@types/pg";
|
import type * as pg from "npm:pg";
|
||||||
import { strToBool } from "../utils/convert.ts";
|
import { strToBool } from "../utils/convert.ts";
|
||||||
import { BadConfigErr } from "../utils/errors.ts";
|
import { BadConfigErr } from "../utils/errors.ts";
|
||||||
import { readJsonFileSync } from "../utils/io.ts";
|
import { readJsonFileSync } from "../utils/io.ts";
|
||||||
import { BotConfig } from "./bot.ts";
|
import * as path from "jsr:@std/path";
|
||||||
|
|
||||||
export const POSTGRES_PASSWORD = "POSTGRES_PASSWORD"
|
export const POSTGRES_PASSWORD = "POSTGRES_PASSWORD"
|
||||||
export const MIC_APPLY_MIGRATIONS = "MIC_APPLY_MIGRATIONS"
|
export const MIC_APPLY_MIGRATIONS = "MIC_APPLY_MIGRATIONS"
|
||||||
export const DEFAULT_CONFIG_FILE_PATH = "DEFAULT_CONFIG_FILE_PATH"
|
export const DEFAULT_CONFIG_FILE_PATH = import.meta.dirname ? path.join(import.meta.dirname, '../config.json') : '/app/config.json'
|
||||||
export const MIC_DROP_DB = "MIC_DROP_DB"
|
export const MIC_DROP_DB = "MIC_DROP_DB"
|
||||||
export const BOT_TOKEN = "BOT_TOKEN"
|
export const BOT_TOKEN = "BOT_TOKEN"
|
||||||
export const MIC_CONFIG_PATH = "MIC_CONFIG_PATH"
|
export const MIC_CONFIG_PATH = "MIC_CONFIG_PATH"
|
||||||
|
|
||||||
|
export enum BotMode{ setup, normal }
|
||||||
|
export type BotConfig = {
|
||||||
|
mode: BotMode,
|
||||||
|
bot_token: string,
|
||||||
|
chat_id: number,
|
||||||
|
admin_ids: number[],
|
||||||
|
}
|
||||||
|
|
||||||
export interface EnvConfig {
|
export interface EnvConfig {
|
||||||
db_password?: string,
|
db_password?: string,
|
||||||
@ -50,7 +57,7 @@ export interface MigrationConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface CompiledConfig {
|
export interface CompiledConfig {
|
||||||
pgPoolCfg: PoolConfig
|
pgPoolCfg: pg.PoolConfig
|
||||||
botCfg: BotConfig
|
botCfg: BotConfig
|
||||||
migrationCfg?: MigrationConfig
|
migrationCfg?: MigrationConfig
|
||||||
}
|
}
|
||||||
@ -81,7 +88,7 @@ export const getConfig = (): Config => {
|
|||||||
if (fileCfg.db_password_file) {
|
if (fileCfg.db_password_file) {
|
||||||
const decoder = new TextDecoder("utf-8")
|
const decoder = new TextDecoder("utf-8")
|
||||||
const data = Deno.readFileSync(fileCfg.db_password_file)
|
const data = Deno.readFileSync(fileCfg.db_password_file)
|
||||||
db_password = decoder.decode(data).toString().slice(0, -1)
|
db_password = decoder.decode(data).toString()
|
||||||
} else if (envCfg.db_password) {
|
} else if (envCfg.db_password) {
|
||||||
db_password = envCfg.db_password
|
db_password = envCfg.db_password
|
||||||
} else throw new BadConfigErr(
|
} else throw new BadConfigErr(
|
||||||
@ -113,5 +120,3 @@ export const getConfig = (): Config => {
|
|||||||
bot_token,
|
bot_token,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export * from "./bot.ts"
|
|
@ -1,7 +1,6 @@
|
|||||||
import type { PoolConfig } from "npm:@types/pg";
|
import type { PoolConfig } from "npm:@types/pg";
|
||||||
import { getConfig } from "./cfg/config.ts";
|
import { BotMode, getConfig } from "./cfg/config.ts";
|
||||||
import type { BotConfig, CompiledConfig } from "./cfg/config.ts";
|
import type { BotConfig, CompiledConfig } from "./cfg/config.ts";
|
||||||
import { BotMode } from "./cfg/bot.ts";
|
|
||||||
import * as path from "jsr:@std/path";
|
import * as path from "jsr:@std/path";
|
||||||
|
|
||||||
const MIC_CHAT_ID = -1002438254268
|
const MIC_CHAT_ID = -1002438254268
|
||||||
@ -16,7 +15,7 @@ export const DEFAULT_DB_TLS = false
|
|||||||
export const loadConfig = (): CompiledConfig => {
|
export const loadConfig = (): CompiledConfig => {
|
||||||
const cfg = getConfig()
|
const cfg = getConfig()
|
||||||
const pgPoolCfg: PoolConfig = {
|
const pgPoolCfg: PoolConfig = {
|
||||||
host: cfg.db_name || DEFAULT_DB_HOST,
|
host: cfg.db_host || DEFAULT_DB_HOST,
|
||||||
user: cfg.db_user || DEFAULT_DB_USER,
|
user: cfg.db_user || DEFAULT_DB_USER,
|
||||||
database: cfg.db_name || DEFAULT_DB_NAME,
|
database: cfg.db_name || DEFAULT_DB_NAME,
|
||||||
port: cfg.db_port || DEFAULT_DB_PORT,
|
port: cfg.db_port || DEFAULT_DB_PORT,
|
||||||
@ -36,7 +35,8 @@ export const loadConfig = (): CompiledConfig => {
|
|||||||
migrationCfg: {
|
migrationCfg: {
|
||||||
dropDb: cfg.drop_db,
|
dropDb: cfg.drop_db,
|
||||||
applyMigrations: cfg.apply_migrations,
|
applyMigrations: cfg.apply_migrations,
|
||||||
migrationsPath: path.join(__dirname, "migrations"),
|
migrationsPath: import.meta.dirname ?
|
||||||
|
path.join(import.meta.dirname, 'migrations') : '/app/migrations',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { Kysely, Transaction } from "npm:kysely";
|
import { Kysely, Transaction } from 'npm:kysely';
|
||||||
import { Database } from "../repo/exports.ts";
|
import { Database } from "../repo/exports.ts";
|
||||||
import { UserCheckedRestrictions, UserRestrictionsInfo } from "./entities.ts";
|
import { UserCheckedRestrictions, UserRestrictionsInfo } from "./entities.ts";
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@
|
|||||||
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/expression/expression-builder.js": "da9c44985b130c4d9ebd2dabff36b66e748e5afa8a785313e0d9318967ef24d7",
|
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/expression/expression-builder.js": "da9c44985b130c4d9ebd2dabff36b66e748e5afa8a785313e0d9318967ef24d7",
|
||||||
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/expression/expression-wrapper.js": "35742f42558a1cbb369ecf7b3cb863f4486fa0c2384fb23e278244440f3c12c9",
|
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/expression/expression-wrapper.js": "35742f42558a1cbb369ecf7b3cb863f4486fa0c2384fb23e278244440f3c12c9",
|
||||||
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/expression/expression.js": "7c024b0c9f292bbd0aefe486c81328d7b18ece24cb569afc3171e06035f4f970",
|
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/expression/expression.js": "7c024b0c9f292bbd0aefe486c81328d7b18ece24cb569afc3171e06035f4f970",
|
||||||
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/index.js": "ba2b09d8e5e4ae121ef77cfd971477858381650c26bcf28dfd3a8e5ed0535e8a",
|
"npm:kysely": "ba2b09d8e5e4ae121ef77cfd971477858381650c26bcf28dfd3a8e5ed0535e8a",
|
||||||
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/kysely.js": "d6b10df0da4bb8d853d1ff946b8a1a5e4c254c7a2e26d3a5ecacce82c9e3c7eb",
|
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/kysely.js": "d6b10df0da4bb8d853d1ff946b8a1a5e4c254c7a2e26d3a5ecacce82c9e3c7eb",
|
||||||
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/migration/file-migration-provider.js": "04be6f4d0bb587f254b270875b529bbf30bbdf19af2d95b06272cd5e6b01e56e",
|
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/migration/file-migration-provider.js": "04be6f4d0bb587f254b270875b529bbf30bbdf19af2d95b06272cd5e6b01e56e",
|
||||||
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/migration/migrator.js": "35c171e46ae9d18b9b9459148f626be5bc88f22ee5f7844b9b6818dd53ecb77a",
|
"https://cdn.jsdelivr.net/npm/kysely/dist/esm/migration/migrator.js": "35c171e46ae9d18b9b9459148f626be5bc88f22ee5f7844b9b6818dd53ecb77a",
|
||||||
|
@ -13,6 +13,8 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgres
|
- postgres
|
||||||
|
environment:
|
||||||
|
- MIC_APPLY_MIGRATIONS=y
|
||||||
networks:
|
networks:
|
||||||
- mic_bot
|
- mic_bot
|
||||||
secrets:
|
secrets:
|
||||||
|
4
main.ts
4
main.ts
@ -3,14 +3,14 @@ import { init as initNormalMode } from "./bot/normal_mode/init.ts"
|
|||||||
import { init as initSetupMode } from "./bot/setup_mode/init.ts"
|
import { init as initSetupMode } from "./bot/setup_mode/init.ts"
|
||||||
import { setupDB } from "./repo/exports.ts";
|
import { setupDB } from "./repo/exports.ts";
|
||||||
import { loadConfig } from "./config.ts";
|
import { loadConfig } from "./config.ts";
|
||||||
import { BotMode } from "./cfg/bot.ts";
|
import { BotMode } from "./cfg/config.ts";
|
||||||
|
|
||||||
const main = async () => {
|
const main = async () => {
|
||||||
const cfg = loadConfig()
|
const cfg = loadConfig()
|
||||||
const { botCfg } = cfg
|
const { botCfg } = cfg
|
||||||
const { db } = await setupDB(cfg)
|
const { db } = await setupDB(cfg)
|
||||||
|
|
||||||
runBot(botCfg, (bot) => {
|
await runBot(botCfg, (bot) => {
|
||||||
switch (botCfg.mode) {
|
switch (botCfg.mode) {
|
||||||
case BotMode.normal:
|
case BotMode.normal:
|
||||||
initNormalMode(bot, db, cfg)
|
initNormalMode(bot, db, cfg)
|
||||||
|
@ -3,37 +3,61 @@ import {
|
|||||||
Migrator,
|
Migrator,
|
||||||
PostgresDialect,
|
PostgresDialect,
|
||||||
FileMigrationProvider
|
FileMigrationProvider
|
||||||
} from 'https://cdn.jsdelivr.net/npm/kysely/dist/esm/index.js'
|
} from 'npm:kysely'
|
||||||
|
|
||||||
/// <reference types="npm:@types/pg" />
|
/// <reference types="npm:@types/pg" />
|
||||||
// @deno-types="npm:@types/pg"
|
import pg from "npm:pg";
|
||||||
import { Pool } from "npm:pg";
|
|
||||||
import { Database } from "./scheme.ts"
|
import { Database } from "./scheme.ts"
|
||||||
import { CompiledConfig } from "../cfg/config.ts";
|
import { CompiledConfig } from "../cfg/config.ts";
|
||||||
import { promises as fs } from 'node:fs'
|
|
||||||
import * as path from 'node:path'
|
|
||||||
|
|
||||||
|
|
||||||
export type SetupDbOutput = {
|
export type SetupDbOutput = {
|
||||||
pool: Pool,
|
pool: pg.Pool,
|
||||||
db: Kysely<Database>,
|
db: Kysely<Database>,
|
||||||
}
|
}
|
||||||
export const setupDB = async (cfg: CompiledConfig): Promise<SetupDbOutput> => {
|
export const setupDB = async (cfg: CompiledConfig): Promise<SetupDbOutput> => {
|
||||||
const pool = new Pool(cfg.pgPoolCfg)
|
console.log("creating db instance")
|
||||||
|
const pool = new pg.Pool(cfg.pgPoolCfg)
|
||||||
const dialect = new PostgresDialect({ pool })
|
const dialect = new PostgresDialect({ pool })
|
||||||
const db = new Kysely<Database>({ dialect })
|
const db = new Kysely<Database>({ dialect })
|
||||||
|
|
||||||
if (cfg.migrationCfg && cfg.migrationCfg.applyMigrations) {
|
if (cfg.migrationCfg?.applyMigrations) {
|
||||||
|
console.log("applying db migrations", cfg.migrationCfg.migrationsPath)
|
||||||
const migrator = new Migrator({
|
const migrator = new Migrator({
|
||||||
db,
|
db,
|
||||||
provider: new FileMigrationProvider({
|
provider: new FileMigrationProvider({
|
||||||
fs,
|
fs: {
|
||||||
path,
|
readdir(path) {
|
||||||
|
return Promise.resolve(
|
||||||
|
[...Deno.readDirSync(path)].map((file) => file.name)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
path: {
|
||||||
|
join(...path) {
|
||||||
|
return path.join('/')
|
||||||
|
},
|
||||||
|
},
|
||||||
migrationFolder: cfg.migrationCfg.migrationsPath,
|
migrationFolder: cfg.migrationCfg.migrationsPath,
|
||||||
}),
|
}),
|
||||||
allowUnorderedMigrations: true
|
allowUnorderedMigrations: true
|
||||||
})
|
})
|
||||||
await migrator.migrateToLatest()
|
|
||||||
|
const { error, results } = await migrator.migrateToLatest()
|
||||||
|
|
||||||
|
results?.forEach((it) => {
|
||||||
|
if (it.status === 'Success') {
|
||||||
|
console.log(`migration "${it.migrationName}" was executed successfully`)
|
||||||
|
} else if (it.status === 'Error') {
|
||||||
|
console.error(`failed to execute migration "${it.migrationName}"`)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
console.error('failed to migrate')
|
||||||
|
console.error(error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return { pool, db }
|
return { pool, db }
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user