29 Commits

Author SHA1 Message Date
Profitroll
056fc52353 This commit closes #4 and closes #6 2023-02-19 20:54:58 +01:00
Profitroll
8bafd0cb35 This commit closes #3 2023-02-19 20:44:00 +01:00
Profitroll
fd47217bad This commit closes #5 2023-02-19 20:31:08 +01:00
Profitroll
6b7b5c22f2 Reverted web preview disable 2023-02-18 00:58:09 +01:00
Profitroll
b3698cfa70 Added support for duplicates access tokens 2023-02-18 00:55:58 +01:00
Profitroll
7607003f55 Added callback message for "nothing" 2023-02-17 23:45:55 +01:00
Profitroll
7918049f49 Fixed language code typo 2023-02-17 23:18:54 +01:00
Profitroll
fcd59b7aca Fixed caption display 2023-02-17 23:18:34 +01:00
Profitroll
8c478072c6 Fixed reply message not getting quoted 2023-02-17 23:18:19 +01:00
Profitroll
b766d0c52c Improved linting and removed unused imports 2023-02-17 22:59:03 +01:00
Profitroll
807e629ae7 Moved cooldowns to PosterUser class 2023-02-17 22:48:37 +01:00
Profitroll
87af9fd333 Fixed captions not getting detected 2023-02-17 22:26:07 +01:00
Profitroll
a54081a2ae Fixed some issues with locale 2023-02-17 21:58:46 +01:00
Profitroll
664284a6f8 Integrated previous commits 2023-02-17 21:55:38 +01:00
Profitroll
bd9917fb17 Replaced user block logic 2023-02-17 21:54:52 +01:00
Profitroll
68ea087963 Integrated interval-based schedule 2023-02-17 21:54:30 +01:00
Profitroll
d1813856d9 Imported callback "nothing" 2023-02-17 21:54:14 +01:00
Profitroll
cf204577e4 Added external address for links 2023-02-17 21:53:57 +01:00
Profitroll
68c887999e Divided admins and owner 2023-02-17 21:53:43 +01:00
Profitroll
642e17ee55 Image resize when too big 2023-02-17 16:46:44 +01:00
Profitroll
25af9b31f8 Changed Client to PosterClient 2023-02-17 16:46:33 +01:00
Profitroll
28fc359593 WIP: export and import 2023-02-17 16:46:13 +01:00
Profitroll
07203a9db9 Changed the way exceptions are handled 2023-02-17 16:45:51 +01:00
Profitroll
663a7b0db8 Submission without confirmation added 2023-02-17 16:44:56 +01:00
Profitroll
0d2e9fa6ec Using PosterClient instead of Client 2023-02-17 16:44:30 +01:00
Profitroll
c90e5eb697 Added Pillow to requirements 2023-02-17 16:44:03 +01:00
Profitroll
f4359aa6cd Added upload_pic method 2023-02-17 11:51:38 +01:00
4cd37be5dc WIP: New submission system 2023-02-16 16:41:01 +01:00
05042f01c6 Disabled WIP warning 2023-02-15 14:07:40 +01:00
22 changed files with 523 additions and 429 deletions

16
classes/exceptions.py Normal file
View File

@@ -0,0 +1,16 @@
from typing import Any
class SubmissionUnavailableError(Exception):
pass
class SubmissionUploadError(Exception):
def __init__(self, file_path: str, status_code: int, content: Any) -> None:
self.status_code = status_code
self.content = content
super().__init__(f"Could not upload photo '{file_path}' due to HTTP {self.status_code}: {self.content}")
class SubmissionDuplicatesError(Exception):
def __init__(self, file_path: str, duplicates: list) -> None:
self.duplicates = duplicates
super().__init__(f"Found duplicates of a photo '{file_path}': {self.duplicates}")

66
classes/poster_client.py Normal file
View File

@@ -0,0 +1,66 @@
from os import path, remove, sep
from shutil import rmtree
from typing import Union
from pyrogram.client import Client
from pyrogram.types import Message
from classes.exceptions import SubmissionDuplicatesError, SubmissionUnavailableError
from modules.api_client import upload_pic
from modules.database import col_submitted
from bson import ObjectId
from modules.logger import logWrite
from modules.utils import configGet
class PosterClient(Client):
def __init__(self, name: str, **kwargs): # type: ignore
super().__init__(name, **kwargs)
self.owner = configGet("owner")
self.admins = configGet("admins")+[configGet("owner")]
async def submit_photo(self, id: str) -> Union[Message, None]:
db_entry = col_submitted.find_one({"_id": ObjectId(id)})
submission = None
if db_entry is None:
raise SubmissionUnavailableError()
else:
if db_entry["temp"]["uuid"] is not None:
if not path.exists(path.join(configGet("data", "locations"), "submissions", db_entry["temp"]["uuid"], db_entry["temp"]["file"])):
raise SubmissionUnavailableError()
else:
filepath = path.join(configGet("data", "locations"), "submissions", db_entry["temp"]["uuid"], db_entry["temp"]["file"])
try:
submission = await self.get_messages(db_entry["user"], db_entry["telegram"]["msg_id"])
except:
pass
else:
try:
submission = await self.get_messages(db_entry["user"], db_entry["telegram"]["msg_id"])
filepath = await self.download_media(submission, file_name=configGet("tmp", "locations")+sep)
except:
raise SubmissionUnavailableError()
response = await upload_pic(str(filepath), allow_duplicates=configGet("allow_duplicates", "submission"))
if len(response[1]) > 0:
raise SubmissionDuplicatesError(str(filepath), response[1])
col_submitted.find_one_and_update({"_id": ObjectId(id)}, {"$set": {"done": True}})
try:
if db_entry["temp"]["uuid"] is not None:
rmtree(path.join(configGet("data", "locations"), "submissions", db_entry["temp"]["uuid"]), ignore_errors=True)
else:
remove(str(filepath))
except (FileNotFoundError, NotADirectoryError):
logWrite(f"Could not delete '{filepath}' on submission accepted", debug=True)
return submission
async def ban_user(self, id: int) -> None:
pass
async def unban_user(self, id: int) -> None:
pass

45
classes/user.py Normal file
View File

@@ -0,0 +1,45 @@
from modules.app import app
from datetime import datetime
from modules.database import col_banned, col_users
from modules.utils import configGet
class PosterUser():
def __init__(self, id: int):
self.id = id
def is_blocked(self) -> bool:
"""Check if user is banned from submitting content.
### Returns:
`bool`: Must be `True` if banned and `False` if not
"""
return False if col_banned.find_one({"user": self.id}) is None else True
def block(self) -> None:
"""Ban user from using command and submitting content."""
if col_banned.find_one({"user": self.id}) is None:
col_banned.insert_one({"user": self.id, "date": datetime.now()})
def unblock(self) -> None:
"""Allow user to use command and submit posts again."""
col_banned.find_one_and_delete({"user": self.id})
def is_limited(self) -> bool:
"""Check if user is on a cooldown after submitting something.
### Returns:
`bool`: Must be `True` if on the cooldown and `False` if not
"""
if self.id in app.admins:
return False
else:
db_record = col_users.find_one({"user": self.id})
if db_record is None:
return False
return True if (datetime.now() - db_record["cooldown"]).total_seconds() < configGet("timeout", "submission") else False
def limit(self) -> None:
"""Restart user's cooldown. Used after post has been submitted."""
if col_users.find_one_and_update({"user": self.id}, {"$set": {"cooldown": datetime.now()}}) is None:
col_users.insert_one({"user": self.id, "cooldown": datetime.now()})

