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