]> apps.delaporte.us Git - matrix-goal-bot.git/blob - matrix_goal_bot/bot.py
Fixup later command
[matrix-goal-bot.git] / matrix_goal_bot / bot.py
1 '''
2 Prefix: .goal
3
4 Synax:
5 .goal COMMAND ARGS
6
7 Commands:
8 help - show this help
9 extra.help - show extended help
10 add - add a goal
11 clear - clear completed tasks under current goal
12 task ID - add a task under the goal specified by ID
13 close ID - mark goal done by ID
14 done ID - mark task done by ID
15 list - list incomplete goals
16 print GOAL_ID - print a goal and all tasks
17 '''
18
19 ex_help = '''
20 More commands:
21 add.vision - add a new vision (collection of goals)
22 close.vision ID - mark vision as complete by ID
23 dump - dump the full data set - BEWARE - so many messages
24 later VISION_ID - put off all goals in VISION for 14 days
25 list.later - list all 'later' goals
26 print.vision ID - print a vision and all goals
27 set.vision GOAL_ID VISION_ID- associate GOAL_ID with VISION_ID
28 visions - list incomplete visions
29 list.done - list completed goals
30 remove ID - remove a task by ID
31 start GOAL_ID - un-put-off a goal (reverse of later)
32 visionless - list goals with no set vision
33 wins - list recently completed goals
34 '''
35
36
37 from datetime import datetime as dt
38 import logging
39 import os
40
41 import simplematrixbotlib as botlib
42
43 from .db import Data, pretty_print
44
45 DATE_FORMAT = '%Y-%m-%d'
46
47 def today():
48 return dt.now().strftime(DATE_FORMAT)
49
50 logger = logging.getLogger(__name__)
51
52 snark = [
53 'Ye cannot get ye flask.',
54 'Ye flask must be load bearing, or something...',
55 '''You have:
56 no tea
57 ''',
58 'How are you gentlemen?',
59 'All your base are belong to us.',
60 'You have been eaten by a groo.'
61 ]
62
63 class GoalBot():
64 def __init__(self, matrix_server,
65 bot_name,
66 bot_pwd,
67 db_file=None,
68 bot_prefix='.goal'):
69
70 creds = botlib.Creds(matrix_server, bot_name, bot_pwd)
71 self.bot = botlib.Bot(creds)
72 self.prefix = bot_prefix
73 self.data = Data(db_file)
74
75 def run(self):
76 logger.debug('Running goal bot...')
77 self.bot.run()
78
79 async def handle_message(self, room, message):
80 match = botlib.MessageMatch(room, message, self.bot, self.prefix)
81
82 if not match.is_not_from_this_bot():
83 # Let's not talk to our-self
84 return
85
86 logger.debug(f'Message: {message}')
87 if not match.prefix():
88 logger.debug(f'{message} - did not match {self.prefix}')
89
90 if match.prefix():
91 try:
92 result_lines = await self._handle_match(match)
93 for line in result_lines:
94 await self.bot.api.send_text_message(
95 room.room_id, str(line))
96 except Exception as ex:
97 logger.warn(f'Caught exception: {str(ex)}')
98 dumb_msg_idx = len(str(ex)) % len(snark)
99 dumb_msg = snark[dumb_msg_idx]
100 await self.bot.api.send_text_message(
101 room.room_id, dumb_msg)
102
103 await self.bot.api.send_text_message(
104 room.room_id, str(ex))
105
106
107 async def _handle_match(self, match):
108 logger.debug(f'Try to match {str(match)}')
109
110 if match.command('setup'):
111 result = self.data.setup()
112 return [result]
113
114 if match.command('add'):
115 new = ' '.join(match.args()[1:])
116 goal_id = self.data.add_goal(new)
117 results = [f'Goal added with id {goal_id}']
118
119 goals = self.data.get_all_goals()
120 results.append('# Goals list...')
121 for goal in goals:
122 results.append(str(goal))
123
124 return results
125
126 if match.command('list'):
127 logger.debug('Asked to list current goals...')
128 goals = self.data.get_current_goals()
129 results = ['# Goals list...']
130 for goal in goals:
131 results.append(str(goal))
132 return results
133
134
135 if match.command('list.done'):
136 goals = self.data.get_done_goals()
137 results = ['# Completed Goals...']
138 for goal in goals:
139 results.append(str(goal))
140 return results
141
142 if match.command('task'):
143 new = ' '.join(match.args()[1:])
144 goal_id = self.data.quick_add_task(new)
145 goal,tasks = self.data.get_goal(goal_id)
146 results = pretty_print(goal, tasks)
147 return results
148
149 if match.command('add.vision'):
150 new = ' '.join(match.args()[1:])
151 result = self.data.add_vision(new)
152 return [f'Vision added with id {result}']
153
154 if match.command('print'):
155 if len(match.args()) > 1:
156 goal_id = int(match.args()[1])
157 else:
158 goal_id = self.data._get_pref_goal_id()
159
160 logger.debug(f'Searching for goal {goal_id}...')
161 goal,tasks = self.data.get_goal(goal_id)
162 results = pretty_print(goal, tasks)
163
164 return results
165
166
167 if match.command('print.vision'):
168 get_id = int(match.args()[1])
169 vision,goals = self.data.get_vision(get_id)
170 results = pretty_print(vision, goals)
171 return results
172
173 if match.command('close'):
174 goal_id = int(match.args()[1])
175 vision_id = self.data.complete_goal(goal_id)
176 vision,goals = self.data.get_vision(vision_id)
177 results = pretty_print(vision, goals)
178 return results
179
180
181 if match.command('clear'):
182 if len(match.args()) > 1:
183 goal_id = int(match.args()[1])
184 else:
185 goal_id = self.data._get_pref_goal_id()
186 _ = self.data.clear(goal_id)
187
188 goal,tasks = self.data.get_goal(goal_id)
189 results = pretty_print(goal, tasks)
190 return results
191
192
193 if match.command('start'):
194 goal_id = int(match.args()[1])
195 vision,goals = self.data.start_goal(goal_id)
196 results = pretty_print(vision, goals)
197 return results
198
199 if match.command('later'):
200 vision_id = int(match.args()[1])
201 self.data.put_off_vision(vision_id)
202 vision,goals = self.data.get_vision(vision_id)
203 results = pretty_print(vision, goals)
204 return results
205
206
207 if match.command('close.vision'):
208 vision_id = int(match.args()[1])
209 self.data.complete_vision(vision_id)
210 vision,goals = self.data.get_vision(vision_id)
211 results = pretty_print(vision, goals)
212 return results
213
214 if match.command('done'):
215 ids = match.args()[1:]
216 for task_id in ids:
217 goal_id = self.data.complete_task(int(task_id))
218 # Print the goal of the last closed task
219 goal,tasks = self.data.get_goal(goal_id)
220 results = pretty_print(goal, tasks)
221 return results
222
223 if match.command('dump'):
224 goals = self.data.get_all_goals()
225 results = ['# Everything ... ']
226 for goal in goals:
227 _,tasks = self.data.get_goal(goal.id)
228 details = pretty_print(goal, tasks)
229 results += details
230 return results
231
232
233 if match.command('list.later'):
234 goals = self.data.get_all_goals()
235 results = ['# All Goals ... ']
236 return results
237
238 if match.command('visions'):
239 items = self.data.get_all_visions()
240 results = ['# Visions']
241 if not items:
242 results.append('-- No current visions --')
243
244 for item in items:
245 results.append(item)
246 return results
247
248 if match.command('visionless'):
249 items = self.data.visionless()
250 results = ['# Goals with no vision']
251 if not items:
252 results.append('-- No visionless goals --')
253
254 for item in items:
255 results.append(item)
256 return results
257
258 if match.command('wins'):
259 items = self.data.wins()
260 results = ['# Wins']
261 if not items:
262 results.append('-- No wins yet --')
263
264 for item in items:
265 results.append(item)
266 return results
267
268
269
270 if match.command('set.vision'):
271 goal_id = int(match.args()[1])
272 vision_id = int(match.args()[2])
273 self.data.assign_vision(goal_id=goal_id, vision_id=vision_id)
274 vision,goals = self.data.get_vision(vision_id)
275 results = pretty_print(vision, goals)
276 return results
277
278
279 if match.command('rename'):
280 goal_id = int(match.args()[1])
281 name = ' '.join(match.args()[2:])
282 self.data.rename_goal(goal_id=goal_id, name=name)
283 goal,tasks = self.data.get_goal(goal_id)
284 results = pretty_print(goal, tasks)
285 return results
286
287 if match.command('remove'):
288 task_id = int(match.args()[1])
289 result = self.data.remove_task(task_id)
290 return [result]
291
292 if match.command('extra.help'):
293 return [ex_help]
294
295 # Help text
296 return [__doc__]
297
298
299