commit c19d102648e769a5448e6d5e397b6943ca495ebc Author: Reiko Kaps Date: Sun Jun 14 15:52:08 2020 +0200 Erster Prototyp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f836aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*~ +*.pyc diff --git a/jitsi-log.py b/jitsi-log.py new file mode 100755 index 0000000..7753e2b --- /dev/null +++ b/jitsi-log.py @@ -0,0 +1,223 @@ +#!/bin/env python3 +# + +import re +import sys +import threading +import time +from time import sleep +from os.path import basename + +from datetime import datetime +from argparse import ArgumentParser +from http.server import BaseHTTPRequestHandler, HTTPServer + +try: + from pygtail import Pygtail + +except ImportError as e: + print('[Error] Please install pygtail via pip! {}'.format(e)) + sys.exit(1) + +try: + from sh import tail + +except ImportError as e: + print('[Error] Please install sh via pip! {}'.format(e)) + sys.exit(1) + + +class MeetingRoom(): + """ + represent a Jitsi Meetingroom + jid: eg room@conference.meet.leinelab.org + ctime: eg 2020-06-01 12:32:02 .. + """ + + members = [] + + def __init__(self, jid, ctime): + self.jid = jid + self.ctime = ctime + + def setOwner(self, name): + self.owner = name + + def getOwner(self): + if hasattr(self, 'owner'): + return self.owner + else: + return None + + def addMember(self, name): + self.members.append(name) + + def getMembers(self): + return self.members + + def __str__(self): + return '{}: {}'.format(self.jid, self.owner) + + +class logThread(threading.Thread): + def __init__(self, threadID, name, filename): + threading.Thread.__init__(self) + self.threadID = threadID + self.name = name + self.filename = filename + + def run(self): + while True: + getLogMsg(self.filename) + sleep(5) + + +class MyServer(BaseHTTPRequestHandler): + def do_GET(self): + self.send_response(200) + self.send_header("Content-type", "text/html") + self.end_headers() + self.wfile.write(bytes("Jitsi Stats", "utf-8")) + self.wfile.write(bytes("

Request: %s

" % self.path, "utf-8")) + self.wfile.write(bytes("", "utf-8")) + self.wfile.write(bytes("

This is an example web server.

", "utf-8")) + if basename(self.path) in roomList: + self.wfile.write(bytes("

"+basename(self.path)+": "+str(roomList[basename(self.path)].ctime)+"

", "utf-8")) + self.wfile.write(bytes("

Participants: "+str(len(roomList[basename(self.path)].members))+"

", "utf-8")) + else: + for key, value in roomList.items(): + link = '

{}

'.format(value.jid, key) + self.wfile.write(bytes(link, "utf-8")) + + + self.wfile.write(bytes("", "utf-8")) + + +def getRoomName(jid): + return jid.split("@")[0].strip() + + +def mkDatetime(str_date, str_time): + return datetime.fromisoformat('{} {}'.format(str_date, str_time)) + + +# active room dictionary +roomList = {} +testList = { + 'test': 'Nichts wichtiges', + 'lounge': 'lounge@meet.leinelab.de' +} + +# @see https://regex101.com/r/R1B1OL/1 +regex = r"(Jicofo)\s(\d+-\d+-\d+)\s(\d+\:\d+\:\d+\.\d+)\s(\w+):\s\[(\d+)\]\s(.*)\(\)\s(.*)" +prog = re.compile(regex) + +## +# new jitsi room +room_regex = r"(^Joining\sthe\sroom):(.*)" +room = re.compile(room_regex) + +# disposed room +disposed_regex = r"^Disposed\sconference\sfor\sroom\:\s(.*)@(.*)\sconference\scount:\s(\d+)" +disposed = re.compile(disposed_regex) + +## +# get the room owner +owner_regex = r"Granted\sowner\sto\s([a-z0-9-]+)\@(.*)\/(.*)" +owner = re.compile(owner_regex) + +# get member for room +member_regex = r"^Member\s(.*)@(.*)\/(.*)\sjoined." +member = re.compile(member_regex) + + +def process_line(line): + """ + process a logfile line, using global object and vars + globals: prog, disposed, owner, member, roomList + line: string + """ + erg = prog.match(line) + if erg: + # detect room creation + new_room = room.match(erg.group(7)) + if new_room: + room_name = getRoomName(new_room.group(2)) + room_date = mkDatetime(erg.group(2), erg.group(3)) + print('{} {}'.format(room_date, room_name)) + currentRoom = MeetingRoom(room_name, room_date) + if room_name in roomList: + # delete old room and recreate it + del roomList[room_name] + roomList[room_name] = currentRoom + else: + roomList[room_name] = currentRoom + + disposed_room = disposed.match(erg.group(7)) + if disposed_room: + room_name = disposed_room.group(1) + print('-> room disposed: {}'.format(room_name)) + if room_name in roomList: + del roomList[room_name] + owner_match = owner.match(erg.group(7)) + if owner_match: + room_name = owner_match.group(1).strip() + room_owner = owner_match.group(3).strip() + # print('{}: {}'.format(room_name, room_owner)) + if room_name in roomList: + roomList[room_name].setOwner(room_owner) + + member_match = member.match(erg.group(7)) + if member_match: + room_name = member_match.group(1).strip() + room_member = member_match.group(3).strip() + print('--> {}: {}'.format(room_name, room_member)) + if room_name in roomList: + roomList[room_name].addMember(room_member) + + +def getLogMsg(logfile): + """ + get log messages and commit it to process_line + used pytail module + """ + # for line in Pygtail(logfile, full_lines=True): + # process_line(line) + + for line in tail("-f", logfile, _iter=True): + process_line(line) + +if __name__ == '__main__': + # start cmdline processing + parser = ArgumentParser(description='Jitsi Meet Conference Stats') + parser.add_argument('--log', '-l', + help='full path to jicofo logfile eg. /var/log/jitsi/jicofo.log') + parser.add_argument('--verbose', '-v', + help='be verbose eg. for debugging', action='store_true') + parser.add_argument('--logwatch', '-w', + help='run as logwatch module, dont start the webserver and only run once') + + args = parser.parse_args() + + if args.log: + try: + loggerThread = logThread(1, "Thread-Logger", args.log) + loggerThread.start() + except: + print('Error: unable to start threads') + + hostName = 'localhost' + serverPort = 9999 + webServer = HTTPServer((hostName, serverPort), MyServer) + + try: + print("Server started http://%s:%s" % (hostName, serverPort)) + webServer.serve_forever() + except: + pass + + # for key in roomList: + # print('Room : {}'.format(roomList[key].jid)) + # print(' Created: {}'.format(roomList[key].ctime)) + # print(' Owner : {}'.format(roomList[key].getOwner())) + # print(' Members: {}'.format(roomList[key].getMembers())) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a2cbd98 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +parso==0.7.0 +pygtail==0.11.1 +sh==1.13.1 +svgwrite==1.4