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>
10 KiB
Memes Bot
ربات شخصی تلگرام برای ذخیره و جستجوی میم (عکس، گیف، ویدیو، صدا، موزیک، استیکر، فایل) با کلیدواژه.
پیشنیازها
- یک سرور با Docker نصبشده
- توکن ربات تلگرام از @BotFather
راهاندازی
۱. ساخت ربات در BotFather
/newbot← توکن بگیرید/setinline← حالت اینلاین را فعال کنید (مثلاً:جستجوی میم...)
۲. پیدا کردن شناسه تلگرام
برای وایتلیست کردن خودتان به ID عددی نیاز دارید.
- سادهترین روش: یک پیام به @userinfobot فوروارد کنید — شناسه شما را برمیگرداند
- روش دیگر: تلگرام وب را باز کنید، روی پروفایل کلیک کنید، عدد داخل URL شناسه شماست
- برای چند کاربر: ID هر نفر را با کاما جدا کنید
۳. کلون و تنظیم
git clone https://git.goyban.com/goyban/memes_bot
cd memes_bot
cp .env.example .env
فایل .env را ویرایش کنید:
BOT_TOKEN=توکن_ربات_شما
ALLOWED_USERS=123456789,987654321
۴. اجرا
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، به هر کسی که شرط عضویت را داشته باشد اجازه دسترسی میدهد:
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 هم همین نشانها دیده میشود.
هنوز هیچچیزی به اشتراک گذاشته نمیشود. این فقط خواستهٔ شما را ثبت میکند. فدراسیون — جایی که رباتهایی که جدا اجرا میشوند میمهای عمومیشان را روی هم میگذارند — هنوز ساخته نشده و تا آنموقع هیچ میمی از این ربات بیرون نمیرود. متن تأیید، معنای اشتراکگذاری را در آینده توضیح میدهد، چون بعد از راهافتادن هاب دیگر برای هشدار دادن دیر است.
دو قاعده در همان تککوئریای که قرار است به هاب داده شود اعمال میشود: فقط رسانهای که هم تأییدشده و هم عمومی باشد واجد شرایط است. رسانهای که هنوز در انتظار بررسی است اصلاً قابل اشتراکگذاری نیست، و پستهای گاوصندوق در جدولی جدا هستند و هیچ مسیری به آنجا ندارند.
خصوصیکردن دوباره، جلوی کپیهای بعدی را میگیرد اما کپیهایی که قبلاً گرفته شده را برنمیگرداند؛ به همین دلیل قبل از عمومیکردن تأیید گرفته میشود، نه بعد از آن.
انتقال به سرور دیگر
فقط کافی است این دو فایل را منتقل کنید:
.envbot_db/media.db