2024-03-03 11:54:32 +00:00
|
|
|
__filename__ = "daemon_get_collections.py"
|
|
|
|
|
__author__ = "Bob Mottram"
|
|
|
|
|
__license__ = "AGPL3+"
|
2026-01-02 11:36:24 +00:00
|
|
|
__version__ = "1.7.0"
|
2024-03-03 11:54:32 +00:00
|
|
|
__maintainer__ = "Bob Mottram"
|
|
|
|
|
__email__ = "bob@libreserver.org"
|
|
|
|
|
__status__ = "Production"
|
2024-12-25 14:31:14 +00:00
|
|
|
__module_group__ = "Daemon GET"
|
2024-03-03 11:54:32 +00:00
|
|
|
|
|
|
|
|
import json
|
2026-06-04 12:32:10 +00:00
|
|
|
from src.context import get_individual_post_context
|
|
|
|
|
from src.httpcodes import write2
|
|
|
|
|
from src.httpcodes import http_404
|
|
|
|
|
from src.httpheaders import set_headers
|
|
|
|
|
from src.posts import json_pin_post
|
|
|
|
|
from src.utils import convert_domains
|
|
|
|
|
from src.utils import get_json_content_from_accept
|
2026-07-18 18:32:41 +00:00
|
|
|
from src.utils import acct_dir
|
|
|
|
|
from src.utils import load_json
|
2026-06-04 12:32:10 +00:00
|
|
|
from src.follow import get_following_feed
|
2026-07-18 18:32:41 +00:00
|
|
|
from src.data import is_a_file
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_feature_authorization(self, calling_domain: str,
|
|
|
|
|
referer_domain: str,
|
|
|
|
|
base_dir: str,
|
|
|
|
|
http_prefix: str,
|
|
|
|
|
nickname: str, domain: str,
|
|
|
|
|
domain_full: str,
|
|
|
|
|
onion_domain: str,
|
|
|
|
|
i2p_domain: str,
|
|
|
|
|
yggdrasil_domain: str) -> None:
|
|
|
|
|
"""Returns the verification stamp for feature authorization
|
|
|
|
|
https://codeberg.org/fediverse/fep/src/branch/main/fep/7aa9/fep-7aa9.md
|
|
|
|
|
"""
|
2026-07-19 11:46:38 +00:00
|
|
|
if '/stamps/' not in self.path:
|
|
|
|
|
return
|
2026-07-18 18:32:41 +00:00
|
|
|
stamp_number = self.path.split('/stamps/')[1]
|
|
|
|
|
if '/' in stamp_number:
|
|
|
|
|
stamp_number = stamp_number.split('/')[0]
|
|
|
|
|
if not stamp_number:
|
|
|
|
|
return
|
|
|
|
|
if not stamp_number.isdigit():
|
|
|
|
|
return
|
|
|
|
|
# does the stamp exist?
|
|
|
|
|
account_dir = acct_dir(base_dir, nickname, domain)
|
|
|
|
|
stamp_filename = account_dir + '/stamps/' + stamp_number
|
|
|
|
|
if not is_a_file(stamp_filename):
|
|
|
|
|
return
|
|
|
|
|
# load the stamp from file
|
|
|
|
|
stamp_json = load_json(stamp_filename)
|
|
|
|
|
if not stamp_json:
|
|
|
|
|
return
|
|
|
|
|
if not stamp_json.get('id') or not stamp_json.get('object'):
|
|
|
|
|
return
|
|
|
|
|
# create the verification
|
|
|
|
|
stamp_url = \
|
|
|
|
|
http_prefix + '://' + domain_full + '/users/' + nickname + \
|
|
|
|
|
'/stamps/' + stamp_number
|
|
|
|
|
verification_json = {
|
|
|
|
|
"@context": [
|
|
|
|
|
"https://www.w3.org/ns/activitystreams",
|
|
|
|
|
"https://gotosocial.org/ns",
|
|
|
|
|
"https://w3id.org/fep/7aa9"
|
|
|
|
|
],
|
|
|
|
|
"id": stamp_url,
|
|
|
|
|
"type": "FeatureAuthorization",
|
|
|
|
|
"interactingObject": stamp_json['id'],
|
|
|
|
|
"interactionTarget": stamp_json['object']
|
|
|
|
|
}
|
|
|
|
|
# send the verification
|
|
|
|
|
msg_str = json.dumps(verification_json, ensure_ascii=False)
|
|
|
|
|
msg_str = convert_domains(calling_domain, referer_domain,
|
|
|
|
|
msg_str, http_prefix,
|
|
|
|
|
domain, onion_domain, i2p_domain,
|
|
|
|
|
yggdrasil_domain)
|
|
|
|
|
msg = msg_str.encode('utf-8')
|
|
|
|
|
msglen = len(msg)
|
|
|
|
|
accept_str = self.headers['Accept']
|
|
|
|
|
protocol_str = get_json_content_from_accept(accept_str)
|
|
|
|
|
set_headers(self, protocol_str, msglen, None, calling_domain, False)
|
|
|
|
|
write2(self, msg)
|
2024-03-03 11:54:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_featured_collection(self, calling_domain: str,
|
|
|
|
|
referer_domain: str,
|
|
|
|
|
base_dir: str,
|
|
|
|
|
http_prefix: str,
|
|
|
|
|
nickname: str, domain: str,
|
|
|
|
|
domain_full: str,
|
2024-04-12 10:31:08 +00:00
|
|
|
system_language: str,
|
|
|
|
|
onion_domain: str,
|
2026-02-23 12:38:32 +00:00
|
|
|
i2p_domain: str,
|
|
|
|
|
yggdrasil_domain: str) -> None:
|
2024-03-03 11:54:32 +00:00
|
|
|
"""Returns the featured posts collections in
|
|
|
|
|
actor/collections/featured
|
|
|
|
|
"""
|
|
|
|
|
featured_collection = \
|
|
|
|
|
json_pin_post(base_dir, http_prefix,
|
|
|
|
|
nickname, domain, domain_full, system_language)
|
|
|
|
|
msg_str = json.dumps(featured_collection,
|
|
|
|
|
ensure_ascii=False)
|
2024-04-12 10:31:08 +00:00
|
|
|
msg_str = convert_domains(calling_domain, referer_domain,
|
2024-03-03 11:54:32 +00:00
|
|
|
msg_str, http_prefix,
|
2026-02-23 12:38:32 +00:00
|
|
|
domain, onion_domain, i2p_domain,
|
|
|
|
|
yggdrasil_domain)
|
2024-03-03 11:54:32 +00:00
|
|
|
msg = msg_str.encode('utf-8')
|
|
|
|
|
msglen = len(msg)
|
|
|
|
|
accept_str = self.headers['Accept']
|
|
|
|
|
protocol_str = \
|
|
|
|
|
get_json_content_from_accept(accept_str)
|
|
|
|
|
set_headers(self, protocol_str, msglen,
|
|
|
|
|
None, calling_domain, False)
|
|
|
|
|
write2(self, msg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_featured_tags_collection(self, calling_domain: str,
|
|
|
|
|
referer_domain: str,
|
2024-04-12 10:31:08 +00:00
|
|
|
path: str, http_prefix: str,
|
|
|
|
|
domain_full: str, domain: str,
|
2026-02-23 12:38:32 +00:00
|
|
|
onion_domain: str, i2p_domain: str,
|
|
|
|
|
yggdrasil_domain: str) -> None:
|
2024-03-03 11:54:32 +00:00
|
|
|
"""Returns the featured tags collections in
|
|
|
|
|
actor/collections/featuredTags
|
|
|
|
|
"""
|
|
|
|
|
post_context = get_individual_post_context()
|
|
|
|
|
featured_tags_collection = {
|
|
|
|
|
'@context': post_context,
|
|
|
|
|
'id': http_prefix + '://' + domain_full + path,
|
|
|
|
|
'orderedItems': [],
|
|
|
|
|
'totalItems': 0,
|
|
|
|
|
'type': 'OrderedCollection'
|
|
|
|
|
}
|
|
|
|
|
msg_str = json.dumps(featured_tags_collection,
|
|
|
|
|
ensure_ascii=False)
|
|
|
|
|
msg_str = convert_domains(calling_domain,
|
|
|
|
|
referer_domain,
|
|
|
|
|
msg_str, http_prefix,
|
|
|
|
|
domain,
|
2024-04-12 10:31:08 +00:00
|
|
|
onion_domain,
|
2026-02-23 12:38:32 +00:00
|
|
|
i2p_domain,
|
|
|
|
|
yggdrasil_domain)
|
2024-03-03 11:54:32 +00:00
|
|
|
msg = msg_str.encode('utf-8')
|
|
|
|
|
msglen = len(msg)
|
|
|
|
|
accept_str = self.headers['Accept']
|
|
|
|
|
protocol_str = \
|
|
|
|
|
get_json_content_from_accept(accept_str)
|
|
|
|
|
set_headers(self, protocol_str, msglen,
|
|
|
|
|
None, calling_domain, False)
|
|
|
|
|
write2(self, msg)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_following_json(self, base_dir: str, path: str,
|
|
|
|
|
calling_domain: str, referer_domain: str,
|
|
|
|
|
http_prefix: str,
|
|
|
|
|
domain: str, port: int,
|
|
|
|
|
following_items_per_page: int,
|
2024-04-12 10:31:08 +00:00
|
|
|
debug: bool, list_name: str,
|
2026-02-23 12:38:32 +00:00
|
|
|
onion_domain: str, i2p_domain: str,
|
|
|
|
|
yggdrasil_domain: str) -> None:
|
2024-03-03 11:54:32 +00:00
|
|
|
"""Returns json collection for following.txt
|
|
|
|
|
"""
|
|
|
|
|
following_json = \
|
|
|
|
|
get_following_feed(base_dir, domain, port, path, http_prefix,
|
|
|
|
|
True, following_items_per_page, list_name)
|
|
|
|
|
if not following_json:
|
|
|
|
|
if debug:
|
|
|
|
|
print(list_name + ' json feed not found for ' + path)
|
|
|
|
|
http_404(self, 109)
|
|
|
|
|
return
|
|
|
|
|
msg_str = json.dumps(following_json,
|
|
|
|
|
ensure_ascii=False)
|
|
|
|
|
msg_str = convert_domains(calling_domain,
|
|
|
|
|
referer_domain,
|
|
|
|
|
msg_str, http_prefix,
|
|
|
|
|
domain,
|
2024-04-12 10:31:08 +00:00
|
|
|
onion_domain,
|
2026-02-23 12:38:32 +00:00
|
|
|
i2p_domain,
|
|
|
|
|
yggdrasil_domain)
|
2024-03-03 11:54:32 +00:00
|
|
|
msg = msg_str.encode('utf-8')
|
|
|
|
|
msglen = len(msg)
|
|
|
|
|
accept_str = self.headers['Accept']
|
|
|
|
|
protocol_str = \
|
|
|
|
|
get_json_content_from_accept(accept_str)
|
|
|
|
|
set_headers(self, protocol_str, msglen,
|
|
|
|
|
None, calling_domain, False)
|
|
|
|
|
write2(self, msg)
|