mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of gitlab.com:bashrc2/epicyon
commit
9cf69b1911
23
daemon.py
23
daemon.py
|
|
@ -8,6 +8,7 @@ __status__ = "Production"
|
||||||
__module_group__ = "Core"
|
__module_group__ = "Core"
|
||||||
|
|
||||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer, HTTPServer
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer, HTTPServer
|
||||||
|
import copy
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
|
@ -2362,7 +2363,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
nickname, domain,
|
nickname, domain,
|
||||||
post_filename,
|
post_filename,
|
||||||
debug,
|
debug,
|
||||||
self.server.recent_posts_cache)
|
self.server.recent_posts_cache,
|
||||||
|
True)
|
||||||
if nickname != 'news':
|
if nickname != 'news':
|
||||||
# if this is a local blog post then also remove it
|
# if this is a local blog post then also remove it
|
||||||
# from the news actor
|
# from the news actor
|
||||||
|
|
@ -2378,7 +2380,8 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
'news', domain,
|
'news', domain,
|
||||||
post_filename,
|
post_filename,
|
||||||
debug,
|
debug,
|
||||||
self.server.recent_posts_cache)
|
self.server.recent_posts_cache,
|
||||||
|
True)
|
||||||
|
|
||||||
self._redirect_headers(actor_str + '/moderation',
|
self._redirect_headers(actor_str + '/moderation',
|
||||||
cookie, calling_domain)
|
cookie, calling_domain)
|
||||||
|
|
@ -8654,7 +8657,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
if self.server.iconsCache.get('repeat_inactive.png'):
|
if self.server.iconsCache.get('repeat_inactive.png'):
|
||||||
del self.server.iconsCache['repeat_inactive.png']
|
del self.server.iconsCache['repeat_inactive.png']
|
||||||
|
|
||||||
# delete the announce post
|
# delete the announce post
|
||||||
if '?unannounce=' in path:
|
if '?unannounce=' in path:
|
||||||
announce_url = path.split('?unannounce=')[1]
|
announce_url = path.split('?unannounce=')[1]
|
||||||
if '?' in announce_url:
|
if '?' in announce_url:
|
||||||
|
|
@ -8668,7 +8671,7 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
if post_filename:
|
if post_filename:
|
||||||
delete_post(base_dir, http_prefix,
|
delete_post(base_dir, http_prefix,
|
||||||
nickname, domain, post_filename,
|
nickname, domain, post_filename,
|
||||||
debug, recent_posts_cache)
|
debug, recent_posts_cache, True)
|
||||||
|
|
||||||
self._post_to_outbox(new_undo_announce,
|
self._post_to_outbox(new_undo_announce,
|
||||||
self.server.project_version,
|
self.server.project_version,
|
||||||
|
|
@ -19398,12 +19401,12 @@ class PubServer(BaseHTTPRequestHandler):
|
||||||
np_thread.kill()
|
np_thread.kill()
|
||||||
|
|
||||||
# make a copy of self.headers
|
# make a copy of self.headers
|
||||||
headers = {}
|
headers = copy.deepcopy(self.headers)
|
||||||
headers_without_cookie = {}
|
headers_without_cookie = copy.deepcopy(headers)
|
||||||
for dict_entry_name, header_line in self.headers.items():
|
if 'cookie' in headers_without_cookie:
|
||||||
headers[dict_entry_name] = header_line
|
del headers_without_cookie['cookie']
|
||||||
if dict_entry_name.lower() != 'cookie':
|
if 'Cookie' in headers_without_cookie:
|
||||||
headers_without_cookie[dict_entry_name] = header_line
|
del headers_without_cookie['Cookie']
|
||||||
print('New post headers: ' + str(headers_without_cookie))
|
print('New post headers: ' + str(headers_without_cookie))
|
||||||
|
|
||||||
length = int(headers['Content-Length'])
|
length = int(headers['Content-Length'])
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ def outbox_delete(base_dir: str, http_prefix: str,
|
||||||
print(message_id)
|
print(message_id)
|
||||||
return True
|
return True
|
||||||
delete_post(base_dir, http_prefix, delete_nickname, delete_domain,
|
delete_post(base_dir, http_prefix, delete_nickname, delete_domain,
|
||||||
post_filename, debug, recent_posts_cache)
|
post_filename, debug, recent_posts_cache, True)
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: post deleted via c2s - ' + post_filename)
|
print('DEBUG: post deleted via c2s - ' + post_filename)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -581,13 +581,16 @@ input[type=submit]:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-avatar {
|
.timeline-avatar {
|
||||||
margin: 10px auto;
|
margin: 0px 0px;
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
|
width: 8%;
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-avatar-reply {
|
.timeline-avatar-reply {
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
width: 80%;
|
width: 6%;
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result-text {
|
.search-result-text {
|
||||||
|
|
@ -795,11 +798,15 @@ div.gallery img {
|
||||||
}
|
}
|
||||||
.timeline-avatar img {
|
.timeline-avatar img {
|
||||||
opacity: 1.0;
|
opacity: 1.0;
|
||||||
width: 8%;
|
width: 100%;
|
||||||
height: 8%;
|
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
-ms-transform: translateY(-10%);
|
border-radius: var(--avatar-rounding);
|
||||||
transform: translateY(-10%);
|
}
|
||||||
|
.timeline-avatar-reply img {
|
||||||
|
opacity: 1.0;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0px 0px;
|
||||||
|
margin: 0px 10%;
|
||||||
border-radius: var(--avatar-rounding);
|
border-radius: var(--avatar-rounding);
|
||||||
}
|
}
|
||||||
.cwButton {
|
.cwButton {
|
||||||
|
|
@ -1149,13 +1156,28 @@ div.gallery img {
|
||||||
margin: 1% 3%;
|
margin: 1% 3%;
|
||||||
border-radius: 0%;
|
border-radius: 0%;
|
||||||
}
|
}
|
||||||
|
.timeline-avatar {
|
||||||
|
margin: 0px 0px;
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 15%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.timeline-avatar-reply {
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 12%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
.timeline-avatar img {
|
.timeline-avatar img {
|
||||||
opacity: 1.0;
|
opacity: 1.0;
|
||||||
width: 15%;
|
width: 100%;
|
||||||
height: 15%;
|
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
-ms-transform: translateY(-10%);
|
border-radius: var(--avatar-rounding);
|
||||||
transform: translateY(-10%);
|
}
|
||||||
|
.timeline-avatar-reply img {
|
||||||
|
opacity: 1.0;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0px 0px;
|
||||||
|
margin: 0px 10%;
|
||||||
border-radius: var(--avatar-rounding);
|
border-radius: var(--avatar-rounding);
|
||||||
}
|
}
|
||||||
.cwButton {
|
.cwButton {
|
||||||
|
|
@ -1496,13 +1518,28 @@ div.gallery img {
|
||||||
margin: 1% 3%;
|
margin: 1% 3%;
|
||||||
border-radius: 0%;
|
border-radius: 0%;
|
||||||
}
|
}
|
||||||
|
.timeline-avatar {
|
||||||
|
margin: 0px 0px;
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 15%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.timeline-avatar-reply {
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 12%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
.timeline-avatar img {
|
.timeline-avatar img {
|
||||||
opacity: 1.0;
|
opacity: 1.0;
|
||||||
width: 15%;
|
width: 100%;
|
||||||
height: 15%;
|
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
-ms-transform: translateY(-10%);
|
border-radius: var(--avatar-rounding);
|
||||||
transform: translateY(-10%);
|
}
|
||||||
|
.timeline-avatar-reply img {
|
||||||
|
opacity: 1.0;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0px 0px;
|
||||||
|
margin: 0px 10%;
|
||||||
border-radius: var(--avatar-rounding);
|
border-radius: var(--avatar-rounding);
|
||||||
}
|
}
|
||||||
.cwButton {
|
.cwButton {
|
||||||
|
|
|
||||||
|
|
@ -582,8 +582,10 @@ input[type=submit]:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-avatar {
|
.timeline-avatar {
|
||||||
margin: 10px auto;
|
margin: 0px 0px;
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
|
width: 8%;
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-avatar:hover {
|
.timeline-avatar:hover {
|
||||||
|
|
@ -592,7 +594,8 @@ input[type=submit]:hover {
|
||||||
|
|
||||||
.timeline-avatar-reply {
|
.timeline-avatar-reply {
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
width: 80%;
|
width: 6%;
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result-text {
|
.search-result-text {
|
||||||
|
|
@ -1054,11 +1057,15 @@ aside .toggle-inside li {
|
||||||
}
|
}
|
||||||
.timeline-avatar img {
|
.timeline-avatar img {
|
||||||
opacity: 1.0;
|
opacity: 1.0;
|
||||||
width: 8%;
|
width: 100%;
|
||||||
height: 8%;
|
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
-ms-transform: translateY(-10%);
|
border-radius: var(--avatar-rounding);
|
||||||
transform: translateY(-10%);
|
}
|
||||||
|
.timeline-avatar-reply img {
|
||||||
|
opacity: 1.0;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0px 0px;
|
||||||
|
margin: 0px 10%;
|
||||||
border-radius: var(--avatar-rounding);
|
border-radius: var(--avatar-rounding);
|
||||||
}
|
}
|
||||||
.buttonevent {
|
.buttonevent {
|
||||||
|
|
@ -1523,13 +1530,28 @@ aside .toggle-inside li {
|
||||||
margin: 1% 3%;
|
margin: 1% 3%;
|
||||||
border-radius: 0%;
|
border-radius: 0%;
|
||||||
}
|
}
|
||||||
|
.timeline-avatar {
|
||||||
|
margin: 0px 0px;
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 15%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.timeline-avatar-reply {
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 12%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
.timeline-avatar img {
|
.timeline-avatar img {
|
||||||
opacity: 1.0;
|
opacity: 1.0;
|
||||||
width: 15%;
|
width: 100%;
|
||||||
height: 15%;
|
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
-ms-transform: translateY(-10%);
|
border-radius: var(--avatar-rounding);
|
||||||
transform: translateY(-10%);
|
}
|
||||||
|
.timeline-avatar-reply img {
|
||||||
|
opacity: 1.0;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0px 0px;
|
||||||
|
margin: 0px 10%;
|
||||||
border-radius: var(--avatar-rounding);
|
border-radius: var(--avatar-rounding);
|
||||||
}
|
}
|
||||||
.buttonevent {
|
.buttonevent {
|
||||||
|
|
@ -1986,13 +2008,28 @@ aside .toggle-inside li {
|
||||||
margin: 1% 3%;
|
margin: 1% 3%;
|
||||||
border-radius: 0%;
|
border-radius: 0%;
|
||||||
}
|
}
|
||||||
|
.timeline-avatar {
|
||||||
|
margin: 0px 0px;
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 15%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.timeline-avatar-reply {
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 12%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
.timeline-avatar img {
|
.timeline-avatar img {
|
||||||
opacity: 1.0;
|
opacity: 1.0;
|
||||||
width: 15%;
|
width: 100%;
|
||||||
height: 15%;
|
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
-ms-transform: translateY(-10%);
|
border-radius: var(--avatar-rounding);
|
||||||
transform: translateY(-10%);
|
}
|
||||||
|
.timeline-avatar-reply img {
|
||||||
|
opacity: 1.0;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0px 0px;
|
||||||
|
margin: 0px 10%;
|
||||||
border-radius: var(--avatar-rounding);
|
border-radius: var(--avatar-rounding);
|
||||||
}
|
}
|
||||||
.buttonevent {
|
.buttonevent {
|
||||||
|
|
|
||||||
|
|
@ -885,8 +885,10 @@ input[type=submit]:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-avatar {
|
.timeline-avatar {
|
||||||
margin: 10px auto;
|
margin: 0px 0px;
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
|
width: 8%;
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.timeline-avatar:hover {
|
.timeline-avatar:hover {
|
||||||
|
|
@ -895,7 +897,8 @@ input[type=submit]:hover {
|
||||||
|
|
||||||
.timeline-avatar-reply {
|
.timeline-avatar-reply {
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
width: 80%;
|
width: 6%;
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result-text {
|
.search-result-text {
|
||||||
|
|
@ -1473,11 +1476,15 @@ h3 {
|
||||||
}
|
}
|
||||||
.timeline-avatar img {
|
.timeline-avatar img {
|
||||||
opacity: 1.0;
|
opacity: 1.0;
|
||||||
width: 8%;
|
width: 100%;
|
||||||
height: 8%;
|
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
-ms-transform: translateY(-10%);
|
border-radius: var(--avatar-rounding);
|
||||||
transform: translateY(-10%);
|
}
|
||||||
|
.timeline-avatar-reply img {
|
||||||
|
opacity: 1.0;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0px 0px;
|
||||||
|
margin: 0px 10%;
|
||||||
border-radius: var(--avatar-rounding);
|
border-radius: var(--avatar-rounding);
|
||||||
}
|
}
|
||||||
.buttonevent {
|
.buttonevent {
|
||||||
|
|
@ -2228,13 +2235,28 @@ h3 {
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
border-radius: 0%;
|
border-radius: 0%;
|
||||||
}
|
}
|
||||||
|
.timeline-avatar {
|
||||||
|
margin: 0px 0px;
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 15%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.timeline-avatar-reply {
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 12%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
.timeline-avatar img {
|
.timeline-avatar img {
|
||||||
opacity: 1.0;
|
opacity: 1.0;
|
||||||
width: 15%;
|
width: 100%;
|
||||||
height: 15%;
|
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
-ms-transform: translateY(-10%);
|
border-radius: var(--avatar-rounding);
|
||||||
transform: translateY(-10%);
|
}
|
||||||
|
.timeline-avatar-reply img {
|
||||||
|
opacity: 1.0;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0px 0px;
|
||||||
|
margin: 0px 10%;
|
||||||
border-radius: var(--avatar-rounding);
|
border-radius: var(--avatar-rounding);
|
||||||
}
|
}
|
||||||
.buttonevent {
|
.buttonevent {
|
||||||
|
|
@ -2988,13 +3010,28 @@ h3 {
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
border-radius: 0%;
|
border-radius: 0%;
|
||||||
}
|
}
|
||||||
|
.timeline-avatar {
|
||||||
|
margin: 0px 0px;
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 15%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.timeline-avatar-reply {
|
||||||
|
padding: 0px 0px;
|
||||||
|
width: 12%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
.timeline-avatar img {
|
.timeline-avatar img {
|
||||||
opacity: 1.0;
|
opacity: 1.0;
|
||||||
width: 15%;
|
width: 100%;
|
||||||
height: 15%;
|
|
||||||
padding: 0px 0px;
|
padding: 0px 0px;
|
||||||
-ms-transform: translateY(-10%);
|
border-radius: var(--avatar-rounding);
|
||||||
transform: translateY(-10%);
|
}
|
||||||
|
.timeline-avatar-reply img {
|
||||||
|
opacity: 1.0;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0px 0px;
|
||||||
|
margin: 0px 10%;
|
||||||
border-radius: var(--avatar-rounding);
|
border-radius: var(--avatar-rounding);
|
||||||
}
|
}
|
||||||
.buttonevent {
|
.buttonevent {
|
||||||
|
|
|
||||||
|
|
@ -1276,7 +1276,7 @@ def dav_delete_response(base_dir: str, nickname: str, domain: str,
|
||||||
token_post_id)
|
token_post_id)
|
||||||
delete_post(base_dir, http_prefix,
|
delete_post(base_dir, http_prefix,
|
||||||
nickname, domain, post_filename,
|
nickname, domain, post_filename,
|
||||||
debug, recent_posts_cache)
|
debug, recent_posts_cache, True)
|
||||||
return 'Ok'
|
return 'Ok'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
6
inbox.py
6
inbox.py
|
|
@ -2058,7 +2058,7 @@ def _receive_delete(session, handle: str, is_group: bool, base_dir: str,
|
||||||
return True
|
return True
|
||||||
delete_post(base_dir, http_prefix, handle_nickname,
|
delete_post(base_dir, http_prefix, handle_nickname,
|
||||||
handle_domain, post_filename, debug,
|
handle_domain, post_filename, debug,
|
||||||
recent_posts_cache)
|
recent_posts_cache, True)
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: post deleted - ' + post_filename)
|
print('DEBUG: post deleted - ' + post_filename)
|
||||||
|
|
||||||
|
|
@ -2069,7 +2069,7 @@ def _receive_delete(session, handle: str, is_group: bool, base_dir: str,
|
||||||
if post_filename:
|
if post_filename:
|
||||||
delete_post(base_dir, http_prefix, 'news',
|
delete_post(base_dir, http_prefix, 'news',
|
||||||
handle_domain, post_filename, debug,
|
handle_domain, post_filename, debug,
|
||||||
recent_posts_cache)
|
recent_posts_cache, True)
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: blog post deleted - ' + post_filename)
|
print('DEBUG: blog post deleted - ' + post_filename)
|
||||||
return True
|
return True
|
||||||
|
|
@ -4094,7 +4094,7 @@ def _inbox_after_initial(server, inbox_start_time,
|
||||||
if edited_filename != destination_filename:
|
if edited_filename != destination_filename:
|
||||||
delete_post(base_dir, http_prefix,
|
delete_post(base_dir, http_prefix,
|
||||||
nickname, domain, edited_filename,
|
nickname, domain, edited_filename,
|
||||||
debug, recent_posts_cache)
|
debug, recent_posts_cache, True)
|
||||||
|
|
||||||
# update the indexes for different timelines
|
# update the indexes for different timelines
|
||||||
for boxname in update_index_list:
|
for boxname in update_index_list:
|
||||||
|
|
|
||||||
2
posts.py
2
posts.py
|
|
@ -4294,7 +4294,7 @@ def archive_posts_for_person(http_prefix: str, nickname: str, domain: str,
|
||||||
'.json.' + ext))
|
'.json.' + ext))
|
||||||
else:
|
else:
|
||||||
delete_post(base_dir, http_prefix, nickname, domain,
|
delete_post(base_dir, http_prefix, nickname, domain,
|
||||||
file_path, False, recent_posts_cache)
|
file_path, False, recent_posts_cache, False)
|
||||||
|
|
||||||
# remove cached html posts
|
# remove cached html posts
|
||||||
post_cache_filename = \
|
post_cache_filename = \
|
||||||
|
|
|
||||||
19
tests.py
19
tests.py
|
|
@ -3393,11 +3393,14 @@ def test_client_to_server(base_dir: str):
|
||||||
|
|
||||||
inbox_path = bob_dir + '/accounts/bob@' + bob_domain + '/inbox'
|
inbox_path = bob_dir + '/accounts/bob@' + bob_domain + '/inbox'
|
||||||
outbox_path = alice_dir + '/accounts/alice@' + alice_domain + '/outbox'
|
outbox_path = alice_dir + '/accounts/alice@' + alice_domain + '/outbox'
|
||||||
posts_before = \
|
bob_posts_before = \
|
||||||
len([name for name in os.listdir(inbox_path)
|
len([name for name in os.listdir(inbox_path)
|
||||||
if os.path.isfile(os.path.join(inbox_path, name))])
|
if os.path.isfile(os.path.join(inbox_path, name))])
|
||||||
|
alice_posts_before = \
|
||||||
|
len([name for name in os.listdir(outbox_path)
|
||||||
|
if os.path.isfile(os.path.join(outbox_path, name))])
|
||||||
print('\n\nEVENT: Alice deletes her post: ' + outbox_post_id + ' ' +
|
print('\n\nEVENT: Alice deletes her post: ' + outbox_post_id + ' ' +
|
||||||
str(posts_before))
|
str(alice_posts_before))
|
||||||
password = 'alicepass'
|
password = 'alicepass'
|
||||||
send_delete_via_server(alice_dir, session_alice, 'alice', password,
|
send_delete_via_server(alice_dir, session_alice, 'alice', password,
|
||||||
alice_domain, alice_port,
|
alice_domain, alice_port,
|
||||||
|
|
@ -3408,14 +3411,20 @@ def test_client_to_server(base_dir: str):
|
||||||
if os.path.isdir(inbox_path):
|
if os.path.isdir(inbox_path):
|
||||||
test = len([name for name in os.listdir(inbox_path)
|
test = len([name for name in os.listdir(inbox_path)
|
||||||
if os.path.isfile(os.path.join(inbox_path, name))])
|
if os.path.isfile(os.path.join(inbox_path, name))])
|
||||||
if test == posts_before-1:
|
if test == bob_posts_before-1:
|
||||||
break
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
test = len([name for name in os.listdir(inbox_path)
|
test = len([name for name in os.listdir(inbox_path)
|
||||||
if os.path.isfile(os.path.join(inbox_path, name))])
|
if os.path.isfile(os.path.join(inbox_path, name))])
|
||||||
assert test == posts_before - 1
|
assert test == bob_posts_before - 1
|
||||||
print(">>> post deleted from Alice's outbox and Bob's inbox")
|
print(">>> post was deleted from Bob's inbox")
|
||||||
|
test = len([name for name in os.listdir(outbox_path)
|
||||||
|
if os.path.isfile(os.path.join(outbox_path, name))])
|
||||||
|
# this should be unchanged because a delete post was added
|
||||||
|
# at the outbox and one was removed
|
||||||
|
assert test == alice_posts_before
|
||||||
|
print(">>> post deleted from Alice's outbox")
|
||||||
assert valid_inbox(bob_dir, 'bob', bob_domain)
|
assert valid_inbox(bob_dir, 'bob', bob_domain)
|
||||||
assert valid_inbox_filenames(bob_dir, 'bob', bob_domain,
|
assert valid_inbox_filenames(bob_dir, 'bob', bob_domain,
|
||||||
alice_domain, alice_port)
|
alice_domain, alice_port)
|
||||||
|
|
|
||||||
108
utils.py
108
utils.py
|
|
@ -91,6 +91,15 @@ def get_actor_languages_list(actor_json: {}) -> []:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def has_object_dict(post_json_object: {}) -> bool:
|
||||||
|
"""Returns true if the given post has an object dict
|
||||||
|
"""
|
||||||
|
if post_json_object.get('object'):
|
||||||
|
if isinstance(post_json_object['object'], dict):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_content_from_post(post_json_object: {}, system_language: str,
|
def get_content_from_post(post_json_object: {}, system_language: str,
|
||||||
languages_understood: [],
|
languages_understood: [],
|
||||||
contentType: str = "content") -> str:
|
contentType: str = "content") -> str:
|
||||||
|
|
@ -1610,7 +1619,8 @@ def _is_reply_to_blog_post(base_dir: str, nickname: str, domain: str,
|
||||||
|
|
||||||
def _delete_post_remove_replies(base_dir: str, nickname: str, domain: str,
|
def _delete_post_remove_replies(base_dir: str, nickname: str, domain: str,
|
||||||
http_prefix: str, post_filename: str,
|
http_prefix: str, post_filename: str,
|
||||||
recent_posts_cache: {}, debug: bool) -> None:
|
recent_posts_cache: {}, debug: bool,
|
||||||
|
manual: bool) -> None:
|
||||||
"""Removes replies when deleting a post
|
"""Removes replies when deleting a post
|
||||||
"""
|
"""
|
||||||
replies_filename = post_filename.replace('.json', '.replies')
|
replies_filename = post_filename.replace('.json', '.replies')
|
||||||
|
|
@ -1626,7 +1636,7 @@ def _delete_post_remove_replies(base_dir: str, nickname: str, domain: str,
|
||||||
if os.path.isfile(reply_file):
|
if os.path.isfile(reply_file):
|
||||||
delete_post(base_dir, http_prefix,
|
delete_post(base_dir, http_prefix,
|
||||||
nickname, domain, reply_file, debug,
|
nickname, domain, reply_file, debug,
|
||||||
recent_posts_cache)
|
recent_posts_cache, manual)
|
||||||
# remove the replies file
|
# remove the replies file
|
||||||
try:
|
try:
|
||||||
os.remove(replies_filename)
|
os.remove(replies_filename)
|
||||||
|
|
@ -1794,9 +1804,53 @@ def _delete_conversation_post(base_dir: str, nickname: str, domain: str,
|
||||||
str(conversation_filename))
|
str(conversation_filename))
|
||||||
|
|
||||||
|
|
||||||
|
def is_dm(post_json_object: {}) -> bool:
|
||||||
|
"""Returns true if the given post is a DM
|
||||||
|
"""
|
||||||
|
if post_json_object['type'] != 'Create':
|
||||||
|
return False
|
||||||
|
if not has_object_dict(post_json_object):
|
||||||
|
return False
|
||||||
|
if post_json_object['object']['type'] != 'ChatMessage':
|
||||||
|
if post_json_object['object']['type'] != 'Note' and \
|
||||||
|
post_json_object['object']['type'] != 'Page' and \
|
||||||
|
post_json_object['object']['type'] != 'Patch' and \
|
||||||
|
post_json_object['object']['type'] != 'EncryptedMessage' and \
|
||||||
|
post_json_object['object']['type'] != 'Article':
|
||||||
|
return False
|
||||||
|
if post_json_object['object'].get('moderationStatus'):
|
||||||
|
return False
|
||||||
|
fields = ('to', 'cc')
|
||||||
|
for field_name in fields:
|
||||||
|
if not post_json_object['object'].get(field_name):
|
||||||
|
continue
|
||||||
|
for to_address in post_json_object['object'][field_name]:
|
||||||
|
if to_address.endswith('#Public'):
|
||||||
|
return False
|
||||||
|
if to_address.endswith('followers'):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def _is_remote_dm(domain_full: str, post_json_object: {}) -> bool:
|
||||||
|
"""Is the given post a DM from a different domain?
|
||||||
|
"""
|
||||||
|
if not is_dm(post_json_object):
|
||||||
|
return False
|
||||||
|
this_post_json = post_json_object
|
||||||
|
if has_object_dict(post_json_object):
|
||||||
|
this_post_json = post_json_object['object']
|
||||||
|
if this_post_json.get('attributedTo'):
|
||||||
|
if isinstance(this_post_json['attributedTo'], str):
|
||||||
|
if '://' + domain_full not in this_post_json['attributedTo']:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def delete_post(base_dir: str, http_prefix: str,
|
def delete_post(base_dir: str, http_prefix: str,
|
||||||
nickname: str, domain: str, post_filename: str,
|
nickname: str, domain: str, post_filename: str,
|
||||||
debug: bool, recent_posts_cache: {}) -> None:
|
debug: bool, recent_posts_cache: {},
|
||||||
|
manual: bool) -> None:
|
||||||
"""Recursively deletes a post and its replies and attachments
|
"""Recursively deletes a post and its replies and attachments
|
||||||
"""
|
"""
|
||||||
post_json_object = load_json(post_filename, 1)
|
post_json_object = load_json(post_filename, 1)
|
||||||
|
|
@ -1804,7 +1858,7 @@ def delete_post(base_dir: str, http_prefix: str,
|
||||||
# remove any replies
|
# remove any replies
|
||||||
_delete_post_remove_replies(base_dir, nickname, domain,
|
_delete_post_remove_replies(base_dir, nickname, domain,
|
||||||
http_prefix, post_filename,
|
http_prefix, post_filename,
|
||||||
recent_posts_cache, debug)
|
recent_posts_cache, debug, manual)
|
||||||
# finally, remove the post itself
|
# finally, remove the post itself
|
||||||
try:
|
try:
|
||||||
os.remove(post_filename)
|
os.remove(post_filename)
|
||||||
|
|
@ -1814,6 +1868,13 @@ def delete_post(base_dir: str, http_prefix: str,
|
||||||
str(post_filename))
|
str(post_filename))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# don't allow DMs to be deleted if they came from a different instance
|
||||||
|
# otherwise this breaks expectations about how DMs should operate
|
||||||
|
# i.e. DMs should only be removed if they are manually deleted
|
||||||
|
if not manual:
|
||||||
|
if _is_remote_dm(domain, post_json_object):
|
||||||
|
return
|
||||||
|
|
||||||
# don't allow deletion of bookmarked posts
|
# don't allow deletion of bookmarked posts
|
||||||
if _is_bookmarked(base_dir, nickname, domain, post_filename):
|
if _is_bookmarked(base_dir, nickname, domain, post_filename):
|
||||||
return
|
return
|
||||||
|
|
@ -1874,7 +1935,7 @@ def delete_post(base_dir: str, http_prefix: str,
|
||||||
# remove any replies
|
# remove any replies
|
||||||
_delete_post_remove_replies(base_dir, nickname, domain,
|
_delete_post_remove_replies(base_dir, nickname, domain,
|
||||||
http_prefix, post_filename,
|
http_prefix, post_filename,
|
||||||
recent_posts_cache, debug)
|
recent_posts_cache, debug, manual)
|
||||||
# finally, remove the post itself
|
# finally, remove the post itself
|
||||||
try:
|
try:
|
||||||
os.remove(post_filename)
|
os.remove(post_filename)
|
||||||
|
|
@ -2769,34 +2830,6 @@ def is_chat_message(post_json_object: {}) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def is_dm(post_json_object: {}) -> bool:
|
|
||||||
"""Returns true if the given post is a DM
|
|
||||||
"""
|
|
||||||
if post_json_object['type'] != 'Create':
|
|
||||||
return False
|
|
||||||
if not has_object_dict(post_json_object):
|
|
||||||
return False
|
|
||||||
if post_json_object['object']['type'] != 'ChatMessage':
|
|
||||||
if post_json_object['object']['type'] != 'Note' and \
|
|
||||||
post_json_object['object']['type'] != 'Page' and \
|
|
||||||
post_json_object['object']['type'] != 'Patch' and \
|
|
||||||
post_json_object['object']['type'] != 'EncryptedMessage' and \
|
|
||||||
post_json_object['object']['type'] != 'Article':
|
|
||||||
return False
|
|
||||||
if post_json_object['object'].get('moderationStatus'):
|
|
||||||
return False
|
|
||||||
fields = ('to', 'cc')
|
|
||||||
for field_name in fields:
|
|
||||||
if not post_json_object['object'].get(field_name):
|
|
||||||
continue
|
|
||||||
for to_address in post_json_object['object'][field_name]:
|
|
||||||
if to_address.endswith('#Public'):
|
|
||||||
return False
|
|
||||||
if to_address.endswith('followers'):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def is_reply(post_json_object: {}, actor: str) -> bool:
|
def is_reply(post_json_object: {}, actor: str) -> bool:
|
||||||
"""Returns true if the given post is a reply to the given actor
|
"""Returns true if the given post is a reply to the given actor
|
||||||
"""
|
"""
|
||||||
|
|
@ -3037,15 +3070,6 @@ def user_agent_domain(user_agent: str, debug: bool) -> str:
|
||||||
return agent_domain
|
return agent_domain
|
||||||
|
|
||||||
|
|
||||||
def has_object_dict(post_json_object: {}) -> bool:
|
|
||||||
"""Returns true if the given post has an object dict
|
|
||||||
"""
|
|
||||||
if post_json_object.get('object'):
|
|
||||||
if isinstance(post_json_object['object'], dict):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def get_alt_path(actor: str, domain_full: str, calling_domain: str) -> str:
|
def get_alt_path(actor: str, domain_full: str, calling_domain: str) -> str:
|
||||||
"""Returns alternate path from the actor
|
"""Returns alternate path from the actor
|
||||||
eg. https://clearnetdomain/path becomes http://oniondomain/path
|
eg. https://clearnetdomain/path becomes http://oniondomain/path
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue