summaryrefslogtreecommitdiffstats
path: root/update_topic.py
blob: bdcba6ce0ad8c6623ddb14aec3dc6807ea4d4001 (plain)
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
#!/usr/bin/env python
"""
update_topic.py - Keep topic in #spline up-to-date
Copyright 2015, Alexander Sulfrian <alex@spline.inf.fu-berlin.de>
Licensed under the Eiffel Forum License 2.

http://inamidst.com/phenny/
"""

import asyncore
import re
import socket
import threading
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from calendar import TUESDAY


CHANNEL = '#spline'
FROMAT = 'http://padlite.spline.de/p/treffen%y%m%d'
REGEX = re.compile(r'.*(http://padlite\.spline\.de/p/treffen[0-9]{6}).*')


def setup(phenny):
    Scheduler(phenny)


class Timer(object):
    def __init__(self, sock):
        self.sock = sock
        self.start()

    def start(self):
        sleep = seconds_until(get_next_meeting() + timedelta(days=1))
        self.timer = threading.Timer(sleep, self.run)
        self.timer.start()

    def run(self):
        self.sock.send('.')
        self.start()

    def cancel(self):
        self.timer.cancel()


class Scheduler(asyncore.dispatcher):
    def __init__(self, phenny):
        self.phenny = phenny
        self.phenny._orig_close = self.phenny.close
        self.phenny.close = (lambda: self._phenny_close())

	recv_timer, send_timer = socket.socketpair()
        self.timer = Timer(send_timer)
        asyncore.dispatcher.__init__(self, recv_timer)

    def _phenny_close(self):
        self.close()
        self.phenny._orig_close()

    def close(self):
        self.timer.cancel()
        asyncore.dispatcher.close()

    def writable(self):
        return False

    def handle_read(self):
       data = self.recv(8192)
       if data:
           self._exec()
       else:
           self.close()

    def _exec(self):
        # get topic, topic update is handled if a topic is received
        self.phenny.write(['TOPIC'], CHANNEL)


def seconds_until(when):
    today = datetime.today().date()
    return (when - today).total_seconds()


def get_next_meeting():
    today = datetime.today()
    return (today + relativedelta(months=+1, day=1, weekday=TUESDAY)).date()


def update_topic(phenny, channel, topic):
    if channel != CHANNEL:
        return

    match = REGEX.match(topic)
    if match is None:
        return

    new_topic = topic.replace(
        match.groups()[0],
        get_next_meeting().strftime(FROMAT),
        1)

    if new_topic != topic:
        print('Updating topic')
        phenny.msg('ChanServ', 'TOPIC %s %s' % (channel, new_topic))


def topic_change(phenny, input):
    update_topic(phenny, input.sender, input)
topic_change.event = 'TOPIC'
topic_change.rule = r'.*'


def topic_reply(phenny, input):
    update_topic(phenny, input.args[1], input)
topic_reply.event = '332'
topic_reply.rule = r'.*'


def request_topic(phenny, input):
    parts = input.split(None, 1)
    if len(parts) < 2:
        phenny.notice(input.nick, 'Usage: %s #channel' % parts[0])
    else:
        phenny.write(['TOPIC'], parts[1])
        phenny.notice(input.nick, 'Done.')
request_topic.rule = r'^!(update|topic|update-topic)(?: +(.*))?$'
request_topic.event = 'NOTICE'