4chan-x/src/Archive/Redirect.coffee

182 lines
5.8 KiB
CoffeeScript

Redirect =
archives:
`<%=
JSON.stringify(readJSON('archives.json'), null, 2)
.replace(/\n {2,}(?!{)/g, ' ')
.replace(/\n/g, '\n ')
.replace(/`/g, '\\`')
%>`
init: ->
@selectArchives()
if Conf['archiveAutoUpdate']
now = Date.now()
@update() unless now - 2 * $.DAY < Conf['lastarchivecheck'] <= now
selectArchives: ->
o =
thread: {}
post: {}
file: {}
archives = {}
for data in Conf['archives']
for key in ['boards', 'files']
data[key] = [] unless data[key] instanceof Array
{uid, name, boards, files, software} = data
continue unless software in ['fuuka', 'foolfuuka']
archives[JSON.stringify(uid ? name)] = data
for boardID in boards
o.thread[boardID] = data unless boardID of o.thread
o.post[boardID] = data unless boardID of o.post or software isnt 'foolfuuka'
o.file[boardID] = data unless boardID of o.file or boardID not in files
for boardID, record of Conf['selectedArchives']
for type, id of record when (archive = archives[JSON.stringify id])
boards = if type is 'file' then archive.files else archive.boards
o[type][boardID] = archive if boardID in boards
Redirect.data = o
update: (cb) ->
urls = []
responses = []
nloaded = 0
for url in Conf['archiveLists'].split('\n') when url[0] isnt '#'
url = url.trim()
urls.push url if url
load = (i) -> ->
fail = (action, msg) -> new Notice 'warning', "Error #{action} archive data from\n#{urls[i]}\n#{msg}", 20
return fail 'fetching', (if @status then "Error #{@statusText} (#{@status})" else 'Connection Error') unless @status is 200
try
response = JSON.parse @response
catch err
return fail 'parsing', err.message
response = [response] unless response instanceof Array
responses[i] = response
nloaded++
if nloaded is urls.length
Redirect.parse responses, cb
if urls.length
for url, i in urls
if url[0] in ['[', '{']
load(i).call
status: 200
response: url
else
$.ajax url,
responseType: 'text'
onloadend: load(i)
else
Redirect.parse [], cb
return
parse: (responses, cb) ->
archives = []
archiveUIDs = {}
for response in responses
for data in response
uid = JSON.stringify(data.uid ? data.name)
if uid of archiveUIDs
$.extend archiveUIDs[uid], data
else
archiveUIDs[uid] = data
archives.push data
items = {archives, lastarchivecheck: Date.now()}
$.set items
$.extend Conf, items
Redirect.selectArchives()
cb?()
to: (dest, data) ->
archive = (if dest in ['search', 'board'] then Redirect.data.thread else Redirect.data[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 archive.software is 'foolfuuka'
path += '/'
if threadID and postID
path += if archive.software is 'foolfuuka'
"##{postID}"
else
"#p#{postID}"
"#{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
url = "#{protocol}#{archive.domain}/_/api/chan/post/?board=#{boardID}&num=#{postID}"
return '' unless Redirect.securityCheck url
url
file: (archive, {boardID, filename}) ->
filename = encodeURIComponent Build.unescape decodeURIComponent filename if boardID is 'f'
"#{Redirect.protocol archive}#{archive.domain}/#{boardID}/full_image/#{filename}"
board: (archive, {boardID}) ->
"#{Redirect.protocol archive}#{archive.domain}/#{boardID}/"
search: (archive, {boardID, type, value}) ->
type = if type is 'name'
'username'
else if type is 'MD5'
'image'
else
type
if type is 'capcode'
# https://github.com/pleebe/FoolFuuka/blob/bf4224eed04637a4d0bd4411c2bf5f9945dfec0b/src/Model/Search.php#L363
value = {
'Developer': 'dev'
'Verified': 'ver'
}[value] or value.toLowerCase()
else if type is 'image'
value = value.replace /[+/=]/g, (c) -> ({'+': '-', '/': '_', '=': ''})[c]
value = encodeURIComponent value
path = if archive.software is 'foolfuuka'
"#{boardID}/search/#{type}/#{value}/"
else if type is 'image'
"#{boardID}/image/#{value}"
else
"#{boardID}/?task=search2&search_#{type}=#{value}"
"#{Redirect.protocol archive}#{archive.domain}/#{path}"
report: (boardID) ->
urls = []
for archive in Conf['archives']
{software, https, reports, boards, name, domain} = archive
if software is 'foolfuuka' and https and reports and boards instanceof Array and boardID in boards
urls.push [name, "https://#{domain}/_/api/chan/offsite_report/"]
urls
securityCheck: (url) ->
/^https:\/\//.test(url) or
location.protocol is 'http:' or
Conf['Exempt Archives from Encryption']
navigate: (dest, data, alternative) ->
Redirect.init() unless Redirect.data
url = Redirect.to dest, data
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