View File

@@ -3,7 +3,8 @@
"locale": "en",
"locale_log": "en",
"locale_fallback": "en",
"admin": 0,
"owner": 0,
"admins": [],
"bot": {
"api_id": 0,
"api_hash": "",
@@ -46,7 +47,8 @@
"channel": 0,
"silent": false,
"move_sent": false,
"interval": 1,
"use_interval": false,
"interval": "1h30m",
"extensions": {
"photo": [
"jpg",
@@ -74,6 +76,7 @@
],
"api": {
"address": "http://localhost:8054",
"address_external": "https://photos.domain.com",
"username": "",
"password": "",
"album": ""
@@ -88,6 +91,11 @@
"timeout": 30,
"file_size": 15728640,
"tmp_size": 15728640,
"allow_duplicates": false,
"require_confirmation": {
"users": true,
"admins": true
},
"mime_types": [
"image/png",
"image/gif",
@@ -101,6 +109,8 @@
"rules"
],
"commands_admin": [
"import",
"export",
"reboot"
]
}

View File

@@ -5,6 +5,8 @@
},
"commands_admin": {
"forwards": "Check post forwards",
"import": "Submit .zip archive with photos",
"export": "Get .zip archive with all photos",
"reboot": "Restart the bot"
},
"message": {
@@ -13,7 +15,9 @@
"shutdown": "Shutting down bot with pid `{0}`",
"startup": "Starting with pid `{0}`",
"sub_yes": "✅ Submission approved and accepted",
"sub_yes_auto": "✅ Submission automatically accepted",
"sub_no": "❌ Submission reviewed and declined",
"sub_dup": "⚠️ Submission automatically declined because database already contains this photo",
"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:",
@@ -30,7 +34,10 @@
"api_queue_error": "__TO_BE_ADDED__",
"post_low": "Low amount of content: `There are only {0} files left in the queue.`",
"api_creds_invalid": "__TO_BE_ADDED__",
"sub_wip": "Post submission is now WIP. It will be available again in a few days. Thank you for your patience."
"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```"
},
"button": {
"sub_yes": "✅ Accept",
@@ -49,7 +56,10 @@
"sub_unblock": "User {0} has been unblocked",
"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_done": "You've already decided what to do with submission",
"sub_upload_failed": "__TO_BE_ADDED__",
"sub_duplicates_found": "__TO_BE_ADDED__",
"nothing": "🏁 This action is already finished"
},
"console": {
"shutdown": "Shutting down bot with pid {0}",

View File

@@ -5,6 +5,8 @@
},
"commands_admin": {
"forwards": "Переглянути репости",
"import": "Надати боту .zip архів з фотографіями",
"export": "Отримати .zip архів з усіма фотографіями",
"reboot": "Перезапустити бота"
},
"message": {
@@ -13,7 +15,9 @@
"shutdown": "Вимкнення бота з підом `{0}`",
"startup": "Запуск бота з підом `{0}`",
"sub_yes": "✅ Подання схвалено та прийнято",
"sub_yes_auto": "✅ Подання автоматично прийнято",
"sub_no": "❌ Подання розглянуто та відхилено",
"sub_dup": "⚠️ Подання автоматично відхилено через наявність цього фото в базі даних",
"sub_blocked": "Вас заблокували, ви більше не можете надсилати медіафайли.",
"sub_unblocked": "Вас розблокували, тепер ви можете надсилати медіафайли.",
"sub_by": "\n\nПредставлено:",
@@ -30,7 +34,10 @@
"api_queue_error": "__TO_BE_ADDED__",
"post_low": "Мала кількість контенту: `Залишилось всього {0} файлів в черзі.`",
"api_creds_invalid": "__TO_BE_ADDED__",
"sub_wip": "Подання постів зараз знаходиться у розробці. Він буде знову доступний через кілька днів. Дякуємо за ваше терпіння."
"sub_wip": "Подання постів зараз знаходиться у розробці. Він буде знову доступний через кілька днів. Дякуємо за ваше терпіння.",
"sub_duplicates_found": "__TO_BE_ADDED__",
"sub_error": "⚠️ Не вдалось завантажити фото через помилку бота. Адміністрацію повідомлено.",
"sub_error_admin": "Користувач {0} не зміг надіслати фото без додаткової перевірки через помилку:\n```\n{1}\n```"
},
"button": {
"sub_yes": "✅ Прийняти",
@@ -49,7 +56,10 @@
"sub_unblock": "Користувача {0} розблоковано",
"sub_msg_unavail": "Повідомлення більше не існує",
"sub_media_unavail": "Не вдалося завантажити подання",
"sub_done": "Ви вже обрали що зробити з цим поданням"
"sub_done": "Ви вже обрали що зробити з цим поданням",
"sub_upload_failed": "__TO_BE_ADDED__",
"sub_duplicates_found": "__TO_BE_ADDED__",
"nothing": "🏁 Цю дію вже було завершено"
},
"console": {
"shutdown": "Вимкнення бота з підом {0}",

View File

@@ -1,3 +1,5 @@
"""This is only a temporary solution. Complete Photos API client is yet to be developed."""
import asyncio
from base64 import b64decode, b64encode
from os import makedirs, path, sep
@@ -5,6 +7,7 @@ from random import choice
from typing import Tuple, Union
from requests import get, patch, post
from classes.exceptions import SubmissionUploadError
from modules.logger import logWrite
from modules.utils import configGet
@@ -37,8 +40,7 @@ async def random_pic(token: Union[str, None] = None) -> Tuple[str, str]:
### Returns:
* `Tuple[str, str]`: First value is an ID and the filename in the filesystem to be indexed.
"""
if token is None:
token = await authorize()
token = await authorize() if token is None else token
logWrite(f'{configGet("address", "posting", "api")}/albums/{configGet("album", "posting", "api")}/photos?q=&page_size=100&caption=queue')
resp = get(f'{configGet("address", "posting", "api")}/albums/{configGet("album", "posting", "api")}/photos?q=&page_size=100&caption=queue', headers={"Authorization": f"Bearer {token}"})
if resp.status_code != 200:
@@ -50,23 +52,42 @@ async def random_pic(token: Union[str, None] = None) -> Tuple[str, str]:
pic = choice(resp.json()["results"])
return pic["id"], pic["filename"]
async def upload_pic(filepath: str) -> Tuple[bool, list]:
token = await authorize()
async def upload_pic(filepath: str, allow_duplicates: bool = False, token: Union[str, None] = None) -> Tuple[bool, list]:
token = await authorize() if token is None else token
try:
pic_name = path.basename(filepath)
files = {'file': (pic_name, open(filepath, 'rb'), 'image/jpeg')}
response = post(f'{configGet("address", "posting", "api")}/albums/{configGet("album", "posting", "api")}/photos&caption=queue', headers={"Authorization": f"Bearer {token}"}, files=files).json()
print(response, flush=True)
response = post(f'{configGet("address", "posting", "api")}/albums/{configGet("album", "posting", "api")}/photos', params={"caption": "queue", "compress": False, "ignore_duplicates": allow_duplicates}, headers={"Authorization": f"Bearer {token}"}, files=files)
if response.status_code != 200 and response.status_code != 409:
logWrite(f"Could not upload '{filepath}' to API: HTTP {response.status_code} with message '{response.content}'")
raise SubmissionUploadError(str(filepath), response.status_code, response.content)
duplicates = []
if "duplicates" in response:
for duplicate in response["duplicates"]:
duplicates.append(f'{configGet("address", "posting", "api")}/photos/{duplicate["id"]}')
if "duplicates" in response.json():
for index, duplicate in enumerate(response.json()["duplicates"]):
if response.json()["access_token"] is None:
duplicates.append(f'`{duplicate["id"]}`:\n{configGet("address_external", "posting", "api")}/photos/{duplicate["id"]}')
else:
duplicates.append(f'`{duplicate["id"]}`:\n{configGet("address_external", "posting", "api")}/token/photo/{response.json()["access_token"]}?id={index}')
return True, duplicates
except:
return False, []
async def find_pic(name: str, caption: Union[str, None] = None, token: Union[str, None] = None) -> Union[dict, None]:
token = await authorize() if token is None else token
try:
response = get(f'{configGet("address", "posting", "api")}/albums/{configGet("album", "posting", "api")}/photos', params={"q": name, "caption": caption}, headers={"Authorization": f"Bearer {token}"})
# logWrite(response.json())
if response.status_code != 200:
return None
if len(response.json()["results"]) == 0:
return None
return response.json()["results"]
except Exception as exp:
logWrite(f"Could not find image with name '{name}' and caption '{caption}' due to: {exp}")
return None
async def move_pic(id: str) -> bool:
token = await authorize()
async def move_pic(id: str, token: Union[str, None] = None) -> bool:
token = await authorize() if token is None else token
try:
patch(f'{configGet("address", "posting", "api")}/photos/{id}?caption=sent', headers={"Authorization": f"Bearer {token}"})
return True

View File

@@ -1,4 +1,4 @@
from pyrogram.client import Client
from modules.utils import configGet
from classes.poster_client import PosterClient
app = Client("duptsiaposter", bot_token=configGet("bot_token", "bot"), api_id=configGet("api_id", "bot"), api_hash=configGet("api_hash", "bot"))
app = PosterClient("duptsiaposter", bot_token=configGet("bot_token", "bot"), api_id=configGet("api_id", "bot"), api_hash=configGet("api_hash", "bot"))

View File

@@ -1,9 +1,9 @@
from os import listdir
from pyrogram.client import Client
from classes.poster_client import PosterClient
from pyrogram.types import BotCommand, BotCommandScopeChat
from modules.utils import configGet, locale
async def register_commands(app: Client):
async def register_commands(app: PosterClient) -> None:
if configGet("submit", "mode"):
# Registering user commands
@@ -30,4 +30,5 @@ async def register_commands(app: Client):
for command in configGet("commands_admin"):
commands_admin_list.append(BotCommand(command, locale(command, "commands_admin", locale=configGet("locale"))))
await app.set_bot_commands(commands_admin_list, scope=BotCommandScopeChat(chat_id=configGet("admin")))
for admin in app.admins:
await app.set_bot_commands(commands_admin_list, scope=BotCommandScopeChat(chat_id=admin))

View File

@@ -16,7 +16,7 @@ with open(getcwd()+path.sep+"config.json", "r", encoding='utf8') as file:
file.close()
# Check latest log size
def checkSize(debug=False):
def checkSize(debug=False) -> None:
global log_folder
@@ -39,7 +39,7 @@ def checkSize(debug=False):
pass
# Append string to log
def logAppend(message, debug=False):
def logAppend(message, debug=False) -> None:
global log_folder
@@ -56,7 +56,7 @@ def logAppend(message, debug=False):
log.close()
# Print to stdout and then to log
def logWrite(message, debug=False):
def logWrite(message, debug=False) -> None:
# save to log file and rotation is to be done
logAppend(f'{message}', debug=debug)
print(f"{message}", flush=True)

View File

@@ -1,5 +1,6 @@
from datetime import datetime, timedelta
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from pytimeparse.timeparse import timeparse
from modules.utils import configGet
from modules.sender import send_content
from modules.commands_register import register_commands
@@ -8,10 +9,11 @@ from modules.app import app
scheduler = AsyncIOScheduler()
if configGet("post", "mode"):
# for entry in configGet("time", "posting"):
# dt_obj = datetime.strptime(entry, "%H:%M")
# Is only used for debug now!
scheduler.add_job(send_content, "interval", seconds=30, args=[app])
# scheduler.add_job(send_content, "cron", hour=dt_obj.hour, minute=dt_obj.minute, args=[app])
if configGet("use_interval", "posting"):
scheduler.add_job(send_content, "interval", seconds=timeparse(configGet("interval", "posting")), args=[app])
else:
for entry in configGet("time", "posting"):
dt_obj = datetime.strptime(entry, "%H:%M")
scheduler.add_job(send_content, "cron", hour=dt_obj.hour, minute=dt_obj.minute, args=[app])
scheduler.add_job(register_commands, "date", run_date=datetime.now()+timedelta(seconds=10), args=[app])

View File

@@ -1,11 +1,11 @@
from datetime import datetime, timezone
from datetime import datetime
from os import makedirs, path
from shutil import copyfileobj, rmtree
from traceback import format_exc
from uuid import uuid4
from PIL import Image
from bson import ObjectId
from pyrogram.client import Client
from classes.poster_client import PosterClient
from requests import get
from modules.api_client import authorize, move_pic, random_pic
@@ -14,14 +14,14 @@ from modules.logger import logWrite
from modules.utils import configGet, locale
async def send_content(app: Client):
async def send_content(app: PosterClient) -> None:
try:
try:
token = await authorize()
except ValueError:
await app.send_message(configGet("admin"), locale("api_creds_invalid", "message", locale=configGet("locale")))
await app.send_message(app.owner, locale("api_creds_invalid", "message", locale=configGet("locale")))
return
try:
@@ -29,11 +29,11 @@ async def send_content(app: Client):
except KeyError:
logWrite(locale("post_empty", "console", locale=configGet("locale")))
if configGet("error", "reports"):
await app.send_message(configGet("admin"), locale("api_queue_empty", "message", locale=configGet("locale")))
await app.send_message(app.owner, locale("api_queue_empty", "message", locale=configGet("locale")))
return
except ValueError:
if configGet("error", "reports"):
await app.send_message(configGet("admin"), locale("api_queue_error", "message", locale=configGet("locale")))
await app.send_message(app.owner, locale("api_queue_error", "message", locale=configGet("locale")))
return
response = get(f'{configGet("address", "posting", "api")}/photos/{pic[0]}', headers={"Authorization": f"Bearer {token}"}, stream=True)
@@ -41,7 +41,7 @@ async def send_content(app: Client):
if response.status_code != 200:
logWrite(locale("post_invalid_pic", "console", locale=configGet("locale")).format(str(response.json())))
if configGet("error", "reports"):
await app.send_message(configGet("admin"), locale("post_invalid_pic", "message", locale=configGet("locale")).format(response.json()))
await app.send_message(app.owner, locale("post_invalid_pic", "message", locale=configGet("locale")).format(response.json()))
tmp_dir = str(uuid4())
@@ -52,12 +52,28 @@ async def send_content(app: Client):
with open(path.join(configGet("tmp", "locations"), tmp_path), 'wb') as out_file:
copyfileobj(response.raw, out_file)
logWrite(f'Candidate {pic[1]} ({pic[0]}) is {path.getsize(path.join(configGet("tmp", "locations"), tmp_path))} bytes big', debug=True)
if path.getsize(path.join(configGet("tmp", "locations"), tmp_path)) > 5242880:
image = Image.open(path.join(configGet("tmp", "locations"), tmp_path))
width, height = image.size
image = image.resize((int(width/2), int(height/2)), Image.ANTIALIAS)
if tmp_path.lower().endswith(".jpeg") or tmp_path.lower().endswith(".jpg"):
image.save(path.join(configGet("tmp", "locations"), tmp_path), "JPEG", optimize=True, quality=50)
elif tmp_path.lower().endswith(".png"):
image.save(path.join(configGet("tmp", "locations"), tmp_path), "PNG", optimize=True, compress_level=8)
image.close()
if path.getsize(path.join(configGet("tmp", "locations"), tmp_path)) > 5242880:
rmtree(path.join(configGet("tmp", "locations"), tmp_dir), ignore_errors=True)
raise BytesWarning
del response
submitted_caption = col_submitted.find_one( {"image": ObjectId(pic[0])} )
submitted = col_submitted.find_one({"temp.file": pic[1]})
if submitted_caption is not None:
caption = submitted_caption["caption"].strip()
if submitted is not None and submitted["caption"] is not None:
caption = submitted["caption"].strip()
else:
caption = ""
@@ -74,17 +90,17 @@ async def send_content(app: Client):
except Exception as exp:
logWrite(f"Could not send image {pic[1]} ({pic[0]}) due to {exp}")
if configGet("error", "reports"):
await app.send_message(configGet("admin"), locale("post_exception", "message", locale=configGet("locale")).format(exp, format_exc()))
await app.send_message(app.owner, locale("post_exception", "message", locale=configGet("locale")).format(exp, format_exc()))
# rmtree(path.join(configGet("tmp", "locations"), tmp_dir), ignore_errors=True)
return
col_sent.insert_one(
{
"date": datetime.now(tz=timezone.utc),
"date": datetime.now(),
"image": pic[0],
"filename": pic[1],
"channel": configGet("channel", "posting"),
"caption": None if submitted_caption is None else submitted_caption["caption"].strip()
"caption": None if (submitted is None or submitted["caption"] is None) else submitted["caption"].strip()
}
)
@@ -97,138 +113,8 @@ async def send_content(app: Client):
except Exception as exp:
logWrite(locale("post_exception", "console", locale=configGet("locale")).format(str(exp), format_exc()))
if configGet("error", "reports"):
await app.send_message(configGet("admin"), locale("post_exception", "message", locale=configGet("locale")).format(exp, format_exc()))
# async def send_content_old(app: Client):
# # Send post to channel
# try:
# index = jsonLoad(configGet("index", "locations"))
# if configGet("api_based", "mode"):
# try:
# pic = random_pic()
# except:
# logWrite(locale("post_empty", "console", locale=configGet("locale")))
# if configGet("error", "reports"):
# await app.send_message(configGet("admin"), locale("post_empty", "message", locale=configGet("locale")))
# return
# token = authorize()
# response = get(f'{configGet("address", "posting", "api")}/photos/{pic[0]}', headers={"Authorization": f"Bearer {token}"}, stream=True)
# with open(configGet("tmp", "locations")+sep+pic[0]+".jpg", 'wb') as out_file:
# copyfileobj(response.raw, out_file)
# del response
# candidate = configGet("tmp", "locations")+sep+pic[0]+".jpg"
# candidate_file = pic[1]
# ext_type = "photo"
# if not configGet("api_based", "mode"):
# list_queue = listdir(configGet("queue", "locations"))
# for file in list_queue:
# if not file in index["sent"]:
# ext_match = False
# for ext in configGet("photo", "posting", "extensions"):
# if file.endswith(ext):
# ext_match = True
# ext_type = "photo"
# break
# for ext in configGet("video", "posting", "extensions"):
# if file.endswith(ext):
# ext_match = True
# ext_type = "video"
# break
# if not ext_match:
# list_queue.remove(file)
# else:
# list_queue.remove(file)
# if len(list_queue) > 0:
# candidate_file = choice(list_queue)
# candidate = configGet("queue", "locations")+sep+candidate_file
# else:
# logWrite(locale("post_empty", "console", locale=configGet("locale")))
# if configGet("error", "reports"):
# await app.send_message(configGet("admin"), locale("post_empty", "message", locale=configGet("locale")))
# return
# if candidate_file in index["captions"]:
# caption = index["captions"][candidate_file]
# else:
# caption = ""
# if configGet("enabled", "caption"):
# if configGet("link", "caption") != None:
# caption = f"{caption}\n\n[{configGet('text', 'caption')}]({configGet('link', 'caption')})"
# else:
# caption = f"{caption}\n\n{configGet('text', 'caption')}"
# else:
# caption = caption
# if ext_type == "photo":
# if configGet("enabled", "caption"):
# if configGet("link", "caption") != None:
# sent = await app.send_photo(configGet("channel", "posting"), candidate, caption=caption, disable_notification=configGet("silent", "posting"))
# else:
# sent = await app.send_photo(configGet("channel", "posting"), candidate, caption=caption, disable_notification=configGet("silent", "posting"))
# else:
# sent = await app.send_photo(configGet("channel", "posting"), candidate, caption=caption, disable_notification=configGet("silent", "posting"))
# elif ext_type == "video":
# if configGet("enabled", "caption"):
# if configGet("link", "caption") != None:
# sent = await app.send_video(configGet("channel", "posting"), candidate, caption=caption, disable_notification=configGet("silent", "posting"))
# else:
# sent = await app.send_video(configGet("channel", "posting"), candidate, caption=caption, disable_notification=configGet("silent", "posting"))
# else:
# sent = await app.send_video(configGet("channel", "posting"), candidate, caption=caption, disable_notification=configGet("silent", "posting"))
# else:
# return
# if configGet("api_based", "mode"):
# remove(configGet("tmp", "locations")+sep+pic[0]+".jpg")
# move_pic(pic[0])
# index["sent"].append(candidate_file)
# index["last_id"] = sent.id
# jsonSave(index, configGet("index", "locations"))
# if configGet("move_sent", "posting"):
# move(candidate, configGet("sent", "locations")+sep+candidate_file)
# logWrite(locale("post_sent", "console", locale=configGet("locale")).format(candidate, ext_type, str(configGet("channel", "posting")), caption.replace("\n", "%n"), str(configGet("silent", "posting"))))
# if configGet("sent", "reports"):
# await app.send_message(configGet("admin"), f"Posted `{candidate_file}`", disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup([
# [InlineKeyboardButton(locale("post_view", "button", locale=configGet("locale")), url=sent.link)]
# ]))
# except Exception as exp:
# logWrite(locale("post_exception", "console", locale=configGet("locale")).format(str(exp), format_exc()))
# if configGet("error", "reports"):
# await app.send_message(configGet("admin"), locale("post_exception", "message", locale=configGet("locale")).format(exp, format_exc()))
# pass
# Work in progress
# Check last posts forwards
# check_forwards(app)
await app.send_message(app.owner, locale("post_exception", "message", locale=configGet("locale")).format(exp, format_exc()))
try:
rmtree(path.join(configGet("tmp", "locations"), tmp_dir), ignore_errors=True)
except:
pass

View File

@@ -1,27 +0,0 @@
from datetime import datetime, timezone
from modules.utils import configGet
from modules.database import col_users, col_banned
from pyrogram.types.user_and_chats import User
def subLimit(user: User) -> None:
if col_users.find_one_and_update({"user": user.id}, {"$set": {"cooldown": datetime.now(tz=timezone.utc)}}) is None:
col_users.insert_one({"user": user.id, "cooldown": datetime.now(tz=timezone.utc)})
def subLimited(user: User) -> bool:
if user.id == configGet("admin"):
return False
else:
db_record = col_users.find_one({"user": user.id})
if db_record is None:
return False
return True if (datetime.now(tz=timezone.utc) - db_record["cooldown"]).total_seconds() < configGet("timeout", "submission") else False
def subBlocked(user: User) -> bool:
return False if col_banned.find_one({"user": user.id}) is None else True
def subBlock(user: User) -> None:
if col_banned.find_one({"user": user.id}) is None:
col_banned.insert_one({"user": user.id, "date": datetime.now(tz=timezone.utc)})
def subUnblock(user: User) -> None:
col_banned.find_one_and_delete({"user": user.id})

View File

@@ -9,10 +9,11 @@ from sys import exit
from os import sep, kill
from os import name as osname
from traceback import print_exc
from typing import Any
from modules.logger import logWrite
def jsonLoad(filename):
def jsonLoad(filename: str) -> Any:
"""Loads arg1 as json and returns its contents"""
with open(filename, "r", encoding='utf8') as file:
try:
@@ -26,7 +27,7 @@ def jsonLoad(filename):
file.close()
return output
def jsonSave(contents, filename):
def jsonSave(contents: Any, filename: str) -> None:
"""Dumps dict/list arg1 to file arg2"""
try:
with open(filename, "w", encoding='utf8') as file:
@@ -108,10 +109,14 @@ except ModuleNotFoundError:
print(locale("deps_missing", "console", locale=configGet("locale")), flush=True)
exit()
def killProc(pid):
def killProc(pid: int) -> None:
"""Kill process by its PID. Meant to be used to kill the main process of bot itself.
### Args:
* pid (`int`): PID of the target
"""
if osname == "posix":
from signal import SIGKILL
kill(pid, SIGKILL)
else:
p = Process(pid)
p.kill()
Process(pid).kill()

View File

@@ -1,11 +1,11 @@
from modules.app import app
from pyrogram import filters
from pyrogram.types import CallbackQuery
from pyrogram.client import Client
from classes.poster_client import PosterClient
from modules.utils import locale
# Callback empty ===============================================================================================================
@app.on_callback_query(filters.regex("nothing"))
async def callback_query_nothing(app: Client, clb: CallbackQuery):
await clb.answer(text=locale("nothing", "callback", locale=clb.from_user))
async def callback_query_nothing(app: PosterClient, clb: CallbackQuery):
await clb.answer(text=locale("nothing", "callback", locale=clb.from_user.language_code))
# ==============================================================================================================================

View File

@@ -1,116 +1,115 @@
from os import path, sep
from pathlib import Path
from os import path
from shutil import rmtree
from pyrogram import filters
from pyrogram.client import Client
from pyrogram.types import CallbackQuery
from pyrogram.types import CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
from classes.exceptions import SubmissionDuplicatesError, SubmissionUnavailableError
from classes.poster_client import PosterClient
from classes.user import PosterUser
from modules.api_client import upload_pic
from modules.app import app
from modules.submissions import subBlock, subUnblock
from modules.utils import configGet, jsonLoad, jsonSave, locale
from modules.utils import configGet, locale
from modules.database import col_submitted
from bson import ObjectId
@app.on_callback_query(filters.regex("sub_yes_[\s\S]*"))
async def callback_query_yes(app: Client, clb: CallbackQuery):
async def callback_query_yes(app: PosterClient, clb: CallbackQuery):
fullclb = clb.data.split("_")
fullclb = str(clb.data).split("_")
user_locale = clb.from_user.language_code
# Check if submission is in DB and really exists
# Upload the file to the API server
# Modify submission in DB to state that it's accepted (or so called "done")
# Change keyboard to a completed variant
# Send replies to both user and admin about accepting the application
db_entry = col_submitted.find_one({"_id": ObjectId(fullclb[2])})
if db_entry is None:
await clb.answer(text=locale("sub_msg_unavail", "message", locale=user_locale), show_alert=True)
return
else:
if db_entry["tmp"]["uuid"] is not None:
if not path.exists(path.join(configGet("data", "locations"), "submissions", db_entry["tmp"]["uuid"], db_entry["tmp"]["file"])):
await clb.answer(text=locale("sub_msg_unavail", "message", locale=user_locale), show_alert=True)
return
else:
try:
submission = await app.get_messages(db_entry["user"], db_entry["telegram"]["msg_id"])
except:
await clb.answer(text=locale("sub_msg_unavail", "message", locale=user_locale), show_alert=True)
return
try:
if configGet("api_based", "mode") is True:
media = await app.download_media(submission, file_name=configGet("tmp", "locations")+sep)
upload = upload_pic(media)
if upload[0] is False:
await clb.answer(text=locale("sub_media_failed", "message", locale=user_locale), show_alert=True)
elif len(upload[1]) > 0:
await clb.answer(text=locale("sub_media_duplicates", "message", locale=user_locale))
await clb.message.reply_text(locale("sub_media_duplicates_list", "message", locale=user_locale).format("\n".join(upload[1])))
else:
if clb.data.endswith("_caption"):
index = jsonLoad(configGet("index", "locations"))
index["captions"][Path(media).name] = submission.caption
jsonSave(index, configGet("index", "locations"))
else:
media = await app.download_media(submission, file_name=configGet("queue", "locations")+sep)
if clb.data.endswith("_caption"):
index = jsonLoad(configGet("index", "locations"))
index["captions"][Path(media).name] = submission.caption
jsonSave(index, configGet("index", "locations"))
except:
await clb.answer(text=locale("sub_media_unavail", "message", locale=user_locale), show_alert=True)
submission = await app.submit_photo(fullclb[2])
except SubmissionUnavailableError:
await clb.answer(text=locale("sub_msg_unavail", "callback", locale=user_locale), show_alert=True)
return
await submission.reply_text(locale("sub_yes", "message", locale=submission.from_user.language_code), quote=True)
except SubmissionDuplicatesError as exp:
await clb.answer(text=locale("sub_duplicates_found", "callback", locale=user_locale), show_alert=True)
await clb.message.reply_text(locale("sub_media_duplicates_list", "message", locale=user_locale).format("\n".join(exp.duplicates)), quote=True)
return
if submission is not None:
await submission.reply_text(locale("sub_yes", "message", locale=submission.from_user.language_code), quote=True)
elif db_entry is not None:
await app.send_message(db_entry["user"], locale("sub_yes", "message"))
await clb.answer(text=locale("sub_yes", "callback", locale=user_locale).format(fullclb[2]), show_alert=True)
# edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
# await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button", locale=user_locale)), callback_data="nothing")], clb.message.reply_markup.inline_keyboard[1]] if len(clb.message.reply_markup.inline_keyboard) > 1 else [[InlineKeyboardButton(text=str(locale("accepted", "button", locale=user_locale)), callback_data="nothing")]]
await clb.message.edit_reply_markup(reply_markup=InlineKeyboardMarkup(edited_markup))
# try:
# if configGet("api_based", "mode") is True:
# media = await app.download_media(submission, file_name=configGet("tmp", "locations")+sep)
# upload = upload_pic(media)
# if upload[0] is False:
# await clb.answer(text=locale("sub_media_failed", "message", locale=user_locale), show_alert=True)
# elif len(upload[1]) > 0:
# await clb.answer(text=locale("sub_media_duplicates", "message", locale=user_locale))
# await clb.message.reply_text(locale("sub_media_duplicates_list", "message", locale=user_locale).format("\n • ".join(upload[1])))
# else:
# if clb.data.endswith("_caption"):
# index = jsonLoad(configGet("index", "locations"))
# index["captions"][Path(media).name] = submission.caption
# jsonSave(index, configGet("index", "locations"))
# else:
# media = await app.download_media(submission, file_name=configGet("queue", "locations")+sep)
# if clb.data.endswith("_caption"):
# index = jsonLoad(configGet("index", "locations"))
# index["captions"][Path(media).name] = submission.caption
# jsonSave(index, configGet("index", "locations"))
# except:
# await clb.answer(text=locale("sub_media_unavail", "message", locale=user_locale), show_alert=True)
# return
@app.on_callback_query(filters.regex("sub_no_[\s\S]*"))
async def callback_query_no(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
async def callback_query_no(app: PosterClient, clb: CallbackQuery):
fullclb = str(clb.data).split("_")
user_locale = clb.from_user.language_code
db_entry = col_submitted.find_one_and_delete({"_id": ObjectId(fullclb[2])})
if db_entry["temp"]["uuid"] is not None:
if path.exists(path.join(configGet("data", "locations"), "submissions", db_entry["temp"]["uuid"])):
rmtree(path.join(configGet("data", "locations"), "submissions", db_entry["temp"]["uuid"]), ignore_errors=True)
try:
submission = await app.get_messages(int(fullclb[2]), int(fullclb[3]))
submission = await app.get_messages(db_entry["user"], db_entry["telegram"]["msg_id"])
except:
await clb.answer(text=locale("sub_msg_unavail", "message", locale=user_locale), show_alert=True)
return
await submission.reply_text(locale("sub_no", "message", locale=submission.from_user.language_code), quote=True)
await clb.answer(text=locale("sub_no", "callback", locale=user_locale).format(fullclb[2]), show_alert=True)
# edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
# await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
edited_markup = [[InlineKeyboardButton(text=str(locale("declined", "button", locale=user_locale)), callback_data="nothing")], clb.message.reply_markup.inline_keyboard[1]] if len(clb.message.reply_markup.inline_keyboard) > 1 else [[InlineKeyboardButton(text=str(locale("declined", "button", locale=user_locale)), callback_data="nothing")]]
await clb.message.edit_reply_markup(reply_markup=InlineKeyboardMarkup(edited_markup))
@app.on_callback_query(filters.regex("sub_block_[\s\S]*"))
async def callback_query_block(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
async def callback_query_block(app: PosterClient, clb: CallbackQuery):
fullclb = str(clb.data).split("_")
user_locale = clb.from_user.language_code
await app.send_message(int(fullclb[2]), locale("sub_msg_unavail", "message", locale=configGet("locale")))
subBlock(int(fullclb[2]))
await app.send_message(int(fullclb[2]), locale("sub_blocked", "message", locale=configGet("locale")))
PosterUser(int(fullclb[2])).block()
await clb.answer(text=locale("sub_block", "callback", locale=user_locale).format(fullclb[2]), show_alert=True)
# edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
# await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
edited_markup = [clb.message.reply_markup.inline_keyboard[0], [InlineKeyboardButton(text=str(locale("sub_unblock", "button", locale=user_locale)), callback_data=f"sub_unblock_{fullclb[2]}")]]
await clb.message.edit_reply_markup(reply_markup=InlineKeyboardMarkup(edited_markup))
@app.on_callback_query(filters.regex("sub_unblock_[\s\S]*"))
async def callback_query_unblock(app: Client, clb: CallbackQuery):
fullclb = clb.data.split("_")
async def callback_query_unblock(app: PosterClient, clb: CallbackQuery):
fullclb = str(clb.data).split("_")
user_locale = clb.from_user.language_code
await app.send_message(int(fullclb[2]), locale("sub_msg_unavail", "message", locale=configGet("locale")))
subUnblock(int(fullclb[2]))
await app.send_message(int(fullclb[2]), locale("sub_unblocked", "message", locale=configGet("locale")))
PosterUser(int(fullclb[2])).unblock()
await clb.answer(text=locale("sub_unblock", "callback", locale=user_locale).format(fullclb[2]), show_alert=True)
# edited_markup = [[InlineKeyboardButton(text=str(locale("accepted", "button")), callback_data="nothing")]]
# await clb.message.edit(text=clb.message.text, reply_markup=InlineKeyboardMarkup(edited_markup))
edited_markup = [clb.message.reply_markup.inline_keyboard[0], [InlineKeyboardButton(text=str(locale("sub_block", "button", locale=user_locale)), callback_data=f"sub_block_{fullclb[2]}")]]
await clb.message.edit_reply_markup(reply_markup=InlineKeyboardMarkup(edited_markup))

View File

@@ -1,7 +1,7 @@
from os import getpid
from pyrogram import filters
from pyrogram.client import Client
from classes.poster_client import PosterClient
from pyrogram.types import Message
from modules.app import app
@@ -10,9 +10,9 @@ from modules.utils import configGet, killProc, locale
@app.on_message(~ filters.scheduled & filters.command(["kill", "die", "reboot"], prefixes=["", "/"]))
async def cmd_kill(app: Client, msg: Message):
async def cmd_kill(app: PosterClient, msg: Message):
if msg.from_user.id == configGet("admin"):
if msg.from_user.id in app.admins:
pid = getpid()
logWrite(locale("shutdown", "console", locale=configGet("locale")).format(str(pid)))
await msg.reply_text(locale("shutdown", "message", locale=configGet("locale")).format(str(pid)))

View File

@@ -1,18 +1,18 @@
from pyrogram import filters
from pyrogram.client import Client
from pyrogram.types import Message
from modules.app import app
from modules.submissions import subBlocked
from modules.utils import configGet, jsonLoad, locale
from modules.utils import locale
from classes.user import PosterUser
from classes.poster_client import PosterClient
@app.on_message(~ filters.scheduled & filters.command(["start"], prefixes="/"))
async def cmd_start(app: Client, msg: Message):
if subBlocked(msg.from_user) is False:
async def cmd_start(app: PosterClient, msg: Message):
if PosterUser(msg.from_user.id).is_blocked() is False:
await msg.reply_text(locale("start", "message", locale=msg.from_user.language_code))
@app.on_message(~ filters.scheduled & filters.command(["rules", "help"], prefixes="/"))
async def cmd_rules(app: Client, msg: Message):
if subBlocked(msg.from_user) is False:
async def cmd_rules(app: PosterClient, msg: Message):
if PosterUser(msg.from_user.id).is_blocked() is False:
await msg.reply_text(locale("rules", "message", locale=msg.from_user.language_code))

View File

@@ -0,0 +1,19 @@
from pyrogram import filters
from pyrogram.types import Message
from classes.poster_client import PosterClient
from modules.app import app
@app.on_message(~ filters.scheduled & filters.command(["import"], prefixes=["", "/"]))
async def cmd_import(app: PosterClient, msg: Message):
if msg.from_user.id in app.admins:
pass
@app.on_message(~ filters.scheduled & filters.command(["export"], prefixes=["", "/"]))
async def cmd_export(app: PosterClient, msg: Message):
if msg.from_user.id in app.admins:
pass

View File

@@ -1,162 +1,190 @@
from datetime import datetime, timezone
from datetime import datetime
from os import makedirs, path, sep
from traceback import format_exc
from uuid import uuid4
from pyrogram import filters
from pyrogram.client import Client
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
from pyrogram.enums.chat_action import ChatAction
from classes.exceptions import SubmissionDuplicatesError
from classes.poster_client import PosterClient
from classes.user import PosterUser
from modules.app import app
from modules.database import col_banned, col_submitted
from modules.logger import logWrite
from modules.submissions import subLimit, subLimited
from modules.utils import configGet, locale
from classes.enums.submission_types import SubmissionType
@app.on_message(~ filters.scheduled & filters.photo | filters.video | filters.animation | filters.document)
async def get_submission(_: Client, msg: Message):
@app.on_message(~filters.scheduled & filters.private & filters.photo | filters.video | filters.animation | filters.document)
async def get_submission(app: PosterClient, msg: Message):
locale("sub_wip", "message", locale=msg.from_user.language_code)
try:
# try:
if col_banned.find_one( {"user": msg.from_user.id} ) is not None:
return
await app.send_chat_action(msg.chat.id, ChatAction.TYPING)
# if col_banned.find_one( {"user": msg.from_user.id} ) is not None:
# return
user_locale = msg.from_user.language_code
save_tmp = True
contents = None
# user_locale = msg.from_user.language_code
# save_tmp = True
# contents = None
if PosterUser(msg.from_user.id).is_limited():
await msg.reply_text(locale("sub_cooldown", "message", locale=user_locale).format(str(configGet("timeout", "submission"))))
return
# if subLimited(msg.from_user):
# await msg.reply_text(locale("sub_cooldown", "message", locale=user_locale).format(str(configGet("timeout", "submission"))))
# return
if msg.document is not None:
if msg.document.mime_type not in configGet("mime_types", "submission"):
await msg.reply_text(locale("mime_not_allowed", "message", locale=user_locale), quote=True)
return
if msg.document.file_size > configGet("file_size", "submission"):
await msg.reply_text(locale("document_too_large", "message", locale=user_locale).format(str(configGet("file_size", "submission")/1024/1024)), quote=True)
return
if msg.document.file_size > configGet("tmp_size", "submission"):
save_tmp = False
contents = msg.document.file_id, SubmissionType.DOCUMENT #, msg.document.file_name
# if msg.document is not None:
# if msg.document.mime_type not in configGet("mime_types", "submission"):
# await msg.reply_text(locale("mime_not_allowed", "message", locale=user_locale), quote=True)
# return
# if msg.document.file_size > configGet("file_size", "submission"):
# await msg.reply_text(locale("document_too_large", "message", locale=user_locale).format(str(configGet("file_size", "submission")/1024/1024)), quote=True)
# return
# if msg.document.file_size > configGet("tmp_size", "submission"):
# save_tmp = False
# contents = msg.document.file_id, SubmissionType.DOCUMENT #, msg.document.file_name
if msg.video is not None:
if msg.video.file_size > configGet("file_size", "submission"):
await msg.reply_text(locale("document_too_large", "message", locale=user_locale).format(str(configGet("file_size", "submission")/1024/1024)), quote=True)
return
if msg.video.file_size > configGet("tmp_size", "submission"):
save_tmp = False
contents = msg.video.file_id, SubmissionType.VIDEO #, msg.video.file_name
# if msg.video is not None:
# if msg.video.file_size > configGet("file_size", "submission"):
# await msg.reply_text(locale("document_too_large", "message", locale=user_locale).format(str(configGet("file_size", "submission")/1024/1024)), quote=True)
# return
# if msg.video.file_size > configGet("tmp_size", "submission"):
# save_tmp = False
# contents = msg.video.file_id, SubmissionType.VIDEO #, msg.video.file_name
if msg.animation is not None:
if msg.animation.file_size > configGet("file_size", "submission"):
await msg.reply_text(locale("document_too_large", "message", locale=user_locale).format(str(configGet("file_size", "submission")/1024/1024)), quote=True)
return
if msg.animation.file_size > configGet("tmp_size", "submission"):
save_tmp = False
contents = msg.animation.file_id, SubmissionType.ANIMATION #, msg.animation.file_name
# if msg.animation is not None:
# if msg.animation.file_size > configGet("file_size", "submission"):
# await msg.reply_text(locale("document_too_large", "message", locale=user_locale).format(str(configGet("file_size", "submission")/1024/1024)), quote=True)
# return
# if msg.animation.file_size > configGet("tmp_size", "submission"):
# save_tmp = False
# contents = msg.animation.file_id, SubmissionType.ANIMATION #, msg.animation.file_name
if msg.photo is not None:
contents = msg.photo.file_id, SubmissionType.PHOTO #, "please_generate"
# if msg.photo is not None:
# contents = msg.photo.file_id, SubmissionType.PHOTO #, "please_generate"
if save_tmp is not None:
# if save_tmp is not None:
if contents is None:
return
# if contents is None:
# return
# tmp_id = str(uuid4())
# # filename = tmp_id if contents[1] == "please_generate" else contents[1]
# makedirs(path.join(configGet("data", "locations"), "submissions", tmp_id), exist_ok=True)
# downloaded = await app.download_media(msg, path.join(configGet("data", "locations"), "submissions", tmp_id)+sep)
# inserted = col_submitted.insert_one(
# {
# "user": msg.from_user.id,
# "date": datetime.now(tz=timezone.utc),
# "done": False,
# "type": contents[1].value,
# "temp": {
# "uuid": tmp_id,
# "file": path.basename(str(downloaded))
# },
# "telegram": {
# "msg_id": msg.id,
# "file_id": contents[0]
# },
# "caption": str(msg.caption) if msg.caption is not None else None
# }
# )
tmp_id = str(uuid4())
# filename = tmp_id if contents[1] == "please_generate" else contents[1]
makedirs(path.join(configGet("data", "locations"), "submissions", tmp_id), exist_ok=True)
downloaded = await app.download_media(msg, path.join(configGet("data", "locations"), "submissions", tmp_id)+sep)
inserted = col_submitted.insert_one(
{
"user": msg.from_user.id,
"date": datetime.now(),
"done": False,
"type": contents[1].value,
"temp": {
"uuid": tmp_id,
"file": path.basename(str(downloaded))
},
"telegram": {
"msg_id": msg.id,
"file_id": contents[0]
},
"caption": str(msg.caption) if msg.caption is not None else None
}
)
# else:
else:
# if contents is None:
# return
if contents is None:
return
# inserted = col_submitted.insert_one(
# {
# "user": msg.from_user.id,
# "date": datetime.now(tz=timezone.utc),
# "done": False,
# "type": contents[1].value,
# "temp": {
# "uuid": None,
# "file": None
# },
# "telegram": {
# "msg_id": msg.id,
# "file_id": contents[0]
# },
# "caption": str(msg.caption) if msg.caption is not None else None
# }
# )
inserted = col_submitted.insert_one(
{
"user": msg.from_user.id,
"date": datetime.now(),
"done": False,
"type": contents[1].value,
"temp": {
"uuid": None,
"file": None
},
"telegram": {
"msg_id": msg.id,
"file_id": contents[0]
},
"caption": str(msg.caption) if msg.caption is not None else None
}
)
# buttons = [
# [
# InlineKeyboardButton(text=locale("sub_yes", "button", locale=configGet("locale")), callback_data=f"sub_yes_{str(inserted.inserted_id)}")
# ]
# ]
buttons = [
[
InlineKeyboardButton(text=locale("sub_yes", "button", locale=configGet("locale")), callback_data=f"sub_yes_{str(inserted.inserted_id)}")
]
]
# if msg.caption is not None:
# caption = str(msg.caption)
# buttons[0].append(
# InlineKeyboardButton(text=locale("sub_yes_caption", "button", locale=configGet("locale")), callback_data=f"sub_yes_{str(inserted.inserted_id)}_caption")
# )
# buttons[0].append(
# InlineKeyboardButton(text=locale("sub_no", "button", locale=configGet("locale")), callback_data=f"sub_no_{str(inserted.inserted_id)}")
# )
# else:
# caption = ""
# buttons[0].append(
# InlineKeyboardButton(text=locale("sub_no", "button", locale=configGet("locale")), callback_data=f"sub_no_{str(inserted.inserted_id)}")
# )
if msg.caption is not None:
caption = str(msg.caption)
buttons[0].append(
InlineKeyboardButton(text=locale("sub_yes_caption", "button", locale=configGet("locale")), callback_data=f"sub_yes_{str(inserted.inserted_id)}_caption")
)
buttons[0].append(
InlineKeyboardButton(text=locale("sub_no", "button", locale=configGet("locale")), callback_data=f"sub_no_{str(inserted.inserted_id)}")
)
else:
caption = ""
buttons[0].append(
InlineKeyboardButton(text=locale("sub_no", "button", locale=configGet("locale")), callback_data=f"sub_no_{str(inserted.inserted_id)}")
)
# caption += locale("sub_by", "message", locale=locale(configGet("locale")))
caption += locale("sub_by", "message", locale=locale(configGet("locale")))
# if msg.from_user.first_name is not None:
# caption += f" {msg.from_user.first_name}"
# if msg.from_user.last_name is not None:
# caption += f" {msg.from_user.last_name}"
# if msg.from_user.username is not None:
# caption += f" (@{msg.from_user.username})"
# if msg.from_user.phone_number is not None:
# caption += f" ({msg.from_user.phone_number})"
if msg.from_user.first_name is not None:
caption += f" {msg.from_user.first_name}"
if msg.from_user.last_name is not None:
caption += f" {msg.from_user.last_name}"
if msg.from_user.username is not None:
caption += f" (@{msg.from_user.username})"
if msg.from_user.phone_number is not None:
caption += f" ({msg.from_user.phone_number})"
# if msg.from_user.id != configGet("admin"):
# buttons += [
# [
# InlineKeyboardButton(text=locale("sub_block", "button", locale=configGet("locale")), callback_data=f"sub_block_{msg.from_user.id}")
# ]
# # [
# # InlineKeyboardButton(text=locale("sub_unblock", "button", locale=configGet("locale")), callback_data=f"sub_unblock_{msg.from_user.id}")
# # ]
# ]
if msg.from_user.id in app.admins and configGet("admins", "submission", "require_confirmation") is False:
try:
await app.submit_photo(str(inserted.inserted_id))
await msg.reply_text(locale("sub_yes_auto", "message", locale=user_locale), quote=True)
await msg.copy(app.owner, caption=caption, disable_notification=True)
return
except SubmissionDuplicatesError as exp:
await msg.reply_text(locale("sub_media_duplicates_list", "message", locale=user_locale).format("\n".join(exp.duplicates)), quote=True)
return
except Exception as exp:
await msg.reply_text(format_exc(), quote=True)
return
elif msg.from_user.id not in app.admins and configGet("users", "submission", "require_confirmation") is False:
try:
await app.submit_photo(str(inserted.inserted_id))
await msg.reply_text(locale("sub_yes_auto", "message", locale=user_locale), quote=True)
await msg.copy(app.owner, caption=caption)
return
except SubmissionDuplicatesError as exp:
await msg.reply_text(locale("sub_dup", "message", locale=user_locale), quote=True)
return
except Exception as exp:
await app.send_message(app.owner, locale("sub_error_admin", "message").format(msg.from_user.id, format_exc()))
await msg.reply_text("sub_error", quote=True)
return
# await msg.reply_text(locale("sub_sent", "message", locale=user_locale), quote=True)
# subLimit(msg.from_user)
if msg.from_user.id not in app.admins:
buttons += [
[
InlineKeyboardButton(text=locale("sub_block", "button", locale=configGet("locale")), callback_data=f"sub_block_{msg.from_user.id}")
]
]
# await msg.copy(configGet("admin"), caption=caption, reply_markup=InlineKeyboardMarkup(buttons))
PosterUser(msg.from_user.id).limit()
# except AttributeError:
# logWrite(f"from_user in function get_submission does not seem to contain id")
if msg.from_user.id != app.owner:
await msg.reply_text(locale("sub_sent", "message", locale=user_locale), quote=True)
await msg.copy(app.owner, caption=caption, reply_markup=InlineKeyboardMarkup(buttons))
except AttributeError:
logWrite(f"from_user in function get_submission does not seem to contain id")

View File

@@ -119,6 +119,7 @@ pid = getpid()
from plugins.commands.general import *
if configGet("submit", "mode"):
from plugins.callbacks.nothing import *
from plugins.callbacks.submission import *
from plugins.commands.mode_submit import *
from plugins.handlers.submission import *
@@ -174,7 +175,7 @@ if __name__ == "__main__":
app.start()
if configGet("startup", "reports"):
app.send_message(configGet("admin"), locale("startup", "message", locale=configGet("locale")).format(str(pid)))
app.send_message(app.owner, locale("startup", "message", locale=configGet("locale")).format(str(pid)))
if configGet("post", "mode"):
scheduler.start()
@@ -186,7 +187,7 @@ if __name__ == "__main__":
idle()
app.send_message(configGet("admin"), locale("shutdown", "message", locale=configGet("locale")).format(str(pid)))
app.send_message(app.owner, locale("shutdown", "message", locale=configGet("locale")).format(str(pid)))
logWrite(locale("shutdown", "console", locale=configGet("locale")).format(str(pid)))
killProc(pid)

View File

@@ -2,4 +2,6 @@ apscheduler~=3.10.0
pyrogram~=2.0.99
requests~=2.28.2
psutil~=5.9.4
pymongo~=4.3.3
pymongo~=4.3.3
pillow~=9.4.0
pytimeparse~=1.1.8