Skip to content

Commit

Permalink
add meetbot.fp.o format minutes/log catcher
Browse files Browse the repository at this point in the history
  • Loading branch information
cydrobolt committed May 23, 2015
1 parent 4e5b130 commit d6e5dae
Show file tree
Hide file tree
Showing 9 changed files with 251 additions and 84 deletions.
64 changes: 63 additions & 1 deletion mote/__init__.py
Expand Up @@ -16,11 +16,14 @@

import collections

import flask, peewee, random, string, pylibmc, json, util, os
import flask, peewee, random, string, pylibmc, json, util, os, re
import dateutil.parser, requests, collections
from bs4 import BeautifulSoup
from flask import Flask, render_template, request, url_for, session, redirect
from flask_fas_openid import fas_login_required, cla_plus_one_required, FAS
from util import RegexConverter

fn_search_regex = "(.*?)\.([0-9]{4}\-[0-9]{2}\-[0-9]{2})\-.*?\..*?\.(.*)"

try:
# if different config directory provided
Expand Down Expand Up @@ -48,27 +51,81 @@
app.config['FAS_OPENID_ENDPOINT'] = 'http://id.fedoraproject.org/'
app.config['FAS_CHECK_CERT'] = True
cwd = os.getcwd()
app.url_map.converters['regex'] = RegexConverter


with open(os.path.join(cwd, 'name_mappings.json')) as data_file:
name_mappings = json.load(data_file)

with open(os.path.join(cwd, 'category_mappings.json')) as data_file:
category_mappings = json.load(data_file)

def return_error(msg):
# generic error handler
# see return_error()
return render_template('error.html', error=msg)

@app.route('/', methods=['GET'])
def index():
# main page
return render_template('index.html')

@app.route('/post_auth', methods=['GET'])
@fas_login_required
def post_auth():
# after FedOAuth processes login
session['logged'] = True
return redirect(url_for('index'))

@app.route('/<meeting_channel>/<date>/<regex("(.*?)\.[0-9]{4}\-[0-9]{2}\-[0-9]{2}\-.*"):file_name>')
def catch_channel_logrequest(date, file_name, meeting_channel):
# catch standard log requests
# links referencing a meeting channel will be caught by this route
# e.g URLs provided by MeetBot at the end of a meeting, or links referencing
# a specific meeting channel, such as #fedora-meeting or #fedora-ambassadors
log_gtype = "channel"
m = re.search(fn_search_regex, file_name)
group_name = m.group(1) # name of channel, e.g fedora-meeting
meeting_date = date # date of log requested: YYYY-MM-DD
log_extension = m.group(3) # type of log requsted: log.html, html, or txt
log_type = util.get_meeting_type(log_extension)
if group_name != meeting_channel:
# if team name can be acquired, then
# treat the group as a team rather than a generic channel meeting
log_gtype = "team"
# group_name + meeting_date + requested_log_type
if log_type == "plain-text":
# redirect to plain-text result
built_url = "{}/{}/{}/{}".format(config.meetbot_prefix, meeting_channel, date, file_name)
return redirect(built_url)

return render_template("single-log.html", gtype=log_gtype, ltype=log_type, group=group_name, date=meeting_date, filename=file_name)

@app.route('/teams/<meeting_team>/<regex("(.*?)\.[0-9]{4}\-[0-9]{2}\-[0-9]{2}\-.*"):file_name>')
def catch_team_logrequest(file_name, meeting_team):
# catch team log requests
# links referencing a meeting team will be caught by this route
# these URLs are not provided by MeetBot at the end of a meeting
# one must manually inscribe this URL, although this is a rare occurence
# a specific meeting team, such as famna or infrastructure

m = re.search(fn_search_regex, file_name)
group_name = m.group(1) # name of team, e.g famna
meeting_date = m.group(2) # date of log requested: YYYY-MM-DD
log_extension = m.group(3) # type of log requsted: log.html, html, or txt
# group_name + meeting_date + requested_log_type
log_type = util.get_meeting_type(log_extension)
if log_type == "plain-text":
# redirect to plain-text result
built_url = "{}/teams/{}/{}".format(config.meetbot_prefix, meeting_team, file_name)
return redirect(built_url)
return render_template("single-log.html", gtype="team", ltype=log_type, group=group_name, date=meeting_date, filename=file_name)

@app.route('/request_logs', methods=['GET', 'POST'])
def request_logs():
# log request endpoint
# called when a date is specified and
# log filenames are requested
if request.method == "GET":
return return_error("400 Bad Request")
else:
Expand All @@ -93,6 +150,10 @@ def request_logs():

@app.route('/get_meeting_log', methods=["GET", "POST"])
def get_meeting_log():
# bs4 meeting log scraper
# called when "View Log" is pressed on sresults
# performs a GET on the meetbot log archive, then
# returns the log HTML to be displayed in the modal
if request.method == "GET":
return return_error("400 Bad Request")
else:
Expand All @@ -117,6 +178,7 @@ def get_meeting_log():

