Compare commits
9
Commits
69da949aa8
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
883fc84c02 | ||
|
|
399d8e498d | ||
|
|
4a965a96a4 | ||
|
|
f64879398f | ||
|
|
3e33de4606 | ||
|
|
8b4bc74b1d | ||
|
|
2b331fbd1f | ||
|
|
b528b0a748 | ||
|
|
5127caed03 |
@@ -1,3 +1,4 @@
|
|||||||
|
mode="EWS"
|
||||||
username=""
|
username=""
|
||||||
password=""
|
password=""
|
||||||
server=""
|
server=""
|
||||||
@@ -12,4 +13,5 @@ alarminator_token=""
|
|||||||
alarminator_zvies_use_PEALGRP="False"
|
alarminator_zvies_use_PEALGRP="False"
|
||||||
printer=DEFAULT
|
printer=DEFAULT
|
||||||
print_num=0
|
print_num=0
|
||||||
BASIC_AUTH_PASSWORD=""
|
DIVERA_MESSANGER_API_KEY=""
|
||||||
|
DIVERA_ALARMER_API_KEY=""
|
||||||
+22
-2
@@ -1,5 +1,6 @@
|
|||||||
FROM python:3.10-bullseye
|
FROM python:3.10-bullseye
|
||||||
|
|
||||||
|
ENV mode="EWS"
|
||||||
ENV username=
|
ENV username=
|
||||||
ENV password=
|
ENV password=
|
||||||
ENV server="exchange.sankt-wendel.de"
|
ENV server="exchange.sankt-wendel.de"
|
||||||
@@ -13,8 +14,9 @@ ENV alarminator_zvies_use_PEALGRP="False"
|
|||||||
ENV print_num=0
|
ENV print_num=0
|
||||||
ENV printer="DEFAULT"
|
ENV printer="DEFAULT"
|
||||||
ENV REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
|
ENV REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
|
||||||
|
ENV DIVERA_MESSANGER_API_KEY=""
|
||||||
|
ENV DIVERA_ALARMER_API_KEY=""
|
||||||
ENV MAPS_API_KEY=""
|
ENV MAPS_API_KEY=""
|
||||||
ENV BASIC_AUTH_PASSWORD=""
|
|
||||||
|
|
||||||
|
|
||||||
COPY *.deb /
|
COPY *.deb /
|
||||||
@@ -56,6 +58,24 @@ RUN useradd \
|
|||||||
print \
|
print \
|
||||||
&& sed -i '/%sudo[[:space:]]/ s/ALL[[:space:]]*$/NOPASSWD:ALL/' /etc/sudoers
|
&& sed -i '/%sudo[[:space:]]/ s/ALL[[:space:]]*$/NOPASSWD:ALL/' /etc/sudoers
|
||||||
|
|
||||||
|
|
||||||
|
# Print PDF
|
||||||
|
RUN apt-get update && apt-get install -y \
|
||||||
|
apt-transport-https \
|
||||||
|
ca-certificates \
|
||||||
|
curl \
|
||||||
|
gnupg \
|
||||||
|
--no-install-recommends \
|
||||||
|
&& curl -sSL https://dl.google.com/linux/linux_signing_key.pub | apt-key add - \
|
||||||
|
&& echo "deb [arch=amd64] https://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list \
|
||||||
|
&& apt-get update && apt-get install -y \
|
||||||
|
google-chrome-stable \
|
||||||
|
--no-install-recommends
|
||||||
|
|
||||||
|
# It won't run from the root user.
|
||||||
|
RUN groupadd chrome && useradd -g chrome -s /bin/bash -G audio,video chrome \
|
||||||
|
&& mkdir -p /home/chrome && chown -R chrome:chrome /home/chrome
|
||||||
|
|
||||||
COPY requirements.txt ./
|
COPY requirements.txt ./
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
@@ -63,4 +83,4 @@ COPY ./app .
|
|||||||
COPY *.crt /usr/local/share/ca-certificates/
|
COPY *.crt /usr/local/share/ca-certificates/
|
||||||
RUN update-ca-certificates
|
RUN update-ca-certificates
|
||||||
|
|
||||||
CMD [ "sh","-c","/etc/init.d/cups start && python3 /usr/src/app/app.py" ]
|
CMD [ "sh","-c","/etc/init.d/cups start && python3 /usr/src/app/run.py" ]
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIGTDCCBDSgAwIBAgIQOXpmzCdWNi4NqofKbqvjsTANBgkqhkiG9w0BAQwFADBf
|
||||||
|
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
|
||||||
|
Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
|
||||||
|
HhcNMjEwMzIyMDAwMDAwWhcNMzYwMzIxMjM1OTU5WjBgMQswCQYDVQQGEwJHQjEY
|
||||||
|
MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIFB1Ymxp
|
||||||
|
YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gQ0EgRFYgUjM2MIIBojANBgkqhkiG9w0B
|
||||||
|
AQEFAAOCAY8AMIIBigKCAYEAljZf2HIz7+SPUPQCQObZYcrxLTHYdf1ZtMRe7Yeq
|
||||||
|
RPSwygz16qJ9cAWtWNTcuICc++p8Dct7zNGxCpqmEtqifO7NvuB5dEVexXn9RFFH
|
||||||
|
12Hm+NtPRQgXIFjx6MSJcNWuVO3XGE57L1mHlcQYj+g4hny90aFh2SCZCDEVkAja
|
||||||
|
EMMfYPKuCjHuuF+bzHFb/9gV8P9+ekcHENF2nR1efGWSKwnfG5RawlkaQDpRtZTm
|
||||||
|
M64TIsv/r7cyFO4nSjs1jLdXYdz5q3a4L0NoabZfbdxVb+CUEHfB0bpulZQtH1Rv
|
||||||
|
38e/lIdP7OTTIlZh6OYL6NhxP8So0/sht/4J9mqIGxRFc0/pC8suja+wcIUna0HB
|
||||||
|
pXKfXTKpzgis+zmXDL06ASJf5E4A2/m+Hp6b84sfPAwQ766rI65mh50S0Di9E3Pn
|
||||||
|
2WcaJc+PILsBmYpgtmgWTR9eV9otfKRUBfzHUHcVgarub/XluEpRlTtZudU5xbFN
|
||||||
|
xx/DgMrXLUAPaI60fZ6wA+PTAgMBAAGjggGBMIIBfTAfBgNVHSMEGDAWgBRWc1hk
|
||||||
|
lfmSGrASKgRieaFAFYghSTAdBgNVHQ4EFgQUaMASFhgOr872h6YyV6NGUV3LBycw
|
||||||
|
DgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYI
|
||||||
|
KwYBBQUHAwEGCCsGAQUFBwMCMBsGA1UdIAQUMBIwBgYEVR0gADAIBgZngQwBAgEw
|
||||||
|
VAYDVR0fBE0wSzBJoEegRYZDaHR0cDovL2NybC5zZWN0aWdvLmNvbS9TZWN0aWdv
|
||||||
|
UHVibGljU2VydmVyQXV0aGVudGljYXRpb25Sb290UjQ2LmNybDCBhAYIKwYBBQUH
|
||||||
|
AQEEeDB2ME8GCCsGAQUFBzAChkNodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3Rp
|
||||||
|
Z29QdWJsaWNTZXJ2ZXJBdXRoZW50aWNhdGlvblJvb3RSNDYucDdjMCMGCCsGAQUF
|
||||||
|
BzABhhdodHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEA
|
||||||
|
YtOC9Fy+TqECFw40IospI92kLGgoSZGPOSQXMBqmsGWZUQ7rux7cj1du6d9rD6C8
|
||||||
|
ze1B2eQjkrGkIL/OF1s7vSmgYVafsRoZd/IHUrkoQvX8FZwUsmPu7amgBfaY3g+d
|
||||||
|
q1x0jNGKb6I6Bzdl6LgMD9qxp+3i7GQOnd9J8LFSietY6Z4jUBzVoOoz8iAU84OF
|
||||||
|
h2HhAuiPw1ai0VnY38RTI+8kepGWVfGxfBWzwH9uIjeooIeaosVFvE8cmYUB4TSH
|
||||||
|
5dUyD0jHct2+8ceKEtIoFU/FfHq/mDaVnvcDCZXtIgitdMFQdMZaVehmObyhRdDD
|
||||||
|
4NQCs0gaI9AAgFj4L9QtkARzhQLNyRf87Kln+YU0lgCGr9HLg3rGO8q+Y4ppLsOd
|
||||||
|
unQZ6ZxPNGIfOApbPVf5hCe58EZwiWdHIMn9lPP6+F404y8NNugbQixBber+x536
|
||||||
|
WrZhFZLjEkhp7fFXf9r32rNPfb74X/U90Bdy4lzp3+X1ukh1BuMxA/EEhDoTOS3l
|
||||||
|
7ABvc7BYSQubQ2490OcdkIzUh3ZwDrakMVrbaTxUM2p24N6dB+ns2zptWCva6jzW
|
||||||
|
r8IWKIMxzxLPv5Kt3ePKcUdvkBU/smqujSczTzzSjIoR5QqQA6lN1ZRSnuHIWCvh
|
||||||
|
JEltkYnTAH41QJ6SAWO66GrrUESwN/cgZzL4JLEqz1Y=
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf
|
||||||
|
MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD
|
||||||
|
Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw
|
||||||
|
HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY
|
||||||
|
MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp
|
||||||
|
YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB
|
||||||
|
AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa
|
||||||
|
ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz
|
||||||
|
SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf
|
||||||
|
iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X
|
||||||
|
ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3
|
||||||
|
IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS
|
||||||
|
VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE
|
||||||
|
SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu
|
||||||
|
+Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt
|
||||||
|
8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L
|
||||||
|
HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt
|
||||||
|
zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P
|
||||||
|
AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c
|
||||||
|
mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ
|
||||||
|
YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52
|
||||||
|
gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA
|
||||||
|
Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB
|
||||||
|
JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX
|
||||||
|
DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui
|
||||||
|
TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5
|
||||||
|
dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65
|
||||||
|
LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp
|
||||||
|
0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY
|
||||||
|
QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL
|
||||||
|
-----END CERTIFICATE-----
|
||||||
-136
@@ -1,136 +0,0 @@
|
|||||||
from flask import Flask, flash, request, redirect, send_from_directory, get_flashed_messages
|
|
||||||
import os
|
|
||||||
import glob
|
|
||||||
import securecad_parser
|
|
||||||
import datetime
|
|
||||||
from hooks import webhook, alarminator_api, cups_print
|
|
||||||
from pathlib import Path
|
|
||||||
from flask_basicauth import BasicAuth
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
app.secret_key = 'super secret key'
|
|
||||||
app.config['SESSION_TYPE'] = 'filesystem'
|
|
||||||
app.config['BASIC_AUTH_USERNAME'] = 'admin'
|
|
||||||
app.config['BASIC_AUTH_PASSWORD'] = os.environ.get('BASIC_AUTH_PASSWORD','password')
|
|
||||||
basic_auth = BasicAuth(app)
|
|
||||||
|
|
||||||
def wrapHtml(innerHtml):
|
|
||||||
return '''<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>JFW Alarm</title>
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
|
||||||
</head>
|
|
||||||
<body><div class="container text-center">
|
|
||||||
''' + flashMessages() +'''
|
|
||||||
''' + innerHtml + '''
|
|
||||||
</div>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
|
||||||
</body>
|
|
||||||
</html>'''
|
|
||||||
|
|
||||||
def flashMessages():
|
|
||||||
messages = get_flashed_messages(with_categories=True)
|
|
||||||
html = ""
|
|
||||||
if messages:
|
|
||||||
for category, message in messages:
|
|
||||||
html = html + category + ": "+message+"<br>"
|
|
||||||
return html
|
|
||||||
|
|
||||||
def alarmsPath():
|
|
||||||
dir_path = os.path.dirname(os.path.realpath(__file__))
|
|
||||||
return dir_path + "/alarms" + os.sep
|
|
||||||
|
|
||||||
def getAlarmFiles():
|
|
||||||
a_list = glob.glob(alarmsPath()+"*.html")
|
|
||||||
a_list.sort()
|
|
||||||
return [os.path.basename(f) for f in a_list]
|
|
||||||
|
|
||||||
def parseAlarm(f):
|
|
||||||
f = alarmsPath() + os.sep + f
|
|
||||||
with open(f, "r") as o:
|
|
||||||
_r: str = o.read()
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
_r = _r.replace('%DATUM%',now.strftime("%d.%m.%Y"))
|
|
||||||
_r = _r.replace('%UHRZEIT%',now.strftime("%H:%M"))
|
|
||||||
if _r != '':
|
|
||||||
return [securecad_parser.parse_securecad_message(_r),_r]
|
|
||||||
|
|
||||||
def allowed_file(filename:str):
|
|
||||||
print(filename.rsplit('.', 1)[1].lower())
|
|
||||||
return '.' in filename and \
|
|
||||||
filename.rsplit('.', 1)[1].lower() in ["html"]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/")
|
|
||||||
@basic_auth.required
|
|
||||||
def root():
|
|
||||||
html = ""
|
|
||||||
file = request.args.get('sendalarm')
|
|
||||||
if file is not None:
|
|
||||||
parsed_body, raw = parseAlarm(file)
|
|
||||||
if parsed_body != None:
|
|
||||||
if 'ALARMDEPESCHE' in parsed_body:
|
|
||||||
webhook(parsed_body)
|
|
||||||
alarminator_api(parsed_body)
|
|
||||||
cups_print(parsed_body,raw)
|
|
||||||
flash("Alarm gesendet!")
|
|
||||||
return redirect('/')
|
|
||||||
|
|
||||||
html = html + '<div class="row align-items-start p-3 ">'
|
|
||||||
i: str
|
|
||||||
files = getAlarmFiles()
|
|
||||||
for f in files:
|
|
||||||
html = html + "<div class=\"col-6\" style='padding: 5px;'><a style='display:block; padding:20px' class=\"btn btn-block btn-danger\" href=\"/?sendalarm="+f+"\">" + f + "</a></div>"
|
|
||||||
html = html + "</div>"
|
|
||||||
return wrapHtml(html)
|
|
||||||
|
|
||||||
@app.route('/files', methods=['POST'])
|
|
||||||
@basic_auth.required
|
|
||||||
def upload_file():
|
|
||||||
# check if the post request has the file part
|
|
||||||
print(request.files)
|
|
||||||
if 'file' not in request.files:
|
|
||||||
flash('No file part')
|
|
||||||
return redirect(request.url)
|
|
||||||
file = request.files['file']
|
|
||||||
# If the user does not select a file, the browser submits an
|
|
||||||
# empty file without a filename.
|
|
||||||
print(file.filename)
|
|
||||||
if file.filename == '':
|
|
||||||
flash('No selected file')
|
|
||||||
return redirect(request.url)
|
|
||||||
if file and allowed_file(file.filename):
|
|
||||||
file.save(os.path.join(alarmsPath(), file.filename))
|
|
||||||
return redirect('/files')
|
|
||||||
|
|
||||||
@app.route('/files/<path:filename>', methods=['GET'])
|
|
||||||
@basic_auth.required
|
|
||||||
def download(filename):
|
|
||||||
uploads = alarmsPath()
|
|
||||||
return send_from_directory(uploads, filename, as_attachment=True)
|
|
||||||
|
|
||||||
@app.route("/files", methods=['GET'])
|
|
||||||
@basic_auth.required
|
|
||||||
def files():
|
|
||||||
Path(alarmsPath()).mkdir(parents=True, exist_ok=True)
|
|
||||||
file = request.args.get('del')
|
|
||||||
if file is not None:
|
|
||||||
try:
|
|
||||||
os.remove(alarmsPath()+os.sep+file)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
flash("Datei gelöscht!")
|
|
||||||
return redirect('/files')
|
|
||||||
|
|
||||||
files = getAlarmFiles()
|
|
||||||
html = '<ul class="list-group">'
|
|
||||||
for f in files:
|
|
||||||
html = html + '<li class="list-group-item"><a href="/files/'+f+'">'+f+'</a> <a href="/files?del='+f+'">löschen</a></li>'
|
|
||||||
html = html + '</ul><form method="post" enctype="multipart/form-data"><input type="file" name="file"><input type=submit value=Upload></form>'
|
|
||||||
return html
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app.run(port=5000)
|
|
||||||
@@ -21,13 +21,14 @@ Message.register("alarmfax_parser_verarbeitet", alarmfax_parser_verarbeitet)
|
|||||||
Message.register("alarmfax_parser_id", alarmfax_parser_id)
|
Message.register("alarmfax_parser_id", alarmfax_parser_id)
|
||||||
#print([f.name for f in Message.FIELDS if f.is_searchable])
|
#print([f.name for f in Message.FIELDS if f.is_searchable])
|
||||||
|
|
||||||
threads = {}
|
def run():
|
||||||
|
threads = {}
|
||||||
|
|
||||||
format = "%(asctime)s|%(threadName)s: %(message)s"
|
format = "%(asctime)s|%(threadName)s: %(message)s"
|
||||||
logging.basicConfig(format=format, level=logging.INFO,
|
logging.basicConfig(format=format, level=logging.INFO,
|
||||||
datefmt="%Y-%m-%d %H:%M:%S")
|
datefmt="%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
def eventHandler(ELEMENT_NAME, item_id, item_changekey):
|
def eventHandler(ELEMENT_NAME, item_id, item_changekey):
|
||||||
if (ELEMENT_NAME == 'ModifiedEvent' and IS_DEV) or ELEMENT_NAME == 'NewMailEvent' or ELEMENT_NAME == 'SearchFolderEvent':
|
if (ELEMENT_NAME == 'ModifiedEvent' and IS_DEV) or ELEMENT_NAME == 'NewMailEvent' or ELEMENT_NAME == 'SearchFolderEvent':
|
||||||
logging.info(ELEMENT_NAME + " - get Mail")
|
logging.info(ELEMENT_NAME + " - get Mail")
|
||||||
m: Message = a.inbox.get(id=item_id, changekey=item_changekey)
|
m: Message = a.inbox.get(id=item_id, changekey=item_changekey)
|
||||||
@@ -49,9 +50,10 @@ def eventHandler(ELEMENT_NAME, item_id, item_changekey):
|
|||||||
webhook(parsed_body)
|
webhook(parsed_body)
|
||||||
alarminator_api(parsed_body)
|
alarminator_api(parsed_body)
|
||||||
cups_print(parsed_body,m.body)
|
cups_print(parsed_body,m.body)
|
||||||
|
divera_messenger(parsed_body)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def folder_event_subscriber(folder: Folder):
|
def folder_event_subscriber(folder: Folder):
|
||||||
logging.info('folder_event_subscriber startet for Folder: {}'.format(folder.name))
|
logging.info('folder_event_subscriber startet for Folder: {}'.format(folder.name))
|
||||||
while True:
|
while True:
|
||||||
# filtern des ordners nach mails der letzten 24h, die nicht verarbeitet wurden
|
# filtern des ordners nach mails der letzten 24h, die nicht verarbeitet wurden
|
||||||
@@ -79,7 +81,6 @@ def folder_event_subscriber(folder: Folder):
|
|||||||
t = Thread(target=eventHandler, args=(event.ELEMENT_NAME,event.item_id.id,event.item_id.changekey,),name="eventHandler: {} ({})".format(event.ELEMENT_NAME, event.item_id.id))
|
t = Thread(target=eventHandler, args=(event.ELEMENT_NAME,event.item_id.id,event.item_id.changekey,),name="eventHandler: {} ({})".format(event.ELEMENT_NAME, event.item_id.id))
|
||||||
t.start()
|
t.start()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
try:
|
try:
|
||||||
username = os.environ.get('username')
|
username = os.environ.get('username')
|
||||||
password = os.environ.get('password')
|
password = os.environ.get('password')
|
||||||
|
|||||||
+90
-16
@@ -2,10 +2,12 @@ import os
|
|||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
import cups
|
import cups
|
||||||
from weasyprint import HTML, CSS
|
from weasyprint import HTML
|
||||||
from weasyprint.text.fonts import FontConfiguration
|
|
||||||
from requests.adapters import Retry
|
from requests.adapters import Retry
|
||||||
import uuid
|
import uuid
|
||||||
|
import subprocess
|
||||||
|
import datetime
|
||||||
|
import time
|
||||||
|
|
||||||
retries = Retry(total=5,
|
retries = Retry(total=5,
|
||||||
backoff_factor=0.1,
|
backoff_factor=0.1,
|
||||||
@@ -40,8 +42,8 @@ def alarminator_api(parsed_body: dict):
|
|||||||
req_string +="&alarmtime={}".format(parsed_body['Einsatzbeginn(Soll)'].split(" ")[1])
|
req_string +="&alarmtime={}".format(parsed_body['Einsatzbeginn(Soll)'].split(" ")[1])
|
||||||
if 'Auftragsnummer' in parsed_body and not (os.environ.get('IS_DEV') and os.environ.get('IS_DEV') == "True"):
|
if 'Auftragsnummer' in parsed_body and not (os.environ.get('IS_DEV') and os.environ.get('IS_DEV') == "True"):
|
||||||
req_string +="&operationnumber={}".format(parsed_body['Auftragsnummer'])
|
req_string +="&operationnumber={}".format(parsed_body['Auftragsnummer'])
|
||||||
if 'Notfallgeschehen' in parsed_body:
|
if 'Sachverhalt' in parsed_body:
|
||||||
req_string +="&message={}".format(parsed_body['Notfallgeschehen'])
|
req_string +="&message={}".format(parsed_body['Sachverhalt'])
|
||||||
if 'Einsatzziel' in parsed_body:
|
if 'Einsatzziel' in parsed_body:
|
||||||
if 'Stadt' in parsed_body['Einsatzziel']:
|
if 'Stadt' in parsed_body['Einsatzziel']:
|
||||||
req_string +="&community={}".format(parsed_body['Einsatzziel']['Stadt'])
|
req_string +="&community={}".format(parsed_body['Einsatzziel']['Stadt'])
|
||||||
@@ -111,6 +113,8 @@ def alarminator_api(parsed_body: dict):
|
|||||||
# if False
|
# if False
|
||||||
# req_string +="&lon={}".format() if False
|
# req_string +="&lon={}".format() if False
|
||||||
subject = ""
|
subject = ""
|
||||||
|
if 'Notfallgeschehen' in parsed_body:
|
||||||
|
subject = parsed_body['Notfallgeschehen'] + "\n"
|
||||||
if 'Notfallgeschehen' in parsed_body:
|
if 'Notfallgeschehen' in parsed_body:
|
||||||
subject = parsed_body['Notfallgeschehen'] + "\n"
|
subject = parsed_body['Notfallgeschehen'] + "\n"
|
||||||
req_string +="&subject={}".format(subject)
|
req_string +="&subject={}".format(subject)
|
||||||
@@ -122,27 +126,97 @@ def alarminator_api(parsed_body: dict):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error("alarminator_api", e)
|
logging.error("alarminator_api", e)
|
||||||
|
|
||||||
def cups_print(parsed_body: dict, body: str):
|
def generate_pdf(html_body, filename):
|
||||||
html = HTML(string='<html><head></head><body>'+body+"</body></html>", base_url="")
|
f = "/tmp/{}.html".format(uuid.uuid4())
|
||||||
font_config = FontConfiguration()
|
with open(f,"w") as _f:
|
||||||
pdf = html.write_pdf(font_config=font_config,stylesheets=[CSS(string='body { font-family: serif !important }')])
|
_f.write(html_body)
|
||||||
fname = "/tmp/{}.pdf".format(uuid.uuid4())
|
subprocess.run(["/usr/bin/google-chrome-stable", "--headless", "--no-sandbox", "--disable-gpu", "--print-to-pdf="+filename, "--no-pdf-header-footer", "--print-to-pdf-no-header", "--no-margins", f])
|
||||||
|
if os.path.exists(f):
|
||||||
|
os.remove(f)
|
||||||
|
|
||||||
if os.environ.get('IS_DEV') and os.environ.get('IS_DEV') == "True":
|
def cups_print(parsed_body: dict, body: str):
|
||||||
with open("{}.pdf".format(uuid.uuid4()),"wb") as f:
|
# if os.environ.get('IS_DEV') and os.environ.get('IS_DEV') == "True":
|
||||||
f.write(pdf)
|
# generate_pdf(body, "{}.pdf".format(uuid.uuid4()))
|
||||||
|
fname = "{}.pdf".format(uuid.uuid4())
|
||||||
try:
|
try:
|
||||||
conn = cups.Connection ()
|
conn = cups.Connection ()
|
||||||
printer_arr = os.environ.get('printer',"DEFAULT").split(";")
|
printer_arr = os.environ.get('printer',"DEFAULT").split(";")
|
||||||
print_num = int(os.environ.get('print_num',0))
|
print_num = int(os.environ.get('print_num',0))
|
||||||
|
#if printer_arr.__len__() > 0:
|
||||||
|
generate_pdf(body, fname)
|
||||||
for printer in printer_arr:
|
for printer in printer_arr:
|
||||||
|
print(printer)
|
||||||
if 'ALARMDEPESCHE' in parsed_body:
|
if 'ALARMDEPESCHE' in parsed_body:
|
||||||
with open(fname,"wb") as f:
|
|
||||||
f.write(pdf)
|
|
||||||
for i in range(0, print_num):
|
for i in range(0, print_num):
|
||||||
conn.printFile (printer, fname, "Alarmfax", {})
|
conn.printFile (printer, fname, "Alarmfax", {})
|
||||||
os.remove(fname)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
logging.error("cups_print", e)
|
||||||
|
finally:
|
||||||
if os.path.exists(fname):
|
if os.path.exists(fname):
|
||||||
os.remove(fname)
|
os.remove(fname)
|
||||||
logging.error("cups_print", e)
|
|
||||||
|
|
||||||
|
def divera_messenger(parsed_body: dict):
|
||||||
|
# /api/v2/alarms
|
||||||
|
# message-channels?accesskey=XXX
|
||||||
|
|
||||||
|
try:
|
||||||
|
api = "https://app.divera247.com/api/v2/"
|
||||||
|
messenger_api_token = os.environ.get('DIVERA_MESSANGER_API_KEY') if os.environ.get('DIVERA_MESSANGER_API_KEY') else ""
|
||||||
|
alarmer_api_token = os.environ.get('DIVERA_ALARMER_API_KEY') if os.environ.get('DIVERA_ALARMER_API_KEY') else ""
|
||||||
|
if messenger_api_token != "":
|
||||||
|
if 'ALARMDEPESCHE' in parsed_body: # sendAlarm triggern
|
||||||
|
if 'Einsatzmittelliste' in parsed_body:
|
||||||
|
|
||||||
|
zveis = []
|
||||||
|
message = "Alarmierte Einsatzmittel:\n"
|
||||||
|
for r in parsed_body['Einsatzmittelliste']:
|
||||||
|
if r['Typ'] == 'PEALGRP':
|
||||||
|
zveis.append(r['Ressourcen'])
|
||||||
|
message +='\n'.join(zveis)
|
||||||
|
if 'Zusatztext zum Ort' in parsed_body:
|
||||||
|
message += "\n\nZusatztext zum Ort:\n"+parsed_body['Zusatztext zum Ort']
|
||||||
|
if 'Zusatztext zum Objekt' in parsed_body:
|
||||||
|
message += "\n\nZusatztext zum Objekt:\n"+parsed_body['Zusatztext zum Objekt']
|
||||||
|
|
||||||
|
logging.info("GET zu {}alarms?accesskey=XXX".format(api))
|
||||||
|
s = requests.Session()
|
||||||
|
s.mount('https://', requests.adapters.HTTPAdapter(max_retries=retries))
|
||||||
|
start = datetime.datetime.now()
|
||||||
|
message_channel_id = None
|
||||||
|
alarm_id = None
|
||||||
|
alarm_text = None
|
||||||
|
while message_channel_id is None and datetime.datetime.now() < start + datetime.timedelta(minutes=1):
|
||||||
|
r = s.get("{}alarms?accesskey={}".format(api, messenger_api_token))
|
||||||
|
r_json = r.json()
|
||||||
|
if 'items' in r_json.get('data',{}):
|
||||||
|
for item in r_json.get('data',{})['items']:
|
||||||
|
if str(r_json['data']['items'][item]['foreign_id']) == str(parsed_body['Auftragsnummer']):
|
||||||
|
logging.info("EinsatzNr {} in Divera gefunden, sende Nachricht...".format(r_json['data']['items'][item]['foreign_id']))
|
||||||
|
message_channel_id = r_json['data']['items'][item]['message_channel_id']
|
||||||
|
alarm_id = r_json['data']['items'][item]['id']
|
||||||
|
alarm_text = r_json['data']['items'][item]['text']
|
||||||
|
if message_channel_id is None or alarm_id is None:
|
||||||
|
time.sleep(20)
|
||||||
|
|
||||||
|
if alarmer_api_token != "":
|
||||||
|
if alarm_text is None:
|
||||||
|
alarm_text = ""
|
||||||
|
r = s.put("{}alarms/{}?accesskey={}".format(api, alarm_id, alarmer_api_token),json={
|
||||||
|
"Alarm": {
|
||||||
|
"text": alarm_text+"\n\n"+message,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
if message_channel_id:
|
||||||
|
r = s.post("{}messages?accesskey={}".format(api, messenger_api_token),json={
|
||||||
|
"Message": {
|
||||||
|
"message_channel_id": str(message_channel_id),
|
||||||
|
# "parent_id": 0,
|
||||||
|
"text": message,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
logging.error("divera_messenger", e)
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
|
||||||
|
from datetime import timedelta, datetime
|
||||||
|
import os
|
||||||
|
import ssl
|
||||||
|
import email
|
||||||
|
import logging
|
||||||
|
from imapclient import IMAPClient
|
||||||
|
from threading import Thread
|
||||||
|
from securecad_parser import parse_securecad_message
|
||||||
|
from hooks import webhook, alarminator_api, cups_print
|
||||||
|
import re
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
def run():
|
||||||
|
threads = {}
|
||||||
|
|
||||||
|
format = "%(asctime)s|%(threadName)s: %(message)s"
|
||||||
|
logging.basicConfig(format=format, level=logging.INFO,
|
||||||
|
datefmt="%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
def eventHandler(ELEMENT_NAME, uid, message_data, _server: IMAPClient = None):
|
||||||
|
email_message = email.message_from_bytes(message_data[b'RFC822'])
|
||||||
|
email_from: list[str] = re.findall(r'([\w\.-]+@[\w\.-]+)', email_message.get('From'))
|
||||||
|
flags = _server.get_flags(uid)
|
||||||
|
logging.info(ELEMENT_NAME + " - get Mail")
|
||||||
|
if 'Processed_{}'.format(parser_id).encode() in flags[uid]:
|
||||||
|
logging.info("Mail {} bereits verarbeitet.. ignoriere".format(uid))
|
||||||
|
if not IS_DEV:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
_server.add_flags(uid, ['\\SEEN','Processed_{}'.format(parser_id)])
|
||||||
|
logging.info("got Mail {} von {}".format(email_message.get('Subject'), email_from))
|
||||||
|
if any(mail in filter_from for mail in email_from):
|
||||||
|
# Get HTML body
|
||||||
|
html_body = ""
|
||||||
|
if email_message.is_multipart():
|
||||||
|
for part in email_message.walk():
|
||||||
|
if part.get_content_type() == 'text/html':
|
||||||
|
html_body = part.get_payload(decode=True).decode(part.get_content_charset() or 'utf-8', errors='replace')
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if email_message.get_content_type() == 'text/html':
|
||||||
|
html_body = email_message.get_payload(decode=True).decode(email_message.get_content_charset() or 'utf-8', errors='replace')
|
||||||
|
|
||||||
|
|
||||||
|
parsed_body = parse_securecad_message(html_body)
|
||||||
|
logging.debug(parsed_body)
|
||||||
|
if parsed_body != None:
|
||||||
|
if 'ALARMDEPESCHE' in parsed_body:
|
||||||
|
logging.info("Alarm für: {}".format(parsed_body['ALARMDEPESCHE']))
|
||||||
|
webhook(parsed_body)
|
||||||
|
alarminator_api(parsed_body)
|
||||||
|
cups_print(parsed_body,html_body)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def folder_event_subscriber(folder: str):
|
||||||
|
logging.info('folder_event_subscriber startet for Folder: {}'.format(folder))
|
||||||
|
with IMAPClient(server, ssl_context=ssl_context) as _server:
|
||||||
|
_server.login(username, password)
|
||||||
|
while True:
|
||||||
|
# filtern des ordners nach mails der letzten 24h, die nicht verarbeitet wurden
|
||||||
|
now = datetime.now()
|
||||||
|
_server.select_folder(folder, readonly=False)
|
||||||
|
q = ['SENTSINCE', now - timedelta(days=1),'NOT','KEYWORD', 'Processed_{}'.format(parser_id)]
|
||||||
|
if IS_DEV:
|
||||||
|
q = ['SENTSINCE', now - timedelta(days=1),'UNSEEN']
|
||||||
|
q = ['UNSEEN']
|
||||||
|
messages = _server.search(q)
|
||||||
|
cnt = messages.__len__()
|
||||||
|
if cnt > 0:
|
||||||
|
logging.info("{} Mails nicht verarbeitet in den letzten 2 Tagen in ordner: {}".format(cnt, folder))
|
||||||
|
for uid, message_data in _server.fetch(messages, 'RFC822').items():
|
||||||
|
# IMAPClient ist nicht thread-safe, daher wird hier der _server übergeben und kein Thread verwendet.
|
||||||
|
eventHandler('SearchFolderEvent', uid, message_data, _server)
|
||||||
|
# t = Thread(target=eventHandler, args=('SearchFolderEvent',uid,message_data,),name="eventHandler: SearchFolderEvent ({})".format(uid))
|
||||||
|
# t.start()
|
||||||
|
# aktives warten auf streaming_events. maximal eine minute lang, dann wird nochmal der ordner durchsucht, falls mails angekommen sind während eines timeout/cooldown.
|
||||||
|
_server.idle()
|
||||||
|
try:
|
||||||
|
logging.debug("Idle check for folder: {}".format(folder))
|
||||||
|
messages = _server.idle_check(timeout=60) # Timeout after 60 seconds
|
||||||
|
_server.idle_done()
|
||||||
|
# In den events stehen nur vorhandenen nachrichten. Exists ist nicht die neue Nachricht, sondern eine bereits vorhandene.
|
||||||
|
# for item in messages:
|
||||||
|
# if item[1] == b'EXISTS':
|
||||||
|
# logging.info("New messages in folder: {}".format(folder))
|
||||||
|
# for uid, message_data in _server.fetch([item[0]], 'RFC822').items():
|
||||||
|
# if uid:
|
||||||
|
# eventHandler('NewMailEvent', uid, message_data, _server)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error("Error during idle check: {}".format(e))
|
||||||
|
|
||||||
|
username = os.environ.get('username')
|
||||||
|
password = os.environ.get('password')
|
||||||
|
server = os.environ.get('server')
|
||||||
|
folders = os.environ.get('folders',"")
|
||||||
|
parser_id = os.environ.get('alarmfax_parser_id',"")
|
||||||
|
primary_smtp_address = os.environ.get('primary_smtp_address')
|
||||||
|
filter_from = os.environ.get('filter_from').split(";") if os.environ.get('filter_from') else []
|
||||||
|
IS_DEV = True if os.environ.get('IS_DEV') and os.environ.get('IS_DEV') == "True" else False
|
||||||
|
if IS_DEV:
|
||||||
|
logging.getLogger().setLevel(logging.INFO)
|
||||||
|
|
||||||
|
ssl_context = ssl.create_default_context()
|
||||||
|
|
||||||
|
|
||||||
|
with IMAPClient(server, ssl_context=ssl_context) as _server:
|
||||||
|
_server.login(username, password)
|
||||||
|
_server.logout()
|
||||||
|
folders_to_subscribe = []
|
||||||
|
for f in folders.split(";"):
|
||||||
|
if f == "":
|
||||||
|
folders_to_subscribe.append('INBOX')
|
||||||
|
else:
|
||||||
|
folders_to_subscribe.append(f)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
for f in folders_to_subscribe:
|
||||||
|
if not f in threads or not threads[f].is_alive():
|
||||||
|
logging.info("folder_event_subscriber for folder \"{}\" not alive, starting".format(f))
|
||||||
|
t = Thread(target=folder_event_subscriber, args=(f,), daemon=True, name="folder_event_subscriber {}".format(f))
|
||||||
|
threads[f] = t
|
||||||
|
t.start()
|
||||||
|
sleep(1)
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
import os
|
||||||
|
from imap_connect import run as run_imap
|
||||||
|
from exchange_connect import run as run_ews
|
||||||
|
mode = os.environ.get('mode')
|
||||||
|
if mode == 'IMAP':
|
||||||
|
run_imap()
|
||||||
|
elif mode == 'EWS':
|
||||||
|
run_ews()
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid mode specified. Use 'IMAP' or 'EWS'.")
|
||||||
+28
-2
@@ -5,8 +5,10 @@ from numpy import nan
|
|||||||
tt_list_alarmdepesche = []
|
tt_list_alarmdepesche = []
|
||||||
tt_list_infodepesche = []
|
tt_list_infodepesche = []
|
||||||
tt_list_einsatzprotokoll = []
|
tt_list_einsatzprotokoll = []
|
||||||
|
|
||||||
def parse_securecad_message(body_html: str):
|
def parse_securecad_message(body_html: str):
|
||||||
body_html = body_html.replace(u'\xa0', u' ')
|
body_html = body_html.replace(u'\xa0', u' ')
|
||||||
|
|
||||||
if 'ALARMDEPESCHE' in body_html:
|
if 'ALARMDEPESCHE' in body_html:
|
||||||
t_list = {}
|
t_list = {}
|
||||||
tables = pd.read_html(body_html) # Returns list of all tables on page
|
tables = pd.read_html(body_html) # Returns list of all tables on page
|
||||||
@@ -25,6 +27,7 @@ def parse_securecad_message(body_html: str):
|
|||||||
for r in table_dict:
|
for r in table_dict:
|
||||||
if table_dict[r][0] is not nan:
|
if table_dict[r][0] is not nan:
|
||||||
t_list[table_dict[r][0].strip(' :')] = table_dict[r][1]
|
t_list[table_dict[r][0].strip(' :')] = table_dict[r][1]
|
||||||
|
#Einsatzziel
|
||||||
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Einsatzziel' and 'Einsatzziel' not in t_list:
|
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Einsatzziel' and 'Einsatzziel' not in t_list:
|
||||||
t_list['Einsatzziel'] = {}
|
t_list['Einsatzziel'] = {}
|
||||||
for r in table_dict:
|
for r in table_dict:
|
||||||
@@ -32,6 +35,12 @@ def parse_securecad_message(body_html: str):
|
|||||||
t_list['Einsatzziel'][table_dict[r][0].strip(' :')] = table_dict[r][1]
|
t_list['Einsatzziel'][table_dict[r][0].strip(' :')] = table_dict[r][1]
|
||||||
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Einsatzziel' and 'Einsatzziel' in t_list:
|
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Einsatzziel' and 'Einsatzziel' in t_list:
|
||||||
continue
|
continue
|
||||||
|
elif t_count > 3 and table_dict[0] is not nan and 'Einsatzziel' in t_list and len(t_list['Einsatzziel']) == 0:
|
||||||
|
#Eigene Tabelle unter 'Einsatzziel'
|
||||||
|
for r in table_dict:
|
||||||
|
if table_dict[r][0] is not nan and table_dict[r][0] != 'Einsatzziel':
|
||||||
|
t_list['Einsatzziel'][table_dict[r][0].strip(' :')] = table_dict[r][1]
|
||||||
|
#Zusatztext zum Ort
|
||||||
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Zusatztext zum Ort' and 'Zusatztext zum Ort' not in t_list:
|
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Zusatztext zum Ort' and 'Zusatztext zum Ort' not in t_list:
|
||||||
t_list['Zusatztext zum Ort'] = []
|
t_list['Zusatztext zum Ort'] = []
|
||||||
for r in table_dict:
|
for r in table_dict:
|
||||||
@@ -39,6 +48,12 @@ def parse_securecad_message(body_html: str):
|
|||||||
t_list['Zusatztext zum Ort'].append(table_dict[r][1])
|
t_list['Zusatztext zum Ort'].append(table_dict[r][1])
|
||||||
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Zusatztext zum Ort' and 'Zusatztext zum Ort' in t_list:
|
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Zusatztext zum Ort' and 'Zusatztext zum Ort' in t_list:
|
||||||
continue
|
continue
|
||||||
|
elif t_count > 3 and table_dict[0] is not nan and 'Zusatztext zum Ort' in t_list and len(t_list['Zusatztext zum Ort']) == 0:
|
||||||
|
#Eigene Tabelle unter 'Zusatztext zum Ort'
|
||||||
|
for r in table_dict:
|
||||||
|
if table_dict[r][0] is not nan and table_dict[r][0] != 'Zusatztext zum Ort':
|
||||||
|
t_list['Zusatztext zum Ort'].append(table_dict[r][1])
|
||||||
|
#Zusatztext zum Objekt
|
||||||
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Zusatztext zum Objekt' and 'Zusatztext zum Objekt' not in t_list:
|
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Zusatztext zum Objekt' and 'Zusatztext zum Objekt' not in t_list:
|
||||||
t_list['Zusatztext zum Objekt'] = []
|
t_list['Zusatztext zum Objekt'] = []
|
||||||
for r in table_dict:
|
for r in table_dict:
|
||||||
@@ -46,13 +61,24 @@ def parse_securecad_message(body_html: str):
|
|||||||
t_list['Zusatztext zum Objekt'].append(table_dict[r][1])
|
t_list['Zusatztext zum Objekt'].append(table_dict[r][1])
|
||||||
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Zusatztext zum Objekt' and 'Zusatztext zum Objekt' in t_list:
|
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Zusatztext zum Objekt' and 'Zusatztext zum Objekt' in t_list:
|
||||||
continue
|
continue
|
||||||
|
elif t_count > 3 and table_dict[0] is not nan and 'Zusatztext zum Objekt' in t_list and len(t_list['Zusatztext zum Objekt']) == 0:
|
||||||
|
#Eigene Tabelle unter 'Zusatztext zum Objekt'
|
||||||
|
for r in table_dict:
|
||||||
|
if table_dict[r][0] is not nan and table_dict[r][0] != 'Zusatztext zum Objekt':
|
||||||
|
t_list['Zusatztext zum Objekt'].append(table_dict[r][1])
|
||||||
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Einsatzmittelliste':
|
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Einsatzmittelliste':
|
||||||
# es folgt die Einsatzmittelliste
|
# es folgt die Einsatzmittelliste
|
||||||
continue
|
continue
|
||||||
elif t_count > 3 and table_dict[0] is not nan and table_dict[0][0] == 'Ressourcen'and table_dict[0][1] == 'Typ' and table_dict[0][2] == 'Organisation':
|
elif t_count > 3 and table_dict[0] is not nan and len(table_dict)>1 and (
|
||||||
|
# In der ersten Zeile steht "Ressourcen, Typ, Organisation"
|
||||||
|
(table_dict[0][0] == 'Ressourcen'and table_dict[0][1] == 'Typ' and table_dict[0][2] == 'Organisation' )
|
||||||
|
or
|
||||||
|
# In der ersten Zeile steht "Alarmierte Ressourcen", in der zweiten Zeile steht "Ressourcen, Typ, Organisation"
|
||||||
|
(table_dict[1][0] == 'Ressourcen'and table_dict[1][1] == 'Typ' and table_dict[1][2] == 'Organisation' )
|
||||||
|
):
|
||||||
t_list['Einsatzmittelliste'] = []
|
t_list['Einsatzmittelliste'] = []
|
||||||
for r in table_dict:
|
for r in table_dict:
|
||||||
if table_dict[r][0] != "Ressourcen":
|
if table_dict[r][0] != "Ressourcen" and table_dict[r][0] != 'Alarmierte Ressourcen':
|
||||||
t_list['Einsatzmittelliste'].append({
|
t_list['Einsatzmittelliste'].append({
|
||||||
'Ressourcen': table_dict[r][0] if table_dict[r][0] is not nan else "",
|
'Ressourcen': table_dict[r][0] if table_dict[r][0] is not nan else "",
|
||||||
'Typ': table_dict[r][1] if table_dict[r][1] is not nan else "",
|
'Typ': table_dict[r][1] if table_dict[r][1] is not nan else "",
|
||||||
|
|||||||
+4
-5
@@ -2,13 +2,11 @@ version: "2"
|
|||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
build: ./
|
build: ./
|
||||||
#image: gitea.simonzeyer.de/simon/wnd_ils_alarmfax_parser:latest
|
image: gitea.simonzeyer.de/simon/wnd_ils_alarmfax_parser:latest
|
||||||
restart: always
|
restart: always
|
||||||
privileged: true
|
privileged: true
|
||||||
# ports:
|
|
||||||
# - 631:631
|
|
||||||
# - 5000:5000
|
|
||||||
environment:
|
environment:
|
||||||
|
- mode=${mode}
|
||||||
- username=${username}
|
- username=${username}
|
||||||
- password=${password}
|
- password=${password}
|
||||||
- server=${server}
|
- server=${server}
|
||||||
@@ -23,7 +21,8 @@ services:
|
|||||||
- alarminator_zvies_use_PEALGRP=${alarminator_zvies_use_PEALGRP}
|
- alarminator_zvies_use_PEALGRP=${alarminator_zvies_use_PEALGRP}
|
||||||
- printer=${printer}
|
- printer=${printer}
|
||||||
- print_num=${print_num}
|
- print_num=${print_num}
|
||||||
- MAPS_API_KEY=${MAPS_API_KEY}
|
- DIVERA_MESSANGER_API_KEY=${DIVERA_MESSANGER_API_KEY}
|
||||||
|
- DIVERA_ALARMER_API_KEY=${DIVERA_ALARMER_API_KEY}
|
||||||
volumes:
|
volumes:
|
||||||
- ./cups:/etc/cups
|
- ./cups:/etc/cups
|
||||||
- ./cupsd.conf.txt:/etc/cups/cupsd.conf
|
- ./cupsd.conf.txt:/etc/cups/cupsd.conf
|
||||||
|
|||||||
+3
-19
@@ -1,34 +1,20 @@
|
|||||||
blinker==1.8.2
|
|
||||||
Brotli==1.1.0
|
|
||||||
cached-property==1.5.2
|
cached-property==1.5.2
|
||||||
certifi==2022.12.7
|
certifi==2022.12.7
|
||||||
cffi==1.15.1
|
cffi==1.15.1
|
||||||
charset-normalizer==3.0.1
|
charset-normalizer==3.0.1
|
||||||
click==8.1.7
|
|
||||||
cryptography==39.0.0
|
cryptography==39.0.0
|
||||||
cssselect2==0.7.0
|
|
||||||
defusedxml==0.7.1
|
defusedxml==0.7.1
|
||||||
dnspython==2.3.0
|
dnspython==2.3.0
|
||||||
exchangelib==4.9.0
|
exchangelib==4.9.0
|
||||||
Flask==3.0.3
|
|
||||||
fonttools==4.54.1
|
|
||||||
html5lib==1.1
|
|
||||||
idna==3.4
|
idna==3.4
|
||||||
isodate==0.6.1
|
isodate==0.6.1
|
||||||
itsdangerous==2.2.0
|
|
||||||
Jinja2==3.1.4
|
|
||||||
lxml==4.9.2
|
lxml==4.9.2
|
||||||
MarkupSafe==3.0.1
|
|
||||||
ntlm-auth==1.5.0
|
ntlm-auth==1.5.0
|
||||||
numpy==1.24.1
|
numpy==1.24.1
|
||||||
oauthlib==3.2.2
|
oauthlib==3.2.2
|
||||||
pandas==1.5.2
|
pandas==1.5.2
|
||||||
pillow==10.4.0
|
|
||||||
pycparser==2.21
|
pycparser==2.21
|
||||||
pycups==2.0.1
|
|
||||||
pydyf==0.11.0
|
|
||||||
Pygments==2.14.0
|
Pygments==2.14.0
|
||||||
pyphen==0.16.0
|
|
||||||
python-dateutil==2.8.2
|
python-dateutil==2.8.2
|
||||||
pytz==2022.7.1
|
pytz==2022.7.1
|
||||||
pytz-deprecation-shim==0.1.0.post0
|
pytz-deprecation-shim==0.1.0.post0
|
||||||
@@ -36,13 +22,11 @@ requests==2.28.2
|
|||||||
requests-ntlm==1.1.0
|
requests-ntlm==1.1.0
|
||||||
requests-oauthlib==1.3.1
|
requests-oauthlib==1.3.1
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
tinycss2==1.3.0
|
|
||||||
tzdata==2022.7
|
tzdata==2022.7
|
||||||
tzlocal==4.2
|
tzlocal==4.2
|
||||||
urllib3==1.26.14
|
urllib3==1.26.14
|
||||||
weasyprint==62.3
|
|
||||||
webencodings==0.5.1
|
|
||||||
Werkzeug==3.0.4
|
|
||||||
xmltodict==0.12.0
|
xmltodict==0.12.0
|
||||||
xmltojson==2.0.1
|
xmltojson==2.0.1
|
||||||
zopfli==0.2.3
|
pycups==2.0.1
|
||||||
|
weasyprint
|
||||||
|
imapclient==3.0.1
|
||||||
Reference in New Issue
Block a user