/* tslint:disable:quotemark */ import * as _ from 'lodash'; import { domain } from '../bbcode/core'; export interface PreviewMutator { match: string|RegExp; injectJs: string; } export interface ImagePreviewMutatorCollection { [key: string]: PreviewMutator; } export class ImagePreviewMutator { private hostMutators: ImagePreviewMutatorCollection = {}; private regexMutators: PreviewMutator[] = []; constructor() { this.init(); } getMutatorJsForSite(url: string): string | undefined { let mutator = this.matchMutator(url); if (!mutator) mutator = this.hostMutators['default']; return this.wrapJs(mutator.injectJs); } matchMutator(url: string): PreviewMutator | undefined { const urlDomain = domain(url); if (!urlDomain) return; if (urlDomain in this.hostMutators) return this.hostMutators[urlDomain]; return _.find( this.regexMutators, (m: PreviewMutator) => { const match = m.match; return (match instanceof RegExp) ? (urlDomain.match(match) !== null) : (match === urlDomain); } ); } protected wrapJs(mutatorJs: string) { return `(() => { try { ${mutatorJs} } catch (err) { console.error('Mutator error', err); } })();`; } protected add(domain: string|RegExp, mutatorJs: string) { if (domain instanceof RegExp) { this.regexMutators.push( { match: domain, injectJs: mutatorJs } ); return; } this.hostMutators[domain] = { match: domain, injectJs: mutatorJs }; } protected init() { this.add('default', this.getBaseJsMutatorScript('#video, #image, video, img')); this.add('e621.net', this.getBaseJsMutatorScript('#image, video')); this.add('e-hentai.org', this.getBaseJsMutatorScript('#img, video')); this.add('gelbooru.com', this.getBaseJsMutatorScript('#image, video')); this.add('chan.sankakucomplex.com', this.getBaseJsMutatorScript('#image, video')); this.add('danbooru.donmai.us', this.getBaseJsMutatorScript('#image, video')); this.add('gfycat.com', this.getBaseJsMutatorScript('video')); this.add('gfycatporn.com', this.getBaseJsMutatorScript('video')); this.add('youtube.com', this.getBaseJsMutatorScript('video')); this.add('instantfap.com', this.getBaseJsMutatorScript('#post img, #post video')); this.add('webmshare.com', this.getBaseJsMutatorScript('video')); this.add('pornhub.com', this.getBaseJsMutatorScript('.mainPlayerDiv video, .photoImageSection img')); this.add('sex.com', this.getBaseJsMutatorScript('.image_frame img, .image_frame video')); this.add('redirect.media.tumblr.com', this.getBaseJsMutatorScript('picture img, picture video')); this.add('i.imgur.com', this.getBaseJsMutatorScript('video, img')); this.add('postimg.cc', this.getBaseJsMutatorScript('#main-image, video')); this.add('gifsauce.com', this.getBaseJsMutatorScript('video')); this.add('motherless.com', this.getBaseJsMutatorScript('.content video, .content img')); // this.add('beeg.com', this.getBaseJsMutatorScript('video')); this.add(/^media[0-9]\.giphy\.com$/, this.getBaseJsMutatorScript('video, img[alt]')); this.add( 'imgur.com', ` const imageCount = $('.post-container video, .post-container img').length; ${this.getBaseJsMutatorScript('.post-container video, .post-container img', true)} if(imageCount > 1) $('#flistWrapper').append('
+' + (imageCount - 1) + '
'); ` ); this.add( 'rule34.xxx', `${this.getBaseJsMutatorScript('#image, video')} const content = document.querySelector('#content'); content.remove(); ` ); } getBaseJsMutatorScript(imageSelector: string, skipElementRemove: boolean = false): string { return `const body = document.querySelector('body'); const img = Array.from(document.querySelectorAll('${imageSelector}')) .filter((i) => ((i.width !== 1) && (i.height !== 1))).shift() if (!img) { return; } const el = document.createElement('div'); el.id = 'flistWrapper'; el.style = 'width: 100% !important; height: 100% !important; position: absolute !important;' + 'top: 0 !important; left: 0 !important; z-index: 100000 !important;' + 'background-color: black !important; background-size: contain !important;' + 'background-repeat: no-repeat !important; background-position: top left !important;' + 'opacity: 1 !important; padding: 0 !important; border: 0 !important; margin: 0 !important;'; img.remove(); el.append(img); body.append(el); body.class = ''; // console.log(el); // console.log(img); // console.log('${imageSelector}'); body.style = 'border: 0 !important; padding: 0 !important; margin: 0 !important; overflow: hidden !important;' + 'width: 100% !important; height: 100% !important; opacity: 1 !important;' + 'top: 0 !important; left: 0 !important;'; img.style = 'object-position: top left !important; object-fit: contain !important;' + 'width: 100% !important; height: 100% !important; opacity: 1 !important;' + 'margin: 0 !imporant; border: 0 !important; padding: 0 !important;'; img.class = ''; el.class = ''; if (img.play) { img.muted = true; img.play(); } let removeList = []; body.childNodes.forEach((el) => { if((el.id !== 'flistWrapper') && (el.id !== 'flistError')) { removeList.push(el); } }); // ${skipElementRemove ? '' : 'removeList.forEach((el) => el.remove());'} removeList = []; `; } getErrorMutator(code: number, description: string): string { const errorHtml = `

${code}

${description}

`; return this.wrapJs(` const range = document.createRange(); range.selectNode(document.body); const error = range.createContextualFragment(\`${errorHtml}\`); document.body.appendChild(error); `); } }