Media Embedder

Enables embedding of certain images in the chat.

当前为 2024-06-26 提交的版本,查看 最新版本

// ==UserScript==
// @name            Media Embedder
// @namespace       http://tampermonkey.net/
// @version         0.0.1
// @description     Enables embedding of certain images in the chat.
// @include         https://*.the-west.*/game.php*
// @grant           none
// @license         GNU
// ==/UserScript==


window.MediaEmbedder = {
    baseUrl: `https://enormous-seasoned-porkpie.glitch.me`,
    screenshotRegex: new RegExp(/(?:https:\/\/)?(?:prnt\.sc|ctrlv\.[a-zA-Z]{2,4})\/[A-Za-z0-9_-]+/, 'g'),


    showImageFullscreen: function(url, originalUrl) {
        const html = $(`
            <div id='screenshot-framefix' style='position: fixed; inset: 0; padding: 2rem 4rem; z-index: 9999; background-color: rgba(0, 0, 0, .8)'>
                <div style='cursor: pointer; position: absolute; top: 1rem; right: 1rem'>
                    <svg style='fill: white; transition: fill .3s; width: 25px' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M64 80c-8.8 0-16 7.2-16 16V416c0 8.8 7.2 16 16 16H448c8.8 0 16-7.2 16-16V96c0-8.8-7.2-16-16-16H64zM0 96C0 60.7 28.7 32 64 32H448c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96zm175 79c9.4-9.4 24.6-9.4 33.9 0l47 47 47-47c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-47 47 47 47c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-47-47-47 47c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l47-47-47-47c-9.4-9.4-9.4-24.6 0-33.9z"/></svg>
                </div>

                <div style='position: relative; display: flex; height: 100%; justify-content: center; align-items: center'>
                    <img src='${url}' alt='image not found' style='object-fit: contain; max-width: 100%; max-height: 100%'>
                </div>

                <div id='image-link' style='position: absolute; bottom: 1rem; right: 1rem; color: white'>
                    <a target='_blank' href='${originalUrl}'>${originalUrl}</a>
                    <span></span>
                </div>
            </div>
        `)

        html.click(() => {
            document.body.removeChild(html[0])
        })

        html.find('img').click(e => e.stopPropagation())

        const closeIcon = html.find('svg')
        closeIcon.click(() => {
            document.body.removeChild(html[0])
        })

        closeIcon.hover(function() {
            closeIcon.css('fill', 'rgb(255, 144, 144)')
        }, function() {
            closeIcon.css('fill', 'rgb(255, 255, 255)')
        })

        document.body.appendChild(html[0])
    },  

    getImageUrl: async function(url) {
        try {
            const response = await fetch(`${this.baseUrl}/img-url?url=${url}`, {
                method: 'Get',
                mode: 'cors'
            })

            if ( !response.ok ) {
                return null
            }

            const { image_url } = await response.json()     
            return image_url
        } catch(e) {
            console.log(e)
            return null
        }         
    },

    getImageHtml: function(url, originalUrl) {
        const collapseHtml = $(`
            <span style='display: flex; gap: 3px; font-weight: bold'>
                Collapse
                <svg style='fill: white; width: 10px' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M439 7c9.4-9.4 24.6-9.4 33.9 0l32 32c9.4 9.4 9.4 24.6 0 33.9l-87 87 39 39c6.9 6.9 8.9 17.2 5.2 26.2s-12.5 14.8-22.2 14.8H296c-13.3 0-24-10.7-24-24V72c0-9.7 5.8-18.5 14.8-22.2s19.3-1.7 26.2 5.2l39 39L439 7zM72 272H216c13.3 0 24 10.7 24 24V440c0 9.7-5.8 18.5-14.8 22.2s-19.3 1.7-26.2-5.2l-39-39L73 505c-9.4 9.4-24.6 9.4-33.9 0L7 473c-9.4-9.4-9.4-24.6 0-33.9l87-87L55 313c-6.9-6.9-8.9-17.2-5.2-26.2s12.5-14.8 22.2-14.8z"/></svg>
            </span>
        `)

        const expandHtml = $(`
            <span style='display: flex; gap: 3px; transform: translateY(.3rem); font-weight: bold'>
                Expand
                <svg style='fill: white; width: 10px' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.5.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M344 0H488c13.3 0 24 10.7 24 24V168c0 9.7-5.8 18.5-14.8 22.2s-19.3 1.7-26.2-5.2l-39-39-87 87c-9.4 9.4-24.6 9.4-33.9 0l-32-32c-9.4-9.4-9.4-24.6 0-33.9l87-87L327 41c-6.9-6.9-8.9-17.2-5.2-26.2S334.3 0 344 0zM168 512H24c-13.3 0-24-10.7-24-24V344c0-9.7 5.8-18.5 14.8-22.2s19.3-1.7 26.2 5.2l39 39 87-87c9.4-9.4 24.6-9.4 33.9 0l32 32c9.4 9.4 9.4 24.6 0 33.9l-87 87 39 39c6.9 6.9 8.9 17.2 5.2 26.2s-12.5 14.8-22.2 14.8z"/></svg>
            </span>
        `)

        const html = $(`
            <span style='width: 100%; cursor: pointer; padding: .2rem .5rem; display: inline-block; box-sizing: border-box; position: relative; overflow: hidden'>
                <img src='${url}' width='100%' alt='embedded image' style='border-radius: 8px' onclick="MediaEmbedder.showImageFullscreen('${url}', '${originalUrl}')">
                <span class='expand-collapse-image' style='position: absolute; right: 5px; bottom: 5px; font-size: .7rem'></span>
            </span> 
        `)

        function replaceElement(isExpanded) {
            const element = isExpanded ? collapseHtml : expandHtml
            html.find('span.expand-collapse-image').html(element)
            html.css('max-height', isExpanded ? '100%' : '1rem')
    
            element.off('click')
    
            element.click(function() {
                isExpanded = !isExpanded
                replaceElement(isExpanded)
            })
    
            return element
        }
    
        function toggleExpand(isExpanded) {
            return function() {
                replaceElement(isExpanded)
            }
        }

        
        collapseHtml.click(toggleExpand(false))
    

        html.find('span.expand-collapse-image').html(collapseHtml)

        return html
    },

    getMessageHtml: function(media) {
        const now = new ServerDate().date

        const html = $(`
            <table cellpadding='0' cellspacing='0'>
                <tr>
                    <td style='white-space: nowrap' class='chat_info'>
                        <span class='chat_time'>
                            [<strong>${now.getHours()}:${now.getMinutes()}</strong>]
                        </span>
                        <span class='chat_from'>
                            <strong>Media Embedder</strong>:
                        </span>
                    </td>
                    <td class='media-content'></td>
                </tr>
            </table>
        `)

        html.find('td.media-content').html(media)
        return html
    },

    pushEmbeddedImage: async function(room, url) {
        const imageUrl = await this.getImageUrl(url)

        if ( imageUrl === null ) return

        const imageHtml = this.getImageHtml(imageUrl, url)
        const message = this.getMessageHtml(imageHtml)

        room.history.push(message)
        room.notify('NewMessage', message)
    },

    getMessageContent: function(htmlString) {
        const html = $(htmlString)
        const message = html.find('td.chat_text')
        const tempDiv = $('<div></div>').html(message.html())
        return tempDiv.text()
    },

    testMessage: function(room, message) {
        const text = this.getMessageContent(message)
        const urls = [...new Set(Array.from(text.matchAll(this.screenshotRegex)).map(e => e[0]))]

        for ( const url of urls ) {
            this.pushEmbeddedImage(room, url)
        }
    }
}

$(document).ready(() => {
    Chat.Resource.Room.prototype.addMessage = function(message) {
        if (this.history.length > this.historyLimit)
            this.history.splice(0, this.historyLimit - this.history.length);
        this.history.push(message);
        this.notify("NewMessage", message);
        MediaEmbedder.testMessage(this, message);
    }

    const newCss = `
            #image-link a {
                text-decoration: none;
                color: white;
                position: relative;
                padding: .4rem .2rem;
            }

            #image-link span {
                position: absolute;
                bottom: 0;
                right: 0;
                width: 100%;
                height: 2px;
                background-color: white;
                opacity: 0;
                transition: opacity .3s;
            }

            #image-link:hover span {
                opacity: 1;
            }
        `

        const style = $('<style>').text(newCss)
        $('head').append(style)
})

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址