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 | #!/usr/bin/env python
###
# This is an example plugin that sends a message to a channel every 60 seconds,
# includes commands to stop, start, and reset the spammer, and a command to
# schedule a one-off event
###
# these are the default plugin modules
import supybot.utils as utils
from supybot.commands import *
import supybot.plugins as plugins
import supybot.ircutils as ircutils
import supybot.callbacks as callbacks
# these are the extra modules we'll be using
import time
import supybot.ircmsgs as ircmsgs
import supybot.schedule as schedule
class Spam(callbacks.Plugin):
"""Add the help for "@plugin help Spam" here
This should describe *how* to use this plugin."""
def __init__(self, irc):
# these two lines are required if you have a custom __init__()
self.__parent = super(Spam, self)
self.__parent.__init__(irc)
# this is the channel we want to spam, and how frequently we want to do it.
# It would be nicer to put it in a supybot config variable instead, but for
# this demonstration, defining it in the plugin itself is fine.
self.spamChannel = '#testytest'
self.spamTime = 60
# scheduler events are global, so we want to test to make sure the event doesn't
# already exist. That is, even if the plugin is reloaded, the event sticks
# around. That means that you also have to be a little careful with your
# event names, especially if you have multiple plugins adding events. It also
# means that events will stick around even if the plugin they originated in
# is unloaded. I don't know how to delete them automatically on an unload, but
# it's not normally an issue. Just make sure to stop the event before unloading
# the plugin if that's what you want.
try:
schedule.removeEvent('mySpamEvent')
except KeyError:
pass
# now that we know there's no event by that name scheduled, we can create one.
# but first, we need to define a local helper function that will do the thing
# that we want. You can put the full contents into here, but I prefer to use
# separate methods, as it makes the code easier to get around in. We need
# the helper function because when you add events, you can't include arguments.
def myEventCaller():
self.spamEvent(irc)
# and now we can schedule the actual event
# schedule.addPeriodicEvent(f, t, name=None, now=True)
# f is the method, t is the time in seconds, name gives it a name and is optional
# (but highly recommended, so that you can refer to the event in the future.
# otherwise, it's easy to accumulate duplicate events), and 'now' specifies
# whether to perform the action immediately, or to wait until time is up to
# perform it for the first time. Default is True.
schedule.addPeriodicEvent(myEventCaller, self.spamTime, 'mySpamEvent')
self.irc = irc
# make sure to have a capital letter or underscore or something, as it's not a method
# that we want turned into an IRC command
def spamEvent(self, irc):
# we need to use queueMsg() rather than reply(), because when the event is
# scheduled on loading the plugin (as opposed to scheduling it with one of the
# commands that we'll define next), it recieves its irc object from __init__().
# When the bot is started, the irc object that comes from __init__() doesn't
# include a reply() method, because it's not loading in response to a command;
# it's loading on the bot startup. If you don't want your event to be scheduled
# automatically and so don't schedule it from __init__(), but only from an IRC
# command, then it's safe to use irc.reply(), as there are no circumstances
# under which the irc object won't have a reply() method.
irc.queueMsg(ircmsgs.privmsg(self.spamChannel, 'I\'m spamming the channel!'))
def start(self, irc, msg, args):
"""takes no arguments
A command to start the spammer."""
# don't forget to redefine the event wrapper
def myEventCaller():
self.spamEvent(irc)
try:
schedule.addPeriodicEvent(myEventCaller, self.spamTime, 'mySpamEvent', False)
except AssertionError:
irc.reply('Error: the spammer was already running!')
else:
irc.reply('Spammer started!')
start = wrap(start)
def stop(self, irc, msg, args):
"""takes no arguments
A command to stop the spammer."""
try:
schedule.removeEvent('mySpamEvent')
except KeyError:
irc.reply('Error: the spammer wasn\'t running!')
else:
irc.reply('Spammer stopped.')
stop = wrap(stop)
def reset(self, irc, msg, args):
"""takes no arguments
Resets the spammer. Can be useful if something changes and you want the
spam to reflect that. For example, if you defined the spamChannel as a
supybot config, and changed it while the spammer was running, it would still
keep going on the same channel until you reset it."""
def myEventCaller():
self.spamEvent(irc)
try:
schedule.removeEvent('mySpamEvent')
except KeyError:
irc.reply('Spammer wasn\'t running')
schedule.addPeriodicEvent(myEventCaller, self.spamTime, 'mySpamEvent', False)
irc.reply('Spammer reset sucessfully!')
reset = wrap(reset)
# Here's an example of a one-off event, scheduled by an IRC command
def sayhi(self, irc, msg, args, delay):
"""<time delay>
Says hi after the specified delay"""
def myEventCaller():
self.Hello(irc)
# for a one-off event, the time is an absolute time, not relative. So we need
# to get the current time and add to it however long we want to wait
t = time.time() + delay
# since we don't specify a name, we won't be able to reference the events in
# the future, but that's ok, because these are one-off events, so even if you
# do call it multiple times, it'll just reply that same number of times and
# then stop. But in some circumstances you might want to name them. Just
# remember that it'll give an AssertionError if you try to create two events
# with the same name
schedule.addEvent(myEventCaller, t)
irc.reply('"hi" scheduled for %d seconds from now!' % delay)
sayhi = wrap(sayhi, ['positiveInt'])
def Hello(self, irc):
# since the irc object is coming from an IRC command, rather than from __init__(),
# it's guaranteed to have a reply() method, so it's safe to use that. It
# might be better to to use queueMsg() instead, regardless, but I don't know
# enough about the supybot internals to say whether one is prefered over
# the other
irc.reply('hi!')
Class = Spam
|