BOT V2:
- What has changed?
Given the great number of functions and work-arounds existent in the last code, I decided to make a version 2. Now, we use classes (sweet :)!), providing a much cleaner, understandable and sane code. Thus far, this version is (function-wise) simpler than the other, having only a basic commands suit (act and say), plus a group permissions class. But, but, it's easier to understand and improve! At least I hope so. Let's get to the code:
- The code:
# -*- coding: utf-8 -*-
import socket, dbm, random, sys, time
########################### Editing below this is necessary:
HOST = "irc.freenode.net"
PORT = 6667
NICK = "FailBot"
USERNAME = "FailBot"
REALNAME = "FailBot"
CHANNELS = ["##devil"]
bot_prefix = "!"
import_plugins = "BasicCommands(), UserLevel(), Admin()" #must be classes
############################ Editing beyond here is not necessary.
storage = dbm.open("botv2", "c")
if "password" not in storage.keys():
set_passwd = raw_input("Set an ident password, put 0 if none: ")
storage["password"] = set_passwd
set_admin = raw_input("Set a nick to be the admin. DO NOT leave blank: ")
storage["users_Owners"] = set_admin
class IrcMessage:
'''Parses the IRC message, defining msg.prefix, msg.command, and msg.args'''
def __init__(self, msg):
self.prefix, self.command, self.args = self.parsemsg(msg)
def parsemsg(self, s):
trailing = 0
prefix = 0
if s[0] == ":":
s = s[1:].split(' ', 1)
prefix = s[0]
s = s[1]
if " :" in s:
s = s.split(" :", 1)
trailing = s[1]
s = s[0]
args = s.split()
command = args.pop(0)
if trailing != 0:
args.append(trailing)
return prefix, command, args
class Privmsg:
'''Parses a PRIVMSG on IRC, defining msg.nick, msg.channel, msg.message, msg.bot_command, and msg.bot_command_args. Also contains methods: reply (send message into channel), reply_act(send a /me into channel).'''
def __init__(self, msg):
try:
self.nick = msg.prefix.split("!", 1)[0]
self.channel = msg.args[0]
self.message = msg.args[1]
self.bot_command = self.message.split()[0]
if not self.bot_command == self.message.split():
self.bot_command_args = self.message.split()[1:]
self.true = 1
except:
self.true = 0
def reply(self, msg):
socket.send("PRIVMSG %s :%s\r\n" % (self.channel, msg))
def reply_act(self, msg):
socket.send("PRIVMSG %s :\x01ACTION %s\x01\r\n" % (self.channel, msg))
class BasicCommands:
'''A basic suit of commands. Include: <bot prefix>say (to say stuff in the channel) and <bot prefix>act (for /me). '''
def say(self, privmsg):
if has_permission("users_BasicCommands", privmsg.nick) :
privmsg.reply(" ".join(privmsg.bot_command_args))
else :
privmsg.reply("Permission denied.")
def act(self, privmsg):
if has_permission("users_BasicCommands", privmsg.nick) :
privmsg.reply_act(" ".join(privmsg.bot_command_args))
else :
privmsg.reply("Permission denied.")
class UserLevel:
'''An user level plugin. '''
groups = [x for x in storage.keys() if x.startswith("users_")]
def set_group(self, privmsg):
groups_edited = []
for grp in privmsg.bot_command_args[2:] :
if privmsg.bot_command_args[1] == '+' and has_permission("users_Owners", privmsg.nick) :
if storage.get(grp, "") :
usr_list = storage[grp].split()
usr_list.append(privmsg.bot_command_args[0])
storage[grp] = " ".join(usr_list)
groups_edited.append(grp)
else :
storage[grp] = privmsg.bot_command_args[0]
groups_edited.append(grp)
self.groups.append(grp)
elif privmsg.bot_command_args[1] == '-' and has_permission("users_Owners", privmsg.nick) and storage.get(grp, "") :
usr_list = storage[grp].split()
if privmsg.bot_command_args[0] in usr_list :
usr_list.remove(privmsg.bot_command_args[0])
storage[grp] = " ".join(usr_list)
groups_edited.append(grp)
if privmsg.bot_command_args[1] == '+':
privmsg.reply("Added user %s to groups: %s" % (privmsg.bot_command_args[0], ", ".join(groups_edited)))
elif privmsg.bot_command_args[1] == '-':
privmsg.reply("Removed user %s from groups: %s" % (privmsg.bot_command_args[0], ", ".join(groups_edited)))
def read_group(self, privmsg):
if privmsg.bot_command_args[0] == '*' :
privmsg.reply("Groups: %s" % ", ".join(self.groups))
else :
if privmsg.bot_command_args[0] in self.groups :
privmsg.reply("People in the group %s: %s" % (privmsg.bot_command_args[0], ", ".join(storage[privmsg.bot_command_args[0]].split())))
else :
privmsg.reply("Group %s not found" % privmsg.bot_command_args[0])
def del_group(self, privmsg):
grps_removed = []
grps_notfound = []
if has_permission("users_Owners", privmsg.nick) :
for grp in privmsg.bot_command_args :
if grp in self.groups :
self.groups.remove(grp)
del storage[grp]
grps_removed.append(grp)
else :
grps_notfound.append(grp)
privmsg.reply("Removed groups: %s. Could not find groups: %s." % (", ".join(grps_removed), ", ".join(grps_notfound)))
else :
privmsg.reply("Permission denied.")
class Admin:
def quit(self, privmsg):
if has_permission("users_Owners", privmsg.nick):
privmsg.reply("Quitting...")
socket.close()
sys.exit()
else:
privmsg.reply("Permission denied.")
def sendraw(self, privmsg):
if has_permission("users_Owners", privmsg.nick):
socket.send(" ".join(privmsg.bot_command_args) + '\n')
else:
privmsg.reply("Permission denied.")
def mode(self, privmsg):
if has_permission("users_Owners", privmsg.nick):
socket.send("MODE %s " % privmsg.channel + " ".join(privmsg.bot_command_args) + '\n')
else:
privmsg.reply("Permission denied.")
def topic(self, privmsg):
if has_permission("users_Owners", privmsg.nick):
socket.send("TOPIC %s :" % privmsg.channel + " ".join(privmsg.bot_command_args) + '\n')
else:
privmsg.reply("Permission denied.")
def kick(self, privmsg):
if has_permission("users_Owners", privmsg.nick):
socket.send("KICK %s %s :%s\n" % (privmsg.channel, privmsg.bot_command_args[0], " ".join(privmsg.bot_command_args[1:])))
else:
privmsg.reply("Permission denied.")
def has_permission(group, user):
if "UserLevel()" in import_plugins.split(", ") :
try :
if user in storage["users_Owners"].split() :
return True
elif user in storage[group].split() :
return True
else :
return False
except :
return False
else :
return True
exec("plugins = %s" % import_plugins)
#INITIAL HANDSHAKE
socket = socket.socket()
socket.connect((HOST, PORT))
if not storage["password"] == "0":
socket.send("PASS :%s\r\n" % (storage["password"]))
time.sleep(3)
socket.send("NICK %s\r\n" % (NICK))
socket.send("USER %s * * :%s\r\n" % (USERNAME, REALNAME))
for channel in CHANNELS:
socket.send("JOIN %s\r\n" % (channel))
#END OF HANDSHAKE
recv = ""
while True:
recv = recv + socket.recv(4096)
s = recv.split("\r\n")
recv = s.pop()
for msg in s:
print msg
msg = IrcMessage(msg)
if msg.command == "PRIVMSG":
privmsg = Privmsg(msg)
for plugin in plugins:
if privmsg.true == 1:
if hasattr(plugin, privmsg.bot_command[1:]) and privmsg.message.startswith(bot_prefix) :
command = getattr(plugin, privmsg.bot_command[1:])
try :
command(privmsg)
except SystemExit :
raise
except :
privmsg.reply("Error calling function.")
elif msg.command == "PING":
socket.send("PONG\r\n")
elif msg.command == "KICK" and NICK in msg.args:
socket.send("JOIN %s\n" % msg.args[0])
- How to run:
Running it is quite simple, obvious and straightforward. There are no mysteries like in the last version, really. Just edit whatever you need and enter information accordingly.
- How to edit:
Basically, what you need to do do is create a class. And the command to call a method via irc is simply !name, so, if we have:
class Test:
def test(self, privmsg):
privmsg.reply("Success!")
Typing !test on the channel will call Test.test. What is important to notice is the methods will be called with privmsg as an argument, and privmsg is an instance of the class Privmsg (what a surprise). Important things to know:privmsg.nick = nick of whoever typed the message which triggered the method
privmsg.bot_command = the actual command. ex, in !kill pedro3005, !kill is the bot_command.
privmsg.bot_command_args = A LIST of the arguments after bot_command split by spaces.
privmsg.channel = the channel the message was sent on (although you usually won't have to worry about this)
privmsg.message = the actual message. I.E., in
:pedro3005~pedro@unaffiliated/pedro3005 PRIVMSG #channel :athe actual message will be "a".
privmsg.reply = this sends a message into the channel that triggered the method. I.E., privmsg.reply("I am here")
privmsg.reply_act = this is the same as above, only it is an action.
So, simply write a class and add it to the import_plugins list on the configuration area. REMEMBER that the method will always be called with privmsg as an argument, so never try to take more than one argument!
- On the group permission system:
The way this works is we have various groups, and these groups have access to all methods inside a class. So for instance, the group users_BasicCommands will have access to all the BasicCommand class methods. Whenever naming a group for this, ALWAYS precede it with users_. That is important! So, to check if a certain user has permission to access a certain class, I wrote the function has_permission(group, user). What it does is firstly check if the group permission system is enabled. If not, it will return TRUE. Then, it checks if the user is either in the owners group, users_Owners, or in the group the function was called with. If yes, it returns TRUE. If not, it will return FALSE.
So, pragmatically, what you need to know about it:
!set_group <user> <+/-> users_Group1 users_Group2
!read_group <group/*> (* will list all groups, and if you specify a group it will list everyone on it)
!del_group users_Group1
Users on the users_Owners group have access to ALL commands. I wish to improve the code to this class (it looks rather ugly), so any tips are welcomed.
EDIT: Some bug fixes, added Admin class (some sweet new functions).
Edited by pedro3005, 06 April 2010 - 08:25 PM.
bugs fixed


Sign In
Create Account


Back to top










