Skip to content

Commit

Permalink
[misc] producer support
Browse files Browse the repository at this point in the history
Should work to upload files to producer instead of hikari.
I don't want to add an url upload in producer, as it is rarely useful
and can easily become a security issue if unchecked, so remote files are
downloaded and re-uploaded.
  • Loading branch information
odrling committed Jul 17, 2024
1 parent 1a9b0f2 commit f48f6d4
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 15 deletions.
3 changes: 2 additions & 1 deletion nanapi/example.local_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@

# General
# TZ = ZoneInfo('Europe/Paris')
# HIKARI_UPLOAD_ENDPOINT = 'https://hikari.butaishoujo.moe/upload'
# PRODUCER_UPLOAD_ENDPOINT = 'https://producer.japan7.bde.enseeiht.fr'
# PRODUCER_TOKEN = ''

# AniList
# LOW_PRIORITY_THRESH = 30
Expand Down
3 changes: 2 additions & 1 deletion nanapi/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@

# General
TZ = ZoneInfo('Europe/Paris')
HIKARI_UPLOAD_ENDPOINT = 'https://hikari.butaishoujo.moe/upload'
PRODUCER_UPLOAD_ENDPOINT = 'https://producer.japan7.bde.enseeiht.fr'
PRODUCER_TOKEN = ''

# AniList
LOW_PRIORITY_THRESH = 30
Expand Down
6 changes: 3 additions & 3 deletions nanapi/utils/collages.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from nanapi.database.anilist.media_select import MediaSelectResult, media_select
from nanapi.database.waicolle.waifu_insert import WaicolleCollagePosition
from nanapi.utils.clients import get_edgedb, get_session
from nanapi.utils.misc import default_backoff, to_hikari
from nanapi.utils.misc import default_backoff, to_producer
from nanapi.utils.waicolle import CHARA_TYPES, RNG, WAIFU_TYPES

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -385,7 +385,7 @@ async def waifu_collage(waifus: list[WAIFU_TYPES]) -> str:
try:
with io.BytesIO() as image_binary:
await asyncio.to_thread(_make_collage, image_binary, chara_images)
hikari = await to_hikari(image_binary, filename=f'wc_{uuid4()}.webp')
hikari = await to_producer(image_binary, filename=f'wc_{uuid4()}.webp')
return hikari['url']
finally:
for group in chara_images:
Expand Down Expand Up @@ -487,7 +487,7 @@ async def chara_album(
try:
with io.BytesIO() as image_binary:
await asyncio.to_thread(_make_collage, image_binary, chara_images)
hikari = await to_hikari(image_binary, filename=f'wc_{uuid4()}.webp')
hikari = await to_producer(image_binary, filename=f'wc_{uuid4()}.webp')
return hikari['url']
finally:
for group in chara_images:
Expand Down
35 changes: 25 additions & 10 deletions nanapi/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
import logging
import time
from functools import singledispatch, wraps
from typing import Callable, ParamSpec, TypeVar
from typing import Callable, ParamSpec, TypedDict, TypeVar

import aiohttp
import backoff
from yarl import URL

from nanapi.settings import HIKARI_UPLOAD_ENDPOINT
from nanapi.settings import PRODUCER_TOKEN, PRODUCER_UPLOAD_ENDPOINT
from nanapi.utils.clients import get_session

conn_backoff = backoff.on_exception(
Expand All @@ -36,22 +36,37 @@
default_backoff = timeout_backoff(conn_backoff(response_backoff))


class HikariResponse(TypedDict):
url: str


@singledispatch
@default_backoff
async def to_hikari(file: str | URL, **kwargs):
async with get_session().get(HIKARI_UPLOAD_ENDPOINT,
params=dict(url=str(file), **kwargs)) as req:
return await req.json()
async def to_producer(file: str | URL) -> HikariResponse:
url = URL(file) if isinstance(file, str) else file

async with get_session().get(url) as req:
filename = url.name
data = aiohttp.FormData()
data.add_field("file", req.content, filename=filename)

@to_hikari.register
async with get_session().post(PRODUCER_UPLOAD_ENDPOINT, data=data) as req:
return await req.json()


@to_producer.register
@default_backoff
async def _(file: io.IOBase, filename=None, **kwargs):
async def _(file: io.IOBase, filename=None) -> HikariResponse:
if filename is not None:
file.name = filename # type: ignore

async with get_session().post(HIKARI_UPLOAD_ENDPOINT,
data=dict(file=file, **kwargs)) as req:
headers = {
"Authorization": f"Bearer {PRODUCER_TOKEN}",
"Expires": 0,
}

async with get_session().post(PRODUCER_UPLOAD_ENDPOINT,
headers=headers, data=dict(file=file)) as req:
return await req.json()


Expand Down

0 comments on commit f48f6d4

Please sign in to comment.