From f3ed76f32f14df3f6a988e1214c921152bf99b52 Mon Sep 17 00:00:00 2001 From: ccd0 Date: Sat, 6 Apr 2019 05:57:16 -0700 Subject: [PATCH] Support specifying the sites that filters apply to. #2171 --- src/Filtering/Filter.coffee | 51 ++++++++++++++------------ src/General/Build.coffee | 3 +- src/General/Settings/Filter-guide.html | 7 +++- src/Monitoring/ThreadWatcher.coffee | 4 +- src/classes/Post.coffee | 1 + src/site/SW.yotsuba.coffee | 3 ++ src/site/Site.coffee | 13 ++++--- 7 files changed, 48 insertions(+), 34 deletions(-) diff --git a/src/Filtering/Filter.coffee b/src/Filtering/Filter.coffee index 17de5c286..a98ac59a9 100644 --- a/src/Filtering/Filter.coffee +++ b/src/Filtering/Filter.coffee @@ -7,9 +7,6 @@ Filter = unless Conf['Filtered Backlinks'] $.addClass doc, 'hide-backlinks' - nsfwBoards = BoardConfig.sfwBoards(false).join(',') - sfwBoards = BoardConfig.sfwBoards(true).join(',') - for key of Config.filter for line in Conf[key].split '\n' continue if line[0] is '#' @@ -20,26 +17,11 @@ Filter = # Don't mix up filter flags with the regular expression. filter = line.replace regexp[0], '' - # Comma-separated list of the boards this filter applies to. - # Defaults to global. - boardsRaw = filter.match(/boards:([^;]+)/)?[1].toLowerCase() - if boardsRaw - boards = {} - for board in boardsRaw.replace('nsfw', nsfwBoards).replace('sfw', sfwBoards).split(',') - boards[board] = true - else - boards = false + # List of the boards this filter applies to. + boards = @parseBoards filter.match(/boards:([^;]+)/)?[1] - # boards to exclude from an otherwise global rule - # due to the sfw and nsfw keywords, also works on all filters - # replaces 'nsfw' and 'sfw' for consistency - excludesRaw = filter.match(/exclude:([^;]+)/)?[1].toLowerCase() - if excludesRaw - excludes = {} - for board in excludesRaw.replace('nsfw', nsfwBoards).replace('sfw', sfwBoards).split(',') - excludes[board] = true - else - excludes = false + # Boards to exclude from an otherwise global rule. + excludes = @parseBoards filter.match(/exclude:([^;]+)/)?[1] if (isstring = (key in ['uniqueID', 'MD5'])) # MD5 filter will use strings instead of regular expressions. @@ -111,6 +93,25 @@ Filter = name: 'Filter' cb: @node + # Parse comma-separated list of boards. + # Sites can be specified by a beginning part of the site domain followed by a colon. + parseBoards: (boardsRaw) -> + return false unless boardsRaw + boardsRaw = boardsRaw.toLowerCase() + boards = {} + siteFilter = '' + for boardID in boardsRaw.split(',') + if ':' in boardID + [siteFilter, boardID] = boardID.split(':')[-2..] + for siteID, siteProperties of Conf['siteProperties'] + continue if siteProperties.canonical or siteID[...siteFilter.length] isnt siteFilter + if boardID in ['nsfw', 'sfw'] + for boardID2 of SW[siteProperties.software]?.sfwBoards?(boardID is 'sfw') or [] + boards["#{siteID}/#{boardID2}"] = true + else + boards["#{siteID}/#{boardID}"] = true + boards + test: (post, hideable=true) -> return post.filterResults if post.filterResults hide = false @@ -122,12 +123,14 @@ Filter = hideable = false mask = (if post.isReply then 2 else 1) mask = (mask | (if post.file then 4 else 8)) + board = "#{post.siteID}/#{post.boardID}" + site = "#{post.siteID}/*" for key of Filter.filters when ((value = Filter.value key, post)?) # Continue if there's nothing to filter (no tripcode for example). for filter in Filter.filters[key] continue if ( - (filter.boards and !filter.boards[post.boardID]) or - (filter.excludes and filter.excludes[post.boardID]) or + (filter.boards and !(filter.boards[board] or filter.boards[site] )) or + (filter.excludes and (filter.excludes[board] or filter.excludes[site])) or (filter.mask & mask) or (if filter.isstring then (filter.regexp isnt value) else !filter.regexp.test(value)) ) diff --git a/src/General/Build.coffee b/src/General/Build.coffee index 9eca7e15e..dda5f49f1 100644 --- a/src/General/Build.coffee +++ b/src/General/Build.coffee @@ -31,12 +31,13 @@ Build = else "/#{boardID}/thread/#{threadID}#p#{postID}" - parseJSON: (data, boardID) -> + parseJSON: (data, boardID, siteID) -> o = # id ID: data.no threadID: data.resto or data.no boardID: boardID + siteID: siteID or Site.hostname isReply: !!data.resto # thread status isSticky: !!data.sticky diff --git a/src/General/Settings/Filter-guide.html b/src/General/Settings/Filter-guide.html index 3099a15cb..8a6a3ea84 100644 --- a/src/General/Settings/Filter-guide.html +++ b/src/General/Settings/Filter-guide.html @@ -9,9 +9,14 @@
  • Per boards, separate them with commas. It is global if not specified. Use sfw and nsfw to reference all worksafe or not-worksafe boards.
    For example: boards:a,jp;.
    + To specify boards on a particular site, put the beginning of the domain and a slash character before the list.
    + Any initial www. should not be included, and all 4chan domains are considered 4chan.org.
    + For example: boards:4:a,jp,sama:a,z;.
    + An asterisk can be used to specify all boards on a site.
    + For example: boards:4:*;.
  • - In case of a global rule or one that uses sfw/nsfw, select boards to be excluded from the filter.
    + Select boards to be excluded from the filter. The syntax is the same as for the boards: option above.
    For example: exclude:vg,v;.
  • diff --git a/src/Monitoring/ThreadWatcher.coffee b/src/Monitoring/ThreadWatcher.coffee index d245ac1c3..c4d907084 100644 --- a/src/Monitoring/ThreadWatcher.coffee +++ b/src/Monitoring/ThreadWatcher.coffee @@ -349,7 +349,7 @@ ThreadWatcher = unread++ - if !quotingYou and !Conf['Require OP Quote Link'] and youOP and not Filter.isHidden(Build.parseJSON postObj, boardID) + if !quotingYou and !Conf['Require OP Quote Link'] and youOP and not Filter.isHidden(Build.parseJSON postObj, boardID, siteID) quotingYou = true continue @@ -367,7 +367,7 @@ ThreadWatcher = } quotesYou = true break - if quotesYou and not Filter.isHidden(Build.parseJSON postObj, boardID) + if quotesYou and not Filter.isHidden(Build.parseJSON postObj, boardID, siteID) quotingYou = true ThreadWatcher.update siteID, boardID, threadID, {last, replies, isDead, unread, quotingYou} diff --git a/src/classes/Post.coffee b/src/classes/Post.coffee index 7720e5171..a913a5829 100644 --- a/src/classes/Post.coffee +++ b/src/classes/Post.coffee @@ -9,6 +9,7 @@ class Post @ID = +root.id.match(/\d*$/)[0] @threadID = @thread.ID @boardID = @board.ID + @siteID = Site.hostname @fullID = "#{@board}.#{@ID}" @context = @ @isReply = (@ID isnt @threadID) diff --git a/src/site/SW.yotsuba.coffee b/src/site/SW.yotsuba.coffee index b96aeb2dc..cb25f01c9 100644 --- a/src/site/SW.yotsuba.coffee +++ b/src/site/SW.yotsuba.coffee @@ -151,3 +151,6 @@ SW.yotsuba = hasCORS: (url) -> url.split('/')[...3].join('/') is location.protocol + '//a.4cdn.org' + + sfwBoards: (sfw) -> + BoardConfig.sfwBoards(sfw) diff --git a/src/site/Site.coffee b/src/site/Site.coffee index 099dd81ee..52165d8a1 100644 --- a/src/site/Site.coffee +++ b/src/site/Site.coffee @@ -1,17 +1,19 @@ Site = defaultProperties: '4chan.org': {software: 'yotsuba'} - '4channel.org': {software: 'yotsuba'} - '4cdn.org': {software: 'yotsuba'} + '4channel.org': {canonical: '4chan.org'} + '4cdn.org': {canonical: '4chan.org'} init: (cb) -> $.extend Conf['siteProperties'], Site.defaultProperties {hostname} = location while hostname and hostname not of Conf['siteProperties'] hostname = hostname.replace(/^[^.]*\.?/, '') - if hostname and Conf['siteProperties'][hostname].software of SW - @set hostname - cb() + if hostname + hostname = canonical if (canonical = Conf['siteProperties'][hostname].canonical) + if Conf['siteProperties'][hostname].software of SW + @set hostname + cb() $.onExists doc, 'body', => for software of SW when (changes = SW[software].detect?()) changes.software = software @@ -32,5 +34,4 @@ Site = set: (@hostname) -> @properties = Conf['siteProperties'][@hostname] @software = @properties.software - @hostname = '4chan.org' if @software is 'yotsuba' $.extend @, SW[@software]