This commit is contained in:
Profitroll 2022-08-10 13:08:15 +02:00
parent ac509194da
commit e03c862a35
8 changed files with 294 additions and 60 deletions

View File

@ -1,5 +1,6 @@
# TelegramPoster
This bot is used for one and only task - post pictures from my personal archive. Here's its source code so you can also host a bot and have fun with it. Just don't exepect it to be brilliant. It is not. But hey, you can always fork it ;)
Шукаєш інструкцію українською? А вона [ось тут](https://git.profitroll.eu/profitroll/TelegramPoster/src/branch/master/README_uk.md) знаходиться)
## Installation
To make this bot run at first you need to have a Python interpreter and git. Google is your friend finding it. You can also ignore git and simply download source code, should also work fine. After that you're ready to go.
@ -10,7 +11,7 @@ To make this bot run at first you need to have a Python interpreter and git. Goo
> If it's non-standart executable path - you should also change
> it in scripts you will use (`loop.sh`, `loop.bat`, `start.sh` and `start.bat`).
1. Download the bot.
1. Download the bot:
1. `git clone https://git.end-play.xyz/profitroll/TelegramSender.git` (if you want to use git)
2. `cd ./TelegramSender`
@ -27,10 +28,10 @@ To make this bot run at first you need to have a Python interpreter and git. Goo
You can edit with vim, nano, on Windows it's Notepad or Notepad++. Whatever.
If you don't know where to find bot_token and your id - here you can find some hints: [get bot token](https://www.siteguarding.com/en/how-to-get-telegram-bot-api-token), [get your id](https://www.alphr.com/telegram-find-user-id/), [get api_hash and api_id](https://core.telegram.org/api/obtaining_api_id).
5. Add bot to the channel
5. Add bot to the channel:
To use your bot of course you need to have a channel or group otherwise makes no sense to have such a bot. [Here](https://stackoverflow.com/a/33497769) you can find a quick guide how to add your bot to a channel.
6. Fill your contents folder
6. Fill your contents folder:
Of course bot cannot post something from nothing. Configure your `config.json` what media types bot should post (`"posting", "extensions"`), when to post them (`"posting", "time"`) and also where to find them (`"locations"`). You can also move them when sent by setting `"posting", "move_sent"` to `true`.
6. Good to go, run it!
@ -43,7 +44,7 @@ Of course bot also has them. You can perform some actions with them.
* `--move-sent` - allows you to move all sent files from queue to sent directories
* `--cleanup` - purge files in both `queue` and `sent` folders if they're sent. Requires `--confirm` argument
* `--cleanup-index` - purge all sent entries from index. Requires `--confirm` argument
* `--norun` - allows you to execute above arguments without tiggering the bot start itself
* `--norun` - allows you to execute above arguments without triggering the bot start itself
Examples:
* `python3 ./main.py --move-sent --norun`

50
README_uk.md Normal file
View File

@ -0,0 +1,50 @@
# TelegramPoster
Цей бот використовується для однієї-єдиної задачі - розміщувати фотографії з мого особистого архіву. Ось його код, тож Ви також можете захостити бота самостійно та розважитися з ним. Тільки не очікуйте, що він ідеальним. Не буде. Але гей, Ви завжди можете його доробити під себе ;)
## Установка
Для запуску цього бота спочатку потрібно мати інтерпретатор Python та встановлений git. Google — Ваш друг у пошуках. Ви також можете ігнорувати git і просто завантажити код, також має спрацювати добре. Після цього Ви готові до встановлення.
> У цьому README я вважаю, що Ви використовуєте python за замовчуванням у своїй
> системі і PATH Вашої системи містить його. Якщо Ваш python за замовчуванням
> є `python3` або, наприклад, `/home/user/.local/bin/python3.9` - використовуйте його натомість.
> Якщо це нестандартний шлях до виконуваного файлу - Вам також слід змінити
> це у скриптах, які Ви використовуватимете (`loop.sh`, `loop.bat`, `start.sh` та `start.bat`).
1. Завантажте бота:
1. `git clone https://git.end-play.xyz/profitroll/TelegramSender.git` (якщо хочете використовувати git)
2. `cd ./TelegramSender`
2. Встановіть залежності:
`python -m pip install -r requirements.txt`
Без їх установки бот не зможе працювати взагалі
3. Встановіть додаткові залежності [Не обов'язково]:
`python -m pip install -r requirements-optional.txt`
Вони не є обов’язковими, але можуть прискорити роботу бота
4. Налаштуйте свого бота за допомогою текстового редактора:
`nano config.json`
Ви можете редагувати за допомогою vim, nano, у Windows це Notepad або Notepad++. На Ваш смак.
Якщо Ви не знаєте, де знайти bot_token і свій ідентифікатор, тут Ви можете знайти кілька підказок: [отримати токен бота](https://www.siteguarding.com/en/how-to-get-telegram-bot-api-token), [отримати свій ідентифікатор](https://www.alphr.com/telegram-find-user-id/), [отримати api_hash і api_id](https://core.telegram.org/api/obtaining_api_id ).
5. Додайте бота на канал:
Звичайно, щоб використовувати свого бота, Вам потрібно мати канал або групу, інакше немає сенсу мати такого бота. [Тут](https://stackoverflow.com/a/33497769) Ви можете знайти короткий гайд, як додати свого бота до каналу.
6. Заповніть папку вмістом:
Звичайно, бот не може опублікувати щось із нічого. Налаштуйте свій `config.json`, які медіа-типи бот повинен публікувати (`"posting", "extensions"`), коли їх публікувати (`"posting", "time"`), а також де їх знайти (`"locations"`). Ви також можете переміщати їх після надсилання, встановивши для `"posting", "move_sent"` значення `true`.
6. Готово, запускайте!
`python ./main.py`
Або ви також можете використовувати `.\start.bat` на Windows і `bash ./start.sh` на Linux.
Крім того, доступні `loop.sh` і `loop.bat`, якщо ви хочете, щоб ваш бот запускався знову після зупинки або після використання команди `/reboot`.
## Аргументи командного рядка
Звичайно, у бота вони також є. З ними можна виконувати деякі дії.
* `--move-sent` - дозволяє перемістити всі надіслані файли з черги до папки надісланих
* `--cleanup` - очистити файли в папках `queue` і `sent`, якщо вони вже надіслані. Потрібен аргумент `--confirm`
* `--cleanup-index` - видалити всі надіслані записи з індексу. Потрібен аргумент `--confirm`
* `--norun` - дозволяє виконувати наведені вище аргументи, не запускаючи самого бота
Приклади:
* `python3 ./main.py --move-sent --norun`
* `python3 ./main.py --cleanup --confirm`

View File

@ -1,5 +1,7 @@
{
"module": null,
"locale": "en",
"locale_fallback": "en",
"bot": {
"api_id": 0,
"api_hash": "",
@ -18,7 +20,8 @@
"sent": "data/sent",
"index": "data/index.json",
"submit": "data/submit.json",
"blocked": "data/blocked.json"
"blocked": "data/blocked.json",
"locale": "locale"
},
"posting": {
"channel": 0,
@ -56,5 +59,9 @@
},
"submission": {
"timeout": 30
}
},
"commands": [
"start",
"rules"
]
}

57
locale/en.json Normal file
View File

@ -0,0 +1,57 @@
{
"commands": {
"start": "Start using the bot",
"rules": "Photos submission rules"
},
"commands_admin": {
"reboot": "Restart the bot"
},
"message": {
"start": "Hi and welcome!\n\nYou can submit your pictures and videos here. We'll review and add them, if we like them. Make sure you send your stuff one at a time and have chosen media that corresponds to our rules.\n\nYou can also write something to us in the description field. We'll send it with the submission itself, if needed.\n\nAlso, make sure you follow the /rules of submission, otherwise your submission will be declined. In case of spam/abuse you may even be blocked.\n\nHave fun and happy submitting!",
"rules": "Photos submission rules:\n1. No porn, only erotics and aesthetics\n2. Nipples are semi-allowed, should be either veiled or barely visible\n3. Genitalia strictly prohibited, but labia prints on clothes or nice pubes/panties/butts - are fine",
"shutdown": "Shutting down bot with pid `{0}`",
"startup": "Starting with pid `{0}`",
"sub_yes": "✅ Submission approved and accepted",
"sub_no": "❌ Submission reviewed and declined",
"sub_blocked": "You were blocked and you can't submit media anymore.",
"sub_unblocked": "You were unblocked and you can now submit media.",
"sub_by": "\n\nSubmitted by:",
"sub_sent": "Media has been submitted.\nWe'll notify you whether it will be accepted or not soon.",
"sub_cooldown": "You can only submit 1 media per {0} seconds",
"post_exception": "Could not send content due to `{exp}`\n\nTraceback:\n```{0}```",
"post_empty": "Could not send content: `Queue folder is empty or contains only unsupported or already sent files.`"
},
"button": {
"sub_yes": "✅ Accept",
"sub_no": "❌ Deny",
"sub_block": "☠️ Block sender",
"sub_unblock": "🏳️ Unblock sender",
"post_view": "View in channel"
},
"callback": {
"sub_yes": "✅ Submission approved",
"sub_no": "❌ Submission declined",
"sub_block": "User {0} has been blocked",
"sub_unblock": "User {0} has been unblocked",
"sub_msg_unavail": "Submission message no longer exist",
"sub_media_unavail": "Could not download submission"
},
"console": {
"shutdown": "Shutting down bot with pid {0}",
"startup":"Starting with pid {0}",
"keyboard_interrupt": "\nShutting down...",
"exception_occured": "Exception {0} happened on task execution",
"post_exception": "Could not send content due to {0}\nTraceback: {1}",
"post_empty": "Could not send content due to queue folder empty with allowed extensions",
"deps_missing": "Required modules are not installed. Run 'pip3 install -r requirements.txt' and restart the program.",
"passed_norun": "Argument --norun passed, not running the main script",
"move_sent_doesnt_exist": "File '{0}' is already moved or does not exist",
"move_sent_doesnt_exception": "Could not move sent file '{0}' to '{1}' due to {2}",
"move_sent_completed": "Moved all sent files to the sent folder",
"cleanup_exception": "Could not remove '{0}' due to {1}",
"cleanup_completed": "Performed cleanup of the sent files",
"cleanup_unathorized": "Requested cleanup of sent files but not authorized. Please pass '--confirm' to perform that",
"cleanup_index_completed": "Performed cleanup of sent files index",
"cleanup_index_unathorized": "Requested cleanup of sent files index but not authorized. Please pass '--confirm' to perform that"
}
}

57
locale/uk.json Normal file
View File

@ -0,0 +1,57 @@
{
"commands": {
"start": "Почати користуватись ботом",
"rules": "Правила пропонування фото"
},
"commands_admin": {
"reboot": "Перезапустити бота"
},
"message": {
"start": "Привіт і ласкаво просимо!\n\nТут можна пропонувати свої фотографії та відео. Ми переглянемо та додамо їх, якщо вони нам сподобаються. Переконайтеся, що ви надсилаєте свої матеріали по одному та вибираєте медіа, які відповідають нашим правилам.\n\nВи також можете написати нам щось у полі опису. За потреби ми надішлемо це разом із самим фото.\n\nКрім того, переконайтеся, що ви дотримуєтеся /rules (правил) подання, інакше вашу пропозицію буде відхилено. У разі спаму/зловживань вас можуть навіть заблокувати.\n\nГарного дня та щасливого надсилання!",
"rules": "Правила для пропонування фото:\n1. Ніякого порно, тільки еротика та естетика\n2. Соски можна, але або завуальовані, або зовсім ледь помітні\n3. Геніталії суворо ні, а ось відбитки статевих губ на одязі або гарні лобочки/трусики/попки - без проблем",
"shutdown": "Вимкнення бота з підом `{0}`",
"startup": "Запуск бота з підом `{0}`",
"sub_yes": "✅ Подання схвалено та прийнято",
"sub_no": "❌ Подання розглянуто та відхилено",
"sub_blocked": "Вас заблокували, і ви більше не можете надсилати медіафайли.",
"sub_unblocked": "Вас розблокували, і тепер ви можете надсилати медіафайли.",
"sub_by": "\n\nПредставлено:",
"sub_sent": "Медіа-файл надіслано.\nСкоро ми повідомимо вас, чи буде його прийнято.",
"sub_cooldown": "Ви можете надсилати лише 1 медіафайл на {0} секунд",
"post_exception": "Не вдалося надіслати контент через `{exp}`\n\nTraceback:\n```{0}```",
"post_empty": "Не вдалося надіслати контент: «Папка черги порожня або містить лише непідтримувані або вже надіслані файли»."
},
"button": {
"sub_yes": "✅ Прийняти",
"sub_no": "❌ Відхилити",
"sub_block": "☠️ Заблокувати відправника",
"sub_unblock": "🏳️ Розблокувати відправника",
"post_view": "Переглянути на каналі"
},
"callback": {
"sub_yes": "✅ Подання схвалено",
"sub_no": "❌ Подання відхилено",
"sub_block": "Користувача {0} заблоковано",
"sub_unblock": "Користувача {0} розблоковано",
"sub_msg_unavail": "Повідомлення більше не існує",
"sub_media_unavail": "Не вдалося завантажити подання"
},
"console": {
"shutdown": "Вимкнення бота з підом {0}",
"startup": "Запуск бота з підом {0}",
"keyboard_interrupt": "\nВимикаюсь...",
"exception_occured": "Помилка {0} сталась під час виконання",
"post_exception": "Не вдалося надіслати контент через {0}\nTraceback: {1}",
"post_empty": "Не вдалося надіслати контент через порожню папку черги з дозволеними розширеннями",
"deps_missing": "Необхідні модулі не встановлені. Запустіть 'pip3 install -r requirements.txt' і перезапустіть програму.",
"passed_norun": "Аргумент --norun надано, основний скрипт не запускається",
"move_sent_doesnt_exist": "Файл '{0}' уже переміщено або він не існує",
"move_sent_doesnt_exception": "Неможливо перемістити надісланий файл '{0}' до '{1}' через {2}",
"move_sent_completed": "Переміщено всі надіслані файли до папки надісланих",
"cleanup_exception": "Не вдалося видалити '{0}' через {1}",
"cleanup_completed": "Виконано очищення надісланих файлів",
"cleanup_unathorized": "Надіслано запит на очищення надісланих файлів, але не авторизовано. Для цього надайте аргумент '--confirm'",
"cleanup_index_completed": "Виконано очищення індексу надісланих файлів",
"cleanup_index_unathorized": "Надіслано запит на очищення індексу надісланих файлів, але не авторизовано. Для цього надайте аргумент '--confirm'"
}
}

120
main.py
View File

@ -8,7 +8,7 @@ import time
import traceback
from modules.logging import logWrite
from modules.utils import configGet, jsonLoad, jsonSave
from modules.utils import configGet, jsonLoad, jsonSave, killProc, locale
# Args =====================================================================================================================================
if "--move-sent" in sys.argv:
@ -16,10 +16,10 @@ if "--move-sent" in sys.argv:
try:
shutil.move(configGet("queue", "locations")+os.sep+entry, configGet("sent", "locations")+os.sep+entry)
except FileNotFoundError:
logWrite(f"File '{entry}' is already moved or does not exist")
logWrite(locale("move_sent_doesnt_exist", "console", locale=configGet("locale")).format(entry))
except Exception as exp:
logWrite(f"Could not move sent file '{entry}' to '{configGet('sent', 'locations')}' due to {exp}")
logWrite(f"Moved all sent files to the sent folder")
logWrite(locale("move_sent_doesnt_exception", "console", locale=configGet("locale")).format(entry, exp))
logWrite(locale("move_sent_completed", "console", locale=configGet("locale")))
if "--cleanup" in sys.argv:
if "--confirm" in sys.argv:
@ -35,23 +35,23 @@ if "--cleanup" in sys.argv:
except FileNotFoundError:
pass
except Exception as exp:
logWrite(f"Could not remove '{entry}' due to {exp}")
logWrite(locale("cleanup_exception", "console", locale=configGet("locale")).format(entry, exp))
jsonSave(index, jsonLoad(configGet("index", "locations")))
logWrite(f"Performed cleanup of the sent files")
logWrite(locale("cleanup_completed", "console", locale=configGet("locale")))
else:
logWrite(f"Requested cleanup of sent files but not authorized. Please pass '--confirm' to perform that")
logWrite(locale("cleanup_unathorized", "console", locale=configGet("locale")))
if "--cleanup-index" in sys.argv:
if "--confirm" in sys.argv:
index = jsonLoad(configGet("index", "locations"))
index["sent"] = []
jsonSave(index, jsonLoad(configGet("index", "locations")))
logWrite(f"Performed cleanup of sent files index")
logWrite(locale("cleanup_index_completed", "console", locale=configGet("locale")))
else:
logWrite(f"Requested cleanup of sent files index but not authorized. Please pass '--confirm' to perform that")
logWrite(locale("cleanup_index_unathorized", "console", locale=configGet("locale")))
if "--norun" in sys.argv:
logWrite("Argument --norun passed, not running the main script")
logWrite(locale("passed_norun", "console", locale=configGet("locale")))
sys.exit()
#===========================================================================================================================================
@ -62,7 +62,7 @@ try:
from pyrogram import Client, filters, idle # type: ignore
from pyrogram.types import ChatPermissions, ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton, BotCommand, BotCommandScopeChat # type: ignore
except ModuleNotFoundError:
print(f"Required modules are not installed. Run 'pip3 install -r requirements.txt' and restart the program.", flush=True)
print(locale("deps_missing", "console", locale=configGet("locale")), flush=True)
sys.exit()
#===========================================================================================================================================
@ -106,9 +106,9 @@ def send_content():
candidate_file = random.choice(list_queue)
candidate = configGet("queue", "locations")+os.sep+candidate_file
else:
logWrite(f"Could not send content due to queue folder empty with allowed extensions")
logWrite(locale("post_empty", "console", locale=configGet("locale")))
if configGet("error", "reports"):
app.send_message(configGet("admin", "reports"), f"Could not send content: `Queue folder is empty or contains only unsupported or already sent files.`") # type: ignore
app.send_message(configGet("admin", "reports"), locale("post_empty", "message", locale=configGet("locale"))) # type: ignore
return
if ext_type == "photo": # type: ignore
@ -143,22 +143,27 @@ def send_content():
])) # type: ignore
except Exception as exp:
logWrite(f"Could not send content due to {exp}")
logWrite(f"Could not send content due to {exp}\nTraceback: {traceback.format_exc()}")
if configGet("error", "reports"):
app.send_message(configGet("admin", "reports"), f"Could not send content due to `{exp}`\n\nTraceback:\n```{traceback.format_exc()}```") # type: ignore
app.send_message(configGet("admin", "reports"), locale("post_exception", "message", locale=configGet("locale")).format(exp, traceback.format_exc())) # type: ignore
@app.on_message(~ filters.scheduled & filters.command(["start", "help"], prefixes="/"))
@app.on_message(~ filters.scheduled & filters.command(["start"], prefixes="/"))
def start(app, msg):
if msg.from_user.id not in jsonLoad(configGet("blocked", "locations")):
msg.reply_text(f"Hi and welcome!\n\nYou can submit your pictures and videos here. We'll review and add them, if we like them. Make sure you send your stuff one at a time and have chosen media that corresponds to our rules.\n\nYou can also write something to us in the description field. We'll send it with the submission itself, if needed.\n\nHave fun and happy submitting!")
msg.reply_text(locale("start", "message", locale=msg.from_user.language_code))
@app.on_message(~ filters.scheduled & filters.command(["rules", "help"], prefixes="/"))
def start(app, msg):
if msg.from_user.id not in jsonLoad(configGet("blocked", "locations")):
msg.reply_text(locale("rules", "message", locale=msg.from_user.language_code))
@app.on_message(~ filters.scheduled & filters.command(["kill", "die", "reboot"], prefixes=["", "/"]))
def kill(app, msg):
if msg.from_user.id == configGet("admin", "reports"):
msg.reply_text(f"Shutting down bot with pid `{pid}`")
os.system('kill -9 '+str(pid))
msg.reply_text(locale("shutdown", "message", locale=configGet("locale")).format(str(pid)))
killProc(pid)
# Submission =====================================================================================================================================
@ -195,6 +200,7 @@ def subUnblock(user):
@app.on_message(~ filters.scheduled & filters.photo | filters.video | filters.animation)
def get_submission(_, msg):
if msg.from_user.id not in jsonLoad(configGet("blocked", "locations")):
user_locale = msg.from_user.language_code
if not subLimited(msg.from_user):
if msg.caption != None:
@ -202,7 +208,7 @@ def get_submission(_, msg):
else:
caption = ""
caption += "\n\nSubmitted by:"
caption += locale("sub_by", "message", locale=locale(configGet("locale")))
if msg.from_user.first_name != None:
caption += f" {msg.from_user.first_name}"
@ -215,62 +221,66 @@ def get_submission(_, msg):
msg.copy(configGet("admin", "reports"), caption=caption, reply_markup=InlineKeyboardMarkup([
[
InlineKeyboardButton(text="✅ Accept", callback_data=f"sub_yes_{msg.from_user.id}_{msg.id}"),
InlineKeyboardButton(text="❌ Deny", callback_data=f"sub_no_{msg.from_user.id}_{msg.id}")
InlineKeyboardButton(text=locale("sub_yes", "button", locale=configGet("locale")), callback_data=f"sub_yes_{msg.from_user.id}_{msg.id}"),
InlineKeyboardButton(text=locale("sub_no", "button", locale=configGet("locale")), callback_data=f"sub_no_{msg.from_user.id}_{msg.id}")
],
[
InlineKeyboardButton(text="☠️ Block sender", callback_data=f"sub_block_{msg.from_user.id}")
InlineKeyboardButton(text=locale("sub_block", "button", locale=configGet("locale")), callback_data=f"sub_block_{msg.from_user.id}")
],
[
InlineKeyboardButton(text="🏳️ Unblock sender", callback_data=f"sub_unblock_{msg.from_user.id}")
InlineKeyboardButton(text=locale("sub_unblock", "button", locale=configGet("locale")), callback_data=f"sub_unblock_{msg.from_user.id}")
]
]
))
msg.reply_text(f"Media has been submitted.\nWe'll notify you whether it will be accepted or not soon.", quote=True)
msg.reply_text(locale("sub_sent", "message", locale=user_locale), quote=True)
subLimit(msg.from_user)
else:
msg.reply_text(f'You can only submit 1 media per {configGet("timeout", "submission")} seconds')
msg.reply_text(locale("sub_cooldown", "message", locale=user_locale).format(str(configGet("timeout", "submission"))))
@app.on_callback_query(filters.regex("sub_yes_[\s\S]*_[\s\S]*")) # type: ignore
def callback_query_yes(app, clb): # type: ignore
fullclb = clb.data.split("_")
user_locale = clb.from_user.language_code
try:
submission = app.get_messages(int(fullclb[2]), int(fullclb[3]))
except:
clb.answer(text=f"Submission message no longer exist", show_alert=True)
clb.answer(text=locale("sub_msg_unavail", "message", locale=user_locale), show_alert=True)
return
try:
app.download_media(submission, file_name=configGet("queue", "locations")+os.sep)
except:
clb.answer(text=f"Could not download submission", show_alert=True)
clb.answer(text=locale("sub_media_unavail", "message", locale=user_locale), show_alert=True)
return
submission.reply_text(f"✅ Submission approved and accepted", quote=True)
clb.answer(text=f"✅ Submission approved", show_alert=True)
submission.reply_text(locale("sub_yes", "message", locale=submission.from_user.language_code), quote=True)
clb.answer(text=locale("sub_yes", "callback", locale=user_locale).format(fullclb[2]), show_alert=True)
@app.on_callback_query(filters.regex("sub_no_[\s\S]*_[\s\S]*")) # type: ignore
def callback_query_no(app, clb): # type: ignore
fullclb = clb.data.split("_")
user_locale = clb.from_user.language_code
try:
submission = app.get_messages(int(fullclb[2]), int(fullclb[3]))
except:
clb.answer(text=f"Submission message no longer exist", show_alert=True)
clb.answer(text=locale("sub_msg_unavail", "message", locale=user_locale), show_alert=True)
return
submission.reply_text(f"❌ Submission reviewed and declined", quote=True)
clb.answer(text=f"❌ Submission declined", show_alert=True)
submission.reply_text(locale("sub_no", "message", locale=submission.from_user.language_code), quote=True)
clb.answer(text=locale("sub_no", "callback", locale=user_locale).format(fullclb[2]), show_alert=True)
@app.on_callback_query(filters.regex("sub_block_[\s\S]*")) # type: ignore
def callback_query_block(app, clb): # type: ignore
fullclb = clb.data.split("_")
app.send_message(int(fullclb[2]), "You were blocked and you can't submit media anymore.")
user_locale = clb.from_user.language_code
app.send_message(int(fullclb[2]), locale("sub_msg_unavail", "message", locale=configGet("locale")))
subBlock(int(fullclb[2]))
clb.answer(text=f"User {fullclb[2]} has been blocked", show_alert=True)
clb.answer(text=locale("sub_block", "callback", locale=user_locale).format(fullclb[2]), show_alert=True)
@app.on_callback_query(filters.regex("sub_unblock_[\s\S]*")) # type: ignore
def callback_query_unblock(app, clb): # type: ignore
fullclb = clb.data.split("_")
app.send_message(int(fullclb[2]), "You were unblocked and you can now submit media.")
user_locale = clb.from_user.language_code
app.send_message(int(fullclb[2]), locale("sub_msg_unavail", "message", locale=configGet("locale")))
subUnblock(int(fullclb[2]))
clb.answer(text=f"User {fullclb[2]} has been unblocked", show_alert=True)
clb.answer(text=locale("sub_unblock", "callback", locale=user_locale).format(fullclb[2]), show_alert=True)
#===========================================================================================================================================
@ -287,34 +297,44 @@ def background_task():
except:
pass
except Exception as exp:
logWrite(f"Exception {exp} happened on task execution")
logWrite(locale("exception_occured", "console", locale=configGet("locale")).format(exp))
except KeyboardInterrupt:
logWrite('\nShutting down...')
app.send_message(configGet("admin", "reports"), f"Shutting down with PID `{pid}`") # type: ignore
os.system('kill -9 '+str(pid))
logWrite(locale("keyboard_interrupt", "console", locale=configGet("locale")))
if configGet("shutdown", "reports"):
app.send_message(configGet("admin", "reports"), locale("shutdown", "message", locale=configGet("locale")).format(str(pid))) # type: ignore
killProc(pid)
if __name__ == "__main__":
logWrite(f'Starting with PID {pid}')
logWrite(locale("startup", "console", locale=configGet("locale")).format(str(pid)))
app.start() # type: ignore
app.send_message(configGet("admin", "reports"), f"Starting with pid `{pid}`") # type: ignore
if configGet("startup", "reports"):
app.send_message(configGet("admin", "reports"), locale("startup", "message", locale=configGet("locale")).format(str(pid))) # type: ignore
t = Thread(target=background_task)
t.start()
app.set_bot_commands([ # type: ignore
BotCommand("start", "Start using the bot")
])
for entry in os.listdir(configGet("locale", "locations")):
if entry.endswith(".json"):
commands_list = []
for command in configGet("commands"):
commands_list.append(BotCommand(command, locale(command, "commands", locale=entry.replace(".json", ""))))
app.set_bot_commands(commands_list, language_code=entry.replace(".json", ""))
commands_list = []
for command in configGet("commands"):
commands_list.append(BotCommand(command, locale(command, "commands", locale=configGet("locale_fallback"))))
app.set_bot_commands(commands_list)
app.set_bot_commands([ # type: ignore
BotCommand("reboot", "Reboot the bot"),
BotCommand("reboot", locale("reboot", "commands_admin", locale=configGet("locale"))),
],
scope=BotCommandScopeChat(chat_id=configGet("admin", "reports")))
idle()
app.send_message(configGet("admin", "reports"), f"Shutting down with pid `{pid}`") # type: ignore
logWrite(f'Shutting down with PID {pid}')
app.send_message(configGet("admin", "reports"), locale("shutdown", "message", locale=configGet("locale")).format(str(pid))) # type: ignore
logWrite(locale("shutdown", "console", locale=configGet("locale")).format(str(pid)))
subprocess.call(f'kill -9 {pid}', shell=True) # type: ignore
killProc(pid)

