Skip to content

Commit

Permalink
feat: download specificed chapters
Browse files Browse the repository at this point in the history
  • Loading branch information
justorez committed Feb 8, 2024
1 parent d655702 commit e76958f
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 24 deletions.
9 changes: 7 additions & 2 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ PICA_DL_CONCURRENCY=5
# leaderboard | favorites | search
# 下载内容,分别表示:排行榜 | 收藏夹 | 搜索
PICA_DL_CONTENT=
# 搜索关键字,多个用 # 隔开
# 搜索关键字或漫画ID,多个用 # 隔开
# 尽量输入完整漫画名,避免返回过多结果
PICA_DL_SEARCH_KEYWORDS=
PICA_DL_SEARCH_KEYWORDS=
# 指定下载章节
# 使用命令行下载时,无需配置,支持手动选择下载章节
# 这里的章节是指按时间排序,1代表第一章
# 示例:1,3,5-20
PICA_DL_CHAPTER=
12 changes: 8 additions & 4 deletions .github/workflows/task.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: task

on:
on:
workflow_dispatch:
inputs:
PICA_DL_CONTENT:
Expand All @@ -15,6 +15,9 @@ on:
PICA_DL_SEARCH_KEYWORDS:
description: '搜索关键字或者漫画ID (多个用 # 隔开)'
type: string
PICA_DL_CHAPTER:
description: '指定下载章节 (示例:1,3,5-20)'
type: string
OUTPUT_ZIP:
description: '每个章节打成独立压缩包'
type: boolean
Expand All @@ -38,6 +41,7 @@ env:
PICA_DL_CONCURRENCY: ${{ inputs.PICA_DL_CONCURRENCY }}
PICA_DL_CONTENT: ${{ inputs.PICA_DL_CONTENT }}
PICA_DL_SEARCH_KEYWORDS: ${{ inputs.PICA_DL_SEARCH_KEYWORDS }}
PICA_DL_CHAPTER: ${{ inputs.PICA_DL_CHAPTER }}

jobs:
download:
Expand All @@ -56,7 +60,7 @@ jobs:
with:
node-version: 20
cache: 'pnpm'

- name: Install deps and build
run: |
pnpm install
Expand All @@ -75,6 +79,6 @@ jobs:
name: pica-comics
path: ${{ inputs.OUTPUT_ZIP && 'comics-zip/' || 'comics/' }}
retention-days: 7

- name: Upload to file.io
run: node scripts/upload.js
run: node scripts/upload.js
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "pica-cli",
"author": "justorez",
"version": "1.3.1",
"version": "1.4.0",
"description": "😉 哔咔漫画下载器",
"packageManager": "[email protected]",
"type": "module",
Expand Down
8 changes: 7 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# pica-cli

