Start merging ccd0's 4chan X stuff

This commit is contained in:
Zixaphir 2015-01-08 13:53:38 -07:00
parent 5449031e60
commit 6f84ae9abe
13 changed files with 4739 additions and 4571 deletions

View File

@ -1,7 +1,8 @@
module.exports = (grunt) ->
grunt.util.linefeed = '\n'
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) ->
parts = template.split /([\$&@]){([^}`]*)}/
@ -38,6 +39,8 @@ module.exports = (grunt) ->
pkg = grunt.config 'pkg'
pkg.importHTML = importHTML
pkg.html = html
pkg.assert = assert
pkg.tests_enabled or= false
pkg
enumerable: true
)
@ -52,17 +55,18 @@ module.exports = (grunt) ->
'src/General/Build.coffee'
'src/General/Get.coffee'
'src/General/UI.coffee'
'src/Filtering/*'
'src/Quotelinks/*'
'src/Linkification/*'
'src/Posting/QR.coffee'
'src/Posting/*'
'src/Images/*'
'src/Menu/*'
'src/Monitoring/*'
'src/Archive/*'
'src/Theming/*'
'src/Miscellaneous/*'
'src/General/CrossOrigin.coffee'
'src/Filtering/**/*.coffee'
'src/Quotelinks/**/*.coffee'
'src/Posting/Captcha.coffee'
'src/Posting/**/*.coffee'
'src/Images/**/*.coffee'
'src/Linkification/**/*.coffee'
'src/Menu/**/*.coffee'
'src/Monitoring/**/*.coffee'
'src/Archive/**/*.coffee'
'src/Miscellaneous/**/*.coffee'
'src/Theming/**/*.coffee'
'src/General/Navigate.coffee'
'src/General/Settings.coffee'
'src/General/Main.coffee'

View File

@ -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==

View File

@ -13,7 +13,6 @@
// @match *://i.4cdn.org/*
// @exclude *://blog.4chan.org/*
// @exclude *://dis.4chan.org/*
// @exclude *://a.4cdn.org/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -15,7 +15,7 @@
"run_at": "document_start"
}],
"homepage_url": "http://zixaphir.github.com/appchan-x/",
"minimum_chrome_version": "33",
"minimum_chrome_version": "32",
"permissions": [
"storage",
"http://*/",

File diff suppressed because one or more lines are too long

View File

@ -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>

View File

@ -19,15 +19,14 @@
],
"excludes": [
"*://blog.4chan.org/*",
"*://dis.4chan.org/*",
"*://a.4cdn.org/*"
"*://dis.4chan.org/*"
],
"files": {
"metajs": "appchan-x.meta.js",
"userjs": "appchan-x.user.js"
},
"min": {
"chrome": "33",
"chrome": "32",
"firefox": "26",
"greasemonkey": "1.14"
}
@ -53,7 +52,9 @@
"author": "Zixaphir <zixaphirmoxphar@gmail.com>",
"contributors": [
"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",
"readmeFilename": "README.md",

View File

@ -53,7 +53,10 @@ Redirect =
post: (archive, {boardID, postID}) ->
# For fuuka-based archives:
# 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
@ -76,3 +79,17 @@ Redirect =
else
"#{boardID}/?task=search2&search_#{if type is 'image' then 'media_hash' else type}=#{value}"
"#{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

View File

@ -5,7 +5,7 @@
"http": false,
"https": true,
"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"]
}, {
"uid": 3,
@ -53,12 +53,13 @@
"boards": ["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",
"domain": "imcute.yt",
"http": true,
"https": false,
"software": "foolfuuka",
"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/"]
}]

View File

@ -1,10 +1,12 @@
Anonymize =
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
name: 'Anonymize'
cb: @node
node: ->
return if @info.capcode or @isClone
{name, tripcode, email} = @nodes
@ -16,3 +18,8 @@ Anonymize =
if @info.email
$.replace email, name
delete @nodes.email
archive: ->
$.ready ->
name.textContent = 'Anonymous' for name in $$ '.name'
$.rm trip for trip in $$ '.postertrip'

View File

@ -1,21 +1,21 @@
Filter =
filters: {}
init: ->
return if !Conf['Filter']
return unless g.VIEW in ['index', 'thread'] and Conf['Filter']
unless Conf['Filtered Backlinks']
$.addClass doc, 'hide-backlinks'
for key of Config.filter
@filters[key] = []
for filter in Conf[key].split '\n'
continue if filter[0] is '#'
for line in Conf[key].split '\n'
continue if line[0] is '#'
unless regexp = filter.match /\/(.+)\/(\w*)/
unless regexp = line.match /\/(.+)\/(\w*)/
continue
# 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
# and it's not specifically applicable to the current board.
@ -33,7 +33,11 @@ Filter =
regexp = RegExp regexp[1], regexp[2]
catch err
# 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
# 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 = top is 'yes' # Turn it into a boolean
@filters[key].push {
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
}
@filters[key].push @createFilter regexp, op, stub, hl, top
# Only execute filter types that contain valid filters.
unless @filters[key].length
@ -82,25 +75,41 @@ Filter =
name: 'Filter'
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: ->
return if @isClone
return if @isClone or @isFetchedQuote
for key of Filter.filters
value = Filter[key] @
# Continue if there's nothing to filter (no tripcode for example).
continue if value is false
for obj in Filter.filters[key]
unless Filter.test obj, value, @isReply
for filter in Filter.filters[key]
unless result = filter value, @isReply
continue
# Hide
if obj.hide
if result.hide
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
# 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) ->
string is value
@ -112,6 +121,7 @@ Filter =
unless test match, value
return false
true
name: (post) ->
if 'name' of post.info
return post.info.name
@ -128,10 +138,6 @@ Filter =
if 'capcode' of post.info
return post.info.capcode
false
email: (post) ->
if 'email' of post.info
return post.info.email
false
subject: (post) ->
if 'subject' of post.info
return post.info.subject or false
@ -151,7 +157,7 @@ Filter =
dimensions: (post) ->
{file} = post
if file and (file.isImage or file.isVideo)
return post.file.dimensions
return file.dimensions
false
filesize: (post) ->
if post.file
@ -164,7 +170,7 @@ Filter =
menu:
init: ->
return if !Conf['Menu'] or !Conf['Filter']
return unless g.VIEW in ['index', 'thread'] and Conf['Menu'] and Conf['Filter']
div = $.el 'div',
textContent: 'Filter'
@ -182,7 +188,6 @@ Filter =
['Unique ID', 'uniqueID']
['Tripcode', 'tripcode']
['Capcode', 'capcode']
['E-mail', 'email']
['Subject', 'subject']
['Comment', 'comment']
['Flag', 'flag']