mirror of https://gitlab.com/bashrc2/epicyon
Offers collection for shared items
parent
ed804adf85
commit
81f3b1d6a4
83
daemon.py
83
daemon.py
|
@ -185,6 +185,7 @@ from webapp_podcast import html_podcast_episode
|
|||
from webapp_theme_designer import html_theme_designer
|
||||
from webapp_minimalbutton import set_minimal
|
||||
from webapp_minimalbutton import is_minimal
|
||||
from webapp_utils import get_shares_collection
|
||||
from webapp_utils import load_buy_sites
|
||||
from webapp_utils import get_default_path
|
||||
from webapp_utils import get_avatar_image_url
|
||||
|
@ -17230,6 +17231,88 @@ class PubServer(BaseHTTPRequestHandler):
|
|||
self.server.debug)
|
||||
return
|
||||
|
||||
# shared items offers collection for this instance
|
||||
# this is only accessible to instance members or to
|
||||
# other instances which present an authorization token
|
||||
if self.path.startswith('/users/') and '/offers' in self.path:
|
||||
offers_collection_authorized = authorized
|
||||
nickname = self.path.split('/users/')[1]
|
||||
if '/' in nickname:
|
||||
nickname = nickname.split('/')[0]
|
||||
page_number = 1
|
||||
if '?page=' in self.path:
|
||||
page_number_str = self.path.split('?page=')[1]
|
||||
if ';' in page_number_str:
|
||||
page_number_str = page_number_str.split(';')[0]
|
||||
if page_number_str.isdigit():
|
||||
page_number = int(page_number_str)
|
||||
if not offers_collection_authorized:
|
||||
if self.server.debug:
|
||||
print('Offers collection access is not authorized. ' +
|
||||
'Checking Authorization header')
|
||||
# Check the authorization token
|
||||
if self.headers.get('Origin') and \
|
||||
self.headers.get('Authorization'):
|
||||
permitted_domains = \
|
||||
self.server.shared_items_federated_domains
|
||||
shared_item_tokens = \
|
||||
self.server.shared_item_federation_tokens
|
||||
if authorize_shared_items(permitted_domains,
|
||||
self.server.base_dir,
|
||||
self.headers['Origin'],
|
||||
calling_domain,
|
||||
self.headers['Authorization'],
|
||||
self.server.debug,
|
||||
shared_item_tokens):
|
||||
offers_collection_authorized = True
|
||||
elif self.server.debug:
|
||||
print('Authorization token refused for ' +
|
||||
'offers collection federation')
|
||||
# show offers collection for federation
|
||||
if self._has_accept(calling_domain) and \
|
||||
offers_collection_authorized:
|
||||
if self.server.debug:
|
||||
print('Preparing offers collection')
|
||||
|
||||
domain_full = self.server.domain_full
|
||||
http_prefix = self.server.http_prefix
|
||||
nickname = self.path.split('/users/')[1]
|
||||
if '/' in nickname:
|
||||
nickname = nickname.split('/')[0]
|
||||
if self.server.debug:
|
||||
print('Offers collection for account: ' + nickname)
|
||||
base_dir = self.server.base_dir
|
||||
offers_items_per_page = 12
|
||||
max_shares_per_account = offers_items_per_page
|
||||
shared_items_federated_domains = \
|
||||
self.server.shared_items_federated_domains
|
||||
actor = \
|
||||
local_actor_url(http_prefix, nickname, domain_full) + \
|
||||
'/offers'
|
||||
offers_json = \
|
||||
get_shares_collection(actor, page_number,
|
||||
offers_items_per_page, base_dir,
|
||||
self.server.domain, nickname,
|
||||
max_shares_per_account,
|
||||
shared_items_federated_domains,
|
||||
'shares')
|
||||
msg_str = json.dumps(offers_json,
|
||||
ensure_ascii=False)
|
||||
msg_str = self._convert_domains(calling_domain,
|
||||
referer_domain,
|
||||
msg_str)
|
||||
msg = msg_str.encode('utf-8')
|
||||
msglen = len(msg)
|
||||
accept_str = self.headers['Accept']
|
||||
protocol_str = \
|
||||
get_json_content_from_accept(accept_str)
|
||||
self._set_headers(protocol_str, msglen,
|
||||
None, calling_domain, False)
|
||||
self._write(msg)
|
||||
return
|
||||
self._400()
|
||||
return
|
||||
|
||||
# shared items catalog for this instance
|
||||
# this is only accessible to instance members or to
|
||||
# other instances which present an authorization token
|
||||
|
|
35
shares.py
35
shares.py
|
@ -1032,6 +1032,41 @@ def get_shared_items_catalog_via_server(session, nickname: str, password: str,
|
|||
return catalog_json
|
||||
|
||||
|
||||
def get_offers_via_server(session, nickname: str, password: str,
|
||||
domain: str, port: int,
|
||||
http_prefix: str, debug: bool,
|
||||
signing_priv_key_pem: str) -> {}:
|
||||
"""Returns the offers collection for shared items via c2s
|
||||
"""
|
||||
if not session:
|
||||
print('WARN: No session for get_offers_via_server')
|
||||
return 6
|
||||
|
||||
auth_header = create_basic_auth_header(nickname, password)
|
||||
|
||||
headers = {
|
||||
'host': domain,
|
||||
'Content-type': 'application/json',
|
||||
'Authorization': auth_header,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
domain_full = get_full_domain(domain, port)
|
||||
url = local_actor_url(http_prefix, nickname, domain_full) + '/offers'
|
||||
if debug:
|
||||
print('Offers collection request to: ' + url)
|
||||
offers_json = get_json(signing_priv_key_pem, session, url, headers, None,
|
||||
debug, __version__, http_prefix, None)
|
||||
if not offers_json:
|
||||
if debug:
|
||||
print('DEBUG: GET offers collection failed for c2s to ' + url)
|
||||
# return 5
|
||||
|
||||
if debug:
|
||||
print('DEBUG: c2s GET offers collection success')
|
||||
|
||||
return offers_json
|
||||
|
||||
|
||||
def outbox_share_upload(base_dir: str, http_prefix: str,
|
||||
nickname: str, domain: str, port: int,
|
||||
message_json: {}, debug: bool, city: str,
|
||||
|
|
12
tests.py
12
tests.py
|
@ -198,6 +198,7 @@ from shares import update_shared_item_federation_token
|
|||
from shares import merge_shared_item_tokens
|
||||
from shares import send_share_via_server
|
||||
from shares import get_shared_items_catalog_via_server
|
||||
from shares import get_offers_via_server
|
||||
from cwlists import add_cw_from_lists
|
||||
from cwlists import load_cw_lists
|
||||
from happening import dav_month_via_server
|
||||
|
@ -2080,6 +2081,17 @@ def test_shared_items_federation(base_dir: str) -> None:
|
|||
assert 'DFC:supplies' in catalog_json
|
||||
assert len(catalog_json.get('DFC:supplies')) == 3
|
||||
|
||||
offers_json = \
|
||||
get_offers_via_server(session_bob, 'bob', bob_password,
|
||||
bob_domain, bob_port,
|
||||
http_prefix, True,
|
||||
signing_priv_key_pem)
|
||||
assert offers_json
|
||||
print('Offers collection:')
|
||||
pprint(offers_json)
|
||||
assert isinstance(offers_json, list)
|
||||
assert len(offers_json) == 1
|
||||
|
||||
print('\n\n*********************************************************')
|
||||
print('Alice sends a message to Bob')
|
||||
alice_tokens_filename = \
|
||||
|
|
2
utils.py
2
utils.py
|
@ -2398,7 +2398,7 @@ def _get_reserved_words() -> str:
|
|||
'mention', 'http', 'https', 'ipfs', 'ipns',
|
||||
'ontologies', 'data', 'postedit', 'moved',
|
||||
'inactive', 'activitypub', 'actors',
|
||||
'notes')
|
||||
'notes', 'offers', 'wanted')
|
||||
|
||||
|
||||
def get_nickname_validation_pattern() -> str:
|
||||
|
|
|
@ -11,6 +11,7 @@ import os
|
|||
from shutil import copyfile
|
||||
from collections import OrderedDict
|
||||
from session import get_json
|
||||
from utils import get_media_extensions
|
||||
from utils import dangerous_markup
|
||||
from utils import acct_handle_dir
|
||||
from utils import remove_id_ending
|
||||
|
@ -556,6 +557,94 @@ def shares_timeline_json(actor: str, page_number: int, items_per_page: int,
|
|||
return result_json, last_page
|
||||
|
||||
|
||||
def get_shares_collection(actor: str, page_number: int, items_per_page: int,
|
||||
base_dir: str, domain: str, nickname: str,
|
||||
max_shares_per_account: int,
|
||||
shared_items_federated_domains: [],
|
||||
shares_file_type: str) -> {}:
|
||||
"""Returns an ActivityStreams collection of Offer activities
|
||||
https://www.w3.org/TR/activitystreams-vocabulary/#dfn-offer
|
||||
"""
|
||||
shares_collection = []
|
||||
shares_json, _ = \
|
||||
shares_timeline_json(actor, page_number, items_per_page,
|
||||
base_dir, domain, nickname,
|
||||
max_shares_per_account,
|
||||
shared_items_federated_domains, shares_file_type)
|
||||
|
||||
if shares_file_type == 'shares':
|
||||
share_type = 'Offer'
|
||||
else:
|
||||
share_type = 'Want'
|
||||
|
||||
for _, shared_item in shares_json.items():
|
||||
if not shared_item.get('shareId'):
|
||||
continue
|
||||
if not shared_item.get('itemType'):
|
||||
continue
|
||||
share_id = shared_item['shareId'].replace('___', '://')
|
||||
share_id = share_id.replace('--', '/')
|
||||
offer_item = {
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"summary": shared_item['summary'],
|
||||
"type": share_type,
|
||||
"actor": shared_item['actor'],
|
||||
"id": share_id,
|
||||
"published": shared_item['published'],
|
||||
"object": {
|
||||
"id": share_id,
|
||||
"type": shared_item['itemType'].title(),
|
||||
"name": shared_item['displayName'],
|
||||
"published": shared_item['published'],
|
||||
"attachment": []
|
||||
}
|
||||
}
|
||||
if shared_item['category']:
|
||||
offer_item['object']['attachment'].append({
|
||||
"type": "PropertyValue",
|
||||
"name": "category",
|
||||
"value": shared_item['category']
|
||||
})
|
||||
if shared_item['location']:
|
||||
offer_item['object']['attachment'].append({
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"type": "Place",
|
||||
"name": shared_item['location'].title()
|
||||
})
|
||||
if shared_item['imageUrl']:
|
||||
if '://' in shared_item['imageUrl']:
|
||||
file_extension = None
|
||||
accepted_types = get_media_extensions()
|
||||
for mtype in accepted_types:
|
||||
if shared_item['imageUrl'].endswith('.' + mtype):
|
||||
if mtype == 'jpg':
|
||||
mtype = 'jpeg'
|
||||
if mtype == 'mp3':
|
||||
mtype = 'mpeg'
|
||||
file_extension = mtype
|
||||
if file_extension:
|
||||
media_type = 'image/' + file_extension
|
||||
offer_item['object']['attachment'].append({
|
||||
'mediaType': media_type,
|
||||
'name': shared_item['displayName'],
|
||||
'type': 'Document',
|
||||
'url': shared_item['imageUrl']
|
||||
})
|
||||
if shared_item['itemPrice'] and shared_item['itemCurrency']:
|
||||
offer_item['object']['attachment'].append({
|
||||
"type": "PropertyValue",
|
||||
"name": "price",
|
||||
"value": shared_item['itemPrice']
|
||||
})
|
||||
offer_item['object']['attachment'].append({
|
||||
"type": "PropertyValue",
|
||||
"name": "currency",
|
||||
"value": shared_item['itemCurrency']
|
||||
})
|
||||
shares_collection.append(offer_item)
|
||||
return shares_collection
|
||||
|
||||
|
||||
def post_contains_public(post_json_object: {}) -> bool:
|
||||
"""Does the given post contain #Public
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue