WIP: API usage as main

This commit is contained in:
Profitroll 2023-02-14 16:25:56 +01:00
parent 8e0fee4cb9
commit 7940cbe5a7
7 changed files with 302 additions and 185 deletions

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}",
"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}",
"post_exception": "Could not send content due to `{exp}`\n\nTraceback:\n```{0}```",
"post_empty": "Could not send content: `Queue folder is empty or contains only unsupported or already sent files.`",
"post_low": "Low amount of content: `There are only {0} files left in the queue.`"
"post_exception": "Could not send content due to `{0}`\n\nTraceback:\n```{1}```",
"post_invalid_pic": "__TO_BE_ADDED__",
"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": {
"sub_yes": "✅ Accept",
@ -52,8 +55,9 @@
"startup":"Starting with pid {0}",
"keyboard_interrupt": "\nShutting down...",
"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_invalid_pic": "__TO_BE_ADDED__",
"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_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}",
"document_too_large": "Надісланий файл завеликий. Будь ласка, надсилайте файли не більше {0} Мб",
"mime_not_allowed": "Тип файлу не дозволений. Розгляньте можливість використання одного з цих: {0}",
"post_exception": "Не вдалося надіслати контент через `{exp}`\n\nTraceback:\n```{0}```",
"post_empty": "Не вдалося надіслати контент: `Папка черги порожня або містить лише непідтримувані або вже надіслані файли`.",
"post_low": "Мала кількість контенту: `Залишилось всього {0} файлів в черзі.`"
"post_exception": "Не вдалося надіслати контент через `{0}`\n\nTraceback:\n```{1}```",
"post_invalid_pic": "__TO_BE_ADDED__",
"api_queue_empty": "Не вдалося надіслати контент: `Папка черги порожня або містить лише непідтримувані або вже надіслані файли`.",
"api_queue_error": "__TO_BE_ADDED__",
"post_low": "Мала кількість контенту: `Залишилось всього {0} файлів в черзі.`",
"api_creds_invalid": "__TO_BE_ADDED__"
},
"button": {
"sub_yes": "✅ Прийняти",
@ -52,8 +55,9 @@
"startup": "Запуск бота з підом {0}",
"keyboard_interrupt": "\nВимикаюсь...",
"exception_occured": "Помилка {0} сталась під час виконання",
"post_sent": "Надіслано {0} типу {1} у {2} з підписом {3} та без звуку {4}",
"post_sent": "Надіслано {0} у {1} з підписом {2} та без звуку {3}",
"post_exception": "Не вдалося надіслати контент через {0}. Traceback: {1}",
"post_invalid_pic": "__TO_BE_ADDED__",
"post_empty": "Не вдалося надіслати контент через порожню папку черги з дозволеними розширеннями",
"sub_mime_not_allowed": "Отримано подання від {0} але типу {1} який не є дозволеним",
"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 base64 import b64encode, b64decode
from random import choice
from typing import Tuple
from requests import get, post, put, patch
from typing import Tuple, Union
from requests import get, patch, post
from modules.logger import logWrite
from modules.utils import configGet
def authorize() -> str:
async def authorize() -> str:
makedirs(configGet("cache", "locations"), exist_ok=True)
if path.exists(configGet("cache", "locations")+sep+"api_access") is True:
with open(configGet("cache", "locations")+sep+"api_access", "rb") as file:
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
payload = {
"grant_type": "password",
@ -18,23 +23,35 @@ def authorize() -> str:
"username": configGet("username", "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:
file.write(b64encode(response["access_token"].encode("utf-8")))
return response["access_token"]
file.write(b64encode(response.json()["access_token"].encode("utf-8")))
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:
* `Tuple[str, str]`: First value is an ID and the filename in the filesystem to be indexed.
"""
token = authorize()
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"])
if token is None:
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"]
def upload_pic(filepath: str) -> bool:
token = authorize()
async def upload_pic(filepath: str) -> Tuple[bool, list]:
token = await authorize()
try:
pic_name = path.basename(filepath)
files = {'file': (pic_name, open(filepath, 'rb'), 'image/jpeg')}
@ -48,8 +65,8 @@ def upload_pic(filepath: str) -> bool:
except:
return False, []
def move_pic(id: str) -> bool:
token = authorize()
async def move_pic(id: str) -> bool:
token = await authorize()
try:
patch(f'{configGet("address", "posting", "api")}/photos/{id}?caption=sent', headers={"Authorization": f"Bearer {token}"})
return True
@ -57,4 +74,4 @@ def move_pic(id: str) -> bool:
return False
if __name__ == "__main__":
print(authorize())
print(asyncio.run(authorize()))

View File

@ -1,5 +1,4 @@
"""Module that provides all database columns and
creates geospatial index for col_applications"""
"""Module that provides all database columns"""
from pymongo import MongoClient
from ujson import loads

View File

@ -1,83 +1,63 @@
from os import listdir, remove, sep
from random import choice
from shutil import copyfileobj, move
from requests import get
from datetime import datetime, timezone
from os import makedirs, path
from shutil import copyfileobj, rmtree
from traceback import format_exc
from uuid import uuid4
from bson import ObjectId
from pyrogram.client import Client
from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from modules.logger import logWrite
from requests import get
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):
# 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")))
token = await authorize()
except ValueError:
await app.send_message(configGet("admin"), locale("api_creds_invalid", "message", locale=configGet("locale")))
return
token = authorize()
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)
with open(configGet("tmp", "locations")+sep+pic[0]+".jpg", 'wb') as out_file:
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()))
tmp_dir = str(uuid4())
makedirs(path.join(configGet("tmp", "locations"), tmp_dir), exist_ok=True)
tmp_path = path.join(tmp_dir, pic[1])
with open(path.join(configGet("tmp", "locations"), tmp_path), '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"
submitted_caption = col_submitted.find_one( {"image": ObjectId(pic[0])} )
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]
if submitted_caption is not None:
caption = submitted_caption["caption"].strip()
else:
caption = ""
@ -89,53 +69,164 @@ async def send_content(app: Client):
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:
try:
sent = await app.send_photo(configGet("channel", "posting"), path.join(configGet("tmp", "locations"), tmp_path), caption=caption, disable_notification=configGet("silent", "posting"))
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()))
# rmtree(path.join(configGet("tmp", "locations"), tmp_dir), ignore_errors=True)
return
if configGet("api_based", "mode"):
remove(configGet("tmp", "locations")+sep+pic[0]+".jpg")
move_pic(pic[0])
col_sent.insert_one(
{
"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)
index["last_id"] = sent.id
await move_pic(pic[0])
jsonSave(index, configGet("index", "locations"))
rmtree(path.join(configGet("tmp", "locations"), tmp_dir), ignore_errors=True)
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)]
]))
logWrite(locale("post_sent", "console", locale=configGet("locale")).format(pic[0], str(configGet("channel", "posting")), caption.replace("\n", "%n"), str(configGet("silent", "posting"))))
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
# 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

View File

@ -6,14 +6,16 @@ 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)
@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")):
if col_banned.find_one( {"user": msg.from_user.id} ) is not None:
return
user_locale = msg.from_user.language_code

View File

@ -69,7 +69,7 @@ if args.norun:
# Import ===================================================================================================================================
try:
from modules.app import app
from pyrogram import idle
from pyrogram.sync import idle
from requests import get, post
except ModuleNotFoundError:
print(locale("deps_missing", "console", locale=configGet("locale")), flush=True)