@app.route('/sresults', methods=['GET'])
def sresults():
# search result display
group_id = request.args.get('group_id', '')
group_type = request.args.get('type', '')
try:
Expand Down
28 changes: 16 additions & 12 deletions mote/static/css/mote.css
@@ -1,6 +1,9 @@
.center {
text-align: center;
}
.logdisplay {
padding-top: 20px;
}
.lev1 {
padding-left: 20px;
text-align: left;
Expand All @@ -17,10 +20,11 @@
padding-bottom: 35px;
}
/* Meetbot Display CSS */
.modal-body .details {
.logdisplay .details {
font-size: 12px;
font-weight:bold;
}
.single-log-minutes {}
.itemtype {
font-style: normal;
font-weight: bold;
Expand All @@ -31,19 +35,19 @@
.modal-dialog {
width: 80%;
}
.modal-body pre { white-space: pre-wrap; }
.modal-body pre { background: #f0f0f0; }
.logdisplay pre { white-space: pre-wrap; }
.logdisplay pre { background: #f0f0f0; }

.modal-body pre .tm { color: #007020 } /* time */
.modal-body pre .nk { color: #062873; font-weight: bold } /* nick, regular */
.modal-body pre .nka { color: #007020; font-weight: bold } /* action nick */
.modal-body pre .ac { color: #00A000 } /* action line */
.modal-body pre .hi { color: #4070a0 } /* hilights */
.logdisplay pre .tm { color: #007020 } /* time */
.logdisplay pre .nk { color: #062873; font-weight: bold } /* nick, regular */
.logdisplay pre .nka { color: #007020; font-weight: bold } /* action nick */
.logdisplay pre .ac { color: #00A000 } /* action line */
.logdisplay pre .hi { color: #4070a0 } /* hilights */
/* Things to make particular MeetBot commands stick out */
.modal-body pre .topic { color: #007020; font-weight: bold }
.modal-body pre .topicline { color: #000080; font-weight: bold }
.modal-body pre .cmd { color: #007020; font-weight: bold }
.modal-body pre .cmdline { font-weight: bold }
.logdisplay pre .topic { color: #007020; font-weight: bold }
.logdisplay pre .topicline { color: #000080; font-weight: bold }
.logdisplay pre .cmd { color: #007020; font-weight: bold }
.logdisplay pre .cmdline { font-weight: bold }
/* Bootstrap Fixes */
body {
padding-top: 60px;
Expand Down
83 changes: 83 additions & 0 deletions mote/static/js/search.js
@@ -0,0 +1,83 @@
/*
#
# Copyright © 2015 Chaoyi Zha <cydrobolt@fedoraproject.org>
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2, or (at your option) any later
# version. This program is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY expressed or implied, including the
# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details. You
# should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
*/

var $eventSelect = $(".tpa");

function formatRes (res) {
if (res.loading) return res.text;

var markup = '<div class="clearfix">' +
'<div>' +
'<h4>' + res.name + '</h4>' +
'<b>type: </b>' + res.type +
'</div>' +
'</div>';

if (res.description) {
markup += '<div>' + res.description + '</div>';
}
return markup;
}

function formatResSelection (res) {
return res.name;
}

$(".tpa").select2({
ajax: {
url: "/search_sugg",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term, // search term
};
},
processResults: function (data, page) {
// parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to
// alter the remote JSON data
return {
results: data.items
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
minimumInputLength: 1,
templateResult: formatRes,
templateSelection: formatResSelection
});
function redirectResults (group_id, type) {
window.location = "/sresults?group_id=" + group_id + "&type=" + type;
}

$eventSelect.on("select2:select", function (e) {
group_id = e.params.data.id;
group_type = e.params.data.type;
if (auto_search === true) {
redirectResults(group_id, group_type);
}
else {
window.group_id = group_id;
window.group_type = group_type;
}
});

$("#search").click(function () {
redirectResults(group_id, group_type);
});
45 changes: 45 additions & 0 deletions mote/static/js/single-log.js
@@ -0,0 +1,45 @@
/*
#
# Copyright © 2015 Chaoyi Zha <cydrobolt@fedoraproject.org>
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions
# of the GNU General Public License v.2, or (at your option) any later
# version. This program is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY expressed or implied, including the
# implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details. You
# should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
*/

function loadLogContents() {
// type == minutes or logs
var data = {
"group_type": current_group_type,
"group_id": current_group_id,
"date_stamp": current_date_stamp,
"file_name": current_fname,
};
$.ajax({
type: "POST",
url: "/get_meeting_log",
data: data,
dataType: "html"
}).done(function (res) {
var markup;
markup = res;
$('.logdisplay').html(markup);
return true;
});
return true;
}

$(function () {
loadLogContents();
if (window.current_log_type == "minutes") {
$(".logdisplay").addClass("single-log-minutes");
}
});

0 comments on commit d6e5dae

Please sign in to comment.