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:
parent
0ff1a65f6c
commit
3b87290132
45
README.rst
45
README.rst
|
@ -2,8 +2,8 @@
|
|||
OpenStack PTG Bot
|
||||
=================
|
||||
|
||||
ptgbot is the bot that PTG room moderators use to surface what's
|
||||
currently happening at the event. Room operators send messages to
|
||||
ptgbot is the bot that PTG track moderators use to surface what's
|
||||
currently happening at the event. Track moderators send messages to
|
||||
the bot, like::
|
||||
|
||||
#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 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.
|
||||
Commands follow the following format::
|
||||
|
||||
#ROOMNAME [now|next] TOPIC
|
||||
#ROOMNAME [color] CSS_COLOR_SPECIFIER
|
||||
#TRACK [now|next] TOPIC
|
||||
#TRACK [color] CSS_COLOR_SPECIFIER
|
||||
|
||||
Please note that:
|
||||
|
||||
* 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.
|
||||
* There can only be one "now" discussion 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
|
||||
wipes out any "next" entry for the same topic. You might want to refresh
|
||||
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
|
||||
form supported by the CSS attribute background-color.
|
||||
|
||||
|
@ -50,10 +50,10 @@ Example::
|
|||
#oslo color #42f4c5
|
||||
#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::
|
||||
|
||||
#ROOMNAME clean
|
||||
#TRACK clean
|
||||
|
||||
|
||||
Admin commands
|
||||
|
@ -62,19 +62,19 @@ Admin commands
|
|||
You have to be a channel operator (+o) to use admin commands.
|
||||
|
||||
~list
|
||||
List available room names
|
||||
List available track names
|
||||
|
||||
~add ROOM [ROOM..]
|
||||
Add new room name(s)
|
||||
~add TRACK [TRACK..]
|
||||
Add new track(s)
|
||||
|
||||
~del ROOM [ROOM..]
|
||||
Deletes room name(s)
|
||||
~del TRACK [TRACK..]
|
||||
Deletes track(s)
|
||||
|
||||
~clean ROOM [ROOM..]
|
||||
Removes active entries for specified room(s)
|
||||
~clean TRACK [TRACK..]
|
||||
Removes active entries for specified track(s)
|
||||
|
||||
~wipe
|
||||
Resets the database entirely (removes all defined rooms and entries)
|
||||
Resets the database entirely (removes all defined tracks and topics)
|
||||
|
||||
|
||||
Local testing
|
||||
|
@ -98,8 +98,9 @@ In one terminal, run the bot::
|
|||
|
||||
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
|
||||
|
||||
(note, the bot currently only takes commands from Freenode identified users)
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
<script id="PTGtemplate" type="text/x-handlebars-template">
|
||||
<style>
|
||||
{{#each colors as |color room|}}
|
||||
.{{room}} {
|
||||
{{#each colors as |color track|}}
|
||||
.{{track}} {
|
||||
background-color: {{color}};
|
||||
}
|
||||
{{/each}}
|
||||
|
@ -27,12 +27,12 @@
|
|||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><h3 class="panel-title">Currently playing...</h3></div>
|
||||
<table class="table">
|
||||
{{#each rooms as |room| }}
|
||||
{{#if (lookup @root.now room) }}
|
||||
{{#each tracks as |track| }}
|
||||
{{#if (lookup @root.now track) }}
|
||||
<tr>
|
||||
<td class="col-sm-1"><span class="label label-primary {{room}}">{{room}}</span></td>
|
||||
<td>{{#hashtag}}{{lookup @root.now room}}{{/hashtag}}</td>
|
||||
<td>{{lookup @root.location room}}</td>
|
||||
<td class="col-sm-1"><span class="label label-primary {{track}}">{{track}}</span></td>
|
||||
<td>{{#hashtag}}{{lookup @root.now track}}{{/hashtag}}</td>
|
||||
<td>{{lookup @root.location track}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
|
@ -43,12 +43,12 @@
|
|||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><h3 class="panel-title">Coming up next...</h3></div>
|
||||
<table class="table">
|
||||
{{#each rooms as |room| }}
|
||||
{{#if (lookup @root.next room) }}
|
||||
{{#each tracks as |track| }}
|
||||
{{#if (lookup @root.next track) }}
|
||||
<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>
|
||||
{{#each (lookup @root.next room) as |item|}}
|
||||
{{#each (lookup @root.next track) as |item|}}
|
||||
{{#hashtag}}{{item}}{{/hashtag}} <br/>
|
||||
{{/each}}
|
||||
</td>
|
||||
|
@ -59,7 +59,7 @@
|
|||
{{/each}}
|
||||
</table>
|
||||
</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>
|
||||
|
||||
|
|
|
@ -89,15 +89,15 @@ class PTGBot(irc.bot.SingleServerIRCBot):
|
|||
|
||||
def usage(self, channel):
|
||||
self.send(channel,
|
||||
"Format is '#ROOMNAME [ now ... | next ... "
|
||||
"Format is '#TRACK [ now ... | next ... "
|
||||
"| location ... | clean ]'")
|
||||
|
||||
def send_room_list(self, channel):
|
||||
rooms = self.data.list_rooms()
|
||||
if rooms:
|
||||
self.send(channel, "Active rooms: %s" % str.join(' ', rooms))
|
||||
def send_track_list(self, channel):
|
||||
tracks = self.data.list_tracks()
|
||||
if tracks:
|
||||
self.send(channel, "Active tracks: %s" % str.join(' ', tracks))
|
||||
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):
|
||||
if not self.identify_msg_cap:
|
||||
|
@ -121,24 +121,24 @@ class PTGBot(irc.bot.SingleServerIRCBot):
|
|||
self.usage(chan)
|
||||
return
|
||||
|
||||
room = words[0][1:].lower()
|
||||
if not self.data.is_room_valid(room):
|
||||
self.send(chan, "%s: unknown room '%s'" % (nick, room))
|
||||
self.send_room_list(chan)
|
||||
track = words[0][1:].lower()
|
||||
if not self.data.is_track_valid(track):
|
||||
self.send(chan, "%s: unknown track '%s'" % (nick, track))
|
||||
self.send_track_list(chan)
|
||||
return
|
||||
|
||||
adverb = words[1].lower()
|
||||
session = str.join(' ', words[2:])
|
||||
if adverb == 'now':
|
||||
self.data.add_now(room, session)
|
||||
self.data.add_now(track, session)
|
||||
elif adverb == 'next':
|
||||
self.data.add_next(room, session)
|
||||
self.data.add_next(track, session)
|
||||
elif adverb == 'clean':
|
||||
self.data.clean_rooms([room])
|
||||
self.data.clean_tracks([track])
|
||||
elif adverb == 'color':
|
||||
self.data.add_color(room, session)
|
||||
self.data.add_color(track, session)
|
||||
elif adverb == 'location':
|
||||
self.data.add_location(room, session)
|
||||
self.data.add_location(track, session)
|
||||
else:
|
||||
self.send(chan, "%s: unknown directive '%s'" % (nick, adverb))
|
||||
self.usage(chan)
|
||||
|
@ -153,13 +153,13 @@ class PTGBot(irc.bot.SingleServerIRCBot):
|
|||
if command == 'wipe':
|
||||
self.data.wipe()
|
||||
elif command == 'list':
|
||||
self.send_room_list(chan)
|
||||
self.send_track_list(chan)
|
||||
return
|
||||
elif command in ('clean', 'add', 'del'):
|
||||
if len(words) < 2:
|
||||
self.send(chan, "this command takes one or more arguments")
|
||||
return
|
||||
getattr(self.data, command + '_rooms')(words[1:])
|
||||
getattr(self.data, command + '_tracks')(words[1:])
|
||||
else:
|
||||
self.send(chan, "%s: unknown command '%s'" % (nick, command))
|
||||
return
|
||||
|
|
64
ptgbot/db.py
64
ptgbot/db.py
|
@ -21,7 +21,7 @@ import datetime
|
|||
|
||||
class PTGDataBase():
|
||||
|
||||
BASE = {'rooms': [], 'now': {}, 'next': {}, 'colors': {},
|
||||
BASE = {'tracks': [], 'now': {}, 'next': {}, 'colors': {},
|
||||
'location': {}}
|
||||
|
||||
def __init__(self, filename):
|
||||
|
@ -33,52 +33,52 @@ class PTGDataBase():
|
|||
self.data = self.BASE
|
||||
self.save()
|
||||
|
||||
def add_now(self, room, session):
|
||||
self.data['now'][room] = session
|
||||
if room in self.data['next']:
|
||||
del self.data['next'][room]
|
||||
def add_now(self, track, session):
|
||||
self.data['now'][track] = session
|
||||
if track in self.data['next']:
|
||||
del self.data['next'][track]
|
||||
self.save()
|
||||
|
||||
def add_color(self, room, color):
|
||||
self.data['colors'][room] = color
|
||||
def add_color(self, track, color):
|
||||
self.data['colors'][track] = color
|
||||
self.save()
|
||||
|
||||
def add_location(self, room, location):
|
||||
def add_location(self, track, location):
|
||||
if 'location' not in self.data:
|
||||
self.data['location'] = {}
|
||||
self.data['location'][room] = location
|
||||
self.data['location'][track] = location
|
||||
self.save()
|
||||
|
||||
def add_next(self, room, session):
|
||||
if room not in self.data['next']:
|
||||
self.data['next'][room] = []
|
||||
self.data['next'][room].append(session)
|
||||
def add_next(self, track, session):
|
||||
if track not in self.data['next']:
|
||||
self.data['next'][track] = []
|
||||
self.data['next'][track].append(session)
|
||||
self.save()
|
||||
|
||||
def is_room_valid(self, room):
|
||||
return room in self.data['rooms']
|
||||
def is_track_valid(self, track):
|
||||
return track in self.data['tracks']
|
||||
|
||||
def list_rooms(self):
|
||||
return sorted(self.data['rooms'])
|
||||
def list_tracks(self):
|
||||
return sorted(self.data['tracks'])
|
||||
|
||||
def add_rooms(self, rooms):
|
||||
for room in rooms:
|
||||
if room not in self.data['rooms']:
|
||||
self.data['rooms'].append(room)
|
||||
def add_tracks(self, tracks):
|
||||
for track in tracks:
|
||||
if track not in self.data['tracks']:
|
||||
self.data['tracks'].append(track)
|
||||
self.save()
|
||||
|
||||
def del_rooms(self, rooms):
|
||||
for room in rooms:
|
||||
if room in self.data['rooms']:
|
||||
self.data['rooms'].remove(room)
|
||||
def del_tracks(self, tracks):
|
||||
for track in tracks:
|
||||
if track in self.data['tracks']:
|
||||
self.data['tracks'].remove(track)
|
||||
self.save()
|
||||
|
||||
def clean_rooms(self, rooms):
|
||||
for room in rooms:
|
||||
if room in self.data['now']:
|
||||
del self.data['now'][room]
|
||||
if room in self.data['next']:
|
||||
del self.data['next'][room]
|
||||
def clean_tracks(self, tracks):
|
||||
for track in tracks:
|
||||
if track in self.data['now']:
|
||||
del self.data['now'][track]
|
||||
if track in self.data['next']:
|
||||
del self.data['next'][track]
|
||||
self.save()
|
||||
|
||||
def wipe(self):
|
||||
|
@ -88,6 +88,6 @@ class PTGDataBase():
|
|||
def save(self):
|
||||
timestamp = datetime.datetime.now()
|
||||
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:
|
||||
json.dump(self.data, fp)
|
||||
|
|
Loading…
Reference in New Issue