Files
memes_bot/README.fa.md
T
goyban 0732f2c34b Record what may be shared, ahead of federation
The bot-side half of TODO #4. Nothing federates yet; this establishes
what would be eligible to, and proves the boundary before there is a
hub that could leak across it.

- Schema v5 adds visibility, defaulting to private. Upgrading an
  existing library therefore opts nothing into sharing, which a test
  on the legacy upgrade path pins down.
- list_syncable() is the only function that will ever feed a hub, and
  it requires both public and approved. Tests force rows into states
  set_visibility refuses, so the filter is what protects the boundary
  rather than the caller being careful.
- set_visibility refuses anything not approved: media still in the
  moderation queue cannot be marked shared.
- /share lists memes with their current state and asks before making
  one public, since un-sharing stops future copies but cannot recall
  those already taken. The wording describes what sharing will mean
  once a hub exists, because by then warning is too late.
- /list shows the same markers.

Vault posts have no path into the sync set at all; being in a separate
table is what guarantees it, and there is a test saying so.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 22:09:37 +00:00

130 lines
10 KiB
Markdown

# Memes Bot
ربات شخصی تلگرام برای ذخیره و جستجوی میم (عکس، گیف، ویدیو، صدا، موزیک، استیکر، فایل) با کلیدواژه.
[English](README.md)
---
### پیش‌نیازها
- یک سرور با [Docker](https://docs.docker.com/engine/install/) نصب‌شده
- توکن ربات تلگرام از [@BotFather](https://t.me/BotFather)
### راه‌اندازی
**۱. ساخت ربات در BotFather**
- `/newbot` ← توکن بگیرید
- `/setinline` ← حالت اینلاین را فعال کنید (مثلاً: `جستجوی میم...`)
**۲. پیدا کردن شناسه تلگرام**
برای وایت‌لیست کردن خودتان به ID عددی نیاز دارید.
- **ساده‌ترین روش:** یک پیام به [@userinfobot](https://t.me/userinfobot) فوروارد کنید — شناسه شما را برمی‌گرداند
- **روش دیگر:** تلگرام وب را باز کنید، روی پروفایل کلیک کنید، عدد داخل URL شناسه شماست
- **برای چند کاربر:** ID هر نفر را با کاما جدا کنید
**۳. کلون و تنظیم**
```bash
git clone https://git.goyban.com/goyban/memes_bot
cd memes_bot
cp .env.example .env
```
فایل `.env` را ویرایش کنید:
```env
BOT_TOKEN=توکن_ربات_شما
ALLOWED_USERS=123456789,987654321
```
**۴. اجرا**
```bash
docker compose up -d --build
```
دیتابیس در مسیر `./bot_db/media.db` ذخیره می‌شود.
### نحوه استفاده
**افزودن میم** — یک عکس، گیف، ویدیو، صدا، موزیک، استیکر یا هر فایلی برای ربات بفرستید. ربات از شما کلیدواژه می‌خواهد. کلیدواژه‌ها را یکی‌یکی یا با کاما جدا بفرستید، سپس `/done` بزنید.
**جستجوی اینلاین** — در هر چتی بنویسید `@نام_ربات کلیدواژه` تا نتایج نمایش داده شود.
**دستورات**
| دستور | توضیح |
|---|---|
| `/list` | نمایش همه رسانه‌های ذخیره‌شده |
| `/vault [search]` | بازیابی پستی که کامل ذخیره کرده‌اید |
| `/review` | بررسی یک‌به‌یک ارسال‌های در انتظار تأیید (فقط ادمین) |
| `/share [search]` | مشخص‌کردن اینکه یک میم به اشتراک گذاشته شود یا خصوصی بماند (فقط ادمین) |
| `/delete <id>` | حذف یک مورد (ID را از `/list` بگیرید) |
| `/cancel` | لغو عملیات جاری |
### گاوصندوق — ذخیره کامل یک پست
اگر رسانه‌ای را مستقیم برای ربات بفرستید، مثل همیشه رفتار می‌کند: رسانه را جدا می‌کند و کلیدواژه می‌خواهد.
اما اگر پستی را **فوروارد** کنید، ربات می‌پرسد چه می‌خواهید:
- **ذخیره کل پست** — پست را دست‌نخورده با کپشن در گاوصندوق نگه می‌دارد. آلبوم هم آلبوم می‌ماند.
- **جدا کردن رسانه** — همان رفتار قبلی؛ رسانه به کتابخانه قابل جستجو اضافه می‌شود.
با `/vault [search]` پست‌های ذخیره‌شده را پیدا کنید؛ جستجو هم روی کلیدواژه‌ها و هم روی متن کپشن اصلی انجام می‌شود. کنار هر نتیجه یک دکمه برای فرستادن دوباره پست و یک دکمه برای حذف آن هست.
> **پست‌های گاوصندوق فقط داخل خود ربات برمی‌گردند.** حالت inline تلگرام نمی‌تواند پیام موجود را فوروارد کند، پس `@yourbotusername keyword` به گاوصندوق دسترسی ندارد. پست را داخل ربات بگیرید و بعد هرجا خواستید فوروارد کنید.
گاوصندوق برای هر کاربر جداگانه و خصوصی است: در جدولی جدا از کتابخانه میم‌ها ذخیره می‌شود، هر جستجو محدود به صاحب آن است، و هیچ‌چیزِ آن بررسی یا به اشتراک گذاشته نمی‌شود.
ذخیره‌سازی به‌جای کپی رسانه، اشاره‌ای به پیام موجود در چت شما با ربات را نگه می‌دارد. اگر تاریخچه چتتان با ربات را پاک کنید، آن پست‌ها دیگر قابل بازیابی نیستند — ربات در این حالت به شما اطلاع می‌دهد تا دوباره فوروارد کنید.
### عمومی‌کردن ربات
با تنظیم `PUBLIC_MODE=true` ربات به‌جای فهرست `ALLOWED_USERS`، به هر کسی که شرط عضویت را داشته باشد اجازه دسترسی می‌دهد:
```env
PUBLIC_MODE=true
ADMIN_USERS=123456789
REQUIRED_CHATS=@mychannel,@mygroup
REQUIRE_MODE=all
```
در `REQUIRED_CHATS` می‌توانید `@username` یا شناسه عددی بنویسید. **ربات باید در هر کدام ادمین باشد**، وگرنه نمی‌تواند عضویت را بررسی کند و همه رد می‌شوند. ربات هنگام راه‌اندازی این را بررسی می‌کند و نام هر چتی را که نمی‌تواند بخواند در لاگ می‌نویسد. مقدار `all` یعنی عضویت در همه چت‌ها لازم است و `any` یعنی یکی کافی است. اگر `REQUIRED_CHATS` خالی باشد ربات برای همه باز است.
کاربری که شرط را ندارد پیامی می‌بیند که فهرست چت‌های لازم را نشان می‌دهد. در جستجوی inline هم به‌جای نتیجه خالی و بدون توضیح، یک نوار قابل لمس می‌بیند که ربات را باز می‌کند و همین توضیح را می‌دهد.
> **قبل از روشن‌کردن این گزینه حتماً `ADMIN_USERS` را تنظیم کنید.** وقتی `ADMIN_USERS` خالی باشد، ربات خصوصی کاربرانش را ادمین حساب می‌کند؛ این برای ربات تک‌نفره راحت است اما در حالت عمومی یعنی همه ادمین می‌شوند. به همین دلیل در حالت عمومی تا وقتی `ADMIN_USERS` تنظیم نشده باشد هیچ‌کس ادمین نیست و ربات هنگام راه‌اندازی خطا ثبت می‌کند.
پاسخ بررسی عضویت پنج دقیقه کش می‌شود، چون جستجوی inline در غیر این صورت با هر بار فشردن کلید از تلگرام سؤال می‌کرد. رد شدن فقط سی ثانیه کش می‌شود تا کاربری که تازه عضو شده تقریباً بلافاصله دسترسی پیدا کند.
### پذیرش ارسال کاربران
اگر در فایل `.env` مقدار `ACCEPT_SUBMISSIONS=true` را تنظیم کنید، کاربران غیرادمین هم می‌توانند رسانه بفرستند. این موارد ذخیره می‌شوند اما تا وقتی یک ناظر تأییدشان نکند در جستجوی inline و `/list` دیده نمی‌شوند. رسانه‌ای که خود ادمین‌ها می‌فرستند مثل قبل مستقیم ذخیره می‌شود.
با دستور `/review` می‌توانید صف را بررسی کنید. هر مورد همراه با کلیدواژه‌هایش و چهار دکمه نمایش داده می‌شود: تأیید، رد، اصلاح کلیدواژه‌ها، و توقف.
صف هیچ نشانگری ذخیره نمی‌کند و `/review` همیشه قدیمی‌ترین مورد در انتظار را می‌آورد. برای همین می‌توانید بعد از چند مورد متوقف شوید و فردا ادامه دهید، و چند ناظر هم می‌توانند هم‌زمان کار کنند — اگر دو نفر یک مورد را باز کنند، تصمیم اولی ثبت می‌شود و به دومی گفته می‌شود که قبلاً بررسی شده است.
> **تا وقتی مطمئن نیستید این گزینه را خاموش بگذارید.** وقتی `ALLOWED_USERS` خالی باشد همه کاربرِ مجاز حساب می‌شوند، پس روشن‌کردن این گزینه یعنی پذیرفتن رسانه از هر کسی که ربات را پیدا کند.
### اشتراک‌گذاری (مقدمات)
هر میم به‌صورت پیش‌فرض **خصوصی** است. با `/share [search]` فهرست میم‌ها را با نشان 🔒 یا 🌐 می‌بینید و می‌توانید وضعیت هرکدام را عوض کنید. در `/list` هم همین نشان‌ها دیده می‌شود.
> **هنوز هیچ‌چیزی به اشتراک گذاشته نمی‌شود.** این فقط خواستهٔ شما را ثبت می‌کند. فدراسیون — جایی که ربات‌هایی که جدا اجرا می‌شوند میم‌های عمومی‌شان را روی هم می‌گذارند — هنوز ساخته نشده و تا آن‌موقع هیچ میمی از این ربات بیرون نمی‌رود. متن تأیید، معنای اشتراک‌گذاری را در آینده توضیح می‌دهد، چون بعد از راه‌افتادن هاب دیگر برای هشدار دادن دیر است.
دو قاعده در همان تک‌کوئری‌ای که قرار است به هاب داده شود اعمال می‌شود: فقط رسانه‌ای که هم **تأییدشده** و هم **عمومی** باشد واجد شرایط است. رسانه‌ای که هنوز در انتظار بررسی است اصلاً قابل اشتراک‌گذاری نیست، و پست‌های گاوصندوق در جدولی جدا هستند و هیچ مسیری به آنجا ندارند.
خصوصی‌کردن دوباره، جلوی کپی‌های بعدی را می‌گیرد اما کپی‌هایی که قبلاً گرفته شده را برنمی‌گرداند؛ به همین دلیل قبل از عمومی‌کردن تأیید گرفته می‌شود، نه بعد از آن.
### انتقال به سرور دیگر
فقط کافی است این دو فایل را منتقل کنید:
- `.env`
- `bot_db/media.db`