Implement simpler API

Move from at/until to now/next API for the bot, which is
simpler to explain. Adapt rendering so that it supports
multiple "next" entries.
This commit is contained in:
Thierry Carrez 2017-05-22 14:59:54 +02:00
parent 42339394d5
commit 465f277ccb
4 changed files with 68 additions and 42 deletions

View File

@ -3,12 +3,30 @@ OpenStack PTG Bot
================= =================
ptgbot is the bot that PTG room moderators use to surface what's ptgbot is the bot that PTG room moderators use to surface what's
currently happening at the event. It builds a static webpage that currently happening at the event. Commands follow the following format:
attendees can query for up-to-date information.
Commands follow the following format: @ROOMNAME [now|next] TIME TOPIC
@ROOMNAME [until|at] TIME TOPIC From that information the bot builds a static webpage with discussion
topics currently discussed ("now") and an indicative set of discussion
topics coming up next ("next").
NB:
* There can only be one "now" topic at a time. If multiple topics are
discussed at the same time in various corners of the room, they should
all be specified in a single "now" command.
* In order to ensure that information is current, entering a "now" command
wipes out any "next" entry for the same room. You might want to refresh
those after entering a "now" topic.
Example::
#swift now discussing ring placement
#swift next at 2pm we plan to discuss #glance support
#swift next around 3pm we plan to cover cold storage features
...
#swift now discussing #glance support, come over!
#swift next at 3pm we plan to cover cold storage features
Testing Testing
@ -28,13 +46,13 @@ port=6667
channels=testptg channels=testptg
db=html/ptg.json db=html/ptg.json
In one terminal, run the bot: In one terminal, run the bot::
tox -evenv -- ptgbot -d config.ini tox -evenv -- ptgbot -d config.ini
Join that channel and give a command to the bot: Join that channel and give a command to the bot::
@swift until 10:00 Discussing ring internals @swift now discussing ring placement
(note, the bot currently only takes commands from Freenode identified users) (note, the bot currently only takes commands from Freenode identified users)

View File

@ -18,20 +18,34 @@
<script id="PTGtemplate" type="text/x-handlebars-template"> <script id="PTGtemplate" type="text/x-handlebars-template">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">Currently playing</h3></div> <div class="panel-heading"><h3 class="panel-title">Currently playing...</h3></div>
<ul class="list-group"> <table class="table">
{{#each until}} {{#each now}}
<li class="list-group-item"><span class="label label-primary">{{@key}}</span> {{this.msg}}</li> <tr>
<td class="col-sm-1"><span class="label label-primary">{{@key}}</span></td>
<td>{{this}}</td>
</tr>
{{else}}
<tr><td><small><i>Nothing yet</i></small><td></tr>
{{/each}} {{/each}}
</ul> </table>
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">Next discussions</h3></div> <div class="panel-heading"><h3 class="panel-title">Coming up next...</h3></div>
<ul class="list-group"> <table class="table">
{{#each at}} {{#each next as |sessions room|}}
<li class="list-group-item"><span class="label label-primary">{{@key}}</span> {{this.msg}}</li> <tr>
<td class="col-sm-1"><span class="label label-primary">{{room}}</span></td>
<td>
{{#each sessions}}
{{ this }}<br/>
{{/each}}
</td>
</tr>
{{else}}
<tr><td><small><i>Nothing yet</i></small><td></tr>
{{/each}} {{/each}}
</ul> </table>
</div> </div>
</script> </script>

View File

@ -88,7 +88,7 @@ class PTGBot(irc.bot.SingleServerIRCBot):
self.identify_msg_cap = True self.identify_msg_cap = True
def usage(self, channel): def usage(self, channel):
self.send(channel, "Format is '@ROOM [until|at] HOUR SESSION'") self.send(channel, "Format is '@ROOM [now|next] SESSION'")
def on_pubmsg(self, c, e): def on_pubmsg(self, c, e):
if not self.identify_msg_cap: if not self.identify_msg_cap:
@ -100,26 +100,23 @@ class PTGBot(irc.bot.SingleServerIRCBot):
msg = e.arguments[0][1:] msg = e.arguments[0][1:]
chan = e.target chan = e.target
if msg.startswith('@') and auth: if msg.startswith('#') and auth:
words = msg.split() words = msg.split()
if len(words) < 4: if len(words) < 3:
self.send(chan, "%s: Incorrect number of arguments" % (nick,)) self.send(chan, "%s: Incorrect number of arguments" % (nick,))
self.usage(chan) self.usage(chan)
return return
room = words[0][1:].lower() room = words[0][1:].lower()
# TODO: Add test for room/day/person match # TODO: Add test for room/day/person match
adverb = words[1].lower() adverb = words[1].lower()
if adverb not in ['until', 'at']: session = str.join(' ', words[2:])
if adverb == 'now':
self.data.add_now(room, session)
elif adverb == 'next':
self.data.add_next(room, session)
else:
self.send(chan, "%s: unknown directive '%s'" % (nick, adverb)) self.send(chan, "%s: unknown directive '%s'" % (nick, adverb))
self.usage(chan) self.usage(chan)
return
hour = words[2]
# TODO: Add test for hour format
session = str.join(' ', words[3:])
msg = '(%s %s) %s' % (adverb, hour, session)
self.data.add(room, adverb, hour, msg)
return
def send(self, channel, msg): def send(self, channel, msg):
self.connection.privmsg(channel, msg) self.connection.privmsg(channel, msg)

View File

@ -26,28 +26,25 @@ class PTGDataBase():
with open(filename, 'r') as fp: with open(filename, 'r') as fp:
self.data = json.load(fp) self.data = json.load(fp)
else: else:
self.data = {} self.data = {'now': {}, 'next': {}}
def add(self, room, adverb, hour, msg): def add_now(self, room, session):
if adverb not in self.data: self.data['now'][room] = session
self.data[adverb] = {} if room in self.data['next']:
self.data[adverb][room] = {'msg': msg, 'expiry': hour} del self.data['next'][room]
self.save() self.save()
def expire(self, now): def add_next(self, room, session):
newdata = [] if room not in self.data['next']:
for room, infos in self.data.items(): self.data['next'][room] = []
for info, session in infos: self.data['next'][room].append(session)
if session['expiry'] > now: self.save()
newdata[room][info] = session
self.data = newdata
def from_ethercalc(self): def from_ethercalc(self):
# TODO: Load from ethercalc # TODO: Load from ethercalc
pass pass
def save(self): def save(self):
# self.expire()
# self.from_ethercalc() # self.from_ethercalc()
with open(self.filename, 'w') as fp: with open(self.filename, 'w') as fp:
json.dump(self.data, fp) json.dump(self.data, fp)