diff --git a/bot_main.py b/bot_main.py index 3ce2902..b942e12 100755 --- a/bot_main.py +++ b/bot_main.py @@ -7,6 +7,7 @@ import slixmpp import random import threading import socket +import time from hintTables import * from commands import * @@ -26,6 +27,8 @@ class MUCBot(slixmpp.ClientXMPP): self.room = room self.nick = nick + self.owners = {} + self.sbuf = None # The session_start event will be triggered when # the bot establishes its connection with the server @@ -51,46 +54,20 @@ class MUCBot(slixmpp.ClientXMPP): async def start(self, event): """ - Process the session_start event. - - Typical actions for the session_start event are - requesting the roster and broadcasting an initial - presence stanza. - - Arguments: - event -- An empty dictionary. The session_start - event does not provide any additional - data. + Requestthe roster and broadcast initial presence stanza. """ + await self.get_roster() self.send_presence() self.plugin['xep_0045'].join_muc(self.room, self.nick, - # If a room password is needed, use: # password=the_room_password, ) def muc_message(self, msg): """ - Process incoming message stanzas from any chat room. Be aware - that if you also have any handlers for the 'message' event, - message stanzas may be processed by both handlers, so check - the 'type' attribute when using a 'message' event handler. - Whenever the bot's nickname is mentioned, respond to - the message. - - IMPORTANT: Always check that a message is not from yourself, - otherwise you will create an infinite loop responding - to your own messages. - - This handler will reply to messages that mention - the bot's nickname. - - Arguments: - msg -- The received message stanza. See the documentation - for stanza objects and the Message stanza to see - how it may be used. + the message from any muc """ if msg['mucnick'] == self.nick: @@ -102,10 +79,13 @@ class MUCBot(slixmpp.ClientXMPP): random.shuffle(cmdhints) for opcod in cmdhints: - if opcod in msg['body']: + if msg['body'][0] == "!" and opcod in msg['body']: self.send_message(mto=msg['from'].bare, mbody="%s, %s" % (msg['mucnick'], - commandtable[opcod]() ), + commandtable[opcod](self.owners[msg['from'].bare], + msg['mucnick'], + msg['body'], + self.sbuf)), mtype='groupchat') return @@ -144,25 +124,25 @@ class MUCBot(slixmpp.ClientXMPP): # And fallback self.send_message(mto=msg['from'].bare, - mbody="%s, je n'ai pas compris (je suis un peu bête) mais j'ai bien lu!" % msg['mucnick'], + mbody="%s, je n'ai pas compris (je suis un peu bot)" % msg['mucnick'], mtype='groupchat') def muc_online(self, presence): """ - Process a presence stanza from a chat room. In this case, - presences from users that have just come online are - handled by sending a welcome message that includes - the user's nickname and role in the room. - - Arguments: - presence -- The received presence stanza. See the - documentation for the Presence stanza - to see how else it may be used. + Send a welcome message that includes + the user's nickname """ + if presence['muc']['nick'] != self.nick: self.send_message(mto=presence['from'].bare, mbody="Salut %s !" % (presence['muc']['nick']), mtype='groupchat') + + if presence['muc']['affiliation'] == "owner": + if not presence['from'].bare in self.owners: + self.owners[presence['from'].bare] = [] + + self.owners[presence['from'].bare].append(presence['muc']['nick']) if __name__ == '__main__': # Setup the command line arguments. @@ -202,11 +182,18 @@ if __name__ == '__main__': # Create buffer sBuffer = SharedBuffer(xmpp) + xmpp.sbuf = sBuffer # Connect to the XMPP server and start processing XMPP stanzas. xmpp.connect() localservthread = LocalServer(sBuffer) + localservthread.daemon = True localservthread.start() + time.sleep(1) + + if not localservthread.is_alive(): + exit(1) + xmpp.process() diff --git a/commands.py b/commands.py index f6176ce..00a00ab 100644 --- a/commands.py +++ b/commands.py @@ -2,7 +2,7 @@ # Isengard commands -def cmdping(): +def cmdping(owners, nick, text, sbuf): """ Ping command. """ @@ -10,9 +10,38 @@ def cmdping(): return "pong !" +def cmdmainteneur(owners, nick, text, sbuf): + """ + Change maintainer for an host + """ + + if not nick in owners: + return "désolé mais vous n'êtes pas autorisé à utiliser cette commande." + + try: + splittedtext = text.split(" ") + + # print maintainer + if len(splittedtext) == 2: + host = splittedtext[1] + + return "le responsable de cette machine est " \ + + sbuf.buf[host]["maintainer"] + + if len(splittedtext) == 3: + host = splittedtext[1] + maintainer = splittedtext[2] + + sbuf.buf[host]["maintainer"] = maintainer + + return "le responsable est à présent " \ + + sbuf.buf[host]["maintainer"] + + except Exception as e: + print(repr(e)) + return "Erreur à l'exécution" - - + return "Syntaxe invalide" @@ -24,6 +53,7 @@ def cmdping(): commandtable = { "ping" : cmdping, +"mainteneur" : cmdmainteneur, } diff --git a/localServer.py b/localServer.py index 5bd055d..50e8d31 100644 --- a/localServer.py +++ b/localServer.py @@ -8,9 +8,10 @@ class LocalServer(threading.Thread): self.sharedBuffer = sharedBuffer def run(self): + sockfd = socket.socket() print("Socket successfully created") - port = 12345 # Reserve a port on your computer...in our case it is 12345, but it can be anything + port = 12346 # Reserve a port on your computer...in our case it is 12345, but it can be anything sockfd.bind(('127.0.0.1', port)) print("Socket binded to %s" %(port)) sockfd.listen(5) # Put the socket into listening mode diff --git a/sharedBuffer.py b/sharedBuffer.py index e8244d2..4a35e93 100644 --- a/sharedBuffer.py +++ b/sharedBuffer.py @@ -1,18 +1,167 @@ class SharedBuffer: + def __init__(self, linkedBot): - self.buf = [] + self.buf = {} self.linkedBot = linkedBot def flush(self): - for msg in self.buf: - self.linkedBot.send_message( - mto=msg.split("|")[0], - mbody=msg.split("|")[1], + + for host in self.buf: + if not isinstance(self.buf[host], dict): + continue + + maintainer = self.buf[host]["maintainer"] + + if self.buf[host]["needUpdate"]: + destmuc = self.buf[host]["destmuc"] + text = self.buf[host]["text"] + msg = "(néant)" + + if self.buf[host]["status_type"] == "PROBLEM": + msg = "{}, je détecte un problème sur {} ({})".format(maintainer, host, text) + + elif self.buf[host]["status_type"] == "UNKNOWN": + msg = "{}, état de {} inconnu ({})".format(maintainer, host, text) + + elif self.buf[host]["status_type"] == "RECOVERY": + msg = "{}, problème résolu sur {} ({})".format(maintainer, host, text) + + self.linkedBot.send_message( + mto=destmuc, + mbody=msg, + mtype='groupchat') + + self.buf[host]["needUpdate"] = False + print("Sent to {}, msg: {}".format(destmuc, msg)) + + for service in self.buf[host]: + if not isinstance(self.buf[host][service], dict): + continue + + if self.buf[host][service]["needUpdate"]: + destmuc = self.buf[host][service]["destmuc"] + text = self.buf[host][service]["text"] + msg = "(néant)" + + if self.buf[host][service]["status_type"] == "PROBLEM": + msg = "{}, je détecte un problème de {} sur {} ({})".format(maintainer, service, host, text) + + elif self.buf[host][service]["status_type"] == "UNKNOWN": + msg = "{}, état de {} inconnu pour {} ({})".format(maintainer, service, host, text) + + elif self.buf[host][service]["status_type"] == "RECOVERY": + msg = "{}, problème de {} résolu sur {} ({})".format(maintainer, service, host, text) + + self.linkedBot.send_message( + mto=destmuc, + mbody=msg, mtype='groupchat') - self.buf.pop(self.buf.index(msg)) + + self.buf[host][service]["needUpdate"] = False + print("Sent to {}, msg: {}".format(destmuc, msg)) + + print("End of flush") def push(self, msg): - self.buf.append(msg) - if len(self.buf) > 0: - self.flush() + # separate dest and message + destmuc, rmsg = msg.split("|") + + # separate and parse lines + cutmsg_l0 = rmsg.split("\n")[0].split(" ") + cutmsg_l1 = rmsg.split("\n")[1].split("-") + + # get the status of location + status_type = cutmsg_l0[0].replace(" ", "") + status_state = cutmsg_l0[-1].replace(" ", "") + + # get the location + location = "" + for i in range(len(cutmsg_l0) - 2): + location += cutmsg_l0[i+1] + " " + location = location[:-1] + + # check if message is about a service or host + if len(location.split("/")) > 1: + host, service = location.split("/") + else: + host = location + service = False + + text = status_state + ": " + cutmsg_l1[1].split("(")[0][1:] + + raw = rmsg.split("\n")[1] + + print("Dest: %s, Msg: %s" % (destmuc, rmsg)) + print("Status: %s" % (status_type + " (" + status_state + ")")) + print("Host: %s, Service: %s" % (host, service)) + print("Text: %s" % (text)) + + if host in self.buf: + if service and service in self.buf[host]: + if status_state != self.buf[host][service]["status_state"] \ + or status_type != self.buf[host][service]["status_type"]: + self.buf[host][service]["status_state"] = status_state + self.buf[host][service]["status_type"] = status_type + self.buf[host][service]["destmuc"] = destmuc + self.buf[host][service]["text"] = text + self.buf[host][service]["raw"] = raw + self.buf[host][service]["needUpdate"] = True + + else: + + # exit if problem resolved (but unkown in the first place) + if status_type == "RECOVERY": + return + + # create zone for service + self.buf[host][service] = {} + self.buf[host][service]["destmuc"] = destmuc + self.buf[host][service]["status_state"] = status_state + self.buf[host][service]["status_type"] = status_type + self.buf[host][service]["text"] = text + self.buf[host][service]["raw"] = raw + self.buf[host][service]["needUpdate"] = True + + else: + + # exit if problem resolved (but unkown in the first place) + if status_type == "RECOVERY": + return + + # create zone for service + if service: + self.buf[host] = {} + self.buf[host]["destmuc"] = None + self.buf[host]["status_state"] = None + self.buf[host]["status_type"] = None + self.buf[host]["text"] = None + self.buf[host]["raw"] = None + self.buf[host]["maintainer"] = None + self.buf[host]["needUpdate"] = False + self.buf[host][service] = {} + self.buf[host][service]["destmuc"] = destmuc + self.buf[host][service]["status_state"] = status_state + self.buf[host][service]["status_type"] = status_type + self.buf[host][service]["text"] = text + self.buf[host][service]["raw"] = raw + self.buf[host][service]["needUpdate"] = True + else: + self.buf[host] = {} + self.buf[host]["destmuc"] = destmuc + self.buf[host]["status_state"] = status_state + self.buf[host]["status_type"] = status_type + self.buf[host]["text"] = text + self.buf[host]["raw"] = raw + self.buf[host]["maintainer"] = None + self.buf[host]["needUpdate"] = True + + print(self.buf) + print("Sending...") + self.flush() + print("Sent.") + print(self.buf) + print("End of push") + +#PROBLEM video.chalec.org/System load CRITICAL +#CRITICAL - Charge moyenne: 6.45, 5.61, 4.12 (Commentaire: [] ) diff --git a/xmpp-notification.py b/xmpp-notification.py new file mode 100755 index 0000000..cce2ec3 --- /dev/null +++ b/xmpp-notification.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +import socket +import sys,os + +s = socket.socket() + +port = 12346 # Define the port on which you want to connect + +s.connect(('127.0.0.1', port)) # Connect to the server on local computer + +str = "%s|%s" % (sys.argv[1], sys.argv[2]) + +s.send(str.encode()) + +if s.recv(1024) != b'': # Receive data from the server + exit(1) + +s.close() +exit(0)