WIP: API change

This commit is contained in:
2023-03-23 15:03:30 +01:00
parent c948f2e34d
commit 2d0d72b026
6 changed files with 168 additions and 59 deletions

View File

@@ -1,9 +1,8 @@
from http import HTTPStatus
from ujson import loads
from os import path, remove, sep from os import path, remove, sep
from shutil import rmtree from shutil import rmtree
from typing import Tuple, Union from typing import Tuple, Union
from photosapi_client.api.default.photo_upload_albums_album_photos_post import (
asyncio as upload_pic,
)
from photosapi_client.models.body_photo_upload_albums_album_photos_post import ( from photosapi_client.models.body_photo_upload_albums_album_photos_post import (
BodyPhotoUploadAlbumsAlbumPhotosPost, BodyPhotoUploadAlbumsAlbumPhotosPost,
) )
@@ -13,7 +12,7 @@ import aiofiles
from pyrogram.client import Client from pyrogram.client import Client
from pyrogram.types import Message from pyrogram.types import Message
from classes.exceptions import SubmissionDuplicatesError, SubmissionUnavailableError from classes.exceptions import SubmissionDuplicatesError, SubmissionUnavailableError
from modules.api_client import client from modules.api_client import client, photo_upload
from modules.database import col_submitted from modules.database import col_submitted
from bson import ObjectId from bson import ObjectId
from modules.logger import logWrite from modules.logger import logWrite
@@ -75,7 +74,7 @@ class PosterClient(Client):
async with aiofiles.open(filepath, "rb") as f: async with aiofiles.open(filepath, "rb") as f:
file_bytes = await f.read() file_bytes = await f.read()
response = await upload_pic( response = await photo_upload(
album=configGet("album", "posting", "api"), album=configGet("album", "posting", "api"),
client=client, client=client,
multipart_data=BodyPhotoUploadAlbumsAlbumPhotosPost( multipart_data=BodyPhotoUploadAlbumsAlbumPhotosPost(
@@ -86,10 +85,20 @@ class PosterClient(Client):
compress=False, compress=False,
) )
if isinstance(response, HTTPValidationError) > 0: print(response, flush=True)
raise SubmissionDuplicatesError(
str(filepath), response.to_dict()["duplicates"] if response.status_code == HTTPStatus.CONFLICT:
) duplicates = []
for index, duplicate in enumerate(loads(response.content)["duplicates"]): # type: ignore
if loads(response.content)["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/{loads(response.content)["access_token"]}?id={index}'
)
raise SubmissionDuplicatesError(str(filepath), duplicates)
col_submitted.find_one_and_update( col_submitted.find_one_and_update(
{"_id": ObjectId(id)}, {"$set": {"done": True}} {"_id": ObjectId(id)}, {"$set": {"done": True}}
@@ -112,7 +121,7 @@ class PosterClient(Client):
f"Could not delete '{filepath}' on submission accepted", debug=True f"Could not delete '{filepath}' on submission accepted", debug=True
) )
return submission, response[2] return submission, response.parsed.id
async def ban_user(self, id: int) -> None: async def ban_user(self, id: int) -> None:
pass pass

View File

@@ -1,6 +1,45 @@
"""This is only a temporary solution. Complete Photos API client is yet to be developed.""" """This is only a temporary solution. Complete Photos API client is yet to be developed."""
from photosapi_client import AuthenticatedClient import asyncio
from photosapi_client import AuthenticatedClient, Client
from photosapi_client.api.default.user_me_users_me_get import sync as user_me
from photosapi_client.api.default.user_create_users_post import asyncio as user_create
from photosapi_client.api.default.login_for_access_token_token_post import (
sync as login,
)
from photosapi_client.api.default.video_find_albums_album_videos_get import (
asyncio as video_find,
)
from photosapi_client.api.default.album_find_albums_get import asyncio as album_find
from photosapi_client.api.default.album_create_albums_post import (
asyncio as album_create,
)
from photosapi_client.api.default.album_delete_album_id_delete import (
asyncio as album_delete,
)
from photosapi_client.api.default.photo_find_albums_album_photos_get import (
asyncio as photo_find,
)
from photosapi_client.api.default.photo_patch_photos_id_patch import (
asyncio as photo_patch,
)
from photosapi_client.api.default.photo_delete_photos_id_delete import (
asyncio as photo_delete,
)
from photosapi_client.api.default.photo_upload_albums_album_photos_post import (
asyncio_detailed as photo_upload,
)
from photosapi_client.api.default.photo_get_photos_id_get import asyncio as photo_get
from photosapi_client.models.body_photo_upload_albums_album_photos_post import (
BodyPhotoUploadAlbumsAlbumPhotosPost,
)
from photosapi_client.types import File
from photosapi_client.models.token import Token
from photosapi_client.models.http_validation_error import HTTPValidationError
from photosapi_client.models.body_login_for_access_token_token_post import (
BodyLoginForAccessTokenTokenPost,
)
# import asyncio # import asyncio
from base64 import b64decode, b64encode from base64 import b64decode, b64encode
@@ -72,8 +111,33 @@ async def authorize() -> str:
return (await response.json())["access_token"] return (await response.json())["access_token"]
unauthorized_client = Client(
base_url=configGet("address", "posting", "api"),
timeout=5.0,
verify_ssl=True,
raise_on_unexpected_status=True,
)
login_token = login(
client=unauthorized_client,
form_data=BodyLoginForAccessTokenTokenPost(
grant_type="password",
scope="me albums.list albums.read albums.write photos.list photos.read photos.write videos.list videos.read videos.write",
username=configGet("username", "posting", "api"),
password=configGet("password", "posting", "api"),
),
)
if not isinstance(login_token, Token):
logWrite(f"Could not initialize connection due to invalid token: {login_token}")
exit()
client = AuthenticatedClient( client = AuthenticatedClient(
base_url=configGet("address", "posting", "api"), token=await authorize() base_url=configGet("address", "posting", "api"),
timeout=5.0,
verify_ssl=True,
raise_on_unexpected_status=True,
token=login_token.access_token,
) )
# async def random_pic(token: Union[str, None] = None) -> Tuple[str, str]: # async def random_pic(token: Union[str, None] = None) -> Tuple[str, str]:
@@ -267,5 +331,5 @@ client = AuthenticatedClient(
# return None # return None
# if __name__ == "__main__": if __name__ == "__main__":
# print(asyncio.run(authorize())) print(asyncio.run(authorize()))

View File

@@ -1,7 +1,7 @@
import asyncio import asyncio
from sys import exit from sys import exit
from traceback import print_exc from traceback import print_exc
from modules.api_client import create_album, create_user, http_session from modules.api_client import album_create, user_create, http_session
from argparse import ArgumentParser from argparse import ArgumentParser
from modules.utils import configSet from modules.utils import configSet
@@ -26,7 +26,7 @@ async def cli_create_user() -> None:
email = input(f"Choose email for user '{username}': ").strip() email = input(f"Choose email for user '{username}': ").strip()
password = input(f"Choose password for user '{username}': ").strip() password = input(f"Choose password for user '{username}': ").strip()
try: try:
result_1 = await create_user(username, email, password) result_1 = await user_create(username, email, password)
# asyncio.run(create_user(username, email, password)) # asyncio.run(create_user(username, email, password))
configSet("username", username, "posting", "api") configSet("username", username, "posting", "api")
configSet("password", password, "posting", "api") configSet("password", password, "posting", "api")
@@ -52,7 +52,7 @@ async def cli_create_album() -> None:
name = input("Choose a name for your album: ").strip() name = input("Choose a name for your album: ").strip()
title = input(f"Choose a title for album '{name}': ").strip() title = input(f"Choose a title for album '{name}': ").strip()
try: try:
result_2 = await create_album(name, title) result_2 = await album_create(name, title)
# asyncio.run(create_album(name, title)) # asyncio.run(create_album(name, title))
configSet("album", name, "posting", "api") configSet("album", name, "posting", "api")
except Exception as exp: except Exception as exp:

View File

@@ -9,7 +9,14 @@ import aiofiles
from classes.poster_client import PosterClient from classes.poster_client import PosterClient
from modules.api_client import authorize, move_pic, random_pic, http_session from modules.api_client import (
client,
authorize,
photo_find,
photo_get,
photo_patch,
http_session,
)
from modules.database import col_sent, col_submitted from modules.database import col_sent, col_submitted
from modules.logger import logWrite from modules.logger import logWrite
from modules.utils import configGet, locale from modules.utils import configGet, locale
@@ -27,8 +34,15 @@ async def send_content(app: PosterClient) -> None:
return return
try: try:
pic = await random_pic() search_result = await photo_find(
except KeyError: client=client,
album=configGet("album", "posting", "api"),
caption="queue",
page_size=configGet("page_size", "posting"),
)
print(search_result, flush=True)
pic = choice(search_result.results)
except (IndexError, KeyError):
logWrite(locale("post_empty", "console", locale=configGet("locale"))) logWrite(locale("post_empty", "console", locale=configGet("locale")))
if configGet("error", "reports"): if configGet("error", "reports"):
await app.send_message( await app.send_message(
@@ -45,7 +59,7 @@ async def send_content(app: PosterClient) -> None:
return return
response = await http_session.get( response = await http_session.get(
f'{configGet("address", "posting", "api")}/photos/{pic[0]}', f'{configGet("address", "posting", "api")}/photos/{pic.id}',
headers={"Authorization": f"Bearer {token}"}, headers={"Authorization": f"Bearer {token}"},
) )
@@ -67,7 +81,7 @@ async def send_content(app: PosterClient) -> None:
makedirs(path.join(configGet("tmp", "locations"), tmp_dir), exist_ok=True) makedirs(path.join(configGet("tmp", "locations"), tmp_dir), exist_ok=True)
tmp_path = path.join(tmp_dir, pic[1]) tmp_path = path.join(tmp_dir, pic.filename)
async with aiofiles.open( async with aiofiles.open(
path.join(configGet("tmp", "locations"), tmp_path), "wb" path.join(configGet("tmp", "locations"), tmp_path), "wb"
@@ -75,7 +89,7 @@ async def send_content(app: PosterClient) -> None:
await out_file.write(await response.read()) await out_file.write(await response.read())
logWrite( logWrite(
f'Candidate {pic[1]} ({pic[0]}) is {path.getsize(path.join(configGet("tmp", "locations"), tmp_path))} bytes big', f'Candidate {pic.filename} ({pic.id}) is {path.getsize(path.join(configGet("tmp", "locations"), tmp_path))} bytes big',
debug=True, debug=True,
) )
@@ -107,7 +121,7 @@ async def send_content(app: PosterClient) -> None:
del response del response
submitted = col_submitted.find_one({"temp.file": pic[1]}) submitted = col_submitted.find_one({"temp.file": pic.filename})
if submitted is not None and submitted["caption"] is not None: if submitted is not None and submitted["caption"] is not None:
caption = submitted["caption"].strip() caption = submitted["caption"].strip()
@@ -144,7 +158,7 @@ async def send_content(app: PosterClient) -> None:
disable_notification=configGet("silent", "posting"), disable_notification=configGet("silent", "posting"),
) )
except Exception as exp: except Exception as exp:
logWrite(f"Could not send image {pic[1]} ({pic[0]}) due to {exp}") logWrite(f"Could not send image {pic.filename} ({pic.id}) due to {exp}")
if configGet("error", "reports"): if configGet("error", "reports"):
await app.send_message( await app.send_message(
app.owner, app.owner,
@@ -158,8 +172,8 @@ async def send_content(app: PosterClient) -> None:
col_sent.insert_one( col_sent.insert_one(
{ {
"date": datetime.now(), "date": datetime.now(),
"image": pic[0], "image": pic.id,
"filename": pic[1], "filename": pic.filename,
"channel": configGet("channel", "posting"), "channel": configGet("channel", "posting"),
"caption": None "caption": None
if (submitted is None or submitted["caption"] is None) if (submitted is None or submitted["caption"] is None)
@@ -167,13 +181,13 @@ async def send_content(app: PosterClient) -> None:
} }
) )
await move_pic(pic[0]) await photo_patch(client=client, id=pic.id, caption="sent")
rmtree(path.join(configGet("tmp", "locations"), tmp_dir), ignore_errors=True) rmtree(path.join(configGet("tmp", "locations"), tmp_dir), ignore_errors=True)
logWrite( logWrite(
locale("post_sent", "console", locale=configGet("locale")).format( locale("post_sent", "console", locale=configGet("locale")).format(
pic[0], pic.id,
str(configGet("channel", "posting")), str(configGet("channel", "posting")),
caption.replace("\n", "%n"), caption.replace("\n", "%n"),
str(configGet("silent", "posting")), str(configGet("silent", "posting")),

View File

@@ -5,16 +5,24 @@ from shutil import disk_usage, rmtree
from traceback import format_exc from traceback import format_exc
from uuid import uuid4 from uuid import uuid4
from zipfile import ZipFile from zipfile import ZipFile
import aiofiles
from convopyro import listen_message from convopyro import listen_message
from pyrogram import filters from pyrogram import filters
from pyrogram.types import Message from pyrogram.types import Message
from classes.poster_client import PosterClient from classes.poster_client import PosterClient
from modules.api_client import remove_pic, upload_pic
from modules.app import app, users_with_context from modules.app import app, users_with_context
from modules.logger import logWrite from modules.logger import logWrite
from modules.utils import configGet, extract_and_save, locale from modules.utils import configGet, extract_and_save, locale
from modules.api_client import (
client,
photo_upload,
photo_delete,
HTTPValidationError,
BodyPhotoUploadAlbumsAlbumPhotosPost,
File,
)
@app.on_message(~filters.scheduled & filters.command(["import"], prefixes=["", "/"])) @app.on_message(~filters.scheduled & filters.command(["import"], prefixes=["", "/"]))
@@ -114,13 +122,34 @@ async def cmd_import(app: PosterClient, msg: Message):
if not path.isfile(filename): if not path.isfile(filename):
continue continue
# upload filename # upload filename
uploaded = await upload_pic(filename) async with aiofiles.open(filename, "rb") as f:
if uploaded[0] is False: file_bytes = await f.read()
logWrite( uploaded = await photo_upload(
f"Could not upload '{filename}' from '{path.join(configGet('tmp', 'locations'), tmp_dir)}'. Duplicates: {str(uploaded[1])}", album=configGet("album", "posting", "api"),
debug=True, client=client,
multipart_data=BodyPhotoUploadAlbumsAlbumPhotosPost(
File(file_bytes, path.basename(filename), "image/jpeg")
),
ignore_duplicates=configGet("allow_duplicates", "submission"),
caption="queue",
compress=False,
)
if uploaded is None or isinstance(uploaded, HTTPValidationError):
await msg.reply_text(
locale(
"import_upload_error_other",
"message",
locale=msg.from_user.language_code,
).format(path.basename(filename)),
disable_notification=True,
) )
if len(uploaded[1]) > 0: return
if not hasattr(uploaded, "id"):
if hasattr(uploaded, "duplicates"):
logWrite(
f"Could not upload '{filename}' from '{path.join(configGet('tmp', 'locations'), tmp_dir)}'. Duplicates: {str(uploaded.duplicates)}",
debug=True,
)
await msg.reply_text( await msg.reply_text(
locale( locale(
"import_upload_error_duplicate", "import_upload_error_duplicate",
@@ -140,7 +169,7 @@ async def cmd_import(app: PosterClient, msg: Message):
) )
else: else:
logWrite( logWrite(
f"Uploaded '{filename}' from '{path.join(configGet('tmp', 'locations'), tmp_dir)}' and got ID {uploaded[2]}", f"Uploaded '{filename}' from '{path.join(configGet('tmp', 'locations'), tmp_dir)}' and got ID {uploaded.id}",
debug=True, debug=True,
) )
@@ -187,8 +216,8 @@ async def cmd_remove(app: PosterClient, msg: Message):
locale("remove_abort", "message", locale=msg.from_user.language_code) locale("remove_abort", "message", locale=msg.from_user.language_code)
) )
return return
response = await remove_pic(answer.text) try:
if response: response = await photo_delete(id=answer.text, client=client)
logWrite( logWrite(
f"Removed '{answer.text}' by request of user {answer.from_user.id}" f"Removed '{answer.text}' by request of user {answer.from_user.id}"
) )
@@ -197,7 +226,7 @@ async def cmd_remove(app: PosterClient, msg: Message):
"remove_success", "message", locale=msg.from_user.language_code "remove_success", "message", locale=msg.from_user.language_code
).format(answer.text) ).format(answer.text)
) )
else: except:
logWrite( logWrite(
f"Could not remove '{answer.text}' by request of user {answer.from_user.id}" f"Could not remove '{answer.text}' by request of user {answer.from_user.id}"
) )

View File

@@ -3,7 +3,7 @@ from os import getpid, path
from sys import exit from sys import exit
from time import time from time import time
from traceback import format_exc from traceback import format_exc
from modules.api_client import authorize from modules.api_client import authorize, album_find, album_create
from modules.cli import * from modules.cli import *
from modules.http_client import http_session from modules.http_client import http_session
@@ -106,8 +106,8 @@ if configGet("post", "mode"):
# if configGet("api_based", "mode"): # if configGet("api_based", "mode"):
# token = authorize() # 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: # if len(get(f'{configGet("address", "posting", "api")}/albums?q={configGet("album", "posting", "api")}', 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}"}) # post(f'{configGet("address", "posting", "api")}/albums?name={configGet("album", "posting", "api")}&title={configGet("album", "posting", "api")}', headers={"Authorization": f"Bearer {token}"})
# await idle() # await idle()
@@ -209,31 +209,24 @@ async def main():
scheduler.start() scheduler.start()
try: try:
token = await authorize()
if ( if (
len( len(
( (
await ( await album_find(
await http_session.get( client=client, q=configGet("album", "posting", "api")
f'{configGet("address", "posting", "api")}/albums?q={configGet("queue", "posting", "api", "albums")}', )
headers={"Authorization": f"Bearer {token}"}, ).results
)
).json()
)["results"]
) )
== 0 == 0
): ):
logWrite("Media album does not exist on API server. Trying to create it...") logWrite("Media album does not exist on API server. Trying to create it...")
try: try:
await http_session.post( await album_create(
f'{configGet("address", "posting", "api")}/albums?name={configGet("queue", "posting", "api", "albums")}&title={configGet("queue", "posting", "api", "albums")}', client=client,
headers={"Authorization": f"Bearer {token}"}, name=configGet("album", "posting", "api"),
) title=configGet("album", "posting", "api"),
logWrite(
"Created media album on API server."}"
) )
logWrite("Created media album on API server.")
except Exception as exp: except Exception as exp:
logWrite( logWrite(
f"Could not create media album on API server due to {exp}: {format_exc()}" f"Could not create media album on API server due to {exp}: {format_exc()}"