230 lines
6.7 KiB
Python
Executable File
230 lines
6.7 KiB
Python
Executable File
#! /usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
admin.py - Sopel Admin Module
|
|
Copyright 2010-2011, Sean B. Palmer (inamidst.com) and Michael Yanovich
|
|
(yanovich.net)
|
|
Copyright © 2012, Elad Alfassa, <elad@fedoraproject.org>
|
|
Copyright 2013, Ari Koivula <ari@koivu.la>
|
|
|
|
Licensed under the Eiffel Forum License 2.
|
|
|
|
http://sopel.chat
|
|
"""
|
|
from __future__ import unicode_literals, absolute_import, print_function, division
|
|
|
|
from config.types import (
|
|
StaticSection, ValidatedAttribute, FilenameAttribute
|
|
)
|
|
import module
|
|
|
|
|
|
class AdminSection(StaticSection):
|
|
hold_ground = ValidatedAttribute('hold_ground', bool, default=False)
|
|
"""Auto re-join on kick"""
|
|
auto_accept_invite = ValidatedAttribute('auto_accept_invite', bool,
|
|
default=True)
|
|
|
|
|
|
def configure(config):
|
|
config.define_section('admin', AdminSection)
|
|
config.admin.configure_setting('hold_ground',
|
|
"Automatically re-join after being kicked?")
|
|
config.admin.configure_setting('auto_accept_invite',
|
|
'Automatically join channels when invited?')
|
|
|
|
|
|
def setup(bot):
|
|
bot.config.define_section('admin', AdminSection)
|
|
|
|
|
|
@module.require_privmsg
|
|
@module.require_admin
|
|
@module.commands('join')
|
|
@module.priority('low')
|
|
@module.example('.join #example or .join #example key')
|
|
def join(bot, trigger):
|
|
"""Join the specified channel. This is an admin-only command."""
|
|
channel, key = trigger.group(3), trigger.group(4)
|
|
if not channel:
|
|
return
|
|
elif not key:
|
|
bot.join(channel)
|
|
else:
|
|
bot.join(channel, key)
|
|
|
|
|
|
@module.require_privmsg
|
|
@module.require_admin
|
|
@module.commands('part')
|
|
@module.priority('low')
|
|
@module.example('.part #example')
|
|
def part(bot, trigger):
|
|
"""Part the specified channel. This is an admin-only command."""
|
|
channel, _sep, part_msg = trigger.group(2).partition(' ')
|
|
if part_msg:
|
|
bot.part(channel, part_msg)
|
|
else:
|
|
bot.part(channel)
|
|
|
|
|
|
@module.require_owner
|
|
@module.commands('quit')
|
|
@module.priority('low')
|
|
def quit(bot, trigger):
|
|
"""Quit from the server. This is an owner-only command."""
|
|
quit_message = trigger.group(2)
|
|
if not quit_message:
|
|
quit_message = 'Quitting on command from %s' % trigger.nick
|
|
|
|
bot.quit(quit_message)
|
|
|
|
|
|
@module.require_privmsg
|
|
@module.require_admin
|
|
@module.commands('msg')
|
|
@module.priority('low')
|
|
@module.example('.msg #YourPants Does anyone else smell neurotoxin?')
|
|
def msg(bot, trigger):
|
|
"""
|
|
Send a message to a given channel or nick. Can only be done in privmsg by an
|
|
admin.
|
|
"""
|
|
if trigger.group(2) is None:
|
|
return
|
|
|
|
channel, _sep, message = trigger.group(2).partition(' ')
|
|
message = message.strip()
|
|
if not channel or not message:
|
|
return
|
|
|
|
bot.say(message, channel)
|
|
|
|
|
|
@module.require_privmsg
|
|
@module.require_admin
|
|
@module.commands('me')
|
|
@module.priority('low')
|
|
def me(bot, trigger):
|
|
"""
|
|
Send an ACTION (/me) to a given channel or nick. Can only be done in privmsg
|
|
by an admin.
|
|
"""
|
|
if trigger.group(2) is None:
|
|
return
|
|
|
|
channel, _sep, action = trigger.group(2).partition(' ')
|
|
action = action.strip()
|
|
if not channel or not action:
|
|
return
|
|
|
|
msg = '\x01ACTION %s\x01' % action
|
|
bot.say(msg, channel)
|
|
|
|
|
|
@module.event('INVITE')
|
|
@module.rule('.*')
|
|
@module.priority('low')
|
|
def invite_join(bot, trigger):
|
|
"""
|
|
Join a channel sopel is invited to, if the inviter is an admin.
|
|
"""
|
|
if trigger.admin or bot.config.admin.auto_accept_invite:
|
|
bot.join(trigger.args[1])
|
|
return
|
|
|
|
|
|
@module.event('KICK')
|
|
@module.rule(r'.*')
|
|
@module.priority('low')
|
|
def hold_ground(bot, trigger):
|
|
"""
|
|
This function monitors all kicks across all channels sopel is in. If it
|
|
detects that it is the one kicked it'll automatically join that channel.
|
|
|
|
WARNING: This may not be needed and could cause problems if sopel becomes
|
|
annoying. Please use this with caution.
|
|
"""
|
|
if bot.config.admin.hold_ground:
|
|
channel = trigger.sender
|
|
if trigger.args[1] == bot.nick:
|
|
bot.join(channel)
|
|
|
|
|
|
@module.require_privmsg
|
|
@module.require_admin
|
|
@module.commands('mode')
|
|
@module.priority('low')
|
|
def mode(bot, trigger):
|
|
"""Set a user mode on Sopel. Can only be done in privmsg by an admin."""
|
|
mode = trigger.group(3)
|
|
bot.write(('MODE ', bot.nick + ' ' + mode))
|
|
|
|
|
|
@module.require_privmsg("This command only works as a private message.")
|
|
@module.require_admin("This command requires admin privileges.")
|
|
@module.commands('set')
|
|
@module.example('.set core.owner Me')
|
|
def set_config(bot, trigger):
|
|
"""See and modify values of sopels config object.
|
|
|
|
Trigger args:
|
|
arg1 - section and option, in the form "section.option"
|
|
arg2 - value
|
|
|
|
If there is no section, section will default to "core".
|
|
If value is None, the option will be deleted.
|
|
"""
|
|
# Get section and option from first argument.
|
|
arg1 = trigger.group(3).split('.')
|
|
if len(arg1) == 1:
|
|
section_name, option = "core", arg1[0]
|
|
elif len(arg1) == 2:
|
|
section_name, option = arg1
|
|
else:
|
|
bot.reply("Usage: .set section.option value")
|
|
return
|
|
section = getattr(bot.config, section_name)
|
|
static_sec = isinstance(section, StaticSection)
|
|
|
|
if static_sec and not hasattr(section, option):
|
|
bot.say('[{}] section has no option {}.'.format(section_name, option))
|
|
return
|
|
|
|
# Display current value if no value is given.
|
|
value = trigger.group(4)
|
|
if not value:
|
|
if not static_sec and bot.config.parser.has_option(section, option):
|
|
bot.reply("Option %s.%s does not exist." % (section_name, option))
|
|
return
|
|
# Except if the option looks like a password. Censor those to stop them
|
|
# from being put on log files.
|
|
if option.endswith("password") or option.endswith("pass"):
|
|
value = "(password censored)"
|
|
else:
|
|
value = getattr(section, option)
|
|
bot.reply("%s.%s = %s" % (section_name, option, value))
|
|
return
|
|
|
|
# Otherwise, set the value to one given as argument 2.
|
|
if static_sec:
|
|
descriptor = getattr(section.__class__, option)
|
|
try:
|
|
if isinstance(descriptor, FilenameAttribute):
|
|
value = descriptor.parse(bot.config, descriptor, value)
|
|
else:
|
|
value = descriptor.parse(value)
|
|
except ValueError as exc:
|
|
bot.say("Can't set attribute: " + str(exc))
|
|
return
|
|
setattr(section, option, value)
|
|
|
|
|
|
@module.require_privmsg
|
|
@module.require_admin
|
|
@module.commands('save')
|
|
@module.example('.save')
|
|
def save_config(bot, trigger):
|
|
"""Save state of sopels config object to the configuration file."""
|
|
bot.config.save()
|