Skip to content

Commit

Permalink
Download link for replay archive of filtered battles
Browse files Browse the repository at this point in the history
Archive download is memory intensive for now, as the archive is built
in memory. To be rewritten later to use the file system.

Also hide download link in battle details if replay does not exist.

Hiding the download link fixes #12
Archive download is a feature request in #1
  • Loading branch information
ceari committed Dec 11, 2013
1 parent 270a97e commit e40e83e
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 5 deletions.
2 changes: 2 additions & 0 deletions whyattend/templates/battles/battle.html
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,10 @@ <h2>Battle details <img style="width:32px; height:32px;" src="{{url_for('static'
</dl>
{% endif %}
</div>
{% if battle.replay and battle.replay.replay_blob %}
<dl>
<dt>Replay</dt>
<dd><a href="{{url_for('download_replay', battle_id=battle.id)}}"><i class="icon-download"></i> Download</a></dd>
</dl>
{% endif %}
{% endblock %}
12 changes: 10 additions & 2 deletions whyattend/templates/battles/battles.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<script type="text/javascript">
$(document).ready(function () {

$('#battles').dataTable({
var table = $('#battles').dataTable({
"oLanguage": {
"sLengthMenu": "Display _MENU_ battles per page",
"sZeroRecords": "No battles yet.",
Expand All @@ -21,6 +21,7 @@
[0, "desc"]
],
"aoColumns": [
{ "bVisible": false },
{ "sType": "date-euro-anchor"},
null,
null,
Expand All @@ -35,6 +36,10 @@
{"bSortable": false}
],
"fnDrawCallback": function (oSettings) {
var battle_ids = jQuery.map(jQuery(this._('tr', {'filter': 'applied'} )), function(element) { return jQuery(element)[0]; });

$('#download').attr('href', '{{url_for('download_replays')}}?' + jQuery.param({ids: battle_ids}));

$("a.confirm-sign").on("click", function (e) {
var link = this;

Expand Down Expand Up @@ -85,10 +90,11 @@ <h2>Battles of {{ clan }} <img style="height: 32px; width: 32px;" src="{{url_for
<i class="icon-info icon-2x"></i> Only one of the battles of a landing tournament is shown in the table.
Follow the <i class="icon-list"></i> links to view all tournament battles.
</p>
<hr>
<hr>
<table id="battles" class="table table-striped">
<thead>
<tr>
<th>ID</th>
<th>Date</th>
<th>Type</th>
<th>Map</th>
Expand All @@ -107,6 +113,7 @@ <h2>Battles of {{ clan }} <img style="height: 32px; width: 32px;" src="{{url_for
{% for battle in battles %}
{% if not battle.battle_group or (battle.battle_group and battle.battle_group.get_representative_battle() == battle) %}
<tr>
<td>{{battle.id}}</td>
<td><a href="{{url_for('battle_details', battle_id=battle.id)}}">{{battle.date.strftime('%d.%m.%Y %H:%M:%S')}}</a></td>
<td>
{% if battle.battle_group %}
Expand Down Expand Up @@ -162,5 +169,6 @@ <h2>Battles of {{ clan }} <img style="height: 32px; width: 32px;" src="{{url_for
{% endfor %}
</tbody>
</table>
<a id="download" href="#"><i class="icon-download"></i> Download replays</a>

{% endblock %}
35 changes: 32 additions & 3 deletions whyattend/webapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
import pickle
import logging
import hashlib
import StringIO
import tarfile
import calendar
import tempfile

from cStringIO import StringIO
from collections import defaultdict, OrderedDict
from functools import wraps
from datetime import timedelta
Expand Down Expand Up @@ -272,7 +275,8 @@ def cached_battle_schedule(clan_id):
logger.info("Querying Wargaming server for battle schedule of clan " + str(clan_id) + " " + g.player.clan)
try:
return wotapi.get_battle_schedule(clan_id)
except:
except Exception as e:
print e
return None

provinces_owned = cached_provinces_owned(config.CLAN_IDS[g.player.clan])
Expand Down Expand Up @@ -993,13 +997,38 @@ def download_replay(battle_id):
"""
battle = Battle.query.get(battle_id) or abort(404)
if not battle.replay_id: abort(404)
if not battle.replay.replay_blob: abort(404)
response = make_response(battle.replay.replay_blob)
response.headers['Content-Type'] = 'application/octet-stream'
response.headers['Content-Disposition'] = 'attachment; filename=' + \
secure_filename(battle.date.strftime(
'%d.%m.%Y_%H_%M_%S') + '_' + battle.clan + '_' + battle.enemy_clan + '.wotreplay')
return response

@app.route('/battles/download-replays')
@require_login
def download_replays():
battle_ids = map(int, request.args.getlist('ids[]'))
if not battle_ids: abort(404)

buffer = StringIO()
tar = tarfile.open(mode='w', fileobj=buffer)
for battle in Battle.query.filter(Battle.id.in_(battle_ids)):
if not battle.replay or not battle.replay.replay_blob: continue
filename = secure_filename(battle.date.strftime(
'%d.%m.%Y_%H_%M_%S') + '_' + battle.clan + '_' + battle.enemy_clan + '.wotreplay')
info = tarfile.TarInfo(filename)
info.size = len(battle.replay.replay_blob)
info.mtime = calendar.timegm(battle.date.utctimetuple())
info.type = tarfile.REGTYPE
tar.addfile(info, StringIO(battle.replay.replay_blob))
tar.close()

response = make_response(buffer.getvalue())
response.headers['Content-Type'] = 'application/tar'
response.headers['Content-Disposition'] = 'attachment; filename=' + secure_filename("replays.tar")
return response


@app.route('/payout/<clan>')
@require_login
Expand Down Expand Up @@ -1415,7 +1444,7 @@ def profile():
@require_role(config.ADMIN_ROLES)
def export_emails(clan):
""" Return names and email addresses as CSV file """
csv_response = StringIO.StringIO()
csv_response = StringIO()
csv_writer = csv.writer(csv_response)
csv_writer.writerow(["Name", "e-mail"])

Expand Down

0 comments on commit e40e83e

Please sign in to comment.