Files
2016-03-06 21:35:53 +01:00

421 lines
16 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>Ban Panel</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link rel="stylesheet" type="text/css" href="{{resource("css/font-awesome.css")}}">
<link rel="stylesheet" type="text/css" href="{{resource("css/style.css")}}">
<style type="text/css">
body {font-size: 8pt; font-family: Arial; padding-top: 30px;}
a {color: green; text-decoration: none;}
a:hover, a:visited {color: #076307;}
.header {height: 30px; padding: 0 10px; position: fixed; top: 0; left: 0; right: 0; background: #ddd; font-size: 1.1em; border-bottom: 1px solid #ccc;}
.header strong {float: left; line-height: 30px;}
.header form {float: right;}
.header .text {float: left; border: 0; width: 150px; height: 20px; line-height: 20px; margin: 5px 0 0 0; padding: 0 5px; font-size: 0.9em; border-bottom: 1px solid #ccc; border-right: 1px solid #aaa;}
.header form select {float: left; width: 60px; height: 21px; line-height: 20px; margin: 5px 0 0 5px; font-size: 0.9em; border: 0; border-bottom: 1px solid #ccc; border-right: 1px solid #aaa;}
.header .search {float: left; border: 0; margin: 5px 0 0 5px; height: 20px; line-height: 20px; padding: 0 5px; background: #076307; color: #eee; font-size: 0.8em; vertical-align: middle;}
.header .search:hover {background: green; cursor: pointer;}
.header .searchInfo {float: left; line-height: 30px; margin: 0 5px; font-size: 0.9em;}
.header .refresh {float: left; text-decoration: none; margin: 0 10px 0 -10px; padding: 0 10px; background: #ccc; font-size: 0.8em; color: green; display: inline-block; height: 30px; line-height: 30px; vertical-align: middle;}
.header .addNew {float: right; text-decoration: none; margin: 0 -10px 0 10px; padding: 0 10px; background: #ccc; font-size: 0.8em; color: green; display: inline-block; height: 30px; line-height: 30px; vertical-align: middle;}
.header .refresh:hover, .header .addNew:hover {background: #bbb;}
table {width: 100%;}
td {padding: 6px 5px; border-bottom: 1px solid #ededed;}
table thead {background: #eee;}
table thead th {padding: 5px 0; border-bottom: 1px solid #ccc;}
th.blank {color: #eee;}
th .sortBy i {margin-left: 5px;}
td.full {padding: 10px;}
td.actions {width: 70px;}
td.actions a {display: inline-block; padding: 2px; text-align: center;}
td.actions i {font-size: 1.3em;}
td.actions a:hover {background: #ccc;}
td.ckey {width: 90px; word-break: break-all;}
td.time {width: 60px;}
td.akey {width: 80px; word-break: break-all;}
td.reason {line-height: 1.4;}
td.compID {width: 60px;}
td.ip {width: 70px;}
.pagination {float: left; padding: 0 0 0 30px; list-style-type: none; text-align: center; margin: 0; height: 30px;}
.pagination li {float: left; line-height: 30px;}
.pagination a {text-decoration: none; display: inline-block; padding: 5px 7px; line-height: 20px;}
.pagination a:hover {background: #ccc;}
.pagination .current {background: #ccc;}
.switchRemoved {display: block; position: fixed; bottom: 0; right: 170px; padding: 8px; background: #ddd; border-top: 1px solid #bbb; border-left: 1px solid #ccc; border-right: 1px solid #ccc;}
.switchRemoved:hover {background: #ccc;}
</style>
</head>
<body>
<div class="header">
<a href="" data-start="0" class="refresh" title="Refresh"><i class="icon-refresh icon-large"></i></a>
<strong><span class="results">0 total bans</span> | <span class="sortedBy">By id desc</span></strong>
<ul class="pagination"></ul>
<a href="" class="addNew" title="Add New Ban"><i class="icon-plus icon-large"></i></a>
<form method="GET" action="">
<span class="searchInfo"></span>
<input type="text" class="text" />
<select>
<option value="all" selected="selected">All</option>
<option value="ckey">Key</option>
<option value="akey">Admin</option>
<option value="reason">Reason</option>
<option value="compID">CompID</option>
<option value="ip">IP</option>
</select>
<input type="submit" value="Search" class="search" />
</form>
</div>
<table border=0 cellspacing=0 cellpadding=0 id="bansTable">
<thead>
<tr>
<th class="blank">Actions</th>
<th><a href="" class="sortBy" data-value="ckey">Key</a></th>
<th>Time</th>
<th><a href="" class="sortBy" data-value="akey">Admin</a></th>
<th><a href="" class="sortBy" data-value="reason">Reason</a></th>
<th><a href="" class="sortBy" data-value="compID">Comp ID</a></th>
<th><a href="" class="sortBy" data-value="ip">IP</a></th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="7" class="full">Loading bans...</td>
</tr>
</tbody>
</table>
<a href="" class="switchRemoved" title="Switch the view to show removed bans">Removed Bans View</a>
<script type="text/javascript" src="{{resource("js/jquery.min.js")}}"></script>
<script type="text/javascript" language="JavaScript">
var ref_src = null /* ref_src */;
var CMinutes = null /* cminutes */;
var windowName = null /* window_name */;
var apiKey = null /* api_key */;
var totalBans = 0;
var pageLimit = 100; //How many rows per page
var viewRemoved = 0;
var searchValues = {
'term': '',
'column': 'all',
'offset': 0,
'sort': 'id',
'order': 'desc'
};
function urldecode(str) {
return decodeURIComponent((str+'').replace(/\+/g, '%20'));
}
function htmlEncode(value) {
return $('<div/>').text(value).html();
}
function urlEncodeParams(data) {
var string = '';
$.each(data, function(key, val) {
string += '&'+key+'='+encodeURIComponent(val);
});
return string;
}
function ehjaxCallback (data) {
var parsed = $.parseJSON(data);
if (parsed.cminutes) {
CMinutes = parseInt(parsed.cminutes);
delete parsed.cminutes;
}
if (parsed.callback) {
var callback = parsed.callback;
delete parsed.callback;
window[callback](2, parsed);
}
}
function getExpiry (minutes) {
minutes = parseInt(minutes);
var exp = minutes - CMinutes;
if (minutes === 0)
return 'Permanent';
else {
var timeleftstring;
if (exp >= 1440) { //1440 = 1 day in minutes
exp = Math.round((exp / 1440) * 10) / 10;
timeleftstring = exp+' Day'+(exp > 1 || exp < -1 ? 's' : '');
}
else if (exp >= 60) { //60 = 1 hour in minutes
exp = Math.round((exp / 60) * 10) / 10;
timeleftstring = exp+' Hour'+(exp > 1 || exp < -1 ? 's' : '');
}
else
timeleftstring = exp+' Minute'+(exp > 1 || exp < -1 ? 's' : '');
return timeleftstring;
}
}
function parseRow (row, hideChain) {
if (typeof(hideChain) === 'undefined') hideChain = 0;
var html =
'<tr>'+
'<td class="actions">';
if (!viewRemoved) {
html += '<a href="?src='+ref_src+'&action=unbane'+urlEncodeParams({id: row.id, target: row.ckey, compID: row.compID, ip: row.ip, reason: row.reason, timestamp: row.timestamp})+'" title="Edit"><i class="icon-edit"></i></a>'+
'<a href="?src='+ref_src+'&action=unbanf'+urlEncodeParams({id: row.id, target: row.ckey, compID: row.compID, ip: row.ip})+'" title="Unban"><i class="icon-trash"></i></a>';
}
html += '<a href="?src='+ref_src+'&action=notes'+urlEncodeParams({target: row.ckey})+'" title="Notes"><i class="icon-comments-alt"></i></a>'+
'</td>'+
'<td class="ckey">'+
'<a href="'+row.ckey+'" class="searchFor">'+row.ckey+'</a>'+
'</td>'+
'<td class="time">'+getExpiry(row.timestamp)+'</td>'+
'<td class="akey">'+
(row.oakey == 'N/A' || row.akey == 'Auto Banner' ? '<a href="'+row.akey+'" class="searchFor">'+row.akey+'</a>' : '<a href="'+row.oakey+'" class="searchFor">'+row.oakey+'</a>')+
(row.oakey != row.akey && row.oakey != 'N/A' ? (row.akey == 'Auto Banner' ? '<br /><small>Original: <a href="'+row.oakey+'" class="searchFor">'+row.oakey+'</a></small>': '<br /><small>Edited by: <a href="'+row.akey+'" class="searchFor">'+row.akey+'</a></small>') : '')+
(hideChain ? '' : (parseInt(row.previous) > 0 ? '<br /><small><a href="'+row.previous+'" class="previous" data-previous="'+row.previous+'">(Show chain)</a></small>' : '') )+
'</td>'+
'<td class="reason">'+(parseInt(row.chain) > 0 ? '[Evasion Attempt x'+row.chain+'] Previous Reason: ' : '') + row.reason +'</td>'+
'<td class="compID"><a href="'+row.compID+'" class="searchFor">'+row.compID+'</a></td>'+
'<td class="ip"><a href="'+row.ip+'" class="searchFor">'+row.ip+'</a></td>'+
'</tr>';
return html;
}
function buildPagination (total, start) {
var pages = Math.ceil(total / pageLimit);
var pagination = '';
for (var i = 1; i <= pages; i++) {
var elStart = (i - 1) * pageLimit;
var className = '';
if (elStart == parseInt(start)) {
className += 'current';
}
var html = '<li><a href="" data-start="'+elStart+'" class="'+className+'">'+i+'</a></li>';
pagination += html;
}
return pagination;
}
function updateBans (step, data) {
if (step === 1) {
data = (data ? data : {});
var term = (data.term ? data.term : '');
var column = (data.column ? data.column : 'all');
var offset = (data.offset ? data.offset : 0);
var sort = (data.sort ? data.sort : 'id');
var order = (data.order ? data.order : 'desc');
//Assign to globals
searchValues = {
'term': term,
'column': column,
'offset': offset,
'sort': sort,
'order': order
};
$('#bansTable tbody').html('<tr><td colspan="7" class="full">Loading bans...</td></tr>');
window.scrollTo(0, 0);
if (apiKey) {
if (window.XMLHtpRequest) {
xmlHttp = new XMLHttpRequest();
} else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttp.open('GET', 'http://goonhub.com/ss13/bans/get?search['+column+']='+term+'&sort='+sort+'&order='+order+'&offset='+offset+'&limit='+pageLimit+'&removed='+viewRemoved+'&bypass=1&forcejson=1&auth='+apiKey+'&t='+Math.random(), false);
xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlHttp.send();
var bansData = xmlHttp.responseText;
try {
bansData = $.parseJSON(bansData);
} catch(err) {
$('#bansTable tbody').html('<tr><td colspan="7" class="full">JSON is invalid: '+err+'<br/>'+xmlHttp.responseText+'</td></tr>');
return;
}
window.location = '?action=ehjax&window='+windowName+'&proc=getWorldMins'; //Update the cminutes var
updateBans(2, bansData);
} else { //Local bans db lookup
window.location = '?action=ehjax&window='+windowName+'&proc=getBanApiFallback&param[searchCol]='+column+'&param[search]='+term+'&param[sort]='+sort+'&param[order]='+order+'&param[offset]='+offset+'&param[limit]='+pageLimit+'&param[removed]='+viewRemoved;
}
}
if (step === 2) {
var totalBans = data.total;
delete data.total;
var term = searchValues.term;
var column = searchValues.column;
var offset = searchValues.offset;
var sort = searchValues.sort;
var order = searchValues.order;
//Shove all our results in the table
var html = '';
$.each(data, function(id, row) {
html += parseRow(row, 0);
});
$('#bansTable tbody').html(html);
$('.header .results').text(totalBans+' total bans');
//Update the pagination
var paginationEl = $('.pagination');
var pagination = buildPagination(totalBans, offset);
if (pagination != paginationEl.html()) {
paginationEl.html(pagination);
}
var sortedHtml = 'By '+sort+' '+order;
if (sort != 'id') {
sortedHtml += ' <a href=""><i class="icon-remove"></i></a>';
}
$('.header .sortedBy').html(sortedHtml);
$('.header .searchInfo').html((term.length > 0 ? 'Searching for '+term+' '+(column ? 'in '+column+' ' : '')+'<a href="" data-start="0"><i class="icon-remove"></i> Cancel</a>' : ''));
}
}
function getPreviousBans(id) { //This is annoying enough to be in it's own mostly copy and pasted function
if (typeof(id) === 'undefined') id = '1';
$('#bansTable tbody').html('<tr><td colspan="7" class="full">Loading bans...</td></tr>');
window.scrollTo(0, 0);
if (window.XMLHtpRequest) {
xmlHttp = new XMLHttpRequest();
} else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttp.open('GET', 'http://goonhub.com/ss13/bans/getPrevious?id='+id+'&forcejson=1&bypass=1&auth='+apiKey+'&t='+Math.random(), false);
xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xmlHttp.send();
var bansData = htmlEncode(xmlHttp.responseText);
try {
bansData = $.parseJSON(bansData);
} catch(err) {
$('#bansTable tbody').html('<tr><td colspan="7" class="full">JSON is invalid: '+err+'</td></tr>');
return;
}
window.location = '?action=ehjax&window='+windowName+'&proc=getWorldMins'; //Update the cminutes var
totalBans = bansData.total;
delete bansData.total;
//Shove all our results in the table
var html = '';
$.each(bansData, function(id, row) {
html += parseRow(row, 1);
});
$('#bansTable tbody').html(html);
$('.header .results').text(totalBans+' total bans');
$('.pagination').html(''); //Remove pagination because fuck it I'm not doing this for this too
$('.header .searchInfo').html('Searching for previous bans of ID: '+id+' <a href="" data-start="0"> <i class="icon-remove"></i> Cancel</a>');
}
function searchBans (term, column) {
term = term.replace(/^\s+|\s+$/gm,'');
if (term.length <= 2) {
$('.header .searchInfo').html('3 characters minimum');
return;
}
searchValues.term = term;
if (!column || column.length < 1) {
column = 'all';
}
searchValues.column = column;
$('.header form .text').val(term);
searchValues.offset = 0;
updateBans(1, searchValues);
}
$(function() {
updateBans(1); //Initial load
//Events!
$('body').on('click', '.pagination a, .header a.refresh', function(e) {
e.preventDefault();
searchValues.offset = $(this).attr('data-start');
updateBans(1, searchValues);
});
$('body').on('click', '.searchInfo a', function(e) {
e.preventDefault();
searchValues.term = '';
searchValues.offset = $(this).attr('data-start');
$('.header form select').val('all');
updateBans(1, searchValues);
});
$('body').on('click', '.sortedBy a', function(e) {
e.preventDefault();
searchValues.sort = 'id';
searchValues.order = 'desc';
$('#bansTable a.sortBy').each(function(key, el) {
$(el).find('i').remove();
});
updateBans(1, searchValues);
});
$('.header form').submit(function(e) {
e.preventDefault();
var term = $(this).children('input').val();
var column = $(this).children('select').val();
searchBans(term, column);
});
$('#bansTable').on('click', 'a.searchFor', function(e) {
e.preventDefault();
var column = $(this).parent().attr('class');
column = (column ? column : 'all');
searchBans($(this).text(), column);
});
$('#bansTable').on('click', 'a.sortBy', function(e) {
e.preventDefault();
var sort = $(this).attr('data-value');
if (searchValues.sort == sort) {
searchValues.order = (searchValues.order == 'asc' ? 'desc' : 'asc');
} else {
searchValues.sort = sort;
searchValues.order = 'desc';
}
$('#bansTable a.sortBy').each(function(key, el) {
$(el).find('i').remove();
});
var iconClass = (searchValues.order == 'asc' ? 'icon-caret-up' : 'icon-caret-down');
$(this).append('<i class="'+iconClass+'"></i>');
updateBans(1, searchValues);
});
$('body').on('click', '#bansTable a.previous', function(e) {
e.preventDefault();
getPreviousBans($(this).attr('data-previous'));
});
$('.header .addNew').attr('href', '?src='+ref_src+';action=addban');
$('.switchRemoved').click(function(e) {
e.preventDefault();
searchValues.term = '';
searchValues.sort = 'id';
searchValues.order = 'desc';
$('.header form select').val('all');
if (viewRemoved) {
$(this).text('Removed Bans View');
viewRemoved = 0;
} else {
$(this).text('Current Bans View');
viewRemoved = 1;
}
updateBans(1, searchValues);
});
});
</script>
</body>
</html>