diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Gemfile | 10 | ||||
-rw-r--r-- | Gemfile.lock | 52 | ||||
-rw-r--r-- | ag-web.rb | 160 | ||||
-rw-r--r-- | config.ru | 3 | ||||
-rw-r--r-- | config.yml.default | 11 | ||||
-rw-r--r-- | lib/helpers.rb | 67 | ||||
-rw-r--r-- | lib/index.rb | 122 | ||||
-rw-r--r-- | public/css/main.css | 66 | ||||
-rw-r--r-- | public/js/quoting.js | 30 | ||||
-rw-r--r-- | views/index.erb | 39 | ||||
-rw-r--r-- | views/layout.erb | 123 | ||||
-rw-r--r-- | views/listindex.erb | 15 | ||||
-rw-r--r-- | views/listmonth.erb | 24 | ||||
-rw-r--r-- | views/message.erb | 71 | ||||
-rw-r--r-- | views/pagination.erb | 31 | ||||
-rw-r--r-- | views/report.erb | 75 | ||||
-rw-r--r-- | views/reportmail.erb | 19 | ||||
-rw-r--r-- | views/reportsent.erb | 5 | ||||
-rw-r--r-- | views/views.erb | 4 |
20 files changed, 928 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e9abc7f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +config.yml
\ No newline at end of file @@ -0,0 +1,10 @@ +source 'https://rubygems.org' + +gem 'sinatra' +gem 'sinatra-partial' +gem 'json' +gem 'redcarpet' +gem 'thin' +gem 'elasticsearch' +gem 'rinku' +gem 'pony'
\ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..eba5798 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,52 @@ +GEM + remote: https://rubygems.org/ + specs: + daemons (1.1.9) + elasticsearch (1.0.6) + elasticsearch-api (= 1.0.6) + elasticsearch-transport (= 1.0.6) + elasticsearch-api (1.0.6) + multi_json + elasticsearch-transport (1.0.6) + faraday + multi_json + eventmachine (1.0.4) + faraday (0.9.1) + multipart-post (>= 1.2, < 3) + json (1.8.2) + mail (2.6.3) + mime-types (>= 1.16, < 3) + mime-types (2.4.3) + multi_json (1.10.1) + multipart-post (2.0.0) + pony (1.11) + mail (>= 2.0) + rack (1.6.0) + rack-protection (1.5.3) + rack + redcarpet (3.2.2) + rinku (1.7.3) + sinatra (1.4.5) + rack (~> 1.4) + rack-protection (~> 1.4) + tilt (~> 1.3, >= 1.3.4) + sinatra-partial (0.4.0) + sinatra + thin (1.6.3) + daemons (~> 1.0, >= 1.0.9) + eventmachine (~> 1.0) + rack (~> 1.0) + tilt (1.4.1) + +PLATFORMS + ruby + +DEPENDENCIES + elasticsearch + json + pony + redcarpet + rinku + sinatra + sinatra-partial + thin diff --git a/ag-web.rb b/ag-web.rb new file mode 100644 index 0000000..850d1db --- /dev/null +++ b/ag-web.rb @@ -0,0 +1,160 @@ +# /usr/bin/env ruby +# AgWeb -- displaying all the 'golden' flamewars on -dev +# Alex Legler <a3li@gentoo.org> +# AGPLv3 + +require 'bundler/setup' +require 'yaml' +require 'sinatra' +require 'sinatra/partial' +require 'elasticsearch' +require 'date' +require 'pony' + +require_relative 'lib/index.rb' +require_relative 'lib/helpers.rb' + +configure do + set :partial_template_engine, :erb + mime_type :atom, 'application/atom+xml' +end + +$es = Elasticsearch::Client.new(log: false) +$es.transport.reload_connections! + +$config = YAML.load_file('config.yml') + +$valid_lists = %w[www-redesign gentoo-alt gentoo-dev gentoo-amd64] + +get '/:list/report/:msgid' do + return unless list_check + + begin + result = get_message(params[:list], params[:msgid]) + + if result['hits']['total'] == 0 + status 404 + body "Message not found." + return + end + + result_data = result['hits']['hits'].first + @title = "Report %s - %s" % [h(result_data['_source']['subject']), params[:list]] + + erb :report, locals: { message: result_data, list: params[:list] } + rescue Exception => e + $stderr.puts e.to_s + status 503 + end +end + +post '/report' do + return unless list_check + + begin + result = get_message(params[:list], params[:msgid]) + + if result['hits']['total'] == 0 + status 404 + body "Message not found." + return + end + + result_data = result['hits']['hits'].first + @title = "Report %s - %s" % [h(result_data['_source']['subject']), params[:list]] + + msg = '' + if params[:captcha] == $config['report_captcha'] + Pony.mail( + to: $config['report_addr'], + from: 'archives.gentoo.org <postmaster@gentoo.org>', + subject: "Reported Message on #{params[:list]}: #{result_data['_source']['subject']}", + body: erb(:reportmail, locals: { message: result_data, list: params[:list] }, layout: false) + ) + msg = 'Thanks for your report.' + else + msg = 'No, Larry does not make that sound (Invalid CAPTCHA). Report not sent.' + end + + erb :reportsent, locals: { message: result_data, list: params[:list], msg: msg } + rescue Exception => e + $stderr.puts e.to_s + status 503 + end +end + +get '/:list/' do + return unless list_check + + begin + result = get_month_listing(params[:list]) + @title = params[:list] + current_monthint = to_monthint(Date.today.year, Date.today.month) + puts current_monthint + + erb :listindex, locals: { results: result, list: params[:list], current_monthint: current_monthint } + rescue => e + $stderr.puts e.to_s + status 503 + end +end + +get '/:list/threads/:year-:month/:page?' do + return unless list_check + + begin + @title = params[:list] + current_page = [(params[:page] || 1).to_i, 1].max + result = threads_in_month(params[:list], params[:year], params[:month], current_page) + max_pages = (result['hits']['total'].to_f / PER_PAGE).ceil + + erb :listmonth, locals: { results: result, list: params[:list], current_page: current_page, max_pages: max_pages, mode: :threads } + rescue => e + $stderr.puts e.to_s + status 503 + end +end + +get '/:list/messages/:year-:month/:page?' do + return unless list_check + + begin + @title = params[:list] + current_page = [(params[:page] || 1).to_i, 1].max + result = messages_in_month(params[:list], params[:year], params[:month], current_page) + max_pages = (result['hits']['total'].to_f / PER_PAGE).ceil + + erb :listmonth, locals: { results: result, list: params[:list], current_page: current_page, max_pages: max_pages, mode: :messages } + rescue => e + $stderr.puts e.to_s + status 503 + end +end + +get '/:list/message/:msgid' do + return unless list_check + + begin + result = get_message(params[:list], params[:msgid]) + + if result['hits']['total'] == 0 + status 404 + body "Message not found." + return + end + + result_data = result['hits']['hits'].first + @title = "%s - %s" % [h(result_data['_source']['subject']), params[:list]] + parent_data = get_parent_data(params[:list], result_data['_source']['parent']) + child_data = get_child_data(params[:list], params[:msgid]) + + erb :message, locals: { message: result_data, list: params[:list], parent: parent_data, children: child_data } + rescue Exception => e + $stderr.puts e.to_s + status 503 + end +end + +get '/' do + erb :index +end
\ No newline at end of file diff --git a/config.ru b/config.ru new file mode 100644 index 0000000..e9d20b7 --- /dev/null +++ b/config.ru @@ -0,0 +1,3 @@ +require File.expand_path '../ag-web.rb', __FILE__ + +run Sinatra::Application diff --git a/config.yml.default b/config.yml.default new file mode 100644 index 0000000..4e87592 --- /dev/null +++ b/config.yml.default @@ -0,0 +1,11 @@ +--- +active_lists: + - gentoo-alpha + - gentoo-amd64 +frozen_lists: + - www-redesign +report_addr: 'devnull@example.com' +report_captcha: 'bird' +report_captcha_q: 'What is the word?' +report_captcha_hint: 'everybody knows about the word' +base_url: 'http://archives.gentoo.org/'
\ No newline at end of file diff --git a/lib/helpers.rb b/lib/helpers.rb new file mode 100644 index 0000000..fe0083a --- /dev/null +++ b/lib/helpers.rb @@ -0,0 +1,67 @@ +require 'date' +require 'rinku' + +helpers do + def list_check + unless $config['active_lists'].include?(params[:list]) or $config['frozen_lists'].include?(params[:list]) + status 404 + body "List not found" + return false + end + + true + end + + def monthint_to_link(monthint) + date = DateTime.parse("%s-%s-01" % [monthint[0..3], monthint[4..5]]) + + "<a href=\"threads/%s/\">%s</a>" % [date.strftime('%Y-%m'), date.strftime('%Y %B')] + end + + def date_format(date) + DateTime.iso8601(date).rfc2822 + end + + def to_monthint(year, month) + ("%i%02i" % [year.to_i, month.to_i]).to_i + end + + def to_month(year, month) + date = DateTime.parse("%s-%s-01" % [year, month]) + date.strftime('%B %Y') + end + + def h(text) + Rack::Utils.escape_html(text) + end + + def strip_email_domain(str) + str.gsub(/@(.*?)(>|$)/) do |s| + if $1 == 'gentoo.org' + "@g.o#{$2}" + elsif $1 == 'lists.gentoo.org' + "@l.g.o#{$2}" + else + "@#{'×' * $1.length}#{$2}" + end + end + end + + def strip_email(str) + str.gsub(/([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+)\.([a-zA-Z]{2,10})/) do |email| + if $2 == 'gentoo' and $3 == 'org' + "#{$1}@g.o" + elsif $2 == 'lists.gentoo' and $3 == 'org' + "#{$1}@l.g.o" + else + "#{$1}@#{'×' * $2.length}.#{$3}" + end + end + end + + def linkize(str) + Rinku.auto_link(str, :urls, 'rel="nofollow"') + end + + +end
\ No newline at end of file diff --git a/lib/index.rb b/lib/index.rb new file mode 100644 index 0000000..b4ad2b7 --- /dev/null +++ b/lib/index.rb @@ -0,0 +1,122 @@ +PER_PAGE = 100 + +def threads_in_month(list, year, month, page) + $es.search( + index: 'ml-' + list, + size: PER_PAGE, + from: PER_PAGE * (page - 1), + body: { + query: { + filtered: { + filter: { + and: + [ + { term: { month: to_monthint(year, month) } }, + { missing: { field: 'parent' } } + ] + } + } + }, + sort: { + date: 'desc', + } + } + ) +end + +def messages_in_month(list, year, month, page) + $es.search( + index: 'ml-' + list, + size: PER_PAGE, + from: PER_PAGE * (page - 1), + body: { + query: { + filtered: { + filter: { + term: { month: to_monthint(year, month) } + } + } + }, + sort: { + date: 'desc', + } + } + ) +end + +def get_month_listing(list) + $es.search( + index: 'ml-' + list, + search_type: 'count', + size: 0, + body: { + size: 0, + aggs: { + messages_by_month: { + terms: { + field: 'month', + size: 0, + order: { + 'month2': 'desc' + } + }, + aggs: { + month2: { + avg: { + field: 'month' + } + } + } + } + } + } + ) +end + + +def get_message(list, hash) + $es.search( + index: 'ml-' + list, + size: 1, + body: { + query: { + filtered: { + filter: { + term: { _id: hash } + } + } + } + } + ) +end + +def get_parent_data(list, parent_id) + return nil if parent_id == nil + + parent = $es.search( + index: 'ml-' + list, + body: { query: { match: { _id: parent_id } } } + ) + + if parent['hits']['total'] == 0 + return nil + else + return parent['hits']['hits'].first + end +end + +def get_child_data(list, parent_id) + return nil if parent_id == nil + + children = $es.search( + index: 'ml-' + list, + size: 100, + body: { query: { match: { parent: parent_id } } } + ) + + if children['hits']['total'] == 0 + return nil + else + return children['hits']['hits'] + end +end
\ No newline at end of file diff --git a/public/css/main.css b/public/css/main.css new file mode 100644 index 0000000..2827892 --- /dev/null +++ b/public/css/main.css @@ -0,0 +1,66 @@ +.ag-text-content { + width: 100%; + overflow-x: scroll; + overflow-y: hidden; + display: block; +} + +.ag-message-table { + width: 100%; + table-layout: fixed; +} + +.ag-message-table td { + text-overflow: ellipsis; + max-height: 1.2em; + overflow: hidden; + white-space: nowrap; +} + +.ag-message-table-date { + width: 22%; +} + +.ag-message-table-from { + width: 18%; +} + +.ag-quote { + color: #999; + cursor: row-resize; + margin-bottom: -1em; + overflow: hidden; +} + +.ag-quote-hidden { + height: 2.4em; + overflow: hidden; + fdisplay: block; + -webkit-mask-image: linear-gradient(to bottom, white, transparent); + mask-image: linear-gradient(to bottom, white, transparent); +} + +.ag-toggle-quotes { + float: right; + margin-bottom: .5em; +} + +.ag-message-content { + clear: both; +} + +.ag-header-name-col { + width: 10em; +} + +.ag-pager { + margin: 0; +} + +.ag-html-content { + white-space: normal; +} + +.ag-view-selection { + margin-bottom: .5em; +}
\ No newline at end of file diff --git a/public/js/quoting.js b/public/js/quoting.js new file mode 100644 index 0000000..edf8ec0 --- /dev/null +++ b/public/js/quoting.js @@ -0,0 +1,30 @@ +$(function() { + var table = $('.ag-header-table'); + + if (table === undefined) { + return; + } + + if ($('.ag-quote').size() == 0) { + return; + } + + var btn = $("<button class=\"btn btn-xs btn-default ag-toggle-quotes\"><span class=\"fa fa-quote-left\"></span> Toggle quotes</button>"); + btn.insertAfter(table); + btn.click(function() { + $('.ag-quote').each(function(index) { + $(this).toggleClass('ag-quote-hidden'); + }); + }); + + $('.ag-quote').each(function(index) { + // Don't hide quotes by default. Maybe put in some cookie stuff to remember the choice + // $(this).addClass('ag-quote-hidden'); + + $(this).click(function() { + $('.ag-quote').each(function(index) { + $(this).toggleClass('ag-quote-hidden'); + }); + }) + }); +});
\ No newline at end of file diff --git a/views/index.erb b/views/index.erb new file mode 100644 index 0000000..4d68cc7 --- /dev/null +++ b/views/index.erb @@ -0,0 +1,39 @@ +<h1 class="first-header">Gentoo Mailing List Archives</h1> + +<h2>Current Mailing Lists</h2> + +<div class="row"> + <div class="col-xs-12 col-md-6"> + <div class="list-group"> + <% $config['active_lists'].each do |list| %> + <a href="<%= h list %>/" class="list-group-item"><span class="fa fa-fw fa-archive"></span> <%= h list %></a> + <% end %> + </div> + </div> + <div class="col-xs-12 col-md-6"> + <div class="alert alert-info" role="alert"> + <strong>How to Participate</strong><br> + Please see our <a href="https://www.gentoo.org/main/en/lists.xml" class="alert-link">Mailing List information page</a> for more information on + how you can subscribe and participate in the discussions. + </div> + </div> +</div> + +<h2>Frozen Archives</h2> + +<div class="row"> + <div class="col-xs-12 col-md-6"> + <div class="list-group"> + <% $config['frozen_lists'].each do |list| %> + <a href="<%= h list %>/" class="list-group-item"><span class="fa fa-fw fa-archive"></span> <%= h list %></a> + <% end %> + </div> + </div> + <div class="col-xs-12 col-md-6"> + <div class="alert alert-warning" role="alert"> + <strong>Inactive Lists</strong><br> + These mailing lists are inactive. You can not post or subscribe to them any more. + Archives are provided for future reference. + </div> + </div> +</div>
\ No newline at end of file diff --git a/views/layout.erb b/views/layout.erb new file mode 100644 index 0000000..79d8794 --- /dev/null +++ b/views/layout.erb @@ -0,0 +1,123 @@ +<!DOCTYPE html> +<html> + <head> + <title><%= "#{h @title} - " if @title %>Gentoo Mailing List Archives</title> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="theme-color" content="#54487a"> + <meta name="description" content=""> + <link href="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/bootstrap.min.css" rel="stylesheet" media="screen"> + <link href="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/tyrian.min.css" rel="stylesheet" media="screen"> + <link href="/css/main.css" rel="stylesheet" media="screen"> + <link rel="icon" href="http://www.gentoo.org/favicon.ico" type="image/x-icon"> + </head> + <body> + <header> + <div class="site-title"> + <div class="container"> + <div class="row"> + <div class="site-title-buttons"> + <div class="btn-group btn-group-sm"> + <a href="http://get.gentoo.org/" role="button" class="btn get-gentoo"><span class="fa fa-download"></span> <strong>Get Gentoo!</strong></a> + <div class="btn-group btn-group-sm"> + <a class="btn gentoo-org-sites dropdown-toggle" data-toggle="dropdown" data-target="#" href="#"> + <span class="glyphicon glyphicon-globe"></span> gentoo.org sites <span class="caret"></span> + </a> + <ul class="dropdown-menu"> + <li><a href="http://www.gentoo.org/" title="Main Gentoo website"><span class="fa fa-home fa-fw"></span> gentoo.org</a></li> + <li><a href="http://wiki.gentoo.org/" title="Find and contribute documentation"><span class="fa fa-file-text fa-fw"></span> Wiki</a></li> + <li><a href="https://bugs.gentoo.org/" title="Report issues and find common issues"><span class="fa fa-bug fa-fw"></span> Bugs</a></li> + <li><a href="http://forums.gentoo.org/" title="Discuss with the community"><span class="fa fa-comments-o fa-fw"></span> Forums</a></li> + <li><a href="http://packages.gentoo.org/" title="Find software for your Gentoo"><span class="fa fa-hdd-o fa-fw"></span> Packages</a></li> + <li class="divider"></li> + <li><a href="http://overlays.gentoo.org/" title="Collaborate on maintaining packages"><span class="fa fa-code-fork fa-fw"></span> Overlays</a></li> + <li><a href="http://planet.gentoo.org/" title="Find out what's going on in the developer community"><span class="fa fa-rss fa-fw"></span> Planet</a></li> + <li><a href="http://archives.gentoo.org/" title="Read up on past discussions"><span class="fa fa-archive fa-fw"></span> Archives</a></li> + <li><a href="http://sources.gentoo.org/" title="Browse our source code"><span class="fa fa-code fa-fw"></span> Sources</a></li> + <li class="divider"></li> + <li><a href="http://infra-status.gentoo.org/" title="Get updates on the services provided by Gentoo"><span class="fa fa-tasks fa-fw"></span> Infra Status</a></li> + </ul> + </div> + </div> + </div> + <div class="logo"> + <img src="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/site-logo.png" data-at2x="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/site-logo@2x.png" alt="Gentoo Linux Logo" /> + <span class="site-label">Archives</span> + </div> + </div> + </div> + </div> + <nav class="tyrian-navbar" role="navigation"> + <div class="container"> + <div class="row"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-main-collapse"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + </div> + <div class="collapse navbar-collapse navbar-main-collapse"> + <ul class="nav navbar-nav"> + <% if params[:list] %> + <li><a href="/">Home</a></li> + <li class="active"><a href="/<%= params[:list] %>/"><%= params[:list] %></a></li> + <% else %> + <li class="active"><a href="/">Home</a></li> + <% end %> + </ul> + </div> + </div> + </div> + </nav> + </header> + + <div class="container"> + <div class="row"> + <div class="col-xs-12"> + <%= yield %> + </div> + </div> + </div> + + <footer> + <div class="container"> + <div class="row"> + <div class="col-xs-12 col-md-offset-2 col-md-7"> + <p class="spacer"> + All contents reflect the opinion of the author, not the Gentoo project or the Gentoo Foundation. + </p> + </div> + <div class="col-xs-12 col-md-3"> + <h3 class="footerhead">Questions or comments?</h3> + Please feel free to <a href="http://www.gentoo.org/main/en/contact.xml">contact us</a>. + </div> + </div> + <div class="row"> + <div class="col-xs-2 col-sm-3 col-md-2"> + <ul class="footerlinks three-icons"> + <li><a href="http://twitter.com/gentoo" title="@Gentoo on Twitter"><span class="fa fa-twitter fa-fw"></span></a></li> + <li><a href="https://plus.google.com/+Gentoo" title="+Gentoo on Google+"><span class="fa fa-google-plus fa-fw"></span></a></li> + <li><a href="https://www.facebook.com/gentoo.org" title="Gentoo on Facebook"><span class="fa fa-facebook fa-fw"></span></a></li> + </ul> + </div> + <div class="col-xs-10 col-sm-9 col-md-10"> + <strong>© 2001–2015 Gentoo Foundation, Inc.</strong><br /> + <small> + Gentoo is a trademark of the Gentoo Foundation, Inc. + The contents of this document, unless otherwise expressly stated, are licensed under the + <a href="http://creativecommons.org/licenses/by-sa/3.0/" rel="license">CC-BY-SA-3.0</a> license. + The <a href="http://www.gentoo.org/main/en/name-logo.xml">Gentoo Name and Logo Usage Guidelines</a> apply. + </small> + </div> + </div> + </div> + </footer> + + <script src="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/jquery.min.js"></script> + <script src="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/bootstrap.min.js"></script> + <script src="https://1b9a50f4f9de4348cd9f-e703bc50ba0aa66772a874f8c7698be7.ssl.cf5.rackcdn.com/retina.min.js"></script> + <script src="/js/quoting.js"></script> + </body> +</html>
\ No newline at end of file diff --git a/views/listindex.erb b/views/listindex.erb new file mode 100644 index 0000000..ecf6ab7 --- /dev/null +++ b/views/listindex.erb @@ -0,0 +1,15 @@ +<h1 class="first-header">Gentoo Archives: <%= list %></h1> + +<table class="table"> + <tr> + <th>Month</th> + <th>Number of messages</th> + </tr> + <% results['aggregations']['messages_by_month']['buckets'].each do |month| %> + <% next if month['key'].to_i > current_monthint and not params[:allmonths] %> + <tr> + <td><%= monthint_to_link(month['key'].to_s) %></td> + <td><%= month['doc_count'] %></td> + </tr> + <% end %> +</table>
\ No newline at end of file diff --git a/views/listmonth.erb b/views/listmonth.erb new file mode 100644 index 0000000..4cdabe3 --- /dev/null +++ b/views/listmonth.erb @@ -0,0 +1,24 @@ +<h1 class="first-header">Gentoo Archives: <%= h list %> in <%= to_month(params[:year], params[:month]) %></h1> + +<div class="hidden-xs"> +<%= partial :pagination, locals: { current_page: current_page, max_pages: max_pages } %> +</div> + +<%= partial :views, locals: { list: list, mode: mode } %> + +<table class="table table-condensed table-hover ag-message-table"> + <tr> + <th class="ag-message-table-subject">Subject</th> + <th class="ag-message-table-from">From</th> + <th class="ag-message-table-date">Date</th> + </tr> + <% results['hits']['hits'].each do |message| %> + <tr> + <td><a href="../../message/<%= message['_id'] %>"><%= h message['_source']['subject'] %></a></td> + <td><%= h message['_source']['from_realname'] %></td> + <td><%= date_format message['_source']['date'] %></td> + </tr> + <% end %> +</table> + +<%= partial :pagination, locals: { current_page: current_page, max_pages: max_pages } %>
\ No newline at end of file diff --git a/views/message.erb b/views/message.erb new file mode 100644 index 0000000..59d2499 --- /dev/null +++ b/views/message.erb @@ -0,0 +1,71 @@ +<h1 class="first-header">Gentoo Archives: <%= list %></h1> + +<table class="table table-condensed ag-header-table"> + <tr> + <th class="ag-header-name-col">From:</th> + <td><%= h strip_email_domain(message['_source']['from']) %></td> + </tr> + <tr> + <th>To:</th> + <td><%= h strip_email_domain(message['_source']['to']) %></td> + </tr> + <tr> + <th>Cc:</th> + <td><%= h strip_email_domain(message['_source']['cc']) %></td> + </tr> + <tr> + <th>Subject:</th> + <td><strong><%= h message['_source']['subject'] %></strong></td> + </tr> + <tr> + <th>Date:</th> + <td><%= date_format message['_source']['date'] %></td> + </tr> + <% unless parent == nil %> + <tr> + <th>In Reply to:</th> + <td><a href="<%= parent['_id'] %>"><%= parent['_source']['subject'] %></a> by <%= parent['_source']['from'] %></td> + </tr> + <% end %> +</table> +<!-- Message-Id: <%= message['_source']['raw_message_id'] %> --> + +<pre class="ag-message-content"> +<%= linkize(strip_email(message['_source']['content'])) %> +</pre> + +<% if message['_source']['attachments'] and not message['_source']['attachments'].empty? %> +<h3>Attachments</h3> + +<table class="table table-condensed ag-attachment-table"> + <tr> + <th>File name</th> + <th>MIME type</th> + </tr> + <% message['_source']['attachments'].each do |attachment| %> + <tr> + <td><%= h attachment['filename'] %></td> + <td><%= h attachment['mime'] %></td> + </tr> + <% end %> +</table> +<% end %> + +<% unless children == nil %> +<h3>Replies</h3> + +<table class="table table-condensed ag-replies-table"> + <tr> + <th>Subject</th> + <th>Author</th> + </tr> + <% children.each do |child| %> + <tr> + <td><a href="<%= child['_id'] %>"><%= h child['_source']['subject'] %></a></td> + <td><%= h strip_email_domain(child['_source']['from']) %></td> + </tr> + <% end %> +</table> +<% end %> + +<a href="/<%= h list %>/report/<%= message['_id'] %>" class="btn btn-danger btn-xs"><span class="fa fa-ban"></span> Report Message</a>
\ No newline at end of file diff --git a/views/pagination.erb b/views/pagination.erb new file mode 100644 index 0000000..7d7be9c --- /dev/null +++ b/views/pagination.erb @@ -0,0 +1,31 @@ +<nav class="pull-right"> + <ul class="pagination ag-pager"> + <% if current_page == 1 %> + <li class="disabled"> + <a href="#" aria-label="Previous"> + <span aria-hidden="true">«</span> + </a> + <% else %> + <li> + <a href="<%= current_page - 1 %>" aria-label="Previous"> + <span aria-hidden="true">«</span> + </a> + <% end %> + </li> + <% (1..max_pages).each do |page| %> + <li <% if page == current_page %><%= 'class="active"' %><% end %>><a href="<%= page %>"><%= page %></a></li> + <% end %> + <% if current_page == max_pages %> + <li class="disabled"> + <a href="#" aria-label="Next"> + <span aria-hidden="true">»</span> + </a> + <% else %> + <li> + <a href="<%= current_page + 1 %>" aria-label="Next"> + <span aria-hidden="true">»</span> + </a> + <% end %> + </li> + </ul> +</nav>
\ No newline at end of file diff --git a/views/report.erb b/views/report.erb new file mode 100644 index 0000000..559dc23 --- /dev/null +++ b/views/report.erb @@ -0,0 +1,75 @@ +<h1 class="first-header">Report Message</h1> + +<p> + Please confirm that you want to report the message below: +</p> + +<table class="table table-condensed ag-header-table"> + <tr> + <th>Mailing List:</th> + <td><%= h list %></td> + </tr> + <tr> + <th class="ag-header-name-col">From:</th> + <td><%= h strip_email_domain(message['_source']['from']) %></td> + </tr> + <tr> + <th>To:</th> + <td><%= h strip_email_domain(message['_source']['to']) %></td> + </tr> + <tr> + <th>Cc:</th> + <td><%= h strip_email_domain(message['_source']['cc']) %></td> + </tr> + <tr> + <th>Subject:</th> + <td><strong><%= h message['_source']['subject'] %></strong></td> + </tr> + <tr> + <th>Date:</th> + <td><%= date_format message['_source']['date'] %></td> + </tr> +</table> + +<div class="alert alert-danger" role="alert"> + <strong>When not to report a message</strong> + <p> + Please do <strong>not</strong> report a message just because you disagree with its contents or can't stand the sender, that's what your personal killfile is for.<br> + Valid reasons for reporting a message include (obvious) spam; anything from Nigerian princes, duchesses, and the whole lot of them; improperly rendered messages or messages whose contents are missing completely. + </p> +</div> + +<hr> + +<form action="/report" method="POST"> + <input type="hidden" name="list" value="<%= list %>"> + <input type="hidden" name="msgid" value="<%= message['_id'] %>"> + <div class="form-group"> + <label for="captcha">El cheapo CAPTCHA</label> + <p class="help-block"><%= h $config['report_captcha_q'] %></p> + <input type="text" name="captcha" class="form-control" id="captcha" placeholder="<%= h $config['report_captcha_hint'] %>"> + </div> + <div class="form-group"> + <label for="reason">Reason</label> + <select class="form-control" name="reason" id="reason"> + <option selected disabled>(Select one)</option> + <option name="spam">Spam</option> + <option name="nigeria_calling">I HAVE PRIVILEGE TO TRANSFER OF SUM OF $65,000,000,000.00 TO YOU</option> + <option name="rendering_b0rked">Contents not correctly rendered</option> + <option name="content_missing">Contents not displayed at all</option> + <option name="other">(other, described below)</option> + </select> + </div> + <div class="form-group"> + <label for="comments">Additional comments</label> + <textarea class="form-control" id="comments" name="comments" rows="3"></textarea> + </div> + <button type="submit" class="btn btn-danger">Send Report</button> +</form> + +<hr> + +<p class="text-muted"> + <small><strong>Privacy Notice:</strong> + Your IP address will be saved to prevent abuse, but not shared with third parties.</small> +</p>
\ No newline at end of file diff --git a/views/reportmail.erb b/views/reportmail.erb new file mode 100644 index 0000000..3cdc3d9 --- /dev/null +++ b/views/reportmail.erb @@ -0,0 +1,19 @@ +<%= $config['base_url'] %><%= params[:list] %>/message/<%= message['_id'] %> + +------------------------------------------------------------------------------- + List: <%= params[:list] %> + Subject: <%= message['_source']['subject'] %> + From: <%= message['_source']['from'] %> + Date: <%= date_format message['_source']['date'] %> + + Message-Id: <%= message['_source']['raw_message_id'] %> + X-Archives-Hash: <%= message['_id'] %> + + Reason: <%= params[:reason] %> + Comments: <%= params[:comments] %> + + Reporter IP: <%= request.ip %> + +-- +Much Love, +Ag
\ No newline at end of file diff --git a/views/reportsent.erb b/views/reportsent.erb new file mode 100644 index 0000000..a10e0fd --- /dev/null +++ b/views/reportsent.erb @@ -0,0 +1,5 @@ +<h1 class="first-header">Report Message</h1> + +<div class="alert alert-info" role="alert"> + <%= h msg %> +</div>
\ No newline at end of file diff --git a/views/views.erb b/views/views.erb new file mode 100644 index 0000000..d644b43 --- /dev/null +++ b/views/views.erb @@ -0,0 +1,4 @@ +<div class="btn-group ag-view-selection" role="group" aria-label="Message view selection"> + <a href="/<%= h list %>/threads/<%= h params[:year] %>-<%= h params[:month] %>/" class="btn btn-<% if mode == :threads%>primary<% else %>default<% end %>">Threads</a> + <a href="/<%= h list %>/messages/<%= h params[:year] %>-<%= h params[:month] %>/" class="btn btn-<% if mode == :messages%>primary<% else %>default<% end %>">Messages</a> +</div>
\ No newline at end of file |