diff --git a/README.md b/README.md index 819f6ed..c28c838 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,9 @@ continuing. Flea was written in [Python 2.7](http://www.python.org/download/releases/2.7/) ## Quick Start -1. Run the terminal/console in the root of the project and type: +1. Edit the *settings.conf* file to appropriate settings on the server you would +like to use + +2. Run the terminal/console in the root of the project and type: *python Flea.py* diff --git a/core/irclib.py b/core/irclib.py new file mode 100644 index 0000000..40cfcc5 --- /dev/null +++ b/core/irclib.py @@ -0,0 +1,121 @@ +# An IRC bot named Flea +# Copyright (C) 2016 Kris Lamoureux + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see + +import socket + +class irc: + debug = False + sock = socket.socket() + + # IRC Parser. Parses by line + def Parser(self, line): + packet = {"nick":None, "ident":None, + "host":None, "cmd":None, + "params":[], "text":None} + + if len(line) > 0: + if(line[0] == ':'): + part, line = line.split(' ', 1) + + ATL = part.find('@') + EXL = part.find('!') + + # Nick + if EXL > -1: + packet["nick"] = part[1:EXL] + elif ATL > -1: + packet["nick"] = part[1:ATL+1] + else: + packet["nick"] = part[1:] + + # Ident + if ATL > -1 and EXL > -1: + packet["ident"] = part[EXL+1:ATL] + # Host + if ATL > -1: + packet["host"] = part[ATL+1:] + + part, line = line.split(' ', 1) + + # Command & Params + params = [] + packet["cmd"] = part + + while True: + if line.find(' ') > -1: + part, line = line.split(' ', 1) + + if part[0] != ':': + packet["params"].append(part) + else: + packet["text"] = part[1:]+" "+line + break + elif len(line) > 1: + if line[0] == ':': + packet["text"] = line[1:] + else: + packet["params"].append(line) + break + else: + break + + return packet + + + # Basic message function to send any data + def msg(self, message): + self.sock.send(message+"\r\n") + if self.debug: print ">>> "+message + + def User(self, nick, mode, unused, owner): + self.msg("USER "+nick+' '+mode+' '+unused+" :"+owner) + + def Nick(self, nick): + self.msg("NICK "+nick) + + def Pong(self, txt): + self.msg("PONG :"+txt) + + def Mode(self, nick, mode): + self.msg("MODE "+ nick + " "+mode) + + def Identify(self, password): + self.msg("NickServ IDENTIFY "+password) + + def Join(self, channel): + self.msg("JOIN "+channel) + + def Quit(self, quitmsg): + self.msg("QUIT :"+quitmsg) + + def Notice(self, message, user): + self.msg("NOTICE "+user+" :"+message) + + def PrivMsg(self, user, message): + self.msg("PRIVMSG "+user+" :"+message) + + def Part(self, channel, message): + self.msg("PART "+channel+" "+message) + + def ReturnVersion(self, version, user): + self.msg("NOTICE "+user+" :\001VERSION "+version+"\001") + + def Whois(self, query): + self.msg("WHOIS "+query+"\r\n") + + def SetMode(self, channel, nick, mode): + self.msg("MODE "+channel+" "+mode+" "+nick) + diff --git a/core/main.py b/core/main.py index 95b55f5..ff87818 100644 --- a/core/main.py +++ b/core/main.py @@ -15,37 +15,51 @@ # along with this program. If not, see from core.config import * +import core.irclib as irclib + +# Built-in to Python 2.7 import socket import ssl def main(): config = cfgParser("settings.conf") + # Create irclib irc object + irc = irclib.irc() + + # Set debug to true/false inside irc() object + irc.debug = config["debug"] + # Create socket object - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(10) + irc.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # Wrap socket object to create SSLSocket object - sock = ssl.wrap_socket(sock) + irc.sock = ssl.wrap_socket(irc.sock) # Connect to IRC server - sock.connect((config["host"], config["port"])) + irc.sock.connect((config["host"], config["port"])) print "Connecting to "+config["host"]+':'+str(config["port"]) # Display SSL information to the user - ssl_info = sock.cipher() + ssl_info = irc.sock.cipher() if ssl_info != None: print "[SSL] Cipher: "+ssl_info[0] print "[SSL] Version: "+ssl_info[1] print "[SSL] Bits: "+str(ssl_info[2]) + # Send User/Nick message to establish user on the server + irc.User(config["ident"], config["mode"], + config["unused"], config["realname"]) + + irc.Nick(config["nick"]) + while True: # Buffer to store data from server data = '' while True: # Receive data from connection - tmpdata = sock.recv(4096) + tmpdata = irc.sock.recv(4096) data = data + tmpdata if len(tmpdata) < 4096: @@ -58,9 +72,31 @@ def main(): # Split data to easily deal with it data = tmpdata.split("\r\n") + + # Parse IRC line by line for line in data: + + # Ignore empty lines if len(line) > 0: + + # Print line, parse it and respond print line + pack = irc.Parser(line) + + # Ping Pong, keep the connection alive. + if pack["cmd"] == "PING": + irc.Pong(pack["text"]) + + # Send user mode message after command 001 + elif pack["cmd"] == "001": + irc.Mode(config["nick"], config["mode"]) + + # Send password after End of MOTD + elif pack["cmd"] == "376": + irc.Identify(config["password"]) + # Temp test join + irc.Join("#Flea") + main() diff --git a/settings.conf b/settings.conf index b387be7..a6965c7 100644 --- a/settings.conf +++ b/settings.conf @@ -1,7 +1,7 @@ debug = true host = irc.example.net -port = 6667 +port = 7001 nick = Flea password = your_password