Start merging ccd0's 4chan X stuff
This commit is contained in:
parent
5449031e60
commit
6f84ae9abe
@ -1,7 +1,8 @@
|
|||||||
module.exports = (grunt) ->
|
module.exports = (grunt) ->
|
||||||
|
grunt.util.linefeed = '\n'
|
||||||
|
|
||||||
importHTML = (filename) ->
|
importHTML = (filename) ->
|
||||||
"\"\"\"#{grunt.file.read("src/General/html/#{filename}.html").replace(/^\s+|\s+$</gm, '').replace(/\n/g, '')}\"\"\""
|
"(innerHTML: #{JSON.stringify grunt.file.read("src/General/html/#{filename}.html").replace(/^\s+|\s+$</gm, '').replace(/\n/g, '')})"
|
||||||
|
|
||||||
html = (template) ->
|
html = (template) ->
|
||||||
parts = template.split /([\$&@]){([^}`]*)}/
|
parts = template.split /([\$&@]){([^}`]*)}/
|
||||||
@ -38,6 +39,8 @@ module.exports = (grunt) ->
|
|||||||
pkg = grunt.config 'pkg'
|
pkg = grunt.config 'pkg'
|
||||||
pkg.importHTML = importHTML
|
pkg.importHTML = importHTML
|
||||||
pkg.html = html
|
pkg.html = html
|
||||||
|
pkg.assert = assert
|
||||||
|
pkg.tests_enabled or= false
|
||||||
pkg
|
pkg
|
||||||
enumerable: true
|
enumerable: true
|
||||||
)
|
)
|
||||||
@ -52,17 +55,18 @@ module.exports = (grunt) ->
|
|||||||
'src/General/Build.coffee'
|
'src/General/Build.coffee'
|
||||||
'src/General/Get.coffee'
|
'src/General/Get.coffee'
|
||||||
'src/General/UI.coffee'
|
'src/General/UI.coffee'
|
||||||
'src/Filtering/*'
|
'src/General/CrossOrigin.coffee'
|
||||||
'src/Quotelinks/*'
|
'src/Filtering/**/*.coffee'
|
||||||
'src/Linkification/*'
|
'src/Quotelinks/**/*.coffee'
|
||||||
'src/Posting/QR.coffee'
|
'src/Posting/Captcha.coffee'
|
||||||
'src/Posting/*'
|
'src/Posting/**/*.coffee'
|
||||||
'src/Images/*'
|
'src/Images/**/*.coffee'
|
||||||
'src/Menu/*'
|
'src/Linkification/**/*.coffee'
|
||||||
'src/Monitoring/*'
|
'src/Menu/**/*.coffee'
|
||||||
'src/Archive/*'
|
'src/Monitoring/**/*.coffee'
|
||||||
'src/Theming/*'
|
'src/Archive/**/*.coffee'
|
||||||
'src/Miscellaneous/*'
|
'src/Miscellaneous/**/*.coffee'
|
||||||
|
'src/Theming/**/*.coffee'
|
||||||
'src/General/Navigate.coffee'
|
'src/General/Navigate.coffee'
|
||||||
'src/General/Settings.coffee'
|
'src/General/Settings.coffee'
|
||||||
'src/General/Main.coffee'
|
'src/General/Main.coffee'
|
||||||
|
|||||||
@ -1,23 +0,0 @@
|
|||||||
// ==UserScript==
|
|
||||||
// @name 4chan X
|
|
||||||
// @version 1.7.33
|
|
||||||
// @minGMVer 1.14
|
|
||||||
// @minFFVer 26
|
|
||||||
// @namespace 4chan-X
|
|
||||||
// @description Cross-browser userscript for maximum lurking on 4chan.
|
|
||||||
// @license MIT; https://github.com/ccd0/4chan-x/blob/master/LICENSE
|
|
||||||
// @match *://boards.4chan.org/*
|
|
||||||
// @match *://sys.4chan.org/*
|
|
||||||
// @match *://a.4cdn.org/*
|
|
||||||
// @match *://i.4cdn.org/*
|
|
||||||
// @grant GM_getValue
|
|
||||||
// @grant GM_setValue
|
|
||||||
// @grant GM_deleteValue
|
|
||||||
// @grant GM_listValues
|
|
||||||
// @grant GM_openInTab
|
|
||||||
// @grant GM_xmlhttpRequest
|
|
||||||
// @run-at document-start
|
|
||||||
// @updateURL https://ccd0.github.io/4chan-x/builds/4chan-X.meta.js
|
|
||||||
// @downloadURL https://ccd0.github.io/4chan-x/builds/4chan-X.user.js
|
|
||||||
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAACVBMVEUAAGcAAABmzDNZt9VtAAAAAXRSTlMAQObYZgAAAF5JREFUeNrtkTESABAQxPD/R6tsE2dUGYUtFJvLDKf93KevHJAjpBorAQWSBIKqFASC4G0pCAkm4GfaEvgYXl0T6HBaE97f0vmnfYHbZOMLZCx9ISdKWwjOWZSC8GYm4SUGwfYgqI4AAAAASUVORK5CYII=
|
|
||||||
// ==/UserScript==
|
|
||||||
@ -13,7 +13,6 @@
|
|||||||
// @match *://i.4cdn.org/*
|
// @match *://i.4cdn.org/*
|
||||||
// @exclude *://blog.4chan.org/*
|
// @exclude *://blog.4chan.org/*
|
||||||
// @exclude *://dis.4chan.org/*
|
// @exclude *://dis.4chan.org/*
|
||||||
// @exclude *://a.4cdn.org/*
|
|
||||||
// @grant GM_getValue
|
// @grant GM_getValue
|
||||||
// @grant GM_setValue
|
// @grant GM_setValue
|
||||||
// @grant GM_deleteValue
|
// @grant GM_deleteValue
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
BIN
builds/crx.crx
BIN
builds/crx.crx
Binary file not shown.
@ -15,7 +15,7 @@
|
|||||||
"run_at": "document_start"
|
"run_at": "document_start"
|
||||||
}],
|
}],
|
||||||
"homepage_url": "http://zixaphir.github.com/appchan-x/",
|
"homepage_url": "http://zixaphir.github.com/appchan-x/",
|
||||||
"minimum_chrome_version": "33",
|
"minimum_chrome_version": "32",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"storage",
|
"storage",
|
||||||
"http://*/",
|
"http://*/",
|
||||||
|
|||||||
4580
builds/crx/script.js
4580
builds/crx/script.js
File diff suppressed because one or more lines are too long
@ -1,7 +0,0 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
|
||||||
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
|
|
||||||
<app appid='lacclbnghgdicfifcamcmcnilckjamag'>
|
|
||||||
<updatecheck codebase='https://ccd0.github.io/4chan-x/builds/crx.crx' version='1.7.33' />
|
|
||||||
</app>
|
|
||||||
</gupdate>
|
|
||||||
|
|
||||||
@ -19,15 +19,14 @@
|
|||||||
],
|
],
|
||||||
"excludes": [
|
"excludes": [
|
||||||
"*://blog.4chan.org/*",
|
"*://blog.4chan.org/*",
|
||||||
"*://dis.4chan.org/*",
|
"*://dis.4chan.org/*"
|
||||||
"*://a.4cdn.org/*"
|
|
||||||
],
|
],
|
||||||
"files": {
|
"files": {
|
||||||
"metajs": "appchan-x.meta.js",
|
"metajs": "appchan-x.meta.js",
|
||||||
"userjs": "appchan-x.user.js"
|
"userjs": "appchan-x.user.js"
|
||||||
},
|
},
|
||||||
"min": {
|
"min": {
|
||||||
"chrome": "33",
|
"chrome": "32",
|
||||||
"firefox": "26",
|
"firefox": "26",
|
||||||
"greasemonkey": "1.14"
|
"greasemonkey": "1.14"
|
||||||
}
|
}
|
||||||
@ -53,7 +52,9 @@
|
|||||||
"author": "Zixaphir <zixaphirmoxphar@gmail.com>",
|
"author": "Zixaphir <zixaphirmoxphar@gmail.com>",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Nicolas Stepien <stepien.nicolas@gmail.com>",
|
"Nicolas Stepien <stepien.nicolas@gmail.com>",
|
||||||
"James Campos <james.r.campos@gmail.com>"
|
"James Campos <james.r.campos@gmail.com>",
|
||||||
|
"seaweedchan <jtbates@asu.edu>",
|
||||||
|
"ccd0"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"readmeFilename": "README.md",
|
"readmeFilename": "README.md",
|
||||||
|
|||||||
@ -53,7 +53,10 @@ Redirect =
|
|||||||
post: (archive, {boardID, postID}) ->
|
post: (archive, {boardID, postID}) ->
|
||||||
# For fuuka-based archives:
|
# For fuuka-based archives:
|
||||||
# https://github.com/eksopl/fuuka/issues/27
|
# https://github.com/eksopl/fuuka/issues/27
|
||||||
URL = new String "#{Redirect.protocol archive}#{archive.domain}/_/api/chan/post/?board=#{boardID}&num=#{postID}"
|
protocol = Redirect.protocol archive
|
||||||
|
URL = new String "#{protocol}#{archive.domain}/_/api/chan/post/?board=#{boardID}&num=#{postID}"
|
||||||
|
return '' unless Redirect.securityCheck URL
|
||||||
|
|
||||||
URL.archive = archive
|
URL.archive = archive
|
||||||
URL
|
URL
|
||||||
|
|
||||||
@ -76,3 +79,17 @@ Redirect =
|
|||||||
else
|
else
|
||||||
"#{boardID}/?task=search2&search_#{if type is 'image' then 'media_hash' else type}=#{value}"
|
"#{boardID}/?task=search2&search_#{if type is 'image' then 'media_hash' else type}=#{value}"
|
||||||
"#{Redirect.protocol archive}#{archive.domain}/#{path}"
|
"#{Redirect.protocol archive}#{archive.domain}/#{path}"
|
||||||
|
|
||||||
|
securityCheck: (URL) ->
|
||||||
|
/^https:\/\//.test(URL) or
|
||||||
|
location.protocol is 'http:' or
|
||||||
|
Conf['Except Archives from Encryption']
|
||||||
|
|
||||||
|
navigate: (URL, alternative) ->
|
||||||
|
if URL and (
|
||||||
|
Redirect.securityCheck(URL) or
|
||||||
|
confirm "Redirect to #{URL}?\n\nYour connection will not be encrypted."
|
||||||
|
)
|
||||||
|
location.replace URL
|
||||||
|
else if alternative
|
||||||
|
location.replace alternative
|
||||||
@ -5,7 +5,7 @@
|
|||||||
"http": false,
|
"http": false,
|
||||||
"https": true,
|
"https": true,
|
||||||
"software": "foolfuuka",
|
"software": "foolfuuka",
|
||||||
"boards": ["a", "biz", "c", "co", "diy", "gd", "h", "i", "int", "jp", "k", "m", "mlp", "out", "po", "r9k", "s4s", "sci", "sp", "tg", "tv", "u", "v", "vg", "vp", "vr", "wsg"],
|
"boards": ["a", "biz", "c", "co", "diy", "gd", "h", "i", "int", "jp", "k", "m", "mlp", "out", "po", "r9k", "s4s", "sci", "tg", "tv", "u", "v", "vg", "vp", "vr", "wsg"],
|
||||||
"files": ["a", "biz", "c", "co", "diy", "gd", "h", "i", "jp", "k", "m", "mlp", "po", "s4s", "sci", "tg", "u", "v", "vg", "vp", "vr", "wsg"]
|
"files": ["a", "biz", "c", "co", "diy", "gd", "h", "i", "jp", "k", "m", "mlp", "po", "s4s", "sci", "tg", "u", "v", "vg", "vp", "vr", "wsg"]
|
||||||
}, {
|
}, {
|
||||||
"uid": 3,
|
"uid": 3,
|
||||||
@ -53,12 +53,13 @@
|
|||||||
"boards": ["asp", "cm", "h", "hc", "hm", "n", "p", "r", "s", "soc", "y"],
|
"boards": ["asp", "cm", "h", "hc", "hm", "n", "p", "r", "s", "soc", "y"],
|
||||||
"files": ["asp", "cm", "h", "hc", "hm", "n", "p", "r", "s", "soc", "y"]
|
"files": ["asp", "cm", "h", "hc", "hm", "n", "p", "r", "s", "soc", "y"]
|
||||||
}, {
|
}, {
|
||||||
"uid": 17,
|
"uid": 21,
|
||||||
"name": "imcute",
|
"name": "imcute",
|
||||||
"domain": "imcute.yt",
|
"domain": "imcute.yt",
|
||||||
"http": true,
|
"http": true,
|
||||||
"https": false,
|
"https": false,
|
||||||
"software": "foolfuuka",
|
"software": "foolfuuka",
|
||||||
"boards": ["an", "fit", "gif", "int", "mlp", "out", "r9k", "toy"],
|
"boards": ["an", "fit", "gif", "int", "mlp", "out", "r9k", "toy"],
|
||||||
"files": ["an", "fit", "gif", "int", "mlp", "out", "r9k", "toy"]
|
"files": ["an", "fit", "gif", "int", "mlp", "out", "r9k", "toy"],
|
||||||
|
"imagehosts": ["http://imcute.yt/"]
|
||||||
}]
|
}]
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
Anonymize =
|
Anonymize =
|
||||||
init: ->
|
init: ->
|
||||||
return if !Conf['Anonymize']
|
return unless g.VIEW in ['index', 'thread', 'archive'] and Conf['Anonymize']
|
||||||
|
return @archive() if g.VIEW is 'archive'
|
||||||
|
|
||||||
Post.callbacks.push
|
Post.callbacks.push
|
||||||
name: 'Anonymize'
|
name: 'Anonymize'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
|
||||||
node: ->
|
node: ->
|
||||||
return if @info.capcode or @isClone
|
return if @info.capcode or @isClone
|
||||||
{name, tripcode, email} = @nodes
|
{name, tripcode, email} = @nodes
|
||||||
@ -16,3 +18,8 @@ Anonymize =
|
|||||||
if @info.email
|
if @info.email
|
||||||
$.replace email, name
|
$.replace email, name
|
||||||
delete @nodes.email
|
delete @nodes.email
|
||||||
|
|
||||||
|
archive: ->
|
||||||
|
$.ready ->
|
||||||
|
name.textContent = 'Anonymous' for name in $$ '.name'
|
||||||
|
$.rm trip for trip in $$ '.postertrip'
|
||||||
@ -1,21 +1,21 @@
|
|||||||
Filter =
|
Filter =
|
||||||
filters: {}
|
filters: {}
|
||||||
init: ->
|
init: ->
|
||||||
return if !Conf['Filter']
|
return unless g.VIEW in ['index', 'thread'] and Conf['Filter']
|
||||||
|
|
||||||
unless Conf['Filtered Backlinks']
|
unless Conf['Filtered Backlinks']
|
||||||
$.addClass doc, 'hide-backlinks'
|
$.addClass doc, 'hide-backlinks'
|
||||||
|
|
||||||
for key of Config.filter
|
for key of Config.filter
|
||||||
@filters[key] = []
|
@filters[key] = []
|
||||||
for filter in Conf[key].split '\n'
|
for line in Conf[key].split '\n'
|
||||||
continue if filter[0] is '#'
|
continue if line[0] is '#'
|
||||||
|
|
||||||
unless regexp = filter.match /\/(.+)\/(\w*)/
|
unless regexp = line.match /\/(.+)\/(\w*)/
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Don't mix up filter flags with the regular expression.
|
# Don't mix up filter flags with the regular expression.
|
||||||
filter = filter.replace regexp[0], ''
|
filter = line.replace regexp[0], ''
|
||||||
|
|
||||||
# Do not add this filter to the list if it's not a global one
|
# Do not add this filter to the list if it's not a global one
|
||||||
# and it's not specifically applicable to the current board.
|
# and it's not specifically applicable to the current board.
|
||||||
@ -33,7 +33,11 @@ Filter =
|
|||||||
regexp = RegExp regexp[1], regexp[2]
|
regexp = RegExp regexp[1], regexp[2]
|
||||||
catch err
|
catch err
|
||||||
# I warned you, bro.
|
# I warned you, bro.
|
||||||
new Notice 'warning', err.message, 60
|
new Notice 'warning', [
|
||||||
|
$.tn "Invalid #{key} filter: " + line,
|
||||||
|
$.el 'br'
|
||||||
|
$.tn err.message
|
||||||
|
], 60
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Filter OPs along with their threads, replies only, or both.
|
# Filter OPs along with their threads, replies only, or both.
|
||||||
@ -60,18 +64,7 @@ Filter =
|
|||||||
top = filter.match(/top:(yes|no)/)?[1] or 'yes'
|
top = filter.match(/top:(yes|no)/)?[1] or 'yes'
|
||||||
top = top is 'yes' # Turn it into a boolean
|
top = top is 'yes' # Turn it into a boolean
|
||||||
|
|
||||||
@filters[key].push {
|
@filters[key].push @createFilter regexp, op, stub, hl, top
|
||||||
hide: !hl
|
|
||||||
op: op
|
|
||||||
stub: stub
|
|
||||||
class: hl
|
|
||||||
top: top
|
|
||||||
match: regexp
|
|
||||||
test: if typeof regexp is 'string'
|
|
||||||
Filter.stringTest # MD5 checking
|
|
||||||
else
|
|
||||||
Filter.regexpTest
|
|
||||||
}
|
|
||||||
|
|
||||||
# Only execute filter types that contain valid filters.
|
# Only execute filter types that contain valid filters.
|
||||||
unless @filters[key].length
|
unless @filters[key].length
|
||||||
@ -82,25 +75,41 @@ Filter =
|
|||||||
name: 'Filter'
|
name: 'Filter'
|
||||||
cb: @node
|
cb: @node
|
||||||
|
|
||||||
|
createFilter: (regexp, op, stub, hl, top) ->
|
||||||
|
test =
|
||||||
|
if typeof regexp is 'string'
|
||||||
|
# MD5 checking
|
||||||
|
Filter.stringTest
|
||||||
|
else
|
||||||
|
Filter.regexpTest
|
||||||
|
|
||||||
|
settings =
|
||||||
|
hide: !hl
|
||||||
|
stub: stub
|
||||||
|
class: hl
|
||||||
|
top: top
|
||||||
|
|
||||||
|
(value, isReply) -> return settings if Filter.test(test, value, isReply)
|
||||||
|
|
||||||
node: ->
|
node: ->
|
||||||
return if @isClone
|
return if @isClone or @isFetchedQuote
|
||||||
for key of Filter.filters
|
for key of Filter.filters
|
||||||
value = Filter[key] @
|
value = Filter[key] @
|
||||||
# Continue if there's nothing to filter (no tripcode for example).
|
# Continue if there's nothing to filter (no tripcode for example).
|
||||||
continue if value is false
|
continue if value is false
|
||||||
|
|
||||||
for obj in Filter.filters[key]
|
for filter in Filter.filters[key]
|
||||||
unless Filter.test obj, value, @isReply
|
unless result = filter value, @isReply
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Hide
|
# Hide
|
||||||
if obj.hide
|
if result.hide
|
||||||
continue unless @isReply or g.VIEW is 'index'
|
continue unless @isReply or g.VIEW is 'index'
|
||||||
@hide "Hidden by filtering the #{key}: #{obj.match}", obj.stub
|
@hide "Hidden by filtering the #{key}: #{result.match}", result.stub
|
||||||
return
|
return
|
||||||
|
|
||||||
# Highlight
|
# Highlight
|
||||||
@highlight "Highlighted by filtering the #{key}: #{obj.match}", obj.class, obj.top
|
@highlight "Highlighted by filtering the #{key}: #{result.match}", result.class, result.top
|
||||||
|
|
||||||
stringTest: (string, value) ->
|
stringTest: (string, value) ->
|
||||||
string is value
|
string is value
|
||||||
@ -112,6 +121,7 @@ Filter =
|
|||||||
unless test match, value
|
unless test match, value
|
||||||
return false
|
return false
|
||||||
true
|
true
|
||||||
|
|
||||||
name: (post) ->
|
name: (post) ->
|
||||||
if 'name' of post.info
|
if 'name' of post.info
|
||||||
return post.info.name
|
return post.info.name
|
||||||
@ -128,10 +138,6 @@ Filter =
|
|||||||
if 'capcode' of post.info
|
if 'capcode' of post.info
|
||||||
return post.info.capcode
|
return post.info.capcode
|
||||||
false
|
false
|
||||||
email: (post) ->
|
|
||||||
if 'email' of post.info
|
|
||||||
return post.info.email
|
|
||||||
false
|
|
||||||
subject: (post) ->
|
subject: (post) ->
|
||||||
if 'subject' of post.info
|
if 'subject' of post.info
|
||||||
return post.info.subject or false
|
return post.info.subject or false
|
||||||
@ -151,7 +157,7 @@ Filter =
|
|||||||
dimensions: (post) ->
|
dimensions: (post) ->
|
||||||
{file} = post
|
{file} = post
|
||||||
if file and (file.isImage or file.isVideo)
|
if file and (file.isImage or file.isVideo)
|
||||||
return post.file.dimensions
|
return file.dimensions
|
||||||
false
|
false
|
||||||
filesize: (post) ->
|
filesize: (post) ->
|
||||||
if post.file
|
if post.file
|
||||||
@ -164,7 +170,7 @@ Filter =
|
|||||||
|
|
||||||
menu:
|
menu:
|
||||||
init: ->
|
init: ->
|
||||||
return if !Conf['Menu'] or !Conf['Filter']
|
return unless g.VIEW in ['index', 'thread'] and Conf['Menu'] and Conf['Filter']
|
||||||
|
|
||||||
div = $.el 'div',
|
div = $.el 'div',
|
||||||
textContent: 'Filter'
|
textContent: 'Filter'
|
||||||
@ -182,7 +188,6 @@ Filter =
|
|||||||
['Unique ID', 'uniqueID']
|
['Unique ID', 'uniqueID']
|
||||||
['Tripcode', 'tripcode']
|
['Tripcode', 'tripcode']
|
||||||
['Capcode', 'capcode']
|
['Capcode', 'capcode']
|
||||||
['E-mail', 'email']
|
|
||||||
['Subject', 'subject']
|
['Subject', 'subject']
|
||||||
['Comment', 'comment']
|
['Comment', 'comment']
|
||||||
['Flag', 'flag']
|
['Flag', 'flag']
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user