mirror of https://gitlab.com/bashrc2/epicyon
followers_synchronization endpoint
parent
d170f6222c
commit
99d3558a46
61
daemon.py
61
daemon.py
|
@ -119,6 +119,7 @@ from inbox import run_inbox_queue_watchdog
|
||||||
from inbox import save_post_to_inbox_queue
|
from inbox import save_post_to_inbox_queue
|
||||||
from inbox import populate_replies
|
from inbox import populate_replies
|
||||||
from inbox import receive_edit_to_post
|
from inbox import receive_edit_to_post
|
||||||
|
from follow import get_followers_for_domain
|
||||||
from follow import follower_approval_active
|
from follow import follower_approval_active
|
||||||
from follow import is_following_actor
|
from follow import is_following_actor
|
||||||
from follow import get_following_feed
|
from follow import get_following_feed
|
||||||
|
@ -876,6 +877,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
def _secure_mode(self, curr_session, proxy_type: str,
|
def _secure_mode(self, curr_session, proxy_type: str,
|
||||||
force: bool = False) -> bool:
|
force: bool = False) -> bool:
|
||||||
"""http authentication of GET requests for json
|
"""http authentication of GET requests for json
|
||||||
|
aka authorized fetch
|
||||||
"""
|
"""
|
||||||
if not self.server.secure_mode and not force:
|
if not self.server.secure_mode and not force:
|
||||||
return True
|
return True
|
||||||
|
@ -16901,11 +16903,63 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
'_GET', '_security_txt[calling_domain]',
|
'_GET', '_security_txt[calling_domain]',
|
||||||
self.server.debug)
|
self.server.debug)
|
||||||
|
|
||||||
|
# followers synchronization
|
||||||
if self.path.startswith('/users/') and \
|
if self.path.startswith('/users/') and \
|
||||||
self.path.endswith('/followers_synchronization'):
|
self.path.endswith('/followers_synchronization'):
|
||||||
print('DEBUG: followers synchronization request ' +
|
if self.server.followers_synchronization:
|
||||||
self.path + ' ' + calling_domain)
|
# only do one request at a time
|
||||||
|
self._503()
|
||||||
|
return
|
||||||
|
self.server.followers_synchronization = True
|
||||||
|
if self.server.debug:
|
||||||
|
print('DEBUG: followers synchronization request ' +
|
||||||
|
self.path + ' ' + calling_domain)
|
||||||
|
# check authorized fetch
|
||||||
|
if self._secure_mode(curr_session, proxy_type):
|
||||||
|
nickname = get_nickname_from_actor(self.path)
|
||||||
|
sync_list = \
|
||||||
|
get_followers_for_domain(self.server.base_dir,
|
||||||
|
nickname, self.server.domain,
|
||||||
|
calling_domain)
|
||||||
|
id_str = self.server.http_prefix + '://' + \
|
||||||
|
self.server.domain_full + \
|
||||||
|
self.path.replace('/followers_synchronization',
|
||||||
|
'/followers?domain=' + calling_domain)
|
||||||
|
sync_json = {
|
||||||
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
|
'id': id_str,
|
||||||
|
'orderedItems': sync_list,
|
||||||
|
'type': 'OrderedCollection'
|
||||||
|
}
|
||||||
|
msg_str = json.dumps(sync_json, ensure_ascii=False)
|
||||||
|
msg_str = self._convert_domains(calling_domain, referer_domain,
|
||||||
|
msg_str)
|
||||||
|
msg = msg_str.encode('utf-8')
|
||||||
|
msglen = len(msg)
|
||||||
|
self._set_headers('application/json', msglen,
|
||||||
|
None, calling_domain, False)
|
||||||
|
self._write(msg)
|
||||||
|
self.server.followers_synchronization = False
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
# request was not signed
|
||||||
|
result_json = {
|
||||||
|
"error": "Request not signed"
|
||||||
|
}
|
||||||
|
msg_str = json.dumps(result_json, ensure_ascii=False)
|
||||||
|
msg = msg_str.encode('utf-8')
|
||||||
|
msglen = len(msg)
|
||||||
|
accept_str = self.headers['Accept']
|
||||||
|
if 'json' in accept_str:
|
||||||
|
protocol_str = \
|
||||||
|
get_json_content_from_accept(accept_str)
|
||||||
|
self._set_headers(protocol_str, msglen,
|
||||||
|
None, calling_domain, False)
|
||||||
|
self._write(msg)
|
||||||
|
self.server.followers_synchronization = False
|
||||||
|
return
|
||||||
self._404()
|
self._404()
|
||||||
|
self.server.followers_synchronization = False
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.path == '/logout':
|
if self.path == '/logout':
|
||||||
|
@ -23333,6 +23387,9 @@ def run_daemon(max_hashtags: int,
|
||||||
# scan the theme directory for any svg files containing scripts
|
# scan the theme directory for any svg files containing scripts
|
||||||
assert not scan_themes_for_scripts(base_dir)
|
assert not scan_themes_for_scripts(base_dir)
|
||||||
|
|
||||||
|
# lock for followers synchronization
|
||||||
|
httpd.followers_synchronization = False
|
||||||
|
|
||||||
# permitted sites from which the buy button may be displayed
|
# permitted sites from which the buy button may be displayed
|
||||||
httpd.buy_sites = load_buy_sites(base_dir)
|
httpd.buy_sites = load_buy_sites(base_dir)
|
||||||
|
|
||||||
|
|
45
follow.py
45
follow.py
|
@ -9,6 +9,7 @@ __module_group__ = "ActivityPub"
|
||||||
|
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import os
|
import os
|
||||||
|
from utils import get_user_paths
|
||||||
from utils import acct_handle_dir
|
from utils import acct_handle_dir
|
||||||
from utils import has_object_string_object
|
from utils import has_object_string_object
|
||||||
from utils import has_object_string_type
|
from utils import has_object_string_type
|
||||||
|
@ -1360,6 +1361,50 @@ def deny_follow_request_via_server(session,
|
||||||
return deny_html
|
return deny_html
|
||||||
|
|
||||||
|
|
||||||
|
def get_followers_for_domain(base_dir: str,
|
||||||
|
nickname: str, domain: str,
|
||||||
|
search_domain: str) -> []:
|
||||||
|
"""Returns the followers for a given domain
|
||||||
|
this is used for followers synchronization
|
||||||
|
"""
|
||||||
|
followers_filename = \
|
||||||
|
acct_dir(base_dir, nickname, domain) + '/followers.txt'
|
||||||
|
if not os.path.isfile(followers_filename):
|
||||||
|
return []
|
||||||
|
lines = []
|
||||||
|
try:
|
||||||
|
with open(followers_filename, 'r', encoding='utf-8') as fp_foll:
|
||||||
|
lines = fp_foll.read().splitlines()
|
||||||
|
except OSError:
|
||||||
|
print('EX: get_followers_for_domain unable to read followers ' +
|
||||||
|
followers_filename)
|
||||||
|
result = []
|
||||||
|
for line_str in lines:
|
||||||
|
if search_domain not in line_str:
|
||||||
|
continue
|
||||||
|
if line_str.endswith('@' + search_domain):
|
||||||
|
nick = line_str.split('@')[0]
|
||||||
|
paths_list = get_user_paths()
|
||||||
|
found = False
|
||||||
|
for prefix in ('https', 'http'):
|
||||||
|
if found:
|
||||||
|
break
|
||||||
|
for possible_path in paths_list:
|
||||||
|
url = prefix + '://' + search_domain + \
|
||||||
|
possible_path + nick
|
||||||
|
filename = base_dir + '/cache/actors/' + \
|
||||||
|
url.replace('/', '#') + '.json'
|
||||||
|
if not os.path.isfile(filename):
|
||||||
|
continue
|
||||||
|
if url not in result:
|
||||||
|
result.append(url)
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
elif '://' + search_domain in line_str:
|
||||||
|
result.append(line_str)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_followers_of_actor(base_dir: str, actor: str, debug: bool) -> {}:
|
def get_followers_of_actor(base_dir: str, actor: str, debug: bool) -> {}:
|
||||||
"""In a shared inbox if we receive a post we know who it's from
|
"""In a shared inbox if we receive a post we know who it's from
|
||||||
and if it's addressed to followers then we need to get a list of those.
|
and if it's addressed to followers then we need to get a list of those.
|
||||||
|
|
Loading…
Reference in New Issue