1
0
mirror of https://github.com/krislamo/Flea synced 2024-09-19 18:20:34 +00:00

Added logging functionality

Added logging of all sent/received data and errors.
Passwords are censored from the terminal and log
file. Fixed case-sensitivity of the Control nick
and channel.
This commit is contained in:
Kris Lamoureux 2016-02-29 05:05:46 -05:00
parent 80e6787d50
commit 037052d1c7
5 changed files with 118 additions and 36 deletions

23
Flea.py
View File

@ -15,10 +15,27 @@
# along with this program. If not, see <http://www.gnu.org/licenses/> # along with this program. If not, see <http://www.gnu.org/licenses/>
import traceback import traceback
import sys
try: try:
import core.main import core.main
except:
traceback.print_exc() except KeyboardInterrupt:
input() print "\nGoodbye!"
sys.exit()
except SystemExit:
raise
except:
# Print error, save it to error.txt
# then wait to be closed.
traceback.print_exc()
errorfile = open("error.txt", 'a')
traceback.print_exc(None, errorfile)
errorfile.close()
raw_input()
sys.exit(0)

View File

@ -16,10 +16,12 @@
# Built-in to Python 2.7 # Built-in to Python 2.7
import socket import socket
import re
class irc: class irc:
debug = False
debug = False
log = False
config = {} config = {}
pack = {} pack = {}
sock = socket.socket() sock = socket.socket()
@ -79,10 +81,22 @@ class irc:
return packet return packet
# Basic message function to send any data # Basic message function to send and log any data
def msg(self, message): def msg(self, message):
self.sock.send(message+"\r\n") self.sock.send(message+"\r\n")
if self.debug: print ">>> "+message
# Match messages containing private information
# then censors it to output to the terminal and log
pattern = r"^PRIVMSG NickServ :IDENTIFY *"
if re.search(pattern, message):
message = "PRIVMSG NickServ :IDENTIFY ****"
output = ">>> "+message
if self.debug:
print output
if self.log:
self.log.write(output+"\n")
def User(self, nick, mode, unused, owner): def User(self, nick, mode, unused, owner):
self.msg("USER "+nick+' '+mode+' '+unused+" :"+owner) self.msg("USER "+nick+' '+mode+' '+unused+" :"+owner)

View File

