[
  {
    "path": ".github/workflows/auto_release.yml",
    "content": "# This is a basic workflow to help you get started with Actions\n\nname: Check JMComic Android APK\n\n# Controls when the workflow will run\non:\n  push:\n  workflow_dispatch:\n  schedule:\n    - cron: '0 */2 * * *'\n\npermissions:\n  contents: write\n\n# A workflow run is made up of one or more jobs that can run sequentially or in parallel\njobs:\n  check:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      - name: Set up Python 3.11\n        uses: actions/setup-python@v4\n        with:\n          python-version: \"3.11\"\n\n      - name: Install Dependency\n        run: |\n          python -m pip install --upgrade pip\n          pip install jmcomic\n\n      - name: Run Script\n        id: script\n        run: |\n          python main.py\n\n      - name: Release\n        if: ${{ steps.script.outputs.found_new == 'true'}}\n        uses: softprops/action-gh-release@v1\n        with:\n          name: v${{ steps.script.outputs.new_ver }}\n          tag_name: ${{ steps.script.outputs.new_ver }}\n          draft: false\n          files: |\n            ${{ steps.script.outputs.new_ver }}.apk\n          body: |\n            禁漫APP v${{ steps.script.outputs.new_ver }}\n            你可以直接下载Assets的`${{ steps.script.outputs.new_ver }}.apk`使用，或者从禁漫官网下载:\n            \n            禁漫官网的`${{ steps.script.outputs.new_ver }}.apk`下载链接：\n            1. [${{ steps.script.outputs.download_path1 }}](${{ steps.script.outputs.download_path1 }})\n            2. [${{ steps.script.outputs.download_path2 }}](${{ steps.script.outputs.download_path2 }})\n            3. [https://18comic.vip/stray](https://18comic.vip/stray/)（发布页）\n            \n            `${{ steps.script.outputs.new_ver }}.apk`的更新信息：\n            \n            > ${{ steps.script.outputs.desc }}\n\n      - name: Commit\n        if: ${{ steps.script.outputs.found_new == 'true'}}\n        run: |\n          # Extract the version number from the previous step\n          version=${{ steps.script.outputs.new_ver }}\n          git config --global user.email \"93357912+hect0x7@users.noreply.github.com\"\n          git config --global user.name \"hect0x7\"\n          git tag -a \"v$version\" -m \"Version $version\"\n          git add ./APK_VERSION.txt\n          git commit -m \"update APK_VERSION.txt\"\n          git push\n          echo \"finished\"\n"
  },
  {
    "path": "APK_VERSION.txt",
    "content": "2.0.18"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\">\n<h1 style=\"margin-top: 0\">JMComic-APK</h1>\n<p>\n<strong>基于jmcomic库自动检查禁漫APK更新</strong>\n</p>\n  \n[![GitHub](https://img.shields.io/badge/-GitHub-181717?logo=github)](https://github.com/hect0x7)\n[![GitHub all download](https://img.shields.io/github/downloads/hect0x7/JMComic-APK/total?color=orange&label=github%20downloads)](https://github.com/hect0x7/JMComic-APK/releases/latest)\n[![GitHub latest releases](https://img.shields.io/github/v/release/hect0x7/JMComic-APK?color=blue&label=release)](https://github.com/hect0x7/JMComic-APK/releases/latest)\n\n</div>\n\n![一图流](images/introduction.jpg)\n\n## 项目介绍\n\n使用GitHub Actions定时检查禁漫APK是否有更新，如果有，就下载一份保存到Release中。\n\n[✨✨✨点我去APK下载界面✨✨✨](https://github.com/hect0x7/JMComic-APK/releases/latest)\n\n\n## Star历史图\n\n<a href=\"https://github.com/hect0x7/JMComic-Crawler-Python\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/svg?repos=hect0x7/JMComic-Crawler-Python%2Chect0x7/JMComic-APK&type=Date&theme=dark\" />\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/svg?repos=hect0x7/JMComic-Crawler-Python%2Chect0x7/JMComic-APK&type=Date\" />\n    <img alt=\"Star History Chart\" src=\"https://api.star-history.com/svg?repos=hect0x7/JMComic-Crawler-Python%2Chect0x7/JMComic-APK&type=Date\" />\n  </picture>\n</a>\n\n\n## 相关项目推荐\n\n本项目的代码基于[`jmcomic`](https://github.com/hect0x7/JMComic-Crawler-Python)库，这是我写的一个pip库，支持用python代码访问禁漫天堂。\n\n> 引流：[jmcomic](https://github.com/hect0x7/JMComic-Crawler-Python) 还可以帮你一键批量下载禁漫本子\n\n<a href=\"https://github.com/hect0x7/JMComic-Crawler-Python\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/hect0x7/hect0x7/refs/heads/master/profile/pin-JMComic-Crawler-Python-dark.svg?t=1\" />\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/hect0x7/hect0x7/refs/heads/master/profile/pin-JMComic-Crawler-Python.svg?t=1\" />\n    <img alt=\"Repo Card\" src=\"https://raw.githubusercontent.com/hect0x7/hect0x7/refs/heads/master/profile/pin-JMComic-Crawler-Python-dark.svg?t=1\" />\n  </picture>\n</a>\n\n---\n\n此外，如果你需要**离线浏览已下载的本子**，可以使用 [`plugin-jm-server`](https://github.com/hect0x7/plugin-jm-server)。\n\n> [**plugin-jm-server**](https://github.com/hect0x7/plugin-jm-server) 是一个“离线版”禁漫天堂文件服务器，支持在浏览器中查看本地文件夹内的图片。该项目界面模仿禁漫章节的下拉式观看页面，并适配了手机端。\n\n<a href=\"https://github.com/hect0x7/plugin-jm-server\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/hect0x7/hect0x7/refs/heads/master/profile/pin-plugin-jm-server-dark.svg?t=1\" />\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/hect0x7/hect0x7/refs/heads/master/profile/pin-plugin-jm-server.svg?t=1\" />\n    <img alt=\"Repo Card\" src=\"https://raw.githubusercontent.com/hect0x7/hect0x7/refs/heads/master/profile/pin-plugin-jm-server-dark.svg?t=1\" />\n  </picture>\n</a>\n\n---\n\n\n如果你希望**通过自然语言与 AI 交互来找本、看本**，那么 [`jmcomic-ai`](https://github.com/hect0x7/jmcomic-ai) 是你的不二之选。\n\n> [jmcomic-ai](https://github.com/hect0x7/jmcomic-ai) 通过 MCP 和 Skills 将 `jmcomic` 的搜索、下载、排行榜等核心能力注入到你的 AI Agent（如 Cursor, Claude Desktop 等）中。现在你只需对 AI 说出“帮我找找主角是电锯人的漫画”或“下载搜索结果中浏览量前三的作品”，AI 就会自动为你执行复杂的爬虫任务。\n\n<a href=\"https://github.com/hect0x7/jmcomic-ai\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/hect0x7/hect0x7/refs/heads/master/profile/pin-jmcomic-ai-dark.svg?t=1\" />\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/hect0x7/hect0x7/refs/heads/master/profile/pin-jmcomic-ai.svg?t=1\" />\n    <img alt=\"Repo Card\" src=\"https://raw.githubusercontent.com/hect0x7/hect0x7/refs/heads/master/profile/pin-jmcomic-ai-dark.svg?t=1\" />\n  </picture>\n</a>\n"
  },
  {
    "path": "main.py",
    "content": "import json\nimport os\nimport re\n\nfrom jmcomic import create_option, JmHtmlClient, JmApiClient, \\\n    PatternTool, file_exists, write_text, read_text, \\\n    save_resp_content, JmModuleConfig, JmcomicText, jm_log\n\napk_version_txt = './APK_VERSION.txt'\nis_dev: bool = file_exists('.idea')\ncur_ver: str = read_text(apk_version_txt).strip()\nJmModuleConfig.FLAG_API_CLIENT_REQUIRE_COOKIES = False\nop = create_option('op.yml')\nhtml_cl: JmHtmlClient = op.new_jm_client(impl='html')\napi_cl: JmApiClient = op.new_jm_client(impl='api')\n\n\ndef compare_versions(v1: str, v2: str) -> int:\n    parts1 = list(map(int, v1.split(\".\")))\n    parts2 = list(map(int, v2.split(\".\")))\n\n    # 补齐长度\n    length = max(len(parts1), len(parts2))\n    parts1 += [0] * (length - len(parts1))\n    parts2 += [0] * (length - len(parts2))\n\n    if parts1 > parts2:\n        return 1  # v1 大\n    elif parts1 < parts2:\n        return -1  # v2 大\n    else:\n        return 0  # 相等\n\ndef add_output(k, v):\n    cmd = f'echo \"{k}={v}\" >> $GITHUB_OUTPUT'\n    if is_dev:\n        print(cmd)\n        return\n\n    print(f'{cmd}: {os.system(cmd)}')\n\n\ndef download_new_ver(new_ver, download_path):\n    resp = html_cl.get(download_path)\n    save_resp_content(resp, f'./{new_ver}.apk')\n    write_text(apk_version_txt, new_ver)\n\n\ndef check_apk():\n    # new_ver, download_path = fetch_apk_ver_and_download_path()\n    new_ver, download_path, desc = fetch_apk_info_via_api()\n    add_output('new_ver', new_ver)\n\n    if compare_versions(new_ver, cur_ver) < 1:\n        add_output('found_new', 'false')\n        return\n\n    add_output('found_new', 'true')\n    add_output('download_path1', f'{JmModuleConfig.PROT}18comic.vip{download_path}')\n    add_output('download_path2', f'{JmModuleConfig.PROT}jmcomic.me{download_path}')\n    add_output('desc', desc.replace('\\r\\n', '\\n').replace('\\n', '<p>'))\n    download_new_ver(new_ver, download_path)\n\n\ndef fetch_apk_info_via_html():\n    resp = html_cl.get_jm_html('/stray/?utm_source=18comic')\n    apk_version_pattern = re.compile(r'a href=\"(/static/apk/(.*?).apk)\"')\n    match = PatternTool.require_match(resp.text, apk_version_pattern, '未匹配上apk下载路径', None)\n    download_path, new_ver = match[1], match[2]\n    return new_ver, download_path\n\n\ndef get_download_path(url):\n    try:\n        domain = JmcomicText.parse_to_jm_domain(url)\n        return url.replace(JmModuleConfig.PROT, '').replace(domain, '')\n    except Exception as e:\n        jm_log('get_download_path', f'{e}: [{url}]')\n        return url.replace(JmModuleConfig.PROT, '')\n\n\ndef fetch_apk_info_via_api():\n    resp = api_cl.setting()\n    jm_log('apk.setting', json.dumps(resp.res_data, indent=2, ensure_ascii=False))\n    data = resp.model_data\n\n    version = data.jm3_version\n    return version, get_download_path(data.jm3_download_url), data.jm3_version_info\n\n\nif __name__ == '__main__':\n    check_apk()\n"
  },
  {
    "path": "op.yml",
    "content": "client:\n  domain:\n    html: [ jmcomic1.me, jmcomic.me ]\n\n"
  },
  {
    "path": "requirements.txt",
    "content": "jmcomic\n"
  }
]