Compare commits
No commits in common. "d06b8f2fdc0fb86e7c9c45bce3d6fce26eb6348f" and "af08fe0f16ed5db69cf492271e9229d333fd6ab4" have entirely different histories.
d06b8f2fdc
...
af08fe0f16
151
bot.py
151
bot.py
|
@ -62,6 +62,9 @@ class Fulvia(irc.IRCClient):
|
|||
in them.
|
||||
"""
|
||||
|
||||
self.users = tools.FulviaMemory()
|
||||
"""A dictionary of all users the bot is aware of."""
|
||||
|
||||
self.memory = tools.FulviaMemory()
|
||||
"""
|
||||
A thread-safe general purpose dictionary to be used by whatever
|
||||
|
@ -73,6 +76,12 @@ class Fulvia(irc.IRCClient):
|
|||
A class with some basic interactions for the bot's sqlite3 databse.
|
||||
"""
|
||||
|
||||
self._callables = {}
|
||||
"""
|
||||
A dictionary containing all callable functions loaded from
|
||||
modules. Keys are the functions name.
|
||||
"""
|
||||
|
||||
self._hooks = []
|
||||
"""
|
||||
A list containing all function names to be hooked with every message
|
||||
|
@ -111,6 +120,7 @@ class Fulvia(irc.IRCClient):
|
|||
Find and load all of our modules.
|
||||
"""
|
||||
print(f"Loading modules...")
|
||||
self._callables = {}
|
||||
self._hooks = []
|
||||
self.commands = {}
|
||||
self._times = {}
|
||||
|
@ -142,11 +152,20 @@ class Fulvia(irc.IRCClient):
|
|||
convenient table.
|
||||
"""
|
||||
if hasattr(func, 'commands'):
|
||||
self._callables[func.__name__] = func
|
||||
for cmd in func.commands:
|
||||
self.commands[cmd] = func
|
||||
self.commands[cmd] = tools.Command(cmd)
|
||||
self.commands[cmd]._func_name = func.__name__
|
||||
self.commands[cmd].priv = func.priv
|
||||
self.commands[cmd].doc = func._docs
|
||||
if cmd in func.aliases:
|
||||
self.commands[cmd].canonical = False
|
||||
aliases = [a for a in func.commands if a != cmd]
|
||||
self.commands[cmd].aliases = aliases
|
||||
|
||||
if func.hook:
|
||||
self._hooks.append(func)
|
||||
self._callables[func.__name__] = func
|
||||
self._hooks.append(func.__name__)
|
||||
|
||||
if func.rate or func.channel_rate or func.global_rate:
|
||||
self._times[func.__name__] = {}
|
||||
|
@ -168,10 +187,12 @@ class Fulvia(irc.IRCClient):
|
|||
return
|
||||
|
||||
if hasattr(func, 'commands'):
|
||||
self._callables.pop(func.__name__)
|
||||
for command in func.commands:
|
||||
self.commands.pop(command)
|
||||
|
||||
if func.hook:
|
||||
self._callables.pop(func.__name__)
|
||||
self._hooks.remove(func.__name__)
|
||||
|
||||
if func.rate or func.channel_rate or func.global_rate:
|
||||
|
@ -240,25 +261,26 @@ class Fulvia(irc.IRCClient):
|
|||
"""
|
||||
nick = user.partition("!")[0].partition("@")[0]
|
||||
if channel.startswith("#"):
|
||||
opSym = self.channels[channel].users[nick].op_level
|
||||
opSym = tools.getOpSym(self.channels[channel].privileges[nick])
|
||||
else:
|
||||
opSym = ''
|
||||
opSym = ""
|
||||
channel = nick
|
||||
line = f"<{opSym}{nick}> {message}"
|
||||
line = "<" + opSym + nick + ">" + " " + message
|
||||
self.log(channel, line)
|
||||
|
||||
funcs = []
|
||||
func_names = []
|
||||
if message.startswith(self.prefix) and message != self.prefix:
|
||||
command = message.partition(" ")[0]
|
||||
command, _, _ = message.partition(" ")
|
||||
command = command.replace(self.prefix, "", 1)
|
||||
cmd = self.commands.get(command)
|
||||
if not cmd:
|
||||
return
|
||||
funcs.append(cmd)
|
||||
func_names.append(cmd._func_name)
|
||||
|
||||
funcs += self._hooks
|
||||
func_names += self._hooks
|
||||
|
||||
for func in funcs:
|
||||
for func_name in func_names:
|
||||
func = self._callables[func_name]
|
||||
trigger = Trigger(user, channel, message, "PRIVMSG", self.config)
|
||||
bot = FulviaWrapper(self, trigger)
|
||||
|
||||
|
@ -289,20 +311,19 @@ class Fulvia(irc.IRCClient):
|
|||
|
||||
def joined(self, channel):
|
||||
"""Called when the bot joins a new channel."""
|
||||
line = f"-!- {self.nickname} [{self.username}@{self.host}] "
|
||||
line += f"has joined {channel}"
|
||||
line = "-!- " + self.nickname + " " + "[" + self.username + "@"
|
||||
line += self.host + "] has joined " + channel
|
||||
self.log(channel, line)
|
||||
|
||||
print(f"Joined {channel}")
|
||||
self.channels[channel] = tools.Channel(channel)
|
||||
user = tools.User(self.nickname)
|
||||
self.channels[channel].users[self.nickname] = user
|
||||
if channel not in self.channels:
|
||||
self.channels[channel] = tools.Channel(channel)
|
||||
|
||||
|
||||
def left(self, channel, reason=""):
|
||||
"""Called when the bot leaves a channel."""
|
||||
line = f"-!- {self.nickname} [{self.username}@{self.host}] "
|
||||
line += f"has left {channel} [{reason}]"
|
||||
line = "-!- " + self.nickname + " " + "[" + self.username + "@"
|
||||
line += self.host + "] has left " + channel + " [" + reason + "]"
|
||||
self.log(channel, line)
|
||||
|
||||
print(f"Parted {channel}")
|
||||
|
@ -317,7 +338,7 @@ class Fulvia(irc.IRCClient):
|
|||
|
||||
def modeChanged(self, user, channel, add_mode, modes, args):
|
||||
"""Called when users or channel's modes are changed."""
|
||||
line = f"-!- mode/{channel} ["
|
||||
line = "-!- mode/" + channel + " ["
|
||||
if add_mode:
|
||||
line += "+"
|
||||
else:
|
||||
|
@ -340,11 +361,11 @@ class Fulvia(irc.IRCClient):
|
|||
|
||||
elif mode in tools.op_level.keys(): # user mode, op_level mode
|
||||
nick = args[n]
|
||||
user = self.channels[channel].users[nick]
|
||||
op_level = tools.op_level[mode]
|
||||
if add_mode:
|
||||
user.op_level += mode
|
||||
self.channels[channel].privileges[nick] += op_level
|
||||
else:
|
||||
user.op_level.replace(mode, '', 1)
|
||||
self.channels[channel].privileges[nick] -= op_level
|
||||
|
||||
else: # user mode, non-op_level mode
|
||||
continue
|
||||
|
@ -357,8 +378,8 @@ class Fulvia(irc.IRCClient):
|
|||
print(f"Signed on as {self.nickname}")
|
||||
self.whois(self.nickname)
|
||||
|
||||
line = f"*** Signed onto {self.hostname} as "
|
||||
line += f"{self.nickname}!{self.username}@{self.host}"
|
||||
line = "*** Signed onto " + self.hostname + " as "
|
||||
line += self.nickname + "!" + self.username + "@" + self.host
|
||||
self.log(self.hostname, line)
|
||||
|
||||
for channel in self.config.core.channels.split(","):
|
||||
|
@ -367,8 +388,8 @@ class Fulvia(irc.IRCClient):
|
|||
|
||||
def kickedFrom(self, channel, kicker, message):
|
||||
"""Called when the bot is kicked from a channel."""
|
||||
line = f"-!- {self.nickname} was kicked from {channel} "
|
||||
line += f"by {kicker} [{message}]"
|
||||
line = "-!- " + self.nickname + " was kicked from " + channel
|
||||
line += " by " + kicker + " [" + message + "]"
|
||||
self.log(channel, line)
|
||||
|
||||
self.channels.pop(channel)
|
||||
|
@ -376,14 +397,16 @@ class Fulvia(irc.IRCClient):
|
|||
|
||||
def nickChanged(self, nick):
|
||||
"""Called when the bot changes it's nickname."""
|
||||
line = f"-!- you are now known as {nick}"
|
||||
line = "-!- you are now known as " + nick
|
||||
|
||||
for channel_name, channel in self.channels.items():
|
||||
user = self.users.pop(self.nickname)
|
||||
self.users[nick] = user
|
||||
for key, channel in self.channels.items():
|
||||
self.log(key, line)
|
||||
|
||||
user = channel.users.pop(self.nickname)
|
||||
user.nick = nick
|
||||
channel.users[nick] = user
|
||||
channel.rename_user(self.nickname, nick)
|
||||
user.nick = nick
|
||||
self.nickname = nick
|
||||
|
||||
|
||||
## Actions the bot observes other users doing in the channel.
|
||||
|
@ -393,11 +416,12 @@ class Fulvia(irc.IRCClient):
|
|||
"""Called when the bot sees another user join a channel."""
|
||||
nick, _, host = user.partition("!")
|
||||
|
||||
line = f"-!- {nick} [{host}] has joined {channel}"
|
||||
line = "-!- " + nick + " " + "[" + host + "] has joined " + channel
|
||||
self.log(channel, line)
|
||||
|
||||
user = tools.User(nick)
|
||||
self.channels[channel].users[nick] = user
|
||||
if nick not in self.users:
|
||||
self.users[nick] = tools.User(nick)
|
||||
self.channels[channel].add_user(self.users[nick])
|
||||
|
||||
for func in self._user_joined:
|
||||
trigger = Trigger(user, channel, f"{user} has joined", "PRIVMSG", self.config)
|
||||
|
@ -410,38 +434,41 @@ class Fulvia(irc.IRCClient):
|
|||
"""Called when the bot sees another user leave a channel."""
|
||||
nick, _, host = user.partition("!")
|
||||
|
||||
line = f"-!- {nick} [{host}] has left {channel} [{reason}]"
|
||||
line = "-!- " + nick + " " + "[" + host + "] has left "
|
||||
line += channel + " [" + reason + "]"
|
||||
self.log(channel, line)
|
||||
|
||||
self.channels[channel].users.pop(nick)
|
||||
self.channels[channel].remove_user(nick)
|
||||
|
||||
|
||||
def userQuit(self, user, quitMessage):
|
||||
"""Called when the bot sees another user disconnect from the network."""
|
||||
nick, _, host = user.partition("!")
|
||||
line = "-!- {nick} [{host}] has quit [{quitMessage}]"
|
||||
line = "-!- " + nick + " [" + host + "] has quit [" + quitMessage + "]"
|
||||
|
||||
for channel_name, channel in self.channels.items():
|
||||
if not nick in channel.users:
|
||||
continue
|
||||
channels = list(self.users[nick].channels.keys())
|
||||
for channel in channels:
|
||||
self.log(channel, line)
|
||||
|
||||
channel.users.pop(nick)
|
||||
self.channels[channel].remove_user(nick)
|
||||
self.users.pop(nick)
|
||||
|
||||
|
||||
def userKicked(self, kickee, channel, kicker, message):
|
||||
"""
|
||||
Called when the bot sees another user getting kicked from the channel.
|
||||
"""
|
||||
line =f"-!- {kickee} was kicked from {channel} by {kicker} [{message}]"
|
||||
line = "-!- " + kickee + " was kicked from " + channel
|
||||
line += " by " + kicker + " [" + message + "]"
|
||||
self.log(channel, line)
|
||||
|
||||
self.channels[channel].users.pop(kickee)
|
||||
self.channels[channel].remove_user(kickee)
|
||||
|
||||
|
||||
def topicUpdated(self, user, channel, newTopic):
|
||||
"""Called when the bot sees a user update the channel's topic."""
|
||||
line = f"-!- {user} changed the topic of {channel} to: {newTopic}"
|
||||
line = "-!- " + user + " changed the topic of " + channel + " to: "
|
||||
line += newTopic
|
||||
self.log(channel, line)
|
||||
|
||||
self.channels[channel].topic = newTopic
|
||||
|
@ -449,14 +476,15 @@ class Fulvia(irc.IRCClient):
|
|||
|
||||
def userRenamed(self, oldname, newname):
|
||||
"""Called when the bot sees a user change their nickname."""
|
||||
line = "-!- {oldname} is now known as {newname}"
|
||||
line = "-!- " + oldname + " is now known as " + newname
|
||||
|
||||
for channel_name, channel in self.channels.items():
|
||||
self.log(channel_name, line)
|
||||
user = self.users.pop(oldname)
|
||||
self.users[newname] = user
|
||||
for key, channel in user.channels.items():
|
||||
self.log(key, line)
|
||||
|
||||
user = channel.users.pop(oldname)
|
||||
user.nick = newname
|
||||
channel.users[newname] = user
|
||||
channel.rename_user(oldname, newname)
|
||||
user.nick = newname
|
||||
|
||||
|
||||
def namesReceived(self, channel, channel_type, nicklist):
|
||||
|
@ -466,13 +494,12 @@ class Fulvia(irc.IRCClient):
|
|||
"""
|
||||
self.channels[channel].channel_type = channel_type
|
||||
for nick in nicklist:
|
||||
op_level = ''
|
||||
if nick[0] in tools.op_level.keys():
|
||||
op_level = nick[0]
|
||||
op_level = tools.op_level.get(nick[0], 0)
|
||||
if op_level > 0:
|
||||
nick = nick[1:]
|
||||
user = tools.User(nick)
|
||||
user.op_level = op_level
|
||||
self.channels[channel].users[nick] = user
|
||||
self.users[nick] = tools.User(nick)
|
||||
self.channels[channel].add_user(self.users[nick])
|
||||
self.channels[channel].privileges[nick] = op_level
|
||||
|
||||
|
||||
def whoisUser(self, nick, ident, host, realname):
|
||||
|
@ -483,13 +510,6 @@ class Fulvia(irc.IRCClient):
|
|||
self.username = ident
|
||||
self.host = host
|
||||
self.realname = realname
|
||||
else:
|
||||
for channel_name, channel in self.channels.items():
|
||||
if nick in channel:
|
||||
user = channel[nick]
|
||||
user.ident = ident
|
||||
user.host = host
|
||||
user.realname = realname
|
||||
|
||||
|
||||
def whoisIdle(self, nick, idle, signon):
|
||||
|
@ -514,10 +534,11 @@ class Fulvia(irc.IRCClient):
|
|||
an appropriate length automatically.
|
||||
"""
|
||||
if user.startswith("#"):
|
||||
opSym = self.channels[user].users[self.nickname].op_level
|
||||
priv = self.channels[user].privileges[self.nickname]
|
||||
opSym = tools.getOpSym(priv)
|
||||
else:
|
||||
opSym = ''
|
||||
line = f"<{opSym}{self.nickname}> {message}"
|
||||
opSym = ""
|
||||
line = "<" + opSym + self.nickname + ">" + " " + message
|
||||
self.log(user, line)
|
||||
|
||||
irc.IRCClient.msg(self, user, message, length=None)
|
||||
|
|
27
loader.py
27
loader.py
|
@ -30,7 +30,6 @@ def unload_module(bot, name):
|
|||
bot.unregister_callable(obj)
|
||||
|
||||
del old_module
|
||||
delattr(sys.modules['modules'], name.rpartition('.')[2])
|
||||
del sys.modules[name]
|
||||
|
||||
|
||||
|
@ -77,10 +76,36 @@ def process_callable(func, config):
|
|||
Sets various helper atributes about a given function.
|
||||
"""
|
||||
prefix = config.core.prefix
|
||||
doc = func.__doc__
|
||||
if doc:
|
||||
doc = doc.strip()
|
||||
doc = doc.replace("\t", "")
|
||||
doc = doc.replace("\n\n", "\x00")
|
||||
doc = doc.replace("\n", " ")
|
||||
doc = doc.replace("\x00", "\n")
|
||||
func._docs = {}
|
||||
|
||||
func.example = getattr(func, "example", [(None, None)])
|
||||
func.thread = getattr(func, "thread", True)
|
||||
func.hook = getattr(func, "hook", False)
|
||||
func.rate = getattr(func, "rate", 0)
|
||||
func.channel_rate = getattr(func, "channel_rate", 0)
|
||||
func.global_rate = getattr(func, "global_rate", 0)
|
||||
func.priv = getattr(func, "priv", 0)
|
||||
func.user_joined = getattr(func, "user_joined", False)
|
||||
|
||||
if hasattr(func, 'commands'):
|
||||
if len(func.commands) > 1:
|
||||
func.aliases = func.commands[1:]
|
||||
else:
|
||||
func.aliases = []
|
||||
if hasattr(func, 'example'):
|
||||
for n, example in enumerate(func.example):
|
||||
ex_input = example[0]
|
||||
if not ex_input:
|
||||
continue
|
||||
if ex_input[0] != prefix:
|
||||
ex_input = prefix + ex_input
|
||||
func.example[n] = (ex_input, example[1])
|
||||
if doc:
|
||||
func._docs = (doc, func.example)
|
||||
|
|
34
module.py
34
module.py
|
@ -146,6 +146,32 @@ def require_chanmsg(message=None):
|
|||
return actual_decorator
|
||||
|
||||
|
||||
def require_privilege(level, message=None):
|
||||
"""
|
||||
Decorate a function to require at least the given channel permission.
|
||||
|
||||
`level` can be one of the privilege levels defined in this module. If the
|
||||
user does not have the privilege, `message` will be said if given. If it is
|
||||
a private message, no checking will be done.
|
||||
"""
|
||||
def actual_decorator(function):
|
||||
function.priv = level
|
||||
@functools.wraps(function)
|
||||
def guarded(bot, trigger, *args, **kwargs):
|
||||
# If this is a privmsg, ignore privilege requirements
|
||||
if trigger.is_privmsg or trigger.admin:
|
||||
return function(bot, trigger, *args, **kwargs)
|
||||
channel_privs = bot.channels[trigger.channel].privileges
|
||||
allowed = channel_privs.get(trigger.nick, 0) >= level
|
||||
if not allowed:
|
||||
if message and not callable(message):
|
||||
bot.msg(message)
|
||||
else:
|
||||
return function(bot, trigger, *args, **kwargs)
|
||||
return guarded
|
||||
return actual_decorator
|
||||
|
||||
|
||||
def require_admin(message=None):
|
||||
"""
|
||||
Decorate a function to require the triggering user to be a bot admin.
|
||||
|
@ -153,7 +179,8 @@ def require_admin(message=None):
|
|||
If they are not, `message` will be said if given.
|
||||
"""
|
||||
def actual_decorator(function):
|
||||
function.require_admin = True
|
||||
function.priv = 5
|
||||
|
||||
@functools.wraps(function)
|
||||
def guarded(bot, trigger, *args, **kwargs):
|
||||
if not trigger.admin:
|
||||
|
@ -175,7 +202,8 @@ def require_owner(message=None):
|
|||
If they are not, `message` will be said if given.
|
||||
"""
|
||||
def actual_decorator(function):
|
||||
function.require_owner = True
|
||||
function.priv = 10
|
||||
|
||||
@functools.wraps(function)
|
||||
def guarded(bot, trigger, *args, **kwargs):
|
||||
if not trigger.owner:
|
||||
|
@ -208,7 +236,7 @@ def example(ex_input, ex_output=None):
|
|||
|
||||
def url_callback(url):
|
||||
"""
|
||||
Decorate a function with a callback to the URL module.
|
||||
Decore a function with a callback to the URL module.
|
||||
|
||||
This URL will be added to the bot.url_callbacks dictionary in the bot's
|
||||
memory which the URL module will compare it's URL's against. If a key in
|
||||
|
|
|
@ -26,11 +26,13 @@ def new_bot_name(number):
|
|||
@user_joined(True)
|
||||
def adalwulf_(bot, trigger):
|
||||
"""Renames adalwulf__."""
|
||||
print(True)
|
||||
print(trigger.nick)
|
||||
if not trigger.nick.startswith('defaultnick'):
|
||||
return
|
||||
nicks = bot.channels[trigger.channel].users.keys()
|
||||
adals = [nick for nick in nicks if nick.startswith('Adalwulf__')]
|
||||
adals += [nick for nick in nicks if nick.startswith('Adalwulf_|')]
|
||||
names = bot.channels[trigger.channel].users
|
||||
adals = [nick for nick in names if nick.startswith('Adalwulf__')]
|
||||
adals += [nick for nick in names if nick.startswith('Adalwulf_|')]
|
||||
old_nick = trigger.nick
|
||||
new_nick = new_bot_name(len(adals) + 1)
|
||||
bot.sendLine(f"SANICK {old_nick} {new_nick}")
|
||||
|
@ -40,12 +42,12 @@ def adalwulf_(bot, trigger):
|
|||
@commands('rename_hydra')
|
||||
def rename_hydra(bot, trigger):
|
||||
"""Renames defaultnick's appropriately."""
|
||||
for nick in bot.channels[trigger.channel].users.keys():
|
||||
for nick in list(bot.channels[trigger.channel].users.keys()):
|
||||
if not nick.startswith('defaultnick'):
|
||||
continue
|
||||
nicks = bot.channels[trigger.channel].users.keys()
|
||||
adals = [nick for nick in nicks if nick.startswith('Adalwulf__')]
|
||||
adals += [nick for nick in nicks if nick.startswith('Adalwulf_|')]
|
||||
names = bot.channels[trigger.channel].users
|
||||
adals = [nick for nick in names if nick.startswith('Adalwulf__')]
|
||||
adals += [nick for nick in names if nick.startswith('Adalwulf_|')]
|
||||
old_nick = nick
|
||||
new_nick = new_bot_name(len(adals) + 1)
|
||||
print(f"SANICK {old_nick} {new_nick}")
|
||||
|
|
|
@ -9,17 +9,18 @@ import re
|
|||
import module
|
||||
from tools import op_level, configureHostMask
|
||||
|
||||
op = ['~', '!', '@', '%']
|
||||
OP = op_level["op"]
|
||||
HALFOP = op_level["halfop"]
|
||||
|
||||
@module.require_chanmsg
|
||||
@module.require_admin
|
||||
@module.require_privilege(OP, 'You are not a channel operator.')
|
||||
@module.commands('kick')
|
||||
@module.example(".kick faggot being a faggot")
|
||||
def kick(bot, trigger):
|
||||
"""
|
||||
Kick a user from the channel.
|
||||
"""
|
||||
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
|
||||
if bot.channels[trigger.channel].privileges[bot.nick] < HALFOP:
|
||||
return bot.reply("I'm not a channel operator!")
|
||||
if not trigger.group(2):
|
||||
return bot.reply("Who do you want me to kick?")
|
||||
|
@ -35,7 +36,7 @@ def kick(bot, trigger):
|
|||
|
||||
|
||||
@module.require_chanmsg
|
||||
@module.require_admin
|
||||
@module.require_privilege(OP, 'You are not a channel operator.')
|
||||
@module.commands('ban')
|
||||
@module.example(".ban faggot")
|
||||
def ban(bot, trigger):
|
||||
|
@ -43,7 +44,7 @@ def ban(bot, trigger):
|
|||
This give admins the ability to ban a user.
|
||||
The bot must be a Channel Operator for this command to work.
|
||||
"""
|
||||
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
|
||||
if bot.channels[trigger.channel].privileges[bot.nick] < HALFOP:
|
||||
return bot.reply("I'm not a channel operator!")
|
||||
if not trigger.group(2):
|
||||
return bot.reply("Who do you want me to ban?")
|
||||
|
@ -53,7 +54,7 @@ def ban(bot, trigger):
|
|||
|
||||
|
||||
@module.require_chanmsg
|
||||
@module.require_admin
|
||||
@module.require_privilege(OP, 'You are not a channel operator.')
|
||||
@module.commands('unban')
|
||||
@module.example(".unban faggot")
|
||||
def unban(bot, trigger):
|
||||
|
@ -61,7 +62,7 @@ def unban(bot, trigger):
|
|||
This give admins the ability to unban a user.
|
||||
The bot must be a Channel Operator for this command to work.
|
||||
"""
|
||||
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
|
||||
if bot.channels[trigger.channel].privileges[bot.nick] < HALFOP:
|
||||
return bot.reply("I'm not a channel operator!")
|
||||
if not trigger.group(2):
|
||||
return bot.reply("Who do you want me to ban?")
|
||||
|
@ -71,7 +72,7 @@ def unban(bot, trigger):
|
|||
|
||||
|
||||
@module.require_chanmsg
|
||||
@module.require_admin
|
||||
@module.require_privilege(OP, 'You are not a channel operator.')
|
||||
@module.commands('kickban')
|
||||
def kickban(bot, trigger):
|
||||
"""
|
||||
|
@ -79,7 +80,7 @@ def kickban(bot, trigger):
|
|||
The bot must be a Channel Operator for this command to work.
|
||||
.kickban [#chan] user1 user!*@module.* get out of here
|
||||
"""
|
||||
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
|
||||
if bot.channels[trigger.channel].privileges[bot.nick] < HALFOP:
|
||||
return bot.reply("I'm not a channel operator!")
|
||||
if not trigger.group(2):
|
||||
return bot.reply("Who do you want me to ban?")
|
||||
|
@ -97,7 +98,7 @@ def kickban(bot, trigger):
|
|||
|
||||
|
||||
@module.require_chanmsg
|
||||
@module.require_admin
|
||||
@module.require_privilege(OP, 'You are not a channel operator.')
|
||||
@module.commands('settopic')
|
||||
@module.example(".settopic We're discussing penises, would you like to join?")
|
||||
def settopic(bot, trigger):
|
||||
|
@ -105,7 +106,7 @@ def settopic(bot, trigger):
|
|||
This gives ops the ability to change the topic.
|
||||
The bot must be a Channel Operator for this command to work.
|
||||
"""
|
||||
if bot.channels[trigger.channel].users[bot.nick].op_level not in op:
|
||||
if bot.channels[trigger.channel].privileges[bot.nick] < HALFOP:
|
||||
return bot.reply("I'm not a channel operator!")
|
||||
if not trigger.group(2):
|
||||
return bot.reply("What do you want the topic set to?")
|
||||
|
|
|
@ -14,6 +14,6 @@ def announce(bot, trigger):
|
|||
if not trigger.admin:
|
||||
bot.reply("Sorry, I can't let you do that")
|
||||
return
|
||||
for channel in bot.channels.keys():
|
||||
for channel in bot.channels:
|
||||
bot.msg(channel, f"[ANNOUNCEMENT] {trigger.group(2)}")
|
||||
bot.reply('Announce complete.')
|
||||
|
|
|
@ -54,7 +54,7 @@ def banheall(bot, trigger):
|
|||
except (IndexError, KeyError, ValueError, TypeError):
|
||||
period = 0
|
||||
|
||||
for nick in bot.channels[trigger.channel].users.keys():
|
||||
for nick in bot.channels[trigger.channel].users:
|
||||
banmask = configureHostMask(nick)
|
||||
bot.mode(trigger.channel, True, "b", mask=banmask)
|
||||
|
||||
|
@ -66,7 +66,7 @@ def banheall(bot, trigger):
|
|||
bot.msg(f"Banned \x0304them all\x03 for \x0309{str(period)}\x03 seconds.")
|
||||
time.sleep(period)
|
||||
|
||||
for nick in bot.channels[trigger.channel].users.keys():
|
||||
for nick in bot.channels[trigger.channel].users:
|
||||
banmask = configureHostMask(nick)
|
||||
bot.mode(trigger.channel, False, "b", mask=banmask)
|
||||
|
||||
|
|
|
@ -7,50 +7,38 @@ import random
|
|||
|
||||
from module import commands, example
|
||||
|
||||
def clean_docstring(doc):
|
||||
"""Cleans the docstring up a bit."""
|
||||
if not doc:
|
||||
return ''
|
||||
doc = doc.strip()
|
||||
doc = doc.replace("\t", "")
|
||||
doc = doc.replace("\n\n", "\x00")
|
||||
doc = doc.replace("\n", " ")
|
||||
doc = doc.replace("\x00", "\n")
|
||||
return doc
|
||||
|
||||
@commands('help', 'commands')
|
||||
@example('.help tell')
|
||||
def help(bot, trigger):
|
||||
"""Shows a command's documentation, and possibly an example."""
|
||||
if trigger.group(2):
|
||||
command = trigger.group(2)
|
||||
command = command.lower()
|
||||
if command not in bot.commands:
|
||||
name = trigger.group(2)
|
||||
name = name.lower()
|
||||
if name not in bot.commands:
|
||||
return bot.msg("Command not found.")
|
||||
cmd = bot.commands[name]
|
||||
docstring, examples = cmd.doc
|
||||
if examples:
|
||||
ex = random.choice(examples)
|
||||
|
||||
func = bot.commands[command]
|
||||
doc = clean_docstring(func.__doc__)
|
||||
bot.msg(doc)
|
||||
|
||||
aliases = [c for c, f in bot.commands.items() if f == func]
|
||||
aliases.remove(command)
|
||||
if aliases:
|
||||
bot.msg("Aliases: " + ", ".join(aliases))
|
||||
|
||||
if hasattr(func, 'example'):
|
||||
ex = random.choice(func.example)
|
||||
bot.msg(docstring)
|
||||
if cmd.aliases:
|
||||
bot.msg("Aliases: " + ", ".join(cmd.aliases))
|
||||
if ex[0]:
|
||||
bot.msg("Ex. In: " + ex[0])
|
||||
if ex[1]:
|
||||
bot.msg("Ex. Out: " + ex[1])
|
||||
if ex[1]:
|
||||
bot.msg("Ex. Out: " + ex[1])
|
||||
|
||||
else:
|
||||
funcs = [func for cmd, func in bot.commands.items()]
|
||||
if not trigger.owner:
|
||||
funcs = [f for f in funcs if not hasattr(f, 'require_owner')]
|
||||
if not trigger.admin:
|
||||
funcs = [f for f in funcs if not hasattr(f, 'require_admin')]
|
||||
if trigger.owner:
|
||||
cmds = [cmd for _, cmd in bot.commands.items()]
|
||||
elif trigger.admin:
|
||||
cmds = [cmd for _, cmd in bot.commands.items() if cmd.priv <= 5]
|
||||
else:
|
||||
priv = bot.channels[trigger.channel].privileges[trigger.nick]
|
||||
cmds = [cmd for _, cmd in bot.commands.items() if cmd.priv <= priv]
|
||||
|
||||
cmds = {func.commands[0] for func in funcs}
|
||||
cmds = sorted(list(cmds))
|
||||
cmds = [cmd.name for cmd in cmds if cmd.canonical]
|
||||
cmds = sorted(cmds)
|
||||
msg = "Available commands: " + ", ".join(cmds)
|
||||
bot.msg(msg)
|
||||
|
|
|
@ -10,8 +10,8 @@ def pingAll(bot, trigger):
|
|||
Says the nick of everyone in the channel. Great way to get thier
|
||||
attention, or just annoy them.
|
||||
"""
|
||||
nicks = list(bot.channels[trigger.channel].users.keys())
|
||||
names = list(bot.channels[trigger.channel].users.keys())
|
||||
for nigger in ["Ishd", "Ishd2", "Ishd_"]:
|
||||
if nigger in nicks:
|
||||
nicks.remove(nigger)
|
||||
bot.msg(" ".join(nicks))
|
||||
if nigger in names:
|
||||
names.remove(nigger)
|
||||
bot.msg(" ".join(names))
|
||||
|
|
|
@ -72,4 +72,4 @@ def f_unload(bot, trigger):
|
|||
return bot.msg(f"Module '{name}' not loaded, try the 'load' command.")
|
||||
|
||||
loader.unload_module(bot, name)
|
||||
bot.msg(f"Module '{name}' unloaded.")
|
||||
bot.msg(f"Module '{name}' unloaded.")
|
|
@ -24,6 +24,7 @@ class MonitorThread(threading.Thread):
|
|||
self.stop = threading.Event()
|
||||
|
||||
def run(self):
|
||||
# while not self._bot.channels.keys():
|
||||
while not self._bot.stillConnected():
|
||||
time.sleep(1)
|
||||
# don't try to say anything if we're not fully connected yet
|
||||
|
|
|
@ -111,8 +111,8 @@ class FulviaMemoryDefault(defaultdict):
|
|||
return result
|
||||
|
||||
|
||||
class User:
|
||||
"""A representation of a user in a channel."""
|
||||
class User(object):
|
||||
"""A representation of a user Fulvia is aware of."""
|
||||
def __init__(self, nick):
|
||||
self.nick = nick
|
||||
"""The user's nickname."""
|
||||
|
@ -124,21 +124,18 @@ class User:
|
|||
self.host = ""
|
||||
"""The user's hostname."""
|
||||
|
||||
self.realname = ""
|
||||
"""The user's realname."""
|
||||
self.channels = {}
|
||||
"""The channels the user is in."""
|
||||
|
||||
self.away = None
|
||||
"""Whether the user is marked as away."""
|
||||
|
||||
self.op_level = ''
|
||||
"""The user's op level in this channel."""
|
||||
|
||||
def hostmask(self):
|
||||
"""Returns the user's full hostmask."""
|
||||
return f"{self.nick}!{self.user}@{self.host}"
|
||||
hostmask = property(lambda self: '{}!{}@{}'.format(self.nick, self.user,
|
||||
self.host))
|
||||
"""The user's full hostmask."""
|
||||
|
||||
|
||||
class Channel:
|
||||
class Channel(object):
|
||||
"""A representation of a channel Fulvia is in."""
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
@ -154,11 +151,55 @@ class Channel:
|
|||
"""The topic of the channel."""
|
||||
|
||||
self.users = {}
|
||||
"""The users in the channel."""
|
||||
"""The users in the channel. A set to ensure there are no duplicates."""
|
||||
|
||||
self.privileges = {}
|
||||
"""The op levels of the users in the channel."""
|
||||
|
||||
self.modes = set()
|
||||
"""The current modes on the channel."""
|
||||
|
||||
def remove_user(self, nick):
|
||||
"""
|
||||
Removes a user from the channel.
|
||||
"""
|
||||
user = self.users.pop(nick, None)
|
||||
self.privileges.pop(nick, None)
|
||||
if user != None:
|
||||
user.channels.pop(self.name, None)
|
||||
|
||||
def add_user(self, user):
|
||||
"""
|
||||
Adds a user to the channel.
|
||||
"""
|
||||
assert isinstance(user, User)
|
||||
self.users[user.nick] = user
|
||||
self.privileges[user.nick] = 0
|
||||
user.channels[self.name] = self
|
||||
|
||||
def rename_user(self, old, new):
|
||||
"""
|
||||
Renames the user.
|
||||
"""
|
||||
if old in self.users:
|
||||
self.users[new] = self.users.pop(old)
|
||||
if old in self.privileges:
|
||||
self.privileges[new] = self.privileges.pop(old)
|
||||
|
||||
|
||||
class Command():
|
||||
"""
|
||||
A representation of a command and associated documentation and other
|
||||
atributes.
|
||||
"""
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self._func_name = ""
|
||||
self.priv = 0
|
||||
self.doc = None
|
||||
self.canonical = True
|
||||
self.aliases = []
|
||||
|
||||
|
||||
def configureHostMask(mask):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue
Block a user