Compare commits

...

5 Commits

Author SHA1 Message Date
cf09017985 TMP: interval changes 2023-02-14 16:26:08 +01:00
7940cbe5a7 WIP: API usage as main 2023-02-14 16:25:56 +01:00
8e0fee4cb9 Added database support 2023-02-14 14:45:52 +01:00
08e03ba911 Moved handlers to another location 2023-02-14 11:38:54 +01:00
b589da5d8f Updated dependencies 2023-02-14 11:38:09 +01:00
15 changed files with 426 additions and 224 deletions

View File

@@ -9,6 +9,13 @@
"api_hash": "", "api_hash": "",
"bot_token": "" "bot_token": ""
}, },
"database": {
"user": null,
"password": null,
"host": "127.0.0.1",
"port": 27017,
"name": "tgposter"
},
"mode": { "mode": {
"post": true, "post": true,
"submit": true, "submit": true,

View File

@@ -24,9 +24,12 @@
"sub_media_duplicates_list": "It seems like following image has duplicates in API's Db.\n\nNext files marked as similar:\n • {0}", "sub_media_duplicates_list": "It seems like following image has duplicates in API's Db.\n\nNext files marked as similar:\n • {0}",
"document_too_large": "File you've sent is too large. Please submit files not bigger than {0} MB", "document_too_large": "File you've sent is too large. Please submit files not bigger than {0} MB",
"mime_not_allowed": "File type not allowed. Please, consider using one of these: {0}", "mime_not_allowed": "File type not allowed. Please, consider using one of these: {0}",
"post_exception": "Could not send content due to `{exp}`\n\nTraceback:\n```{0}```", "post_exception": "Could not send content due to `{0}`\n\nTraceback:\n```{1}```",
"post_empty": "Could not send content: `Queue folder is empty or contains only unsupported or already sent files.`", "post_invalid_pic": "__TO_BE_ADDED__",
"post_low": "Low amount of content: `There are only {0} files left in the queue.`" "api_queue_empty": "Could not send content: `Queue folder is empty or contains only unsupported or already sent files.`",
"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__"
}, },
"button": { "button": {
"sub_yes": "✅ Accept", "sub_yes": "✅ Accept",
@@ -52,8 +55,9 @@
"startup":"Starting with pid {0}", "startup":"Starting with pid {0}",
"keyboard_interrupt": "\nShutting down...", "keyboard_interrupt": "\nShutting down...",
"exception_occured": "Exception {0} happened on task execution", "exception_occured": "Exception {0} happened on task execution",
"post_sent": "Sent {0} of type {1} to {2} with caption {3} and silently {4}", "post_sent": "Sent {0} to {1} with caption {2} and silently {3}",
"post_exception": "Could not send content due to {0}. Traceback: {1}", "post_exception": "Could not send content due to {0}. Traceback: {1}",
"post_invalid_pic": "__TO_BE_ADDED__",
"post_empty": "Could not send content due to queue folder empty with allowed extensions", "post_empty": "Could not send content due to queue folder empty with allowed extensions",
"sub_mime_not_allowed": "Got submission from {0} but type of {1} which is not allowed", "sub_mime_not_allowed": "Got submission from {0} but type of {1} which is not allowed",
"sub_document_too_large": "Got submission from {0} but but file is too large ({1} > {2})", "sub_document_too_large": "Got submission from {0} but but file is too large ({1} > {2})",

View File

@@ -24,9 +24,12 @@
"sub_media_duplicates_list": "Здається, подане зображення має дублікати в базі даних.\n\nНаступні файли було відмічено як дуже схожі з поданням:\n • {0}", "sub_media_duplicates_list": "Здається, подане зображення має дублікати в базі даних.\n\nНаступні файли було відмічено як дуже схожі з поданням:\n • {0}",
"document_too_large": "Надісланий файл завеликий. Будь ласка, надсилайте файли не більше {0} Мб", "document_too_large": "Надісланий файл завеликий. Будь ласка, надсилайте файли не більше {0} Мб",
"mime_not_allowed": "Тип файлу не дозволений. Розгляньте можливість використання одного з цих: {0}", "mime_not_allowed": "Тип файлу не дозволений. Розгляньте можливість використання одного з цих: {0}",
"post_exception": "Не вдалося надіслати контент через `{exp}`\n\nTraceback:\n```{0}```", "post_exception": "Не вдалося надіслати контент через `{0}`\n\nTraceback:\n```{1}```",
"post_empty": "Не вдалося надіслати контент: `Папка черги порожня або містить лише непідтримувані або вже надіслані файли`.", "post_invalid_pic": "__TO_BE_ADDED__",
"post_low": "Мала кількість контенту: `Залишилось всього {0} файлів в черзі.`" "api_queue_empty": "Не вдалося надіслати контент: `Папка черги порожня або містить лише непідтримувані або вже надіслані файли`.",
"api_queue_error": "__TO_BE_ADDED__",
"post_low": "Мала кількість контенту: `Залишилось всього {0} файлів в черзі.`",
"api_creds_invalid": "__TO_BE_ADDED__"
}, },
"button": { "button": {
"sub_yes": "✅ Прийняти", "sub_yes": "✅ Прийняти",
@@ -52,8 +55,9 @@
"startup": "Запуск бота з підом {0}", "startup": "Запуск бота з підом {0}",
"keyboard_interrupt": "\nВимикаюсь...", "keyboard_interrupt": "\nВимикаюсь...",
"exception_occured": "Помилка {0} сталась під час виконання", "exception_occured": "Помилка {0} сталась під час виконання",
"post_sent": "Надіслано {0} типу {1} у {2} з підписом {3} та без звуку {4}", "post_sent": "Надіслано {0} у {1} з підписом {2} та без звуку {3}",
"post_exception": "Не вдалося надіслати контент через {0}. Traceback: {1}", "post_exception": "Не вдалося надіслати контент через {0}. Traceback: {1}",
"post_invalid_pic": "__TO_BE_ADDED__",
"post_empty": "Не вдалося надіслати контент через порожню папку черги з дозволеними розширеннями", "post_empty": "Не вдалося надіслати контент через порожню папку черги з дозволеними розширеннями",
"sub_mime_not_allowed": "Отримано подання від {0} але типу {1} який не є дозволеним", "sub_mime_not_allowed": "Отримано подання від {0} але типу {1} який не є дозволеним",
"sub_document_too_large": "Отримано подання від {0} але файл завеликий({1} > {2})", "sub_document_too_large": "Отримано подання від {0} але файл завеликий({1} > {2})",

View File

@@ -1,16 +1,21 @@
import asyncio
from base64 import b64decode, b64encode
from os import makedirs, path, sep from os import makedirs, path, sep
from base64 import b64encode, b64decode
from random import choice from random import choice
from typing import Tuple from typing import Tuple, Union
from requests import get, post, put, patch
from requests import get, patch, post
from modules.logger import logWrite
from modules.utils import configGet from modules.utils import configGet
def authorize() -> str:
async def authorize() -> str:
makedirs(configGet("cache", "locations"), exist_ok=True) makedirs(configGet("cache", "locations"), exist_ok=True)
if path.exists(configGet("cache", "locations")+sep+"api_access") is True: if path.exists(configGet("cache", "locations")+sep+"api_access") is True:
with open(configGet("cache", "locations")+sep+"api_access", "rb") as file: with open(configGet("cache", "locations")+sep+"api_access", "rb") as file:
token = b64decode(file.read()).decode("utf-8") token = b64decode(file.read()).decode("utf-8")
if "user" in get(configGet("address", "posting", "api")+"/users/me/", headers={"Authorization": f"Bearer {token}"}).json(): if get(configGet("address", "posting", "api")+"/users/me/", headers={"Authorization": f"Bearer {token}"}).status_code == 200:
return token return token
payload = { payload = {
"grant_type": "password", "grant_type": "password",
@@ -18,23 +23,35 @@ def authorize() -> str:
"username": configGet("username", "posting", "api"), "username": configGet("username", "posting", "api"),
"password": configGet("password", "posting", "api") "password": configGet("password", "posting", "api")
} }
response = post(configGet("address", "posting", "api")+"/token", data=payload).json() response = post(configGet("address", "posting", "api")+"/token", data=payload)
if response.status_code != 200:
logWrite(f'Incorrect API credentials! Could not login into "{configGet("address", "posting", "api")}" using login "{configGet("username", "posting", "api")}": HTTP {response.status_code}')
raise ValueError
with open(configGet("cache", "locations")+sep+"api_access", "wb") as file: with open(configGet("cache", "locations")+sep+"api_access", "wb") as file:
file.write(b64encode(response["access_token"].encode("utf-8"))) file.write(b64encode(response.json()["access_token"].encode("utf-8")))
return response["access_token"] return response.json()["access_token"]
def random_pic() -> Tuple[str, str]: async def random_pic(token: Union[str, None] = None) -> Tuple[str, str]:
"""Returns random image id and filename from the queue. """Returns random image id and filename from the queue.
### Returns: ### Returns:
* `Tuple[str, str]`: First value is an ID and the filename in the filesystem to be indexed. * `Tuple[str, str]`: First value is an ID and the filename in the filesystem to be indexed.
""" """
token = authorize() if token is None:
pic = choice(get(f'{configGet("address", "posting", "api")}/albums/{configGet("album", "posting", "api")}/photos?q=&page_size=100&caption=queue', headers={"Authorization": f"Bearer {token}"}).json()["results"]) token = await authorize()
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:
logWrite(f'Could not get photos from album {configGet("album", "posting", "api")}: HTTP {resp.status_code}')
logWrite(f'Could not get photos from "{configGet("address", "posting", "api")}/albums/{configGet("album", "posting", "api")}/photos?q=&page_size=100&caption=queue" using token "{token}": HTTP {resp.status_code}', debug=True)
raise ValueError
if len(resp.json()["results"]) == 0:
raise KeyError
pic = choice(resp.json()["results"])
return pic["id"], pic["filename"] return pic["id"], pic["filename"]
def upload_pic(filepath: str) -> bool: async def upload_pic(filepath: str) -> Tuple[bool, list]:
token = authorize() token = await authorize()
try: try:
pic_name = path.basename(filepath) pic_name = path.basename(filepath)
files = {'file': (pic_name, open(filepath, 'rb'), 'image/jpeg')} files = {'file': (pic_name, open(filepath, 'rb'), 'image/jpeg')}
@@ -48,8 +65,8 @@ def upload_pic(filepath: str) -> bool:
except: except:
return False, [] return False, []
def move_pic(id: str) -> bool: async def move_pic(id: str) -> bool:
token = authorize() token = await authorize()
try: try:
patch(f'{configGet("address", "posting", "api")}/photos/{id}?caption=sent', headers={"Authorization": f"Bearer {token}"}) patch(f'{configGet("address", "posting", "api")}/photos/{id}?caption=sent', headers={"Authorization": f"Bearer {token}"})
return True return True
@@ -57,4 +74,4 @@ def move_pic(id: str) -> bool:
return False return False
if __name__ == "__main__": if __name__ == "__main__":
print(authorize()) print(asyncio.run(authorize()))

36
modules/database.py Normal file
View File

@@ -0,0 +1,36 @@
"""Module that provides all database columns"""
from pymongo import MongoClient
from ujson import loads
with open("config.json", "r", encoding="utf-8") as f:
db_config = loads(f.read())["database"]
f.close()
if db_config["user"] is not None and db_config["password"] is not None:
con_string = 'mongodb://{0}:{1}@{2}:{3}/{4}'.format(
db_config["user"],
db_config["password"],
db_config["host"],
db_config["port"],
db_config["name"]
)
else:
con_string = 'mongodb://{0}:{1}/{2}'.format(
db_config["host"],
db_config["port"],
db_config["name"]
)
db_client = MongoClient(con_string)
db = db_client.get_database(name=db_config["name"])
collections = db.list_collection_names()
for collection in ["sent", "banned", "submitted"]:
if not collection in collections:
db.create_collection(collection)
col_sent = db.get_collection("sent")
col_banned = db.get_collection("banned")
col_submitted = db.get_collection("submitted")

View File

@@ -1,83 +0,0 @@
from pyrogram import filters
from pyrogram.client import Client
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, Message
from modules.utils import jsonLoad, configGet, locale
from modules.logger import logWrite
from modules.app import app
from modules.submissions import subLimited, subLimit
@app.on_message(~ filters.scheduled & filters.photo | filters.video | filters.animation | filters.document)
async def get_submission(_: Client, msg: Message):
try:
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.document != 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.video != 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
buttons = [
[
InlineKeyboardButton(text=locale("sub_yes", "button", locale=configGet("locale")), callback_data=f"sub_yes_{msg.from_user.id}_{msg.id}")
]
]
if msg.caption != None:
caption = str(msg.caption)
buttons[0].append(
InlineKeyboardButton(text=locale("sub_yes_caption", "button", locale=configGet("locale")), callback_data=f"sub_yes_{msg.from_user.id}_{msg.id}_caption")
)
buttons[0].append(
InlineKeyboardButton(text=locale("sub_no", "button", locale=configGet("locale")), callback_data=f"sub_no_{msg.from_user.id}_{msg.id}")
)
else:
caption = ""
buttons[0].append(
InlineKeyboardButton(text=locale("sub_no", "button", locale=configGet("locale")), callback_data=f"sub_no_{msg.from_user.id}_{msg.id}")
)
caption += locale("sub_by", "message", locale=locale(configGet("locale")))
if msg.from_user.first_name != None:
caption += f" {msg.from_user.first_name}"
if msg.from_user.last_name != None:
caption += f" {msg.from_user.last_name}"
if msg.from_user.username != None:
caption += f" (@{msg.from_user.username})"
if msg.from_user.phone_number != 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}")
]
]
await msg.reply_text(locale("sub_sent", "message", locale=user_locale), quote=True)
subLimit(msg.from_user)
await msg.copy(configGet("admin"), caption=caption, reply_markup=InlineKeyboardMarkup(buttons))
else:
await msg.reply_text(locale("sub_cooldown", "message", locale=user_locale).format(str(configGet("timeout", "submission"))))
except AttributeError:
logWrite(f"from_user in function get_submission does not seem to contain id")

