From 87ffd22d358e42d5387ccfe13c5390c04a861533 Mon Sep 17 00:00:00 2001 From: Sasha MOREL Date: Tue, 14 Dec 2021 07:44:26 +0100 Subject: [PATCH] Code splitting for specific usages Also add a script to update a file containing SMSdb. --- server.py | 412 +++++++++++++++++++++++++++++++++++++++++++++++++ sms.py | 448 ++++-------------------------------------------------- update.py | 19 +++ 3 files changed, 457 insertions(+), 422 deletions(-) create mode 100755 server.py mode change 100755 => 100644 sms.py create mode 100644 update.py diff --git a/server.py b/server.py new file mode 100755 index 0000000..7f5bff3 --- /dev/null +++ b/server.py @@ -0,0 +1,412 @@ +#!/data/data/com.termux/files/usr/bin/python3 + +from subprocess import Popen, DEVNULL, PIPE +from json import loads as read_json +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer as http4_server_do_not_use +from urllib.parse import quote, unquote +from socket import AF_INET6 +from cgi import FieldStorage +from os import kill, getpid + +from sms import SMS_Service + +contacts_list_program = '/data/data/com.termux/files/usr/bin/termux-contact-list' + + +class HTTPServer (http4_server_do_not_use): + ''' + This block is just to have a IPv6 web server + This is not IPv6 only, the server also accepts IPv4 clients + ''' + address_family = AF_INET6 + + +def html_header (title = 'No title'): + return ('\n\n\t' + title + '\n' + '''\t''' + '\n') + + +def html_title (text): + return ('\n\t

' + text + '

') + + +def html_iframe (src, height = '150', width = '300', name = None, style = 'border:none;'): + r = '' - return (r) - - -def html_paragraph (text): - return ('\n\t

' + text + '

') - - -def html_list (lst): - t = '\n\t' - return (t) - - -def html_link (url, text = None, target = '_self'): - if text is None: - text = url - return ('' + text + '') - - -def html_table (body, table_style = None, cell_style = None): - t = '\n\t' - for line in body: - t += '\n\t\t' - for cell in line: - t += '\n\t\t\t' + cell + '' - t += '\n\t\t' - t += '\n\t' - return (t) - - -def html_message (msg, sent, time, name, avatar = None): - r = '\n\t
\n\t\t' + name + '') + '

