Add archive selection.

This commit is contained in:
Mayhem 2013-05-06 06:57:29 +02:00
parent f1b6647475
commit 538e117746
14 changed files with 384 additions and 106 deletions

View File

@ -1,3 +1,6 @@
- **New feature**: `Archive selection`
- Select which archive you want for specific boards and redirection type.
- Access it in the `Archives` tab of the Settings window.
- Fix quote previews getting 'stuck' in Opera.
### 3.3.1 - *2013-05-04*

View File

@ -122,6 +122,7 @@ module.exports = function(grunt) {
'src/**/*',
'html/**/*',
'css/**/*',
'json/**/*',
'img/**/*'
],
tasks: 'build'

View File

@ -358,6 +358,18 @@ a[href="javascript:;"] {
.section-rice textarea {
height: 150px;
}
.section-archives table {
width: 100%;
}
.section-archives th:not(:first-child) {
width: 30%;
}
.section-archives td {
text-align: center;
}
.section-archives select {
width: 90%;
}
#fourchanx-settings fieldset {
border: 1px solid;
border-radius: 3px;

View File

@ -0,0 +1,12 @@
<div class="warning" #{if Conf['404 Redirect'] then 'hidden' else ''}><code>404 Redirect</code> is disabled.</div>
<p>Disabled selections indicate that only one archive is available for that board and redirection type.</p>
<table>
<caption>Archived boards</caption>
<thead>
<th>Board</th>
<th>Thread redirection</th>
<th>Post fetching</th>
<th>File redirection</th>
</thead>
<tbody></tbody>
</table>

100
json/archives.json Normal file
View File

@ -0,0 +1,100 @@
[{
"uid": 0,
"name": "Foolz",
"domain": "archive.foolz.us",
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["a", "co", "gd", "jp", "m", "q", "sp", "tg", "tv", "vp", "vr", "wsg"],
"files": ["a", "gd", "jp", "m", "q", "tg", "vp", "vr", "wsg"]
}, {
"uid": 1,
"name": "NSFW Foolz",
"domain": "nsfw.foolz.us",
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["u"],
"files": ["u"]
}, {
"uid": 2,
"name": "The Dark Cave",
"domain": "archive.thedarkcave.org",
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["c", "int", "out", "po"],
"files": ["c", "po"]
}, {
"uid": 3,
"name": "4plebs",
"domain": "archive.4plebs.org",
"http": true,
"https": false,
"software": "foolfuuka",
"boards": ["hr", "tg", "tv", "x"],
"files": ["hr", "tg", "tv", "x"]
}, {
"uid": 4,
"name": "Nyafuu",
"domain": "archive.nyafuu.org",
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["c", "w", "wg"],
"files": ["c", "w", "wg"]
}, {
"uid": 5,
"name": "Love is Over",
"domain": "loveisover.me",
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["d", "h", "v"],
"files": ["d", "h", "v"]
}, {
"uid": 6,
"name": "nth-chan",
"domain": "nth.pensivenonsen.se",
"http": true,
"https": false,
"software": "foolfuuka",
"boards": [],
"files": []
}, {
"uid": 7,
"name": "Install Gentoo",
"domain": "archive.installgentoo.net",
"http": true,
"https": true,
"software": "fuuka",
"boards": ["diy", "g", "sci"],
"files": []
}, {
"uid": 8,
"name": "Rebecca Black Tech",
"domain": "rbt.asia",
"http": true,
"https": true,
"software": "fuuka",
"boards": ["cgl", "g", "mu", "w"],
"files": ["cgl", "g", "mu", "w"]
}, {
"uid": 9,
"name": "Heinessen",
"domain": "archive.heinessen.com",
"http": true,
"https": false,
"software": "fuuka",
"boards": ["an", "fit", "k", "mlp", "r9k", "toy", "x"],
"files": ["an", "k", "toy", "x"]
}, {
"uid": 10,
"name": "warosu",
"domain": "fuuka.warosu.org",
"http": true,
"https": true,
"software": "fuuka",
"boards": ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "q", "s4s", "tg", "vr"],
"files": ["3", "cgl", "ck", "fa", "ic", "jp", "lit", "q", "s4s", "vr"]
}]

101
json/archives1.json Normal file
View File

