Compare commits
	
		
			No commits in common. "master" and "v0.1.1" have entirely different histories.
		
	
	
		|  | @ -4,4 +4,3 @@ FRITZ_IP="192.168.178.1" | |||
| FRITZ_TMP="/tmp" | ||||
| FRITZ_VOICEBOX_PATH="fritz.nas/FRITZ/voicebox" | ||||
| FRITZ_TAM='{"0" : "!roomhash1:matrix.org", "1" : "!roomhash2:matrix.org"}' | ||||
| FRITZ_CALL_WATCH=False | ||||
|  |  | |||
|  | @ -4,8 +4,7 @@ __FritzAB2Matrix__ reads out the answering machine (_TAM_) of a _Fritz!Box_ in y | |||
| 
 | ||||
| Uses the python based cmd-line-tool [matrix-commander](https://github.com/8go/matrix-commander) so the matrix-commander.py in this repo is just a copy of that file to ease testing. | ||||
| ## Features | ||||
|  * Since _v0.1.1_ __Multitam__ is integrated so that you can check multiple answering machines __and__ post the messages to different matrix rooms. (Use _FRITZ\_TAM_ variable in .env file) | ||||
|  * Set _FRITZ\_CALL\_WATCH_=True if you want to receive a message everytime you miss a call. | ||||
|  * Since _v0.1.1_ __Multitam__ is integrated so that you can check multiple answering machines __and__ post the messages to different matrix rooms. (Use FRITZ\_TAM_ variable in .env file) | ||||
| ## Installation | ||||
| If you like to test this repository you are recommended to use one of the following two options. | ||||
| ### Necessary preparations for both cases | ||||
|  | @ -31,7 +30,6 @@ FRITZ_IP="192.168.178.1" | |||
| FRITZ_TMP="/tmp"  | ||||
| # FRITZ_VOICEBOX_PATH="fritz.nas/FRITZ/voicebox"  | ||||
| FRITZ_TAM='{"0" : "!roomhash1:matrix.org", "1" : "!roomhash2:matrix.org"}'  | ||||
| FRITZ_CALL_WATCH=False | ||||
|  ``` | ||||
| __.env__ | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,9 +1,8 @@ | |||
| # syntax=docker/dockerfile:1 | ||||
| 
 | ||||
| FROM python:alpine | ||||
| FROM ubuntu:latest | ||||
| 
 | ||||
| ENV TZ=Europe/Berlin | ||||
| ENV UNBUFFERED=1 | ||||
| 
 | ||||
| WORKDIR /app | ||||
| VOLUME /app | ||||
|  | @ -11,20 +10,23 @@ VOLUME /app | |||
| COPY . . | ||||
| 
 | ||||
| RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone; \ | ||||
|     apk --no-cache update && apk add --no-cache  --virtual .build-deps \ | ||||
|     gcc \ | ||||
|     cargo \ | ||||
|     libffi-dev \ | ||||
|     openssl-dev \ | ||||
|     olm-dev \ | ||||
|     zlib-dev \ | ||||
|     jpeg-dev ; \ | ||||
|     apk add --no-cache olm libmagic ffmpeg speex; \ | ||||
|     pip install pip -U --no-cache-dir; \ | ||||
|     pip install --no-cache-dir -r requirements.txt ; \ | ||||
|     apk del --no-cache .build-deps; | ||||
|     /bin/bash -c 'apt update && apt install -y libolm-dev python3-pip ffmpeg htop; \ | ||||
|     pip install update pip && pip install -r requirements.txt ;' | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ENTRYPOINT ["./fritzab2matrix.py "] | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # ENTRYPOINT ["python3", "-u", "fritzab2matrix.py"] | ||||
| ENTRYPOINT /bin/sh -c "export UNBUFFERED=1 && python3 -u ./fritzab2matrix.py" | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ services: | |||
|       context: ../. | ||||
|       dockerfile: ./docker/Dockerfile | ||||
|     working_dir: /app | ||||
| #    entrypoint: /bin/sh -c "export UNBUFFERED=1 && python3 -u ./fritzab2matrix.py" | ||||
|     entrypoint: ./fritzab2matrix.py | ||||
|     volumes: | ||||
|       - ../.:/app | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,14 +1,13 @@ | |||
| #!/usr/bin/env python3 | ||||
| 
 | ||||
| from fritzconnection import FritzConnection | ||||
| from fritzconnection.lib.fritzcall import FritzCall, Call | ||||
| from dotenv import load_dotenv | ||||
| from pydub import AudioSegment | ||||
| from libs.monitoring import endedCall | ||||
| from libs.message import conversion as conv | ||||
| import urllib.request | ||||
| import xmltodict, json | ||||
| import sys, os, time | ||||
| import sys, os | ||||
| import smbclient | ||||
| 
 | ||||
| 
 | ||||
|  | @ -20,15 +19,8 @@ env_pass = os.environ.get('FRITZ_PASSWORD') | |||
| env_ip = os.environ.get('FRITZ_IP') | ||||
| env_voicebox = os.environ.get('FRITZ_VOICEBOX_PATH') | ||||
| env_tam = json.loads(os.environ.get('FRITZ_TAM')) | ||||
| env_call_watch = eval(os.environ.get('FRITZ_CALL_WATCH')) | ||||
| env_tmp = os.environ.get('TEMP_DIR') | ||||
| 
 | ||||
| if env_call_watch is None: | ||||
|     env_call_watch = False | ||||
| elif env_call_watch: | ||||
|     at_least_one_new_message = False | ||||
| 
 | ||||
| 
 | ||||
| if env_voicebox is None: | ||||
|     env_voicebox = "/fritz.nas/FRITZ/voicebox/" | ||||
| 
 | ||||
|  | @ -36,13 +28,12 @@ if env_tam is None: | |||
|     env_tam = { | ||||
|         "0" : "!MxRrNGhFuQwnIeEWnX:ismus.net" | ||||
|         } | ||||
| #print(env_tam) | ||||
| print(env_tam) | ||||
| 
 | ||||
| if env_tmp is None: | ||||
|     env_tmp = "/tmp" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     # Build the url to download the message via smb | ||||
| def build_download_url(mid, tam=0): | ||||
|     recording = "rec." + str(tam) + r"." + str(mid).zfill(3) | ||||
|  | @ -63,47 +54,16 @@ def get_message_list(url): | |||
|         messages = xmltodict.parse(doc) | ||||
|         return messages | ||||
| 
 | ||||
| def get_last_call(): | ||||
|     """ Get the last Call. """ | ||||
|     try: | ||||
|         fc = FritzCall(address=env_ip,password=env_pass) | ||||
|     except: | ||||
|         print("Couldn't connect to Box") | ||||
|     missed_calls = fc.get_missed_calls(False,1,1) | ||||
|      | ||||
|     if len(missed_calls) > 0: | ||||
|         return missed_calls[0] | ||||
|     else: | ||||
|         return False | ||||
| 
 | ||||
| def lastcall2matrix(tam,tam_no): | ||||
|     # Call Watch to Matrix | ||||
|     if env_call_watch and not at_least_one_new_message: | ||||
|         c = get_last_call() | ||||
|         if c: | ||||
|             c_msg = "{} - {} ({})".format(c.Date, c.Caller, c.Name) | ||||
|         else: | ||||
|             return False | ||||
|          | ||||
|         # ... and send message and file to Matrix Room | ||||
|         ## if Number of a TAM and the last call match | ||||
|         if tam_no == c.CalledNumber: | ||||
|             cmd = "python3 matrix-commander.py --room {} -m '{}'".format(env_tam[tam],c_msg) | ||||
|             os.system(cmd) | ||||
|          | ||||
|     else: | ||||
|         print("Call Watch is off.") | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| def fritzab2matrix(tam): | ||||
| 
 | ||||
|     ### CHECK AND GET MESSAGES FROM FRITZBOX ### | ||||
|     ############################################ | ||||
| 
 | ||||
|     ## Connect to the FritzBox in the LAN | ||||
|     # We don't use tls because the self-signed cert of the box leads to a malfunction in urllib later on. | ||||
|     fc = FritzConnection(address=env_ip, user=env_user, password=env_pass, use_tls=False) | ||||
|     at_least_one_new_message = False | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     ## Get info about messages from the main answering machine | ||||
|  | @ -111,6 +71,27 @@ def fritzab2matrix(tam): | |||
|     message_list_url = message_list['NewURL'] | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     # Build the url to download the message via smb | ||||
|     def build_download_url(mid, tam=tam): | ||||
|         recording = "rec." + str(tam) + r"." + str(mid).zfill(3) | ||||
|         url = os.path.join("//",env_ip,env_voicebox,"rec",recording) | ||||
|         return url | ||||
| 
 | ||||
|     def download_speex_file(smb_url): | ||||
|         smbclient.register_session(server=env_ip, username=env_user, password=env_pass, auth_protocol="ntlm") | ||||
|         fd = smbclient.open_file(smb_url, mode="rb") | ||||
|         return fd | ||||
|      | ||||
| 
 | ||||
|     def get_message_list(url): | ||||
|         """ Get and and convert the xml formatted list of messages into a dictionary. """ | ||||
|         with urllib.request.urlopen(url) as f: | ||||
|             doc = f.read() | ||||
|             # Convert the xml formatted message list to dict | ||||
|             messages = xmltodict.parse(doc) | ||||
|             return messages | ||||
| 
 | ||||
|     l = get_message_list(message_list_url) | ||||
|     if l['Root'] == None or l['Root']['Message'] == None: | ||||
|         return False | ||||
|  | @ -124,7 +105,7 @@ def fritzab2matrix(tam): | |||
|     for a in messages: | ||||
|          | ||||
|         # format the information regarding the message | ||||
|         msg_info = a['Date'] + " - " + str(a['Number']) | ||||
|         msg_info = a['Date'] + " - " + a['Number'] | ||||
|         if a['Name']: | ||||
|             msg_info += " (" + a['Name'] + ") " | ||||
|              | ||||
|  | @ -135,7 +116,7 @@ def fritzab2matrix(tam): | |||
|         message_new = bool(int(a['New'])) | ||||
|      | ||||
|         if message_new == True: | ||||
|             at_least_one_new_message = True | ||||
| 
 | ||||
|             # Download and convert the speex files to wav | ||||
|             smb_url = build_download_url(a['Index']) | ||||
|             speex_fd = download_speex_file(smb_url) | ||||
|  | @ -166,20 +147,19 @@ def fritzab2matrix(tam): | |||
|             # Show that message is already read | ||||
|             print("__ " + msg_info) | ||||
| 
 | ||||
|     tam_no = a['Called'] | ||||
|     lastcall2matrix(tam,tam_no) | ||||
|             # ## For testing purposes only | ||||
| #            if a['Date'].endswith('20:53'): | ||||
| #                fc.call_action("X_AVM-DE_TAM1", "MarkMessage", NewIndex=1, NewMessageIndex=int(a['Index']), NewMarkedAsRead=0)           | ||||
|        | ||||
|             continue | ||||
| 
 | ||||
|         continue | ||||
| 
 | ||||
| def multitam(tams): | ||||
|     time.sleep(10) | ||||
|     for tam in tams.keys(): | ||||
|         print("Check TAM {}.".format(tam)) | ||||
|         fritzab2matrix(tam) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
| 
 | ||||
|      | ||||
|  |  | |||
|  | @ -15,17 +15,10 @@ def watch_disconnect(monitor, event_queue, func, tams, healthcheck_interval=10): | |||
|         else: | ||||
|             # do event processing here: | ||||
|             print(event) | ||||
|             if 'DISCONNECT;0' in event: | ||||
|                 print("Incoming call stopped. Check the TAM.\n") | ||||
|             if 'DISCONNECT' in event: | ||||
|                 print("Anruf beendet. Jetzt den AB checken.\n") | ||||
|                 func(tams) | ||||
| 
 | ||||
|             elif 'DISCONNECT;1' in event: | ||||
|                 print("Outgoing call stopped. Do nothing.\n") | ||||
| 
 | ||||
|             else: | ||||
|                 print("Unknown event.\n") | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| def endedCall(func, tams, fritz_ip='192.168.1.1'): | ||||
|  |  | |||
|  | @ -1,4 +1,3 @@ | |||
| 
 | ||||
| fritzconnection | ||||
| python-dotenv | ||||
| xmltodict | ||||
|  | @ -8,16 +7,13 @@ pydub | |||
| # for matrix-commander | ||||
| 
 | ||||
| aiohttp | ||||
| aiofiles #<0.5.0,>=0.4.0    | ||||
| aiofiles<0.5.0,>=0.4.0 | ||||
| argparse | ||||
| asyncio | ||||
| atomicwrites | ||||
| cachetools | ||||
| datetime | ||||
| markdown | ||||
| matrix-nio[e2e]>=0.18.3 | ||||
| peewee | ||||
| matrix-nio[e2e]>=0.14.1 | ||||
| Pillow | ||||
| python-magic | ||||
| python_magic | ||||
| uuid | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue