Compare commits
3 Commits
1684c5177c
...
v0.1
Author | SHA1 | Date | |
---|---|---|---|
853c3c7cea | |||
e5f80d9702 | |||
6f03d5c18f |
20
.renovaterc
Normal file
20
.renovaterc
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"baseBranches": [
|
||||
"dev"
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"matchUpdateTypes": [
|
||||
"minor",
|
||||
"patch",
|
||||
"pin",
|
||||
"digest"
|
||||
],
|
||||
"automerge": true
|
||||
}
|
||||
]
|
||||
}
|
15
README.md
15
README.md
@@ -50,12 +50,7 @@ To make this bot run at first you need to have a Python interpreter, Photos API,
|
||||
`python -m pip install -r requirements.txt`
|
||||
Without installing those - bot cannot work at all.
|
||||
|
||||
5. Install optional dependencies [Optional]:
|
||||
|
||||
`python -m pip install -r requirements-optional.txt`
|
||||
These are not required but can make the bot run a bit faster.
|
||||
|
||||
6. Configure "bot" and "owner" with your favorite text editor:
|
||||
5. Configure "bot" and "owner" with your favorite text editor:
|
||||
|
||||
1. Copy file `config_example.json` to `config.json`
|
||||
2. Open `config.json` using your favorite text editor. For example `nano config.json`, but you can edit with vim, nano, on Windows it's Notepad or Notepad++. Whatever
|
||||
@@ -63,7 +58,7 @@ To make this bot run at first you need to have a Python interpreter, Photos API,
|
||||
|
||||
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).
|
||||
|
||||
7. Configure database and API:
|
||||
6. Configure database and API:
|
||||
|
||||
1. Configure database:
|
||||
1. Change database host and port in keys `"database.host"` and `"database.port"`. For default local installation those will be `127.0.0.1` and `27017` respectively
|
||||
@@ -74,15 +69,15 @@ To make this bot run at first you need to have a Python interpreter, Photos API,
|
||||
1. Change `"posting.api.address"` to the one your API servers uses
|
||||
2. Run your bot using `python poster.py --create-user --create-album` to configure its new user and album. You can also use manual user and album creation described [in the wiki](https://git.end-play.xyz/profitroll/TelegramPoster/wiki/Configuring-API). You can also change username, password and album in`"posting.api"` to the user and album you have if you already have Photos API album and user set up. In that case you don't need to create a new one.
|
||||
|
||||
8. Add bot to the channel:
|
||||
7. 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. After that simply set `"posting.channel"` to your channel's ID.
|
||||
|
||||
9. Configure posting time:
|
||||
8. Configure posting time:
|
||||
|
||||
To make your bot post random content you need to configure `"posting.time"` with a list of "DD:MM" formatted strings or use `"posting.interval"` formatted as "XdXhXmXs". To use interval instead of selected time set `"posting.use_interval"` to `true`.
|
||||
|
||||
10. Good to go, run it!
|
||||
9. Good to go, run it!
|
||||
|
||||
Make sure MongoDB and Photos API are running and use `python poster.py` to start it.
|
||||
Or you can also use `.\start.bat` on Windows and `bash ./start.sh` on Linux.
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"reports": {
|
||||
"sent": false,
|
||||
"error": true,
|
||||
"update": true,
|
||||
"startup": true,
|
||||
"shutdown": true
|
||||
},
|
||||
@@ -116,6 +117,7 @@
|
||||
"commands_admin": [
|
||||
"import",
|
||||
"export",
|
||||
"remove",
|
||||
"shutdown"
|
||||
]
|
||||
}
|
1
docs/updating.md
Normal file
1
docs/updating.md
Normal file
@@ -0,0 +1 @@
|
||||
# Updating your bot
|
@@ -9,7 +9,7 @@
|
||||
"export": "Get .zip archive with all photos",
|
||||
"remove": "Delete photo by its ID",
|
||||
"purge": "Completely purge bot's queue",
|
||||
"shutdown": "Restart the bot"
|
||||
"shutdown": "Turn off 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!",
|
||||
@@ -40,9 +40,27 @@
|
||||
"post_low": "Low amount of content: `There are only {0} files left in the queue.`",
|
||||
"api_creds_invalid": "Could not authorize API access. Please check whether provided in config file are valid and update them if they're not.",
|
||||
"sub_wip": "Post submission is now WIP. It will be available again in a few days. Thank you for your patience.",
|
||||
"sub_duplicates_found": "__TO_BE_ADDED__",
|
||||
"sub_error": "⚠️ Could not upload this image due to bot error. Admins are advised.",
|
||||
"sub_error_admin": "User {0} could not submit photo without additional confirmation due to:\n```\n{1}\n```"
|
||||
"sub_error_admin": "User {0} could not submit photo without additional confirmation due to:\n```\n{1}\n```",
|
||||
"import_request": "Please send me a zip archive with your media to be imported. Use /cancel if you want to abort this operation.",
|
||||
"import_ignored": "No response, aborting import.",
|
||||
"import_abort": "Import aborted.",
|
||||
"import_invalid_media": "File to import must be a zip archive. Aborting.",
|
||||
"import_invalid_mime": "Provided file is not supported. Please send `application/zip`. Aborting.",
|
||||
"import_too_big": "You archive is `{0} GiB` big, but system has only `{1} GiB` free. Unpacking may take even more space. Aborting.",
|
||||
"import_downloading": "Downloading archive...",
|
||||
"import_unpacking": "Unpacking archive...",
|
||||
"import_unpack_error": "Could not unpack the archive\n\nException: {0}\n\nTraceback:\n```python\n{1}\n```",
|
||||
"import_uploading": "Uploading archive contents...",
|
||||
"import_upload_error_duplicate": "Could not upload `{0}` because there're duplicates on server.",
|
||||
"import_upload_error_other": "Could not upload `{0}`. Probably disallowed filetype.",
|
||||
"import_finished": "Import finished.",
|
||||
"remove_request": "Please send me an ID to delete. You might have it from upload dialog. Use /cancel if you want to abort this operation.",
|
||||
"remove_ignored": "No response, aborting removal.",
|
||||
"remove_abort": "Removal aborted.",
|
||||
"remove_success": "Removed media with ID `{0}`.",
|
||||
"remove_failure": "Could not remove media with ID `{0}`. Check if provided ID is correct and if it is - you can also check bot's log for details.",
|
||||
"update_available": "**New version found**\nThere's a newer version of a bot found. You can update your bot to [{0}]({1}) using command line of your host.\n\n**Release notes**\n{2}\n\nRead more about updating you bot on the [wiki page](https://git.end-play.xyz/profitroll/TelegramPoster/wiki/Updating-Instance).\n\nPlease not that you can also disable this notification by editing `reports.update` key of the config."
|
||||
},
|
||||
"button": {
|
||||
"sub_yes": "✅ Accept",
|
||||
@@ -62,7 +80,6 @@
|
||||
"sub_msg_unavail": "Submission message no longer exist",
|
||||
"sub_media_unavail": "Could not download submission",
|
||||
"sub_done": "You've already decided what to do with submission",
|
||||
"sub_upload_failed": "__TO_BE_ADDED__",
|
||||
"sub_duplicates_found": "There're duplicates in bot's database",
|
||||
"nothing": "🏁 This action is already finished"
|
||||
},
|
||||
|
@@ -9,7 +9,7 @@
|
||||
"export": "Отримати .zip архів з усіма фотографіями",
|
||||
"remove": "Видалити фото за його ID",
|
||||
"purge": "Повністю видалити всю чергу бота",
|
||||
"shutdown": "Перезапустити бота"
|
||||
"shutdown": "Вимкнути бота"
|
||||
},
|
||||
"message": {
|
||||
"start": "Привіт і ласкаво просимо!\n\nТут можна пропонувати свої фотографії та відео. Ми переглянемо та додамо їх, якщо вони нам сподобаються. Переконайтеся, що ви надсилаєте свої матеріали по одному та вибираєте медіа, які відповідають нашим правилам.\n\nВи також можете написати нам щось у полі опису. За потреби ми надішлемо це разом із самим фото.\n\nКрім того, переконайтеся, що ви дотримуєтеся /rules (правил) подання, інакше вашу пропозицію буде відхилено. У разі спаму/зловживань вас можуть навіть заблокувати.\n\nГарного дня та щасливого надсилання!",
|
||||
@@ -40,9 +40,27 @@
|
||||
"post_low": "Мала кількість контенту: `Залишилось всього {0} файлів в черзі.`",
|
||||
"api_creds_invalid": "Не вдалося авторизувати запит до API. Будь ласка, перевірте чи дані авторизації в конфігураційному файлі вірні та оновіть їх, якщо це не так.",
|
||||
"sub_wip": "Подання постів зараз знаходиться у розробці. Він буде знову доступний через кілька днів. Дякуємо за ваше терпіння.",
|
||||
"sub_duplicates_found": "__TO_BE_ADDED__",
|
||||
"sub_error": "⚠️ Не вдалось завантажити фото через помилку бота. Адміністрацію повідомлено.",
|
||||
"sub_error_admin": "Користувач {0} не зміг надіслати фото без додаткової перевірки через помилку:\n```\n{1}\n```"
|
||||
"sub_error_admin": "Користувач {0} не зміг надіслати фото без додаткової перевірки через помилку:\n```\n{1}\n```",
|
||||
"import_request": "Будь ласка, надішліть zip-архів з медіа для імпортування. Використовуйте /cancel, якщо ви хочете перервати цю операцію.",
|
||||
"import_ignored": "Немає відповіді, перериваємо імпорт.",
|
||||
"import_abort": "Імпорт перервано.",
|
||||
"import_invalid_media": "Файл для імпорту має бути zip-архівом. Перериваємо.",
|
||||
"import_invalid_mime": "Наданий файл не підтримується. Будь ласка, надішліть `application/zip`. Перервано.",
|
||||
"import_too_big": "Ваш архів має розмір `{0} GiB`, але система має лише `{1} GiB` вільних. Розпакування може зайняти значно більше місця. Перервано.",
|
||||
"import_downloading": "Завантажуємо архів...",
|
||||
"import_unpacking": "Розпаковуємо архів...",
|
||||
"import_unpack_error": "Не вдалося розпакувати архів\n\nПомилка: {0}\n\nTraceback:\n```python\n{1}\n```",
|
||||
"import_uploading": "Завантажуємо вміст архіву...",
|
||||
"import_upload_error_duplicate": "Не вдалося завантажити `{0}`, оскільки на сервері є дублікати.",
|
||||
"import_upload_error_other": "Не вдалося завантажити `{0}`. Ймовірно, заборонений тип файлу.",
|
||||
"import_finished": "Імпорт завершено.",
|
||||
"remove_request": "Будь ласка, надішліть мені ID для видалення. Ви могли отримати його з діалогу завантаження. Використовуйте /cancel, якщо ви хочете перервати цю операцію.",
|
||||
"remove_ignored": "Немає відповіді, перериваємо видалення.",
|
||||
"remove_abort": "Видалення перервано.",
|
||||
"remove_success": "Видалено медіа з ID `{0}`.",
|
||||
"remove_failure": "Не вдалося видалити медіа з ID `{0}`. Перевірте, чи вказано правильний ID, і якщо він правильний, ви також можете переглянути логи бота для отримання більш детальної інформації.",
|
||||
"update_available": "**Знайдено нову версію**\nЗнайдено нову версію бота. Ви можете оновити бота до [{0}]({1}) за допомогою командного рядка вашого хосту.\n\n**Примітки до релізу**\n{2}\n\nДетальніше про оновлення бота можна знайти на [вікі-сторінці](https://git.end-play.xyz/profitroll/TelegramPoster/wiki/Updating-Instance).\n\nЗверніть увагу, що ви також можете вимкнути це сповіщення, відредагувавши ключ `reports.update` у конфігурації."
|
||||
},
|
||||
"button": {
|
||||
"sub_yes": "✅ Прийняти",
|
||||
@@ -62,7 +80,6 @@
|
||||
"sub_msg_unavail": "Повідомлення більше не існує",
|
||||
"sub_media_unavail": "Не вдалося завантажити подання",
|
||||
"sub_done": "Ви вже обрали що зробити з цим поданням",
|
||||
"sub_upload_failed": "__TO_BE_ADDED__",
|
||||
"sub_duplicates_found": "Знайдено дублікати в базі даних бота",
|
||||
"nothing": "🏁 Цю дію вже було завершено"
|
||||
},
|
||||
|
@@ -8,8 +8,7 @@ from traceback import print_exc
|
||||
from typing import Tuple, Union
|
||||
|
||||
import aiofiles
|
||||
from aiohttp import ClientSession, FormData
|
||||
from ujson import dumps
|
||||
from aiohttp import FormData
|
||||
|
||||
from classes.exceptions import (
|
||||
AlbumCreationDuplicateError,
|
||||
@@ -21,10 +20,7 @@ from classes.exceptions import (
|
||||
)
|
||||
from modules.logger import logWrite
|
||||
from modules.utils import configGet, locale
|
||||
|
||||
http_session = ClientSession(
|
||||
json_serialize=dumps,
|
||||
)
|
||||
from modules.http_client import http_session
|
||||
|
||||
|
||||
async def authorize() -> str:
|
||||
@@ -208,10 +204,28 @@ async def find_pic(
|
||||
async def move_pic(id: str, token: Union[str, None] = None) -> bool:
|
||||
token = await authorize() if token is None else token
|
||||
try:
|
||||
await http_session.patch(
|
||||
response = await http_session.patch(
|
||||
f'{configGet("address", "posting", "api")}/photos/{id}?caption=sent',
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
)
|
||||
if response.status != 200:
|
||||
logWrite(f"Media moving failed with HTTP {response.status}", debug=True)
|
||||
return False
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
async def remove_pic(id: str, token: Union[str, None] = None) -> bool:
|
||||
token = await authorize() if token is None else token
|
||||
try:
|
||||
response = await http_session.delete(
|
||||
f'{configGet("address", "posting", "api")}/photos/{id}',
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
)
|
||||
if response.status != 204:
|
||||
logWrite(f"Media removal failed with HTTP {response.status}", debug=True)
|
||||
return False
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
6
modules/http_client.py
Normal file
6
modules/http_client.py
Normal file
@@ -0,0 +1,6 @@
|
||||
from aiohttp import ClientSession
|
||||
from ujson import dumps
|
||||
|
||||
http_session = ClientSession(
|
||||
json_serialize=dumps,
|
||||
)
|
@@ -11,10 +11,10 @@ from pyrogram import filters
|
||||
from pyrogram.types import Message
|
||||
|
||||
from classes.poster_client import PosterClient
|
||||
from modules.api_client import upload_pic
|
||||
from modules.api_client import remove_pic, upload_pic
|
||||
from modules.app import app, users_with_context
|
||||
from modules.logger import logWrite
|
||||
from modules.utils import configGet, extract_and_save
|
||||
from modules.utils import configGet, extract_and_save, locale
|
||||
|
||||
|
||||
@app.on_message(~filters.scheduled & filters.command(["import"], prefixes=["", "/"]))
|
||||
@@ -26,30 +26,47 @@ async def cmd_import(app: PosterClient, msg: Message):
|
||||
else:
|
||||
return
|
||||
await msg.reply_text(
|
||||
f"Alright, please send me a zip archive with your media to be imported. Use /cancel if you want to abort this operation."
|
||||
locale("import_request", "message", locale=msg.from_user.language_code)
|
||||
)
|
||||
answer = await listen_message(app, msg.chat.id, timeout=600)
|
||||
users_with_context.remove(msg.from_user.id)
|
||||
if answer is None:
|
||||
await msg.reply_text("No response, aborting import.", quote=True)
|
||||
await msg.reply_text(
|
||||
locale("import_ignored", "message", locale=msg.from_user.language_code),
|
||||
quote=True,
|
||||
)
|
||||
return
|
||||
if answer.text == "/cancel":
|
||||
await answer.reply_text("Okay, aborting.")
|
||||
await answer.reply_text(
|
||||
locale("import_abort", "message", locale=msg.from_user.language_code)
|
||||
)
|
||||
return
|
||||
if answer.document is None:
|
||||
await answer.reply_text(
|
||||
"File to import must be a zip archive. Aborting.", quote=True
|
||||
locale(
|
||||
"import_invalid_media",
|
||||
"message",
|
||||
locale=msg.from_user.language_code,
|
||||
),
|
||||
quote=True,
|
||||
)
|
||||
return
|
||||
if answer.document.mime_type != "application/zip":
|
||||
await answer.reply_text(
|
||||
"Provided file is not supported. Please send `application/zip`. Aborting.",
|
||||
locale(
|
||||
"import_invalid_mime", "message", locale=msg.from_user.language_code
|
||||
),
|
||||
quote=True,
|
||||
)
|
||||
return
|
||||
if disk_usage(getcwd())[2] < (answer.document.file_size) * 3:
|
||||
await msg.reply_text(
|
||||
f"You archive is `{answer.document.file_size//(2**30)} GiB` big, but system has only `{disk_usage(getcwd())[2]//(2**30)} GiB` free. Unpacking may take even more space. Aborting."
|
||||
locale(
|
||||
"import_too_big", "message", locale=msg.from_user.language_code
|
||||
).format(
|
||||
answer.document.file_size // (2**30),
|
||||
disk_usage(getcwd())[2] // (2**30),
|
||||
)
|
||||
)
|
||||
return
|
||||
tmp_dir = str(uuid4())
|
||||
@@ -58,9 +75,14 @@ async def cmd_import(app: PosterClient, msg: Message):
|
||||
)
|
||||
makedirs(path.join(configGet("tmp", "locations"), tmp_dir), exist_ok=True)
|
||||
tmp_path = path.join(configGet("tmp", "locations"), answer.document.file_id)
|
||||
downloading = await answer.reply_text("Okay, downloading...", quote=True)
|
||||
downloading = await answer.reply_text(
|
||||
locale("import_downloading", "message", locale=msg.from_user.language_code),
|
||||
quote=True,
|
||||
)
|
||||
await app.download_media(answer, file_name=tmp_path)
|
||||
await downloading.edit("Downloaded, unpacking...")
|
||||
await downloading.edit(
|
||||
locale("import_unpacking", "message", locale=msg.from_user.language_code)
|
||||
)
|
||||
try:
|
||||
with ZipFile(tmp_path, "r") as handle:
|
||||
tasks = [
|
||||
@@ -75,11 +97,15 @@ async def cmd_import(app: PosterClient, msg: Message):
|
||||
f"Could not import '{answer.document.file_name}' due to {exp}: {format_exc}"
|
||||
)
|
||||
await answer.reply_text(
|
||||
f"Could not unpack the archive\n\nException: {exp}\n\nTraceback:\n```python\n{format_exc}\n```"
|
||||
locale(
|
||||
"import_unpack_error", "message", locale=msg.from_user.language_code
|
||||
).format(exp, format_exc())
|
||||
)
|
||||
return
|
||||
logWrite(f"Downloaded '{answer.document.file_name}' - awaiting upload")
|
||||
await downloading.edit("Unpacked, uploading...")
|
||||
await downloading.edit(
|
||||
locale("import_uploading", "message", locale=msg.from_user.language_code)
|
||||
)
|
||||
remove(tmp_path)
|
||||
|
||||
for filename in iglob(
|
||||
@@ -96,12 +122,20 @@ async def cmd_import(app: PosterClient, msg: Message):
|
||||
)
|
||||
if len(uploaded[1]) > 0:
|
||||
await msg.reply_text(
|
||||
f"Could not upload `{path.basename(filename)}` because there're duplicates on server.",
|
||||
locale(
|
||||
"import_upload_error_duplicate",
|
||||
"message",
|
||||
locale=msg.from_user.language_code,
|
||||
).format(path.basename(filename)),
|
||||
disable_notification=True,
|
||||
)
|
||||
else:
|
||||
await msg.reply_text(
|
||||
f"Could not upload `{path.basename(filename)}`. Probably disallowed filetype",
|
||||
locale(
|
||||
"import_upload_error_other",
|
||||
"message",
|
||||
locale=msg.from_user.language_code,
|
||||
).format(path.basename(filename)),
|
||||
disable_notification=True,
|
||||
)
|
||||
else:
|
||||
@@ -116,7 +150,10 @@ async def cmd_import(app: PosterClient, msg: Message):
|
||||
debug=True,
|
||||
)
|
||||
rmtree(path.join(configGet("tmp", "locations"), tmp_dir), ignore_errors=True)
|
||||
await answer.reply_text("Done.", quote=True)
|
||||
await answer.reply_text(
|
||||
locale("import_finished", "message", locale=msg.from_user.language_code),
|
||||
quote=True,
|
||||
)
|
||||
return
|
||||
|
||||
|
||||
@@ -129,7 +166,46 @@ async def cmd_export(app: PosterClient, msg: Message):
|
||||
@app.on_message(~filters.scheduled & filters.command(["remove"], prefixes=["", "/"]))
|
||||
async def cmd_remove(app: PosterClient, msg: Message):
|
||||
if msg.from_user.id in app.admins:
|
||||
pass
|
||||
global users_with_context
|
||||
if msg.from_user.id not in users_with_context:
|
||||
users_with_context.append(msg.from_user.id)
|
||||
else:
|
||||
return
|
||||
await msg.reply_text(
|
||||
locale("remove_request", "message", locale=msg.from_user.language_code)
|
||||
)
|
||||
answer = await listen_message(app, msg.chat.id, timeout=600)
|
||||
users_with_context.remove(msg.from_user.id)
|
||||
if answer is None:
|
||||
await msg.reply_text(
|
||||
locale("remove_ignored", "message", locale=msg.from_user.language_code),
|
||||
quote=True,
|
||||
)
|
||||
return
|
||||
if answer.text == "/cancel":
|
||||
await answer.reply_text(
|
||||
locale("remove_abort", "message", locale=msg.from_user.language_code)
|
||||
)
|
||||
return
|
||||
response = await remove_pic(answer.text)
|
||||
if response:
|
||||
logWrite(
|
||||
f"Removed '{answer.text}' by request of user {answer.from_user.id}"
|
||||
)
|
||||
await answer.reply_text(
|
||||
locale(
|
||||
"remove_success", "message", locale=msg.from_user.language_code
|
||||
).format(answer.text)
|
||||
)
|
||||
else:
|
||||
logWrite(
|
||||
f"Could not remove '{answer.text}' by request of user {answer.from_user.id}"
|
||||
)
|
||||
await answer.reply_text(
|
||||
locale(
|
||||
"remove_failure", "message", locale=msg.from_user.language_code
|
||||
).format(answer.text)
|
||||
)
|
||||
|
||||
|
||||
@app.on_message(~filters.scheduled & filters.command(["purge"], prefixes=["", "/"]))
|
||||
|
102
poster.py
102
poster.py
@@ -1,18 +1,21 @@
|
||||
from os import getpid, path
|
||||
from datetime import datetime
|
||||
from os import getpid, path
|
||||
from sys import exit
|
||||
from time import time
|
||||
from traceback import format_exc
|
||||
from modules.api_client import authorize
|
||||
|
||||
from modules.cli import *
|
||||
from modules.http_client import http_session
|
||||
from modules.logger import logWrite
|
||||
from modules.scheduler import scheduler
|
||||
from modules.utils import configGet, jsonLoad, jsonSave, killProc, locale
|
||||
from modules.utils import configGet, jsonLoad, jsonSave, locale
|
||||
|
||||
# Import ===================================================================================================================================
|
||||
try:
|
||||
from pyrogram.sync import idle
|
||||
from pyrogram.errors import bad_request_400
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from pyrogram.errors import bad_request_400
|
||||
from pyrogram.sync import idle
|
||||
|
||||
from modules.app import app
|
||||
except ModuleNotFoundError:
|
||||
@@ -22,6 +25,7 @@ except ModuleNotFoundError:
|
||||
|
||||
|
||||
pid = getpid()
|
||||
version = 0.1
|
||||
|
||||
# Work in progress
|
||||
# def check_forwards(app):
|
||||
@@ -59,9 +63,10 @@ pid = getpid()
|
||||
# check_forwards(app)
|
||||
|
||||
|
||||
from plugins.callbacks.shutdown import *
|
||||
|
||||
# Imports ==================================================================================================================================
|
||||
from plugins.commands.general import *
|
||||
from plugins.callbacks.shutdown import *
|
||||
|
||||
if configGet("submit", "mode"):
|
||||
from plugins.callbacks.nothing import *
|
||||
@@ -116,10 +121,11 @@ if configGet("post", "mode"):
|
||||
# uvloop.install()
|
||||
# asyncio.run(main())
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
async def main():
|
||||
logWrite(locale("startup", "console").format(str(pid)))
|
||||
|
||||
app.start()
|
||||
await app.start()
|
||||
|
||||
if configGet("startup", "reports"):
|
||||
try:
|
||||
@@ -133,7 +139,7 @@ if __name__ == "__main__":
|
||||
),
|
||||
)
|
||||
if downtime.days >= 1:
|
||||
app.send_message(
|
||||
await app.send_message(
|
||||
configGet("owner"),
|
||||
locale(
|
||||
"startup_downtime_days",
|
||||
@@ -141,7 +147,7 @@ if __name__ == "__main__":
|
||||
).format(pid, downtime.days),
|
||||
)
|
||||
elif downtime.hours >= 1:
|
||||
app.send_message(
|
||||
await app.send_message(
|
||||
configGet("owner"),
|
||||
locale(
|
||||
"startup_downtime_hours",
|
||||
@@ -149,7 +155,7 @@ if __name__ == "__main__":
|
||||
).format(pid, downtime.hours),
|
||||
)
|
||||
else:
|
||||
app.send_message(
|
||||
await app.send_message(
|
||||
configGet("owner"),
|
||||
locale(
|
||||
"startup_downtime_minutes",
|
||||
@@ -158,7 +164,7 @@ if __name__ == "__main__":
|
||||
).format(pid, downtime.minutes),
|
||||
)
|
||||
else:
|
||||
app.send_message(
|
||||
await app.send_message(
|
||||
configGet("owner"),
|
||||
locale("startup", "message").format(pid),
|
||||
)
|
||||
@@ -167,18 +173,75 @@ if __name__ == "__main__":
|
||||
f"Could not send startup message to bot owner. Perhaps user has not started the bot yet."
|
||||
)
|
||||
|
||||
if configGet("update", "reports"):
|
||||
try:
|
||||
check_update = await http_session.get(
|
||||
"https://git.end-play.xyz/api/v1/repos/profitroll/TelegramPoster/releases?page=1&limit=1"
|
||||
)
|
||||
response = await check_update.json()
|
||||
if len(response) == 0:
|
||||
raise ValueError("No bot releases on git found.")
|
||||
if float(response[0]["tag_name"].replace("v.", "")) > version:
|
||||
logWrite(
|
||||
f'New version {response[0]["tag_name"].replace("v.", "")} found (current {version})'
|
||||
)
|
||||
await app.send_message(
|
||||
configGet("owner"),
|
||||
locale(
|
||||
"update_available",
|
||||
"message",
|
||||
).format(
|
||||
response[0]["tag_name"],
|
||||
response[0]["html_url"],
|
||||
response[0]["body"],
|
||||
),
|
||||
)
|
||||
else:
|
||||
logWrite(f"No updates found, bot is up to date.")
|
||||
except bad_request_400.PeerIdInvalid:
|
||||
logWrite(
|
||||
f"Could not send startup message to bot owner. Perhaps user has not started the bot yet."
|
||||
)
|
||||
except Exception as exp:
|
||||
logWrite(f"Update check failed due to {exp}: {format_exc()}")
|
||||
|
||||
if configGet("post", "mode"):
|
||||
scheduler.start()
|
||||
|
||||
# if configGet("api_based", "mode"):
|
||||
# token = await authorize()
|
||||
# if len(get(f'{configGet("address", "posting", "api")}/albums?q={configGet("queue", "posting", "api", "albums")}', headers={"Authorization": f"Bearer {token}"}).json()["results"]) == 0:
|
||||
# post(f'{configGet("address", "posting", "api")}/albums?name={configGet("queue", "posting", "api", "albums")}&title={configGet("queue", "posting", "api", "albums")}', headers={"Authorization": f"Bearer {token}"})
|
||||
try:
|
||||
token = await authorize()
|
||||
|
||||
idle()
|
||||
if (
|
||||
len(
|
||||
(
|
||||
await (
|
||||
await http_session.get(
|
||||
f'{configGet("address", "posting", "api")}/albums?q={configGet("album", "posting", "api")}',
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
)
|
||||
).json()
|
||||
)["results"]
|
||||
)
|
||||
== 0
|
||||
):
|
||||
logWrite("Media album does not exist on API server. Trying to create it...")
|
||||
try:
|
||||
await http_session.post(
|
||||
f'{configGet("address", "posting", "api")}/albums?name={configGet("album", "posting", "api")}&title={configGet("album", "posting", "api")}',
|
||||
headers={"Authorization": f"Bearer {token}"},
|
||||
)
|
||||
logWrite("Created media album on API server.")
|
||||
except Exception as exp:
|
||||
logWrite(
|
||||
f"Could not create media album on API server due to {exp}: {format_exc()}"
|
||||
)
|
||||
except Exception as exp:
|
||||
logWrite(f"Could not check if API album exists due to {exp}: {format_exc()}")
|
||||
|
||||
await idle()
|
||||
|
||||
try:
|
||||
app.send_message(
|
||||
await app.send_message(
|
||||
configGet("owner"),
|
||||
locale("shutdown", "message").format(pid),
|
||||
)
|
||||
@@ -197,4 +260,7 @@ if __name__ == "__main__":
|
||||
|
||||
scheduler.shutdown()
|
||||
|
||||
killProc(pid)
|
||||
|
||||
if __name__ == "__main__":
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(main())
|
||||
|
@@ -1 +0,0 @@
|
||||
tgcrypto==1.2.5
|
@@ -1,11 +1,12 @@
|
||||
python_dateutil==2.8.2
|
||||
apscheduler~=3.10.1
|
||||
pytimeparse~=1.1.8
|
||||
apscheduler==3.10.1
|
||||
pytimeparse==1.1.8
|
||||
convopyro==0.5
|
||||
pyrogram~=2.0.102
|
||||
pyrogram==2.0.104
|
||||
aiofiles~=23.1.0
|
||||
tgcrypto==1.2.5
|
||||
aiohttp~=3.8.4
|
||||
psutil~=5.9.4
|
||||
pymongo~=4.3.3
|
||||
pillow~=9.4.0
|
||||
ujson~=5.7.0
|
||||
psutil==5.9.5
|
||||
pymongo==4.3.3
|
||||
pillow~=9.5.0
|
||||
ujson==5.7.0
|
Reference in New Issue
Block a user