@ -0,0 +1,101 @@
{
"Foolz": {
"uid": 0,
"domain": "archive.foolz.us",
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["a", "co", "gd", "jp", "m", "q", "sp", "tg", "tv", "vp", "vr", "wsg"],
"files": ["a", "gd", "jp", "m", "q", "tg", "vp", "vr", "wsg"]
},
"NSFW Foolz": {
"uid": 1,
"domain": "nsfw.foolz.us",
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["u"],
"files": ["u"]
},
"The Dark Cave": {
"uid": 2,
"domain": "archive.thedarkcave.org",
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["c", "int", "out", "po"],
"files": ["c", "po"]
},
"4plebs": {
"uid": 3,
"domain": "archive.4plebs.org",
"http": true,
"https": false,
"software": "foolfuuka",
"boards": ["hr", "tg", "tv", "x"],
"files": ["hr", "tg", "tv", "x"]
},
"Nyafuu": {
"uid": 4,
"domain": "archive.nyafuu.org",
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["c", "w", "wg"],
"files": ["c", "w", "wg"]
},
"Love is Over": {
"uid": 5,
"domain": "loveisover.me",
"http": true,
"https": true,
"software": "foolfuuka",
"boards": ["d", "h", "v"],
"files": ["d", "h", "v"]
},
"nth-chan": {
"uid": 6,
"domain": "nth.pensivenonsen.se",
"http": true,
"https": false,
"software": "foolfuuka",
"boards": ["vg"],
"files": ["vg"]
},
"Install Gentoo": {
"uid": 7,
"domain": "archive.installgentoo.net",
"http": true,
"https": true,
"software": "fuuka",
"boards": ["diy", "g", "sci"],
"files": []
},
"Rebecca Black Tech": {
"uid": 8,
"domain": "rbt.asia",
"http": true,
"https": true,
"software": "fuuka",
"boards": ["cgl", "g", "mu", "w"],
"files": ["cgl", "g", "mu", "w"]
},
"Heinessen": {
"uid": 9,
"domain": "archive.heinessen.com",
"http": true,
"https": false,
"software": "fuuka",
"boards": ["an", "fit", "k", "mlp", "r9k", "toy", "x"],
"files": ["an", "k", "toy", "x"]
},
"warosu": {
"uid": 10,
"domain": "fuuka.warosu.org",
"http": true,
"https": true,
"software": "fuuka",
"boards": ["cgl", "ck", "fa", "jp", "lit", "q", "s4s", "tg", "vr"],
"files": ["cgl", "ck", "fa", "jp", "lit", "q", "s4s", "tg", "vr"]
}
}

View File

