post-filter.js restructure

- Changed how filters are stored. Have included code to migrate from
previous version
- Added support for 'subject' and 'comment' in the options panel
- Added regex support in the options panel
This commit is contained in:
marktaiwan 2015-02-26 00:05:43 +08:00 committed by czaks
parent f84d0b9027
commit 8f6ea6dd94

View File

@ -27,34 +27,42 @@ if (active_page === 'thread' || active_page === 'index') {
list.nextPurge[boardId][threadId] = {timestamp: timestamp(), interval: 86400}; // 86400 seconds == 1 day list.nextPurge[boardId][threadId] = {timestamp: timestamp(), interval: 86400}; // 86400 seconds == 1 day
} }
function addFilter(type, value, useRegex) {
var list = getList();
var filter = list.generalFilter;
var obj = {
type: type,
value: value,
regex: useRegex
};
for (var i=0; i<filter.length; i++) {
if (filter[i].type == type && filter[i].value == value && filter[i].regex == useRegex)
return;
}
filter.push(obj);
setList(list);
drawFilterList();
}
function removeFilter(type, value, useRegex) {
var list = getList();
var filter = list.generalFilter;
for (var i=0; i<filter.length; i++) {
if (filter[i].type == type && filter[i].value == value && filter[i].regex == useRegex) {
filter.splice(i, 1);
break;
}
}
setList(list);
drawFilterList();
}
var blacklist = { var blacklist = {
add: { add: {
name: function (posterName) {
var list = getList();
var filter = list.nameFilter;
for (var i in filter) {
if (filter[i].name == posterName) return;
}
filter.push({
name: posterName
});
setList(list);
drawFilterList();
},
trip: function (posterTrip) {
var list = getList();
var filter = list.nameFilter;
for (var i in filter) {
if (filter[i].trip == posterTrip) return;
}
filter.push({
trip: posterTrip
});
setList(list);
drawFilterList();
},
post: function (boardId, threadId, postId, hideReplies) { post: function (boardId, threadId, postId, hideReplies) {
var list = getList(); var list = getList();
var filter = list.postFilter; var filter = list.postFilter;
@ -87,32 +95,6 @@ if (active_page === 'thread' || active_page === 'index') {
} }
}, },
remove: { remove: {
name: function (posterName) {
var list = getList();
var filter = list.nameFilter;
for (var i=0; i<filter.length; i++) {
if (filter[i].name == posterName) {
filter.splice(i, 1);
break;
}
}
setList(list);
drawFilterList();
},
trip: function (posterTrip) {
var list = getList();
var filter = list.nameFilter;
for (var i=0; i<filter.length; i++) {
if (filter[i].trip == posterTrip) {
filter.splice(i, 1);
break;
}
}
setList(list);
drawFilterList();
},
post: function (boardId, threadId, postId) { post: function (boardId, threadId, postId) {
var list = getList(); var list = getList();
var filter = list.postFilter; var filter = list.postFilter;
@ -174,10 +156,10 @@ if (active_page === 'thread' || active_page === 'index') {
function hide(ele) { function hide(ele) {
var $ele = $(ele); var $ele = $(ele);
if ($(ele).data('hidden') === '1') if ($(ele).data('hidden'))
return; return;
$(ele).data('hidden', '1'); $(ele).data('hidden', true);
if ($ele.hasClass('op')) { if ($ele.hasClass('op')) {
$ele.parent().find('.body, .files, .video-container').not($ele.children('.reply').children()).hide(); $ele.parent().find('.body, .files, .video-container').not($ele.children('.reply').children()).hide();
@ -191,7 +173,7 @@ if (active_page === 'thread' || active_page === 'index') {
function show(ele) { function show(ele) {
var $ele = $(ele); var $ele = $(ele);
$(ele).data('hidden', '0'); $(ele).data('hidden', false);
if ($ele.hasClass('op')) { if ($ele.hasClass('op')) {
$ele.parent().find('.body, .files, .video-container').show(); $ele.parent().find('.body, .files, .video-container').show();
if (active_page == 'index') $ele.parent().find('.omitted, .reply:not(.hidden), post_no, .mentioned, br').show(); if (active_page == 'index') $ele.parent().find('.omitted, .reply:not(.hidden), post_no, .mentioned, br').show();
@ -243,7 +225,7 @@ if (active_page === 'thread' || active_page === 'index') {
*/ */
// unhide button // unhide button
if ($ele.data('hidden') == '1') { if ($ele.data('hidden')) {
$buffer.find('#filter-menu-unhide').click(function () { $buffer.find('#filter-menu-unhide').click(function () {
// if hidden due to post id, remove it from blacklist // if hidden due to post id, remove it from blacklist
// otherwise just show this post // otherwise just show this post
@ -259,7 +241,7 @@ if (active_page === 'thread' || active_page === 'index') {
} }
// post id // post id
if ($ele.data('hiddenByPost') == '0') { if (!$ele.data('hiddenByPost')) {
$buffer.find('#filter-add-post-plus').click(function () { $buffer.find('#filter-add-post-plus').click(function () {
blacklist.add.post(pageData.boardId, threadId, postId, true); blacklist.add.post(pageData.boardId, threadId, postId, true);
}); });
@ -268,7 +250,7 @@ if (active_page === 'thread' || active_page === 'index') {
} }
// UID // UID
if (pageData.hasUID && $ele.data('hiddenByUid') == '0') { if (pageData.hasUID && !$ele.data('hiddenByUid')) {
$buffer.find('#filter-add-id').click(function () { $buffer.find('#filter-add-id').click(function () {
blacklist.add.uid(pageData.boardId, threadId, postUid, false); blacklist.add.uid(pageData.boardId, threadId, postUid, false);
}); });
@ -277,7 +259,7 @@ if (active_page === 'thread' || active_page === 'index') {
}); });
$buffer.find('#filter-remove-id').addClass('hidden'); $buffer.find('#filter-remove-id').addClass('hidden');
} else if (pageData.hasUID) { } else if (pageData.hasUID) {
$buffer.find('#filter-remove-id').click(function () { $buffer.find('#filter-remove-id').click(function () {
blacklist.remove.uid(pageData.boardId, threadId, postUid); blacklist.remove.uid(pageData.boardId, threadId, postUid);
}); });
@ -292,15 +274,15 @@ if (active_page === 'thread' || active_page === 'index') {
} }
// name // name
if (!pageData.forcedAnon && $ele.data('hiddenByName') == '0') { if (!pageData.forcedAnon && !$ele.data('hiddenByName')) {
$buffer.find('#filter-add-name').click(function () { $buffer.find('#filter-add-name').click(function () {
blacklist.add.name(postName); addFilter('name', postName, false);
}); });
$buffer.find('#filter-remove-name').addClass('hidden'); $buffer.find('#filter-remove-name').addClass('hidden');
} else if (!pageData.forcedAnon) { } else if (!pageData.forcedAnon) {
$buffer.find('#filter-remove-name').click(function () { $buffer.find('#filter-remove-name').click(function () {
blacklist.remove.name(postName); removeFilter('name', postName, false);
}); });
$buffer.find('#filter-add-name').addClass('hidden'); $buffer.find('#filter-add-name').addClass('hidden');
@ -311,15 +293,15 @@ if (active_page === 'thread' || active_page === 'index') {
} }
// tripcode // tripcode
if (!pageData.forcedAnon && $ele.data('hiddenByTrip') == '0' && postTrip !== '') { if (!pageData.forcedAnon && !$ele.data('hiddenByTrip') && postTrip !== '') {
$buffer.find('#filter-add-trip').click(function () { $buffer.find('#filter-add-trip').click(function () {
blacklist.add.trip(postTrip); addFilter('trip', postTrip, false);
}); });
$buffer.find('#filter-remove-trip').addClass('hidden'); $buffer.find('#filter-remove-trip').addClass('hidden');
} else if (!pageData.forcedAnon && postTrip !== '') { } else if (!pageData.forcedAnon && postTrip !== '') {
$buffer.find('#filter-remove-trip').click(function () { $buffer.find('#filter-remove-trip').click(function () {
blacklist.remove.trip(postTrip); removeFilter('trip', postTrip, false);
}); });
$buffer.find('#filter-add-trip').addClass('hidden'); $buffer.find('#filter-add-trip').addClass('hidden');
@ -341,18 +323,18 @@ if (active_page === 'thread' || active_page === 'index') {
} }
/* /*
* add menu button to the thread/post * hide/unhide thread on index view
*/ */
function quickToggle(ele, threadId, pageData) { function quickToggle(ele, threadId, pageData) {
/*if ($(ele).find('.hide-thread-link').length) /*if ($(ele).find('.hide-thread-link').length)
$('.hide-thread-link').remove();*/ $('.hide-thread-link').remove();*/
if ($(ele).hasClass('op') && !$(ele).find('.hide-thread-link').length) { if ($(ele).hasClass('op') && !$(ele).find('.hide-thread-link').length) {
$('<a class="hide-thread-link" style="float:left;margin-right:5px" href="javascript:void(0)">[' + ($(ele).data('hidden') == '1' ? '+' : '&ndash;') + ']</a>') $('<a class="hide-thread-link" style="float:left;margin-right:5px" href="javascript:void(0)">[' + ($(ele).data('hidden') ? '+' : '&ndash;') + ']</a>')
.insertBefore($(ele).find(':not(h2,h2 *):first')) .insertBefore($(ele).find(':not(h2,h2 *):first'))
.click(function() { .click(function() {
var postId = $(ele).find('.post_no').not('[id]').text(); var postId = $(ele).find('.post_no').not('[id]').text();
var hidden = ($(ele).data('hidden') == '1'); var hidden = $(ele).data('hidden');
if (hidden) { if (hidden) {
blacklist.remove.post(pageData.boardId, threadId, postId, false); blacklist.remove.post(pageData.boardId, threadId, postId, false);
@ -375,8 +357,8 @@ if (active_page === 'thread' || active_page === 'index') {
var $post = $(post); var $post = $(post);
var list = getList(); var list = getList();
var postId = $post.find('.post_no').not('[id]').text(); var postId = $post.find('.post_no').not('[id]').text();
var name, trip, uid; var name, trip, uid, subject, comment;
var i, array; // temp variables var i, length, array, rule, pattern; // temp variables
var boardId = pageData.boardId; var boardId = pageData.boardId;
var localList = pageData.localList; var localList = pageData.localList;
@ -384,11 +366,16 @@ if (active_page === 'thread' || active_page === 'index') {
var hasUID = pageData.hasUID; var hasUID = pageData.hasUID;
var forcedAnon = pageData.forcedAnon; var forcedAnon = pageData.forcedAnon;
$post.data('hidden', '0'); var hasTrip = ($post.find('.trip').length > 0);
$post.data('hiddenByUid', '0'); var hasSub = ($post.find('.subject').length > 0);
$post.data('hiddenByPost', '0');
$post.data('hiddenByName', '0'); $post.data('hidden', false);
$post.data('hiddenByTrip', '0'); $post.data('hiddenByUid', false);
$post.data('hiddenByPost', false);
$post.data('hiddenByName', false);
$post.data('hiddenByTrip', false);
$post.data('hiddenBySubject', false);
$post.data('hiddenByComment', false);
// add post with matched UID to localList // add post with matched UID to localList
if (hasUID && if (hasUID &&
@ -399,7 +386,7 @@ if (active_page === 'thread' || active_page === 'index') {
for (i=0; i<array.length; i++) { for (i=0; i<array.length; i++) {
if (array[i].uid == uid) { if (array[i].uid == uid) {
$post.data('hiddenByUid', '1'); $post.data('hiddenByUid', true);
localList.push(postId); localList.push(postId);
if (array[i].hideReplies) noReplyList.push(postId); if (array[i].hideReplies) noReplyList.push(postId);
break; break;
@ -410,23 +397,83 @@ if (active_page === 'thread' || active_page === 'index') {
// match localList // match localList
if (localList.length) { if (localList.length) {
if ($.inArray(postId, localList) != -1) { if ($.inArray(postId, localList) != -1) {
if ($post.data('hiddenByUid') != '1') $post.data('hiddenByPost', '1'); if ($post.data('hiddenByUid') !== true) $post.data('hiddenByPost', true);
hide(post); hide(post);
} }
} }
// match poster name and tripcode // matches generalFilter
if (!forcedAnon) { if (!forcedAnon)
name = (typeof $post.find('.name').contents()[0] == 'undefined') ? '' : $post.find('.name').contents()[0].nodeValue.trim(); name = (typeof $post.find('.name').contents()[0] == 'undefined') ? '' : $post.find('.name').contents()[0].nodeValue.trim();
if ($(list.nameFilter).filter(function(){if (this.name == name) return true;}).length) { if (!forcedAnon && hasTrip)
$post.data('hiddenByName', '1'); trip = $post.find('.trip').text();
hide(post); if (hasSub)
} subject = ' '+ $post.find('.subject').text() +' ';
if ($post.find('.trip').length) {
trip = $post.find('.trip').text(); array = $post.find('.body').contents().filter(function () {if ($(this).text() !== '') return true;}).toArray();
if ($(list.nameFilter).filter(function(){if (this.trip == trip) return true;}).length) { array = $.map(array, function (ele) {
$post.data('hiddenByTrip', '1'); return $(ele).text();
hide(post); });
comment = ' '+ array.join(' ') +' ';
for (i = 0, length = list.generalFilter.length; i < length; i++) {
rule = list.generalFilter[i];
if (rule.regex) {
pattern = new RegExp(rule.value);
switch (rule.type) {
case 'name':
if (!forcedAnon && pattern.test(name)) {
$post.data('hiddenByName', true);
hide(post);
}
break;
case 'trip':
if (!forcedAnon && pattern.test(trip)) {
$post.data('hiddenByTrip', true);
hide(post);
}
break;
case 'sub':
if (hasSub && pattern.test(subject)) {
$post.data('hiddenBySubject', true);
hide(post);
}
break;
case 'com':
if (pattern.test(comment)) {
$post.data('hiddenByComment', true);
hide(post);
}
break;
}
} else {
switch (rule.type) {
case 'name':
if (!forcedAnon && rule.value == name) {
$post.data('hiddenByName', true);
hide(post);
}
break;
case 'trip':
if (!forcedAnon && hasTrip && rule.value == trip) {
$post.data('hiddenByTrip', true);
hide(post);
}
break;
case 'sub':
if (hasSub && subject.indexOf(' '+ rule.value +' ') != -1) {
$post.data('hiddenBySubject', true);
hide(post);
}
break;
case 'com':
if (comment.indexOf(' '+ rule.value +' ') != -1) {
$post.data('hiddenByComment', true);
hide(post);
}
break;
} }
} }
} }
@ -445,12 +492,11 @@ if (active_page === 'thread' || active_page === 'index') {
}); });
// post didn't match any filters // post didn't match any filters
if ((typeof $post.data('hidden') == 'undefined' || $post.data('hidden') == '0') && if (!$post.data('hidden')) {
$post.data('hiddenByUid') === '0' &&
$post.data('hiddenByUid') == $post.data('hiddenByPost') == $post.data('hiddenByName') == $post.data('hiddenByTrip')) {
show(post); show(post);
} }
} }
/* (re)runs the filter on the entire page /* (re)runs the filter on the entire page
*/ */
function filterPage(pageData) { function filterPage(pageData) {
@ -471,16 +517,14 @@ if (active_page === 'thread' || active_page === 'index') {
var i, array; // temp variables var i, array; // temp variables
// add posts to localList and noReplyList // add posts to localList and noReplyList
if (typeof list.postFilter[pageData.boardId] != 'undefined') { if (typeof list.postFilter[pageData.boardId] != 'undefined' && typeof list.postFilter[pageData.boardId][threadId] != 'undefined') {
array = list.postFilter[pageData.boardId][threadId]; array = list.postFilter[pageData.boardId][threadId];
if (typeof array != 'undefined') { for (i=0; i<array.length; i++) {
for (i=0; i<array.length; i++) { if ( typeof array[i].post == 'undefined')
if ( typeof array[i].post == 'undefined') continue;
continue;
pageData.localList.push(array[i].post); pageData.localList.push(array[i].post);
if (array[i].hideReplies) pageData.noReplyList.push(array[i].post); if (array[i].hideReplies) pageData.noReplyList.push(array[i].post);
}
} }
} }
// run filter on OP // run filter on OP
@ -488,7 +532,7 @@ if (active_page === 'thread' || active_page === 'index') {
quickToggle(op, threadId, pageData); quickToggle(op, threadId, pageData);
// iterate filter over each post // iterate filter over each post
if ($(op).data('hidden') != '1' || active_page == 'thread') { if (!$(op).data('hidden') || active_page == 'thread') {
$thread.find('.reply').not('.hidden').each(function () { $thread.find('.reply').not('.hidden').each(function () {
filter(this, threadId, pageData); filter(this, threadId, pageData);
}); });
@ -506,6 +550,8 @@ if (active_page === 'thread' || active_page === 'index') {
$ele.remove(); $ele.remove();
cssString = '\n/*** Generated by post-filter ***/\n' + cssString = '\n/*** Generated by post-filter ***/\n' +
'#filter-control input[type=text] {width: 130px;}' +
'#filter-control input[type=checkbox] {vertical-align: middle;}' +
'#filter-control #clear {float: right;}\n' + '#filter-control #clear {float: right;}\n' +
'#filter-container {margin-top: 20px; border: 1px solid; height: 270px; overflow: auto;}\n' + '#filter-container {margin-top: 20px; border: 1px solid; height: 270px; overflow: auto;}\n' +
'#filter-list {width: 100%; border-collapse: collapse;}\n' + '#filter-list {width: 100%; border-collapse: collapse;}\n' +
@ -524,33 +570,40 @@ if (active_page === 'thread' || active_page === 'index') {
} }
function drawFilterList() { function drawFilterList() {
var list = getList().nameFilter; var list = getList().generalFilter;
var $ele = $('#filter-list'); var $ele = $('#filter-list');
var $row; var $row, i, length, obj, val;
var type, val;
var i, length, obj; var typeName = {
name: 'name',
trip: 'tripcode',
sub: 'subject',
com: 'comment'
};
$ele.empty(); $ele.empty();
$ele.append('<tr id="header"><th>Type</th><th>Content</th><th>Remove</th></tr>'); $ele.append('<tr id="header"><th>Type</th><th>Content</th><th>Remove</th></tr>');
for (i = 0, length = list.length; i < length; i++) { for (i = 0, length = list.length; i < length; i++) {
obj = list[i]; obj = list[i];
for (type in obj) {
val = obj[type]; // display formatting
$row = $('<tr>'); val = (obj.regex) ? '/'+ obj.value +'/' : obj.value;
$row.append(
'<td>'+ type +'</td>', $row = $('<tr>');
'<td>'+ val +'</td>', $row.append(
$('<td>').append( '<td>'+ typeName[obj.type] +'</td>',
$('<a>').html('X') '<td>'+ val +'</td>',
.addClass('del-btn') $('<td>').append(
.attr('href', '#') $('<a>').html('X')
.attr('data-type', type) .addClass('del-btn')
.attr('data-val', val) .attr('href', '#')
) .data('type', obj.type)
); .data('val', obj.value)
$ele.append($row); .data('useRegex', obj.regex)
} )
);
$ele.append($row);
} }
} }
@ -559,9 +612,15 @@ if (active_page === 'thread' || active_page === 'index') {
Options.add_tab('filter', 'list', 'Filters'); Options.add_tab('filter', 'list', 'Filters');
Options.extend_tab('filter', Options.extend_tab('filter',
'<div id="filter-control">' + '<div id="filter-control">' +
'<input id="input" type="text"></input>' + '<select>' +
'<button id="name">Add Name</button>' + '<option value="name">Name</option>' +
'<button id="trip">Add Tripcode</button>' + '<option value="trip">Tripcode</option>' +
'<option value="sub">Subject</option>' +
'<option value="com">Comment</option>' +
'</select>' +
'<input type="text"></input>' +
'<input type="checkbox">regex</input>' +
'<button id="set-filter">Add</button>' +
'<button id="clear">Clear all filters</button>' + '<button id="clear">Clear all filters</button>' +
'<div id="confirm" class="hidden">' + '<div id="confirm" class="hidden">' +
'This will clear all filtering rules including hidden posts. <a id="confirm-y" href="#">yes</a> | <a id="confirm-n" href="#">no</a>' + 'This will clear all filtering rules including hidden posts. <a id="confirm-y" href="#">yes</a> | <a id="confirm-n" href="#">no</a>' +
@ -572,15 +631,16 @@ if (active_page === 'thread' || active_page === 'index') {
drawFilterList(); drawFilterList();
// control buttons // control buttons
$('#filter-control').on('click', '#name', function () { $('#filter-control').on('click', '#set-filter', function () {
var str = $('#filter-control #input').val().trim(); var type = $('#filter-control select option:selected').val();
$('#filter-control #input').val(''); var value = $('#filter-control input[type=text]').val();
blacklist.add.name(str); var useRegex = $('#filter-control input[type=checkbox]').prop('checked');
});
$('#filter-control').on('click', '#trip', function () { //clear the input form
var str = $('#filter-control #input').val().trim(); $('#filter-control input[type=text]').val('');
$('#filter-control #input').val('');
blacklist.add.trip(str); addFilter(type, value, useRegex);
drawFilterList();
}); });
$('#filter-control').on('click', '#clear', function () { $('#filter-control').on('click', '#clear', function () {
$('#filter-control #clear').addClass('hidden'); $('#filter-control #clear').addClass('hidden');
@ -592,7 +652,7 @@ if (active_page === 'thread' || active_page === 'index') {
$('#filter-control #clear').removeClass('hidden'); $('#filter-control #clear').removeClass('hidden');
$('#filter-control #confirm').addClass('hidden'); $('#filter-control #confirm').addClass('hidden');
setList({ setList({
nameFilter: [], generalFilter: [],
postFilter: {}, postFilter: {},
nextPurge: {}, nextPurge: {},
lastPurge: timestamp() lastPurge: timestamp()
@ -612,9 +672,11 @@ if (active_page === 'thread' || active_page === 'index') {
e.preventDefault(); e.preventDefault();
var $ele = $(e.target); var $ele = $(e.target);
var type = $ele.attr('data-type'); var type = $ele.data('type');
var val = $ele.attr('data-val'); var val = $ele.data('val');
blacklist.remove[type](val); var useRegex = $ele.data('useRegex');
removeFilter(type, val, useRegex);
}); });
} }
} }
@ -684,13 +746,40 @@ if (active_page === 'thread' || active_page === 'index') {
function init() { function init() {
if (typeof localStorage.postFilter === 'undefined') { if (typeof localStorage.postFilter === 'undefined') {
localStorage.postFilter = JSON.stringify({ localStorage.postFilter = JSON.stringify({
nameFilter: [], generalFilter: [],
postFilter: {}, postFilter: {},
nextPurge: {}, nextPurge: {},
lastPurge: timestamp() lastPurge: timestamp()
}); });
} }
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Migrate from previous version of post filter
* Remember to remove next time anyone touches this file
*/
(function () {
var list = getList();
if (typeof list.nameFilter != 'undefined') {
var filter = list.nameFilter;
list.generalFilter = [];
for (var i = 0; i < filter.length; i++) {
var obj = filter[i];
for (var key in obj) {
list.generalFilter.push({
type: key,
value: obj[key],
regex: false
});
}
}
delete list.nameFilter;
localStorage.postFilter = JSON.stringify(list);
}
})();
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
var pageData = { var pageData = {
boardId: board_name, // get the id from the global variable boardId: board_name, // get the id from the global variable
localList: [], // all the blacklisted post IDs or UIDs that apply to the current page localList: [], // all the blacklisted post IDs or UIDs that apply to the current page