breeze-plugin-nhentai 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Breeze Plugin Example
|
|
2
|
+
|
|
3
|
+
Breeze 插件示例工程,包含所有 API 类型的占位实现。新插件推荐直接 clone 本仓库进行改造。
|
|
4
|
+
|
|
5
|
+
## 文档
|
|
6
|
+
|
|
7
|
+
插件开发文档:[https://deretame.github.io/plugin-dev-docs/](https://deretame.github.io/plugin-dev-docs/)
|
|
8
|
+
|
|
9
|
+
## 已导出的 fnPath
|
|
10
|
+
|
|
11
|
+
### 核心
|
|
12
|
+
- `getInfo` — 插件信息
|
|
13
|
+
- `searchComic` — 搜索漫画
|
|
14
|
+
- `getComicDetail` — 漫画详情
|
|
15
|
+
- `getReadSnapshot` — 阅读快照
|
|
16
|
+
- `getChapter` — 章节内容
|
|
17
|
+
- `fetchImageBytes` — 下载图片
|
|
18
|
+
|
|
19
|
+
### 社交
|
|
20
|
+
- `toggleLike` — 点赞
|
|
21
|
+
- `toggleFavorite` — 收藏
|
|
22
|
+
- `listFavoriteFolders` — 收藏夹列表
|
|
23
|
+
- `moveFavoriteToFolder` — 移动到收藏夹
|
|
24
|
+
- `getCommentFeed` — 评论列表
|
|
25
|
+
- `loadCommentReplies` — 加载回复
|
|
26
|
+
- `postComment` — 发评论
|
|
27
|
+
- `postCommentReply` — 回复评论
|
|
28
|
+
|
|
29
|
+
### 发现
|
|
30
|
+
- `getAdvancedSearchScheme` — 高级搜索方案
|
|
31
|
+
- `getComicListSceneBundle` — 列表场景
|
|
32
|
+
- `getRankingData` — 榜单数据
|
|
33
|
+
- `getRankingFilterBundle` — 榜单筛选
|
|
34
|
+
|
|
35
|
+
### 设置
|
|
36
|
+
- `getSettingsBundle` — 设置方案
|
|
37
|
+
- `getCapabilitiesBundle` — 能力操作
|
|
38
|
+
- `getUserInfoBundle` — 用户信息
|
|
39
|
+
|
|
40
|
+
### 回调
|
|
41
|
+
- `onAuthChanged` / `onRememberChanged` / `onThemeChanged` / `onQualityChanged` / `onAdultChanged` / `onHiddenTagsChanged` — 设置字段变更
|
|
42
|
+
- `clearPluginCache` — 清理缓存
|
|
43
|
+
|
|
44
|
+
## 快速开始
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
git clone https://github.com/deretame/Breeze-plugin-example.git your-plugin-name
|
|
48
|
+
cd your-plugin-name
|
|
49
|
+
pnpm install
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
克隆后删除 `.git` 重新初始化:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Windows
|
|
56
|
+
Remove-Item -Recurse -Force .git
|
|
57
|
+
|
|
58
|
+
# macOS / Linux
|
|
59
|
+
rm -rf .git
|
|
60
|
+
|
|
61
|
+
git init
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
然后修改 `src/common.ts` 的 `PLUGIN_ID` 和 `src/get-info.ts` 的插件信息。
|
|
65
|
+
|
|
66
|
+
## 开发
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pnpm run dev
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
dev server 启动后输出 bundle 地址,在 Breeze 中通过"网络安装"加载即可调试。支持热更新。
|
|
73
|
+
|
|
74
|
+
## 构建
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pnpm run build
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
构建流程:typecheck → 同步版本号 → 生成 `manifest.json` → rspack 打包 → Brotli 压缩。
|
|
81
|
+
|
|
82
|
+
**构建前请先更新 `src/get-info.ts` 中的 `version` 字段。**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(()=>{"use strict";var e={};e.d=(t,n,a)=>{var r=(n,a)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,[a]:n[r]})};r(n,"get"),r(a,"value")},e.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),e.r=e=>{"u">typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var t={};e.r(t),e.d(t,{default:()=>R});let n="416598d0-84d0-4de9-8ec5-e74816e768f2";function a(e){return!e||"object"!=typeof e||Array.isArray(e)?{}:e}function r(e,t={},n={}){return{name:String(null!=e?e:""),onTap:t,extern:n}}function l(e={}){var t,n,a,r,i;return{id:String(null!=(t=e.id)?t:""),url:String(null!=(n=e.url)?n:"").trim()||"",name:String(null!=(a=e.name)?a:""),path:String(null!=(r=e.path)?r:"").trim()||"placeholder/image-404.png",extern:null!=(i=e.extern)?i:{}}}let i="https://nhentai.net",o="https://nhentai.net/api/v2",u="https://t3.nhentai.net",s="main";function c(e){return e&&"object"==typeof e&&!Array.isArray(e)?e:{}}function p(e){return Array.isArray(e)?e:[]}function d(e,t=0){let n=Number(e);return Number.isFinite(n)?n:t}function m(e){return String(null!=e?e:"").trim()}function h(e,t){let n=m(t);return n?/^https?:\/\//i.test(n)?n:`${e}/${n.replace(/^\/+/,"")}`:""}function g(e){let t=d(e);if(!t)return"";let n=new Date(1e3*t);return Number.isNaN(n.getTime())?"":n.toISOString().slice(0,10)}function y(e){if("string"==typeof e)return e.trim();let t=c(e),n=c(t.title||e);return m(t.pretty_title)||m(t.japanese_title)||m(t.english_title)||m(n.pretty)||m(n.english)||m(n.japanese)||"Untitled"}function f(e){let t=c(e),n=c(t.title||e);return m(t.japanese_title)||m(t.english_title)||m(n.japanese)||m(n.english)||""}function v(e,t){return e.filter(e=>e.type===t).map(e=>m(e.name)).filter(Boolean)}async function b(e,t=3e4){let n=await fetch(e,{headers:{Accept:"application/json",Referer:`${i}/`,"User-Agent":"Breeze-plugin-nhentai/0.1.0"},signal:AbortSignal.timeout(t)});if(!n.ok)throw Error(`nhentai 请求失败: HTTP ${n.status}`);return await n.json()}async function x(e){let t=m(e);if(!t)throw Error("comicId 不能为空");return b(`${o}/galleries/${encodeURIComponent(t)}?include=related,favorite`)}function w(e){return m(e.id)}function S(e){var t;return p(e.pages).length||d(null!=(t=e.num_pages)?t:e.page_count)}function $(e){let t=w(e),n=c(e.cover),a=m(n.thumbnail)||m(n.path)||m(e.thumbnail)||m(e.cover_url);return l({id:t,url:h(u,a),name:`${t||"cover"}.jpg`,path:a||`gallery/${t}/cover.jpg`,extern:{path:a}})}function B(e){let t=p(e.tags),a=[],l=(e,t,l)=>{var i;let o=(i=t=>r(t,{type:"openSearch",payload:{source:n,keyword:`${e}:"${t.replace(/"/g,'\\"')}"`}}),{type:e,name:t,value:(Array.isArray(l)?l:null==l?[]:[l]).map(e=>String(null!=e?e:"").trim()).filter(e=>e.length>0).map(e=>i?i(e):r(e))});o.value.length>0&&a.push(o)};return l("language","语言",v(t,"language")),l("artist","作者",v(t,"artist")),l("group","社团",v(t,"group")),l("parody","原作",v(t,"parody")),l("character","角色",v(t,"character")),l("category","分类",v(t,"category")),l("tag","标签",v(t,"tag")),a}function k(e){var t;let a=w(e),r=y(e),l=S(e),o=g(e.upload_date);return{source:n,id:a,title:r,subtitle:[l?`${l} pages`:"",o].filter(Boolean).join(" / "),finished:!0,likesCount:d(null!=(t=e.num_favorites)?t:e.favorites),viewsCount:0,updatedAt:o,cover:$(e),metadata:B(e),raw:e,extern:{webUrl:`${i}/g/${a}/`}}}function _(e){let t=k(e),n=t.metadata.flatMap(e=>e.value).slice(0,6);return{...t,metadata:n}}function j(e){return{id:s,requestId:s,logicalKey:s,storageChapterId:w(e)||s,name:"本篇",order:1,extern:{}}}function A(e){return{...j(e),pages:p(e.pages).map((e,t)=>{var n,a;let r=m(e.path),l=d(e.number,t+1),i=r.split("/").pop()||`${l}.jpg`;return{id:String(l),name:i,path:r,url:h("https://i3.nhentai.net",r),extern:{thumbnail:h(u,e.thumbnail),width:null!=(n=e.width)?n:null,height:null!=(a=e.height)?a:null}}})}}async function I(e={}){var t,r;let l,i,u,s=Math.max(1,d(e.page,1)),c=(r=m(e.keyword),[r||"all",...(l=[m(a(e.extern).languages)].filter(Boolean).slice(0,1)).includes("all")||0===l.length?[]:Array.from(new Set(l))].join(" ").trim()),h=(i=m(a(e.extern).sortBy),new Set(["date","popular","popular-today","popular-week","popular-month"]).has(i)?i:"date"),g=await b(((u=new URLSearchParams).set("query",c),u.set("page",String(s)),u.set("sort",h),`${o}/search?${u.toString()}`)),y=Math.max(1,d(g.num_pages,1)),f=d(g.total,p(g.result).length),v=p(g.result).map(k),x={page:s,pages:y,total:f,hasReachedMax:s>=y};return{source:n,extern:null!=(t=e.extern)?t:null,scheme:{version:"1.0.0",type:"searchResult",source:n,list:"comicGrid"},data:{paging:x,items:v},paging:x,items:v}}async function C(e={}){var t;let a=await I(e);return{source:n,extern:null!=(t=e.extern)?t:null,scheme:{version:"1.0.0",type:"comicPagedList",source:n},data:{items:a.items,hasReachedMax:a.paging.hasReachedMax}}}let R={getInfo:async function(){return{name:"nhentai",uuid:n,iconUrl:"https://raw.githubusercontent.com/deretame/Breeze-plugin-nhentai/main/assets/Nhentai_idAD-FU-t__1.svg",creator:{name:"Breeze plugin",describe:"nhentai source adapter"},describe:"nhentai 漫画源插件",version:"0.0.1",updateUrl:"https://api.github.com/repos/deretame/Breeze-plugin-nhentai/releases/latest",home:"https://github.com/deretame/Breeze-plugin-nhentai",npmName:"breeze-plugin-nhentai",function:[{id:"latest",title:"最新",action:{type:"openComicList",payload:{scene:{title:"nhentai",source:n,body:{type:"pluginPagedComicList",request:{fnPath:"getRankingData",core:{},extern:{sortBy:"date"}}},filter:{fnPath:"getRankingFilterBundle",extern:{}}}}}}]}},searchComic:I,getComicDetail:async function(e={}){var t,a;let o,u,s,c,h,b,k=m(e.comicId),A=await x(k);return{source:n,comicId:k,extern:null!=(t=e.extern)?t:null,scheme:{version:"1.0.0",type:"comicDetail",source:n},data:{normal:(o=w(A),u=y(A),s=m(A.japanese_title)||f(A),v(p(A.tags),"artist"),c=S(A),h=g(A.upload_date),b=[s&&s!==u?r(`Japanese: ${s}`):null,o?r(`ID: ${o}`):null,null!=A.media_id?r(`Media ID: ${m(A.media_id)}`):null,c?r(`${c} pages`):null,h?r(h):null].filter(Boolean),{comicInfo:{id:o,title:u,titleMeta:b,creator:{id:"",name:"",avatar:l({id:"",url:"",name:"",path:"",extern:{}}),onTap:{},extern:{}},description:f(A),cover:$(A),metadata:B(A),extern:{webUrl:`${i}/g/${o}/`}},eps:[j(A)],recommend:p(A.related).map(_),totalViews:0,totalLikes:d(null!=(a=A.num_favorites)?a:A.favorites),totalComments:0,isFavourite:!!A.is_favorited,isLiked:!1,allowComments:!0,allowLike:!1,allowCollected:!1,allowDownload:!0,extern:{}}),raw:A}}},getReadSnapshot:async function(e={}){var t;let a=m(e.comicId),r=await x(a),l=A(r),o=j(r);return{source:n,extern:null!=(t=e.extern)?t:null,data:{comic:{id:w(r),source:n,title:y(r),extern:{webUrl:`${i}/g/${w(r)}/`}},chapter:l,chapters:[{id:o.id,name:o.name,order:o.order,extern:o.extern}]}}},getChapter:async function(e={}){var t;let a=m(e.comicId),r=await x(a),l=A(r);return{source:n,comicId:a,chapterId:s,extern:null!=(t=e.extern)?t:null,scheme:{version:"1.0.0",type:"chapterContent",source:n},data:{comic:{id:w(r),source:n,title:y(r),extern:{webUrl:`${i}/g/${w(r)}/`}},chapter:l,chapters:[j(r)]}}},fetchImageBytes:async function({url:e="",timeoutMs:t=3e4}={}){let n=m(e);if(!n)throw Error("url 不能为空");let a=await fetch(n,{headers:{Referer:`${i}/`,"User-Agent":"Breeze-plugin-nhentai/0.1.0","x-rquickjs-host-offload-binary-v1":"1"},signal:AbortSignal.timeout(t)});if(!a.ok)throw Error(`图片请求失败: HTTP ${a.status}`);return new Uint8Array(await a.arrayBuffer())},getAdvancedSearchScheme:async function(){return{source:n,scheme:{version:"1.0.0",type:"advancedSearch",title:"高级搜索",fields:[{key:"sortBy",kind:"choice",label:"排序",options:[{label:"最新",value:"date"},{label:"最热",value:"popular"},{label:"今日热门",value:"popular-today"},{label:"本周热门",value:"popular-week"},{label:"本月热门",value:"popular-month"}]},{key:"languages",kind:"choice",label:"语言",options:[{label:"所有",value:"all"},{label:"仅中文",value:"chinese"},{label:"仅日文",value:"japanese"},{label:"仅英文",value:"english"}]}]},data:{values:{sortBy:"date",languages:"all"}}}},getComicListSceneBundle:async function(){return{source:n,scheme:{version:"1.0.0",type:"comicListSceneBundle"},data:{scene:{title:"nhentai",source:n,body:{type:"pluginPagedComicList",request:{fnPath:"getRankingData",core:{},extern:{sortBy:"date"}}},filter:{fnPath:"getRankingFilterBundle",extern:{}}}}}},getRankingData:C,getRankingFilterBundle:async function(){return{source:n,scheme:{version:"1.0.0",title:"排序",fields:[{key:"sortBy",kind:"choice",label:"排序",options:[{label:"最新",value:"date",result:{extern:{sortBy:"date"}}},{label:"最热",value:"popular",result:{extern:{sortBy:"popular"}}},{label:"今日热门",value:"popular-today",result:{extern:{sortBy:"popular-today"}}},{label:"本周热门",value:"popular-week",result:{extern:{sortBy:"popular-week"}}},{label:"本月热门",value:"popular-month",result:{extern:{sortBy:"popular-month"}}}]}]},data:{values:{sortBy:"date"}}}},getCommentFeed:async function(e={}){var t;let a=m(e.comicId);if(!a)throw Error("comicId 不能为空");let r=(await b(`${o}/galleries/${encodeURIComponent(a)}/comments`)).map((e,t)=>{let n=c(e.poster),a=m(n.avatar_url);return{id:m(e.id)||`comment-${t+1}`,author:{name:m(n.username)||"anonymous",avatar:{url:a||"",path:a}},content:m(e.body),createdAt:g(e.post_date),replyCount:0,replies:[],extern:{}}});return{source:n,extern:null!=(t=e.extern)?t:null,scheme:{version:"1.0.0",type:"commentFeed"},data:{topItems:[],items:r,paging:{hasReachedMax:!0},replyMode:"embedded",canComment:{comic:!1,reply:!1}}}},getSettingsBundle:async function(){return{source:n,scheme:{version:"1.0.0",type:"settings",sections:[]},data:{canShowUserInfo:!1,values:{}}}}};module.exports=t})();
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "breeze-plugin-nhentai",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"files": [
|
|
6
|
+
"dist"
|
|
7
|
+
],
|
|
8
|
+
"devDependencies": {
|
|
9
|
+
"@rspack/cli": "^2.0.5",
|
|
10
|
+
"@rspack/core": "^2.0.5",
|
|
11
|
+
"@types/node": "^25.9.1",
|
|
12
|
+
"cross-env": "^10.1.0",
|
|
13
|
+
"tsx": "^4.22.4",
|
|
14
|
+
"typescript": "^6.0.3"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"build": "pnpm typecheck && node --import tsx build/generate-version.ts && node --import tsx build/generate-manifest.ts && cross-env NODE_OPTIONS=\"--import tsx\" rspack build && node --import tsx build/generate-brotli.ts",
|
|
19
|
+
"dev": "pnpm dev:serve",
|
|
20
|
+
"dev:serve": "tsx dev-server.ts"
|
|
21
|
+
}
|
|
22
|
+
}
|