Durchwahl Export per REST-API (Python)

Hallo, ich möchte hier mal mein Export-Script für Durchwahlen zur verfügung stellen, vielleicht kann es jemand brauchen, bzw. als Grundlage für eine eigene Idee verwenden!


Problemstellung
Wie es sicher bei vielen der Fall ist, wurde bei uns jemand dazu verdonnert eine interne Telefonliste zu pflegen, was natürlich nicht gut klappt und vor allem eine unnötige wiederkehrende Aufgabe ist.


Lösung
Ich habe daher ein Python Script gebaut, das auf einem Linux Server per Systemd-Timer jede Nacht ausgeführt wird und eine fertig Formatierte Text-Datei im Markdown-Format erzeugt. In meinem Fall wird diese Datei direkt auf das Firmeninterne Dokuwiki geschrieben, so das diese Liste für die Mitarbeiter jederzeit einsehbar ist.


Zum Spannenden Teil:

Das Python-script Selbst:

PhonebookWorker.py

#!/bin/python3
import requests
import datetime
import logging
import logging.handlers
import sys

# ###################################################################################
# Config:

# Blacklist mit Benutzernamen die von der Liste ausgenommen werden:
user_blacklist = ["Administrator", "Klingel"]

# Ausgabe Datei:
output_filename = "/home/data/dokuwiki/data/pages/dokumentation/telefonanlage/rufnummern_durchwahlen.txt"

# API Zugangsdaten:
api_auth_user = 'API-User'
api_auth_pass = 'API-Password'

# Server Adresse, bitte hostname und instanzname entsprechend anpassen!
url_base = 'https://hostname/instanzname/services/'
url_object = 'identity/'


# ###################################################################################
# Logging:

# Logger Name
logger = logging.getLogger("PhonebookWorker")

# Loglevel
# Das loglevel kann am ende auf ERROR gestellt werden um nicht unnötig in den Syslog zu schreiben
# beim einrichten macht das level INFO allerdings nützliche ausgaben zur Fehlersuche!

# Valid Loglevels are: CRITICAL, ERROR, WARNING, INFO, DEBUG
logger.setLevel(logging.INFO)

handler = logging.handlers.SysLogHandler('/dev/log')
formatter = logging.Formatter('%(name)s[%(process)d]: %(levelname)s %(message)s')

handler.formatter = formatter
logger.addHandler(handler)

# ###################################################################################
# Code
def getextention(object_element):
    return object_element.get('009ext_extension')
logger.info("Starting Phonebook worker...")
logger.info("Trying to connect to REST API: " + url_base)

# API Verbindung aufbauen:
try:
    r = requests.get(url_base + url_object, auth=(api_auth_user, api_auth_pass))
    r.raise_for_status()
except requests.exceptions.RequestException as e:
    logger.error("Connection error: " + str(e))
    print(e)
    sys.exit(1)
logger.info("Got " + str(r))
response = r.json()

# Serverantwort sortieren:
response.sort(key=getextention)

logger.info("Creating output File: \"" + output_filename + "\"!")
try:
    file = open(output_filename, "w")
except:
    logger.error("Unable to open File: \"" + output_filename + "\" for writing!")
    sys.exit(1)

# Hier wird das Textfile mit statischem inhalt befüllt:
file.write("===== Telefonliste =====\n")
file.write("Anklicken der Kopfzeile sortiert die Tabelle.\n")
file.write("<sortable>\n")
file.write("^**Durchwahl**^**Vorname**^**Nachname**|\n")

count_all = 0
count_user = 0
count_blacklist = 0

# Hauptschleife in der alle benutzerobjekte abgearbeitet werden:
for user_object in response:
    displayname = user_object.get('003use_bez')
    displayname = displayname.split()
    extention = user_object.get('009ext_extension')

    count_all += 1

    blacklist = False

    for name in user_blacklist:
        if name == displayname[0]:
            blacklist = True
            count_blacklist += 1

    if not blacklist:
        if len(displayname) > 1:
            givenname = displayname[1]
        else:
            givenname = " "
        firstname = displayname[0]
        file.write("|" + extention + "|" + firstname + "|" + givenname + "|\n")
        count_user += 1

# Aktuelles Datum vom System holen
now = datetime.datetime.now()

# Hier wieder statischer Inhalt mit datum:
file.write("</sortable>\n")
file.write("Zuletzt aktualisiert am: " + now.strftime("%d.%m.%Y") + " um " + now.strftime("%H:%M" + "\n"))
file.close()

# Wenn das Loglevel auf Info steht, Statistiken ausgeben:
logger.info("Done! Processed " + str(count_all) + " Users, " + str(count_blacklist) + " are on Blacklist, " + str(count_user) + " written to File!")
sys.exit(0)

Ich habe noch ein paar Kommentare eingebaut, ich hoffe es ist halbwegs verständlich aufgebaut :wink:

Damit das ganze dann auch automatisch läuft, brauchts natürlich noch einen Timer, ich habe hier mal einen SystemD Timer ausprobiert, man kann natürlich auch einen klassischen Cron-Job einrichten…


Automatisierung
Die Dateipfade beziehen sich hier auf ein Debian basiertes System, bei anderen Distributionen kann das anders sein! (Google hilft an dieser Stelle)

Der Timer
/usr/lib/systemd/system/PhonebookWorker.timer

[Unit]
Description=PhonebookWorker timer

[Timer]
OnBootSec=1h
OnCalendar=2:00

[Install]
WantedBy=basic.target

OnBootSec=1h bedeutet, der Dienst PhonebookWorker wird eine Stunde nachdem der Server hochgefahren wurde, einmal ausgeführt, OnCalendar=2:00 bedeutet, jede Nacht um 2:00 Uhr wird der Dienst wieder Ausgeführt!

Der Dienst
/etc/systemd/system/PhonebookWorker.service

[Unit]
Description=PhonebookWorker
After=network.target

[Service]
Type=simple
User=www-data
ExecStart=/opt/PhonebookWorker/PhonebookWorker.py

[Install]
WantedBy=multi-user.target

Nach dem diese Dateien angelegt sind muss systemd den neu hinzugefügten dienst einlesen, das geht mit systemctl daemon-reload. Anschließend kann der Timer aktiviert und gestartet werden:
systemctl enable --now PhonebookWorker.timer

Das sollte es auch schon gewesen sein, somit wird jede Nacht die Durchwahlliste automatisch Aktualisiert!

Fehlersuche
Um zu schauen ob der System Timer erfolgreich gestartet wurde kann man mit folgendem Befehl alle aktiven timer auflisten, hier muss der PhonebookWorker dabei sein:
systemctl list-timers

Um den log vom script anzusehen hilft dieser filter:
cat /var/log/syslog | grep PhonebookWorker | less