@ -1,102 +1,78 @@
Redirect =
image: (boardID, filename) ->
# Do not use g.BOARD, the image url can originate from a cross-quote.
switch boardID
when 'a', 'gd', 'jp', 'm', 'q', 'tg', 'vp', 'vr', 'wsg'
"//archive.foolz.us/#{boardID}/full_image/#{filename}"
when 'u'
"//nsfw.foolz.us/#{boardID}/full_image/#{filename}"
when 'po'
"//archive.thedarkcave.org/#{boardID}/full_image/#{filename}"
when 'hr', 'tv'
"http://archive.4plebs.org/#{boardID}/full_image/#{filename}"
when 'c', 'w', 'wg'
"//archive.nyafuu.org/#{boardID}/full_image/#{filename}"
when 'd', 'h', 'v'
"//loveisover.me/#{boardID}/full_image/#{filename}"
when 'vg'
"http://nth.pensivenonsen.se/#{boardID}/full_image/#{filename}"
when 'ck', 'fa', 'lit', 's4s'
"//fuuka.warosu.org/#{boardID}/full_image/#{filename}"
when 'cgl', 'g', 'mu'
"//rbt.asia/#{boardID}/full_image/#{filename}"
when 'an', 'k', 'toy', 'x'
"http://archive.heinessen.com/#{boardID}/full_image/#{filename}"
post: (boardID, postID) ->
# XXX foolz had HSTS set for 120 days, which broke XHR+CORS+Redirection when on HTTP.
# Remove necessary HTTPS procotol in September 2013.
switch boardID
when 'a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'vp', 'vr', 'wsg'
"https://archive.foolz.us/_/api/chan/post/?board=#{boardID}&num=#{postID}"
when 'u'
"https://nsfw.foolz.us/_/api/chan/post/?board=#{boardID}&num=#{postID}"
when 'int', 'out', 'po'
"//archive.thedarkcave.org/_/api/chan/post/?board=#{boardID}&num=#{postID}"
when 'hr', 'x'
"http://archive.4plebs.org/_/api/chan/post/?board=#{boardID}&num=#{postID}"
when 'c', 'w', 'wg'
"//archive.nyafuu.org/_/api/chan/post/?board=#{boardID}&num=#{postID}"
when 'd', 'h', 'v'
"//loveisover.me/_/api/chan/post/?board=#{boardID}&num=#{postID}"
when 'vg'
"http://nth.pensivenonsen.se/_/api/chan/post/?board=#{boardID}&num=#{postID}"
# for fuuka-based archives:
# https://github.com/eksopl/fuuka/issues/27
to: (data) ->
{boardID} = data
switch boardID
when 'a', 'co', 'gd', 'jp', 'm', 'q', 'sp', 'tg', 'tv', 'vp', 'vr', 'wsg'
Redirect.path '//archive.foolz.us', 'foolfuuka', data
when 'u'
Redirect.path '//nsfw.foolz.us', 'foolfuuka', data
when 'int', 'out', 'po'
Redirect.path '//archive.thedarkcave.org', 'foolfuuka', data
when 'hr'
Redirect.path 'http://archive.4plebs.org', 'foolfuuka', data
when 'c', 'w', 'wg'
Redirect.path '//archive.nyafuu.org', 'foolfuuka', data
when 'd', 'h', 'v'
Redirect.path '//loveisover.me', 'foolfuuka', data
when 'vg'
Redirect.path 'http://nth.pensivenonsen.se', 'foolfuuka', data
when 'ck', 'fa', 'lit', 's4s'
Redirect.path '//fuuka.warosu.org', 'fuuka', data
when 'diy', 'g', 'sci'
Redirect.path '//archive.installgentoo.net', 'fuuka', data
when 'cgl', 'mu'
Redirect.path '//rbt.asia', 'fuuka', data
when 'an', 'fit', 'k', 'mlp', 'r9k', 'toy', 'x'
Redirect.path 'http://archive.heinessen.com', 'fuuka', data
else
if data.threadID then "//boards.4chan.org/#{boardID}/" else ''
path: (base, archiver, data) ->
if data.isSearch
{boardID, type, value} = data
type = if type is 'name'
'username'
else if type is 'MD5'
'image'
else
type
value = encodeURIComponent value
return if archiver is 'foolfuuka'
"#{base}/#{boardID}/search/#{type}/#{value}"
else if type is 'image'
"#{base}/#{boardID}/?task=search2&search_media_hash=#{value}"
else
"#{base}/#{boardID}/?task=search2&search_#{type}=#{value}"
archives: `<%= JSON.stringify(grunt.file.readJSON('json/archives.json')) %>`
thread: {}
post: {}
file: {}
{boardID, threadID, postID} = data
# keep the number only if the location.hash was sent f.e.
init: ->
for boardID, data of Conf['selectedArchives']
for type, uid of data
for archive in Redirect.archives
continue if archive.uid isnt uid or type is 'post' and archive.software isnt 'foolfuuka'
arr = if type is 'file'
archive.files
else
archive.boards
Redirect[type][boardID] = archive if boardID in arr
for archive in Redirect.archives
for boardID in archive.boards
unless boardID of Redirect.thread
Redirect.thread[boardID] = archive
unless boardID of Redirect.post or archive.software isnt 'foolfuuka'
Redirect.post[boardID] = archive
unless boardID of Redirect.file or boardID not in archive.files
Redirect.file[boardID] = archive
return
to: (dest, data) ->
archive = (if dest is 'search' then Redirect.thread else Redirect[dest])[data.boardID]
return '' unless archive
Redirect[dest] archive, data
protocol: (archive) ->
protocol = location.protocol
unless archive[protocol[0...-1]]
protocol = if protocol is 'https:' then 'http:' else 'https:'
"#{protocol}//"
thread: (archive, {boardID, threadID, postID}) ->
# Keep the post number only if the location.hash was sent f.e.
path = if threadID
"#{boardID}/thread/#{threadID}"
else
"#{boardID}/post/#{postID}"
if archiver is 'foolfuuka'
if archive.software is 'foolfuuka'
path += '/'
if threadID and postID
path += if archiver is 'foolfuuka'
path += if archive.software is 'foolfuuka'
"##{postID}"
else
"#p#{postID}"
"#{base}/#{path}"
"#{Redirect.protocol archive}#{archive.domain}/#{path}"
post: (archive, {boardID, postID}) ->
# For fuuka-based archives:
# https://github.com/eksopl/fuuka/issues/27
protocol = Redirect.protocol archive
# XXX foolz had HSTS set for 120 days, which broke XHR+CORS+Redirection when on HTTP.
# Remove necessary HTTPS procotol in September 2013.
if archive.name in ['Foolz', 'NSFW Foolz']
protocol = 'https://'
"#{protocol}#{archive.domain}/_/api/chan/post/?board=#{boardID}&num=#{postID}"
file: (archive, {boardID, filename}) ->
"#{Redirect.protocol archive}#{archive.domain}/#{boardID}/full_image/#{filename}"
search: (archive, {boardID, type, value}) ->
type = if type is 'name'
'username'
else if type is 'MD5'
'image'
else
type
value = encodeURIComponent value
path = if archive.software is 'foolfuuka'
"#{boardID}/search/#{type}/#{value}"
else
"#{boardID}/?task=search2&search_#{if type is 'image' then 'media_hash' else type}=#{value}"
"#{Redirect.protocol archive}#{archive.domain}/#{path}"

