Rooms are now called Tracks

Since a given theme/team may meet in several different
locations during the week, let's call that a "track"
rather than a "room" (which was a confusing concept
since we had "location" as well).

Change-Id: I0978f4c8b33954f53698d8a058b9a802556e56c1
This commit is contained in:
Thierry Carrez 2017-11-29 17:55:43 +01:00
parent 0ff1a65f6c
commit 3b87290132
4 changed files with 84 additions and 83 deletions

View File

@ -2,8 +2,8 @@
OpenStack PTG Bot OpenStack PTG Bot
================= =================
ptgbot is the bot that PTG room moderators use to surface what's ptgbot is the bot that PTG track moderators use to surface what's
currently happening at the event. Room operators send messages to currently happening at the event. Track moderators send messages to
the bot, like:: the bot, like::
#swift now discussing ring balancing #swift now discussing ring balancing
@ -12,26 +12,26 @@ and from that information the bot builds a static webpage with discussion
topics currently discussed ("now") and an indicative set of discussion topics currently discussed ("now") and an indicative set of discussion
topics coming up next ("next"). topics coming up next ("next").
Room operators commands Track moderators commands
======================= =========================
You have to have voice in the channel (+v) to send commands to the ptgbot. You have to have voice in the channel (+v) to send commands to the ptgbot.
Commands follow the following format:: Commands follow the following format::
#ROOMNAME [now|next] TOPIC #TRACK [now|next] TOPIC
#ROOMNAME [color] CSS_COLOR_SPECIFIER #TRACK [color] CSS_COLOR_SPECIFIER
Please note that: Please note that:
* There can only be one "now" topic at a time. If multiple topics are * There can only be one "now" discussion topic at a time. If multiple
discussed at the same time in various corners of the room, they should topics are discussed at the same time in various corners of the room,
all be specified in a single "now" command. they should all be specified in a single "now" command.
* In order to ensure that information is current, entering a "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 wipes out any "next" entry for the same topic. You might want to refresh
those after entering a "now" topic. those after entering a "now" topic.
* The color command only sets the background color for the room * The color command only sets the background color for the track
name. The foreground is always white. Colors can be specified in any name. The foreground is always white. Colors can be specified in any
form supported by the CSS attribute background-color. form supported by the CSS attribute background-color.
@ -50,10 +50,10 @@ Example::
#oslo color #42f4c5 #oslo color #42f4c5
#oslo next after lunch we plan to discuss auto-generating config reference docs #oslo next after lunch we plan to discuss auto-generating config reference docs
You can also remove all entries related to your room by issuing the following You can also remove all entries related to your track by issuing the following
command:: command::
#ROOMNAME clean #TRACK clean
Admin commands Admin commands
@ -62,19 +62,19 @@ Admin commands
You have to be a channel operator (+o) to use admin commands. You have to be a channel operator (+o) to use admin commands.
~list ~list
List available room names List available track names
~add ROOM [ROOM..] ~add TRACK [TRACK..]
Add new room name(s) Add new track(s)
~del ROOM [ROOM..] ~del TRACK [TRACK..]
Deletes room name(s) Deletes track(s)
~clean ROOM [ROOM..] ~clean TRACK [TRACK..]
Removes active entries for specified room(s) Removes active entries for specified track(s)
~wipe ~wipe
Resets the database entirely (removes all defined rooms and entries) Resets the database entirely (removes all defined tracks and topics)
Local testing Local testing
@ -98,8 +98,9 @@ In one terminal, run the bot::
tox -evenv -- ptgbot -d config.json tox -evenv -- ptgbot -d config.json
Join that channel and give a command to the bot:: Join that channel and give commands to the bot::
~add swift
#swift now discussing ring placement #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,8 +18,8 @@
<script id="PTGtemplate" type="text/x-handlebars-template"> <script id="PTGtemplate" type="text/x-handlebars-template">
<style> <style>
{{#each colors as |color room|}} {{#each colors as |color track|}}
.{{room}} { .{{track}} {
background-color: {{color}}; background-color: {{color}};
} }
{{/each}} {{/each}}
@ -27,12 +27,12 @@
<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>
<table class="table"> <table class="table">
{{#each rooms as |room| }} {{#each tracks as |track| }}
{{#if (lookup @root.now room) }} {{#if (lookup @root.now track) }}
<tr> <tr>
<td class="col-sm-1"><span class="label label-primary {{room}}">{{room}}</span></td> <td class="col-sm-1"><span class="label label-primary {{track}}">{{track}}</span></td>
<td>{{#hashtag}}{{lookup @root.now room}}{{/hashtag}}</td> <td>{{#hashtag}}{{lookup @root.now track}}{{/hashtag}}</td>
<td>{{lookup @root.location room}}</td> <td>{{lookup @root.location track}}</td>
</tr> </tr>
{{/if}} {{/if}}
{{else}} {{else}}
@ -43,12 +43,12 @@
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><h3 class="panel-title">Coming up next...</h3></div> <div class="panel-heading"><h3 class="panel-title">Coming up next...</h3></div>
<table class="table"> <table class="table">
{{#each rooms as |room| }} {{#each tracks as |track| }}
{{#if (lookup @root.next room) }} {{#if (lookup @root.next track) }}
<tr> <tr>
<td class="col-sm-1"><span class="label label-primary {{room}}">{{room}}</span></td> <td class="col-sm-1"><span class="label label-primary {{track}}">{{track}}</span></td>
<td> <td>
{{#each (lookup @root.next room) as |item|}} {{#each (lookup @root.next track) as |item|}}
{{#hashtag}}{{item}}{{/hashtag}} <br/> {{#hashtag}}{{item}}{{/hashtag}} <br/>
{{/each}} {{/each}}
</td> </td>
@ -59,7 +59,7 @@
{{/each}} {{/each}}
</table> </table>
</div> </div>
<p class="text-muted">Content on this page is being driven by room operators through the openstackptg bot on the #openstack-ptg IRC channel. It was last refreshed on {{timestamp}}.</p> <p class="text-muted">Content on this page is being driven by track moderators through the openstackptg bot on the #openstack-ptg IRC channel. It was last refreshed on {{timestamp}}.</p>
</script> </script>

View File

@ -89,15 +89,15 @@ class PTGBot(irc.bot.SingleServerIRCBot):
def usage(self, channel): def usage(self, channel):
self.send(channel, self.send(channel,
"Format is '#ROOMNAME [ now ... | next ... " "Format is '#TRACK [ now ... | next ... "
"| location ... | clean ]'") "| location ... | clean ]'")
def send_room_list(self, channel): def send_track_list(self, channel):
rooms = self.data.list_rooms() tracks = self.data.list_tracks()
if rooms: if tracks:
self.send(channel, "Active rooms: %s" % str.join(' ', rooms)) self.send(channel, "Active tracks: %s" % str.join(' ', tracks))
else: else:
self.send(channel, "There are no active rooms defined yet") self.send(channel, "There are no active tracks defined yet")
def on_pubmsg(self, c, e): def on_pubmsg(self, c, e):
if not self.identify_msg_cap: if not self.identify_msg_cap:
@ -121,24 +121,24 @@ class PTGBot(irc.bot.SingleServerIRCBot):
self.usage(chan) self.usage(chan)
return return
room = words[0][1:].lower() track = words[0][1:].lower()
if not self.data.is_room_valid(room): if not self.data.is_track_valid(track):
self.send(chan, "%s: unknown room '%s'" % (nick, room)) self.send(chan, "%s: unknown track '%s'" % (nick, track))
self.send_room_list(chan) self.send_track_list(chan)
return return
adverb = words[1].lower() adverb = words[1].lower()
session = str.join(' ', words[2:]) session = str.join(' ', words[2:])
if adverb == 'now': if adverb == 'now':
self.data.add_now(room, session) self.data.add_now(track, session)
elif adverb == 'next': elif adverb == 'next':
self.data.add_next(room, session) self.data.add_next(track, session)
elif adverb == 'clean': elif adverb == 'clean':
self.data.clean_rooms([room]) self.data.clean_tracks([track])
elif adverb == 'color': elif adverb == 'color':
self.data.add_color(room, session) self.data.add_color(track, session)
elif adverb == 'location': elif adverb == 'location':
self.data.add_location(room, session) self.data.add_location(track, session)
else: 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)
@ -153,13 +153,13 @@ class PTGBot(irc.bot.SingleServerIRCBot):
if command == 'wipe': if command == 'wipe':
self.data.wipe() self.data.wipe()
elif command == 'list': elif command == 'list':
self.send_room_list(chan) self.send_track_list(chan)
return return
elif command in ('clean', 'add', 'del'): elif command in ('clean', 'add', 'del'):
if len(words) < 2: if len(words) < 2:
self.send(chan, "this command takes one or more arguments") self.send(chan, "this command takes one or more arguments")
return return
getattr(self.data, command + '_rooms')(words[1:]) getattr(self.data, command + '_tracks')(words[1:])
else: else:
self.send(chan, "%s: unknown command '%s'" % (nick, command)) self.send(chan, "%s: unknown command '%s'" % (nick, command))
return return

View File

@ -21,7 +21,7 @@ import datetime
class PTGDataBase(): class PTGDataBase():
BASE = {'rooms': [], 'now': {}, 'next': {}, 'colors': {}, BASE = {'tracks': [], 'now': {}, 'next': {}, 'colors': {},
'location': {}} 'location': {}}
def __init__(self, filename): def __init__(self, filename):
@ -33,52 +33,52 @@ class PTGDataBase():
self.data = self.BASE self.data = self.BASE
self.save() self.save()
def add_now(self, room, session): def add_now(self, track, session):
self.data['now'][room] = session self.data['now'][track] = session
if room in self.data['next']: if track in self.data['next']:
del self.data['next'][room] del self.data['next'][track]
self.save() self.save()
def add_color(self, room, color): def add_color(self, track, color):
self.data['colors'][room] = color self.data['colors'][track] = color
self.save() self.save()
def add_location(self, room, location): def add_location(self, track, location):
if 'location' not in self.data: if 'location' not in self.data:
self.data['location'] = {} self.data['location'] = {}
self.data['location'][room] = location self.data['location'][track] = location
self.save() self.save()
def add_next(self, room, session): def add_next(self, track, session):
if room not in self.data['next']: if track not in self.data['next']:
self.data['next'][room] = [] self.data['next'][track] = []
self.data['next'][room].append(session) self.data['next'][track].append(session)
self.save() self.save()
def is_room_valid(self, room): def is_track_valid(self, track):
return room in self.data['rooms'] return track in self.data['tracks']
def list_rooms(self): def list_tracks(self):
return sorted(self.data['rooms']) return sorted(self.data['tracks'])
def add_rooms(self, rooms): def add_tracks(self, tracks):
for room in rooms: for track in tracks:
if room not in self.data['rooms']: if track not in self.data['tracks']:
self.data['rooms'].append(room) self.data['tracks'].append(track)
self.save() self.save()
def del_rooms(self, rooms): def del_tracks(self, tracks):
for room in rooms: for track in tracks:
if room in self.data['rooms']: if track in self.data['tracks']:
self.data['rooms'].remove(room) self.data['tracks'].remove(track)
self.save() self.save()
def clean_rooms(self, rooms): def clean_tracks(self, tracks):
for room in rooms: for track in tracks:
if room in self.data['now']: if track in self.data['now']:
del self.data['now'][room] del self.data['now'][track]
if room in self.data['next']: if track in self.data['next']:
del self.data['next'][room] del self.data['next'][track]
self.save() self.save()
def wipe(self): def wipe(self):
@ -88,6 +88,6 @@ class PTGDataBase():
def save(self): def save(self):
timestamp = datetime.datetime.now() timestamp = datetime.datetime.now()
self.data['timestamp'] = '{:%Y-%m-%d %H:%M:%S}'.format(timestamp) self.data['timestamp'] = '{:%Y-%m-%d %H:%M:%S}'.format(timestamp)
self.data['rooms'] = sorted(self.data['rooms']) self.data['tracks'] = sorted(self.data['tracks'])
with open(self.filename, 'w') as fp: with open(self.filename, 'w') as fp:
json.dump(self.data, fp) json.dump(self.data, fp)