ytptube/app/Webhooks.py

97 lines
3 KiB
Python

import asyncio
import logging
import os
from ItemDTO import ItemDTO
import httpx
from version import APP_VERSION
LOG = logging.getLogger('Webhooks')
class Webhooks:
targets: list[dict] = []
def __init__(self, file: str):
if os.path.exists(file):
self.load(file)
def load(self, file: str):
try:
if os.path.getsize(file) < 2:
raise Exception(f'file is empty.')
LOG.info(f'Loading webhooks from {file}')
from Utils import load_file
(target, status, error) = load_file(file, list)
if not status:
raise Exception(f'{error}')
self.targets = target
except Exception as e:
LOG.error(f'Error loading webhooks from {file}: {e}')
pass
async def send(self, event: str, item: ItemDTO) -> list[dict]:
if len(self.targets) == 0:
return []
if not isinstance(item, ItemDTO):
return []
tasks = []
for target in self.targets:
allowed_events = target.get('on') if 'on' in target else []
if len(allowed_events) > 0 and event not in allowed_events:
continue
tasks.append(self.__send(event, target, item))
return await asyncio.gather(*tasks)
async def __send(self, event: str, target: dict, item: ItemDTO) -> dict:
req: dict = target.get('request')
try:
LOG.info(f"Sending {event=} {item.id=} to [{target.get('name')}]")
async with httpx.AsyncClient() as client:
request_type = req.get('type', 'json')
reqBody = {
'method': req.get('method', 'POST'),
'url': req.get('url'),
'headers': {
'User-Agent': f"YTPTube/{APP_VERSION}"
},
}
if req.get('headers', None):
reqBody['headers'].update(req.get('headers'))
match(request_type):
case 'json':
reqBody['json'] = item.__dict__
reqBody['headers']['Content-Type'] = 'application/json'
case _:
reqBody['data'] = item.__dict__
reqBody['headers']['Content-Type'] = 'application/x-www-form-urlencoded'
response = await client.request(**reqBody)
respData = {
'url': req.get('url'),
'status': response.status_code,
'text': response.text
}
msg = f"[{target.get('name')}] Response to [{event=} {item.id=}] [status: {response.status_code}]."
if respData.get('text'):
msg += f" [Body: {respData.get('text','??')}]"
LOG.info(msg)
return respData
except Exception as e:
return {
'url': req.get('url'),
'status': 500,
'text': str(e)
}