@ -58,7 +58,14 @@ class ImportRollback:
__builtin__.__import__ = self.newImport __builtin__.__import__ = self.newImport
def PluginsImport(): # Print and log to logfile
def prntlog(message, logfile):
print message
if logfile:
logfile.write(message+"\n")
def PluginsImport(log=False):
# Get root of Flea # Get root of Flea
current = os.getcwd() current = os.getcwd()
# Path to /plugins/ under /Flea/ # Path to /plugins/ under /Flea/
@ -76,7 +83,7 @@ def PluginsImport():
# Only import directory plugins (no single files) # Only import directory plugins (no single files)
if os.path.isdir(plugins+item): if os.path.isdir(plugins+item):
print "[Plugins] Initializing "+item prntlog("[Plugins] Initializing "+item, log)
plugin = __import__(item+".main") plugin = __import__(item+".main")
plugin_list.append(plugin) plugin_list.append(plugin)
@ -87,7 +94,6 @@ def PluginsImport():
return plugin_list return plugin_list
def main(): def main():
# Create irclib irc object # Create irclib irc object
@ -96,14 +102,22 @@ def main():
# Parse main settings.conf file # Parse main settings.conf file
irc.config = cfgParser("settings.conf") irc.config = cfgParser("settings.conf")
# If logging is enabled, open log file.
if irc.config["logging"]:
log = open("log.txt", 'a')
irc.log = log
else:
log = False
# Keep track of modules for a rollback # Keep track of modules for a rollback
importctrl = ImportRollback() importctrl = ImportRollback()
# Import /plugins/ # Import /plugins/
if irc.config["plugins"]: if irc.config["plugins"]:
plugins = PluginsImport() plugins = PluginsImport(log)
if not plugins: if not plugins:
print "[Plugins] Failed to load." prntlog("[Plugins] Failed to load.", log)
# Set debug to true/false inside irc() object # Set debug to true/false inside irc() object
irc.debug = irc.config["debug"] irc.debug = irc.config["debug"]
@ -115,15 +129,18 @@ def main():
irc.sock = ssl.wrap_socket(irc.sock) irc.sock = ssl.wrap_socket(irc.sock)
# Connect to IRC server # Connect to IRC server
irc.sock.connect((irc.config["host"], irc.config["port"])) host = irc.config["host"]
print "Connecting to "+irc.config["host"]+':'+str(irc.config["port"]) port = irc.config["port"]
irc.sock.connect((host, port))
prntlog("Connecting to "+host+':'+str(port), log)
# Display SSL information to the user # Display SSL information to the user
ssl_info = irc.sock.cipher() ssl_info = irc.sock.cipher()
if ssl_info != None: if ssl_info != None:
print "[SSL] Cipher: "+ssl_info[0] prntlog("[SSL] Cipher: "+ssl_info[0], log)
print "[SSL] Version: "+ssl_info[1] prntlog("[SSL] Version: "+ssl_info[1], log)
print "[SSL] Bits: "+str(ssl_info[2]) prntlog("[SSL] Bits: "+str(ssl_info[2]), log)
# Send User/Nick message to establish user on the server # Send User/Nick message to establish user on the server
irc.User(irc.config["ident"], irc.config["mode"], irc.User(irc.config["ident"], irc.config["mode"],
@ -145,8 +162,9 @@ def main():
# If no incoming data exists then connection has closed # If no incoming data exists then connection has closed
if len(tmpdata) == 0: if len(tmpdata) == 0:
input("Connection closed.") print "Connection closed."
sys.exit() raw_input()
sys.exit(0)
# Split data to easily deal with it # Split data to easily deal with it
data = tmpdata.split("\r\n") data = tmpdata.split("\r\n")
@ -157,14 +175,17 @@ def main():
# Ignore empty lines # Ignore empty lines
if len(line) > 0: if len(line) > 0:
# Print line, parse it and respond # Print/log line, parse it and respond
print line prntlog(line, log)
irc.pack = irc.Parser(line) irc.pack = irc.Parser(line)
# Run all plugins main() function # Run all plugins main() function
wait = ''
if irc.config["plugins"]: if irc.config["plugins"]:
for plugin in plugins: for plugin in plugins:
plugin.main.main(irc) wait = plugin.main.main(irc)
if wait == "QUIT":
break
# Ping Pong, keep the connection alive. # Ping Pong, keep the connection alive.
if irc.pack["cmd"] == "PING": if irc.pack["cmd"] == "PING":
@ -183,5 +204,18 @@ def main():
irc.Identify(irc.config["password"]) irc.Identify(irc.config["password"])
irc.Join(irc.config["channel"]) irc.Join(irc.config["channel"])
if log: log.flush()
# Wait for QUIT to be returned from any plugin's main() function
if wait == "QUIT":
# Quit, close connection and logfile.
irc.Quit("Fleabot https://github.com/Kris619/Flea")
irc.sock.close()
if log: log.close()
print "Press the [ENTER] key to close."
raw_input()
sys.exit(0)
main() main()

View File

@ -1,3 +1,19 @@
# 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 <http://www.gnu.org/licenses/>
import re import re
# Init # Init
@ -11,7 +27,7 @@ def chkcontrol(irc):
global access global access
global queue global queue
nick = irc.pack["nick"] nick = irc.pack["nick"].lower()
for person in access: for person in access:
if nick == person: if nick == person:
@ -33,13 +49,14 @@ def main(irc):
# Set control channel # Set control channel
controlchan = irc.config["channel"] controlchan = irc.config["channel"]
controlusr = irc.config["control"]
# NOTICEs are used to "control" Flea # NOTICEs are used to "control" Flea
if irc.pack["cmd"] == "NOTICE": if irc.pack["cmd"] == "NOTICE":
# Nick must match the nick in settings # Nick must match the nick in settings
# e.g. control = Kris # e.g. control = Kris
if irc.pack["nick"] == irc.config["control"]: if irc.pack["nick"].lower() == controlusr.lower():
# Split message by spaces, for functions with # Split message by spaces, for functions with
# required parameters. e.g. "<cmd> <param1> <param2>" # required parameters. e.g. "<cmd> <param1> <param2>"
@ -67,13 +84,10 @@ def main(irc):
if chkcontrol(irc): if chkcontrol(irc):
irc.Notice("You already have access to Control.", irc.Notice("You already have access to Control.",
irc.pack["nick"]) irc.pack["nick"])
else:
noaccess(irc)
if irc.pack["text"] == "quit": if irc.pack["text"] == "quit":
if chkcontrol(irc): if chkcontrol(irc):
irc.Quit("Fleabot https://github.com/Kris619/Flea") return "QUIT"
quit()
else: else:
noaccess(irc) noaccess(irc)
@ -81,32 +95,34 @@ def main(irc):
elif irc.pack["cmd"] == "307": elif irc.pack["cmd"] == "307":
if irc.pack["text"] == "is identified for this nick": if irc.pack["text"] == "is identified for this nick":
usernick = irc.pack["params"][1]
# Check if Nick is in the queue for access list # Check if Nick is in the queue for access list
if queue.count(irc.pack["params"][1]) == 1: if queue.count(usernick) == 1:
# Remove Nick from queue # Remove Nick from queue
queue.remove(irc.pack["params"][1]) queue.remove(usernick)
# Check if user is set to control in settings # Check if user is set to control in settings
# e.g. control = Kris # e.g. control = Kris
if irc.pack["params"][1] == irc.config["control"]: if usernick.lower() == controlusr.lower():
# Is control user inside the control channel? # Is control user inside the control channel?
if chans[controlchan].count(irc.pack["params"][1]) == 1: if chans[controlchan.lower()].count(usernick) == 1:
# Grant access # Grant access
access.append(irc.pack["params"][1]) access.append(usernick)
print irc.pack["params"][1]+" added to Access" print usernick+" added to Access"
irc.Notice( irc.Notice(
"You have been given access to Control.", "You have been given access to Control.",
irc.pack["params"][1]) usernick)
else: else:
irc.Notice( irc.Notice(
"You are not in the Control channel: "+controlchan, "You are not in the Control channel: "+controlchan,
irc.pack["params"][1]) usernick)
# Keep track of users in every channel # Keep track of users in every channel
# "353" lists users to a channel # "353" lists users to a channel
@ -137,7 +153,7 @@ def main(irc):
if irc.pack["nick"] == irc.config["nick"]: if irc.pack["nick"] == irc.config["nick"]:
# Create channel user list if it doesn't exist # Create channel user list if it doesn't exist
if chans.keys().count(irc.pack["text"]) == 0: if chans.keys().count(irc.pack["text"]) == 0:
chans[irc.pack["text"]] = [] chans[irc.pack["text"].lower()] = [irc.pack["text"]]
# Another user joined # Another user joined
else: else:

View File

@ -1,4 +1,5 @@
debug = true debug = true
logging = false
plugins = true plugins = true
host = irc.example.net host = irc.example.net