139 lines
2.5 KiB
Python
139 lines
2.5 KiB
Python
import json
|
|
|
|
from functools import wraps
|
|
from izzylib import DotDict, LruCache, logging
|
|
from izzylib.http_urllib_client import HttpUrllibClient
|
|
from izzylib.http_urllib_client.error import MaxRetryError
|
|
|
|
from . import __version__
|
|
from .config import config
|
|
from .database import db
|
|
|
|
|
|
client = HttpUrllibClient(
|
|
appagent = f'UnciaRelay/{__version__}; https://{config.host}',
|
|
headers = {
|
|
'accept': 'application/activity+json,application/json'
|
|
}
|
|
)
|
|
|
|
client.set_global()
|
|
fetch_cache = LruCache()
|
|
|
|
|
|
def fetch_actor(url):
|
|
with db.session as s:
|
|
cached = s.get.actor(url)
|
|
|
|
if cached:
|
|
return cached
|
|
|
|
data = fetch(url, sign=True, cache=False)
|
|
|
|
if data == False:
|
|
return False
|
|
|
|
try:
|
|
error = data.get('error')
|
|
|
|
except:
|
|
error = None
|
|
|
|
if error:
|
|
logging.debug(f'Failed to fetch actor "{url}" with error: {error}')
|
|
return
|
|
|
|
if not data:
|
|
logging.verbose(f'Failed to fetch actor: {url}')
|
|
return
|
|
|
|
s.put.actor(url, data)
|
|
return data
|
|
|
|
|
|
def fetch(url, sign=False, headers={}, cache=True):
|
|
cached_data = fetch_cache.fetch(url)
|
|
|
|
if cached_data and cache:
|
|
return cached_data
|
|
|
|
if sign:
|
|
with db.session as s:
|
|
response = client.request(url,
|
|
privkey = s.get.config('privkey'),
|
|
keyid = f'https://{config.host}/actor#main-key',
|
|
headers = {}
|
|
)
|
|
|
|
else:
|
|
response = client.request(url)
|
|
|
|
if response.status == 410:
|
|
return False
|
|
|
|
try:
|
|
data = response.dict
|
|
|
|
except json.decoder.JSONDecodeError:
|
|
return {}
|
|
|
|
if not data:
|
|
return {}
|
|
|
|
if cache:
|
|
fetch_cache.store(url, data)
|
|
|
|
return data
|
|
|
|
|
|
def fetch_auth(url):
|
|
return fetch(url, sign=True)
|
|
|
|
|
|
def get_inbox(actor):
|
|
if not actor:
|
|
return
|
|
|
|
try:
|
|
return actor.endpoints.sharedInbox
|
|
except:
|
|
return actor.inbox
|
|
|
|
|
|
def push_message(inbox, message, headers={}):
|
|
with db.session as s:
|
|
try:
|
|
response = client.request(
|
|
inbox,
|
|
body = message.to_json(),
|
|
method = 'post',
|
|
privkey = s.get.config('privkey'),
|
|
keyid = f'https://{config.host}/actor#main-key'
|
|
)
|
|
|
|
except MaxRetryError as e:
|
|
response = DotDict(status=0, error=e)
|
|
|
|
except Exception as e:
|
|
#logging.debug(f'push_message: {e.__class__.__name__}: {e}')
|
|
response = DotDict(status=0, error=e)
|
|
|
|
if response.status not in [200, 202]:
|
|
s.put.retry(inbox, message, headers)
|
|
|
|
if response.status:
|
|
try:
|
|
body = response.dict
|
|
except:
|
|
body = response.text
|
|
|
|
logging.debug(f'Error from {inbox}: {response.status} {body}')
|
|
|
|
else:
|
|
logging.debug(f'Error from {inbox}: {response.error}')
|
|
|
|
return
|
|
|
|
logging.debug(f'Pushed message to {inbox}:', message['id'])
|
|
return response
|