View File

@ -71,7 +71,7 @@ Get =
if threadID
$.cache "//api.4chan.org/#{boardID}/res/#{threadID}.json", ->
Get.fetchedPost @, boardID, threadID, postID, root, context
else if url = Redirect.post boardID, postID
else if url = Redirect.to 'post', {boardID, postID}
$.cache url, ->
Get.archivedPost @, boardID, postID, root, context
insert: (post, root, context) ->
@ -97,7 +97,7 @@ Get =
{status} = req
if status not in [200, 304]
# The thread can die by the time we check a quote.
if url = Redirect.post boardID, postID
if url = Redirect.to 'post', {boardID, postID}
$.cache url, ->
Get.archivedPost @, boardID, postID, root, context
else
@ -115,7 +115,7 @@ Get =
break if post.no is postID # we found it!
if post.no > postID
# The post can be deleted by the time we check a quote.
if url = Redirect.post boardID, postID
if url = Redirect.to 'post', {boardID, postID}
$.cache url, ->
Get.archivedPost @, boardID, postID, root, context
else

View File

@ -14,6 +14,7 @@ Main =
flatten null, Config
for db in DataBoards
Conf[db] = boards: {}
Conf['selectedArchives'] = {}
$.get Conf, Main.initFeatures
$.on d, '4chanMainInit', Main.initStyle
@ -43,8 +44,11 @@ Main =
when 'images.4chan.org'
$.ready ->
if Conf['404 Redirect'] and d.title is '4chan - 404 Not Found'
url = Redirect.image pathname[1], pathname[3]
location.href = url if url
Redirect.init()
URL = Redirect.to 'file',
boardID: pathname[1]
filename: pathname[3]
location.href = URL if URL
return
initFeature = (name, module) ->
@ -65,6 +69,7 @@ Main =
initFeature 'Announcement Hiding', PSAHiding
initFeature 'Fourchan thingies', Fourchan
initFeature 'Custom CSS', CustomCSS
initFeature 'Redirect', Redirect
initFeature 'Resurrect Quotes', Quotify
initFeature 'Filter', Filter
initFeature 'Thread Hiding', ThreadHiding
@ -148,7 +153,7 @@ Main =
initReady: ->
if d.title is '4chan - 404 Not Found'
if Conf['404 Redirect'] and g.VIEW is 'thread'
href = Redirect.to
href = Redirect.to 'thread',
boardID: g.BOARD.ID
threadID: g.THREADID
postID: +location.hash.match /\d+/ # post number or 0

View File

