-
Notifications
You must be signed in to change notification settings - Fork 4
/
admin.py
230 lines (190 loc) · 6.95 KB
/
admin.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# 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 sopel.config.types import (
StaticSection, ValidatedAttribute, FilenameAttribute
)
import sopel.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)
@sopel.module.require_privmsg
@sopel.module.require_admin
@sopel.module.commands('join')
@sopel.module.priority('low')
@sopel.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)
@sopel.module.require_privmsg
@sopel.module.require_admin
@sopel.module.commands('part')
@sopel.module.priority('low')
@sopel.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)
@sopel.module.require_privmsg
@sopel.module.require_owner
@sopel.module.commands('quit')
@sopel.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)
@sopel.module.require_privmsg
@sopel.module.require_admin
@sopel.module.commands('msg')
@sopel.module.priority('low')
@sopel.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.msg(channel, message)
@sopel.module.require_privmsg
@sopel.module.require_admin
@sopel.module.commands('me')
@sopel.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.msg(channel, msg)
@sopel.module.event('INVITE')
@sopel.module.rule('.*')
@sopel.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
@sopel.module.event('KICK')
@sopel.module.rule(r'.*')
@sopel.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)
@sopel.module.require_privmsg
@sopel.module.require_admin
@sopel.module.commands('mode')
@sopel.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))
@sopel.module.require_privmsg("This command only works as a private message.")
@sopel.module.require_admin("This command requires admin privileges.")
@sopel.module.commands('set')
@sopel.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(descriptor, value)
except ValueError as exc:
bot.say("Can't set attribute: " + str(exc))
return
setattr(section, option, value)
@sopel.module.require_privmsg
@sopel.module.require_admin
@sopel.module.commands('save')
@sopel.module.example('.save')
def save_config(bot, trigger):
"""Save state of sopels config object to the configuration file."""
bot.config.save()
bot.reply('config saved')