aboutsummaryrefslogblamecommitdiffstats
path: root/main.py
blob: 4ba4aea24a2d0717d6727f789ba16f05cd874414 (plain) (tree)
1
2
3
4
5
6
7
8
9
                      
 

          
           
             
             
               
               
 
                                         











                                                                                     
                                                                             













                                                                          
                            
               

                                 
                         
                                
                                               
                                       
                                                                        

                                   
                                                      
                                  
                                                    
                                  
                                          
                                    
                                          
                                           



                                                                         


                                                          
                                                                 
                                                          

                                                    
                                          



                                      

 




                                      


                      
               
                                                                                     



                                                                                 


                                                          
                                                                                                       
 
                                                         
 
                                          

             
                                                                     







                                                                                   
 
                                                         
 
                                          


                
 








                                                                            





                                       
                                    


                                                  
                   



                          
#!/usr/bin/env python3

import os
import sys
import uuid
import base64
import getopt
import requests
import tempfile

from libs.pysignald.signald import Signal
from configparser import ConfigParser


def usage():
    print(os.path.basename(sys.argv[0]) + " [-h|--help] [-r|--register]")
    print("Runs the signal frontend to N. Reads the number to use from n_signal.ini")
    print("    -h|--help           prints this help and exits")
    print("    -r|--register       register the number with signal")


def read_config():
    config_object = ConfigParser()
    # config_object.read(os.environ.get('XDG_CONFIG_HOME') + "/n_signal.ini")
    config_object.read("n_signal.ini")

    info = config_object["INFO"]

    return info["number"]


def register_signald(number):
    s = Signal(number)
    s.register(voice=False)
    code = input(f"Please input register code send via sms to {number}: ")
    s.verify(code)


def handle_replies(replies):
    answer = ""
    if type(replies) is not list:
        replies = [replies]
    for reply in replies:
        l_answer = reply['text']
        for annotation in reply["annotations"]:
            a_type = annotation["type"]
            a_extra, is_attachment = handle_replies(annotation["extra"])

            if a_type == "command":
                l_answer = f"/{l_answer}: {a_extra}\n"
            elif a_type == "link":
                l_answer = f"{a_extra} ({l_answer})"
            elif a_type == "bold":
                l_answer = f"*{l_answer}*"
            elif a_type == "italic":
                l_answer = f"_{l_answer}_"
            elif a_type == "strikethrough":
                l_answer = f"~{l_answer}~"
            elif a_type == "attachment":
                [file_name, file_type, file_content] = a_extra.split(';')
                try:
                    tmp_path = "/tmp/" + str(uuid.uuid1())
                    os.mkdir(tmp_path)
                    # hack, do clean
                    file_content = base64.b64decode(file_content)
                    file_path = tmp_path + '/' + file_name
                    with open(file_path, "wb") as f:
                        f.write(file_content)
                    return file_path, True
                except Exception as e:
                    print(str(e))
        answer += l_answer
    return answer, False


def handle_response(response):
    replies = response.json()['reply']
    return handle_replies(replies)


def startup(number):
    s = Signal(number)

    # with args
    @s.chat_handler("^/([^\\s]+)\\s+([^$]*)$", order=10)  # This is case-insensitive.
    def klinger(message, match):
        # Returning `False` as the first argument will cause matching to continue
        # after this handler runs.
        stop = True

        # TODO: try catch
        response = requests.post('http://localhost:18080',
                                 json={"command": match.group(1), "arguments": match.group(2).strip()})

        answer, is_attachment = handle_response(response)

        return stop, answer, is_attachment

    # no args
    @s.chat_handler("^/(.+)$", order=20)  # This is case-insensitive.
    def klinger(message, match):
        # Returning `False` as the first argument will cause matching to continue
        # after this handler runs.
        stop = True

        # TODO: try catch
        response = requests.post('http://localhost:18080',
                                 json={"command": match.group(1), "arguments": ""})

        answer, is_attachment = handle_response(response)

        return stop, answer, is_attachment

    s.run_chat()


def main():
    number = read_config()
    try:
        opts, args = getopt.getopt(sys.argv[1:], "hr", ["help", "register"])
    except getopt.GetoptError as err:
        # print help information and exit:
        print(err)  # will print something like "option -a not recognized"
        usage()
        sys.exit(2)

    for o, a in opts:
        if o in ("-h", "--help"):
            usage()
            sys.exit()
        elif o in ("-r", "--register"):
            register_signald(number)
            sys.exit()
        else:
            assert False, "unhandled option: " + o
    startup(number)


if __name__ == "__main__":
    main()