Feeder - 貼り付けて画像投稿

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

Από την 27/05/2021. Δείτε την τελευταία έκδοση.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==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)