Skip to content

Commit

Permalink
Merge pull request #24 from ryukaizen/dev
Browse files Browse the repository at this point in the history
README update
  • Loading branch information
ryukaizen authored Jul 29, 2024
2 parents e635530 + 8308e7b commit 6213768
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 6 deletions.
98 changes: 94 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,97 @@
![Lucyna Kushinada](https://github.com/user-attachments/assets/d3f8158f-9ebd-450d-8d7f-357e7d2ea718)

## To-do
- [ ] refactor everything since there's A LOT of repeated code
- [x] markdown parsing for notes, filters, rules, welcomes
<h1 align="center">A Telegram Chat Management Bot</h1>

<h3 align="center">Built using <a href="https://grammy.dev">grammY</a> & <a href="https://gram.js.org/">GramJS</a></h3>

<h2>Features</h2>
<p>This bot offers a variety of chat management features to help you keep your Telegram groups organized and secure. Below is a list of available modules:</p>

- **Admin**: Manage administrative tasks and settings.
- **AniList**: Integration with AniList to provide anime-related information.
- **Antiflood**: Prevent spam by limiting the number of messages a user can send in a short period.
- **Bans**: Ban users from the chat.
- **Blacklists**: Create and manage blacklists to automatically remove unwanted content.
- **Cleanservice**: Clean up service messages to keep the chat tidy.
- **Extras**: Additional features and utilities.
- **Filters**: Set up custom filters to automatically respond to specific messages.
- **Fun**: Fun commands to engage with chat members.
- **Greetings**: Send welcome messages to new members.
- **Locks**: Lock specific types of messages (e.g., media, links) to control chat content.
- **Mutes**: Mute users to prevent them from sending messages temporarily.
- **Notes**: Save and recall notes.
- **Purges**: Bulk delete messages.
- **Reports**: Report messages to administrators.
- **Rules**: Define and display chat rules.
- **Users**: Manage user settings and permissions.
- **Warns**: Warn users for rule violations.

<h2>Installation</h2>
<p>Follow these steps to install and set up the bot:</p>

1. **Clone the repository**:
```sh
git clone https://github.com/ryukaizen/lucyna.git
cd lucyna
```

2. **Install Node.js and npm**: Ensure you have Node.js and npm installed. You can download them from [here](https://nodejs.org/).

3. **Install TypeScript**:
```sh
npm install -g typescript
```

4. **Install dependencies**:
```sh
npm install
```

5. **Set up environment variables**:
```sh
cp .env.example .env
```

6. **Edit and fill up all the relevant environment variables inside the .env file**

6. **Add PostgreSQL URL, Telegram API ID, API Hash, and GramJS String Session to the .env file**:
Edit the `.env` file and add your PostgreSQL connection URL, Telegram API ID, API Hash, and GramJS String Session:
```env
DATABASE_URL=your-postgresql-connection-url
API_ID=your-telegram-api-id
API_HASH=your-telegram-api-hash
STRING_SESSION=your-gramjs-string-session
```
You can generate the GramJS string session using [telegramtools.com/string-session-generator](https://telegramtools.com/string-session-generator).

7. **Set up Prisma**:
```sh
npx prisma db push
```


8. **Start the bot using nodemon**:
```sh
npm start
```


## To-do & potential ideas
- [x] Markdown parsing for notes, filters, rules, welcomes
- [x] GramJS as utility
- [ ] command prefixes !, ?
- [ ] Pagination buttons for /notes so it wont cover entire screen
- [ ] Refactor everything since there's A LOT of repeated code
- [ ] Command prefixes !, ?
- [ ] Autodelete "Only admins can use this command" type of messages
- [ ] Hydration plugin (change every ctx and bot method)
- [ ] Make use of all invitelink methods given by Telegram API, make a separate module for it
- [ ] Pillow welcome where you fetch pfp of user and create a welcome card
- [ ] Custom bot token (bot instances)
- [ ] Moderator roles
- [ ] Presets for security, settings and etc.
- [ ] /shutup on | off command to make the bot shut up (owner only)
## Bottom Notes
Feel free to clone, contribute and raise issues. You can even reach out to me on [Telegram](https://telegram.me/please_help_me_im_dumb).
The project was rushed due to time constraints, so there might be some bugs and issues. Although, we're just getting started ;)
5 changes: 5 additions & 0 deletions src/database/users_sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ export async function get_user(id: bigint) {
return user;
};

export async function get_all_users() {
let users = await prisma.users.findMany();
return users;
}

export async function register_user(id: bigint, username: string) {
try {
let user = await prisma.users.upsert({
Expand Down
77 changes: 75 additions & 2 deletions src/modules/devtools.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Composer } from "grammy";
import { Composer, InlineKeyboard } from "grammy";
import { superusersOnly } from "../helpers/helper_func";
import { grammyErrorLog } from "../logger";
import { get_all_users } from "../database/users_sql";

const composer = new Composer();

Expand All @@ -22,4 +23,76 @@ composer.chatType(["supergroup", "group", "private"]).command("snipe", superuser
}
}));

export default composer;
const keyboard = new InlineKeyboard()
.text("Cancel Broadcast", "cancel_broadcast");

composer.command("broadcast", superusersOnly(async (ctx: any) => {
let RATE_LIMIT = 5; // messages per second
let STATUS_UPDATE_INTERVAL = 5000; // 5 seconds

let message = ctx.match;
if (!message) {
await ctx.reply("Please provide a message to broadcast.");
return;
}

let users = await get_all_users();
let success_count = 0;
let fail_count = 0;
let last_status_update = 0;

let status_message = await ctx.reply(
`Broadcasting to <code>${users.length}</code> users. This may take a while...`,
{ reply_markup: keyboard, parse_mode: "HTML" }
);

let update_status = async (force = false) => {
let now = Date.now();
if (force || now - last_status_update >= STATUS_UPDATE_INTERVAL) {
await ctx.api.editMessageText(
ctx.chat!.id,
status_message.message_id,
`Broadcasting: ${success_count + fail_count}/${users.length}\nSuccess: ${success_count}\nFailed: ${fail_count}`,
{ reply_markup: keyboard }
);
last_status_update = now;
}
};

let broadcast_queue = async () => {
let batch_size = Math.min(RATE_LIMIT, users.length);
let batch = users.splice(0, batch_size);
let batch_start = Date.now();

for (let user_id of batch) {
try {
await ctx.api.sendMessage(user_id, message);
success_count++;
} catch (error) {
console.error(`Failed to send message to user ${user_id}:`, error);
fail_count++;
}

await update_status();

let batch_duration = Date.now() - batch_start;
let delay_before_next_batch = Math.max(0, 1000 - batch_duration);

if (users.length > 0) {
setTimeout(broadcast_queue, delay_before_next_batch);
} else {
await update_status(true);
await ctx.api.editMessageText(
ctx.chat!.id,
status_message.message_id,
`Broadcast complete.\nSuccess: ${success_count}\nFailed: ${fail_count}`
);
}
};

broadcast_queue();
}
}));


export default composer;

0 comments on commit 6213768

Please sign in to comment.