aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjason2016-08-10 22:22:48 -0600
committerjason2016-08-10 22:22:48 -0600
commit96ce83f826d37ad8430c9efddcc8fd880a0c293b (patch)
tree33545358d43272086612ec35f8e3a831979f71d1
parent321278d788b8fdc035860c07745be6177d0be3d1 (diff)
downloadwarmachine-ng-96ce83f826d37ad8430c9efddcc8fd880a0c293b.tar.gz
warmachine-ng-96ce83f826d37ad8430c9efddcc8fd880a0c293b.zip
Add support for saving standup schedules and reloading them on startup
-rwxr-xr-xbin/dbolla7
-rw-r--r--warmachine/addons/base.py2
-rw-r--r--warmachine/addons/standup.py81
-rw-r--r--warmachine/connections/slack.py8
4 files changed, 66 insertions, 32 deletions
diff --git a/bin/dbolla b/bin/dbolla
index 78fe482..6c0b573 100755
--- a/bin/dbolla
+++ b/bin/dbolla
@@ -4,6 +4,8 @@ import asyncio
4import datetime 4import datetime
5import functools 5import functools
6import logging.config 6import logging.config
7import os
8
7 9
8from warmachine.config import Config 10from warmachine.config import Config
9from warmachine.connections.irc import AioIRC 11from warmachine.connections.irc import AioIRC
@@ -53,6 +55,8 @@ class Bot(object):
53 self.load_plugin('warmachine.addons.giphy.GiphySearch') 55 self.load_plugin('warmachine.addons.giphy.GiphySearch')
54 self.load_plugin('warmachine.addons.standup.StandUpPlugin') 56 self.load_plugin('warmachine.addons.standup.StandUpPlugin')
55 57
58 # TODO: Ensure the config directory has been created
59
56 def start(self): 60 def start(self):
57 for connection in self.connections: 61 for connection in self.connections:
58 t = asyncio.ensure_future(connection.connect()) 62 t = asyncio.ensure_future(connection.connect())
@@ -64,6 +68,9 @@ class Bot(object):
64 self.connections[connection] = {} 68 self.connections[connection] = {}
65 69
66 def on_connect(self, connection, task): 70 def on_connect(self, connection, task):
71 for p in self.loaded_plugins:
72 if hasattr(p, 'on_connect'):
73 p.on_connect(connection)
67 asyncio.ensure_future(self.process_message(connection)) 74 asyncio.ensure_future(self.process_message(connection))
68 75
69 async def process_message(self, connection): 76 async def process_message(self, connection):
diff --git a/warmachine/addons/base.py b/warmachine/addons/base.py
index aa23c78..e605c2c 100644
--- a/warmachine/addons/base.py
+++ b/warmachine/addons/base.py
@@ -1,6 +1,8 @@
1import asyncio
1import logging 2import logging
2 3
3 4
4class WarMachinePlugin(object): 5class WarMachinePlugin(object):
5 def __init__(self): 6 def __init__(self):
7 self._loop = asyncio.get_event_loop()
6 self.log = logging.getLogger(self.__class__.__name__) 8 self.log = logging.getLogger(self.__class__.__name__)
diff --git a/warmachine/addons/standup.py b/warmachine/addons/standup.py
index dc5f70a..99094d5 100644
--- a/warmachine/addons/standup.py
+++ b/warmachine/addons/standup.py
@@ -30,6 +30,9 @@ class StandUpPlugin(WarMachinePlugin):
30 # } 30 # }
31 self.users_awaiting_reply = {} 31 self.users_awaiting_reply = {}
32 32
33 def on_connect(self, connection):
34 self.load_schedule(connection)
35
33 async def recv_msg(self, connection, message): 36 async def recv_msg(self, connection, message):
34 """ 37 """
35 When the connection receives a message this method is called. We parse 38 When the connection receives a message this method is called. We parse
@@ -73,39 +76,12 @@ class StandUpPlugin(WarMachinePlugin):
73 cmd = message['message'].split(' ')[0] 76 cmd = message['message'].split(' ')[0]
74 parts = message['message'].split(' ')[1:] 77 parts = message['message'].split(' ')[1:]
75 78
76 self._loop = asyncio.get_event_loop()
77
78 ################ 79 ################
79 # !standup-add # 80 # !standup-add #
80 ################ 81 ################
81 if cmd == '!standup-add': 82 if cmd == '!standup-add':
82 next_standup = self.get_next_standup_secs(parts[0]) 83 self.schedule_standup(connection, message['channel'], parts[0])
83 84 self.save_schedule(connection)
84 standup_td = next_standup - datetime.now()
85 next_standup_secs = standup_td.seconds
86
87 f = self._loop.call_later(
88 next_standup_secs, functools.partial(
89 self.standup_schedule_func, connection, message['channel']))
90
91 self.standup_schedules[message['channel']] = {
92 'future': f,
93 'datetime': next_standup,
94 'time24h': parts[0],
95 }
96
97 self.log.info('New schedule added to channel {} for {}'.format(
98 connection.channel_map[message['channel']]['name'],
99 parts[0]
100 ))
101
102 await connection.say('Next standup at {} ({}s)'.format(
103 next_standup.ctime(), next_standup_secs), message['channel'])
104
105 # d = json.dumps(self.standup_schedules)
106 # with open('~/.warmachine/standup_schedules.json', 'w') as f:
107 # f.write(d)
108
109 85
110 ###################### 86 ######################
111 # !standup-schedules # 87 # !standup-schedules #
@@ -122,6 +98,7 @@ class StandUpPlugin(WarMachinePlugin):
122 'Current Time: {}'.format(datetime.now()), message['channel']) 98 'Current Time: {}'.format(datetime.now()), message['channel'])
123 await connection.say( 99 await connection.say(
124 pformat(self.standup_schedules), message['channel']) 100 pformat(self.standup_schedules), message['channel'])
101
125 ############################ 102 ############################
126 # !standup-waiting_replies # 103 # !standup-waiting_replies #
127 ############################ 104 ############################
@@ -134,6 +111,30 @@ class StandUpPlugin(WarMachinePlugin):
134 await connection.say( 111 await connection.say(
135 pformat(self.users_awaiting_reply), message['channel']) 112 pformat(self.users_awaiting_reply), message['channel'])
136 113
114 def schedule_standup(self, connection, channel, time24h):
115 """
116 Schedules a standup
117 """
118 next_standup = self.get_next_standup_secs(time24h)
119
120 standup_td = next_standup - datetime.now()
121 next_standup_secs = standup_td.seconds
122
123 f = self._loop.call_later(
124 next_standup_secs, functools.partial(
125 self.standup_schedule_func, connection, channel))
126
127 self.standup_schedules[channel] = {
128 'future': f,
129 'datetime': next_standup,
130 'time24h': time24h,
131 }
132
133 self.log.info('New schedule added to channel {} for {}'.format(
134 connection.channel_map[channel]['name'],
135 time24h
136 ))
137
137 def standup_schedule_func(self, connection, channel): 138 def standup_schedule_func(self, connection, channel):
138 """ 139 """
139 Non-async function used to schedule the standup for a channel. 140 Non-async function used to schedule the standup for a channel.
@@ -249,12 +250,30 @@ class StandUpPlugin(WarMachinePlugin):
249 250
250 return next_standup 251 return next_standup
251 252
252 def save_schedule(self): 253 def save_schedule(self, connection):
253 """ 254 """
254 Save all channel schedules to a file. 255 Save all channel schedules to a file.
255 """ 256 """
257 keys_to_save = ['time24h', ]
258 data = {}
259 for channel in self.standup_schedules:
260 data[channel] = {}
261 for key in keys_to_save:
262 data[channel][key] = self.standup_schedules[channel][key]
263
264 data = {connection.id: data}
265 with open('/home/jason/.warmachine/standup_schedules.json', 'w') as f:
266 f.write(json.dumps(data))
256 267
257 def load_schedule(self): 268 self.log.info('Schedules saved to disk')
269
270 def load_schedule(self, connection):
258 """ 271 """
259 Load the channel schedules from a file. 272 Load the channel schedules from a file.
260 """ 273 """
274 with open('/home/jason/.warmachine/standup_schedules.json', 'r') as f:
275 data = json.loads(f.read())
276
277 for channel in data[connection.id]:
278 self.schedule_standup(
279 connection, channel, data[connection.id][channel]['time24h'])
diff --git a/warmachine/connections/slack.py b/warmachine/connections/slack.py
index 0cc69d4..8ae52da 100644
--- a/warmachine/connections/slack.py
+++ b/warmachine/connections/slack.py
@@ -8,7 +8,7 @@ import urllib.request
8import websockets 8import websockets
9 9
10from .base import Connection, INITALIZED, CONNECTED 10from .base import Connection, INITALIZED, CONNECTED
11 11from ..utils.decorators import memoize
12 12
13#: Define slack as a config section prefix 13#: Define slack as a config section prefix
14__config_prefix__ = 'slack' 14__config_prefix__ = 'slack'
@@ -36,6 +36,12 @@ class SlackWS(Connection):
36 36
37 self.status = INITALIZED 37 self.status = INITALIZED
38 38
39 @property
40 @memoize
41 def id(self):
42 from hashlib import md5
43 return md5(self.token.encode()).hexdigest()
44
39 async def connect(self): 45 async def connect(self):
40 self.host = self.authenticate() 46 self.host = self.authenticate()
41 self.log.info('Connecting to {}'.format(self.host)) 47 self.log.info('Connecting to {}'.format(self.host))