Feeder - 貼り付けて画像投稿

コピーした画像や画像のアドレスを貼り付けるだけでアップロードできるスクリプトです。

Versione datata 27/05/2021. Vedi la nuova versione l'ultima versione.

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         Feeder - 貼り付けて画像投稿
// @namespace    http://tampermonkey.net/
// @version      1.0.0
// @license      MIT
// @description  コピーした画像や画像のアドレスを貼り付けるだけでアップロードできるスクリプトです。
// @author       You
// @match        *.x-feeder.info/*
// @exclude      *.x-feeder.info/*/sp
// @exclude      *.x-feeder.info/*/settings/*
// @icon         https://www1.x-feeder.info/favicon.ico
// @grant        GM.setValue
// @grant        GM.getValue
// @grant        GM.xmlHttpRequest
// ==/UserScript==

'use strict'
const SIZE_SAVE_KEY = 'size',
    PASTE_AREA_LABEL_TEXT = 'ここに貼り付け',
    POST_URL = 'post_picture_xhr.php'

const main = async () => {
    const scrollData = {
        old: [window.pageXOffset, window.pageYOffset],
        cur: [window.pageXOffset, window.pageYOffset]
    }
    window.addEventListener('scroll', () => {
        [scrollData.old[0], scrollData.old[1]] = scrollData.cur
        scrollData.cur[0] = window.pageXOffset
        scrollData.cur[1] = window.pageYOffset
    })

    const h = (() => {
        const e = document.createElement('div')
        e.style.padding = '1em'
        e.style.borderRadius = '5px'
        e.style.backgroundColor = '#C0C0C0'
        const parNode = document.getElementById('main_right')
        parNode.insertBefore(e, parNode.firstChild)
        return e
    })()

    const selectSize = await (async () => {
        const label = document.createElement('label')
        label.textContent = 'サイズ '
        h.appendChild(label)

        const e = document.createElement('select')
        for (const [i, v] of ['縮小しない', '84 x 84', '168 x 168(デフォルト)', '252 x 252', '336 x 336', '420 x 420'].entries()) {
            const opt = document.createElement('option')
            opt.textContent = v
            opt.value = i.toString()
            e.appendChild(opt)
        }
        e.addEventListener('change', e => void GM.setValue(SIZE_SAVE_KEY, e.target.value))
        const val = await GM.getValue(SIZE_SAVE_KEY)
        e.value = val || '2'
        label.appendChild(e)
        return e
    })()

    h.appendChild(document.createElement('hr'))

    const pasteArea = (() => {
        const label = document.createElement('div')
        label.textContent = PASTE_AREA_LABEL_TEXT
        h.appendChild(label)

        const e = document.createElement('div')
        e.contentEditable = true
        e.style.height = '3em'
        e.style.borderRadius = '5px'
        e.style.boxShadow = '0px 0px 2.5px 0px #000000 inset'
        e.style.caretColor = 'transprent'
        e.style.backgroundColor = 'gray'
        label.appendChild(e)
        return e
    })()

    const btnArea = (() => {
        const e = document.createElement('div')
        e.style.display = 'none'
        h.appendChild(e)
        e.appendChild(document.createElement('hr'))
        e.appendChild(document.createTextNode('画像を削除'))
        e.appendChild(document.createElement('br'))
        return e
    })()

    for (const e of h.getElementsByTagName('hr')) e.style.margin = '5px'

    new MutationObserver(([record]) => {
        const e = record.addedNodes[0]
        pasteArea.innerHTML = ''
        window.scrollTo(...scrollData.old)
        if (e === void 0 || (('tagName' in e) && e.tagName !== 'IMG')) return
        GM.xmlHttpRequest({
            method: 'GET',
            responseType: 'blob',
            url: e.src || e.textContent,
            onload: async res => {
                if (res.status >= 200 && res.status < 400) {
                    const fd = new FormData()
                    fd.append('frame_size', selectSize.value)
                    fd.append('picture', res.response)
                    const body = await (await fetch(POST_URL, { method: 'POST', body: fd })).text(),
                        m = body.match(/^([1-9][0-9]*),([0-9a-f]{16})$/)
                    if (m === null) {
                        console.error(body)
                        alert(body)
                        return
                    }
                    const [id, hash] = m.slice(1),
                        inputArea = document.getElementById(unsafeWindow.newActiveForm),
                        pos = inputArea.selectionStart
                    inputArea.value = `${inputArea.value.substr(0, pos)}[P:${id}]${inputArea.value.substr(pos, inputArea.value.length)}`
                    btnArea.style.display = 'block'
                    const btn = document.createElement('button')
                    btn.textContent = id
                    btnArea.appendChild(btn)
                    btn.addEventListener('click', async e => {
                        const fd = new FormData()
                        fd.append('id', id)
                        fd.append('hash', hash)
                        await fetch(POST_URL, { method: 'POST', body: fd })
                        e.target.parentNode.removeChild(e.target)
                        if (btnArea.getElementsByTagName('button').length === 0) btnArea.style.display = 'none'
                    })
                } else {
                    console.error(res)
                    alert('画像を取得できませんでした')
                }
            }
        })
    }).observe(pasteArea, { childList: true })
}

main().catch(console.error)