diff --git a/admin-scripts/join.py b/admin-scripts/join.py new file mode 100755 index 0000000..ab80177 --- /dev/null +++ b/admin-scripts/join.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +import socket + +sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +sockpath = "/root/sexiibot/sexiibot.sock" +try: + sock.connect(sockpath) +except socket.error: + sys.exit(1) + +try: + + # Send data + message = 'join #bordel' + sock.sendall(bytes(message, 'UTF-8')) + +finally: + sock.close() diff --git a/admin-scripts/leave.py b/admin-scripts/leave.py new file mode 100755 index 0000000..9bb24f4 --- /dev/null +++ b/admin-scripts/leave.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +import socket + +sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) +sockpath = "/root/sexiibot/sexiibot.sock" +try: + sock.connect(sockpath) +except socket.error: + sys.exit(1) + +try: + + # Send data + message = 'leave #bordel' + sock.sendall(bytes(message, 'UTF-8')) + +finally: + sock.close() diff --git a/launch.py b/launch.py index 7fb6aae..12bfc5a 100755 --- a/launch.py +++ b/launch.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 -import time from sexiibot.core import Sexiibot -sex = Sexiibot("irc.smoothirc.net", "sexiibot", ssl=True, channels=["#hashtagueule","#sexiibot"], iipath="/var/bot/ii-1.7/ii") +sex = Sexiibot("irc.smoothirc.net", "sexiibot", ssl=True, channels=["#sexiibot","#hashtagueule"], iipath="/var/bot/ii-1.7/ii") sex.start() diff --git a/sexiibot/channel.py b/sexiibot/channel.py index 3e895f7..f4d2e8f 100644 --- a/sexiibot/channel.py +++ b/sexiibot/channel.py @@ -1,8 +1,20 @@ #!/bin/env python +"""channel.py: Contains the channel class if sexiibot""" + +__author__ = "raspbeguy" +__copyright__ = "Copyright 2016, raspbeguy" +__credits__ = ["raspbeguy"] +__license__ = "WTFPL" +__version__ = "0.1.1" +__maintainer__ = "raspbeguy" +__email__ = "raspbeguy@hashtagueule.fr" +__status__ = "Devlopment" + import time import threading import os +import shutil #from core import Sexiibot class Channel(object): @@ -24,13 +36,11 @@ class Channel(object): os.makedirs(self.__bot.getIrcPath() + self.__name) open(self.__bot.getIrcPath() + "%s/out" % self.__name, 'a').close() self.__out = open(self.__bot.getIrcPath() + "%s/out" % self.__name, 'r') - print("----> first line of %s logfile is:" % self.__name) - print(self.__out.readline()) - self.__out.seek(0,2) + #self.__out.seek(0,2) self.__thread = threading.Thread(target=self.watch) self.__thread.start() while not self.__connect: - self.__bot.join(self.__name) + self.__bot.sendJoin(self.__name) time.sleep(1) #TODO: add something to wait the FIFO to be ready time.sleep(1) @@ -41,7 +51,7 @@ class Channel(object): return self.__name def message(self, msg): - print("message: %s" % msg) + print("%s <-- %s" % (self.__name, msg)) self.__in.write("%s\n" % msg) def action(self, action): @@ -50,25 +60,28 @@ class Channel(object): def leave(self, msg="sexiibot, the bot you're dreaming about"): self.message("/l %s" % msg) self.__alive = False + self.__connect = False self.__thread.join() self.__in.close() self.__out.close() + shutil.rmtree(self.__bot.getIrcPath() + self.__name) def watch(self): while self.__alive: line = self.__out.readline().rstrip() if line: - print(line) if not self.__connect: self.__connect = True else: - self.treat(line) #À ce stade du développement on ne traite rien + message = line.split(' ',3) + self.treat(message) time.sleep(0.1) - def treat(self, line): # bon là, clairement, c'est pas sa forme définitive, c'est qu'un POC - content = line.split(' ',3) - if content[3] and not content[2] is "<%s>" % self.__bot.getNick() and self.__bot.getNick() in content[3]: - self.message("%s, je suis flattée que l'on s'adresse à moi, malheureusement je suis con comme un balai." % content[2][1:-1]) + def treat(self, content): # bon là, clairement, c'est pas sa forme définitive, c'est qu'un POC + if not content[2][1:-1] == self.__bot.getNick(): + print("%s --> %s" % (self.__name, content)) + if content[3] and self.__bot.getNick() in content[3]: + self.message("%s, je suis flattée que l'on s'adresse à moi, malheureusement je suis sexiibot." % content[2][1:-1]) def __del__(self): self.__alive = False diff --git a/sexiibot/core.py b/sexiibot/core.py index 3988e61..2ee6643 100644 --- a/sexiibot/core.py +++ b/sexiibot/core.py @@ -1,23 +1,35 @@ #!/bin/env python +"""core.py: Contains the main class of sexiibot""" + +__author__ = "raspbeguy" +__copyright__ = "Copyright 2016, raspbeguy" +__credits__ = ["raspbeguy"] +__license__ = "WTFPL" +__version__ = "0.1.1" +__maintainer__ = "raspbeguy" +__email__ = "raspbeguy@hashtagueule.fr" +__status__ = "Devlopment" + +from sexiibot.channel import Channel import os import subprocess import time import threading import shutil -from sexiibot.channel import Channel +import socket class Sexiibot(object): """Core sexiibot class""" - def __init__(self, server, nick, new=True, port=None, ssl=False, channels=[], realname=None, iipath=None): + def __init__(self, server, nick, new=True, port=None, ssl=False, channels=[], realname=None, iipath=None, sock="./sexiibot.sock"): if new: self.__server = server else: self.__server = None self.__port = port self.__ssl = ssl - self.__channels = [] + self.__channels = {} self.__nick = nick if not realname is None: self.__realname = realname @@ -28,16 +40,23 @@ class Sexiibot(object): self.__iipath = iipath self.__iiproc = None for chan in channels: - self.__channels += [Channel(chan,self)] + self.__channels[chan] = Channel(chan,self) self.__treated = channels - for dirname in next(os.walk(self.getIrcPath()))[1]: - if not dirname in channels: - shutil.rmtree(self.getIrcPath() + dirname) self.__quit = False self.__watch = None - + self.__sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + try: + os.unlink(sock) + except OSError: + if os.path.exists(sock): + raise + self.__sock.bind(sock) def start(self): + if os.path.exists(self.getIrcPath()): + for dirname in next(os.walk(self.getIrcPath()))[1]: + print ("deleting " + dirname) + shutil.rmtree(self.getIrcPath() + dirname) if not self.__server is None: try: os.remove(self.getIrcPath()+"in") @@ -56,27 +75,27 @@ class Sexiibot(object): print(" ".join(cmd)) self.__iiproc = subprocess.Popen(cmd) # self.__iiproc.terminate() later to stop time.sleep(2) #temporaire - self.openServerIO() - self.joinAll() - - - def joinAll(self): - for chan in self.__channels: - chan.join() - - def openServerIO(self): self.__in = open(self.getIrcPath() + "in", 'w', 1) self.__out = open(self.getIrcPath() + "out", 'r') + chans_t0 = list(self.__channels.values()) + for chan in chans_t0: + chan.join() + self.listenCommands() def messageServer(self, message): self.__in.write(message + "\n") - print("Message: %s" % message) + print("Command to server: %s" % message) - def join(self, channel): + def sendJoin(self, channel): self.messageServer("/j %s" % channel) - def messageChannel(self, channel, message): - self.__channels[channel].message(message) + def messageChan(self, args): + if len(args) == 2: + self.__channels[args[0]].message(args[1]) + + def actionChan(self, args): + if len(args) == 3: + self.__channels[args[0]].action(args[1]) def getIrcPath(self): return "%s/irc/%s/" % (os.environ["HOME"], self.__server) @@ -84,21 +103,75 @@ class Sexiibot(object): def getNick(self): return self.__nick - def createChan(self, dirname): + def setNick(self, nick): + self.messageServer("/n %s" % nick) + self.__nick = nick + + def newChan(self, args): + if len(args) == 1: + chan = Channel(args[0],self) + self.__channels[args[0]] = chan + chan.join() + + def leaveChan(self, args): + if len(args) == 1: + self.__channels[args[0]].leave() + if len(args) == 2: + self.__channels[args[0]].leave(args[1]) + del self.__channel[args[0]] + + def incomingChan(self, dirname): root = self.getIrcPath() if os.path.isdir(root + dirname): if os.path.exists(root + dirname + "/in") and os.path.isfile(root + dirname + "/out"): chan = Channel(dirname, self, connected=True) chan.join() - self.__channels += [chan] - self.__treated += [dirname] + self.__channels[dirname] = chan + def watchChan(self): root = self.getIrcPath() while not self.__quit: chanlist = next(os.walk(self.getIrcPath()))[1] - diff = list(set(chanlist) - set(self.__treated)) - for chan in diff: - print("--> popped chan: " + chan) - self.createChan(chan) + usrlist = list(filter(lambda k: not k[0] is "#" and not k in self.__treated, chanlist)) + #diff = list(set(usrlist) - set(self.__treated)) + for chan in usrlist: + print("*** popped chan: " + chan) + self.incomingChan(chan) + self.__treated += [chan] time.sleep(0.1) + + 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) + break + finally: + connection.close() + + def parseCommand(self, command): + cmd = command.split(" ") + order = { + "join" : self.newChan, + "leave" : self.leaveChan, + "quit" : self.quit, + "say" : self.messageChan, + "action" : self.actionChan, + "nick" : self.setNick + } + order[cmd[0]](cmd[1:]) + + def quit(selfi, args=[]): + for chan in self.__channels: + self.leaveChan([chan, "sexiibot stopping"]) + self.__quit = True + self.__watch.join() + self.__in.close() + self.__out.close()