From fd5019f739721fe146ba5780ce86b1512aeb990c Mon Sep 17 00:00:00 2001 From: raspbeguy Date: Sat, 4 Jun 2016 19:03:10 +0200 Subject: [PATCH] =?UTF-8?q?am=C3=A9lior=C3=A9=20sexiictl=20et=20ajout?= =?UTF-8?q?=C3=A9=20des=20commandes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin-scripts/sexiictl | 30 +++++++++++- sexiibot/channel.py | 2 + sexiibot/core.py | 102 ++++++++++++++++++++++++++++++----------- 3 files changed, 106 insertions(+), 28 deletions(-) diff --git a/admin-scripts/sexiictl b/admin-scripts/sexiictl index 20a7a4e..2919991 100755 --- a/admin-scripts/sexiictl +++ b/admin-scripts/sexiictl @@ -3,6 +3,7 @@ import socket import sys import os +import struct sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) sockpath = "/var/tmp/%s/sexiibot.sock" % os.environ["USER"] @@ -30,6 +31,30 @@ To get a list of possible commands, use command "help" args = sys.argv +def send_msg(connexion, msg): + # Prefix each message with a 4-byte length (network byte order) + msg = struct.pack('>I', len(msg)) + msg + connexion.sendall(msg) + +def recv_msg(connection): + # Read message length and unpack it into an integer + raw_msglen = recvall(connection, 4) + if not raw_msglen: + return b'' + msglen = struct.unpack('>I', raw_msglen)[0] + # Read the message data + return recvall(connection, msglen) + +def recvall(connection,n): + # Helper function to recv n bytes or return None if EOF is hit + data = b'' + while len(data) < n: + packet = connection.recv(n - len(data)) + if not packet: + return b'' + data += packet + return data + if len(args) < 2: print(usage, file=sys.stderr) sys.exit(1) @@ -47,7 +72,6 @@ else: message = " ".join(args[1:]) try: - print(message) sock.connect(sockpath) except socket.error: error = """\ @@ -64,6 +88,8 @@ If you need help to generate a config file, use the sexiiwizard script. print(error, file=sys.stderr) sys.exit(1) try: - sock.sendall(bytes(message, 'UTF-8')) + send_msg(sock, bytes(message, 'UTF-8')) + response = recv_msg(sock).decode('UTF-8') + print(response) finally: sock.close() diff --git a/sexiibot/channel.py b/sexiibot/channel.py index f4d2e8f..772fbb2 100644 --- a/sexiibot/channel.py +++ b/sexiibot/channel.py @@ -51,6 +51,8 @@ class Channel(object): return self.__name def message(self, msg): + while self.__in == None: + time.sleep(0.1) print("%s <-- %s" % (self.__name, msg)) self.__in.write("%s\n" % msg) diff --git a/sexiibot/core.py b/sexiibot/core.py index d497ec5..46aaf0a 100644 --- a/sexiibot/core.py +++ b/sexiibot/core.py @@ -18,11 +18,12 @@ import time import threading import shutil import socket +import struct class Sexiibot(object): """Core sexiibot class""" - def __init__(self, server, nick, new=True, port=None, ssl=False, channels=[], realname=None, iipath=None, sock="./sexiibot.sock"): + def __init__(self, server, nick, new=True, port=None, ssl=False, channels=[], realname=None, iipath=None, sock="/var/tmp/%s/sexiibot.sock" % os.environ["USER"]): if new: self.__server = server else: @@ -44,6 +45,9 @@ class Sexiibot(object): self.__treated = channels self.__quit = False self.__watch = None + sockdir = os.path.dirname(sock) + if not os.path.exists(sockdir): + os.makedirs(sockdir) self.__sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) try: os.unlink(sock) @@ -108,19 +112,37 @@ class Sexiibot(object): self.__nick = nick def newChan(self, args): - if len(args) == 1: + if len(args) > 0: + if args[0] in self.__channels: + return "warning: already joined %s" % args[0] chan = Channel(args[0],self) self.__channels[args[0]] = chan chan.join() + response = "" + if len(args) > 1: + response += "warning: \"" + ' '.join(args[1:]) + "\" garbage\n" + response += "Successfully joined %s" % args[0] + return response + else: + return "usage: join " def leaveChan(self, args): - if len(args) == 1: - self.__channels[args[0]].leave() - elif if len(args) == 2: - self.__channels[args[0]].leave(args[1]) + + if len(args) > 0: + if args[0] not in self.__channels: + return "warning: not in %s" % args[0] + response = "" + if len(args) == 1: + self.__channels[args[0]].leave() + else: + self.__channels[args[0]].leave(args[1]) + if not args[1:] == []: + response += "warning: \"%s\" garbage\n" % " ".join(args[1:]) + del self.__channels[args[0]] + response += "Successfully leaved %s" % args[0] + return response else: - return "warning: \"%s\" garbage" - del self.__channels[args[0]] + return "usage: leave [message]" def incomingChan(self, dirname): root = self.getIrcPath() @@ -129,7 +151,6 @@ class Sexiibot(object): chan = Channel(dirname, self, connected=True) chan.join() self.__channels[dirname] = chan - def watchChan(self): root = self.getIrcPath() @@ -143,34 +164,63 @@ class Sexiibot(object): self.__treated += [chan] time.sleep(0.1) + def send_msg(self, connection, msg): + # Prefix each message with a 4-byte length (network byte order) + msg = struct.pack('>I', len(msg)) + msg + connection.sendall(msg) + + def recv_msg(self, connection): + # Read message length and unpack it into an integer + raw_msglen = self.recvall(connection, 4) + if not raw_msglen: + return b'' + msglen = struct.unpack('>I', raw_msglen)[0] + # Read the message data + return self.recvall(connection, msglen) + + def recvall(self, connection,n): + # Helper function to recv n bytes or return None if EOF is hit + data = b'' + while len(data) < n: + packet = connection.recv(n - len(data)) + if not packet: + return b'' + data += packet + return data + def listenCommands(self): self.__sock.listen(1) while not self.__quit: connection, client = self.__sock.accept() try: - command = "" - while True: - data = connection.recv(16) - command += data.decode('UTF-8') - if not data: - self.parseCommand(command, connexion) - break + command = self.recv_msg(connection).decode('UTF-8') + print("*** command from control socket: %s" % command) + self.parseCommand(command, connection) finally: connection.close() - def parseCommand(self, command, connexion): + def parseCommand(self, command, connection): cmd = command.split(" ") - order = { - "join" : self.newChan, - "leave" : self.leaveChan, - "quit" : self.quit, - "say" : self.messageChan, - "action" : self.actionChan, - "nick" : self.setNick + orders = { + "join" : { "method": self.newChan, "desc": "join a new channel" }, + "leave" : { "method": self.leaveChan, "desc": "leave an existing channel" }, + "quit" : { "method": self.quit, "desc": "quit sexiibot instance" }, + "say" : { "method": self.messageChan, "desc": "say a message on a channel" }, + "action" : { "method": self.actionChan, "desc": "send an action message on a channel" }, + "nick" : { "method": self.setNick, "desc": "get or change nick" }, } - #connection.sendall(order[cmd[0]](cmd[1:], 'UTF-8')) + if cmd[0] == "help": + message = "Welcome to sexiibot control help. Here is the list of available commands:\n" + for item in orders: + message += " %s: %s\n" % (item, orders[item]["desc"]) + message += " help: displays this help\n\n" + message += "To have specific help for a command, just use it without any argument.\n" + message += "Sexiibot loves you." + self.send_msg(connection, bytes(message, 'UTF-8')) + else: + self.send_msg(connection, bytes(orders[cmd[0]]["method"](cmd[1:]), 'UTF-8')) - def quit(selfi, args=[]): + def quit(self, args=[]): for chan in self.__channels: self.leaveChan([chan, "sexiibot stopping"]) self.__quit = True