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