![NPM Version](https://img.shields.io/npm/v/pica-cli) [![publish](https://github.com/justorez/pica-cli/actions/workflows/publish.yml/badge.svg)](https://github.com/justorez/pica-cli/actions/workflows/publish.yml) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)
![NPM Version](https://img.shields.io/npm/v/pica-cli)
[![publish](https://github.com/justorez/pica-cli/actions/workflows/publish.yml/badge.svg)](https://github.com/justorez/pica-cli/actions/workflows/publish.yml)
[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/)

😉 哔咔漫画下载器

Expand All @@ -14,6 +16,7 @@
- 如果没有相关环境变量,则启动交互命令界面;若有则直接执行
- 通过 `pica-zip` 命令分章节批量压缩,配合支持 zip 的漫画阅读软件使用,比如 [Perfect Viewer](https://play.google.com/store/apps/details?id=com.rookiestudio.perfectviewer)。不限于 `pica-cli` 下载的漫画,只要符合 [cmoics/漫画标题/漫画章节/漫画图片](#) 的目录结构即可。
- 借助 github action 实现飞速下载,支持从 github artifact 和 file.io 两种方式下载完整漫画包。file.io 无需注册,无需科学上网,文件保存两周,单文件最大 2GB,注意链接只能下载**一次**,下载后文件会自动删除
- [更新日志](#更新日志)

如果用的开心,求个 star 支持一下,比心 ~ ❤️

Expand Down Expand Up @@ -72,7 +75,7 @@ PICA_DL_CONCURRENCY=5
# leaderboard | favorites | search
# 下载内容,分别表示:排行榜 | 收藏夹 | 搜索
PICA_DL_CONTENT=
# 搜索关键字,多个用 # 隔开
# 搜索关键字或漫画ID,多个用 # 隔开
# 尽量输入完整漫画名,避免返回过多结果
PICA_DL_SEARCH_KEYWORDS=
```
Expand All @@ -81,7 +84,7 @@ PICA_DL_SEARCH_KEYWORDS=
# 运行
pica-cli
# 漫画下好后,生成 zip
# 漫画打压缩包
pica-zip
```

Expand All @@ -108,6 +111,7 @@ pnpm dev:zip

## 更新日志

- 2024/02/08 支持下载指定章节
- 2024/02/01 支持通过漫画ID精确下载
- 2024/01/31 github action 同时将漫画包上传到 file.io
- 2024/01/30 提供 github action 的下载方式
Expand Down
61 changes: 48 additions & 13 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
loadEnv,
filterEpisodes,
filterPictures,
isValidComicId
isValidComicId,
selectChapterByInput
} from './utils'
import ora from 'ora'
import input from '@inquirer/input'
Expand All @@ -19,9 +20,22 @@ import pico from 'picocolors'
loadEnv()

async function main() {
const { PICA_DL_CONTENT, PICA_DL_CONCURRENCY, PICA_IS_GITHUB } = process.env
const {
PICA_DL_CONTENT,
PICA_DL_CHAPTER,
PICA_DL_CONCURRENCY,
PICA_IS_GITHUB
} = process.env
const PICA_DL_SEARCH_KEYWORDS = process.env.PICA_DL_SEARCH_KEYWORDS?.trim()

const keysTip = [
`${pico.cyan('<space>')} 选中`,
`${pico.cyan('<a>')} 全选`,
`${pico.cyan('<i>')} 反选`,
`${pico.cyan('<enter>')} 确认`
]
const checkboxHelpTip = ` (${keysTip.join(', ')})`

const answer =
PICA_DL_CONTENT ||
(await select({
Expand Down Expand Up @@ -91,12 +105,17 @@ async function main() {
searchRes = await pica.searchAll(keyword)
spinner.stop()

if (searchRes.length === 0) {
continue
}

const selected = PICA_DL_SEARCH_KEYWORDS
? searchRes
: await checkbox({
message: '请选择要下载的漫画',
pageSize: 10,
loop: false,
instructions: checkboxHelpTip,
choices: searchRes.map((x) => {
return {
name: x.title.trim(),
Expand All @@ -117,9 +136,27 @@ async function main() {
episodes = filterEpisodes(episodes, cid)
spinner.stop()

log.info(`${title} 查询到 ${episodes.length} 个章节`)
log.info(`${title} 查询到 ${episodes.length} 个未下载章节`)

if (episodes.length === 0) {
continue
}

const selectedEpisodes = PICA_DL_CHAPTER
? selectChapterByInput(PICA_DL_CHAPTER, episodes)
: await checkbox({
message: '请选择要下载的章节',
pageSize: 10,
instructions: checkboxHelpTip,
choices: episodes.map((ep) => {
return {
name: ep.title.trim(),
value: ep
}
})
})

for (const ep of episodes) {
for (const ep of selectedEpisodes) {
spinner.start(`正在获取章节 ${ep.title} 的图片信息`)
let pictures = await pica.picturesAll(cid, ep)
pictures = filterPictures(pictures, title, ep.title)
Expand All @@ -137,19 +174,17 @@ async function main() {
const concurrency = Number(PICA_DL_CONCURRENCY || 5)
const limit = pLimit(concurrency)
const tasks = pictures.map((pic) => {
return limit(() => {
return pica
.download(pic.url, {
title: title,
epTitle: pic.epTitle,
picName: pic.name
})
.then(() => bar.tick())
return limit(async () => {
await pica.download(pic.url, {
title: title,
epTitle: pic.epTitle,
picName: pic.name
})
return bar.tick()
})
})

await Promise.all(tasks)

mark(cid, ep.id)
}

Expand Down
19 changes: 19 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,25 @@ import figures from 'figures'

export const debug = Debug('pica')

/**
* @param s 示例:1,3,5-20
*/
export function selectChapterByInput(input: string, episodes: Episode[]) {
const idx = input.split(/[,,]/).reduce((pre: number[], cur: string) => {
if (!cur) return pre
if (cur.includes('-')) {
const index = cur.split('-').map((s) => Number(s))
for (let i = index[0]; i <= index[1]; i++) {
pre.push(i)
}
} else {
pre.push(Number(cur))
}
return pre
}, [])
return episodes.filter((_, index) => idx.includes(index + 1))
}

export function isValidComicId(cid: string) {
return /^[0-9a-zA-Z]{24}$/.test(cid)
}
Expand Down

0 comments on commit e76958f

Please sign in to comment.