pylokid/main.py

191 lines
6 KiB
Python
Raw Normal View History

2017-12-21 21:12:44 +00:00
#!/usr/bin/env python3
""" Thy pylokid main program """
import os
import re
2017-12-24 14:35:16 +00:00
from datetime import datetime
2017-12-21 21:12:44 +00:00
import asyncio
import logging
import time
import email
import email.parser
import imaplib
import aioeasywebdav
from dotenv import load_dotenv, find_dotenv
2017-12-23 16:55:02 +00:00
import paho.mqtt.client as mqtt
2017-12-24 14:35:16 +00:00
from lodur_connect import create_einsatzrapport, upload_alarmdepesche
2017-12-21 21:12:44 +00:00
2017-12-23 17:31:40 +00:00
_EMAIL_SUBJECTS = '(OR SUBJECT "Einsatzausdruck_FW" SUBJECT "Einsatzprotokoll" UNSEEN)'
2017-12-21 21:12:44 +00:00
load_dotenv(find_dotenv())
imap_server = os.getenv("IMAP_SERVER")
imap_username = os.getenv("IMAP_USERNAME")
imap_password = os.getenv("IMAP_PASSWORD")
imap_mailbox = os.getenv("IMAP_MAILBOX", "INBOX")
2017-12-23 17:31:40 +00:00
imap_mailbox_archive = os.getenv("IMAP_MAILBOX_ARCHIVE", "Archive")
2017-12-21 21:12:44 +00:00
webdav_url = os.getenv("WEBDAV_URL")
webdav_username = os.getenv("WEBDAV_USERNAME")
webdav_password = os.getenv("WEBDAV_PASSWORD")
webdav_basedir = os.getenv("WEBDAV_BASEDIR")
tmp_dir = os.getenv("TMP_DIR", "/tmp")
2017-12-23 16:55:02 +00:00
mqtt_server = os.getenv("MQTT_SERVER")
mqtt_user = os.getenv("MQTT_USER")
mqtt_password = os.getenv("MQTT_PASSWORD")
2017-12-24 14:35:16 +00:00
lodur_user = os.getenv("LODUR_USER")
lodur_password = os.getenv("LODUR_PASSWORD")
lodur_base_url = os.getenv("LODUR_BASE_URL")
2017-12-21 21:12:44 +00:00
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
2017-12-23 16:55:02 +00:00
def get_attachments(mqtt_client):
2017-12-21 21:12:44 +00:00
# imap connection
logger.info('Connecting to IMAP server ' + imap_server)
imap = imaplib.IMAP4_SSL(imap_server)
imap.login(imap_username, imap_password)
2017-12-23 17:31:40 +00:00
imap.select(imap_mailbox, readonly=False)
2017-12-21 21:12:44 +00:00
# search for matching messages
logger.info('Searching for messages matching the subject')
typ, msg_ids = imap.search(
None,
_EMAIL_SUBJECTS,
)
if typ != 'OK':
2017-12-24 14:35:16 +00:00
logger.error('Error searching for matching messages')
2017-12-21 21:12:44 +00:00
raise
2017-12-23 17:31:40 +00:00
logger.info('Found ' + str(len(msg_ids[0].split())) + ' matching messages')
2017-12-21 21:12:44 +00:00
for msg_id in msg_ids[0].split():
subject = str()
f_id = str()
2017-12-24 14:35:16 +00:00
f_type = str()
2017-12-21 21:12:44 +00:00
# download message
typ, msg_data = imap.fetch(msg_id, '(RFC822)')
for response_part in msg_data:
if isinstance(response_part, tuple):
2017-12-24 14:35:16 +00:00
msg = email.message_from_string(str(response_part[1], 'utf-8'))
2017-12-21 21:12:44 +00:00
subject = msg["subject"]
# extract F id from subject
2017-12-24 14:35:16 +00:00
parse_subject = re.search('(.*): (F[0-9].*)', subject)
f_type = parse_subject.group(1)
f_id = parse_subject.group(2)
# mark as seen
imap.store(msg_id, '+FLAGS', '(\\Seen)')
2017-12-21 21:12:44 +00:00
logger.info('Processing message: ' + subject)
2017-12-24 14:35:16 +00:00
logger.info('Detected type: ' + f_type)
2017-12-21 21:12:44 +00:00
logger.info('Detected F ID: ' + f_id)
2017-12-24 14:35:16 +00:00
# publish over MQTT
mqtt_client.publish("pylokid/einsatz/" + f_id, f_type)
# Talk to Lodur
if f_type == 'Einsatzausdruck_FW':
# create new Einsatzrapport in Lodur
logger.info('Sending data to Lodur')
lodur_id = create_einsatzrapport(
lodur_user,
lodur_password,
lodur_base_url,
f_id,
)
logger.info('Sent data to Lodur. Assigned Lodur ID: ' + lodur_id)
elif f_type == 'Einsatzprotokoll':
logger.info('Updating data in Lodur')
else:
logger.error('Unknown type: ' + f_type)
2017-12-23 17:31:40 +00:00
2017-12-21 21:12:44 +00:00
# extract attachment from body
2017-12-24 14:35:16 +00:00
mail = email.message_from_string(str(msg_data[0][1], 'utf-8'))
2017-12-21 21:12:44 +00:00
for part in mail.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
file_name = part.get_filename()
logger.info('Extracting attachment: ' + file_name)
if bool(file_name):
# save attachment to filesystem
file_path = os.path.join(tmp_dir, file_name)
logger.info('Saving attachment to ' + file_path)
if not os.path.isfile(file_path):
file = open(file_path, 'wb')
file.write(part.get_payload(decode=True))
file.close()
upload_attachment(file_path, file_name, f_id)
2017-12-24 14:35:16 +00:00
logger.info('Uploading PDF to Lodur')
upload_alarmdepesche(
lodur_user,
lodur_password,
lodur_base_url,
lodur_id,
file_name,
file_path,
)
2017-12-21 21:12:44 +00:00
def upload_attachment(file, file_name, f_id):
# webdav connection
logger.info('Connecting to WebDAV server ' + webdav_url)
loop = asyncio.get_event_loop()
webdav = aioeasywebdav.connect(
webdav_url,
username=webdav_username,
password=webdav_password,
)
# upload with webdav
upload_dir = webdav_basedir + "/" + str(datetime.now().year) + "/" + f_id
logger.info('Uploading attachment to ' + upload_dir)
# create directory if not yet there
2017-12-21 21:12:44 +00:00
if not loop.run_until_complete(webdav.exists(upload_dir)):
logger.info('Creating directory ' + upload_dir)
2017-12-21 21:12:44 +00:00
loop.run_until_complete(webdav.mkdir(upload_dir))
remote_file_path = upload_dir + "/" + file_name
if loop.run_until_complete(webdav.exists(remote_file_path)):
logger.info('File ' + file_name + ' already uploaded')
else:
loop.run_until_complete(
webdav.upload(file, remote_file_path)
)
logger.info('File ' + file_name + ' uploaded')
2017-12-21 21:12:44 +00:00
2017-12-23 16:55:02 +00:00
def on_connect(client, userdata, flags, rc):
logger.info('Connected to MQTT with result code ' + str(rc))
2017-12-21 21:12:44 +00:00
def main():
""" main """
2017-12-23 16:55:02 +00:00
logger.info('Connecting to MQTT broker ' + mqtt_server)
client = mqtt.Client('pylokid')
client.on_connect = on_connect
client.username_pw_set(mqtt_user, password=mqtt_password)
client.tls_set()
client.connect(mqtt_server, 8883, 60)
client.loop_start()
2017-12-21 21:12:44 +00:00
while True:
2017-12-23 16:55:02 +00:00
get_attachments(client)
2017-12-21 21:12:44 +00:00
time.sleep(60)
if __name__ == '__main__':
main()