📖 Lofter

Lofter

分享者: guaner001125 (317)发布时间: 6天前

【使用lyc改版阅读sigma效果更佳】



更新日志

1、点击正文👤作者支持查看合集列表

2、适配一些正文里的跳转链接
二维码导入
{
    "articleStyle": 3,
    "cacheFirst": false,
    "customOrder": 25,
    "enableJs": true,
    "enabled": true,
    "enabledCookieJar": true,
    "header": "@js:JSON.stringify({\n\t\"User-Agent\": java.getWebViewUA(),\n\"Content-Type\": \"application\/x-www-form-urlencoded;charset=utf-8\"\n})",
    "jsLib": "function isL(){\n\tconst {source} = this;\n\ttry{\n\t\tsource.refreshJSLib();\n\t\treturn true\n\t\t}catch(e){\n\t\t\treturn false\n\t\t\t}\n\t}\n\nfunction getHtmlto(name,info,cover,type,url,id){\n    let yurl = url;\n    if(type==\"👤\")url=`http:\/\/api.lofter.com\/v2.0\/blogHomePage.api?product=lofter-android-8.3.20,{\"method\": \"POST\",\"body\":\"targetblogid=${id}&method=getBlogInfoDetail&returnData=1&checkpwd=1&needgetpoststat=1\"}`;\nlet addUrl =  `legado:\/\/import\/addToBookshelf?src=${encodeURIComponent(url)},{\"origin\":\"📖Lofter\"}`;\nlet c = `<button class=\"copy-btn\" onclick=\"toOpen()\">\n                <span class=\"copy-icon\">🔍<\/span>\n                <span class=\"copy-text\">查看<\/span>\n            <\/button>`;\t\nlet result = `\n    <title>${name}<\/title>\n    <meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\">\n    <p><a href=\"legado:\/\/import\/bookSource?src=${encodeURI(\"http:\/\/www.yckceo.com\/yuedu\/shuyuan\/json\/id\/6873.json\")}\">导入lofter书源<\/a><\/p>\n    <div class=\"user-profile-card\">\n    <div class=\"user-header\">\n            <img src=\"${cover}\" class=\"user-avatar\">\n            <div class=\"user-meta\">\n                <h2 class=\"username\">${name}<\/h2>\n                <p class=\"user-bio\">${info}<\/p>\n            <\/div>\n        <\/div>\n        \n        <div class=\"copy-section\">\n            <div class=\"copy-content\" id=\"copyContent\">\n${type}${name}::${yurl}\n            <\/div>\n            <button class=\"copy-btn\" onclick=\"handleCopy()\">\n                <span class=\"copy-icon\">⎘<\/span>\n                <span class=\"copy-text\">一键复制后粘贴到分类URL<\/span>\n            <\/button>\n            <button class=\"copy-btn\" onclick=\"toAdd()\">\n                <span class=\"copy-icon\">📚<\/span>\n                <span class=\"copy-text\">加入书架<\/span>\n            <\/button>\n            ${this.isL()?c:\"\"}\n            <div class=\"copy-feedback\" id=\"copyFeedback\"><\/div>\n        <\/div>\n        \n         \n    <\/div>\n\n    <style>\n        .user-profile-card{\n            max-width: 600px;\n            margin: 0 auto;\n            padding: 25px;\n            background: white;\n            border-radius: 12px;\n            box-shadow: 0 5px 15px rgba(0,0,0,0.08);\n            font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif;\n        }\n      \n        .user-header {\n            display: flex;\n            align-items: flex-start;\n            margin-bottom: 20px;\n        padding: 15px;\n        background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);\n        border-radius: 10px;\n        box-shadow: 0 2px 10px rgba(0,0,0,0.1);\n        }\n        \n        .user-avatar {\n            width: 70px;\n            height: 70px;\n            border-radius: 50%;\n            object-fit: cover;\n            border: 3px solid white;\n            box-shadow: 0 3px 10px rgba(0,0,0,0.1);\n        }\n        \n        .user-meta {\n            margin-left: 18px;\n            flex: 1;\n        }\n        \n        .username {\n            margin: 0 0 5px;\n            color: #333;\n            font-size: 20px;\n            font-weight: 600;\n        }\n        \n        .user-bio {\n            margin: 0;\n            color: #666;\n            font-size: 15px;\n            line-height: 1.5;\n        }\n        \n        .copy-section {\n            margin-top: 25px;\n        }\n        \n        .copy-content {\n            padding: 15px;\n            background: #f8f9fa;\n            border-radius: 8px;\n            border: 1px solid #eaeaea;\n            font-family: 'Courier New', monospace;\n            font-size: 14px;\n            line-height: 1.5;\n            word-break: break-all;\n            white-space: pre-wrap;\n            margin-bottom: 15px;\n            max-height: 200px;\n            overflow-y: auto;\n        }\n        \n        .copy-btn {\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            padding: 12px 24px;\n            margin:10px 0px;\n            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);\n            border: none;\n            border-radius: 8px;\n            font-size: 15px;\n            font-weight: 500;\n            cursor: pointer;\n            transition: all 0.3s;\n            width: 100%;\n            box-shadow: 0 2px 5px rgba(0,0,0,0.1);\n        }\n        \n        .copy-btn:hover {\n            transform: translateY(-2px);\n            box-shadow: 0 5px 10px rgba(0,0,0,0.15);\n        }\n        \n        .copy-icon {\n            font-size: 18px;\n            margin-right: 8px;\n        }\n        \n        .copy-feedback {\n            height: 20px;\n            margin-top: 12px;\n            text-align: center;\n            font-size: 14px;\n            transition: all 0.3s;\n        }\n        \n        @media (max-width: 600px) {\n            .user-profile-card {\n                padding: 18px;\n                border-radius: 0;\n            }\n            \n            .user-header {\n                flex-direction: column;\n                align-items: center;\n                text-align: center;\n            }\n            \n            .user-meta {\n                margin-left: 0;\n                margin-top: 15px;\n            }\n            \n            .copy-content {\n                font-size: 13px;\n                padding: 12px;\n            }\n            \n            .copy-btn {\n                padding: 10px 15px;\n                font-size: 14px;\n            }\n        }\n    <\/style>\n\n    <script>\n         function toAdd(){\n             window.location.href = '${addUrl}';\n         }\n         function toOpen(){\n             java.open(\"sort\", '${yurl}',\"${type}${name} ${info.match(\/^\\d+篇\/)?.[0]??''}\");\n         }\n         \n        function handleCopy() {\n            const content = document.getElementById('copyContent');\n            const feedback = document.getElementById('copyFeedback');\n            \n            \/\/ 创建范围并选择文本\n            const range = document.createRange();\n            range.selectNode(content);\n            window.getSelection().removeAllRanges();\n            window.getSelection().addRange(range);\n            \n            try {\n                \/\/ 执行复制命令\n                const successful = document.execCommand('copy');\n                if(successful) {\n                    feedback.textContent = '复制成功!';\n                    feedback.style.color = '#4CAF50';\n                } else {\n                    feedback.textContent = '复制失败,请手动选择文本';\n                    feedback.style.color = '#F44336';\n                }\n            } catch(err) {\n                feedback.textContent = '复制错误: ' + err;\n                feedback.style.color = '#F44336';\n            }\n            \n            \/\/ 清除选择\n            window.getSelection().removeAllRanges();\n            \n            \/\/ 3秒后隐藏反馈\n            setTimeout(() => {\n                feedback.textContent = '';\n            }, 3000);\n        }\n    <\/script>\n    `;\n\t\nreturn result\t\n\t\n\t\n\t}\n",
    "lastUpdateTime": 1771102776678,
    "loadWithBaseUrl": true,
    "loginUrl": "https:\/\/www.lofter.com\/front\/login",
    "preload": false,
    "preloadJs": "window.java = java;",
    "ruleArticles": "<js>result.replace(\/:null\/g,':\"\"').replace(\/null\/,'');<\/js>\n$.response.items[*]||$.response.posts[*]||$.data.posts[*]||$.data.blogs[*]||$.data.collections[*]||$.data.grainList[*]||$.response.collections[*]\n<js>\na=result;\nbaseUrl.match(\/newsearch\/)?result=\"[{post:{title:'右上角三点,设置源变量确认搜索'}}]\":result=result;\nsource.getVariable()!=''?result=a:result=result\n<\/js>\n$.[*]",
    "ruleContent": "<js>\nif(\/window.__initialize_data__\/.test(result)){\n\tresult = result.match(\/window.__initialize_data__ =([\\s\\S]+?)<\\\/script>\/)[1];\n\tjava.setContent(result);\n\t}\ncontent = String(java.getString(\"$..content||$..caption\"));\nimgs = eval(String(java.getString(\"$..photoLinks\")));\nlet tags = String(java.getString(\"$..tag\"));\nlet blogdomain = String(java.getString(\"$..blogInfo.blogName\"));\n\nlet author = String(java.getString(\"$..blogInfo.blogNickName\"));\nauthoru = `http:\/\/api.lofter.com\/v2.0\/blogHomePage.api?product=lofter-android-7.4.4,{\"method\": \"POST\",\"body\":\"targetblogid=${java.getString(\"$..blogInfo.blogId\")}&method=getBlogInfoDetail&returnData=1&limit=2000&offset=0&&checkpwd=1&needgetpoststat=1\"}`;\nauthorurl= `legado:\/\/import\/addToBookshelf?src=${encodeURIComponent(authoru)},{\"origin\":\"📖Lofter\"}`\n\nlet  postCollection =String(java.getString(\"$..postCollection.name\")); \nlet postNum = postCollection?\"(\"+String(java.getString(\"$..postCollection.postCount\"))+\"篇)\":\"\";\npostCollectionu = `https:\/\/api.lofter.com\/v1.1\/postCollection.api?product=lofter-android-7.4.4,{\"method\": \"POST\",\"body\":\"blogdomain=${java.getString(\"$..blogInfo.blogName\")}.lofter.com&method=getCollectionSimple&offset=0&limit=2000&blogid=${java.getString(\"$..postCollection.blogId\")}&collectionid=${java.getString(\"$..postCollection.id\")}&order=1\"}`;\n\npostCollectionurl= `legado:\/\/import\/addToBookshelf?src=${encodeURIComponent(postCollectionu)},{\"origin\":\"📖Lofter\"}`\n\npostCollection = postCollection?`<p style=\"text-align:center\"><a class=\"toBook\" onclick='toOpen(\"📖\",\"${postCollection}\",\\`${postCollectionu}\\`,1)'>📖合集:<\/a><a href='${postCollectionurl}'>${postCollection}<\/a><\/p>`:\"\";\n\nauthor = `<p style=\"text-align:center\"><a class=\"toAuthor\" onclick='toOpen(\"👤\",\"${author}\",\\`${authoru}\\`,1)'>👤作者:<\/a><a href='${authorurl}'>${author}<\/a><\/p>${postCollection}`;\n\ntags = tags?tags.split(\",\").map(x=>{\n    let url = `https:\/\/api.lofter.com\/oldapi\/tagPosts.api?product=lofter-android-7.4.4&method=newTagSearch&offset={\\{(page-1) *18}}&limit=18&firstpermalink=null&tag=${x}&type=new,{\"method\": \"POST\",\"body\":\"null\"}`;\n\treturn `<label class=\"tag\" onclick='toOpen(\"🏷\",\"${x}\",\\`${url}\\`)'>${x}<\/label>`\n\t}).join(\"\"):null;\ntags = tags?`<div>${tags}<\/div>`:\"\";\nlet embed,img_height,img_width,video_first_img\ntry{\nembed = java.getString(\"$.response.posts[0].post.embed\")??\"{x:1}\";\nimg_height = java.getString(\"$.img_height\", embed);\nimg_width = java.getString(\"$.img_width\", embed);\nvideo_first_img = java.getString(\"$.video_first_img\", embed);\n}catch(e){\n\t\/\/java.log(e)\n\t}\n\/\/ 获取视频URL\nlet videoUrl = \/video_down_url\\\\\":\\\\\"(.*?)\\\\\"\/.test(result) ? String(result).match(\/video_down_url\\\\\":\\\\\"(.*?)\\\\\"\/)[1] : \"\";\n\nvideo = videoUrl ? `<div style=\"display: flex; flex-direction: column; align-items: center; margin: 5px 0;\"> \n  \n  <div style=\"width: 100%; max-width: 100%; border: 2px solid #e0e0e0; border-radius: 8px; box-shadow: 0 8px 25px rgba(0,0,0,0.15); background: #000; overflow: hidden;\">\n    <video controls poster=\"${video_first_img}\" style=\"width: 100%; display: block;\">\n      <source src=\"${videoUrl}\" type=\"video\/mp4\">\n    <\/video>\n  <\/div>\n<\/div>\n` : \"\";\n\nvideoUrl = videoUrl?`<div style=\"width: 100%; max-width: 90%; word-break: break-all; background: #f8f9fa; border: 1px solid #e9ecef; border-radius: 8px; padding: 12px 15px; font-family: 'Consolas', 'Monaco', monospace; font-size: 14px; color: #495057;\">\n    视频链接:${videoUrl}\n  <\/div>`:\"\";\n\nimg = \"\";\nif(imgs) {\n    imgs.forEach(x => {\n        if(x) {\n            img += `<div class=\"image-container\">\n                <img src=\"${x.orign.replace(\/%7C.*\/g, '')}\" loading=\"lazy\">\n            <\/div>\\n`;\n        }\n    });\n}\n\ncontent = content.replace(\/<p[^>]*>\\s* * *<\\\/p>\/g, '')\n.replace(\/\\s{2,}\/g,'')\n.replace(\/title=\"\"[^>]+|style=\"[^\"]+\"\/g,'\/')\n.replace(\/(<img([^>]+)>)\/g,'<div class=\"image-container\">$1<\/div>')\n.replace(\/<a href=\"(.*?\\.lofter.com\\\/post\\\/.*?)\".*?>([^<]+)<\\\/a>\/g,'<a onclick=\\'openContent(\"$1\")\\' href=\\'javascript:;\\'>$2<\/a>')\n.replace(\/<a loftermentionblogid=\"(\\d+)\" href=\"[^\"]+\".*?>@([^<]+)<\\\/a>\/g,`<a onclick='toOpen(\"👤\",\"$2\",\\`http:\/\/api.lofter.com\/v2.0\/blogHomePage.api?product=lofter-android-7.4.4,{\"method\": \"POST\",\"body\":\"targetblogid=$1&method=getBlogInfoDetail&returnData=1&checkpwd=1&needgetpoststat=1\"}\\`,1)' href='javascript:;'>@$2<\/a>`);\n\ncontent = content.replace(\/<p[^>]*>\/g, '<p>'); \/\/ 移除p标签中的所有属性\n\nlet openUrlButton = `<button onclick=\"openUrl(1)\" \n                            style=\"\n                                background: #6c757d;\n                                color: white;\n                                border: none;\n                                padding: 8px 16px;\n                                border-radius: 4px;\n                                font-size: 14px;\n                                cursor: pointer;\n                                flex: 1;\n                                min-width: 120px;\n                                transition: background 0.2s ease;\n                            \"\n                            onmouseover=\"this.style.background='#5a6268';\"\n                            onmouseout=\"this.style.background='#6c757d';\">\n                        打开\n                    <\/button>`;\nlet addButton= `<button onclick=\"openUrl(0)\" \n                            style=\"\n                                background: #6c757d;\n                                color: white;\n                                border: none;\n                                padding: 8px 16px;\n                                border-radius: 4px;\n                                font-size: 14px;\n                                cursor: pointer;\n                                flex: 1;\n                                min-width: 120px;\n                                transition: background 0.2s ease;\n                            \"\n                            onmouseover=\"this.style.background='#5a6268';\"\n                            onmouseout=\"this.style.background='#6c757d';\">\n                        加入书架\n                    <\/button>`;\nlet postButton = ` <button id=\"postButton\" onclick=\"openPost()\" \n                            style=\"\n                                background: #2c3e50;\n                                color: white;\n                                border: none;\n                                padding: 8px 16px;\n                                border-radius: 4px;\n                                font-size: 14px;\n                                cursor: pointer;\n                                flex: 1;\n                                min-width: 120px;\n                                transition: background 0.2s ease;\n                            \"\n                            onmouseover=\"this.style.background='#34495e';\"\n                            onmouseout=\"this.style.background='#2c3e50';\">\n                        合集列表\n                    <\/button>`\n\nresult = `\n<title>${String(java.getString(\"$..title||$..content\")).replace(\/<\\\/?([a-z]+)[^>]*>|\\s\/g,'')}<\/title>\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\">\n${String(java.getString(\"$..title\"))?'<h3 class=\"title-card\">'+java.getString(\"$..title\")+'<\/h3>'+author+'<hr>':author+\"<hr>\"}\n\n<div id=\"modalOverlay\" style=\"position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; z-index: 1001; opacity: 0; visibility: hidden; transition: all 0.3s ease; padding: 0;\">\n    <div id=\"modalContainer\" style=\"background-color: white;margin:0; padding:0;border-radius: 16px; width: 90%; max-width: 400px; max-height: 85vh; overflow: hidden; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15); transform: translateY(30px); transition: transform 0.3s ease;\">\n        <div style=\"padding: 4px 14px; border-bottom: 1px solid #f0f0f0; display: flex; justify-content: space-between; align-items: center; background-color: white;\">\n            <div style=\"font-size: 1rem; font-weight: 700; color: #1a1a1a;\">合集列表<span id=\"postnum\"><\/span><\/div>\n            <button id=\"closeModalBtn\" style=\"background: none; border: none; font-size: 1.8rem; color: #999; cursor: pointer; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: all 0.2s;\" onmouseover=\"this.style.backgroundColor='#f5f5f5'; this.style.color='#666';\" onmouseout=\"this.style.backgroundColor='transparent'; this.style.color='#999';\">×<\/button>\n        <\/div>\n        <div style=\"padding: 0; overflow-y: auto; max-height: calc(85vh - 80px);\">\n            <div id=\"collectionList\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n\n\n<div class=\"post-container\">\n    <div class=\"post-content\">\n        ${content}\n    <\/div>\n    ${img}\n    ${video}\n    ${tags}\n<\/div>\n${videoUrl}\n    <div id=\"apiPopupOverlay\" \n         style=\"\n            display: none;\n            position: fixed;\n            top: 0;\n            left: 0;\n            width: 100%;\n            height: 100%;\n            background: rgba(0, 0, 0, 0.6);\n            z-index: 1000;\n            justify-content: center;\n            align-items: center;\n         \" \n         onclick=\"closeApiPopup()\">\n        \n        <div id=\"apiPopup\" \n             style=\"\n                background: white;\n                border-radius: 8px;\n                padding: 0;\n                width: 90%;\n                max-width: 700px;\n                max-height: 80vh;\n                box-shadow: 0 5px 20px rgba(0, 0, 0, 0.2);\n                position: relative;\n                display: flex;\n                flex-direction: column;\n             \" \n             onclick=\"event.stopPropagation();\">\n            \n            <div style=\"\n                background: #f8f9fa;\n                padding: 20px;\n                border-bottom: 1px solid #e9ecef;\n                border-radius: 8px 8px 0 0;\n                display: flex;\n                justify-content: space-between;\n                align-items: center;\n            \">\n                <h3 style=\"margin: 0; font-size: 16px; font-weight: 600; color: #333;\">\n                    API接口信息\n                <\/h3>\n                <button onclick=\"closeApiPopup()\" \n                        style=\"\n                            background: none;\n                            border: none;\n                            color: #666;\n                            font-size: 24px;\n                            cursor: pointer;\n                            padding: 0;\n                            line-height: 1;\n                            width: 30px;\n                            height: 30px;\n                            display: flex;\n                            align-items: center;\n                            justify-content: center;\n                            border-radius: 4px;\n                        \"\n                        onmouseover=\"this.style.background='#e9ecef';\"\n                        onmouseout=\"this.style.background='transparent';\">\n                    &times;\n                <\/button>\n            <\/div>\n            \n            <div style=\"padding: 20px; flex: 1; overflow: auto;\">\n                <textarea id=\"apiTextArea\" \n                          readonly\n                          style=\"\n                            width: 100%;\n                            height: 150px;\n                            padding: 12px;\n                            border: 1px solid #ddd;\n                            border-radius: 4px;\n                            font-family: 'Consolas', 'Monaco', 'Courier New', monospace;\n                            font-size: 13px;\n                            line-height: 1.5;\n                            color: #333;\n                            background: #fafafa;\n                            resize: none;\n                            outline: none;\n                            box-sizing: border-box;\n                          \"\n                          onfocus=\"this.select();\"><\/textarea>\n                \n                \n                <div style=\"display: flex; gap: 10px; margin-top: 20px; flex-wrap: wrap;\">\n                    <button onclick=\"selectAndCopy()\" \n                            style=\"\n                                background: #2c3e50;\n                                color: white;\n                                border: none;\n                                padding: 8px 16px;\n                                border-radius: 4px;\n                                font-size: 14px;\n                                cursor: pointer;\n                                flex: 1;\n                                min-width: 120px;\n                                transition: background 0.2s ease;\n                            \"\n                            onmouseover=\"this.style.background='#34495e';\"\n                            onmouseout=\"this.style.background='#2c3e50';\">\n                        复制\n                    <\/button>\n                    \n              ${isL()?openUrlButton:\"\"}\n              ${postButton}\n              ${addButton}\n                <\/div>\n                \n                <!-- 提示信息 -->\n                <div id=\"copySuccess\" \n                     style=\"\n                        display: none;\n                        background: #d4edda;\n                        border: 1px solid #c3e6cb;\n                        color: #155724;\n                        padding: 10px 15px;\n                        border-radius: 4px;\n                        margin-top: 15px;\n                        text-align: center;\n                        font-size: 13px;\n                     \">\n                    文本已复制到剪贴板\n                <\/div>\n                \n                <!-- 使用说明 -->\n                <div style=\"\n                    margin-top: 20px;\n                    padding: 12px;\n                    background: #f8f9fa;\n                    border-left: 4px solid #6c757d;\n                    border-radius: 4px;\n                    font-size: 13px;\n                    color: #495057;\n                \">\n                    <div style=\"font-weight: 600; margin-bottom: 5px;\">使用说明:<\/div>\n                    复制上述文本后,可粘贴到分类URL中使用\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n\n<script>\n\nfunction renderCollections(collectionsData) {\n    collectionsData = collectionsData.response.collections;\n    const collectionList = document.getElementById('collectionList');\n    document.querySelector(\"#postnum\").textContent = \"(\"+collectionsData.length+\"个)\";\n    collectionList.innerHTML = '';\n    collectionsData.forEach(collection => {\n        const collectionItem = document.createElement('div');\n        collectionItem.style.cssText = 'display: flex; padding: 8px 10px; border-bottom: 1px solid #f0f0f0; align-items: center; justify-content: center;';\n       collectionItem.setAttribute('data-id', collection.id);\n       collectionItem.className = \"collectionItem\";\n       collectionItem.innerHTML = \\`\n       <div style=\"width: 88px; height: 88px; flex-shrink: 0; border-radius: 8px; overflow: hidden; margin-right: 16px; display: flex; align-items: center; justify-content: center; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\">\n           <img src=\"$\\{collection.coverUrl}\" style=\"width:100%;height:100%\">\n      <\/div>\n      <div class=\"name\" style=\"flex: 1; display: flex; flex-direction: column; justify-content: space-between; min-height: 88px;font-weight: 500;color:#10a37f;font-size: 0.9rem;\">$\\{collection.name}\n          <div style=\"font-size: 0.8rem; color: #666; line-height: 1.1; margin-bottom: 5px;\">$\\{collection.description}<\/div>\n          <div style=\"display: flex; justify-content: space-between; align-items: center;\">\n              <div style=\"font-size: 0.7rem; color: #999; display: flex; align-items: center;\">\n              $\\{collection.postCount}篇•$\\{collection.viewCount}浏览 <br>🏷$\\{collection.tags}\n              <\/div>\n          <\/div>\n       <\/div>\n\\`;\ncollectionList.appendChild(collectionItem);\n});\n\ndocument.querySelectorAll('.collectionItem').forEach(btn => {\n    btn.addEventListener('click', function() {\n        const id = this.getAttribute('data-id');\n        const textarea = document.getElementById('apiTextArea').value.split(\"::\");\n        let name = this.querySelector(\".name\").textContent;\n        n = name.split(\"\\\\n\")[0];\n        let url = textarea[1];\n        let targetblogid= url.match(\/blogid=(\\\\d+)\/)[1];\n        url =  \"https:\/\/api.lofter.com\/v1.1\/postCollection.api?product=lofter-android-7.4.4,\";\n        let post = {\"method\": \"POST\",\"body\":\"targetblogid=\"+targetblogid+\"&method=getCollectionSimple&offset=0&limit=2000&blogid=\"+targetblogid+\"&collectionid=\"+id+\"&order=1\"}\n        url +=JSON.stringify(post);\n        toOpen(\"📖\",n,url,1,\"(\"+name.match(\/(\\\\d+篇)•\/)[1]+\")\")\n      });\n});\n}\n\n\nfunction showModal() {\n    const modalOverlay = document.getElementById('modalOverlay');\n    const modalContainer = document.getElementById('modalContainer');\n    document.getElementById('apiPopupOverlay').style.zIndex = \"1000\";\n    modalOverlay.style.zIndex = \"9999\";\n    modalOverlay.style.opacity = '1';\n    modalOverlay.style.visibility = 'visible';\n    modalContainer.style.transform = 'translateY(0)';\n    document.body.style.overflow = 'hidden';\n}\n\nfunction hideModal() {\n    const modalOverlay = document.getElementById('modalOverlay');\n    const modalContainer = document.getElementById('modalContainer');\n    modalOverlay.style.opacity = '0';\n    modalOverlay.style.visibility = 'hidden';\n    modalContainer.style.transform = 'translateY(30px)';\n    document.body.style.overflow = 'auto';\n}\n\ndocument.getElementById('closeModalBtn').addEventListener('click', hideModal);\ndocument.getElementById('modalOverlay').addEventListener('click', function(e) {\n    if (e.target === this) {\n        hideModal();\n    }\n});\n\n\/\/ 显示弹窗\nfunction openContent(url){\n     try{\n             java.open(\"rss\", url);\n        }catch(e){\n             window.open(url)\n        }\n}\n\nasync function openPost(){\n    const textarea = document.getElementById('apiTextArea').value.split(\"::\");\n    let url = textarea[1];\n    let targetblogid= url.match(\/blogid=(\\\\d+)\/)[1];\n    let postUrl = \"https:\/\/api.lofter.com\/v1.1\/postCollection.api?product=lofter-android-8.3.20\";\n    const response = await fetch(postUrl, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application\/x-www-form-urlencoded',\n      },\n      body: \"targetblogid=\"+targetblogid+\"&method=getCollectionList&needViewCount=1&blogid=\"+targetblogid\n    });\n    let jsonData = await response.json();\n    showModal();\n    renderCollections(jsonData)\n}\n\n\n\n        function showApiPopup() {\n            document.getElementById('apiPopupOverlay').style.zIndex = \"9999\";\n            document.getElementById('modalOverlay').style.zIndex = \"1000\";\n            document.getElementById('apiPopupOverlay').style.display = 'flex';\n            document.getElementById('copySuccess').style.display = 'none';\n        }\n        \n        \/\/ 关闭弹窗\n        function closeApiPopup() {\n            document.getElementById('apiPopupOverlay').style.display = 'none';\n        }\n        \n        \/\/打开\n        function openUrl(t) {\n            try{\n            const textarea = document.getElementById('apiTextArea').value.split(\"::\");\n            let name = textarea[0].match(\/^..(.*)\/)[1];\n            let type = textarea[0].match(\/^(..)\/)[1];\n            \n            let num = null;\n            if(\/📖\/.test(type)){\n                num = \"(\"+document.querySelector('#apiPopup h3').textContent.match(\/(\\\\d+篇)\/)[1]+\")\";\n            }\n            \n            let url = textarea[1];\n            if(t==1){\n                toOpen(type,name,url,0,num)\n            }else if(t==0){\n                if(\/targetblogid=\/.test(url)){\n                url = \\`http:\/\/api.lofter.com\/v2.0\/blogHomePage.api?product=lofter-android-7.4.4,{\"method\": \"POST\",\"body\":\"targetblogid=$\\{url.match(\/targetblogid=(\\\\d+)\/)[1]}&method=getBlogInfoDetail&returnData=1&limit=2000&offset=0&checkpwd=1&needgetpoststat=1\"}\\`;\n                }\n                url = \\`legado:\/\/import\/addToBookshelf?src=$\\{encodeURIComponent(url)},{\"origin\":\"📖Lofter\"}\\`;\n                window.open(url)\n            }\n            \n            }catch(e){\n            }\n        }\n        \n        \/\/ 复制文本\n        function selectAndCopy() {\n            const textarea = document.getElementById('apiTextArea');\n            textarea.select();\n            textarea.focus();\n            \n            try {\n                const successful = document.execCommand('copy');\n                if (successful) {\n                    showCopySuccess();\n                } else {\n                    fallbackCopy();\n                }\n            } catch (err) {\n                fallbackCopy();\n            }\n        }\n        \n        \/\/ 显示复制成功提示\n        function showCopySuccess() {\n            const successMsg = document.getElementById('copySuccess');\n            successMsg.style.display = 'block';\n            successMsg.textContent = '✅ 文本已复制到剪贴板';\n            \n            setTimeout(() => {\n                successMsg.style.display = 'none';\n            }, 3000);\n        }\n        \n        \/\/ 备用复制方法\n        function fallbackCopy() {\n            const textarea = document.getElementById('apiTextArea');\n            textarea.select();\n            textarea.focus();\n            \n            try {\n                navigator.clipboard.writeText(textarea.value)\n                    .then(() => {\n                        showCopySuccess();\n                    })\n                    .catch(() => {\n                        alert('复制失败,请手动复制文本');\n                    });\n            } catch (err) {\n                alert('请手动选择并复制文本');\n            }\n        }\n        \n        \/\/ 点击弹窗外关闭弹窗\n        document.getElementById('apiPopupOverlay').addEventListener('click', closeApiPopup);\n\n\nfunction toOpen(type,name,url,f,num){\n\tif(\/👤\/.test(type)){\n         let targetblogid = url.match(\/targetblogid=(\\\\d+)\/)[1];\n\t\t url = \\`http:\/\/api.lofter.com\/v2.0\/blogHomePage.api?product=lofter-android-7.4.4,{\"method\":\"POST\",\"body\":\"supportposttypes=1%2C2%2C3%2C4%2C5%2C6&targetblogid=$\\{targetblogid}&offset={\\{(page-1)*18}}&method=getPostLists&postdigestnew=1&returnData=1&limit=18&checkpwd=1&needgetpoststat=1\"}\\`;\n\t\t}\n        \n        url = String(url).replace(\/offset=\\\\d+\/g,'offset={\\{(page-1)*18}}').replace(\/limit=\\\\d+\/g,'limit=18');\n       document.querySelector(\"#apiPopup h3\").textContent= type+name+(\/📖\/.test(type)?(num??\"${postNum}\"):\"\");\n       \n                document.querySelector(\"textarea\").value=type+ name+\"::\"+url;\n               showApiPopup();\n               \n        try{\n          if(f!==1)  java.open(\"sort\", url, type+name+(\/📖\/.test(type)?(num??\"${postNum}\"):\"\"));\n        }catch(e){\n            \n        }\n\t} \n<\/script>\n`;\n\nif(String(java.getString(\"$..blogInfo.blogNickName\"))==\"\"){\n\tresult = String(java.getString(\"$..msg\"))\n\t}\nresult = result.replace(\/(<p><br\\s*\\\/><\\\/p>){1,}\/g,'')\n\n<\/js>\n##tbc\\.##<br>&lrm;<br>",
    "ruleDescription": "@js:\nif(\/newsearch\\\/blog.json\/.test(baseUrl) || String(java.get(\"prefix\"))==\"@\"){\n    let url = `http:\/\/api.lofter.com\/v2.0\/blogHomePage.api?product=lofter-android-7.4.4,{\"method\":\"POST\",\"body\":\"supportposttypes=1%2C2%2C3%2C4%2C5%2C6&blogdomain=${java.getString('$.blogName')}.lofter.com&offset={\\{(page-1)*18}}&method=getPostLists&postdigestnew=1&returnData=1&limit=18&checkpwd=1&needgetpoststat=1\"}`;\n    let info = `${java.getString('$.authName')}<hr>${java.getString('$.selfIntro')}`;\n    result = getHtmlto(java.getString(\"$.blogNickName\"),info,java.getString(\"$.bigAvaImg\"),\"👤\",url,java.getString('$.blogId'));\n} else if(String(java.get(\"prefix\"))==\"%\"){\n    let grainurl = 'https:\/\/api.lofter.com\/api-grain\/grain\/getDetail.json?grainId='+java.getString(\"$.id\")+'&offset=0';\n    let info = `${java.getString('$.postCount')}篇🏷${java.getString('$.tags')}\\n<hr>${java.getString(\"$.description\")}`;\n    result = getHtmlto(java.getString(\"$.name\"),info,java.getString(\"$.coverUrl\"),\"📗\",grainurl)\n}else if((String(java.get(\"prefix\"))==\"#\" ||String(java.get(\"prefix\")) == \"#\")){\n        blogid = '{{$.blogId}}';\n        id = '{{$.id}}';\n        blogName = '{{$.blogName}}';\n         let curl = 'https:\/\/api.lofter.com\/v1.1\/postCollection.api?product=lofter-android-7.4.4,{\"method\": \"POST\",\"body\":\"blogdomain=' + blogName + '.lofter.com&method=getCollectionSimple&offset=0&limit=2000&blogid=' + blogid + '&collectionid=' + id + '&order=1\"}';\n         let info = `${java.getString('$.postCount')}篇🏷${java.getString('$.tags')}`\n         result = getHtmlto(java.getString(\"$.name\"),info,java.getString(\"$.coverUrl\"),\"📖\",curl)\n        curl = `legado:\/\/import\/addToBookshelf?src=${encodeURIComponent(curl)},{\"origin\":\"📖Lofter\"}`;\n}else {\n    result = \"\";\n}\nresult\n",
    "ruleImage": "{{$..firstImageUrl##.*?(https.*?)\"##$1###}}{{$..postView.firstImage.orign||$.postData.blogInfo.bigAvaImg||$..blogInfo.bigAvaImg||$..bigAvaImg||$..coverUrl}}##(http.*?)https?.*##$1\n<js>\nif(\/^http\/.test(result)){\nresult = result+\",\"+JSON.stringify({'headers':{'referer':'http:\/\/www.lofter.com'}});\n}\n<\/js>",
    "ruleLink": "@js:\nif (String(java.get(\"prefix\")) == \"@\" ){\n        id = '{{$.blogId}}';\n        result = 'http:\/\/api.lofter.com\/v2.0\/blogHomePage.api?product=lofter-android-7.4.4,{\"method\": \"POST\",\"body\":\"targetblogid=' + id + '&method=getBlogInfoDetail&returnData=1&checkpwd=1&needgetpoststat=1\"}'\n    } else if (String(java.get(\"prefix\")) == \"%\") {\n        result = `http:\/\/www.lofter.com@js:'data:grain;base64,${java.base64Encode(java.getString(\"$.id\")+\"❌\"+java.getString(\"$.userId\")+\"❌\"+java.getString(\"$.name\"))},{\"type\":\"\"}'`;\n        result  = isL()?result:java.getString(\"$.id\")+\"&\"+java.getString(\"$.userId\");\n    } else if (String(java.get(\"prefix\")) == \"#\" || String(java.get(\"prefix\")) == \"#\") {\n        blogid = '{{$.blogId}}';\n        id = '{{$.id}}';\n        blogName = '{{$.blogName}}';\n        result = `http:\/\/www.lofter.com@js:'data:collections;base64,${java.base64Encode(blogid+\"❌\"+id+\"❌\"+blogName+\"❌\"+java.getString(\"$.name\"))},{\"type\":\"\"}'`;\n       result  = isL()?result:id+\"&\"+blogid;\n    }else{\n        url = '{{$.post.blogId||$.blogId||$..postView.blogId}}';\n        id = '{{$.post.id||$.id||$..postView.id}}';\n        if (url.match(\/_blogid_\\d+\/)) {\n            main = url.match(\/(_blogid_.*?)\\\/\/)[1];\n            body = \"blogdomain=\" + main + \"&postid=\" + id;\n            result = 'https:\/\/api.lofter.com\/oldapi\/post\/detail.api?product=lofter-android-7.4.4,{\"method\":\"POST\",\"body\":\"' + String(body) + '\"}';\n        } else {\n            result = \"https:\/\/api.lofter.com\/oldapi\/post\/detail.api?product=lofter-android-7.4.4\";\n            option = {\n                \"method\": \"POST\",\n                \"body\": \"blogdomain=_blogid_\" + url + \".lofter.com&postid=\" + id\n            }\n           result =  result + \",\" + JSON.stringify(option)\n        }\n    };\nresult",
    "ruleNextPage": "<js>\nif(\/offset={\\{\\(page-1\\)\\s*\\*\\d+}\\}\/.test(baseUrl)){\n\tlet p = baseUrl.match(\/\\*(\\d+)\\}\/)[1];\n\tbaseUrl = baseUrl.replace(\/offset={\\{\\(page-1\\)\\s*\\*\\d+}\\}\/,'offset='+p);\n\t}else if(String(java.getString(\"$.data.offset\"))){\n\t\t  let offset = String(java.getString(\"$.data.offset\"));\n\t\t  if(offset!=-1){\n\t\t  \tbaseUrl = baseUrl.replace(\/offset=\\d+\/,'offset='+offset);\n\t\t  \t}\n\t}else if(\/offset=\\d+\/.test(baseUrl)){\n\t\t offset =Number(baseUrl.match(\/offset=(\\d+)\/)[1]);\n    let limit = Number(baseUrl.match(\/limit=(\\d+)\/)[1]);\n    baseUrl = baseUrl.replace(\/offset=\\d+\/,'offset='+(offset+limit));\n\t\t}\n<\/js>",
    "rulePubDate": "$.post.publishTime||$.publishTime\n@js:a=result?java.timeFormat(parseInt(result)):'';\nresult = a+\" {{$.postCount##^[^\\d]+.*}}篇•\"+String(java.getString(\"$.post.tag||$.tagList||$..tags\")).replace(\/\\n|\"*,\"*|\\[\"\/g,'🏷').replace(\/\"\\]|\\[\\]\/g,'')+java.getString(\"$.authName&&$.selfIntro&&$..$..postView.digest\");\nresult.replace(\/\\s+篇•|•$\/g,' ')",
    "ruleTitle": "{{$..longInfo.title}}•{{$.post.title||$.post.noticeLinkTitle||$..postView.title||$..postView.digest||$.post.digest||$.blogNiceName||$.blogNickName||$.title||$.noticeLinkTitle||$.digest||$.blogInfo.blogNiceName||$.blogNickName||$.post.blogInfo.blogId||$.post.blogPageUrl||$.name}}\n<js>\n\nif(\/api-grain\/.test(baseUrl)){\n\tresult = String(java.getString(\"$..postView.title||$..postView.digest\"));\n\tif(String(java.getString(\"$..viewRankPublic\"))==\"false\"){\n\t\tresult = \"\"\n\t\t}\n\t}\n\na=result.replace(\/^(.{0,15})\/,'$1').replace(\/<.*?>\/g,'').replace(\/^•\/,'');\njava.put('text',a);\na<\/js>",
    "searchUrl": "@js:\nlet prefix = key.charAt(0);\njava.put(\"prefix\",prefix);\nlet offset = '{\\{(page-1) *' + (prefix === '%' ? '10}' : (prefix === '@' ? '10}' : '20}')) + '}';\nlet baseUrl = \"https:\/\/api.lofter.com\/newsearch\/\"\nswitch(prefix) {\n    case '@':\n        result = baseUrl+'blog.json?key=' + key.slice(1)+ '&limit=10&offset=' + offset;\n        break;\n    case '#':\n    case '#':\n        result = baseUrl+'collection.json?key=' + key.slice(1) + '&limit=20&offset=' + offset;\n        break;\n    case '%':\n        result = baseUrl+'grain.json?key='+key.slice(1)+'&limit=10&offset=' + offset;\n        break;\n    default:\n        let header = {\n            \"headers\": {\n                \"Content-Type\": \"application\/x-www-form-urlencoded;charset=utf-8\",\n                \"deviceid\": java.androidId(),\n                \"if-modified-since\": String(new Date()).replace(\/(.*?)\\s(.*?)\\s(.*?)\\s(.*?)GMT.*\/,'$1, $3 $2 $4 GMT')\n            }\n        };\n        result = baseUrl+'post.json?key=' + key + '&sortType=0&offset=' + offset + '&limit=20,' + JSON.stringify(header);\n}",
    "showWebLog": true,
    "singleUrl": false,
    "sortUrl": "🏷双女主::https:\/\/api.lofter.com\/oldapi\/tagPosts.api?product=lofter-android-7.4.4&method=newTagSearch&offset={{(page-1) *22}}&limit=22&firstpermalink=null&tag=双女主&type=new,{\"method\": \"POST\",\"body\":\"null\"}\n🏷橘气::https:\/\/api.lofter.com\/oldapi\/tagPosts.api?product=lofter-android-7.4.4&method=newTagSearch&offset={{(page-1) *18}}&limit=18&firstpermalink=null&tag=橘气&type=new,{\"method\": \"POST\",\"body\":\"null\"}\n🏷手机壁纸::https:\/\/api.lofter.com\/oldapi\/tagPosts.api?product=lofter-android-7.4.4&method=newTagSearch&offset={{(page-1) *22}}&limit=22&firstpermalink=null&tag=手机壁纸&type=new,{\"method\": \"POST\",\"body\":\"null\"}\n🏷百合文::https:\/\/api.lofter.com\/oldapi\/tagPosts.api?product=lofter-android-7.4.4&method=newTagSearch&offset={{(page-1) *18}}&limit=18&firstpermalink=null&tag=百合文&type=new,{\"method\": \"POST\",\"body\":\"null\"}\n🏷短视频::https:\/\/api.lofter.com\/oldapi\/tagPosts.api?product=lofter-android-7.4.4&method=newTagSearch&offset={{(page-1) *22}}&limit=22&firstpermalink=null&tag=短视频&type=new,{\"method\": \"POST\",\"body\":\"null\"}\n\n\n🔍搜索::{{let a=\"\";svg=String(java.base64Encode(`<svg width=\"1190\" height=\"300\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><rect width=\"100%\" height=\"100%\" fill=\"#ffffff\"\/><text x=\"220\" y=\"100\" font-family=\"Arial, sans-serif\" font-size=\"50\" fill=\"#333\" font-weight=\"bold\">输入要搜索的内容,格式如下:<\/text><text x=\"150\" y=\"200\" font-family=\"Arial, sans-serif\" font-size=\"50\" fill=\"#333\" font-weight=\"bold\">文章名  @用户名  #合集名  %粮单名<\/text><text x=\"190\" y=\"290\" font-family=\"Arial, sans-serif\" font-size=\"30\" fill=\"#333\">下拉【🔍搜索】或刷新【🔍搜索】分类弹出输入框<\/text><\/svg>`));if(page==1){try{a=java.getVerificationCode('data:image\/svg+xml;base64,'+svg);}catch(e){java.log(e)};if(a==\"\"){a=source.getVariable()};source.setVariable(a);}else{a=source.getVariable()};key = String(a);let prefix = key.charAt(0);java.put(\"prefix\",prefix);let offset=0;let baseUrl = \"https:\/\/api.lofter.com\/newsearch\/\";switch(prefix) {case '@':result = baseUrl+'blog.json?key=' + key.slice(1)+ '&limit=10&offset=' + offset;break;case '#':case '#':result = baseUrl+'collection.json?key=' + key.slice(1) + '&limit=10&offset=' + offset;break;case '%':result = baseUrl+'grain.json?key='+key.slice(1)+'&limit=10&offset=' + offset;break;default:let header = {\"headers\": {\"Content-Type\": \"application\/x-www-form-urlencoded;charset=utf-8\",\"deviceid\": java.androidId(),\"if-modified-since\": String(new Date()).replace(\/(.*?)\\s(.*?)\\s(.*?)\\s(.*?)GMT.*\/,'$1, $3 $2 $4 GMT')} };result = baseUrl+'post.json?key=' + key + '&sortType=0&offset=' + offset + '&limit=10,' + JSON.stringify(header);};result}}\n\n👤砂上雪::http:\/\/api.lofter.com\/v2.0\/blogHomePage.api?product=lofter-android-7.4.4,{\"method\":\"POST\",\"body\":\"supportposttypes=1%2C2%2C3%2C4%2C5%2C6&blogdomain=taste-s.lofter.com&offset={{(page-1)*18}}&method=getPostLists&postdigestnew=1&returnData=1&limit=18&checkpwd=1&needgetpoststat=1\"}",
    "sourceComment": "下拉【🔍搜索】或刷新【🔍搜索】分类搜索\n\n🏷标签名::https:\/\/api.lofter.com\/oldapi\/tagPosts.api?product=lofter-android-7.4.4&method=newTagSearch&offset={{(page-1) *22}}&limit=22&firstpermalink=null&tag=标签名&type=new,{\"method\": \"POST\",\"body\":\"null\"}",
    "sourceGroup": "阅读",
    "sourceIcon": "https:\/\/is1-ssl.mzstatic.com\/image\/thumb\/Purple221\/v4\/af\/c2\/00\/afc200a4-978b-193a-a749-2151041ef09e\/AppIcon-1x_U007ephone-0-0-0-85-220-0.png\/492x0w.webp",
    "sourceName": "📖\nLofter",
    "sourceUrl": "Lofter",
    "style": ".tag {display: inline-block;  background: #f1f1f1; color: #333333; border-radius: 15px; padding: 2px 10px; margin: 4px; box-shadow: 0 3px 6px rgba(0,0,0,0.1); transition: all 0.2s ease; cursor: pointer; } \n.post-container {\n        max-width: 800px;\n        margin: 0 auto;\n        padding: 20px;      \n        line-height: 1.6;\n        color: #333;\n    }\n    .title-card{    \t\n    border-radius: 8px;\n    text-align: center;\n    margin: 5px auto;\n    margin-bottom:20px;\n    max-width: 80%;\n    \t}\n    .post-content {\n        margin-bottom: 20px;\n    }\n    \n    .post-content p {\n        margin: 0 0 10px 0;\n        text-indent:1.7em;\n        word-break: break-word;\n    }\n    \n    .image-container {\n        margin: 15px 0;\n        text-align: center;\n    }\n    \n    .image-container img {\n        max-width: 100%;\n        height: auto;\n        border-radius: 8px;\n        box-shadow: 0 2px 4px rgba(0,0,0,0.1);\n    }\n    ",
    "type": 0
}
广告