123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- # encoding: UTF-8
- ###
- # Copyright (c) 2016, Toni Fadjukoff
- # All rights reserved.
- #
- # Redistribution and use in source and binary forms, with or without
- # modification, are permitted provided that the following conditions are met:
- #
- # * Redistributions of source code must retain the above copyright notice,
- # this list of conditions, and the following disclaimer.
- # * Redistributions in binary form must reproduce the above copyright notice,
- # this list of conditions, and the following disclaimer in the
- # documentation and/or other materials provided with the distribution.
- # * Neither the name of the author of this software nor the name of
- # contributors to this software may be used to endorse or promote products
- # derived from this software without specific prior written consent.
- #
- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- # POSSIBILITY OF SUCH DAMAGE.
-
- ###
-
- import time
- from dateutil.rrule import *
-
- import supybot.utils as utils
- from supybot.commands import *
- import supybot.plugins as plugins
- import supybot.ircutils as ircutils
- import supybot.schedule as schedule
- import supybot.callbacks as callbacks
- try:
- from supybot.i18n import PluginInternationalization
- _ = PluginInternationalization('Timer')
- except ImportError:
- # Placeholder that allows to run the plugin on a bot
- # without the i18n module
- _ = lambda x: x
-
-
- class Timer(callbacks.Plugin):
- """Command based scheduling for triggers"""
-
- def __init__(self, irc):
- self.__parent = super(Timer, self)
- self.__parent.__init__(irc)
- self.events = {}
-
- def _makeCommandFunction(self, irc, msg, message):
- nickprefix = msg.prefix.split("!")[0] + ": " if ircutils.isChannel(msg.args[0]) else ""
- message = format("echo %s%s", nickprefix, message)
- tokens = callbacks.tokenize(message)
- def f():
- del self.events[str(f.eventId)]
- self.Proxy(irc.irc, msg, tokens)
- return f
-
- @staticmethod
- def _parseDate(arg):
- day = 0
- month = 0
- if len(arg) == 6 and arg[2] == arg[5] == "." and arg[0:2].isdigit() and arg[3:5].isdigit():
- day = int(arg[0:2])
- month = int(arg[3:5])
- elif len(arg) == 5 and arg[2] == arg[4] == "." and arg[0:2].isdigit() and arg[3:4].isdigit():
- day = int(arg[0:2])
- month = int(arg[3:4])
- elif len(arg) == 5 and arg[1] == arg[4] == "." and arg[0:1].isdigit() and arg[2:4].isdigit():
- day = int(arg[0:1])
- month = int(arg[2:4])
- elif len(arg) == 4 and arg[1] == arg[3] == "." and arg[0:1].isdigit() and arg[2:3].isdigit():
- day = int(arg[0:1])
- month = int(arg[2:3])
- if 0 < day < 32 and 0 < month < 13:
- return month, day
- return None
-
- @staticmethod
- def _parseTime(arg):
- if ":" in arg:
- hours, minutes = arg.split(":")
- elif "." in arg:
- hours, minutes = arg.split(".")
- elif len(arg) == 4:
- hours = arg[0:2]
- minutes = arg[2:4]
- elif len(arg) == 3:
- hours = arg[0]
- minutes = arg[1:3]
- elif len(arg) in (1,2):
- hours = arg
- minutes = "0"
- else:
- hours = None
- minutes = None
- if hours == None or len(hours) not in (1,2) or len(minutes) not in (1,2):
- return
-
- try:
- hours = int(hours)
- except ValueError as e:
- return
- try:
- minutes = int(minutes)
- except ValueError as e:
- return
-
- if minutes >= 60:
- hours += int(minutes / 60)
- minutes = minutes % 60
- if hours >= 24:
- hours = hours % 24
-
- return hours, minutes
-
- def _resolveTime(self, irc, dateArg, timeArg):
- month = mday = hours = minutes = None
- if dateArg != None:
- (month, mday) = self._parseDate(dateArg)
-
- (hours, minutes) = self._parseTime(timeArg)
-
- return list(rrule(MINUTELY, count = 1, bymonth = month, bymonthday = mday,
- byhour = hours, byminute = minutes))[0]
-
- def _testDate(date):
- return Timer._parseDate(date) != None
-
- def _testTime(time):
- return Timer._parseTime(time) != None
-
- def _scheduleOnce(self, irc, msg, message, scheduleTime):
- #irc.reply(format("Scheduled at %s", scheduleTime))
- f = self._makeCommandFunction(irc, msg, message)
- id = schedule.addEvent(f, scheduleTime)
- f.eventId = id
- self.events[str(id)] = f
-
- def timer(self, irc, msg, args, dateArg, timeArg, message):
- """[date] <time> <message>
-
- Set a message to be played back later.
- """
- scheduleTime = self._resolveTime(irc, dateArg, timeArg).timestamp()
- self._scheduleOnce(irc, msg, message, scheduleTime)
-
- timer = wrap(timer, [optional(('something', None, _testDate)), ('something', None, _testTime), 'text'])
-
- def food(self, irc, msg, args, minutes, message):
- """[minuutit] [viesti]
-
- Huomauta viestillä muutaman minuutin päästä.
- Pikakomennot: pizza 12 minuuttia, makaronilaatikko 60 minuuttia, ranskalaiset 30 minuuttia
- """
- irc.reply(format('Meikä kiekaisee sitten %i minuutin päästä %s', minutes, message))
- scheduleTime = time.time() + minutes * 60
- self._scheduleOnce(irc, msg, message, scheduleTime)
- food = wrap(food, ['positiveInt', 'text'])
-
- Class = Timer
-
-
- # vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:
|