Skip to content

Commit

Permalink
refactor: more elegant process.env handling
Browse files Browse the repository at this point in the history
  • Loading branch information
AnotiaWang committed Jan 18, 2024
1 parent 5e39d17 commit ac14883
Show file tree
Hide file tree
Showing 13 changed files with 101 additions and 72 deletions.
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ MAX_DOWNLOADING=3
DEFAULT_SERVICE=Catbox
DEFAULT_EXPR=72
CATBOX_TOKEN=
WEBHOOK_URL=
WEBHOOK_URL=
DOWNLOAD_DC_ID=5
DOWNLOAD_WORKERS=5
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<p align="center">A simple Node.js bot for uploading Telegram files to <a href="https://catbox.moe">Catbox</a> or <a href="https://litterbox.catbox.moe">Litterbox</a>.</p>

-------
---

## 特性

Expand Down Expand Up @@ -47,7 +47,7 @@ pnpm install && pnpm start

- `ADMIN_ID`: 机器人拥有者(你本人)的 ID。可从 [GetIDs Bot](https://t.me/getidsbot) 获取。

- `LOG_CHANNEL_ID`: 用于存放记录的频道 ID。*可留空,仅用于回溯确认文件是否违反 ToS*
- `LOG_CHANNEL_ID`: 用于存放记录的频道 ID。_可留空,仅用于回溯确认文件是否违反 ToS_

- `DEFAULT_LANG`: [ `zh_CN` / `en_US` ] 用户的默认语言。

Expand All @@ -61,6 +61,10 @@ pnpm install && pnpm start

- `WEBHOOK_URL`: [ 可选 ] Webhook 的 URL,若留空则默认使用 Polling。Express.js 监听端口可在代码中修改,需设置反代。

- `DONWLOAD_DC_ID`: [ 可选 ] 下载文件时使用的 [Telegram 数据中心](https://docs.pyrogram.org/faq/what-are-the-ip-addresses-of-telegram-data-centers)。代码中默认为 5,修改为您机器人所在的 DC 可提高下载速度。

- `DOWNLOAD_WORKERS`: [ 可选 ] 同时下载文件的分块数。代码中默认为 5,提高此项可提高下载速度,但可能会带来未知问题。

## Demo

👉👉 [Catbox Uploader Bot](https://t.me/CatboxUploaderBot) 👈👈
Expand All @@ -79,4 +83,4 @@ pnpm install && pnpm start
## 开源许可

MIT License
MIT License
14 changes: 9 additions & 5 deletions README_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

<p align="center">A simple Node.js bot for uploading Telegram files to <a href="https://catbox.moe">Catbox.moe</a> or <a href="https://litterbox.catbox.moe">Litterbox</a>.</p>

------------
---

## Features

- [x] Upload files (stickers, photos, audios, videos)
- [x] Upload files (stickers, photos, audios, videos)

- [x] Use Catbox (max 200 MB per file) and Litterbox (max 1 GB per file) as storage

Expand Down Expand Up @@ -45,7 +45,7 @@ pnpm install && pnpm start

- `ADMIN_ID`: Admin ID (Usually yours. Get it from [GetIDs Bot](https://t.me/getidsbot)).

- `LOG_CHANNEL_ID`: Channel to store logs. Can be left empty. *This is only needed to check if files violated the ToS*.
- `LOG_CHANNEL_ID`: Channel to store logs. Can be left empty. _This is only needed to check if files violated the ToS_.

- `DEFAULT_LANG`: [ `zh_CN` / `en_US` ] Default language for your users.

Expand All @@ -59,6 +59,10 @@ pnpm install && pnpm start

- `WEBHOOK_URL`: [ Optional ] Webhook URL. If not specified, bot will use polling as default. The port that express.js listens can be changed in the code. You may use a reverse proxy to make it work.

- `DOWNLOAD_DC_ID`: [ Optional ] [Telegram DC](https://docs.pyrogram.org/faq/what-are-the-ip-addresses-of-telegram-data-centers) ID for downloading files. The default value written in the code is `5`. Changing this to your bot's DC ID may improve the download speed.

- `DOWNLOAD_WORKERS`: [ Optional ] Number of parallel chunk downloads. The default value written in the code is `5`. Increasing this value may improve the download speed, but may cause unknown problems.

## Demo

👉👉 [Catbox Uploader Bot](https://t.me/CatboxUploaderBot) 👈👈
Expand All @@ -71,10 +75,10 @@ pnpm install && pnpm start

3. Edit the file, and add your translation, according to `zh_CN.json` (Chinese is my mother tongue, so the expressions may be more accurate. You can also choose other files as the source). All properties in `zh_CN.json` are required.

4. Commit and push your changes. Create a Pull Request.
4. Commit and push your changes. Create a Pull Request.

> You can also directly edit the files in Web IDE, and create Pull Request after modifying.
## License

MIT License
MIT License
16 changes: 5 additions & 11 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
import { TelegramClient, type Api } from 'telegram'
import { StringSession } from 'telegram/sessions/index.js'
import { existsSync, readFileSync, writeFileSync } from 'fs'
import {
handleMessage,
handleCallbackQuery,
launchBot,
loadBotData,
BOT_TOKEN,
API_ID,
API_HASH,
} from './src/handler/index.js'
import { LogLevel } from 'telegram/extensions/Logger.js'
import { CallbackQuery } from 'telegram/events/CallbackQuery.js'
import { NewMessage } from 'telegram/events/index.js'
import { log } from './src/handler/data.js'
import { launchBot, loadBotData, log } from './src/handler/data.js'
import { API_ID, API_HASH, BOT_TOKEN } from './src/env.js'
import { handleCallbackQuery } from './src/handler/callbackQuery.js'
import { handleMessage } from './src/handler/message.js'

const stringSession = new StringSession(
existsSync('./data/.session') ? readFileSync('./data/.session', 'utf-8') : '',
)

launchBot()
export const bot = new TelegramClient(stringSession, parseInt(API_ID), API_HASH, {
export const bot = new TelegramClient(stringSession, API_ID, API_HASH, {
connectionRetries: 5,
useWSS: false,
autoReconnect: true,
Expand Down
15 changes: 15 additions & 0 deletions src/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'dotenv/config'
import type { LitterboxExpiration } from './types/data.js'

export const DEFAULT_LANG = process.env.DEFAULT_LANG
export const DEFAULT_SERVICE = process.env.DEFAULT_SERVICE
export const DEFAULT_EXPR = parseInt(process.env.DEFAULT_EXPR) as LitterboxExpiration
export const ADMIN_ID = parseInt(process.env.ADMIN_ID)
export const MAX_DOWNLOADING = parseInt(process.env.MAX_DOWNLOADING)
export const BOT_TOKEN = process.env.BOT_TOKEN
export const API_ID = parseInt(process.env.API_ID)
export const API_HASH = process.env.API_HASH
export const LOG_CHANNEL_ID = parseInt(process.env.LOG_CHANNEL_ID)
export const CATBOX_TOKEN = process.env.CATBOX_TOKEN
export const DOWNLOAD_DC_ID = parseInt(process.env.DOWNLOAD_DC_ID) || 5
export const DOWNLOAD_WORKERS = parseInt(process.env.DOWNLOAD_WORKERS) || 5
3 changes: 2 additions & 1 deletion src/handler/callbackQuery.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import strings from '../strings.js'
import { chatData, initChatData, buttons, saveBotData } from './index.js'
import { bot } from '../../index.js'
import type { Api } from 'telegram'
import type { LitterboxExpiration, StorageService } from '../types/data.js'
import type { CallbackQueryEvent } from 'telegram/events/CallbackQuery.js'
import * as buttons from './buttons.js'
import { chatData, initChatData, saveBotData } from './data.js'

// Callback query handler
// I use callback queries in the format of: [callback function]_[argument]
Expand Down
6 changes: 4 additions & 2 deletions src/handler/command.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import strings from '../strings.js'
import { chatData, ADMIN_ID, buttons, saveBotData } from './index.js'
import * as buttons from './buttons.js'
import { bot, BOT_NAME } from '../../index.js'
import { Catbox } from 'node-catbox'
import { chatData, saveBotData } from './data.js'
import { ADMIN_ID } from '../env.js'
import type { Api } from 'telegram'

// Bot command handler
Expand All @@ -17,7 +19,7 @@ export async function handleCommand(msg: Api.Message) {
const arg = text.split(' ').slice(1).join(' ')
// Check if the command is valid
if (GeneralCommands.prototype.hasOwnProperty(command)) new GeneralCommands(msg)[command](arg)
else if (OwnerCommands.prototype.hasOwnProperty(command) && chat.toString() === ADMIN_ID)
else if (OwnerCommands.prototype.hasOwnProperty(command) && chat === ADMIN_ID)
new OwnerCommands(msg)[command](arg)
}

Expand Down
23 changes: 5 additions & 18 deletions src/handler/data.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,16 @@
import 'dotenv/config'
import { writeFileSync, readFileSync, existsSync, readdirSync, mkdirSync } from 'fs'
import { bot } from '../../index.js'
import strings from '../strings.js'
import type { LitterboxExpiration, UserData } from '../types/data.js'

export const {
DEFAULT_LANG,
DEFAULT_SERVICE,
DEFAULT_EXPR,
ADMIN_ID,
MAX_DOWNLOADING,
BOT_TOKEN,
API_ID,
API_HASH,
LOG_CHANNEL_ID,
CATBOX_TOKEN,
} = process.env
import { bot } from '../../index.js'
import { writeFileSync, readFileSync, existsSync, readdirSync, mkdirSync } from 'fs'
import { DEFAULT_LANG, DEFAULT_SERVICE, DEFAULT_EXPR, BOT_TOKEN, API_ID, API_HASH } from '../env.js'
import type { UserData } from '../types/data.js'

export let chatData: Record<string, UserData> = {}
export const chatDataTemplate = {
lang: DEFAULT_LANG,
downloading: 0,
total: 0,
service: DEFAULT_SERVICE,
lbe: parseInt(DEFAULT_EXPR) as LitterboxExpiration,
lbe: DEFAULT_EXPR,
banned: false,
token: '',
}
Expand Down
23 changes: 0 additions & 23 deletions src/handler/index.ts

This file was deleted.

8 changes: 5 additions & 3 deletions src/handler/message.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { chatData, handleCommand, initChatData, transfer } from './index.js'
import { bot } from '../../index.js'
import strings from '../strings.js'
import { bot } from '../../index.js'
import { handleCommand } from './command.js'
import { chatData, initChatData } from './data.js'
import { transfer } from './transfer.js'
import type { NewMessageEvent } from 'telegram/events'

// Message handler
Expand All @@ -10,7 +12,7 @@ export async function handleMessage(event: NewMessageEvent) {
if (msg.peerId.className !== 'PeerUser') return
const chatId = msg.peerId.userId.toString()
const lang = chatData[chatId].lang

// Check if the user has configured the bot
initChatData(chatId)
if (isCommand(msg.message)) await handleCommand(msg)
Expand Down
22 changes: 17 additions & 5 deletions src/handler/transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@ import * as fs from 'fs'
import strings from '../strings.js'
import mime from 'mime-types'
import bigInt from 'big-integer'
import { log } from './data.js'
import { chatData, log } from './data.js'
import { bot, BOT_NAME } from '../../index.js'
import { Catbox, Litterbox } from 'node-catbox'
import { MAX_DOWNLOADING, chatData, LOG_CHANNEL_ID, CATBOX_TOKEN, ADMIN_ID } from './index.js'
import {
MAX_DOWNLOADING,
ADMIN_ID,
CATBOX_TOKEN,
LOG_CHANNEL_ID,
DOWNLOAD_DC_ID,
DOWNLOAD_WORKERS,
} from '../env.js'
import type { Api } from 'telegram'

export async function transfer(msg: Api.Message) {
Expand All @@ -16,7 +23,7 @@ export async function transfer(msg: Api.Message) {

if (chatData[chat].banned)
return bot.sendMessage(chat, { message: strings[lang]['error_banned'] })
else if (chatData[chat].downloading >= +MAX_DOWNLOADING && chat.toString() !== ADMIN_ID)
else if (chatData[chat].downloading >= MAX_DOWNLOADING && chat !== ADMIN_ID)
return bot.sendMessage(chat, {
message: strings[lang]['flood_protection'].replace('{s}', MAX_DOWNLOADING),
})
Expand Down Expand Up @@ -96,10 +103,14 @@ export async function transfer(msg: Api.Message) {
let downloadedChunks = 0

while (downloadedChunks < totalChunks) {
let chunksToDownload = 5
if (!bot.connected) await bot.connect()

let chunksToDownload = DOWNLOAD_WORKERS

if (downloadedChunks + chunksToDownload > totalChunks) {
chunksToDownload = totalChunks - downloadedChunks
}
// Download the file in chunks
const chunks = await Promise.all(
Array.from({ length: chunksToDownload }, (_, i) => {
return bot
Expand All @@ -108,11 +119,12 @@ export async function transfer(msg: Api.Message) {
requestSize: chunkSize,
offset: bigInt(chunkSize * i + downloadedChunks * chunkSize),
limit: 1,
dcId: 5,
dcId: DOWNLOAD_DC_ID,
})
.collect()
}),
)
// Append the chunks to the file
chunks.forEach(chunk => {
fs.appendFileSync(filePath, chunk[0] as Buffer, { encoding: 'binary' })
downloadedBytes += (chunk[0] as Buffer).length
Expand Down
2 changes: 2 additions & 0 deletions src/types/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ declare namespace NodeJS {
API_HASH: string
LOG_CHANNEL_ID: string
CATBOX_TOKEN: string
DOWNLOAD_DC_ID: string
DOWNLOAD_WORKERS: string
}
}
27 changes: 27 additions & 0 deletions test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
async function fetchData(page: number) {
return new Promise(resolve => {
setTimeout(() => {
resolve(`Page: ${page}`)
}, 1000)
})
}

async function* asyncDataGenerator(pages: number) {
for (let i = 1; i <= pages; i++) {
yield await fetchData(i)
}
}

;(async () => {
const generator = asyncDataGenerator(4)
await new Promise(resolve => setTimeout(resolve, 2000))
console.log(await generator.next())
console.log(await generator.next())
console.log(await generator.next())
await generator.return()
console.log(await generator.next())
console.log(await generator.next())
// for await (const data of generator) {
// console.log(data)
// }
})()

0 comments on commit ac14883

Please sign in to comment.