This repository has been archived by the owner on Jun 16, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BlockListHide.js
604 lines (587 loc) · 41.3 KB
/
BlockListHide.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
// ==UserScript==
// @name 巴哈黑名單、關鍵詞、字數過少隱藏顯示
// @namespace https://home.gamer.com.tw/moontai0724
// @version 2.4.9
// @description 在巴哈姆將黑名單、關鍵詞、字數過少過濾文章留言,在頂端列可以開關過濾器(一次性)
// @author moontai0724
// @match https://forum.gamer.com.tw/B.php*
// @match https://forum.gamer.com.tw/Bo.php*
// @match https://forum.gamer.com.tw/C.php*
// @match https://forum.gamer.com.tw/Co.php*
// @match https://forum.gamer.com.tw/search.php*
// @grant GM_xmlhttpRequest
// @connect home.gamer.com.tw
// @require https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js
// @supportURL https://home.gamer.com.tw/moontai0724
// @license MIT
// ==/UserScript==
(function () {
'use strict';
console.log('Start, varsion: ' + GM_info.script.version + ', setting: ', localStorage.getItem("BLH_Setting"));
if (!localStorage.getItem("BLH_Setting") || JSON.parse(localStorage.getItem("BLH_Setting")) == null)
(localStorage.setItem("BLH_Setting", JSON.stringify({
switch: {
keywordPostFilter: true,
keywordCommentFilter: true,
blacklistPostFilter: true,
blacklistCommentFilter: true,
contentLengthPostFilter: false,
contentLengthCommentFilter: false,
},
lengthLimit: {
contentLengthPostLimit: 2,
contentLengthCommentLimit: 2
},
data: {
forceShowList: [],
forceHideList: [],
blockKeywordsPC: [],
postBlockKeywordsPC: [],
commentBlockKeywordsPC: [],
blockKeywordsFC: [],
postBlockKeywordsFC: [],
commentBlockKeywordsFC: []
}
})), console.log('New Setting'));
var setting = JSON.parse(localStorage.getItem("BLH_Setting"));
// 加入隱藏切換
jQuery('head').append('<style type="text/css" id="BLH_BlockHideCSS">.BlockHide { display: none !important; }</style>');
jQuery('.BH-menuE').append('<li><a id="BLH_ShowBlock" href="javascript:;" style="display: block;" onclick="BlockDisplay(true);">關閉過濾器</a></li>');
jQuery('.BH-menuE').append('<li><a id="BLH_HideBlock" href="javascript:;" style="display: none;" onclick="BlockDisplay(false);">開啟過濾器</a></li>');
jQuery('.BH-menuE').append('<li><a id="BLH_FilterSetting" href="javascript:;" style="display: block;">過濾器設定</a></li>');
jQuery('body').append('<script type="text/javascript">' + function BlockDisplay(status) {
document.getElementById('BLH_HideBlock').style.display = status ? 'block' : 'none';
document.getElementById('BLH_ShowBlock').style.display = status ? 'none' : 'block';
document.getElementById('BLH_BlockHideCSS').innerHTML = document.getElementById('BLH_BlockHideCSS').innerHTML.replace(status ? 'BlockHide' : 'noBlockHide', status ? 'noBlockHide' : 'BlockHide');
} + '</script>');
document.getElementById('BLH_FilterSetting').onclick = () => openSettingWindow();
// 將 blockKeywords 加入 postBlockKeywords 和 commentBlockKeywords 中
for (let i = 0; i < setting.data.blockKeywordsPC.length; i++) setting.data.postBlockKeywordsPC[setting.data.postBlockKeywordsPC.length] = setting.data.commentBlockKeywordsPC[setting.data.commentBlockKeywordsPC.length] = setting.data.blockKeywordsPC[i];
for (let i = 0; i < setting.data.blockKeywordsFC.length; i++) setting.data.postBlockKeywordsFC[setting.data.postBlockKeywordsFC.length] = setting.data.commentBlockKeywordsFC[setting.data.commentBlockKeywordsFC.length] = setting.data.blockKeywordsFC[i];
//BC頁分開
switch (location.pathname) {
case '/B.php':
console.group('Filter log message');
setTimeout(() => console.groupEnd(), 200);
// blacklist post filter
if (setting.switch.blacklistPostFilter) startFilter('blacklist', 'post', '.b-list__count__user>a', '.b-list__row');
// keywords post title filter
if (setting.switch.keywordPostFilter) (startFilter('postBlockKeywordsPC', 'post', '.b-list__main__title', '.b-list__row'), startFilter('postBlockKeywordsFC', 'post', '.b-list__main__title', '.b-list__row'));
// popular recommend title filter
if (setting.switch.keywordPostFilter) (startFilter('postBlockKeywordsPC', 'post', '.popular .name', '.popular__item'), startFilter('postBlockKeywordsFC', 'post', '.popular .name', '.popular__item'));
break;
case '/C.php': case '/Co.php':
console.group('Filter log message');
setTimeout(() => console.groupEnd(), 200);
// 擷取展開按鈕事件:當展開留言按鈕被點擊,執行原生展開留言指令並處理內容
jQuery('body').append('<button id="extendCommentListener" style="display: none;"></button>');
jQuery('.more-reply').each((index, element) => element.setAttribute("onclick", element.getAttribute("onclick") + " [document.getElementById('extendCommentListener').dataset.bsn, document.getElementById('extendCommentListener').dataset.postid] = [" + element.getAttribute('onclick').replace('extendComment(', '').replace(');', '').split(', ') + "]; jQuery('#Commendlist_" + element.getAttribute('onclick').replace('extendComment(', '').replace(');', '').split(', ')[1] + "').append('<div id=\"extendCommentAreaListener\"></div>'); document.getElementById('extendCommentListener').click();"));
// 當按鈕點擊就執行
document.getElementById('extendCommentListener').onclick = function () {
let [bsn, postid] = [document.getElementById('extendCommentListener').dataset.bsn, document.getElementById('extendCommentListener').dataset.postid], times = 0, ms = 0;
setTimeout(function restartFilter(ms) {
setTimeout(function () {
if (!document.getElementById('extendCommentAreaListener')) {
jQuery('#Commendlist_' + postid).each((index, element) => {
if (setting.switch.blacklistCommentFilter) {
getBlackList().then(BlackList => jQuery(element).find('.reply-content__user').each((index, value) => {
if (BlackList.includes(value.href.replace('https://home.gamer.com.tw/', '').toLowerCase())) {
jQuery(value).parents('.c-reply__item').addClass('BlockHide');
console.log('Hid a comment with block user: ' + value.innerText.toLowerCase(), jQuery(value).parents('.c-reply__item'));
}
}));
}
if (setting.switch.keywordCommentFilter) {
jQuery(element).find('.reply-content__article').each((index, value) => {
setting.data.commentBlockKeywordsPC.forEach(data => {
if (value.innerText.toLowerCase().includes(data)) {
jQuery(value).parents('.c-reply__item').addClass('BlockHide');
console.log('Hid a post includes keyword: ' + data, jQuery(value).parents('.c-reply__item'));
}
});
setting.data.commentBlockKeywordsFC.forEach(data => {
if (value.innerText.toLowerCase() == data) {
jQuery(value).parents('.c-reply__item').addClass('BlockHide');
console.log('Hid a post includes keyword: ' + data, jQuery(value).parents('.c-reply__item'));
}
});
});
}
if (setting.switch.contentLengthCommentFilter) {
jQuery(element).find('.reply-content__article').each((index, value) => {
let data = value.innerText.replace(/\s/g, '').length;
if (data < setting.lengthLimit.contentLengthCommentLimit) {
jQuery(value).parents('.c-reply__item').addClass('BlockHide');
console.log('Hid a comment less then setting text totalLength limit: ' + setting.lengthLimit.contentLengthCommentLimit, data, jQuery(value).parents('.c-reply__item'));
}
});
}
});
} else if (times++ < 50) restartFilter(100);
}, ms);
});
};
// blacklist post filter
if (setting.switch.blacklistPostFilter) startFilter('blacklist', 'post', '.c-post__header__author>.userid', '.c-section');
// blacklist comment filter
if (setting.switch.blacklistCommentFilter) startFilter('blacklist', 'comment', '.reply-content__user', '.c-reply__item');
// keywords post filter
if (setting.switch.keywordPostFilter) (startFilter('postBlockKeywordsPC', 'post', '.c-article.FM-P2', '.c-section'), startFilter('postBlockKeywordsFC', 'post', '.c-article.FM-P2', '.c-section'));
// keywords comment filter
if (setting.switch.keywordCommentFilter) (startFilter('commentBlockKeywordsPC', 'post', '.reply-content__article', '.c-reply__item'), startFilter('commentBlockKeywordsFC', 'post', '.reply-content__article', '.c-reply__item'));
// post content length filter
if (setting.switch.contentLengthPostFilter) startFilter('contentLengthPostLimit', 'post', '.c-article.FM-P2', '.c-section');
// comment content length filter
if (setting.switch.contentLengthCommentFilter) startFilter('contentLengthCommentLimit', 'comment', '.reply-content__article', '.c-reply__item');
// popular recommend title filter
if (setting.switch.keywordPostFilter) (startFilter('postBlockKeywordsPC', 'post', '.popular .name', '.popular__item'), startFilter('postBlockKeywordsFC', 'post', '.popular .name', '.popular__item'));
break;
case '/Bo.php':
console.group('Filter log message');
setTimeout(() => console.groupEnd(), 200);
// blacklist post filter
if (setting.switch.blacklistPostFilter) startFilter('blacklist', 'post', '.FM-blist6>a[href*="home.gamer.com.tw"]', 'tr');
// keywords post title filter
if (setting.switch.keywordPostFilter) (startFilter('postBlockKeywordsPC', 'post', '.FM-blist3', 'tr'), startFilter('postBlockKeywordsFC', 'post', '.FM-blist3', 'tr'));
break;
case '/search.php':
setTimeout(function restartFilter(ms) {
setTimeout(() => {
if (jQuery('.gsc-table-cell-snippet-close').length > 0) {
console.group('Filter log message');
setTimeout(() => console.groupEnd(), 100);
if (setting.switch.keywordPostFilter) (startFilter('postBlockKeywordsPC', 'post', '.gsc-table-cell-snippet-close', '.gsc-result'), startFilter('postBlockKeywordsFC', 'post', '.gsc-table-cell-snippet-close', '.gsc-result'));
} else restartFilter(100);
}, ms);
});
break;
}
function startFilter(filterType, elementType, target, hideClass) {
if (filterType.includes('Keyword') && filterType.includes('PC')) {
console.log('Keyword part compare filter start.');
jQuery(target).each((index, element) => setting.data[filterType].forEach(value => {
if (element.innerText.toLowerCase().replace(/\s/g, '').includes(value)) {
jQuery(element).parents(hideClass).addClass('BlockHide');
console.log('Hid a ' + elementType + ' includes keyword: ' + value, jQuery(element).parents(hideClass));
}
}));
} else if (filterType.includes('Keyword') && filterType.includes('FC')) {
console.log('Keyword full compare filter start.');
jQuery(target).each((index, element) => setting.data[filterType].forEach(value => {
if (element.innerText.toLowerCase().replace(/\s/g, '') == value) {
jQuery(element).parents(hideClass).addClass('BlockHide');
console.log('Hid a ' + elementType + ' includes keyword: ' + value, jQuery(element).parents(hideClass));
}
}));
} else if (filterType.includes('blacklist')) {
console.log('Blacklist filter start.');
getBlackList().then(BlackList => jQuery(target).each((index, element) => {
if (BlackList.includes(element.href.replace('https://home.gamer.com.tw/', '').toLowerCase())) {
jQuery(element).parents(hideClass).addClass('BlockHide');
console.log('Hid a ' + elementType + ' with block user: ' + element.href.replace('https://home.gamer.com.tw/', '').toLowerCase(), jQuery(element).parents(hideClass));
}
}));
} else if (filterType.includes('Length')) {
console.log('content length filter start.');
jQuery(target).each((index, element) => {
let value = element.innerText.replace(/\s/g, '').length;
if (value < setting.lengthLimit[filterType]) {
jQuery(element).parents(hideClass).addClass('BlockHide');
console.log('Hid a ' + elementType + ' less then setting text totalLength limit: ' + setting.lengthLimit[filterType], value, jQuery(element).parents(hideClass));
}
});
}
}
function BlackListHandle(BlackList) {
let removeNum = [];
setting.data.forceHideList.forEach(value => BlackList.includes(value.replace(/\s/g, '').toLowerCase()) ? void (0) : BlackList[BlackList.length] = value.replace(/\s/g, '').toLowerCase());
BlackList.forEach((value, index) => setting.data.forceShowList.includes(value.toLowerCase()) ? removeNum[removeNum.length] = index : void (0));
for (let i = removeNum.length - 1; i >= 0; i--) BlackList.splice(removeNum[i], 1);
console.log('BlackList handle process over, returned blacklist: ', BlackList);
return BlackList;
}
function getBlackList(forceReload) {
return new Promise(resolve => {
console.log('Received get blacklist request!');
if (localStorage.getItem('BHBlackList') && !forceReload) {
let BHBlackList = JSON.parse(localStorage.getItem('BHBlackList')), today = new Date((new Date()).getFullYear(), (new Date()).getMonth(), (new Date()).getDate(), 0, 0, 0, 0);
if (today.getTime() < BHBlackList.time && BHBlackList.time < today.getTime() + 86400000) {
console.log('Already requested blacklist today, resolve.');
resolve(BlackListHandle(BHBlackList.BlackList));
} else {
console.log('Today not requested blacklist yet, start request.');
getBlackList(true).then(data => resolve(BlackListHandle(data)));
}
} else {
console.log('Start get blacklist from Bahamut server.');
GM_xmlhttpRequest({
method: "GET",
url: "https://home.gamer.com.tw/ajax/friend_getData.php?here=0",
onload: data => {
console.log(data);
let list = data.responseText.match(/data\-gamercard\-userid\=\"[\s\S]*?\"/g);
let BlackList = list != (null || undefined) ? list.map(value => value.replace(/data\-gamercard\-userid\=\"|\"/g, '').toLowerCase()) : [];
console.log('Get blacklist data from Bahamut server.');
localStorage.setItem('BHBlackList', JSON.stringify({ time: new Date().getTime(), BlackList: BlackList }));
resolve(BlackListHandle(BlackList));
},
onerror: err => console.error('Responsed Error: ', err),
ontimeout: err => console.error('Response timeout: ', err)
});
}
});
}
function openSettingWindow() {
// black background
let BLH_SW_Background = document.createElement("div");
BLH_SW_Background.id = "BLH_SW_Background";
BLH_SW_Background.setAttribute("onmousedown", "javascript:if(!jQuery(this).hasClass('mouseenter')) jQuery('#BLH_SW_Background').remove();");
BLH_SW_Background.style = "background-color: rgba(0, 0, 0, 0.5); z-index: 95; position: fixed; top: 0px; bottom: 0px; left: 0px; right: 0px; width: 100%; height: 100%; padding-top: 35px;" +
" border: 1px solid #a7c7c8;" +
" display: flex; align-items: center; justify-content: center;" +
" -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;";
document.body.appendChild(BLH_SW_Background);
// window case
let BLH_SW_Case = document.createElement("div");
BLH_SW_Case.id = "BLH_SW_Case";
BLH_SW_Case.setAttribute("onmouseenter", "javascipt:jQuery('#BLH_SW_Background').addClass('mouseenter');");
BLH_SW_Case.setAttribute("onmouseleave", "javascipt:jQuery('#BLH_SW_Background').removeClass('mouseenter');");
BLH_SW_Case.style = "position: absolute; height: 80%; width: 90%; overflow: hidden;" +
" display: flex; align-item: stretch; flex-direction: column;" +
" background-color: #FFFFFF; border: 1px solid #a7c7c8;";
document.getElementById("BLH_SW_Background").appendChild(BLH_SW_Case);
// title
let BLH_SW_Title = document.createElement("div");
BLH_SW_Title.setAttribute("style", "display: flex; align-items: center; justify-content: center; width: 100%; min-height: 35px;" +
" background-color: #E5F7F8; color: #484b4b;" +
" font-size: 22px; font-weight: bold; font-family: '微軟正黑體', 'Microsoft JhengHei', '黑體-繁', '蘋果儷中黑', 'sans-serif';");
BLH_SW_Title.innerHTML = "過濾器設定";
document.getElementById("BLH_SW_Case").appendChild(BLH_SW_Title);
// content
let BLH_SW_Content = document.createElement("div");
BLH_SW_Content.id = "BLH_SW_Content";
BLH_SW_Content.setAttribute("style", "display: flex; align-items: center; justify-content: center; flex-flow: row wrap; flex-grow: 1; overflow: auto; padding: 10px;" +
" background-color: #FFFFFF;" +
" word-break: break-all; font-size: 16px; line-height: 150%; text-align: center; font-family: 微軟正黑體, Microsoft JhengHei, 黑體-繁, 蘋果儷中黑, sans-serif;" +
" -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box;");
document.getElementById("BLH_SW_Case").appendChild(BLH_SW_Content);
// bottom element
let BLH_SW_BottomArea = document.createElement("div");
BLH_SW_BottomArea.id = "BLH_SW_BottomArea";
BLH_SW_BottomArea.style = "display: flex; align-items: center; justify-content: center;" +
" background-color: #E5F7F8;" +
" width: 100%; min-height: 35px;";
document.getElementById('BLH_SW_Case').appendChild(BLH_SW_BottomArea);
// close button
let BLH_SW_CloseButton = document.createElement('button');
BLH_SW_CloseButton.innerHTML = '完成';
BLH_SW_CloseButton.setAttribute("onclick", "jQuery('#BLH_SW_Background').remove();");
document.getElementById('BLH_SW_BottomArea').appendChild(BLH_SW_CloseButton);
// content
jQuery('#BLH_SW_Content').append(`
<div style="padding: 10px; border: 1px solid; border-radius: 10px; margin: 10px; background: antiquewhite;">
切換
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; background: beige;">
黑名單過濾
<div style="display: flex; align-items: center; border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px;">
黑名單文章過濾:
<span id="blacklistPostFilter"></span>
<button style="margin: 5px;" onclick="BLH_switch('blacklistPostFilter');">切換</button>
</div>
<div style="display: flex; align-items: center; border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px;">
黑名單留言過濾:
<span id="blacklistCommentFilter"></span>
<button style="margin: 5px;" onclick="BLH_switch('blacklistCommentFilter');">切換</button>
</div>
</div>
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; background: beige;">
關鍵詞過濾
<div style="display: flex; align-items: center; border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px;">
關鍵詞文章過濾:
<span id="keywordPostFilter"></span>
<button style="margin: 5px;" onclick="BLH_switch('keywordPostFilter');">切換</button>
</div>
<div style="display: flex; align-items: center; border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px;">
關鍵詞留言過濾:
<span id="keywordCommentFilter"></span>
<button style="margin: 5px;" onclick="BLH_switch('keywordCommentFilter');">切換</button>
</div>
</div>
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; background: beige;">
字數過濾
<div style="display: flex; align-items: center; border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px;">
文章字數過濾:
<span id="contentLengthPostFilter"></span>
<button style="margin: 5px;" onclick="BLH_switch('contentLengthPostFilter');">切換</button>
</div>
<div style="display: flex; align-items: center; border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px;">
留言字數過濾:
<span id="contentLengthCommentFilter"></span>
<button style="margin: 5px;" onclick="BLH_switch('contentLengthCommentFilter');">切換</button>
</div>
</div>
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; background: beige;">
字數過濾
<div style="display: flex; align-items: center; border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px;">
文章字數下限:
<span id="contentLengthPostLimit"></span>
<button style="margin: 5px;" onclick="BLH_lengthLimit('contentLengthPostLimit');">變更</button>
</div>
<div style="display: flex; align-items: center; border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px;">
留言字數下限:
<span id="contentLengthCommentLimit"></span>
<button style="margin: 5px;" onclick="BLH_lengthLimit('contentLengthCommentLimit');">變更</button>
</div>
</div>
</div>
</div>
<div style="width: 100%; margin: 10px; padding: 10px; border: 1px solid; border-radius: 10px; background: antiquewhite;">
部分符合關鍵詞封鎖(不分大小寫)<br>
當設定在此處,文章或留言只要部分符合這個內容就會被過濾。<br>
當設定在全域變數中,下方就不需再設定同樣的字詞(系統會體醒已在全域過濾清單中有)。<br>
當文章與留言都有相同的變數,會自動改到全域變數中。
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; width: 90%; background: beige;">
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
全域過濾關鍵詞(文章與留言皆會過濾)
<button style="margin: 5px;" onclick="BLH_addFilter('blockKeywordsPC');">新增</button>
<button style="margin: 5px;" onclick="BLH_removeFilter('blockKeywordsPC');">移除選取</button>
</div>
<div id="blockKeywordsPC" style="display: flex; flex-flow: row wrap; width: 90%; padding: 10px;">
</div>
</div>
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; width: 45%; background: beige;">
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
文章過濾關鍵詞
<button style="margin: 5px;" onclick="BLH_addFilter('postBlockKeywordsPC');">新增</button>
<button style="margin: 5px;" onclick="BLH_removeFilter('postBlockKeywordsPC');">移除選取</button>
</div>
<div id="postBlockKeywordsPC" style="display: flex; flex-flow: row wrap; width: 90%; padding: 10px;">
</div>
</div>
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; width: 45%; background: beige;">
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
留言過濾關鍵詞
<button style="margin: 5px;" onclick="BLH_addFilter('commentBlockKeywordsPC');">新增</button>
<button style="margin: 5px;" onclick="BLH_removeFilter('commentBlockKeywordsPC');">移除選取</button>
</div>
<div id="commentBlockKeywordsPC" style="display: flex; flex-flow: row wrap; width: 90%; padding: 10px;">
</div>
</div>
</div>
</div>
<div style="width: 100%; margin: 10px; padding: 10px; border: 1px solid; border-radius: 10px; background: antiquewhite;">
完全符合關鍵詞封鎖(不分大小寫)<br>
當設定在此處,文章或留言必須完全符合這個內容才會被過濾。<br>
當設定在全域變數中,下方就不需再設定同樣的字詞(系統會體醒已在全域過濾清單中有)。<br>
當文章與留言都有相同的變數,會自動改到全域變數中。
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; width: 90%; background: beige;">
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
全域過濾關鍵詞(文章與留言皆會過濾)
<button style="margin: 5px;" onclick="BLH_addFilter('blockKeywordsFC');">新增</button>
<button style="margin: 5px;" onclick="BLH_removeFilter('blockKeywordsFC');">移除選取</button>
</div>
<div id="blockKeywordsFC" style="display: flex; flex-flow: row wrap; width: 90%; padding: 10px;">
</div>
</div>
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; width: 45%; background: beige;">
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
文章過濾關鍵詞
<button style="margin: 5px;" onclick="BLH_addFilter('postBlockKeywordsFC');">新增</button>
<button style="margin: 5px;" onclick="BLH_removeFilter('postBlockKeywordsFC');">移除選取</button>
</div>
<div id="postBlockKeywordsFC" style="display: flex; flex-flow: row wrap; width: 90%; padding: 10px;">
</div>
</div>
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; width: 45%; background: beige;">
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
留言過濾關鍵詞
<button style="margin: 5px;" onclick="BLH_addFilter('commentBlockKeywordsFC');">新增</button>
<button style="margin: 5px;" onclick="BLH_removeFilter('commentBlockKeywordsFC');">移除選取</button>
</div>
<div id="commentBlockKeywordsFC" style="display: flex; flex-flow: row wrap; width: 90%; padding: 10px;">
</div>
</div>
</div>
</div>
<div style="width: 100%; margin: 10px; padding: 10px; border: 1px solid; border-radius: 10px; background: antiquewhite;">
ID封鎖(不分大小寫)<button onclick="localStorage.removeItem('BHBlackList'); location.reload();">強制重獲取黑名單</button><br>
黑名單會自動獲取已經被黑名單的列表,但若要手動添加,可於上方參數進行添加。<br>
可以添加強制顯示、強制隱藏,這兩個參數會優先於黑名單列表。<br>
ID只能在強制顯示與強制隱藏其中一個清單內,不會有重複(輸入時會被提醒)。<br>
輸入的ID不分大小寫。
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; width: 45%; background: beige;">
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
顯示名單
<button style="margin: 5px;" onclick="BLH_addFilter('forceShowList');">新增</button>
<button style="margin: 5px;" onclick="BLH_removeFilter('forceShowList');">移除選取</button>
</div>
<div id="forceShowList" style="display: flex; flex-flow: row wrap; width: 90%; padding: 10px;">
</div>
</div>
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; width: 45%; background: beige;">
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
隱藏名單
<button style="margin: 5px;" onclick="BLH_addFilter('forceHideList');">新增</button>
<button style="margin: 5px;" onclick="BLH_removeFilter('forceHideList');">移除選取</button>
</div>
<div id="forceHideList" style="display: flex; flex-flow: row wrap; width: 90%; padding: 10px;">
</div>
</div>
</div>
</div>
<div style="margin: 10px; padding: 10px; border: 1px solid; border-radius: 10px; background: antiquewhite;">
其他設定
<div style="display: flex; align-items: center; justify-content: center; flex-flow: row wrap;">
<div style="border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px; background: beige;">
備份與還原
<div style="display: flex; align-items: center; border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px;">
備份:
<input type="text" readonly="" name="BLH_Setting_backupText">
<button style="margin: 5px;" onclick="document.getElementsByName('BLH_Setting_backupText')[0].value = localStorage.getItem('BLH_Setting');">手動獲取</button>
</div>
<div style="display: flex; align-items: center; justify-content: center; border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px;">
還原:
<button style="margin: 5px;" onclick="localStorage.setItem('BLH_Setting', window.prompt('請貼上設定檔:(將重新整理)')); location.reload();">還原</button>
</div>
<div style="display: flex; align-items: center; justify-content: center; border: 1px solid; padding: 5px; margin: 10px; border-radius: 10px;">
還原初始設定:
<button style="margin: 5px;" onclick="if(window.confirm('確定要還原初始設定?還原後將重新整理。')) (localStorage.removeItem('BLH_Setting'), location.reload()); ">還原</button>
</div>
</div>
</div>
</div>
`);
let setting = JSON.parse(localStorage.getItem("BLH_Setting"));
for (let key in setting.switch) {
document.getElementById(key).innerHTML = (setting.switch[key] ? '開' : '關');
document.getElementById(key).parentNode.style.color = setting.switch[key] ? 'olive' : 'crimson';
}
for (let key in setting.lengthLimit) document.getElementById(key).innerHTML = setting.lengthLimit[key];
for (let key in setting.data) {
for (let i = 0; i < setting.data[key].length; i++) {
jQuery('#' + key).append(`<div style="margin: 10px;" data-value="` + encodeURIComponent(setting.data[key][i]) + `"><input type="checkbox"><span onclick="jQuery(this).parent().find('input').prop('checked', !jQuery(this).parent().find('input').prop('checked'));">` + setting.data[key][i] + `</span></div>`);
}
}
}
jQuery('body').append('<script type="text/javascript">' + function BLH_switch(key) {
let setting = JSON.parse(localStorage.getItem("BLH_Setting"));
setting.switch[key] = !setting.switch[key];
localStorage.setItem('BLH_Setting', JSON.stringify(setting));
document.getElementById(key).innerHTML = (setting.switch[key] ? '開' : '關');
document.getElementById(key).parentNode.style.color = setting.switch[key] ? 'olive' : 'crimson';
console.log('Switch ' + key + ' to ' + setting.switch[key]);
} + function BLH_lengthLimit(key) {
let lengthLimit = window.prompt('請輸入不小於2之過濾字數,若輸入5將過濾4字,5字不過濾。');
console.log('Input: ' + lengthLimit);
if (lengthLimit == null) return false;
else lengthLimit = parseInt(lengthLimit);
if (isNaN(lengthLimit)) (window.alert('請輸入半形數字。'), console.log('Input value is not a number'));
else if (lengthLimit < 2) (window.alert('數值不得小於2'), console.log('Input value less then 2!'));
else {
let setting = JSON.parse(localStorage.getItem("BLH_Setting"));
setting.lengthLimit[key] = lengthLimit;
localStorage.setItem('BLH_Setting', JSON.stringify(setting));
document.getElementById(key).innerHTML = lengthLimit;
console.log('Set ' + key + ' to ' + lengthLimit);
}
} + function BLH_addFilter(key) {
let setting = JSON.parse(localStorage.getItem("BLH_Setting"));
let response = window.prompt('請輸入欲過濾' + (key.includes('force') ? '使用者ID(不分大小寫,非英數字會被過濾)' : '詞(不分大小寫,空白會被過濾。)'));
console.log('Input: ' + response);
if (response != null) response = key.includes('force') ? response.replace(/[^a-zA-Z0-9]/g, '').toLowerCase() : response.replace(/\s/g, '').toLowerCase();
else return false;
if (response != '' && response != null) {
let listInfo = {
forceShowList: {
id: 'forceShowList',
type: 'ID',
name: 'ID封鎖白名單',
equal: ['forceHideList']
}, forceHideList: {
id: 'forceHideList',
type: 'ID',
name: 'ID封鎖黑名單',
equal: ['forceShowList']
}, blockKeywordsPC: {
id: 'blockKeywordsPC',
type: '關鍵詞',
name: '全域關鍵詞部分符合封鎖清單',
equal: ['postBlockKeywordsPC', 'commentBlockKeywordsPC']
}, postBlockKeywordsPC: {
id: 'postBlockKeywordsPC',
type: '關鍵詞',
name: '文章關鍵詞部分符合封鎖清單',
partner: 'commentBlockKeywordsPC',
parent: 'blockKeywordsPC'
}, commentBlockKeywordsPC: {
id: 'commentBlockKeywordsPC',
type: '關鍵詞',
name: '留言關鍵詞部分符合封鎖清單',
partner: 'postBlockKeywordsPC',
parent: 'blockKeywordsPC'
}, blockKeywordsFC: {
id: 'blockKeywordsFC',
type: '關鍵詞',
name: '全域關鍵詞完全符合封鎖清單',
equal: ['postBlockKeywordsFC', 'commentBlockKeywordsFC']
}, postBlockKeywordsFC: {
id: 'postBlockKeywordsFC',
type: '關鍵詞',
name: '文章關鍵詞完全符合封鎖清單',
partner: 'commentBlockKeywordsFC',
parent: 'blockKeywordsFC'
}, commentBlockKeywordsFC: {
id: 'commentBlockKeywordsFC',
type: '關鍵詞',
name: '留言關鍵詞完全符合封鎖清單',
partner: 'postBlockKeywordsFC',
parent: 'blockKeywordsFC'
}
};
// 當清單中已經有的時候就提示並中止
if (setting.data[key].includes(response)) {
window.alert('清單中已經有此' + listInfo[key].type);
console.log('"' + response + '" already exist in ' + key + '.');
return false;
}
// 檢查其他清單中是不是已經有重複的
for (let listnum in listInfo[key].equal) {
if (setting.data[listInfo[key].equal[listnum]].includes(response)) {
if (window.confirm(listInfo[listInfo[key].equal[listnum]].name + ' 中已經有此' + listInfo[listInfo[key].equal[listnum]].type + ',是否從清單中移除並加到這個清單?')) {
setting.data[listInfo[key].equal[listnum]].splice(setting.data[listInfo[key].equal[listnum]].findIndex(element => element == response), 1);
jQuery('#' + listInfo[key].equal[listnum] + ' [data-value="' + encodeURIComponent(response) + '"]').remove();
console.log('Removed "' + response + '" from ' + listInfo[key].equal[listnum] + ' because it is ready to add to ' + key + '.');
} else {
console.log('"' + response + '" already exist in ' + listInfo[key].equal[listnum] + '.');
return false;
}
}
}
// 如果同位的另一個清單中有了就上放到父清單中
if (listInfo[key].partner && setting.data[listInfo[key].partner].includes(response)) {
setting.data[listInfo[key].partner].splice(setting.data[listInfo[key].partner].findIndex(element => element == response), 1);
jQuery('#' + listInfo[key].partner + ' [data-value="' + encodeURIComponent(response) + '"]').remove();
key = listInfo[key].parent;
console.log('Removed "' + response + '" from ' + listInfo[key].partner + ' because it is ready to add to ' + key + '.');
}
// 開始加入過濾詞
setting.data[key][setting.data[key].length] = response;
localStorage.setItem('BLH_Setting', JSON.stringify(setting));
jQuery('#' + key).append(`<div style="margin: 10px;" data-value="` + encodeURIComponent(response) + `"><input type="checkbox"><span onclick="jQuery(this).parent().find('input').prop('checked', !jQuery(this).parent().find('input').prop('checked'));">` + response + `</span></div>`);
console.log('Added ' + response + ' to ' + key + '.');
} else window.alert('輸入的內容錯誤。');
} + function BLH_removeFilter(key) {
let setting = JSON.parse(localStorage.getItem("BLH_Setting"));
let removeList = [];
jQuery('#' + key + ' input:checked').each((index, element) => {
console.log('Removed ' + jQuery(element).parent().attr('data-value') + ' from ' + key);
setting.data[key].splice(setting.data[key].findIndex(element => element == jQuery(element).parent().attr('data-value')), 1);
jQuery(element).parent().remove();
});
localStorage.setItem('BLH_Setting', JSON.stringify(setting));
} + '</script>');
})();