View File

@@ -8,8 +8,10 @@ from modules.app import app
scheduler = AsyncIOScheduler() scheduler = AsyncIOScheduler()
if configGet("post", "mode"): if configGet("post", "mode"):
for entry in configGet("time", "posting"): # for entry in configGet("time", "posting"):
dt_obj = datetime.strptime(entry, "%H:%M") # dt_obj = datetime.strptime(entry, "%H:%M")
scheduler.add_job(send_content, "cron", hour=dt_obj.hour, minute=dt_obj.minute, args=[app]) # 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])
scheduler.add_job(register_commands, "date", run_date=datetime.now()+timedelta(seconds=10), args=[app]) scheduler.add_job(register_commands, "date", run_date=datetime.now()+timedelta(seconds=10), args=[app])

View File

@@ -1,83 +1,63 @@
from os import listdir, remove, sep from datetime import datetime, timezone
from random import choice from os import makedirs, path
from shutil import copyfileobj, move from shutil import copyfileobj, rmtree
from requests import get
from traceback import format_exc from traceback import format_exc
from uuid import uuid4
from bson import ObjectId
from pyrogram.client import Client from pyrogram.client import Client
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton from requests import get
from modules.logger import logWrite
from modules.api_client import authorize, move_pic, random_pic from modules.api_client import authorize, move_pic, random_pic
from modules.utils import jsonLoad, jsonSave, configGet, locale from modules.database import col_sent, col_submitted
from modules.logger import logWrite
from modules.utils import configGet, locale
async def send_content(app: Client): async def send_content(app: Client):
# Send post to channel
try: try:
index = jsonLoad(configGet("index", "locations")) try:
token = await authorize()
except ValueError:
await app.send_message(configGet("admin"), locale("api_creds_invalid", "message", locale=configGet("locale")))
return
if configGet("api_based", "mode"): try:
pic = await random_pic()
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")))
return
except ValueError:
if configGet("error", "reports"):
await app.send_message(configGet("admin"), 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)
try: if response.status_code != 200:
pic = random_pic() logWrite(locale("post_invalid_pic", "console", locale=configGet("locale")).format(str(response.json())))
except: if configGet("error", "reports"):
logWrite(locale("post_empty", "console", locale=configGet("locale"))) await app.send_message(configGet("admin"), locale("post_invalid_pic", "message", locale=configGet("locale")).format(response.json()))
if configGet("error", "reports"):
await app.send_message(configGet("admin"), locale("post_empty", "message", locale=configGet("locale")))
return
token = authorize() tmp_dir = str(uuid4())
response = get(f'{configGet("address", "posting", "api")}/photos/{pic[0]}', headers={"Authorization": f"Bearer {token}"}, stream=True) makedirs(path.join(configGet("tmp", "locations"), tmp_dir), exist_ok=True)
with open(configGet("tmp", "locations")+sep+pic[0]+".jpg", 'wb') as out_file: tmp_path = path.join(tmp_dir, pic[1])
copyfileobj(response.raw, out_file)
del response with open(path.join(configGet("tmp", "locations"), tmp_path), 'wb') as out_file:
copyfileobj(response.raw, out_file)
candidate = configGet("tmp", "locations")+sep+pic[0]+".jpg" del response
candidate_file = pic[1]
ext_type = "photo"
if not configGet("api_based", "mode"): submitted_caption = col_submitted.find_one( {"image": ObjectId(pic[0])} )
list_queue = listdir(configGet("queue", "locations")) if submitted_caption is not None:
caption = submitted_caption["caption"].strip()
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: else:
caption = "" caption = ""
@@ -89,53 +69,164 @@ async def send_content(app: Client):
else: else:
caption = caption caption = caption
if ext_type == "photo": try:
sent = await app.send_photo(configGet("channel", "posting"), path.join(configGet("tmp", "locations"), tmp_path), caption=caption, disable_notification=configGet("silent", "posting"))
if configGet("enabled", "caption"): except Exception as exp:
if configGet("link", "caption") != None: logWrite(f"Could not send image {pic[1]} ({pic[0]}) due to {exp}")
sent = await app.send_photo(configGet("channel", "posting"), candidate, caption=caption, disable_notification=configGet("silent", "posting")) if configGet("error", "reports"):
else: await app.send_message(configGet("admin"), locale("post_exception", "message", locale=configGet("locale")).format(exp, format_exc()))
sent = await app.send_photo(configGet("channel", "posting"), candidate, caption=caption, disable_notification=configGet("silent", "posting")) # rmtree(path.join(configGet("tmp", "locations"), tmp_dir), ignore_errors=True)
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 return
if configGet("api_based", "mode"): col_sent.insert_one(
remove(configGet("tmp", "locations")+sep+pic[0]+".jpg") {
move_pic(pic[0]) "date": datetime.now(tz=timezone.utc),
"image": pic[0],
"filename": pic[1],
"channel": configGet("channel", "posting"),
"caption": None if submitted_caption is None else submitted_caption["caption"].strip()
}
)
index["sent"].append(candidate_file) await move_pic(pic[0])
index["last_id"] = sent.id
jsonSave(index, configGet("index", "locations")) rmtree(path.join(configGet("tmp", "locations"), tmp_dir), ignore_errors=True)
if configGet("move_sent", "posting"): logWrite(locale("post_sent", "console", locale=configGet("locale")).format(pic[0], str(configGet("channel", "posting")), caption.replace("\n", "%n"), str(configGet("silent", "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: except Exception as exp:
logWrite(locale("post_exception", "console", locale=configGet("locale")).format(str(exp), format_exc())) logWrite(locale("post_exception", "console", locale=configGet("locale")).format(str(exp), format_exc()))
if configGet("error", "reports"): 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(configGet("admin"), locale("post_exception", "message", locale=configGet("locale")).format(exp, format_exc()))
pass
# 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 # Work in progress

View File

@@ -1,4 +1,4 @@
from app import app from modules.app import app
from pyrogram import filters from pyrogram import filters
from pyrogram.types import CallbackQuery from pyrogram.types import CallbackQuery
from pyrogram.client import Client from pyrogram.client import Client

View File

@@ -1,12 +1,15 @@
from os import sep from os import sep
from pathlib import Path from pathlib import Path
from pyrogram import filters from pyrogram import filters
from pyrogram.client import Client from pyrogram.client import Client
from pyrogram.types import CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton from pyrogram.types import (CallbackQuery, InlineKeyboardButton,
InlineKeyboardMarkup)
from modules.api_client import upload_pic from modules.api_client import upload_pic
from modules.utils import jsonLoad, jsonSave, configGet, locale
from modules.submissions import subBlock, subUnblock
from modules.app import app from modules.app import app
from modules.submissions import subBlock, subUnblock
from modules.utils import configGet, jsonLoad, jsonSave, locale
@app.on_callback_query(filters.regex("sub_yes_[\s\S]*_[\s\S]*")) @app.on_callback_query(filters.regex("sub_yes_[\s\S]*_[\s\S]*"))

View File

@@ -1,11 +1,14 @@
from os import getpid from os import getpid
from pyrogram import filters from pyrogram import filters
from pyrogram.client import Client from pyrogram.client import Client
from pyrogram.types import Message from pyrogram.types import Message
from modules.app import app from modules.app import app
from modules.logger import logWrite from modules.logger import logWrite
from modules.utils import configGet, killProc, locale from modules.utils import configGet, killProc, locale
@app.on_message(~ filters.scheduled & filters.command(["kill", "die", "reboot"], prefixes=["", "/"])) @app.on_message(~ filters.scheduled & filters.command(["kill", "die", "reboot"], prefixes=["", "/"]))
async def cmd_kill(app: Client, msg: Message): async def cmd_kill(app: Client, msg: Message):

View File

@@ -1,8 +1,10 @@
from pyrogram import filters from pyrogram import filters
from pyrogram.client import Client from pyrogram.client import Client
from pyrogram.types import Message from pyrogram.types import Message
from modules.app import app from modules.app import app
from modules.utils import jsonLoad, configGet, locale from modules.utils import configGet, jsonLoad, locale
@app.on_message(~ filters.scheduled & filters.command(["start"], prefixes="/")) @app.on_message(~ filters.scheduled & filters.command(["start"], prefixes="/"))
async def cmd_start(app: Client, msg: Message): async def cmd_start(app: Client, msg: Message):

View File

@@ -0,0 +1,87 @@
from pyrogram import filters
from pyrogram.client import Client
from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
from modules.app import app
from modules.logger import logWrite
from modules.submissions import subLimit, subLimited
from modules.utils import configGet, jsonLoad, locale
from modules.database import col_banned
@app.on_message(~ filters.scheduled & filters.photo) # | filters.video | filters.animation | filters.document)
async def get_submission(_: Client, msg: Message):
try:
if col_banned.find_one( {"user": msg.from_user.id} ) is not None:
return
user_locale = msg.from_user.language_code
if not subLimited(msg.from_user):
if msg.document != 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.video != 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
buttons = [
[
InlineKeyboardButton(text=locale("sub_yes", "button", locale=configGet("locale")), callback_data=f"sub_yes_{msg.from_user.id}_{msg.id}")
]
]
if msg.caption != None:
caption = str(msg.caption)
buttons[0].append(
InlineKeyboardButton(text=locale("sub_yes_caption", "button", locale=configGet("locale")), callback_data=f"sub_yes_{msg.from_user.id}_{msg.id}_caption")
)
buttons[0].append(
InlineKeyboardButton(text=locale("sub_no", "button", locale=configGet("locale")), callback_data=f"sub_no_{msg.from_user.id}_{msg.id}")
)
else:
caption = ""
buttons[0].append(
InlineKeyboardButton(text=locale("sub_no", "button", locale=configGet("locale")), callback_data=f"sub_no_{msg.from_user.id}_{msg.id}")
)
caption += locale("sub_by", "message", locale=locale(configGet("locale")))
if msg.from_user.first_name != None:
caption += f" {msg.from_user.first_name}"
if msg.from_user.last_name != None:
caption += f" {msg.from_user.last_name}"
if msg.from_user.username != None:
caption += f" (@{msg.from_user.username})"
if msg.from_user.phone_number != 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}")
]
]
await msg.reply_text(locale("sub_sent", "message", locale=user_locale), quote=True)
subLimit(msg.from_user)
await msg.copy(configGet("admin"), caption=caption, reply_markup=InlineKeyboardMarkup(buttons))
else:
await msg.reply_text(locale("sub_cooldown", "message", locale=user_locale).format(str(configGet("timeout", "submission"))))
except AttributeError:
logWrite(f"from_user in function get_submission does not seem to contain id")

View File

@@ -69,7 +69,7 @@ if args.norun:
# Import =================================================================================================================================== # Import ===================================================================================================================================
try: try:
from modules.app import app from modules.app import app
from pyrogram import idle from pyrogram.sync import idle
from requests import get, post from requests import get, post
except ModuleNotFoundError: except ModuleNotFoundError:
print(locale("deps_missing", "console", locale=configGet("locale")), flush=True) print(locale("deps_missing", "console", locale=configGet("locale")), flush=True)
@@ -116,13 +116,12 @@ pid = getpid()
# Imports ================================================================================================================================== # Imports ==================================================================================================================================
from modules.commands.general import * from plugins.commands.general import *
from modules.commands_register import register_commands
if configGet("submit", "mode"): if configGet("submit", "mode"):
from modules.callbacks.submission import * from plugins.callbacks.submission import *
from modules.commands.mode_submit import * from plugins.commands.mode_submit import *
from modules.handlers.submission import * from plugins.handlers.submission import *
if configGet("api_based", "mode"): if configGet("api_based", "mode"):
from modules.api_client import authorize from modules.api_client import authorize
@@ -139,6 +138,35 @@ if configGet("api_based", "mode"):
# # else: # # else:
# # logWrite(f"Got raw update of type {type(update)} with contents {update}", debug=True) # # logWrite(f"Got raw update of type {type(update)} with contents {update}", debug=True)
# async def main():
# await app.start()
# logWrite(locale("startup", "console", locale=configGet("locale")).format(str(pid)))
# if configGet("startup", "reports"):
# await app.send_message(configGet("admin"), locale("startup", "message", locale=configGet("locale")).format(str(pid)))
# if configGet("post", "mode"):
# scheduler.start()
# if configGet("api_based", "mode"):
# token = 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}"})
# await idle()
# await app.send_message(configGet("admin"), locale("shutdown", "message", locale=configGet("locale")).format(str(pid)))
# logWrite(locale("shutdown", "console", locale=configGet("locale")).format(str(pid)))
# killProc(pid)
# if __name__ == "__main__":
# if find_spec("uvloop") is not None:
# uvloop.install()
# asyncio.run(main())
if __name__ == "__main__": if __name__ == "__main__":
logWrite(locale("startup", "console", locale=configGet("locale")).format(str(pid))) logWrite(locale("startup", "console", locale=configGet("locale")).format(str(pid)))

View File

@@ -1,4 +1,5 @@
apscheduler~=3.9.1.post1 apscheduler~=3.10.0
pyrogram~=2.0.97 pyrogram~=2.0.99
requests~=2.28.2 requests~=2.28.2
psutil~=5.9.4 psutil~=5.9.4
pymongo~=4.3.3