-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
daemon_post_moderator.py
336 lines (329 loc) · 15.6 KB
/
daemon_post_moderator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
__filename__ = "daemon_post_moderator.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.5.0"
__maintainer__ = "Bob Mottram"
__email__ = "[email protected]"
__status__ = "Production"
__module_group__ = "Core POST"
import os
import errno
import urllib.parse
from socket import error as SocketError
from utils import data_dir
from utils import delete_post
from utils import locate_post
from utils import get_full_domain
from utils import get_domain_from_actor
from utils import get_nickname_from_actor
from utils import get_instance_url
from posts import is_moderator
from httpcodes import write2
from httpheaders import redirect_headers
from httpheaders import login_headers
from webapp_moderation import html_account_info
from webapp_moderation import html_moderation_info
from person import can_remove_post
from person import remove_account
from person import suspend_account
from person import reenable_account
from filters import add_global_filter
from filters import remove_global_filter
from cache import clear_actor_cache
from blocking import add_global_block
from blocking import update_blocked_cache
from blocking import remove_global_block
def moderator_actions(self, path: str, calling_domain: str, cookie: str,
base_dir: str, http_prefix: str,
domain: str, port: int, debug: bool,
domain_full: str,
onion_domain: str, i2p_domain: str,
translate: {},
system_language: str,
signing_priv_key_pem: str,
block_federated: [],
theme_name: str,
access_keys: {}, person_cache: {},
recent_posts_cache: {},
blocked_cache: {},
mitm_servers: []) -> None:
"""Actions on the moderator screen
"""
users_path = path.replace('/moderationaction', '')
nickname = users_path.replace('/users/', '')
actor_str = \
get_instance_url(calling_domain,
http_prefix, domain_full,
onion_domain, i2p_domain) + \
users_path
if not is_moderator(base_dir, nickname):
redirect_headers(self, actor_str + '/moderation',
cookie, calling_domain, 303)
self.server.postreq_busy = False
return
length = int(self.headers['Content-length'])
try:
moderation_params = self.rfile.read(length).decode('utf-8')
except SocketError as ex:
if ex.errno == errno.ECONNRESET:
print('EX: POST moderation_params connection was reset')
else:
print('EX: POST moderation_params ' +
'rfile.read socket error')
self.send_response(400)
self.end_headers()
self.server.postreq_busy = False
return
except ValueError as ex:
print('EX: POST moderation_params rfile.read failed, ' +
str(ex))
self.send_response(400)
self.end_headers()
self.server.postreq_busy = False
return
if '&' in moderation_params:
moderation_text = None
moderation_button = None
# get the moderation text first
act_str = 'moderationAction='
for moderation_str in moderation_params.split('&'):
if moderation_str.startswith(act_str):
if act_str in moderation_str:
moderation_text = \
moderation_str.split(act_str)[1].strip()
mod_text = moderation_text.replace('+', ' ')
moderation_text = \
urllib.parse.unquote_plus(mod_text.strip())
# which button was pressed?
for moderation_str in moderation_params.split('&'):
if moderation_str.startswith('submitInfo='):
if not moderation_text and \
'submitInfo=' in moderation_str:
moderation_text = \
moderation_str.split('submitInfo=')[1].strip()
mod_text = moderation_text.replace('+', ' ')
moderation_text = \
urllib.parse.unquote_plus(mod_text.strip())
search_handle = moderation_text
if search_handle:
if '/@' in search_handle and \
'/@/' not in search_handle:
search_nickname = \
get_nickname_from_actor(search_handle)
if search_nickname:
search_domain, _ = \
get_domain_from_actor(search_handle)
if search_domain:
search_handle = \
search_nickname + '@' + search_domain
else:
search_handle = ''
else:
search_handle = ''
if '@' not in search_handle or \
'/@/' in search_handle:
if search_handle.startswith('http') or \
search_handle.startswith('ipfs') or \
search_handle.startswith('ipns'):
search_nickname = \
get_nickname_from_actor(search_handle)
if search_nickname:
search_domain, _ = \
get_domain_from_actor(search_handle)
if search_domain:
search_handle = \
search_nickname + '@' + \
search_domain
else:
search_handle = ''
else:
search_handle = ''
if '@' not in search_handle:
# is this a local nickname on this instance?
local_handle = \
search_handle + '@' + domain
dir_str = data_dir(base_dir)
if os.path.isdir(dir_str + '/' + local_handle):
search_handle = local_handle
else:
search_handle = ''
if search_handle is None:
search_handle = ''
if '@' in search_handle:
msg = \
html_account_info(translate,
base_dir, http_prefix,
nickname,
domain,
search_handle,
debug,
system_language,
signing_priv_key_pem,
None,
block_federated,
mitm_servers)
else:
msg = \
html_moderation_info(translate,
base_dir, nickname,
domain,
theme_name,
access_keys)
if msg:
msg = msg.encode('utf-8')
msglen = len(msg)
login_headers(self, 'text/html',
msglen, calling_domain)
write2(self, msg)
self.server.postreq_busy = False
return
if moderation_str.startswith('submitBlock'):
moderation_button = 'block'
elif moderation_str.startswith('submitUnblock'):
moderation_button = 'unblock'
elif moderation_str.startswith('submitFilter'):
moderation_button = 'filter'
elif moderation_str.startswith('submitUnfilter'):
moderation_button = 'unfilter'
elif moderation_str.startswith('submitClearCache'):
moderation_button = 'clearcache'
elif moderation_str.startswith('submitSuspend'):
moderation_button = 'suspend'
elif moderation_str.startswith('submitUnsuspend'):
moderation_button = 'unsuspend'
elif moderation_str.startswith('submitRemove'):
moderation_button = 'remove'
if moderation_button and moderation_text:
if debug:
print('moderation_button: ' + moderation_button)
print('moderation_text: ' + moderation_text)
nickname = moderation_text
if nickname.startswith('http') or \
nickname.startswith('ipfs') or \
nickname.startswith('ipns') or \
nickname.startswith('hyper'):
nickname = get_nickname_from_actor(nickname)
if '@' in nickname:
nickname = nickname.split('@')[0]
if moderation_button == 'suspend':
suspend_account(base_dir, nickname, domain)
if moderation_button == 'unsuspend':
reenable_account(base_dir, nickname)
if moderation_button == 'filter':
add_global_filter(base_dir, moderation_text)
if moderation_button == 'unfilter':
remove_global_filter(base_dir, moderation_text)
if moderation_button == 'clearcache':
clear_actor_cache(base_dir, person_cache,
moderation_text)
if moderation_button == 'block':
full_block_domain = None
moderation_text = moderation_text.strip()
moderation_reason = None
if ' ' in moderation_text:
moderation_domain = moderation_text.split(' ', 1)[0]
moderation_reason = moderation_text.split(' ', 1)[1]
else:
moderation_domain = moderation_text
if moderation_domain.startswith('http') or \
moderation_domain.startswith('ipfs') or \
moderation_domain.startswith('ipns') or \
moderation_domain.startswith('hyper'):
# https://domain
block_domain, block_port = \
get_domain_from_actor(moderation_domain)
if block_domain:
full_block_domain = \
get_full_domain(block_domain, block_port)
if '@' in moderation_domain:
# nick@domain or *@domain
full_block_domain = \
moderation_domain.split('@')[1]
else:
# assume the text is a domain name
if not full_block_domain and '.' in moderation_domain:
nickname = '*'
full_block_domain = \
moderation_domain.strip()
if full_block_domain or nickname.startswith('#'):
if nickname.startswith('#') and ' ' in nickname:
nickname = nickname.split(' ')[0]
add_global_block(base_dir, nickname,
full_block_domain, moderation_reason)
blocked_cache_last_updated = \
self.server.blocked_cache_last_updated
self.server.blocked_cache_last_updated = \
update_blocked_cache(base_dir, blocked_cache,
blocked_cache_last_updated, 0)
if moderation_button == 'unblock':
full_block_domain = None
if ' ' in moderation_text:
moderation_domain = moderation_text.split(' ', 1)[0]
else:
moderation_domain = moderation_text
if moderation_domain.startswith('http') or \
moderation_domain.startswith('ipfs') or \
moderation_domain.startswith('ipns') or \
moderation_domain.startswith('hyper'):
# https://domain
block_domain, block_port = \
get_domain_from_actor(moderation_domain)
if block_domain:
full_block_domain = \
get_full_domain(block_domain, block_port)
if '@' in moderation_domain:
# nick@domain or *@domain
full_block_domain = moderation_domain.split('@')[1]
else:
# assume the text is a domain name
if not full_block_domain and '.' in moderation_domain:
nickname = '*'
full_block_domain = moderation_domain.strip()
if full_block_domain or nickname.startswith('#'):
if nickname.startswith('#') and ' ' in nickname:
nickname = nickname.split(' ')[0]
remove_global_block(base_dir, nickname,
full_block_domain)
blocked_cache_last_updated = \
self.server.blocked_cache_last_updated
self.server.blocked_cache_last_updated = \
update_blocked_cache(base_dir, blocked_cache,
blocked_cache_last_updated, 0)
if moderation_button == 'remove':
if '/statuses/' not in moderation_text:
remove_account(base_dir, nickname, domain, port)
else:
# remove a post or thread
post_filename = \
locate_post(base_dir, nickname, domain,
moderation_text)
if post_filename:
if can_remove_post(base_dir, domain, port,
moderation_text):
delete_post(base_dir,
http_prefix,
nickname, domain,
post_filename,
debug,
recent_posts_cache,
True)
if nickname != 'news':
# if this is a local blog post then also remove it
# from the news actor
post_filename = \
locate_post(base_dir, 'news', domain,
moderation_text)
if post_filename:
if can_remove_post(base_dir, domain, port,
moderation_text):
delete_post(base_dir,
http_prefix,
'news', domain,
post_filename,
debug,
recent_posts_cache,
True)
redirect_headers(self, actor_str + '/moderation',
cookie, calling_domain, 303)
self.server.postreq_busy = False
return