View File

@ -3,7 +3,9 @@ try:
except ModuleNotFoundError:
import json
import os
from signal import SIGKILL
import psutil
def jsonLoad(filename):
"""Loads arg1 as json and returns its contents"""
@ -52,3 +54,42 @@ def configGet(key: str, *args: str):
for dict_key in args:
this_key = this_key[dict_key]
return this_key[key]
def locale(key: str, *args: list, locale=configGet("locale")):
"""Get value of locale string
Args:
* key (str): The last key of the locale's keys path.
* *args (list): Path to key like: dict[args][key].
* locale (str): Locale to looked up in. Defaults to config's locale value.
Returns:
* any: Value of provided locale key
"""
if (locale == None):
locale = configGet("locale")
try:
this_dict = jsonLoad(f'{configGet("locale", "locations")}{os.sep}{locale}.json')
except FileNotFoundError:
try:
this_dict = jsonLoad(f'{configGet("locale", "locations")}{os.sep}{configGet("locale")}.json')
except FileNotFoundError:
try:
this_dict = jsonLoad(f'{configGet("locale_fallback", "locations")}{os.sep}{configGet("locale")}.json')
except:
return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"'
this_key = this_dict
for dict_key in args:
this_key = this_key[dict_key]
try:
return this_key[key]
except KeyError:
return f'⚠️ Locale in config is invalid: could not get "{key}" in {str(args)} from locale "{locale}"'
def killProc(pid):
if os.name == "posix":
os.kill(pid, SIGKILL)
else:
p = psutil.Process(pid)
p.kill()

View File

@ -1,2 +1,3 @@
schedule
pyrogram>=2.0.0
psutil