\n\t\t' + time + '\n\t
' - return (r) - - -def html_form (body, url, post = True): - return ('\n\t
' + body + '\n\t
') - - -def html_form_text (id, value = '', textarea = False): - if textarea: - return ('\n\t') - return ('\n\t') - - -def html_form_hidden (id, value): - return ('\n\t') - - -def html_form_submit (label): - return ('\n\t') - - -def html_footer (): - return ('\n\n') class SMS_Service (Thread): - def __init__ (self): + def __init__ (self, sms_list = None): Thread.__init__ (self) - self.sms_list = [] + if type (sms_list) == list: + self.sms_list = sms_list + else: + self.sms_list = [] - def run (self): + def build_database (self): limit_fast_get = 1000000 - limit_normal_get = 20 offset = 0 while True: msgs = self.get_sms (limit = limit_fast_get, offset = offset) @@ -173,20 +29,27 @@ class SMS_Service (Thread): offset += limit_fast_get for msg in self.sms_list: del (msg ['read']) + + def update_database (self): + limit_normal_get = 20 + getting_new = True + offset = 0 + while getting_new: + msgs = self.get_sms (limit = limit_normal_get, offset = offset) + getting_new = False + for msg in msgs: + del (msg ['read']) + for msg in msgs: + if msg not in self.sms_list: + getting_new = True + self.sms_list.append (msg) + offset += limit_normal_get + + def run (self): + self.build_database () while True: sleep (5) - getting_new = True - offset = 0 - while getting_new: - msgs = self.get_sms (limit = limit_normal_get, offset = offset) - getting_new = False - for msg in msgs: - del (msg ['read']) - for msg in msgs: - if msg not in self.sms_list: - getting_new = True - self.sms_list.append (msg) - offset += limit_normal_get + self.update_database () def get_sms (self, limit = 10, offset = 0): while True: @@ -239,263 +102,4 @@ class SMS_Service (Thread): number = i ['number'] if 'sender' in i: name = i ['sender'] - return (number, name, sorted (l, key = lambda item: item [0])) - - -def contact_list (): - p = Popen ( - [contacts_list_program, ], - stdin = DEVNULL, - stdout = PIPE - ) - return (read_json (p.communicate () [0])) - - -class Web_Service (BaseHTTPRequestHandler): - def do_GET (self): - global locked_client - client = self.client_address [0] - if locked_client is None: - locked_client = client - print ('Locking on ' + str (client) + '…') - if locked_client == client: - global sms - if self.path == '/': - self.send_response (200) - self.send_header ('Content-type', 'text/html; charset=UTF-8') - self.end_headers () - self.wfile.write (( - html_header (title = 'Termux WebSMS') + - html_iframe ('/list', height = '100%', width = '30%', name = 'list') + html_iframe ('about:blank', height = '100%', width = '70%', name = 'thread') + - html_footer () - ).encode ('utf-8')) - elif self.path == '/up.svg': - self.send_response (200) - self.send_header ('Content-type', 'image/svg+xml; charset=UTF-8') - self.end_headers () - self.wfile.write (( - '\n' + - '\t\n' + - '\t\t\n' + - '\t\n' + - '' - ).encode ('utf-8')) - elif self.path == '/down.svg': - self.send_response (200) - self.send_header ('Content-type', 'image/svg+xml; charset=UTF-8') - self.end_headers () - self.wfile.write (( - '\n' + - '\t\n' + - '\t\t\n' + - '\t\n' + - '' - ).encode ('utf-8')) - elif self.path == '/list': - self.send_response (200) - self.send_header ('Content-type', 'text/html; charset=UTF-8') - self.send_header ('Refresh', '20') - self.end_headers () - ls = sms.thread_list () - lst = [] - for i in sorted (ls, key = lambda item: ls [item] [1], reverse = True): - s = ls [i] [0] + ' (' + str (ls [i] [3]) + ')' - if len (ls [i]) == 5: - s = ls [i] [4] + ' (' + str (ls [i] [3]) + ')' - lst.append (html_link ('/?thread=' + str (i), text = s, target = 'thread')) - self.wfile.write (( - html_header (title = 'Conversations list') + - html_title ('Conversation') + - html_paragraph (html_link ('/new', text = 'New conversation', target = 'thread')) + - html_paragraph (html_link ('/list', text = 'Refresh list')) + - html_paragraph ('List of conversations follows:') + - html_list (lst) + - html_footer () - ).encode ('utf-8')) - elif self.path == '/new': - self.send_response (200) - self.send_header ('Content-type', 'text/html; charset=UTF-8') - self.end_headers () - ls = contact_list () - lst = [] - for i in sorted (ls, key = lambda item: item ['name']): - lst.append (html_link ('/new?num=' + quote (i ['number']), text = i ['name'] + ' (' + i ['number'] + ')')) - self.wfile.write (( - html_header (title = 'New conversation') + - html_title ('Create a new conversation') + - html_paragraph ('Put number here:') + - html_form ( - html_form_text ('num') + - html_form_submit ('Validate'), - '/new', - post = False - ) + - html_paragraph ('List of contacts follows:') + - html_list (lst) + - html_footer () - ).encode ('utf-8')) - elif self.path [0:9] == '/new?num=': - self.send_response (200) - self.send_header ('Content-type', 'text/html; charset=UTF-8') - self.end_headers () - number = self.path [9:] - self.wfile.write (( - html_header (title = 'New conversation') + - html_paragraph (html_link ('/new', text = '← Back to new message')) + - html_title ('Create a new conversation with ' + unquote (number)) + - html_paragraph ('Message:') + - html_form ( - html_form_text ('msg', textarea = True) + - html_form_hidden ('number', unquote (number)) + - html_form_submit ('Send'), - '/send' - ) + - html_footer () - ).encode ('utf-8')) - elif self.path [0:9] == '/?thread=': - try: - id = self.path [9:] - number, name, conv = sms.get_thread (id) - if number is None: - raise (IndexError) - except (ValueError, IndexError): - self.send_response (404) - self.send_header ('Content-type', 'text/html') - self.end_headers () - self.wfile.write (( - html_header (title = 'Page not found') + - html_title ('Not found') + - html_paragraph ('This page does not exist. You cas return to the ' + html_link ('/', text = 'home') + '.') + - html_footer () - ).encode ('utf-8')) - return () - if name is None: - name = number - else: - name = name + ' (' + number + ')' - self.send_response (200) - self.send_header ('Content-type', 'text/html; charset=UTF-8') - self.end_headers () - self.wfile.write (( - html_header (title = 'Conversation with ' + name) + - html_title (name) + - html_form ( - html_form_text ('msg', textarea = True) + - html_form_hidden ('number', number) + - html_form_submit ('Send'), - '/send' - ) + - html_iframe ('/messages?thread=' + str (id), height = '80%', width = '100%', name = 'messages') + - html_footer () - ).encode ('utf-8')) - elif self.path [0:17] == '/messages?thread=': - try: - id = self.path [17:] - number, name, conv = sms.get_thread (id) - if number is None: - raise (IndexError) - except (ValueError, IndexError): - self.send_response (404) - self.send_header ('Content-type', 'text/html') - self.end_headers () - self.wfile.write (( - html_header (title = 'Page not found') + - html_title ('Not found') + - html_paragraph ('This page does not exist. You cas return to the ' + html_link ('/', text = 'home') + '.') + - html_footer () - ).encode ('utf-8')) - return () - self.send_response (200) - self.send_header ('Content-type', 'text/html; charset=UTF-8') - self.send_header ('Refresh', '10') - self.end_headers () - msgs = '' - for i in sorted (conv, key = lambda item: item [0], reverse = True) [0:2000]: - msgs += html_message (i [2], not i [1], i [0], '↓' if i [1] else '↑', avatar = 'down.svg' if i [1] else 'up.svg') - if name is None: - name = number - else: - name = name + ' (' + number + ')' - self.wfile.write (( - html_header (title = 'Conversation with ' + name) + - html_link (self.path, text = 'Refresh') + - msgs + - html_footer () - ).encode ('utf-8')) - else: - self.send_response (404) - self.send_header ('Content-type', 'text/html') - self.end_headers () - self.wfile.write (( - html_header (title = 'Page not found') + - html_title ('Not found') + - html_paragraph ('This page does not exist. You cas return to the ' + html_link ('/', text = 'home') + '.') + - html_footer () - ).encode ('utf-8')) - else: - self.send_response (403) - self.send_header ('Content-type', 'text/html') - self.end_headers () - self.wfile.write (( - html_header (title = 'Access denied') + - html_title ('Access denied') + - html_paragraph ('Access have allready been granted to another host.') + - html_footer () - ).encode ('utf-8')) - - def do_POST (self): - global locked_client - client = self.client_address [0] - if locked_client is None: - locked_client = client - print ('Locking on ' + str (client) + '…') - if locked_client == client: - global sms - if self.path == '/send': - post_data = FieldStorage (fp = self.rfile, headers = self.headers, environ = {'REQUEST_METHOD': 'POST'}) - sms.send_sms (post_data.getvalue ('number'), post_data.getvalue ('msg')) - self.send_response (301) - self.send_header ('Location', self.headers.get ('Referer')) - self.end_headers () - else: - self.send_response (404) - self.send_header ('Content-type', 'text/html') - self.end_headers () - self.wfile.write (( - html_header (title = 'Page not found') + - html_title ('Not found') + - html_paragraph ('This page does not exist. You cas return to the ' + html_link ('/', text = 'home') + '.') + - html_footer () - ).encode ('utf-8')) - else: - self.send_response (403) - self.send_header ('Content-type', 'text/html') - self.end_headers () - self.wfile.write (( - html_header (title = 'Access denied') + - html_title ('Access denied') + - html_paragraph ('Access have allready been granted to another host.') + - html_footer () - ).encode ('utf-8')) - - -if __name__ == '__main__': - sms = SMS_Service () - server = HTTPServer (('::', 8080), Web_Service) - locked_client = None - print ('Started!') - try: - sms.start () - server.serve_forever () - except KeyboardInterrupt: - print ('Interrupt received, closing process…') - server.server_close () - # BUG: the program must kill itself to end or the user must send Ctrl+C several time to close - # TODO: find another way to close the program in one action, suicide is never the solution - kill (getpid (), 15) \ No newline at end of file + return (number, name, sorted (l, key = lambda item: item [0])) \ No newline at end of file diff --git a/update.py b/update.py new file mode 100644 index 0000000..f1c2840 --- /dev/null +++ b/update.py @@ -0,0 +1,19 @@ +#!/data/data/com.termux/files/usr/bin/python3 + +from json import loads as json_read, dumps as json_write +from sys import argv +from os.path import isfile + +from sms import SMS_Service + +output = argv [1] + +if isfile (output): + database = json_read (open (output).read ()) + s = SMS_Service (sms_list = database) + s.update_database () + open (output, 'w').write (json_write (s.sorted_list ())) +else: + s = SMS_Service () + s.build_database () + open (output, 'w').write (json_write (s.sorted_list ())) \ No newline at end of file