Skip to content

Instantly share code, notes, and snippets.

@jaideejung007
Last active December 16, 2019 01:42
Show Gist options
  • Save jaideejung007/f26fdb2bd72d75539c2a926dc96327f7 to your computer and use it in GitHub Desktop.
Save jaideejung007/f26fdb2bd72d75539c2a926dc96327f7 to your computer and use it in GitHub Desktop.
Source Tampermonkey-SiamBitZoomScreenShot
(function ( $ ) {
/*
* ##REQUIRE##
* jquery
* md5
* fancybox
*
* ##CDN https://raw.githack.com/ ##
* release new version must purge cached
* use source url for purge cached
*/
"use strict"
let SiambitZoomScreenShot = function ( options ) {
let defaults = {
debug : false,
cache : true, //Enable local cache
cacheTimeout : 604800, //Min for local cache timeout
directLink : true, //Enable DirectLink Cache
directLinkApi : 'https://nekotools.info/direct-links',
directLinkTimeout : 2500,
previewColumnMaxHeight : 171, //Set false for use auto detect column height
previewMaxHeight : 80,
previewMaxWidth : 120,
previewFail : 'https://i.imgur.com/jaM7eqT.png?1',
previewExcept : 'https://i.imgur.com/blbuhiy.png?1',
exceptCategories : null,
}
let settings = $.extend({}, defaults, options)
let debug = settings.debug
let cacheKey = 'SIAMBIT_ZOOM_SCREEN_SHOT_CACHE'
let patterns = {
"selector" : [
{
attr : "src",
selector : "div.image_view img",
domains : [
"postto.me",
]
},
{
attr : "src",
selector : "div#image img",
domains : [
"pic.8e88.in.th",
]
},
],
"meta" : [
{
selector : "og:image",
domains : [
"www.imgbb.me",
"imgbb.me",
"www.picz.in.th",
"picz.in.th",
"www.imgtrue.com",
"imgtrue.com",
"imdb.com",
"www.imdb.com",
"ibb.co",
"www.lmgbb.me",
"roop.xyz",
"www.roop.xyz",
"bpicc.com",
"www.bpicc.com",
"lmgbb.me",
"www.img.live",
"img.live",
]
}
],
"replace" : [
{
replace_find : "viewer.php?file=",
replace_new : "files/",
domains : [
"img.best-story.net",
]
},
{
replace_find : ".cc/v",
replace_new : ".cc/d",
domains : [
"uppic.cc",
]
},
],
"direct" : {
excepts : [
'img.best-story.net/viewer',
]
},
"custom" : [
{
domains : [
'imgur.com',
],
synchronous : true,
callback : async function ( url, self ) {
let _url = url.replace("https://", "")
.replace("http://", "")
if (_url.startsWith("imgur.com/a/")) {
url = await this.getDirectSourceSite(url, 'meta', { selector : 'twitter:image' })
} else if (_url.startsWith("imgur.com/")
&& _url.lastIndexOf(".jpg") === -1
&& _url.lastIndexOf(".jpeg") === -1
&& _url.lastIndexOf(".gif") === -1
&& _url.lastIndexOf(".png") === -1
) {
url = "https://i." + _url + ".jpg"
}
return url
}
}
]
}
let locationCurrent = window.location
let locationList = [
'/viewno18.php',
'/viewbr.php',
'/upfinish.php',
]
let downloadListHead = {
element : null,
td : null,
index : {}
}
let downloadList = []
let progressBar = {
all : 0,
run : 0,
template : $("<span>", { title : 'Direct source status.' }),
}
let loading = '<div class="lds-grid"><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div></div>'
let hoverPreview = {
xOffset : 10,
yOffset : 30,
yOffsetFix : 0,
yOffsetPreLoadFix : 0,
previewTop : 0,
previewLeft : 0,
popup : $('<p>', { class : 'hover-popup' }),
img : $('<img>'),
imgHeight : 0,
}
function log( index, message ) {
console.log("#" + index + " " + message)
}
return {
init : function () {
this.css()
this.loadDownloadList()
//Add popup to body
$("body").append(hoverPreview.popup.append(hoverPreview.img))
},
css : function () {
//Loading
GM_addStyle('.lds-grid{display:inline-block;position:relative;width:80px;height:80px}.lds-grid div{position:absolute;width:16px;height:16px;border-radius:50%;background:#7369af;animation:lds-grid 1.2s linear infinite}.lds-grid div:nth-child(1){top:8px;left:8px;animation-delay:0s}.lds-grid div:nth-child(2){top:8px;left:32px;animation-delay:-.4s}.lds-grid div:nth-child(3){top:8px;left:56px;animation-delay:-.8s}.lds-grid div:nth-child(4){top:32px;left:8px;animation-delay:-.4s}.lds-grid div:nth-child(5){top:32px;left:32px;animation-delay:-.8s}.lds-grid div:nth-child(6){top:32px;left:56px;animation-delay:-1.2s}.lds-grid div:nth-child(7){top:56px;left:8px;animation-delay:-.8s}.lds-grid div:nth-child(8){top:56px;left:32px;animation-delay:-1.2s}.lds-grid div:nth-child(9){top:56px;left:56px;animation-delay:-1.6s}@keyframes lds-grid{0%,100%{opacity:1}50%{opacity:.5}}')
//Preview Cover
GM_addStyle('img.preview{max-height:' + settings.previewMaxHeight + 'px;max-width:' + settings.previewMaxWidth + 'px;display:none;}')
//Preview hover
GM_addStyle('.hover-popup { position: absolute; border: 2px solid #fff; background: #fff; padding: 4px 4px 4px 4px; display: none; border-radius:5px; color: #fff ;}')
},
workingSource : async function () {
let self = this
//Get cache direct links
let caches = []
if (settings.directLink) {
if (debug) log('+', 'Use DirectLink')
if (debug) log('+', 'Host is ' + settings.directLinkApi)
let find = downloadList.filter(r => !r.coverSource || !r.coverThumbnail).map(r => r.coverHash).join(',')
if (debug) log('+', 'Find: ' + find)
if (find !== '') {
try {
caches = await this.getDirectLinks(downloadList.map(r => r.coverHash).join(','))
if (!Array.isArray(caches)) throw "response not array"
} catch (err) {
if (debug) log('+', 'Get DirectLink error ' + err)
caches = []
}
}
}
Promise.all(downloadList.map(async function ( item, index ) {
if (debug) log(item.index, 'Working')
if (debug) log(item.index, 'Title: ' + item.title)
let cache = caches.find(r => r.link_hash === item.coverHash)
if (cache) {
if (!item.coverSource) {
item.coverSource = cache.direct
if (debug) log(item.index, 'DirectLink source: ' + cache.direct)
}
if (!item.coverThumbnail && cache.thumbnail) {
item.coverThumbnail = cache.thumbnail.link
if (debug) log(item.index, 'DirectLink thumbnail: ' + cache.thumbnail.link)
}
}
if (!item.coverSource) {
if (debug) log(item.index, 'Load cover ' + item.cover)
item.coverSource = await self.getDirectSource(item.cover)
if (debug) log(item.index, 'Sourced is ' + item.coverSource)
} else {
if (debug) log(item.index, 'No need to load source')
if (debug) log(item.index, 'Source form DirectLink')
}
self.afterCoverSourced(item)
return item
})).then(() => {
self.afterCoversSourced()
})
},
working : function () {
let self = this
//Column picture
$(downloadListHead.td.get(0)).after(
$("<td>", {
class : 'colhead 11',
align : 'center',
width : '125px',
text : "รูป"
}).append(progressBar.template)
)
downloadList.map(function ( item, index ) {
if (debug) log(item.index, 'Add event preview loaded')
//Add Event
item.coverHoverPreviewImg
// .onerror(self.errorCoverPreview)
.onload = () => {
self.loadedHoverPreview(self, item)
}
item.coverPreviewImg.on('error', self.errorCoverPreview).on('load', ( e ) => {
self.loadedCoverPreview(e.target)
// self.afterLoadedCoverPreview(self, item)
})
item.coverPreview.html(loading)
let td = $("<td>", {
align : 'center',
'bgcolor' : item.tdColor
}).append(item.coverPreview)
$(item.elements.td.get(0)).after(td)
//reset preview max height to column height
let columnHeight = td.height()
if (settings.previewMaxHeight < columnHeight)
item.coverPreviewImg.css('max-height', (settings.previewColumnMaxHeight === false ? columnHeight : settings.previewColumnMaxHeight) + 'px')
})
},
afterDownloadListed : function () {
this.working()
this.workingSource()
},
afterCoverSourced : function ( dList ) {
//progressBar Head Column
progressBar.run++
this.updateProgressBar()
//update cover preview
this.updateCoverPreview(dList)
//update hover preview
this.updateHoverPreview(dList)
},
afterCoversSourced : function () {
//Add DirectLink
let coverSources = downloadList.filter(r => r.coverSource && r.except === false).map(r => {
return { 'link' : r.cover, 'direct' : r.coverSource }
})
if (coverSources.length > 0) this.addDirectLinks(coverSources)
},
timestamp : function () {
return (Date.now() / 1000 | 0)
},
cacheGenKey : function ( url ) {
return cacheKey + md5(url)
},
cacheGet : function ( key, valueDefault ) {
let cache = GM_getValue(key, null)
if (cache) {
cache = JSON.parse(cache)
cache = $.extend({
val : null,
timeout : this.timestamp(),
}, cache)
if (cache.timeout > this.timestamp()) {
return cache.val
} else {
GM_deleteValue(key)
}
}
return valueDefault
},
cacheSet : function ( key, val, minute ) {
let cache = {
val : val,
timeout : this.timestamp() + (minute * 60),
}
GM_setValue(key, JSON.stringify(cache))
},
cacheHas : function ( key ) {
return this.cacheGet(key, null) !== null
},
extractHostname : function ( url ) {
let hostname
if (url.indexOf("//") > -1) {
hostname = url.split('/')[ 2 ]
} else {
hostname = url.split('/')[ 0 ]
}
hostname = hostname.split(':')[ 0 ]
hostname = hostname.split('?')[ 0 ]
return hostname
},
loadDownloadList : function () {
let self = this
//List pages
if (locationList.includes(locationCurrent.pathname)) {
$.when($(".mainouter table[width='100%'] tr").each(function ( index, element ) {
let _this = $(this)
let _td = $("td", _this)
//Head
if (index === 0) {
downloadListHead.element = element
downloadListHead.td = _td
_td.each(function ( index, tdElement ) {
if (tdElement.textContent === "ขนาด") downloadListHead.index.fileSize = index
if (tdElement.textContent === "เสร็จ") downloadListHead.index.downloaded = index
if (tdElement.textContent === "ปล่อย") downloadListHead.index.seed = index
if (tdElement.textContent === "ดูด") downloadListHead.index.peer = index
})
} else {
//Title
let _title = $("a:first-child b", _td.get(1)).first()
let title = _title.text()
//Cover
let _cover = $(locationCurrent.pathname === '/upfinish.php' ? "td a>img[src='/pic/cam.gif']" : "td[width='900'] a>img[src='pic/cam.gif ']", _this).parent()
let cover = null
if (_cover.is('a')) {
cover = _cover.attr('href')
}
//Category
let _category = $("img", _td.get(0)).first()
let category = null
if (_category.length === 1) {
category = _category.attr('src').replace('pic/categories/cat-', '')
.replace('pic/categories/', '')
.replace('.gif', '')
.replace('.png', '')
}
//FileSize
let _fileSize = _td.get(downloadListHead.index.fileSize)
let fileSize = _fileSize.textContent
//Downloaded
let _downloaded = _td.get(downloadListHead.index.downloaded)
let downloaded = _downloaded.textContent
//Seed
let _seed = _td.get(downloadListHead.index.seed)
let seed = _seed.textContent
//Peer
let _peer = _td.get(downloadListHead.index.peer)
let peer = _peer.textContent
//TdColor
let tdColor = $(_td.get(0)).attr('bgcolor')
//Elements
let elements = {
'element' : element,
'title' : _title,
'cover' : _cover,
'category' : _category,
'fileSize' : _fileSize,
'downloaded' : _downloaded,
'seed' : _seed,
'peer' : _peer,
'td' : _td,
}
self.addDownloadList(title, cover, category, fileSize, downloaded, seed, peer, tdColor, elements)
}
})).then(() => {
this.afterDownloadListed()
})
}
},
addDownloadList : function ( title, cover, category, fileSize, downloaded, seed, peer, tdColor, elements ) {
let data = {
title : title,
cover : cover,
coverSource : null,
coverHoverPreviewImg : new Image(),
coverThumbnail : null,
coverHash : md5(cover),
coverPreview : $('<div>'),
coverPreviewImg : $('<img>', { class : 'preview' }),
category : category,
fileSize : fileSize,
downloaded : downloaded,
seed : seed,
peer : peer,
tdColor : tdColor,
except : false,
elements : elements,
}
//Add Index
data.index = downloadList.length + 1
//Use Cache before add downloadList
if (settings.cache) {
let coverSourceCache = this.cacheGet(this.cacheGenKey(cover), null)
if (coverSourceCache) {
if (debug) log(data.index, 'Use cache ' + coverSourceCache)
data.coverSource = coverSourceCache
}
let coverThumbnailCache = this.cacheGet(this.cacheGenKey(cover + '-thumbnail'), null)
if (coverThumbnailCache) {
if (debug) log(data.index, 'Use cache thumbnail ' + coverThumbnailCache)
data.coverThumbnail = coverThumbnailCache
}
}
//Check exclude preview
if (settings.exceptCategories.includes(category)) {
data.coverSource = settings.previewExcept
data.coverThumbnail = settings.previewExcept
data.except = true
}
//Check no cover
if (data.cover === null) {
data.cover = settings.previewFail
data.except = true
}
downloadList.push(data)
progressBar.all++
},
getDirectSource : async function ( url ) {
let domain = this.extractHostname(url)
//Custom
let custom = patterns.custom.find(r => r.domains.includes(domain))
if (custom) {
if (custom.synchronous) {
return await custom.callback(url, this)
} else {
return custom.callback(url, this)
}
}
//Direct
if (url.match(/\.(jpeg|jpg|gif|png)$/) != null) {
if (patterns.direct.excepts.indexOf(domain) === -1)
return url
}
//Meta
let meta = patterns.meta.find(r => r.domains.includes(domain))
if (meta) {
if (debug) log('+', 'Get source from meta')
return await this.getDirectSourceSite(url, 'meta', { selector : meta.selector })
}
//Selector
let selector = patterns.selector.find(r => r.domains.includes(domain))
if (selector) {
if (debug) log('+', 'Get source from selector')
return await this.getDirectSourceSite(url, 'selector', {
selector : selector.selector,
attr : selector.attr,
})
}
//Replace
let replace = patterns.replace.find(r => r.domains.includes(domain))
if (replace) {
if (debug) log('+', 'Get source from replace')
return url.replace(replace.replace_find, replace.replace_new)
}
return url
},
getDirectSourceSite : async function ( url, mode, argument, callback ) {
return await new Promise(resolve => {
GM_xmlhttpRequest({
method : "GET",
url : url,
synchronous : true,
onload : function ( res ) {
let responseHTML = new DOMParser().parseFromString(res.responseText, "text/html")
let data
if (mode === 'meta') {
data = $("meta[property='" + argument.selector + "']", responseHTML).attr("content")
} else if (mode === 'selector') {
data = $(argument.selector, responseHTML).first().attr(argument.attr)
}
if (callback) {
callback(res)
}
resolve(data)
},
ontimeout : () => {
resolve(null)
},
onerror : () => {
resolve(null)
}
})
})
},
getDirectLinks : async function ( coversHash ) {
return await new Promise(resolve => {
GM_xmlhttpRequest({
method : "GET",
url : settings.directLinkApi + '?find=' + coversHash,
responseType : "json",
timeout : settings.directLinkTimeout,
synchronous : true,
onload : function ( res ) {
resolve(res.response)
},
ontimeout : () => {
resolve([])
},
onerror : () => {
resolve([])
},
onabort : () => {
resolve([])
}
})
})
},
addDirectLinks : function ( sources ) {
GM_xmlhttpRequest({
method : "PUT",
url : settings.directLinkApi,
headers : {
"Content-Type" : "application/x-www-form-urlencoded"
},
responseType : "json",
synchronous : false,
data : 'data=' + JSON.stringify(sources),
onload : function ( res ) {
if (res.response.status)
if (debug) log('+', 'Add DirectLink success ' + res.response.count_created + ' items')
}
})
},
updateProgressBar : function () {
progressBar.template.html(" [" + progressBar.run + "/" + progressBar.all + "]")
},
updateHoverPreview : function ( dList ) {
if (debug) log(dList.index, 'Update cover hover preview')
if (dList.coverSource) {
dList.coverHoverPreviewImg.src = dList.coverSource
}
},
updateCoverPreview : function ( dList ) {
if (debug) log(dList.index, 'Update cover preview')
let src = dList.coverThumbnail || dList.coverSource
if (src) {
dList.coverPreviewImg.attr('src', src)
} else {
dList.coverPreviewImg.trigger('error')
}
dList.coverPreview.append(dList.coverPreviewImg)
},
errorCoverPreview : function () {
this.src = settings.previewFail
this.title = 'Loaded image fail!'
let element = $(this)
element.prev().hide()
element.show()
},
loadedCoverPreview : function ( self ) {
if (debug) log('+', 'Loaded cover ' + self.src)
let element = $(self)
element.prev().hide()
element.show()
//Title for except
if (settings.previewExcept === self.src)
self.title = 'Except image!'
},
loadedHoverPreview : function ( self, dList ) {
if (debug) log(dList.index, 'Call loaded hover preview')
//Cache cover thumbnail
if (settings.cache
&& !self.cacheHas(self.cacheGenKey(dList.cover + '-thumbnail'))
&& dList.coverThumbnail
&& dList.except === false) {
if (debug) log(dList.index, 'Write cache thumbnail')
self.cacheSet(self.cacheGenKey(dList.cover + '-thumbnail'), dList.coverThumbnail, settings.cacheTimeout)
}
//Cache cover source
if (settings.cache
&& !self.cacheHas(self.cacheGenKey(dList.cover))
&& dList.coverSource
&& dList.except === false) {
if (debug) log(dList.index, 'Write cache source')
self.cacheSet(self.cacheGenKey(dList.cover), dList.coverSource, settings.cacheTimeout)
}
//Add hover
if (!dList.except) {
self.hoverPreview(dList.elements.title, dList)
self.hoverPreview(dList.coverPreview, dList)
}
},
hoverPreview : function ( element, dList ) {
let self = this
let imageHeight = Math.ceil(window.innerHeight * 0.6)
let offset = element.offset()
element.hover(function ( e ) {
//Change img src
hoverPreview.img
.attr('src', dList.coverSource)
.css('max-height', imageHeight + 'px')
.on('load', function () {
hoverPreview.imgHeight = $(this).height() + 10
})
hoverPreview.previewTop = e.pageY - hoverPreview.xOffset
hoverPreview.previewLeft = e.pageX + hoverPreview.yOffset
hoverPreview.yOffsetPreLoadFix = 0
hoverPreview.yOffsetFix = (window.innerHeight - e.clientY)
hoverPreview.yOffsetFix = hoverPreview.yOffsetFix < 0 ? (hoverPreview.yOffsetFix - 50) : 0
hoverPreview.yOffsetPreLoadFix = hoverPreview.yOffsetFix
//Show popup
hoverPreview.popup.css({
top : hoverPreview.previewTop + "px",
left : hoverPreview.previewLeft + "px"
}).show()
}, function ( e ) {
hoverPreview.previewTop = e.pageY - hoverPreview.xOffset
hoverPreview.popup.hide()
})
$(element).mousemove(function ( e ) {
let fixY = 60
if (e.clientY < hoverPreview.imgHeight) {
fixY = hoverPreview.yOffsetPreLoadFix + hoverPreview.imgHeight - e.clientY
}
hoverPreview.popup.css("top", e.pageY - hoverPreview.xOffset + hoverPreview.yOffsetPreLoadFix - hoverPreview.imgHeight + fixY + "px").css("left", e.pageX + hoverPreview.yOffset + "px")
})
}
}
}
SiambitZoomScreenShot().init()
}(jQuery))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment