{"version":"https://jsonfeed.org/version/1.1","title":"DBD-raws","home_page_url":"https://cms.dbdraws.dpdns.org","feed_url":"https://cms.dbdraws.dpdns.org/json/","description":"<style>\n        #api-text-container {\n            font-size: 22px;\n            \n            max-width: 90%;\n            text-align: center;\n            line-height: 1.6;\n            padding: 20px;\n            border-left: 4px solid #4CAF50;\n            box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n        }\n@media (max-width: 768px) {\n            #api-text-container {\n                font-size: 18px; /* 移动端减小到18px */\n                max-width: 95%; /* 移动端宽度占比更大（减少留白） */\n                padding: 15px; /* 移动端内边距减小 */\n            }\n    </style>\n<p id=\"api-text-container\"></p>\n<script>\n  // 调用文字API（以「一言」为例，返回随机句子）\n  fetch(\"https://v1.hitokoto.cn/?c=d\") // API地址（返回JSON）\n    .then(response => response.json())\n    .then(data => {\n      // 将API返回的文字填入容器（不添加任何样式，使用网站默认文本样式）\n      document.getElementById(\"api-text-container\").textContent = data.hitokoto;\n    })\n    .catch(error => {\n      // 加载失败时显示提示（同样使用默认样式）\n      document.getElementById(\"api-text-container\").textContent = \"加载失败，请稍后刷新\";\n    });\n</script>\n\n<p>这是一款轻量级的内容管理系统（CMS），可自行托管于Cloudflare平台。通过microfeed，您能够便捷地发布多种形式的内容——包括音频、视频、照片、文档、博客文章及外部链接，并以网页、RSS订阅和JSON格式输出信息流。</p>","icon":"https://cms.dbdraws.dpdns.org/assets/default/channel-image.png","favicon":"https://cms.dbdraws.dpdns.org/assets/default/favicon.png","authors":[{"name":"DBD制作组"}],"language":"zh-cn","items":[{"id":"Ak02D0CbhPX","title":"随机小姐姐 - 最新源","url":"https://cms.dbdraws.dpdns.org/i/随机小姐姐-新源-Ak02D0CbhPX/","content_html":"\n    <style>\n        body {\n            font-family: 'Arial', sans-serif;\n            max-width: 1000px;\n            margin: 0 auto;\n            padding: 15px;\n            background-color: #f5f5f5;\n        }\n\n        #player-container {\n            background: #000;\n            border-radius: 8px;\n            margin-bottom: 15px;\n            overflow: hidden;\n            box-shadow: 0 4px 8px rgba(0,0,0,0.1);\n        }\n\n        #player {\n            width: 100%;\n            height: auto;\n            max-height: 80vh;\n            min-height: 500px;\n            max-height: 550px;\n            display: block;\n        }\n\n        .control-panel {\n            background: white;\n            padding: 15px;\n            border-radius: 8px;\n            box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n            margin-bottom: 15px;\n        }\n\n        .button-group {\n            display: flex;\n            gap: 8px;\n            margin-bottom: 12px;\n            flex-wrap: wrap;\n        }\n\n        button {\n            background: #7F9CCC;\n            color: #fff;\n            border: none;\n            padding: 10px 12px;\n            border-radius: 6px;\n            font-weight: bold;\n            cursor: pointer;\n            transition: all 0.3s;\n            flex-grow: 1;\n            font-size: 14px;\n            min-width: 80px;\n        }\n\n        button:hover {\n            background: #6A8BBC;\n            transform: translateY(-1px);\n        }\n\n        button#toggleAuto {\n            flex-grow: 2;\n        }\n\n        .source-management {\n            margin-top: 15px;\n        }\n\n        .source-list {\n            margin-top: 10px;\n            max-height: 30vh;\n            overflow-y: auto;\n            border: 1px solid #ddd;\n            border-radius: 4px;\n            padding: 8px;\n            background: white;\n        }\n\n        .source-item {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            padding: 8px;\n            border-bottom: 1px solid #eee;\n        }\n\n        .source-item:last-child {\n            border-bottom: none;\n        }\n\n        .source-url {\n            flex-grow: 1;\n            overflow: hidden;\n            text-overflow: ellipsis;\n            white-space: nowrap;\n            margin-right: 8px;\n            font-size: 14px;\n        }\n\n        .source-actions {\n            display: flex;\n            gap: 5px;\n        }\n\n        .source-actions button {\n            padding: 5px 8px;\n            font-size: 12px;\n            background: #ff6b6b;\n            min-width: 50px;\n            flex-grow: 0;\n        }\n\n        .source-actions button:first-child {\n            background: #4CAF50;\n        }\n\n        .add-source-form {\n            display: flex;\n            gap: 8px;\n            margin-top: 12px;\n        }\n\n        .add-source-form input {\n            flex-grow: 1;\n            padding: 10px;\n            border: 1px solid #ddd;\n            border-radius: 4px;\n            font-size: 14px;\n        }\n\n        .add-source-form button {\n            width: 90px;\n            flex-grow: 0;\n        }\n\n        .status {\n            margin-top: 10px;\n            font-size: 14px;\n            color: #666;\n            text-align: center;\n        }\n\n        .current-source {\n            font-weight: bold;\n            color: #7F9CCC;\n            word-break: break-all;\n        }\n\n        .default-source-indicator {\n            color: #888;\n            font-style: italic;\n            margin-top: 5px;\n        }\n\n        /* 手机端优化 */\n        @media (max-width: 600px) {\n            body {\n                padding: 10px;\n            }\n\n            #player {\n                min-height: 500px;\n            }\n\n            .control-panel {\n                padding: 12px;\n            }\n\n            button {\n                padding: 8px 10px;\n                font-size: 13px;\n            }\n\n            .source-item {\n                flex-direction: column;\n                align-items: flex-start;\n            }\n\n            .source-actions {\n                margin-top: 5px;\n                width: 100%;\n                justify-content: flex-end;\n            }\n\n            .add-source-form {\n                flex-direction: column;\n            }\n\n            .add-source-form button {\n                width: 100%;\n            }\n        }\n    </style>\n\n\n    <div id=\"player-container\">\n        <video id=\"player\" controls playsinline></video>\n    </div>\n    \n    <div class=\"control-panel\">\n        <div class=\"button-group\">\n            <button id=\"toggleAuto\">连续播放: 开</button>\n            <button id=\"nextVideo\">换一个 ▶</button>\n            <button id=\"switchSource\">切换源</button>\n        </div>\n        \n        <div class=\"status\" id=\"statusArea\">\n            <!-- 状态信息动态生成 -->\n        </div>\n        \n        <div class=\"source-management\">\n            <h3 style=\"margin-bottom: 8px;\">视频源管理</h3>\n            <div class=\"source-list\" id=\"sourceList\">\n                <!-- 视频源列表动态生成 -->\n            </div>\n            \n            <div class=\"add-source-form\">\n                <input type=\"text\" id=\"newSourceInput\" placeholder=\"输入视频API地址\">\n                <button id=\"addSource\">添加源</button>\n            </div>\n        </div>\n    </div>\n\n    <script>\n        document.addEventListener('DOMContentLoaded', function() {\n            // 隐藏默认源\n            const defaultSources = [\n                'http://api.mmp.cc/api/ksvideo?type=mp4&id=jk',\n                'https://www.ximi.me/video/list.php'\n            ];\n            \n            // 用户添加的源\n            let userSources = JSON.parse(localStorage.getItem('userVideoSources')) || [];\n            \n            // 获取所有源\n            function getAllSources() {\n                return [...userSources, ...defaultSources];\n            }\n            \n            let currentSourceIndex = 0;\n            let autoPlay = localStorage.getItem('autoPlay') !== 'false';\n            const player = document.getElementById('player');\n            let isProcessing = false;\n            \n            // 单源重试控制\n            let currentSourceRetries = 0;\n            const maxRetriesPerSource = 2;\n            \n            // DOM元素\n            const elements = {\n                toggleAuto: document.getElementById('toggleAuto'),\n                nextVideo: document.getElementById('nextVideo'),\n                switchSource: document.getElementById('switchSource'),\n                sourceList: document.getElementById('sourceList'),\n                newSourceInput: document.getElementById('newSourceInput'),\n                addSource: document.getElementById('addSource'),\n                statusArea: document.getElementById('statusArea')\n            };\n            \n            // 重置重试计数\n            function resetSourceRetry() {\n                currentSourceRetries = 0;\n            }\n            \n            // 初始化播放器\n            function initPlayer() {\n                updateAutoPlayButton();\n                updateSourceDisplay();\n                renderSourceList();\n                \n                if (userSources.length > 0) {\n                    currentSourceIndex = 0;\n                } else {\n                    currentSourceIndex = defaultSources.length > 0 ? userSources.length : 0;\n                }\n                \n                resetSourceRetry();\n                loadRandomVideo();\n            }\n            \n            // 更新自动播放按钮\n            function updateAutoPlayButton() {\n                elements.toggleAuto.textContent = `连续播放: ${autoPlay ? '开' : '关'}`;\n            }\n            \n            // 加载随机视频\n            function loadRandomVideo() {\n                if (isProcessing) return;\n                isProcessing = true;\n                \n                const allSources = getAllSources();\n                if (allSources.length === 0) {\n                    showStatus('无可用视频源，请添加视频源', true);\n                    isProcessing = false;\n                    return;\n                }\n                \n                if (currentSourceIndex >= allSources.length) {\n                    currentSourceIndex = 0;\n                }\n                \n                const currentSource = allSources[currentSourceIndex];\n                const timestamp = new Date().getTime();\n                const randomParam = Math.random();\n                \n                let videoUrl = currentSource;\n                if (currentSource.includes('?')) {\n                    videoUrl += `&_t=${timestamp}_${randomParam}`;\n                } else {\n                    videoUrl += `?_t=${timestamp}_${randomParam}`;\n                }\n                \n                player.src = videoUrl;\n                updateSourceDisplay();\n                \n                requestAnimationFrame(() => {\n                    player.play().catch(e => {\n                        console.error(`当前源第${currentSourceRetries+1}次播放失败:`, e);\n                        \n                        if (e.name === 'NotAllowedError') {\n                            showStatus('请点击播放按钮开始（浏览器限制自动播放）', true);\n                        } else {\n                            if (currentSourceRetries < maxRetriesPerSource) {\n                                currentSourceRetries++;\n                                showStatus(`当前源重试中(${currentSourceRetries}/${maxRetriesPerSource})...`, true);\n                                setTimeout(() => {\n                                    loadRandomVideo();\n                                }, 1000);\n                                return;\n                            } else {\n                                showStatus(`当前源已重试${maxRetriesPerSource}次失败，切换到下一个源...`, true);\n                                resetSourceRetry();\n                                switchToNextSource();\n                            }\n                        }\n                    }).finally(() => {\n                        isProcessing = false;\n                        if (player.paused === false) {\n                            resetSourceRetry();\n                        }\n                    });\n                });\n            }\n            \n            // 显示状态\n            function showStatus(message, isError = false) {\n                requestAnimationFrame(() => {\n                    elements.statusArea.innerHTML = `<div class=\"status-message\" style=\"color: ${isError ? '#ff4444' : '#666'}\">${message}</div>`;\n                });\n            }\n            \n            // 切换下一个源\n            function switchToNextSource() {\n                if (isProcessing) return;\n                \n                const allSources = getAllSources();\n                if (allSources.length === 0) return;\n                \n                currentSourceIndex = (currentSourceIndex + 1) % allSources.length;\n                resetSourceRetry();\n                loadRandomVideo();\n            }\n            \n            // 更新源显示\n            function updateSourceDisplay() {\n                const allSources = getAllSources();\n                if (allSources.length > 0) {\n                    const currentSource = allSources[currentSourceIndex];\n                    const isDefaultSource = defaultSources.includes(currentSource);\n                    \n                    requestAnimationFrame(() => {\n                        if (isDefaultSource) {\n                            elements.statusArea.innerHTML = `\n                                <div class=\"status-message\">正在使用系统默认视频源</div>\n                                <div class=\"default-source-indicator\">如需更好体验，请添加自定义视频源</div>\n                            `;\n                        } else {\n                            elements.statusArea.innerHTML = `\n                                <div class=\"status-message\">当前视频源:</div>\n                                <div class=\"current-source\">${currentSource}</div>\n                            `;\n                        }\n                    });\n                } else {\n                    showStatus('无可用视频源，请添加视频源', true);\n                }\n            }\n            \n            // 渲染源列表\n            function renderSourceList() {\n                requestAnimationFrame(() => {\n                    elements.sourceList.innerHTML = '';\n                    \n                    if (userSources.length === 0) {\n                        elements.sourceList.innerHTML = '<div style=\"text-align: center; padding: 10px; color: #888;\">暂无自定义视频源，请添加</div>';\n                        return;\n                    }\n                    \n                    const fragment = document.createDocumentFragment();\n                    \n                    userSources.forEach((source, index) => {\n                        const sourceItem = document.createElement('div');\n                        sourceItem.className = 'source-item';\n                        \n                        const sourceUrl = document.createElement('span');\n                        sourceUrl.className = 'source-url';\n                        sourceUrl.textContent = source;\n                        \n                        const sourceActions = document.createElement('div');\n                        sourceActions.className = 'source-actions';\n                        \n                        const useBtn = document.createElement('button');\n                        useBtn.textContent = '使用';\n                        useBtn.addEventListener('click', () => {\n                            if (!isProcessing) {\n                                resetSourceRetry();\n                                useSource(index);\n                            }\n                        });\n                        \n                        const deleteBtn = document.createElement('button');\n                        deleteBtn.textContent = '删除';\n                        deleteBtn.addEventListener('click', () => {\n                            if (!isProcessing) deleteSource(index);\n                        });\n                        \n                        sourceActions.appendChild(useBtn);\n                        sourceActions.appendChild(deleteBtn);\n                        \n                        sourceItem.appendChild(sourceUrl);\n                        sourceItem.appendChild(sourceActions);\n                        \n                        fragment.appendChild(sourceItem);\n                    });\n                    \n                    elements.sourceList.appendChild(fragment);\n                });\n            }\n            \n            // 删除源\n            function deleteSource(userSourceIndex) {\n                if (isProcessing) return;\n                isProcessing = true;\n                \n                const allSources = getAllSources();\n                const sourceToDelete = userSources[userSourceIndex];\n                \n                if (allSources[currentSourceIndex] === sourceToDelete) {\n                    switchToNextSource();\n                }\n                \n                userSources.splice(userSourceIndex, 1);\n                saveUserSources();\n                renderSourceList();\n                updateSourceDisplay();\n                \n                if (userSources.length === 0 && allSources.length > 0) {\n                    currentSourceIndex = allSources.length - 1;\n                    loadRandomVideo();\n                }\n                \n                isProcessing = false;\n            }\n            \n            // 使用指定源\n            function useSource(index) {\n                if (isProcessing) return;\n                currentSourceIndex = index;\n                loadRandomVideo();\n            }\n            \n            // 添加新源\n            function addNewSource() {\n                if (isProcessing) return;\n                isProcessing = true;\n                \n                const newSource = elements.newSourceInput.value.trim();\n                \n                if (!newSource) {\n                    showStatus('请输入有效的视频API地址', true);\n                    isProcessing = false;\n                    return;\n                }\n                \n                if (!newSource.startsWith('http://') && !newSource.startsWith('https://')) {\n                    showStatus('URL必须以http://或https://开头', true);\n                    isProcessing = false;\n                    return;\n                }\n                \n                if (getAllSources().includes(newSource)) {\n                    showStatus('该视频源已存在', true);\n                    isProcessing = false;\n                    return;\n                }\n                \n                userSources.unshift(newSource);\n                elements.newSourceInput.value = '';\n                saveUserSources();\n                \n                currentSourceIndex = 0;\n                resetSourceRetry();\n                loadRandomVideo();\n                renderSourceList();\n                \n                showStatus('视频源添加成功', false);\n                isProcessing = false;\n            }\n            \n            // 保存用户源\n            function saveUserSources() {\n                localStorage.setItem('userVideoSources', JSON.stringify(userSources));\n            }\n            \n            // 事件监听\n            document.addEventListener('click', function(e) {\n                if (e.target === elements.toggleAuto) {\n                    autoPlay = !autoPlay;\n                    localStorage.setItem('autoPlay', autoPlay);\n                    updateAutoPlayButton();\n                } else if (e.target === elements.nextVideo) {\n                    resetSourceRetry();\n                    loadRandomVideo();\n                } else if (e.target === elements.switchSource) {\n                    resetSourceRetry();\n                    switchToNextSource();\n                } else if (e.target === elements.addSource) {\n                    addNewSource();\n                }\n            });\n            \n            // 回车添加源\n            elements.newSourceInput.addEventListener('keypress', function(e) {\n                if (e.key === 'Enter') {\n                    addNewSource();\n                }\n            });\n            \n            // 视频结束事件\n            player.addEventListener('ended', function() {\n                if (autoPlay && !isProcessing) {\n                    resetSourceRetry();\n                    loadRandomVideo();\n                }\n            });\n            \n            // 视频错误事件\n            player.addEventListener('error', function() {\n                if (!isProcessing && currentSourceRetries < maxRetriesPerSource) {\n                    currentSourceRetries++;\n                    showStatus(`当前源重试中(${currentSourceRetries}/${maxRetriesPerSource})...`, true);\n                    setTimeout(() => loadRandomVideo(), 1000);\n                }\n            });\n            \n            // 初始化\n            initPlayer();\n        });\n    </script>\n","content_text":"连续播放: 开 换一个 ▶ 切换源\n\n\n\n视频源管理\n\n\n添加源","date_published":"2025-12-07T17:26:24.196Z","_microfeed":{"web_url":"https://cms.dbdraws.dpdns.org/i/随机小姐姐-最新源-Ak02D0CbhPX/","json_url":"https://cms.dbdraws.dpdns.org/i/Ak02D0CbhPX/json/","rss_url":"https://cms.dbdraws.dpdns.org/i/Ak02D0CbhPX/rss/","guid":"Ak02D0CbhPX","status":"published","itunes:episodeType":"full","date_published_short":"Sun Dec 07 2025","date_published_ms":1765128384196}}],"_microfeed":{"microfeed_version":"0.1.5","base_url":"https://cms.dbdraws.dpdns.org","categories":[],"subscribe_methods":[{"name":"JSON","type":"json","url":"https://cms.dbdraws.dpdns.org/json/","image":"https://cms.dbdraws.dpdns.org/assets/brands/subscribe/json.png","enabled":true,"editable":false,"id":"p0wHIR3D42R"},{"name":"友情链接","type":"google podcasts","url":"https://blog.dbdraws.dpdns.org/friends","image":"https://cms.dbdraws.dpdns.org/assets/brands/subscribe/google.png","enabled":true,"editable":true,"id":"BRWdIXxcFlR"}],"description_text":"这是一款轻量级的内容管理系统（CMS），可自行托管于Cloudflare平台。通过microfeed，您能够便捷地发布多种形式的内容——包括音频、视频、照片、文档、博客文章及外部链接，并以网页、RSS订阅和JSON格式输出信息流。","copyright":"Copyright © DBD制作组.2026","itunes:type":"episodic","items_sort_order":"newest_first"}}