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
currently happening at the event. It builds a static webpage that
attendees can query for up-to-date information.
currently happening at the event. Commands follow the following format:
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
@ -28,13 +46,13 @@ port=6667
channels=testptg
db=html/ptg.json
In one terminal, run the bot:
In one terminal, run the bot::
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)

View File

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

View File

@ -88,7 +88,7 @@ class PTGBot(irc.bot.SingleServerIRCBot):
self.identify_msg_cap = True
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):
if not self.identify_msg_cap:
@ -100,26 +100,23 @@ class PTGBot(irc.bot.SingleServerIRCBot):
msg = e.arguments[0][1:]
chan = e.target
if msg.startswith('@') and auth:
if msg.startswith('#') and auth:
words = msg.split()
if len(words) < 4:
if len(words) < 3:
self.send(chan, "%s: Incorrect number of arguments" % (nick,))
self.usage(chan)
return
room = words[0][1:].lower()
# TODO: Add test for room/day/person match
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.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):
self.connection.privmsg(channel, msg)

View File

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