@ -41,6 +41,7 @@ Settings =
Settings.addSection 'QR', Settings.qr
Settings.addSection 'Sauce', Settings.sauce
Settings.addSection 'Rice', Settings.rice
Settings.addSection 'Archives', Settings.archives
Settings.addSection 'Keybinds', Settings.keybinds
$.on d, 'AddSettingsSection', Settings.addSection
$.on d, 'OpenSettings', (e) -> Settings.open e.detail
@ -386,6 +387,69 @@ Settings =
usercss: ->
CustomCSS.update()
archives: (section) ->
section.innerHTML = """
<%= grunt.file.read('html/General/Settings-section-Archives.html').replace(/>\s+</g, '><').trim() %>
"""
boards = {}
for archive in Redirect.archives
for boardID in archive.boards
data = boards[boardID] or= {
thread: []
post: []
file: []
}
data.thread.push archive
if archive.software is 'foolfuuka'
data.post.push archive
if boardID in archive.files
data.file.push archive
rows = []
for boardID in Object.keys(boards).sort() # Alphabetical order
row = $.el 'tr'
rows.push row
$.add row, $.el 'th',
textContent: "/#{boardID}/"
className: if boardID is g.BOARD.ID then 'warning' else ''
data = boards[boardID]
Settings.addArchiveCell row, boardID, data, 'thread'
Settings.addArchiveCell row, boardID, data, 'post'
Settings.addArchiveCell row, boardID, data, 'file'
$.add $('tbody', section), rows
$.get 'selectedArchives', Conf['selectedArchives'], ({selectedArchives}) ->
for boardID, data of selectedArchives
for type, uid of data
if option = $ "select[data-boardid='#{boardID}'][data-type='#{type}'] > option[value='#{uid}']", section
option.selected = true
return
addArchiveCell: (row, boardID, data, type) ->
options = []
for archive in data[type]
options.push $.el 'option',
textContent: archive.name
value: archive.uid
td = $.el 'td'
{length} = options
if length
td.innerHTML = '<select></select>'
select = td.firstElementChild
unless select.disabled = length is 1
# XXX GM can't into datasets
select.setAttribute 'data-boardid', boardID
select.setAttribute 'data-type', type
$.on select, 'change', Settings.saveSelectedArchive
$.add select, options
else
td.textContent = 'N/A'
$.add row, td
saveSelectedArchive: ->
$.get 'selectedArchives', Conf['selectedArchives'], ({selectedArchives}) =>
(selectedArchives[@dataset.boardid] or= {})[@dataset.type] = +@value
$.set 'selectedArchives', selectedArchives
keybinds: (section) ->
section.innerHTML = """
<%= grunt.file.read('html/General/Settings-section-Keybinds.html').replace(/>\s+</g, '><').trim() %>

View File

@ -136,7 +136,10 @@ ImageExpand =
src = @src.split '/'
if src[2] is 'images.4chan.org'
if URL = Redirect.image src[3], src[5]
URL = Redirect.to 'file',
boardID: src[3]
filename: src[5].replace /\?.+$/, ''
if URL
setTimeout ImageExpand.expand, 10000, post, URL
return
if g.DEAD or post.isDead or post.file.isDead

View File

@ -28,7 +28,10 @@ ImageHover =
src = @src.split '/'
if src[2] is 'images.4chan.org'
if URL = Redirect.image src[3], src[5].replace /\?.+$/, ''
URL = Redirect.to 'file',
boardID: src[3]
filename: src[5].replace /\?.+$/, ''
if URL
@src = URL
return
if g.DEAD or post.isDead or post.file.isDead

View File

@ -10,8 +10,7 @@ ArchiveLink =
el: div
order: 90
open: ({ID, thread, board}) ->
redirect = Redirect.to {postID: ID, threadID: thread.ID, boardID: board.ID}
redirect isnt "//boards.4chan.org/#{board}/"
!!Redirect.to 'thread', {postID: ID, threadID: thread.ID, boardID: board.ID}
subEntries: []
for type in [
@ -35,18 +34,17 @@ ArchiveLink =
open = if type is 'post'
({ID, thread, board}) ->
el.href = Redirect.to {postID: ID, threadID: thread.ID, boardID: board.ID}
el.href = Redirect.to 'thread', {postID: ID, threadID: thread.ID, boardID: board.ID}
true
else
(post) ->
value = Filter[type] post
# We want to parse the exact same stuff as the filter does already.
return false unless value
el.href = Redirect.to
el.href = Redirect.to 'search',
boardID: post.board.ID
type: type
value: value
isSearch: true
true
return {

View File

@ -47,14 +47,14 @@ Quotify =
a.setAttribute 'data-boardid', boardID
a.setAttribute 'data-threadid', post.thread.ID
a.setAttribute 'data-postid', postID
else if redirect = Redirect.to {boardID, threadID: 0, postID}
else if redirect = Redirect.to 'thread', {boardID, threadID: 0, postID}
# Replace the .deadlink span if we can redirect.
a = $.el 'a',
href: redirect
className: 'deadlink'
target: '_blank'
textContent: "#{quote}\u00A0(Dead)"
if Redirect.post boardID, postID
if Redirect.to 'post', {boardID, postID}
# Make it function as a normal quote if we can fetch the post.
$.addClass a, 'quotelink'
a.setAttribute 'data-boardid', boardID