Greasy Fork

来自缓存

Greasy Fork is available in English.

lck

롤캐 숙제 바로가기 (드래그 이동 기능 추가)

当前为 2025-01-24 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         lck
// @namespace    lck
// @version      1.7
// @description  롤캐 숙제 바로가기 (드래그 이동 기능 추가)
// @match        https://lolcast.kr/*
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function() {
    'use strict';

    // 채널 정보
    const CHANNELS = {
        youtube: {
            id: 'UCw1DsweY9b2AKGjV4kGJP1A',
            buttonLabel: '유튜브',
            color: '#FF0000',
            url: (id) => `/#/player/youtube/${id}`
        },
        chzzk: {
            buttonLabel: '치지직',
            color: '#00FFA3',
            url: () => '/#/player/chzzk/9381e7d6816e6d915a44a13c0195b202'
        },
        afreeca: {
            buttonLabel: '숲',
            color: '#2970B6',
            url: () => '/#/player/afreeca/aflol'
        }
    };

    // 유튜브 라이브 영상 ID 가져오기
    async function fetchLiveVideoId(channelId) {
        const YOUTUBE_LIVE_URL = `https://www.youtube.com/channel/${channelId}/live`;
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: "GET",
                url: YOUTUBE_LIVE_URL,
                onload: function(response) {
                    const videoIdMatch = response.responseText.match(/"videoId":"([\w-]+)"/);
                    const isLiveNow = response.responseText.includes('"isLiveNow":true') || response.responseText.includes('"isLive":true');
                    const liveBroadcastContentMatch = response.responseText.match(/"liveBroadcastContent":"(\w+)"/);
                    const isLiveBroadcast = liveBroadcastContentMatch && liveBroadcastContentMatch[1] === 'live';

                    if (videoIdMatch && videoIdMatch[1] && (isLiveNow || isLiveBroadcast)) {
                        resolve(videoIdMatch[1]);
                    } else {
                        reject('No live video found.');
                    }
                },
                onerror: reject
            });
        });
    }

    // 컨트롤 패널 생성
    const controlPanel = document.createElement('div');
    controlPanel.style.position = 'fixed';
    // 기본 위치 (left: 0, top: 380px) - 이후 드래그가 가능하므로 원하는 위치로 옮길 수 있습니다.
    controlPanel.style.top = '380px';
    controlPanel.style.left = '0';
    controlPanel.style.padding = '7px';
    controlPanel.style.borderRadius = '0 4px 4px 0';
    controlPanel.style.zIndex = '9999';
    controlPanel.style.display = 'flex';
    controlPanel.style.gap = '6px';
    controlPanel.style.background = 'transparent';
    controlPanel.style.transition = 'all 0.3s ease';

    // 이전 위치 불러오기(localStorage)
    const savedPosition = localStorage.getItem('lckControlPanelPosition');
    if (savedPosition) {
        try {
            const { left, top } = JSON.parse(savedPosition);
            controlPanel.style.left = left;
            controlPanel.style.top = top;
        } catch(e) {
            console.error('Failed to parse saved control panel position:', e);
        }
    }

    // 드래그 기능 추가
    let isDragging = false;
    let offsetX = 0;
    let offsetY = 0;

    controlPanel.addEventListener('mousedown', (e) => {
        // 버튼 위에서도 이동 가능하도록 하려면, e.target이 버튼이면 return을 제거하거나 조정하세요.
        // 현재는 패널의 빈 영역에서만 드래그가 되는 것이 일반적이므로 조건을 사용하지 않습니다.
        isDragging = true;
        offsetX = e.clientX - controlPanel.offsetLeft;
        offsetY = e.clientY - controlPanel.offsetTop;
    });

    document.addEventListener('mousemove', (e) => {
        if (isDragging) {
            controlPanel.style.left = (e.clientX - offsetX) + 'px';
            controlPanel.style.top = (e.clientY - offsetY) + 'px';
        }
    });

    document.addEventListener('mouseup', () => {
        if (isDragging) {
            isDragging = false;
            // 위치 저장
            localStorage.setItem('lckControlPanelPosition', JSON.stringify({
                left: controlPanel.style.left,
                top: controlPanel.style.top
            }));
        }
    });

    // 버튼 생성 함수 (크기 1pt씩 작게 조정)
    function createChannelButton(channel) {
        const button = document.createElement('button');
        button.textContent = channel.buttonLabel;
        button.style.padding = '5px 11px';
        button.style.color = channel.color;
        button.style.border = `1px solid ${channel.color}`;
        button.style.borderRadius = '3px';
        button.style.cursor = 'pointer';
        button.style.fontSize = '13px';
        button.style.transition = 'all 0.2s';
        button.style.background = 'transparent';

        button.onmouseover = () => {
            button.style.background = channel.color;
            button.style.color = 'white';
        };
        button.onmouseout = () => {
            button.style.background = 'transparent';
            button.style.color = channel.color;
        };
        button.onclick = async () => {
            if (channel.buttonLabel === '유튜브') {
                try {
                    const liveVideoId = await fetchLiveVideoId(channel.id);
                    window.location.href = channel.url(liveVideoId);
                } catch {
                    alert('유튜브 라이브 방송이 없습니다.');
                }
            } else {
                window.location.href = channel.url();
            }
        };
        return button;
    }

    // 토글 버튼 생성 (크기 1pt씩 작게 조정)
    function createToggleButton() {
        const toggleButton = document.createElement('button');
        toggleButton.textContent = '◀';
        toggleButton.style.padding = '5px 11px';
        toggleButton.style.color = '#888';
        toggleButton.style.border = '1px solid #888';
        toggleButton.style.borderRadius = '3px';
        toggleButton.style.cursor = 'pointer';
        toggleButton.style.fontSize = '13px';
        toggleButton.style.transition = 'all 0.2s';
        toggleButton.style.background = 'transparent';

        toggleButton.onmouseover = () => {
            toggleButton.style.background = '#888';
            toggleButton.style.color = 'white';
        };
        toggleButton.onmouseout = () => {
            toggleButton.style.background = 'transparent';
            toggleButton.style.color = '#888';
        };
        toggleButton.onclick = () => {
            controlPanel.style.display = 'none'; // 패널 숨기기
        };
        return toggleButton;
    }

    // 버튼 추가
    const youtubeButton = createChannelButton(CHANNELS.youtube);
    const chzzkButton = createChannelButton(CHANNELS.chzzk);
    const afreecaButton = createChannelButton(CHANNELS.afreeca);
    const toggleButton = createToggleButton();

    controlPanel.appendChild(youtubeButton);
    controlPanel.appendChild(chzzkButton);
    controlPanel.appendChild(afreecaButton);
    controlPanel.appendChild(toggleButton);
    document.body.appendChild(controlPanel);
})();