From 3780993fd8cf204924de4d38a0b34a2a59bfe3bc Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Mon, 31 Jan 2022 16:54:36 +1100 Subject: [PATCH 01/11] remove some notifs --- components/notifiers.py | 2 +- components/watchers.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/notifiers.py b/components/notifiers.py index c5b454c..ea042b4 100644 --- a/components/notifiers.py +++ b/components/notifiers.py @@ -10,7 +10,7 @@ class Notifier(ABC): class TermuxNotifier(Notifier): def notify(self, title, content, *args, **kwargs): - subprocess.call(['termux-notification', '--title', title, '--content', content]) + subprocess.call(['termux-notification', '--title', title, '--content', content or 'No Message']) class NotifySendNotifier(Notifier): diff --git a/components/watchers.py b/components/watchers.py index 7ad5dbf..ad5445c 100644 --- a/components/watchers.py +++ b/components/watchers.py @@ -35,12 +35,12 @@ class RecentWatcher(Watcher): def connect(): logging.debug(f'Live posts client connected') client.emit('room', f'{board}-manage-recent-hashed' if board else 'globalmanage-recent-hashed') - notify(f'Connected', f'Watching live posts') + #notify(f'Connected', f'Watching live posts') @client.event def disconnect(): logging.error(f'Live posts client disconnected') - notify(f'Lost live posts connection', f'Retrying in {reconnection_delay} seconds') + #notify(f'Lost live posts connection', f'Retrying in {reconnection_delay} seconds') @client.on('newPost') def on_new_post(post): @@ -88,7 +88,7 @@ class ReportsWatcher(Watcher): except RequestException as e: logging.error(f'Exception {e} occurred while fetching reports') - self.notify(f'Error while fetching reports', f'Trying to reconnect') + #self.notify(f'Error while fetching reports', f'Trying to reconnect') if self._stp.wait(self.fetch_interval): logging.info("Exiting reports watcher") From 7a7c2dc4c2e1596ef1573a59f859b553063f8c52 Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Mon, 31 Jan 2022 17:29:10 +1100 Subject: [PATCH 02/11] add action url to open to post --- components/notifiers.py | 10 ++++++---- components/watchers.py | 7 ++----- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/components/notifiers.py b/components/notifiers.py index ea042b4..54a9f1f 100644 --- a/components/notifiers.py +++ b/components/notifiers.py @@ -4,15 +4,17 @@ from abc import ABC, abstractmethod class Notifier(ABC): @abstractmethod - def notify(self, title, content, *args, **kwargs): + def notify(self, title, content, url, *args, **kwargs): raise NotImplementedError class TermuxNotifier(Notifier): - def notify(self, title, content, *args, **kwargs): - subprocess.call(['termux-notification', '--title', title, '--content', content or 'No Message']) + def notify(self, title, content, url, *args, **kwargs): + print(url) + subprocess.call(['termux-notification', '--title', title, '--content', content or 'No Message', '--action', 'termux-open-url', url]) class NotifySendNotifier(Notifier): - def notify(self, title, content, *args, **kwargs): + def notify(self, title, content, url, *args, **kwargs): + print(url) subprocess.call(['notify-send', title, content]) diff --git a/components/watchers.py b/components/watchers.py index ad5445c..91dbd14 100644 --- a/components/watchers.py +++ b/components/watchers.py @@ -5,10 +5,8 @@ from threading import Thread, Event import socketio from requests import RequestException - def get_path(post): return f'>>>/{post["board"]}/{post["thread"] or post["postId"]} ({post["postId"]})' - class Watcher(ABC, Thread): def __init__(self, session): Thread.__init__(self) @@ -44,9 +42,8 @@ class RecentWatcher(Watcher): @client.on('newPost') def on_new_post(post): - urls, entries = evaluate(post["nomarkup"]) - if urls or entries: - notify(f'Alert! {get_path(post)}', '\n'.join(urls) + '\n'.join(entries)) + board_name = post["board"] + notify(f'Alert! {get_path(post)}\n', post['nomarkup'], f'{session.imageboard_url}/{board_name}/manage/thread/{post["thread"] or post["postId"]}.html#{post["postId"]}') self.client = client self.start() From 578839a5b57714e849e2eb186ba1b4c107b20976 Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Tue, 1 Feb 2022 20:05:15 +1100 Subject: [PATCH 03/11] move url to kwargs, update button action calls for upcoming feature --- components/notifiers.py | 19 ++++++++++++------- components/watchers.py | 8 +++----- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/components/notifiers.py b/components/notifiers.py index 54a9f1f..cd786ce 100644 --- a/components/notifiers.py +++ b/components/notifiers.py @@ -4,17 +4,22 @@ from abc import ABC, abstractmethod class Notifier(ABC): @abstractmethod - def notify(self, title, content, url, *args, **kwargs): + def notify(self, title, content, *args, **kwargs): raise NotImplementedError class TermuxNotifier(Notifier): - def notify(self, title, content, url, *args, **kwargs): - print(url) - subprocess.call(['termux-notification', '--title', title, '--content', content or 'No Message', '--action', 'termux-open-url', url]) - + def notify(self, title, content, *args, **kwargs): + subprocess.call(['termux-notification', '--title', title, + '--content', content or 'No Message', + '--action', f'termux-open-url {kwargs["url"]}' + '--button1', 'Delete', + '--button1-action', f'python3 notification_button.py -b {kwargs["board"]} -id {kwargs["postId"]} -a delete', + '--button2', 'Ban+Delete', + '--button2-action', f'python3 notificaiton_button.py -b {kwargs["board"]} -id {kwargs["postId"]} -a delete+ban', + '--button3', 'Dismiss', + '--button3-action', f'python3 notification_button.py -b {kwargs["board"]} -id {kwargs["postId"]} -a dismiss']) class NotifySendNotifier(Notifier): - def notify(self, title, content, url, *args, **kwargs): - print(url) + def notify(self, title, content, *args, **kwargs): subprocess.call(['notify-send', title, content]) diff --git a/components/watchers.py b/components/watchers.py index 91dbd14..e5b6ea7 100644 --- a/components/watchers.py +++ b/components/watchers.py @@ -33,17 +33,16 @@ class RecentWatcher(Watcher): def connect(): logging.debug(f'Live posts client connected') client.emit('room', f'{board}-manage-recent-hashed' if board else 'globalmanage-recent-hashed') - #notify(f'Connected', f'Watching live posts') @client.event def disconnect(): logging.error(f'Live posts client disconnected') - #notify(f'Lost live posts connection', f'Retrying in {reconnection_delay} seconds') @client.on('newPost') def on_new_post(post): - board_name = post["board"] - notify(f'Alert! {get_path(post)}\n', post['nomarkup'], f'{session.imageboard_url}/{board_name}/manage/thread/{post["thread"] or post["postId"]}.html#{post["postId"]}') + board_name=post["board"] + post_url=f'{session.imageboard_url}/{board_name}/manage/thread/{post["thread"] or post["postId"]}.html#{post["postId"]}' + notify(f'Alert! {get_path(post)}\n', post['nomarkup'], url=post_url) self.client = client self.start() @@ -85,7 +84,6 @@ class ReportsWatcher(Watcher): except RequestException as e: logging.error(f'Exception {e} occurred while fetching reports') - #self.notify(f'Error while fetching reports', f'Trying to reconnect') if self._stp.wait(self.fetch_interval): logging.info("Exiting reports watcher") From 9fe2e61afa4ab1963ce692230bc4f1ed58a47004 Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Tue, 1 Feb 2022 20:13:45 +1100 Subject: [PATCH 04/11] notification_button.py with csrf update and args, no posting actions yet --- components/notifiers.py | 6 +++--- notification_button.py | 28 ++++++++++++++++++++++++++++ session.py | 22 ++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100755 notification_button.py diff --git a/components/notifiers.py b/components/notifiers.py index cd786ce..4c635c5 100644 --- a/components/notifiers.py +++ b/components/notifiers.py @@ -14,11 +14,11 @@ class TermuxNotifier(Notifier): '--content', content or 'No Message', '--action', f'termux-open-url {kwargs["url"]}' '--button1', 'Delete', - '--button1-action', f'python3 notification_button.py -b {kwargs["board"]} -id {kwargs["postId"]} -a delete', + '--button1-action', f'python3 notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete', '--button2', 'Ban+Delete', - '--button2-action', f'python3 notificaiton_button.py -b {kwargs["board"]} -id {kwargs["postId"]} -a delete+ban', + '--button2-action', f'python3 notificaiton_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete+ban', '--button3', 'Dismiss', - '--button3-action', f'python3 notification_button.py -b {kwargs["board"]} -id {kwargs["postId"]} -a dismiss']) + '--button3-action', f'python3 notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a dismiss']) class NotifySendNotifier(Notifier): def notify(self, title, content, *args, **kwargs): diff --git a/notification_button.py b/notification_button.py new file mode 100755 index 0000000..c4e8a64 --- /dev/null +++ b/notification_button.py @@ -0,0 +1,28 @@ +import logging + +import sys, getopt +from config import config +from session import ModSession + +def main(argv): + logging.basicConfig(level=logging.DEBUG, + format='[%(asctime)s %(funcName)s] %(message)s (%(name)s)') + + try: + opts, args = getopt.getopt(argv, 'b:p:a:', ['board=', 'postid=', 'actions=']) + optdict = dict(opts) + except getopt.GetoptError: + logging.error('invalid arguments') + sys.exit(1) + + session = ModSession(imageboard=config.IMAGEBOARD, username=config.ACCOUNT_USERNAME, + password=config.ACCOUNT_PASSWORD, retries=config.REQUEST_RETRIES, + timeout=config.REQUEST_TIMEOUT, backoff_factor=config.RETRIES_BACKOFF_FACTOR) + + session.update_csrf() + + #todo: for board, postid and action args, send the request + session.post_actions(board=optdict['-b'], postid=optdict['-p'], actions=optdict['-a']) + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/session.py b/session.py index 4924922..f5ee789 100644 --- a/session.py +++ b/session.py @@ -12,6 +12,7 @@ class ModSession(Session): self.imageboard = imageboard self.imageboard_url = f"https://{imageboard}" self.auth_params = {'username': username, 'password': password} + self.csrf_token = None # overwrites session default behaviour self.mount(self.imageboard_url, HTTPAdapter(max_retries=Retry(total=retries, backoff_factor=backoff_factor))) @@ -32,3 +33,24 @@ class ModSession(Session): except requests.RequestException as e: # ambiguous catch but atm nothing can be done in more specific cases logging.error(f'Exception {e} occurred while authenticating moderator') raise Exception('Unable to authenticate moderator') + + def update_csrf(self): + try: + res = self.get(url=f'{self.imageboard_url}/csrf.json', + headers={'Referer': f'{self.imageboard_url}/csrf.json'}).json() + if 'token' in res: + self.csrf_token = res['token'] + else: + raise Exception('Unable to update csrf token') + except requests.RequestException as e: + logging.error(f'Exception {e} occurred while updating csrf token') + raise Exception('Unable to update csrf token') + + def post_actions(self, **kwargs): + try: + raise Exception('not implemented') +# res = self.post(url=f'{self.imageboard_url}/forms/board/{kwargs["board"]}/modactions', +# headers={'Referer': f'{self.imageboard_url}/forms/board/{kwargs["board"]}/modactions'}).json() + except requests.RequestException as e: + logging.error(f'Exception {e} occurred while authenticating moderator') + raise Exception('Failed to submit post actions') From 9b0fc04749756a1f7a126afa05917f21cf17c7a0 Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Wed, 2 Feb 2022 16:39:05 +1100 Subject: [PATCH 05/11] make the form submission work, and add a temp hack for csrf until 0.2.0 jschan --- notification_button.py | 6 ++++-- session.py | 33 +++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/notification_button.py b/notification_button.py index c4e8a64..3b86870 100755 --- a/notification_button.py +++ b/notification_button.py @@ -1,4 +1,5 @@ import logging +import subprocess import sys, getopt from config import config @@ -21,8 +22,9 @@ def main(argv): session.update_csrf() - #todo: for board, postid and action args, send the request - session.post_actions(board=optdict['-b'], postid=optdict['-p'], actions=optdict['-a']) + res = session.post_actions(board=optdict['-b'], postid=optdict['-p'], actions=optdict['-a']) + if 'message' in res: + subprocess.call(['termux-toast', res['message']]) if __name__ == '__main__': main(sys.argv[1:]) diff --git a/session.py b/session.py index f5ee789..3f98be2 100644 --- a/session.py +++ b/session.py @@ -36,21 +36,34 @@ class ModSession(Session): def update_csrf(self): try: - res = self.get(url=f'{self.imageboard_url}/csrf.json', - headers={'Referer': f'{self.imageboard_url}/csrf.json'}).json() - if 'token' in res: - self.csrf_token = res['token'] - else: - raise Exception('Unable to update csrf token') + +# res = self.get(url=f'{self.imageboard_url}/csrf.json', +# headers={'Referer': f'{self.imageboard_url}/csrf.json'}).json() +# if 'token' in res: +# self.csrf_token = res['token'] +# else: +# raise Exception('Unable to update csrf token') + + #temporary hack to get csrf token to test on <=0.1.10 + res2 = self.get(url=f'{self.imageboard_url}/account.html', + headers={'Referer': f'{self.imageboard_url}/account.html'}) + csrfi = res2.text.index('_csrf') + self.csrf_token = res2.text[csrfi+14:csrfi+50] + except requests.RequestException as e: logging.error(f'Exception {e} occurred while updating csrf token') raise Exception('Unable to update csrf token') def post_actions(self, **kwargs): try: - raise Exception('not implemented') -# res = self.post(url=f'{self.imageboard_url}/forms/board/{kwargs["board"]}/modactions', -# headers={'Referer': f'{self.imageboard_url}/forms/board/{kwargs["board"]}/modactions'}).json() + actions = kwargs['actions'].split(',') + body = {'checkedposts':kwargs["postid"],'_csrf':self.csrf_token,'log_message':'globalafk'} + for action in actions: + body[action] = '1' + res = self.post(url=f'{self.imageboard_url}/forms/board/{kwargs["board"]}/modactions', + headers={'Referer': f'{self.imageboard_url}/forms/board/{kwargs["board"]}/modactions','x-using-xhr': 'true'}, + data=body).json() + return res except requests.RequestException as e: - logging.error(f'Exception {e} occurred while authenticating moderator') + logging.error(f'Exception {e} occurred while posting action') raise Exception('Failed to submit post actions') From 8adc1573497a1dc91149da94e34514e465e97467 Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Wed, 2 Feb 2022 16:52:27 +1100 Subject: [PATCH 06/11] change notification button options, dont display for reports --- components/notifiers.py | 21 +++++++++++---------- components/watchers.py | 5 ++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/components/notifiers.py b/components/notifiers.py index 4c635c5..77256e6 100644 --- a/components/notifiers.py +++ b/components/notifiers.py @@ -7,18 +7,19 @@ class Notifier(ABC): def notify(self, title, content, *args, **kwargs): raise NotImplementedError - class TermuxNotifier(Notifier): def notify(self, title, content, *args, **kwargs): - subprocess.call(['termux-notification', '--title', title, - '--content', content or 'No Message', - '--action', f'termux-open-url {kwargs["url"]}' - '--button1', 'Delete', - '--button1-action', f'python3 notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete', - '--button2', 'Ban+Delete', - '--button2-action', f'python3 notificaiton_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete+ban', - '--button3', 'Dismiss', - '--button3-action', f'python3 notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a dismiss']) + args = ['termux-notification', '--title', title, + '--content', content or 'No Message'] + if 'url' in kwargs: + args = args + ['--action', f'termux-open-url {kwargs["url"]}', + '--button1', 'Delete', + '--button1-action', f'python3 notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete', + '--button2', 'Delete+Ban', + '--button2-action', f'python3 notificaiton_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete,ban', + '--button3', 'Delete+Global Ban', + '--button3-action', f'python3 notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete,global_ban'] + subprocess.call(args) class NotifySendNotifier(Notifier): def notify(self, title, content, *args, **kwargs): diff --git a/components/watchers.py b/components/watchers.py index e5b6ea7..38756be 100644 --- a/components/watchers.py +++ b/components/watchers.py @@ -40,9 +40,8 @@ class RecentWatcher(Watcher): @client.on('newPost') def on_new_post(post): - board_name=post["board"] - post_url=f'{session.imageboard_url}/{board_name}/manage/thread/{post["thread"] or post["postId"]}.html#{post["postId"]}' - notify(f'Alert! {get_path(post)}\n', post['nomarkup'], url=post_url) + post_url=f'{session.imageboard_url}/{post["board"]}/manage/thread/{post["thread"] or post["postId"]}.html#{post["postId"]}' + notify(f'Alert! {get_path(post)}\n', post['nomarkup'], url=post_url, board=post["board"], postId=post["postId"]) self.client = client self.start() From 6cac2135f3b292eab54621c36ec478fd2d54a164 Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Wed, 2 Feb 2022 17:08:44 +1100 Subject: [PATCH 07/11] add cwd for calling notification button --- components/notifiers.py | 7 ++++--- notification_button.py | 10 ++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/components/notifiers.py b/components/notifiers.py index 77256e6..fb848c0 100644 --- a/components/notifiers.py +++ b/components/notifiers.py @@ -1,4 +1,5 @@ import subprocess +from os import getcwd from abc import ABC, abstractmethod @@ -14,11 +15,11 @@ class TermuxNotifier(Notifier): if 'url' in kwargs: args = args + ['--action', f'termux-open-url {kwargs["url"]}', '--button1', 'Delete', - '--button1-action', f'python3 notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete', + '--button1-action', f'python3 {getcwd()}/notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete', '--button2', 'Delete+Ban', - '--button2-action', f'python3 notificaiton_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete,ban', + '--button2-action', f'python3 {getcwd()}/notificaiton_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete,ban', '--button3', 'Delete+Global Ban', - '--button3-action', f'python3 notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete,global_ban'] + '--button3-action', f'python3 {getcwd()}/notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete,global_ban'] subprocess.call(args) class NotifySendNotifier(Notifier): diff --git a/notification_button.py b/notification_button.py index 3b86870..cd384b1 100755 --- a/notification_button.py +++ b/notification_button.py @@ -23,7 +23,17 @@ def main(argv): session.update_csrf() res = session.post_actions(board=optdict['-b'], postid=optdict['-p'], actions=optdict['-a']) + + toast_message = None if 'message' in res: + toast_message = res['message'] + elif 'messages' in res: + toast_message = "\n".join(res['messages']) + elif 'error' in res: + toast_message = res['error'] + elif 'errors' in res: + toast_message = "\n".join(res['errors']) + if toast_message: subprocess.call(['termux-toast', res['message']]) if __name__ == '__main__': From f2839e4ce8a507e7da3e8b9f10f87865f654d400 Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Wed, 2 Feb 2022 17:12:14 +1100 Subject: [PATCH 08/11] typo, bugfix --- notification_button.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notification_button.py b/notification_button.py index cd384b1..ebe60aa 100755 --- a/notification_button.py +++ b/notification_button.py @@ -34,7 +34,7 @@ def main(argv): elif 'errors' in res: toast_message = "\n".join(res['errors']) if toast_message: - subprocess.call(['termux-toast', res['message']]) + subprocess.call(['termux-toast', toast_message]) if __name__ == '__main__': main(sys.argv[1:]) From a00ea8803653272f4dd3911e1f68fe08a34367d6 Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Wed, 2 Feb 2022 17:16:21 +1100 Subject: [PATCH 09/11] bugfix, typo --- components/notifiers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/notifiers.py b/components/notifiers.py index fb848c0..96264b5 100644 --- a/components/notifiers.py +++ b/components/notifiers.py @@ -17,7 +17,7 @@ class TermuxNotifier(Notifier): '--button1', 'Delete', '--button1-action', f'python3 {getcwd()}/notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete', '--button2', 'Delete+Ban', - '--button2-action', f'python3 {getcwd()}/notificaiton_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete,ban', + '--button2-action', f'python3 {getcwd()}/notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete,ban', '--button3', 'Delete+Global Ban', '--button3-action', f'python3 {getcwd()}/notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete,global_ban'] subprocess.call(args) From 043de1bda4f5ab68d5c56fec1227be0fff78c0a6 Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Wed, 2 Feb 2022 17:19:20 +1100 Subject: [PATCH 10/11] proper csrf method, remove temporary hack --- session.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/session.py b/session.py index 3f98be2..617f3cd 100644 --- a/session.py +++ b/session.py @@ -36,20 +36,12 @@ class ModSession(Session): def update_csrf(self): try: - -# res = self.get(url=f'{self.imageboard_url}/csrf.json', -# headers={'Referer': f'{self.imageboard_url}/csrf.json'}).json() -# if 'token' in res: -# self.csrf_token = res['token'] -# else: -# raise Exception('Unable to update csrf token') - - #temporary hack to get csrf token to test on <=0.1.10 - res2 = self.get(url=f'{self.imageboard_url}/account.html', - headers={'Referer': f'{self.imageboard_url}/account.html'}) - csrfi = res2.text.index('_csrf') - self.csrf_token = res2.text[csrfi+14:csrfi+50] - + res = self.get(url=f'{self.imageboard_url}/csrf.json', + headers={'Referer': f'{self.imageboard_url}/csrf.json'}).json() + if 'token' in res: + self.csrf_token = res['token'] + else: + raise Exception('Unable to update csrf token') except requests.RequestException as e: logging.error(f'Exception {e} occurred while updating csrf token') raise Exception('Unable to update csrf token') From 7917c79495887790b19d306fe34ee1b17ff7624f Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Sat, 5 Feb 2022 17:38:38 +1100 Subject: [PATCH 11/11] add back evaluate to newpost, close #4 pass buttons as an arg for notify, ref #3 add buttons to report notifications, close #2 --- components/evaluators.py | 4 +--- components/notifiers.py | 21 ++++++++++++--------- components/watchers.py | 27 +++++++++++++++++++++------ 3 files changed, 34 insertions(+), 18 deletions(-) diff --git a/components/evaluators.py b/components/evaluators.py index 20e4fd7..d5a8619 100755 --- a/components/evaluators.py +++ b/components/evaluators.py @@ -25,8 +25,6 @@ class PostEvaluator(Evaluator): trigger_urls = [ *filter(self.url_blacklist_re.match, self._url_extractor.find_urls(text, only_unique=True)) ] if self.url_blacklist_re and text else [] - trigger_entries = [ - _format_match(entry) for entry in re.finditer(self.blacklist_re, text) - ] if self.blacklist_re and text else [] + trigger_entries = re.findall(self.blacklist_re, text) if self.blacklist_re and text else [] logging.debug(f'Evaluated text:{text}\ntrigger urls:{trigger_urls}\ntrigger entries:{trigger_entries}') return trigger_urls, trigger_entries diff --git a/components/notifiers.py b/components/notifiers.py index 96264b5..d1bf365 100644 --- a/components/notifiers.py +++ b/components/notifiers.py @@ -2,7 +2,6 @@ import subprocess from os import getcwd from abc import ABC, abstractmethod - class Notifier(ABC): @abstractmethod def notify(self, title, content, *args, **kwargs): @@ -12,14 +11,18 @@ class TermuxNotifier(Notifier): def notify(self, title, content, *args, **kwargs): args = ['termux-notification', '--title', title, '--content', content or 'No Message'] - if 'url' in kwargs: - args = args + ['--action', f'termux-open-url {kwargs["url"]}', - '--button1', 'Delete', - '--button1-action', f'python3 {getcwd()}/notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete', - '--button2', 'Delete+Ban', - '--button2-action', f'python3 {getcwd()}/notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete,ban', - '--button3', 'Delete+Global Ban', - '--button3-action', f'python3 {getcwd()}/notification_button.py -b {kwargs["board"]} -p {kwargs["postId"]} -a delete,global_ban'] + + #open link when clicking on notification + if 'link' in kwargs: + args = args + ['--action', f'termux-open-url {kwargs["link"]}'] + + #add buttons to the notification + if 'buttons' in kwargs: + post = kwargs["post"] + for i, button in enumerate(kwargs["buttons"], start=1): + args = args + [f'--button{i}', button["text"], + f'--button{i}-action', f'python3 {getcwd()}/notification_button.py -b {post["board"]} -p {post["postId"]} -a {button["actions"]}'] + subprocess.call(args) class NotifySendNotifier(Notifier): diff --git a/components/watchers.py b/components/watchers.py index 38756be..a5cde87 100644 --- a/components/watchers.py +++ b/components/watchers.py @@ -5,7 +5,9 @@ from threading import Thread, Event import socketio from requests import RequestException -def get_path(post): return f'>>>/{post["board"]}/{post["thread"] or post["postId"]} ({post["postId"]})' +def get_quote(post): return f'>>>/{post["board"]}/{post["thread"] or post["postId"]} ({post["postId"]})' + +def get_manage_path(post): return f'/{post["board"]}/manage/thread/{post["thread"] or post["postId"]}.html#{post["postId"]}' class Watcher(ABC, Thread): def __init__(self, session): @@ -40,8 +42,15 @@ class RecentWatcher(Watcher): @client.on('newPost') def on_new_post(post): - post_url=f'{session.imageboard_url}/{post["board"]}/manage/thread/{post["thread"] or post["postId"]}.html#{post["postId"]}' - notify(f'Alert! {get_path(post)}\n', post['nomarkup'], url=post_url, board=post["board"], postId=post["postId"]) + urls, entries = evaluate(post["nomarkup"]) + if urls or entries: + post_url=f'{session.imageboard_url}{get_manage_path(post)}' + buttons=[{"text":"Delete","actions":"delete"}, + {"text":"Delete+Ban" if board else "Delete+Global Ban","actions":"delete,ban" if board else "delete,global_ban"}] + #todo: add this last button even if a board recents, because global staff can still global ban. but need a way to + #check if the account is global staff, which we dont have a json endpoint for in jschan yet. + #{"text":"Delete+Global Ban","actions":"dismiss" if board else "global_dismiss"}] + notify(f'Alert! {get_quote(post)}\n', post['nomarkup'], link=post_url, post=post, buttons=buttons) self.client = client self.start() @@ -61,6 +70,7 @@ class ReportsWatcher(Watcher): self.notify = notify self.fetch_interval = fetch_interval + self.board = board self._endpoint = f'{session.imageboard_url}/{f"{board}/manage" if board else "globalmanage"}/reports.json' self.known_reports = 0 @@ -75,9 +85,14 @@ class ReportsWatcher(Watcher): try: reported_posts, num_reported_posts = self.fetch_reports() if 0 < num_reported_posts != self.known_reports: - self.notify(f'New reports!', "\n".join([ - f'{get_path(p)} {[r["reason"] for r in (p["globalreports"] if "globalreports" in p else p["reports"])]}' - for p in reported_posts])) + for p in reported_posts: + post_url=f'{self.session.imageboard_url}{get_manage_path(p)}' + #todo: allow to customise these buttons somewhere + buttons=[{"text":"Delete","actions":"delete"}, + {"text":"Delete+Ban" if self.board else "Delete+Global Ban","actions":"delete,ban" if self.board else "delete,global_ban"}, + {"text":"Dismiss","actions":"dismiss" if self.board else "global_dismiss"}] + self.notify(f'New reports!', "\n".join([f'{get_quote(p)} {[r["reason"] for r in (p["globalreports"] if "globalreports" in p else p["reports"])]}']), + link=post_url, post=p, buttons=buttons) self.known_reports = num_reported_posts