breeze-plugin-webtoon 0.0.1 → 0.0.2

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.
@@ -1 +1 @@
1
- (()=>{"use strict";var e={};e.d=(t,r,a)=>{var n=(r,a)=>{for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,[a]:r[n]})};n(r,"get"),n(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:()=>Q});let r="7efa2a7c-da0f-4db1-9167-98045ae37fdb",a="https://webtoons-static.pstatic.net/image/favicon/favicon.ico",n="https://m.webtoons.com/",i="https://www.webtoons.com",l="https://m.webtoons.com";function o(e){return!e||"object"!=typeof e||Array.isArray(e)?{}:e}function s(e){return String(null!=e?e:"").trim()}function c(e){return String(null!=e?e:"").replace(/[\s\u00a0\u3000]+$/u,"")}function u(e,t={},r={}){return{name:c(e),onTap:t,extern:r}}function d(e={}){var t,r,n,i,l;return{id:String(null!=(t=e.id)?t:""),url:String(null!=(r=e.url)?r:"").trim()||a,name:String(null!=(n=e.name)?n:""),path:String(null!=(i=e.path)?i:"").trim()||"placeholder/image-404.png",extern:null!=(l=e.extern)?l:{}}}let g=["en","zh-hant","zh-hans","th","id","es","fr","de"],p={"plugin.describe":"WEBTOON official web source","settings.section.content":"Content","settings.lang.label":"Default search language","settings.lang.followSystem":"Follow system (current: {lang})","settings.r18.label":"Show R18 / mature content","advancedSearch.title":"Advanced search","advancedSearch.lang":"Language","meta.author":"Author","meta.categories":"Genre","titleMeta.type":"Type: {type}","titleMeta.chapters":"Chapters: {count}","titleMeta.lang":"Language: {lang}","type.original":"Original","type.canvas":"Canvas","error.keywordRequired":"Please enter a search keyword","error.comicIdRequired":"comicId is required","error.noEpisodes":"No episodes available","error.noViewerLink":"Episode {id} is missing viewerLink","error.noImageList":"imageList not found on viewer page","error.emptyImageList":"imageList is empty","error.detailUrlEmpty":"Detail page URL is empty","error.cannotResolveDetail":"Cannot resolve detail URL (titleNo={titleNo}). Open again from search.","error.downloadFailed":"Download failed: {status} {statusText}","error.http":"HTTP {status}: {url}","error.r18Blocked":"This title is mature content. Enable R18 in plugin settings.","error.urlRequired":"url is required"},h={...p,"plugin.describe":"แหล่ง WEBTOON เว็บอย่างเป็นทางการ","settings.section.content":"เนื้อหา","settings.lang.label":"ภาษาค้นหาเริ่มต้น","settings.lang.followSystem":"ตามระบบ (ปัจจุบัน: {lang})","settings.r18.label":"แสดงเนื้อหา R18 / 18+","advancedSearch.title":"ค้นหาขั้นสูง","advancedSearch.lang":"ภาษา","meta.author":"ผู้แต่ง","meta.categories":"ประเภท","titleMeta.type":"ประเภท: {type}","titleMeta.chapters":"ตอน: {count}","titleMeta.lang":"ภาษา: {lang}","error.keywordRequired":"กรุณาใส่คำค้นหา","error.comicIdRequired":"ต้องระบุ comicId","error.noEpisodes":"ยังไม่มีตอน","error.r18Blocked":"เรื่องนี้เป็นเนื้อหาสำหรับผู้ใหญ่ เปิด R18 ในการตั้งค่าปลั๊กอิน"},m={...p,"plugin.describe":"Sumber web resmi WEBTOON","settings.section.content":"Konten","settings.lang.label":"Bahasa pencarian default","settings.lang.followSystem":"Ikuti sistem (saat ini: {lang})","settings.r18.label":"Tampilkan konten R18 / dewasa","advancedSearch.title":"Pencarian lanjutan","advancedSearch.lang":"Bahasa","meta.author":"Penulis","meta.categories":"Genre","titleMeta.type":"Tipe: {type}","titleMeta.chapters":"Episode: {count}","titleMeta.lang":"Bahasa: {lang}","error.keywordRequired":"Masukkan kata kunci pencarian","error.comicIdRequired":"comicId wajib diisi","error.noEpisodes":"Belum ada episode","error.r18Blocked":"Judul ini konten dewasa. Aktifkan R18 di pengaturan plugin."},f={...p,"plugin.describe":"Fuente web oficial de WEBTOON","settings.section.content":"Contenido","settings.lang.label":"Idioma de b\xfasqueda predeterminado","settings.lang.followSystem":"Seguir el sistema (actual: {lang})","settings.r18.label":"Mostrar contenido R18 / adulto","advancedSearch.title":"B\xfasqueda avanzada","advancedSearch.lang":"Idioma","meta.author":"Autor","meta.categories":"G\xe9nero","titleMeta.type":"Tipo: {type}","titleMeta.chapters":"Cap\xedtulos: {count}","titleMeta.lang":"Idioma: {lang}","error.keywordRequired":"Introduce una palabra clave","error.comicIdRequired":"comicId es obligatorio","error.noEpisodes":"No hay episodios","error.r18Blocked":"Este t\xedtulo es contenido adulto. Activa R18 en la configuraci\xf3n del plugin."},w={...p,"plugin.describe":"Source web officielle WEBTOON","settings.section.content":"Contenu","settings.lang.label":"Langue de recherche par d\xe9faut","settings.lang.followSystem":"Suivre le syst\xe8me (actuel : {lang})","settings.r18.label":"Afficher le contenu R18 / mature","advancedSearch.title":"Recherche avanc\xe9e","advancedSearch.lang":"Langue","meta.author":"Auteur","meta.categories":"Genre","titleMeta.type":"Type : {type}","titleMeta.chapters":"Chapitres : {count}","titleMeta.lang":"Langue : {lang}","error.keywordRequired":"Veuillez saisir un mot-cl\xe9","error.comicIdRequired":"comicId est requis","error.noEpisodes":"Aucun \xe9pisode disponible","error.r18Blocked":"Ce titre est r\xe9serv\xe9 aux adultes. Activez R18 dans les param\xe8tres du plugin."},y={...p,"plugin.describe":"Offizieller WEBTOON-Web-Quell","settings.section.content":"Inhalt","settings.lang.label":"Standard-Suchsprache","settings.lang.followSystem":"System folgen (aktuell: {lang})","settings.r18.label":"R18- / Mature-Inhalte anzeigen","advancedSearch.title":"Erweiterte Suche","advancedSearch.lang":"Sprache","meta.author":"Autor","meta.categories":"Genre","titleMeta.type":"Typ: {type}","titleMeta.chapters":"Kapitel: {count}","titleMeta.lang":"Sprache: {lang}","error.keywordRequired":"Bitte Suchbegriff eingeben","error.comicIdRequired":"comicId ist erforderlich","error.noEpisodes":"Keine Episoden verf\xfcgbar","error.r18Blocked":"Dieser Titel ist Mature-Inhalt. R18 in den Plugin-Einstellungen aktivieren."},v={en:p,"zh-hant":{"plugin.describe":"WEBTOON 官方 Web 端源","settings.section.content":"內容","settings.lang.label":"預設搜尋語言","settings.lang.followSystem":"跟隨系統(目前 {lang})","settings.r18.label":"顯示 R18 / 成人內容","advancedSearch.title":"進階搜尋","advancedSearch.lang":"語言","meta.author":"作者","meta.categories":"分類","titleMeta.type":"類型:{type}","titleMeta.chapters":"章節:{count}","titleMeta.lang":"語言:{lang}","type.original":"Original","type.canvas":"Canvas","error.keywordRequired":"請輸入搜尋關鍵字","error.comicIdRequired":"comicId 不能為空","error.noEpisodes":"該作品暫無章節","error.noViewerLink":"章節 {id} 缺少 viewerLink","error.noImageList":"未在 viewer 頁面找到 imageList","error.emptyImageList":"imageList 為空","error.detailUrlEmpty":"詳情頁 URL 為空","error.cannotResolveDetail":"無法解析詳情頁 URL (titleNo={titleNo}),請從搜尋結果重新開啟","error.downloadFailed":"下載失敗:{status} {statusText}","error.http":"HTTP {status}: {url}","error.r18Blocked":"此作品為成人內容,請在外掛設定中開啟 R18","error.urlRequired":"url 不能為空"},"zh-hans":{"plugin.describe":"WEBTOON 官方 Web 端源","settings.section.content":"内容","settings.lang.label":"默认搜索语言","settings.lang.followSystem":"跟随系统(当前 {lang})","settings.r18.label":"显示 R18 / 成人内容","advancedSearch.title":"高级搜索","advancedSearch.lang":"语言","meta.author":"作者","meta.categories":"分类","titleMeta.type":"类型:{type}","titleMeta.chapters":"章节:{count}","titleMeta.lang":"语言:{lang}","type.original":"Original","type.canvas":"Canvas","error.keywordRequired":"请输入搜索关键词","error.comicIdRequired":"comicId 不能为空","error.noEpisodes":"该作品暂无章节","error.noViewerLink":"章节 {id} 缺少 viewerLink","error.noImageList":"未在 viewer 页面找到 imageList","error.emptyImageList":"imageList 为空","error.detailUrlEmpty":"详情页 URL 为空","error.cannotResolveDetail":"无法解析详情页 URL (titleNo={titleNo}),请从搜索结果重新打开","error.downloadFailed":"下载失败:{status} {statusText}","error.http":"HTTP {status}: {url}","error.r18Blocked":"此作品为成人内容,请在插件设置中开启 R18","error.urlRequired":"url 不能为空"},th:h,id:m,es:f,fr:w,de:y};async function b(){try{let e=globalThis.bridge;if("function"!=typeof(null==e?void 0:e.call))return"";let t=await Promise.resolve(e.call("dart.getLocaleInfo")),r="string"==typeof t?t:JSON.stringify(null!=t?t:"");if(!r)return"";let a=JSON.parse(r);return s(a.locale)||s(a.systemLocale)||s(a.language)||""}catch{return""}}async function S(){let e=s(await b()).toLowerCase().replace(/_/g,"-");if(!e)return"en";if(g.includes(e))return e;if(e.startsWith("zh"))return e.includes("hant")||e.includes("tw")||e.includes("hk")||e.includes("mo")?"zh-hant":"zh-hans";let t=e.split("-")[0]||"";return g.includes(t)?t:"en"}function k(e,t,r){var a,n;let i=null!=(a=null!=(n=(v[e]||p)[t])?n:p[t])?a:t;if(r)for(let[e,t]of Object.entries(r))i=i.replace(RegExp(`\\{${e}\\}`,"g"),String(t));return i}async function R(){return{name:"WEBTOON",uuid:r,iconUrl:"https://webtoons-static.pstatic.net/image/favicon/favicon.ico",creator:{name:"",describe:""},describe:k(await S(),"plugin.describe"),version:"0.0.1",home:"https://www.webtoons.com",updateUrl:"",npmName:"breeze-plugin-webtoon",function:[]}}let I=[{label:"English",value:"en"},{label:"中文 (繁體)",value:"zh-hant"},{label:"ภาษาไทย",value:"th"},{label:"Indonesia",value:"id"},{label:"Espa\xf1ol",value:"es"},{label:"Fran\xe7ais",value:"fr"},{label:"Deutsch",value:"de"}],L=new Set(I.map(e=>e.value)),N="auto",x="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36";function E(e){return`ageGatePass=${e?"true":"false"}; needGDPR=false`}function M(e=!1){return{"User-Agent":x,Referer:n,"Accept-Language":"en-US,en;q=0.9",Cookie:E(e)}}function O(e=!1){return{"User-Agent":"Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36",Referer:n,"Accept-Language":"en-US,en;q=0.9",Cookie:E(e)}}async function C(e,t,r=2e4,a="en"){let n=await fetch(e,{method:"GET",headers:t,signal:AbortSignal.timeout(r)});if(!n.ok)throw Error(k(a,"error.http",{status:n.status,url:e}));return n.text()}async function T(e,t,r=2e4,a="en"){return JSON.parse(await C(e,t,r,a))}async function q(){try{let e=await ((e,t="")=>bridge.call("load_plugin_config",e,t))("content.r18","");if(!e)return!1;let t=JSON.parse(e);return!0===t.value||"true"===t.value}catch{return!1}}function B(e){return L.has(e)}async function $(){let e=await b();if(!e)return"en";let t=s(e).toLowerCase().replace(/_/g,"-");if(!t)return"en";if(B(t))return t;if(t.startsWith("zh"))return t.includes("hant")||t.includes("tw")||t.includes("hk")||t.includes("mo"),"zh-hant";let r=t.split("-")[0]||"";return B(r)?r:"en"}async function A(){try{let e=await ((e,t="")=>bridge.call("load_plugin_config",e,t))("content.lang","");if(!e)return N;let t=JSON.parse(e),r=s(t.value);if(!r||r===N)return N;if(B(r))return r;return N}catch{return N}}async function _(){let e=await A();return e!==N&&B(e)?e:$()}function U(e){let t=e.href||"";return[e.lang,e.type,e.titleNo,t].map(e=>encodeURIComponent(e)).join("|")}function W(e,t="en"){let r=s(e);if(!r)throw Error("comicId 不能为空");if(r.includes("|")){let a=r.split("|").map(e=>{try{return decodeURIComponent(e)}catch{return e}}),n=a[0]||t,i="canvas"===a[1]?"canvas":"webtoon",l=a[2]||"",o=a[3]||"";if(!l)throw Error(`无效 comicId: ${e}`);return{lang:n,type:i,titleNo:l,href:o}}return{lang:t,type:"webtoon",titleNo:r,href:""}}function z(e){return e.includes("/challenge/")?"canvas":"webtoon"}function P(e){let t=s(e);return t?t.startsWith("http://")||t.startsWith("https://")?t:t.startsWith("/")?`${i}${t}`:t:""}function j(e){let t=s(e);return t?t.startsWith("http://")||t.startsWith("https://")?t:t.startsWith("/")?`${l}${t}`:`${l}/${t}`:""}function D(e,t,a,n){let i=a.map(e=>c(e).trimStart()).map(e=>e.trim()).filter(Boolean);return i.length?{type:e,name:c(t),value:i.map(e=>u(e,{type:"openSearch",payload:{source:r,keyword:e,extern:n?{lang:n}:{}}}))}:null}async function G(e,t,n=1,l={}){var o;let u=!!l.allowR18,g=null!=(o=l.uiLang)?o:"en",p=new URL(`${i}/${t}/search`);p.searchParams.set("keyword",e),p.searchParams.set("page",String(n));let h=await C(p.toString(),M(u),2e4,g),m=BreezeHtml.load(h),f=[];return m(".webtoon_list li a").each((e,n)=>{let i=m(n),l=c(i.find(".title").text()).trim(),o=c(i.find(".author").text()).trim(),p=P(s(i.attr("href"))),h=s(i.find("img").attr("src")),w=s(i.attr("data-title-no"));if(!l||!w)return;let y=function(e){var t;if(e.find(".ico_age19, .age19, .ico_mature, .mature").length>0)return!0;let r=s(e.attr("class")).toLowerCase();if(r.includes("age19")||r.includes("mature"))return!0;let a=s(null!=(t=e.html())?t:"").toLowerCase();return!!(a.includes("ico_age19")||a.includes("age19")||a.includes("grade19")||a.includes("mature"))}(i);if(y&&!u)return;let v=z(p),b=U({titleNo:w,type:v,lang:t,href:p}),S=`comic/${w}/cover.jpg`;f.push({source:r,id:b,title:l,subtitle:o,finished:!1,likesCount:0,viewsCount:0,updatedAt:"",cover:d({id:w,url:h||a,name:"cover.jpg",path:S,extern:{}}),metadata:[D("author",k(g,"meta.author"),o?[o]:[],t)].filter(e=>null!=e),raw:{title:l,author:o,href:p,img:h,titleNo:w,type:v,lang:t,mature:y},extern:{href:p,type:v,lang:t,titleNo:w,mature:y}})}),{results:f,hasNext:m("a.pagination[aria-current=true] + a").length>0}}async function K(e,t={}){var r;let a,n=!!t.allowR18,i=null!=(r=t.uiLang)?r:"en",l=P(e);if(!l)throw Error(k(i,"error.detailUrlEmpty"));let o=await C(l,M(n),2e4,i),u=(a=o.toLowerCase()).includes("ico_age19")||a.includes("agegate")||a.includes("age_gate")||a.includes("mature")||/grade\s*[=:]\s*["']?19/.test(a);if(u&&!n)throw Error(k(i,"error.r18Blocked"));let d=BreezeHtml.load(o),g=c(d("h1.subj, h3.subj").first().text()).trim(),p=c(d(".detail_header .info .author_area").first().text().replace(/author info/gi,"")).replace(/\s+/g," ").trim(),h=[];d(".detail_header .info .genre").each((e,t)=>{let r=c(d(t).text()).trim();r&&h.push(r)});let m=c(d("#_asideDetail p.summary").text()).trim()||c(d(".detail_header p.summary").text()).trim(),f=s(d(".detail_header .thmb img").attr("src"))||s(d('head meta[property="og:image"]').attr("content")),w="";try{w=new URL(l).searchParams.get("title_no")||""}catch{w=""}return{title:g,author:p,genre:h.join(", "),summary:m,thumbnail:f,titleNo:w,url:l,mature:u}}async function J(e,t="webtoon",r="en",a={}){var n,i;let o=!!a.allowR18,s=null!=(n=a.uiLang)?n:"en",c=new URL(`${l}/api/v1/${t}/${e}/episodes`);c.searchParams.set("pageSize","99999"),"canvas"===t&&c.searchParams.set("readingLanguageCode",r);let u=await T(c.toString(),O(o),2e4,s),d=null==u||null==(i=u.result)?void 0:i.episodeList;return Array.isArray(d)?d:[]}async function F(e,t={}){var r;let a=!!t.allowR18,n=null!=(r=t.uiLang)?r:"en",i=j(e);if(!i)throw Error(k(n,"error.noViewerLink",{id:"?"}));let l=(await C(i,O(a),2e4,n)).match(/var\s+imageList\s*=\s*(\[[\s\S]*?\]);/);if(!l)throw Error(k(n,"error.noImageList"));let o=JSON.parse(l[1].replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g,'$1"$2":'));if(!Array.isArray(o)||0===o.length)throw Error(k(n,"error.emptyImageList"));return o.sort((e,t)=>{var r,a;return Number(null!=(r=e.sortOrder)?r:0)-Number(null!=(a=t.sortOrder)?a:0)}),{viewerUrl:i,imageList:o}}async function V(e,t={}){var r;let a=null!=(r=t.uiLang)?r:"en";if(e.href)return P(e.href);let n=await J(e.titleNo,e.type,e.lang,t);if(n.length>0){let e=function(e){let t=j(e);if(!t)return"";try{let e=new URL(t),r=e.pathname.split("/").filter(Boolean);if(r.length>=3){let t=e.searchParams.get("title_no")||"";return`${i}/${r[0]}/${r[1]}/${r[2]}/list?title_no=${t}`}}catch{}return""}(n[0].viewerLink);if(e)return e}throw Error(k(a,"error.cannotResolveDetail",{titleNo:e.titleNo}))}async function H(e={}){let t=await S(),n=await q(),i=s(e.comicId);if(!i)throw Error(k(t,"error.comicIdRequired"));let l=W(i,await _()),g=o(e.extern),p={allowR18:n,uiLang:t};s(g.href)&&(l.href=s(g.href)),"canvas"===s(g.type)&&(l.type="canvas"),s(g.lang)&&(l.lang=s(g.lang));let h=await V(l,p);l.href=h,l.type=z(h);let[m,f]=await Promise.all([K(h,p),J(l.titleNo,l.type,l.lang,p)]);m.titleNo&&(l.titleNo=m.titleNo);let w=U(l),y=f.map((e,t)=>{var r,a;let n=String(e.episodeNo),i=s(e.viewerLink);return{id:n,requestId:n,logicalKey:n,storageChapterId:n,name:s(e.episodeTitle)||`Ep. ${e.episodeNo}`,order:t+1,extern:{comicId:w,episodeNo:e.episodeNo,viewerLink:i,thumbnail:null!=(r=e.thumbnail)?r:"",exposureDateMillis:null!=(a=e.exposureDateMillis)?a:0}}}),v=m.genre?m.genre.split(",").map(e=>e.trim()).filter(Boolean):[],b=k(t,"canvas"===l.type?"type.canvas":"type.original");return{source:r,comicId:w,extern:{...g,href:h,type:l.type,lang:l.lang,titleNo:l.titleNo,mature:m.mature},scheme:{version:"1.0.0",type:"comicDetail",source:r},data:{normal:{comicInfo:{id:w,title:m.title||`WEBTOON #${l.titleNo}`,titleMeta:[k(t,"titleMeta.type",{type:b}),k(t,"titleMeta.chapters",{count:y.length}),k(t,"titleMeta.lang",{lang:l.lang})].map(e=>c(e)).filter(e=>e.length>0).map(e=>u(e)),creator:{id:"",name:"",avatar:{id:"",url:"",name:"",path:"",extern:{}},onTap:{},extern:{}},description:m.summary||"",cover:d({id:l.titleNo,url:m.thumbnail||a,name:"cover.jpg",path:`comic/${l.titleNo}/cover.jpg`}),metadata:[D("author",k(t,"meta.author"),m.author?[m.author]:[],l.lang),D("categories",k(t,"meta.categories"),v,l.lang)].filter(e=>null!=e),extern:{href:h,type:l.type,lang:l.lang,titleNo:l.titleNo,mature:m.mature}},eps:y,recommend:[],totalViews:0,totalLikes:0,totalComments:0,isFavourite:!1,isLiked:!1,allowComments:!1,allowLike:!1,allowCollected:!1,allowDownload:!0,extern:{href:h,type:l.type,lang:l.lang,titleNo:l.titleNo,mature:m.mature}},raw:{detail:m,episodes:f,parts:l}}}}async function Z(e){var t,r,a,n;let i=await S(),l=await q(),c=s(e.comicId);if(!c)throw Error(k(i,"error.comicIdRequired"));let u=await H({comicId:c,extern:e.extern}),d=u.data.normal.eps;if(!d.length)throw Error(k(i,"error.noEpisodes"));let g=s(e.chapterId),p=null!=(t=d.find(e=>e.requestId===g||e.id===g))?t:d[0],h=o(p.extern),m=s(h.viewerLink);if(!m){let e=W(c,await _()),t=(await J(e.titleNo,e.type,e.lang,{allowR18:l,uiLang:i})).find(e=>String(e.episodeNo)===p.id);m=s(null==t?void 0:t.viewerLink)}if(!m)throw Error(k(i,"error.noViewerLink",{id:p.id}));let{imageList:f}=await F(m,{allowR18:l,uiLang:i}),w=(a=u.comicId,n=p.storageChapterId,f.map((e,t)=>{var r,i,l;let o=s(e.url),c=function(e,t){try{let t=new URL(e).pathname.split("/").filter(Boolean).pop()||"";if(t)return t}catch{}return`${String(t+1).padStart(4,"0")}.jpg`}(o,t);return{id:`${n}-p-${t}`,name:c,path:`comic/${a}/${n}/${c}`,url:o,extern:{width:null!=(r=e.width)?r:0,height:null!=(i=e.height)?i:0,sortOrder:null!=(l=e.sortOrder)?l:t}}}));return{comicId:u.comicId,title:u.data.normal.comicInfo.title,chapter:{...p,pages:w,extern:{...h,viewerLink:m}},chapters:d,extern:null!=(r=e.extern)?r:null}}let Q={getInfo:async function(){return await R()},searchComic:async function(e={}){var t,a;let n=await S(),i=await q(),l=o(e.extern),c=Math.max(1,Number(null!=(t=e.page)?t:1)||1),u=s(null!=(a=e.keyword)?a:l.keyword);if(!u)throw Error(k(n,"error.keywordRequired"));let d=await _(),g=s(l.lang),p=(g&&B(g)?g:"")||d||"en",{results:h,hasNext:m}=await G(u,p,c,{allowR18:i,uiLang:n}),f=function(e=1,t=1,r=0,a=!0){return{page:e,pages:Math.max(1,t),total:r,hasReachedMax:a}}(c,m?c+1:c,h.length,!m);return{source:r,extern:{...l,keyword:u,lang:p,page:c},scheme:{version:"1.0.0",type:"searchResult",source:r,list:"comicGrid"},data:{paging:f,items:h},paging:f,items:h}},getComicDetail:H,getChapter:async function(e={}){let t=await Z(e);return{source:r,comicId:t.comicId,chapterId:t.chapter.id,extern:t.extern,scheme:{version:"1.0.0",type:"chapterContent",source:r},data:{comic:{id:t.comicId,source:r,title:t.title,extern:{}},chapter:t.chapter,chapters:t.chapters.map(e=>({id:e.id,requestId:e.requestId,logicalKey:e.logicalKey,storageChapterId:e.storageChapterId,name:e.name,order:e.order,extern:e.extern}))}}},getReadSnapshot:async function(e={}){let t=await Z(e);return{source:r,extern:t.extern,data:{comic:{id:t.comicId,source:r,title:t.title,extern:{}},chapter:t.chapter,chapters:t.chapters.map(e=>({id:e.id,name:e.name,order:e.order,extern:e.extern}))}}},fetchImageBytes:async function(e={}){var t;let r,a=await S(),i=await q(),l=s(e.url);if(!l)throw Error(k(a,"error.urlRequired"));let o=Number(null!=(t=e.timeoutMs)?t:3e4)||3e4,c=s(e.taskGroupKey);if(c&&await (r=c,bridge.call("runtime.is_task_group_cancelled",r)))return new Uint8Array(0);let u=await fetch(l,{method:"GET",headers:{"User-Agent":x,Referer:n,Cookie:E(i),"x-rquickjs-host-offload-binary-v1":"1"},signal:AbortSignal.timeout(o)});if(!u.ok)throw Error(k(a,"error.downloadFailed",{status:u.status,statusText:u.statusText}));return new Uint8Array(await u.arrayBuffer())},getSettingsBundle:async function(){let e=await S(),t=await A(),a=await _(),n=await q();return{source:r,scheme:{version:"1.0.0",type:"settings",sections:[{title:k(e,"settings.section.content"),fields:[{key:"content.lang",kind:"choice",label:k(e,"settings.lang.label"),options:[{label:k(e,"settings.lang.followSystem",{lang:a}),value:N},...I.map(e=>({label:e.label,value:e.value}))],fnPath:"onLangChanged",persist:!0},{key:"content.r18",kind:"switch",label:k(e,"settings.r18.label"),fnPath:"onR18Changed",persist:!0}]}]},data:{canShowUserInfo:!1,values:{"content.lang":t,"content.r18":n}}}},getCapabilitiesBundle:async function(){return{source:r,scheme:{version:"1.0.0",type:"capabilities",actions:[]},data:{}}},getAdvancedSearchScheme:async function(){let e=await S(),t=await _();return{source:r,scheme:{version:"1.0.0",type:"advancedSearch",title:k(e,"advancedSearch.title"),fields:[{key:"lang",kind:"choice",label:k(e,"advancedSearch.lang"),options:I.map(e=>({label:e.label,value:e.value}))}]},data:{values:{lang:t}}}},onLangChanged:async function(e){let t,r,a=s(e.key)||"content.lang",n=s(e.value)||N;return n===N||B(n)||(n=N),await (t=a,r=JSON.stringify({value:n}),bridge.call("save_plugin_config",t,r)),{ok:!0,value:n}},onR18Changed:async function(e){let t,r,a=s(e.key)||"content.r18",n=!0===e.value||"true"===e.value;return await (t=a,r=JSON.stringify({value:n}),bridge.call("save_plugin_config",t,r)),{ok:!0,value:n}}};module.exports=t})();
1
+ (()=>{"use strict";var e={};e.d=(t,r,a)=>{var n=(r,a)=>{for(var n in r)e.o(r,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,[a]:r[n]})};n(r,"get"),n(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:()=>Q});let r="7efa2a7c-da0f-4db1-9167-98045ae37fdb",a="https://webtoons-static.pstatic.net/image/favicon/favicon.ico",n="https://m.webtoons.com/",i="https://www.webtoons.com",l="https://m.webtoons.com";function o(e){return!e||"object"!=typeof e||Array.isArray(e)?{}:e}function s(e){return String(null!=e?e:"").trim()}function c(e){return String(null!=e?e:"").replace(/[\s\u00a0\u3000]+$/u,"")}function u(e,t={},r={}){return{name:c(e),onTap:t,extern:r}}function d(e={}){var t,r,n,i,l;return{id:String(null!=(t=e.id)?t:""),url:String(null!=(r=e.url)?r:"").trim()||a,name:String(null!=(n=e.name)?n:""),path:String(null!=(i=e.path)?i:"").trim()||"placeholder/image-404.png",extern:null!=(l=e.extern)?l:{}}}let g=["en","zh-hant","zh-hans","th","id","es","fr","de"],p={"plugin.describe":"WEBTOON official web source","settings.section.content":"Content","settings.lang.label":"Default search language","settings.lang.followSystem":"Follow system (current: {lang})","settings.r18.label":"Show R18 / mature content","advancedSearch.title":"Advanced search","advancedSearch.lang":"Language","meta.author":"Author","meta.categories":"Genre","titleMeta.type":"Type: {type}","titleMeta.chapters":"Chapters: {count}","titleMeta.lang":"Language: {lang}","type.original":"Original","type.canvas":"Canvas","error.keywordRequired":"Please enter a search keyword","error.comicIdRequired":"comicId is required","error.noEpisodes":"No episodes available","error.noViewerLink":"Episode {id} is missing viewerLink","error.noImageList":"imageList not found on viewer page","error.emptyImageList":"imageList is empty","error.detailUrlEmpty":"Detail page URL is empty","error.cannotResolveDetail":"Cannot resolve detail URL (titleNo={titleNo}). Open again from search.","error.downloadFailed":"Download failed: {status} {statusText}","error.http":"HTTP {status}: {url}","error.r18Blocked":"This title is mature content. Enable R18 in plugin settings.","error.urlRequired":"url is required"},h={...p,"plugin.describe":"แหล่ง WEBTOON เว็บอย่างเป็นทางการ","settings.section.content":"เนื้อหา","settings.lang.label":"ภาษาค้นหาเริ่มต้น","settings.lang.followSystem":"ตามระบบ (ปัจจุบัน: {lang})","settings.r18.label":"แสดงเนื้อหา R18 / 18+","advancedSearch.title":"ค้นหาขั้นสูง","advancedSearch.lang":"ภาษา","meta.author":"ผู้แต่ง","meta.categories":"ประเภท","titleMeta.type":"ประเภท: {type}","titleMeta.chapters":"ตอน: {count}","titleMeta.lang":"ภาษา: {lang}","error.keywordRequired":"กรุณาใส่คำค้นหา","error.comicIdRequired":"ต้องระบุ comicId","error.noEpisodes":"ยังไม่มีตอน","error.r18Blocked":"เรื่องนี้เป็นเนื้อหาสำหรับผู้ใหญ่ เปิด R18 ในการตั้งค่าปลั๊กอิน"},m={...p,"plugin.describe":"Sumber web resmi WEBTOON","settings.section.content":"Konten","settings.lang.label":"Bahasa pencarian default","settings.lang.followSystem":"Ikuti sistem (saat ini: {lang})","settings.r18.label":"Tampilkan konten R18 / dewasa","advancedSearch.title":"Pencarian lanjutan","advancedSearch.lang":"Bahasa","meta.author":"Penulis","meta.categories":"Genre","titleMeta.type":"Tipe: {type}","titleMeta.chapters":"Episode: {count}","titleMeta.lang":"Bahasa: {lang}","error.keywordRequired":"Masukkan kata kunci pencarian","error.comicIdRequired":"comicId wajib diisi","error.noEpisodes":"Belum ada episode","error.r18Blocked":"Judul ini konten dewasa. Aktifkan R18 di pengaturan plugin."},f={...p,"plugin.describe":"Fuente web oficial de WEBTOON","settings.section.content":"Contenido","settings.lang.label":"Idioma de b\xfasqueda predeterminado","settings.lang.followSystem":"Seguir el sistema (actual: {lang})","settings.r18.label":"Mostrar contenido R18 / adulto","advancedSearch.title":"B\xfasqueda avanzada","advancedSearch.lang":"Idioma","meta.author":"Autor","meta.categories":"G\xe9nero","titleMeta.type":"Tipo: {type}","titleMeta.chapters":"Cap\xedtulos: {count}","titleMeta.lang":"Idioma: {lang}","error.keywordRequired":"Introduce una palabra clave","error.comicIdRequired":"comicId es obligatorio","error.noEpisodes":"No hay episodios","error.r18Blocked":"Este t\xedtulo es contenido adulto. Activa R18 en la configuraci\xf3n del plugin."},w={...p,"plugin.describe":"Source web officielle WEBTOON","settings.section.content":"Contenu","settings.lang.label":"Langue de recherche par d\xe9faut","settings.lang.followSystem":"Suivre le syst\xe8me (actuel : {lang})","settings.r18.label":"Afficher le contenu R18 / mature","advancedSearch.title":"Recherche avanc\xe9e","advancedSearch.lang":"Langue","meta.author":"Auteur","meta.categories":"Genre","titleMeta.type":"Type : {type}","titleMeta.chapters":"Chapitres : {count}","titleMeta.lang":"Langue : {lang}","error.keywordRequired":"Veuillez saisir un mot-cl\xe9","error.comicIdRequired":"comicId est requis","error.noEpisodes":"Aucun \xe9pisode disponible","error.r18Blocked":"Ce titre est r\xe9serv\xe9 aux adultes. Activez R18 dans les param\xe8tres du plugin."},y={...p,"plugin.describe":"Offizieller WEBTOON-Web-Quell","settings.section.content":"Inhalt","settings.lang.label":"Standard-Suchsprache","settings.lang.followSystem":"System folgen (aktuell: {lang})","settings.r18.label":"R18- / Mature-Inhalte anzeigen","advancedSearch.title":"Erweiterte Suche","advancedSearch.lang":"Sprache","meta.author":"Autor","meta.categories":"Genre","titleMeta.type":"Typ: {type}","titleMeta.chapters":"Kapitel: {count}","titleMeta.lang":"Sprache: {lang}","error.keywordRequired":"Bitte Suchbegriff eingeben","error.comicIdRequired":"comicId ist erforderlich","error.noEpisodes":"Keine Episoden verf\xfcgbar","error.r18Blocked":"Dieser Titel ist Mature-Inhalt. R18 in den Plugin-Einstellungen aktivieren."},v={en:p,"zh-hant":{"plugin.describe":"WEBTOON 官方 Web 端源","settings.section.content":"內容","settings.lang.label":"預設搜尋語言","settings.lang.followSystem":"跟隨系統(目前 {lang})","settings.r18.label":"顯示 R18 / 成人內容","advancedSearch.title":"進階搜尋","advancedSearch.lang":"語言","meta.author":"作者","meta.categories":"分類","titleMeta.type":"類型:{type}","titleMeta.chapters":"章節:{count}","titleMeta.lang":"語言:{lang}","type.original":"Original","type.canvas":"Canvas","error.keywordRequired":"請輸入搜尋關鍵字","error.comicIdRequired":"comicId 不能為空","error.noEpisodes":"該作品暫無章節","error.noViewerLink":"章節 {id} 缺少 viewerLink","error.noImageList":"未在 viewer 頁面找到 imageList","error.emptyImageList":"imageList 為空","error.detailUrlEmpty":"詳情頁 URL 為空","error.cannotResolveDetail":"無法解析詳情頁 URL (titleNo={titleNo}),請從搜尋結果重新開啟","error.downloadFailed":"下載失敗:{status} {statusText}","error.http":"HTTP {status}: {url}","error.r18Blocked":"此作品為成人內容,請在外掛設定中開啟 R18","error.urlRequired":"url 不能為空"},"zh-hans":{"plugin.describe":"WEBTOON 官方 Web 端源","settings.section.content":"内容","settings.lang.label":"默认搜索语言","settings.lang.followSystem":"跟随系统(当前 {lang})","settings.r18.label":"显示 R18 / 成人内容","advancedSearch.title":"高级搜索","advancedSearch.lang":"语言","meta.author":"作者","meta.categories":"分类","titleMeta.type":"类型:{type}","titleMeta.chapters":"章节:{count}","titleMeta.lang":"语言:{lang}","type.original":"Original","type.canvas":"Canvas","error.keywordRequired":"请输入搜索关键词","error.comicIdRequired":"comicId 不能为空","error.noEpisodes":"该作品暂无章节","error.noViewerLink":"章节 {id} 缺少 viewerLink","error.noImageList":"未在 viewer 页面找到 imageList","error.emptyImageList":"imageList 为空","error.detailUrlEmpty":"详情页 URL 为空","error.cannotResolveDetail":"无法解析详情页 URL (titleNo={titleNo}),请从搜索结果重新打开","error.downloadFailed":"下载失败:{status} {statusText}","error.http":"HTTP {status}: {url}","error.r18Blocked":"此作品为成人内容,请在插件设置中开启 R18","error.urlRequired":"url 不能为空"},th:h,id:m,es:f,fr:w,de:y};async function b(){try{let e=globalThis.bridge;if("function"!=typeof(null==e?void 0:e.call))return"";let t=await Promise.resolve(e.call("dart.getLocaleInfo")),r="string"==typeof t?t:JSON.stringify(null!=t?t:"");if(!r)return"";let a=JSON.parse(r);return s(a.locale)||s(a.systemLocale)||s(a.language)||""}catch{return""}}async function S(){let e=s(await b()).toLowerCase().replace(/_/g,"-");if(!e)return"en";if(g.includes(e))return e;if(e.startsWith("zh"))return e.includes("hant")||e.includes("tw")||e.includes("hk")||e.includes("mo")?"zh-hant":"zh-hans";let t=e.split("-")[0]||"";return g.includes(t)?t:"en"}function k(e,t,r){var a,n;let i=null!=(a=null!=(n=(v[e]||p)[t])?n:p[t])?a:t;if(r)for(let[e,t]of Object.entries(r))i=i.replace(RegExp(`\\{${e}\\}`,"g"),String(t));return i}async function R(){return{name:"WEBTOON",uuid:r,iconUrl:"https://webtoons-static.pstatic.net/image/favicon/favicon.ico",creator:{name:"",describe:""},describe:k(await S(),"plugin.describe"),version:"0.0.2",home:"https://www.webtoons.com",updateUrl:"",npmName:"breeze-plugin-webtoon",function:[]}}let L=[{label:"English",value:"en"},{label:"中文 (繁體)",value:"zh-hant"},{label:"ภาษาไทย",value:"th"},{label:"Indonesia",value:"id"},{label:"Espa\xf1ol",value:"es"},{label:"Fran\xe7ais",value:"fr"},{label:"Deutsch",value:"de"}],I=new Set(L.map(e=>e.value)),N="auto",x="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36";function E(e){return`ageGatePass=${e?"true":"false"}; needGDPR=false`}function M(e=!1){return{"User-Agent":x,Referer:n,"Accept-Language":"en-US,en;q=0.9",Cookie:E(e)}}function O(e=!1){return{"User-Agent":"Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36",Referer:n,"Accept-Language":"en-US,en;q=0.9",Cookie:E(e)}}async function C(e,t,r=2e4,a="en"){let n=await fetch(e,{method:"GET",headers:t,signal:AbortSignal.timeout(r)});if(!n.ok)throw Error(k(a,"error.http",{status:n.status,url:e}));return n.text()}async function T(e,t,r=2e4,a="en"){return JSON.parse(await C(e,t,r,a))}async function q(){try{let e=await ((e,t="")=>bridge.call("load_plugin_config",e,t))("content.r18","");if(!e)return!1;let t=JSON.parse(e);return!0===t.value||"true"===t.value}catch{return!1}}function B(e){return I.has(e)}async function $(){let e=await b();if(!e)return"en";let t=s(e).toLowerCase().replace(/_/g,"-");if(!t)return"en";if(B(t))return t;if(t.startsWith("zh"))return t.includes("hant")||t.includes("tw")||t.includes("hk")||t.includes("mo"),"zh-hant";let r=t.split("-")[0]||"";return B(r)?r:"en"}async function A(){try{let e=await ((e,t="")=>bridge.call("load_plugin_config",e,t))("content.lang","");if(!e)return N;let t=JSON.parse(e),r=s(t.value);if(!r||r===N)return N;if(B(r))return r;return N}catch{return N}}async function _(){let e=await A();return e!==N&&B(e)?e:$()}function U(e){let t=e.href||"";return[e.lang,e.type,e.titleNo,t].map(e=>encodeURIComponent(e)).join("|")}function W(e,t="en"){let r=s(e);if(!r)throw Error("comicId 不能为空");if(r.includes("|")){let a=r.split("|").map(e=>{try{return decodeURIComponent(e)}catch{return e}}),n=a[0]||t,i="canvas"===a[1]?"canvas":"webtoon",l=a[2]||"",o=a[3]||"";if(!l)throw Error(`无效 comicId: ${e}`);return{lang:n,type:i,titleNo:l,href:o}}return{lang:t,type:"webtoon",titleNo:r,href:""}}function z(e){let t=s(e).toLowerCase();return t.includes("/canvas/")||t.includes("/challenge/")||t.includes("episodelist/challenge")||t.includes("type=challenge")||t.includes("type=canvas")?"canvas":"webtoon"}function P(e){let t=s(e);return t?t.startsWith("http://")||t.startsWith("https://")?t:t.startsWith("/")?`${i}${t}`:t:""}function j(e){let t=s(e);return t?t.startsWith("http://")||t.startsWith("https://")?t:t.startsWith("/")?`${l}${t}`:`${l}/${t}`:""}function D(e,t,a,n){let i=a.map(e=>c(e).trimStart()).map(e=>e.trim()).filter(Boolean);return i.length?{type:e,name:c(t),value:i.map(e=>u(e,{type:"openSearch",payload:{source:r,keyword:e,extern:n?{lang:n}:{}}}))}:null}async function G(e,t,n=1,l={}){var o;let u=!!l.allowR18,g=null!=(o=l.uiLang)?o:"en",p=new URL(`${i}/${t}/search`);p.searchParams.set("keyword",e),p.searchParams.set("page",String(n));let h=await C(p.toString(),M(u),2e4,g),m=BreezeHtml.load(h),f=[];return m(".webtoon_list li a").each((e,n)=>{let i=m(n),l=c(i.find(".title").text()).trim(),o=c(i.find(".author").text()).trim(),p=P(s(i.attr("href"))),h=s(i.find("img").attr("src")),w=s(i.attr("data-title-no"));if(!l||!w)return;let y=function(e){var t;if(e.find(".ico_age19, .age19, .ico_mature, .mature").length>0)return!0;let r=s(e.attr("class")).toLowerCase();if(r.includes("age19")||r.includes("mature"))return!0;let a=s(null!=(t=e.html())?t:"").toLowerCase();return!!(a.includes("ico_age19")||a.includes("age19")||a.includes("grade19")||a.includes("mature"))}(i);if(y&&!u)return;let v=z(p),b=U({titleNo:w,type:v,lang:t,href:p}),S=`comic/${w}/cover.jpg`;f.push({source:r,id:b,title:l,subtitle:o,finished:!1,likesCount:0,viewsCount:0,updatedAt:"",cover:d({id:w,url:h||a,name:"cover.jpg",path:S,extern:{}}),metadata:[D("author",k(g,"meta.author"),o?[o]:[],t)].filter(e=>null!=e),raw:{title:l,author:o,href:p,img:h,titleNo:w,type:v,lang:t,mature:y},extern:{href:p,type:v,lang:t,titleNo:w,mature:y}})}),{results:f,hasNext:m("a.pagination[aria-current=true] + a").length>0}}async function K(e,t={}){var r;let a,n=!!t.allowR18,i=null!=(r=t.uiLang)?r:"en",l=P(e);if(!l)throw Error(k(i,"error.detailUrlEmpty"));let o=await C(l,M(n),2e4,i),u=(a=o.toLowerCase()).includes("ico_age19")||a.includes("agegate")||a.includes("age_gate")||a.includes("mature")||/grade\s*[=:]\s*["']?19/.test(a);if(u&&!n)throw Error(k(i,"error.r18Blocked"));let d=BreezeHtml.load(o),g=c(d("h1.subj, h3.subj").first().text()).trim(),p=c(d(".detail_header .info .author_area").first().text().replace(/author info/gi,"")).replace(/\s+/g," ").trim(),h=[];d(".detail_header .info .genre").each((e,t)=>{let r=c(d(t).text()).trim();r&&h.push(r)});let m=c(d("#_asideDetail p.summary").text()).trim()||c(d(".detail_header p.summary").text()).trim(),f=s(d(".detail_header .thmb img").attr("src"))||s(d('head meta[property="og:image"]').attr("content")),w="";try{w=new URL(l).searchParams.get("title_no")||""}catch{w=""}return{title:g,author:p,genre:h.join(", "),summary:m,thumbnail:f,titleNo:w,url:l,mature:u}}async function J(e,t="webtoon",r="en",a={}){var n,i;let o=!!a.allowR18,s=null!=(n=a.uiLang)?n:"en",c=new URL(`${l}/api/v1/${t}/${e}/episodes`);c.searchParams.set("pageSize","99999"),"canvas"===t&&c.searchParams.set("readingLanguageCode",r);let u=await T(c.toString(),O(o),2e4,s),d=null==u||null==(i=u.result)?void 0:i.episodeList;return Array.isArray(d)?d:[]}async function F(e,t={}){var r;let a=!!t.allowR18,n=null!=(r=t.uiLang)?r:"en",i=j(e);if(!i)throw Error(k(n,"error.noViewerLink",{id:"?"}));let l=(await C(i,O(a),2e4,n)).match(/var\s+imageList\s*=\s*(\[[\s\S]*?\]);/);if(!l)throw Error(k(n,"error.noImageList"));let o=JSON.parse(l[1].replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g,'$1"$2":'));if(!Array.isArray(o)||0===o.length)throw Error(k(n,"error.emptyImageList"));return o.sort((e,t)=>{var r,a;return Number(null!=(r=e.sortOrder)?r:0)-Number(null!=(a=t.sortOrder)?a:0)}),{viewerUrl:i,imageList:o}}async function V(e,t={}){var r;let a=null!=(r=t.uiLang)?r:"en";if(e.href)return P(e.href);let n=await J(e.titleNo,e.type,e.lang,t);if(n.length>0){let e=function(e){let t=j(e);if(!t)return"";try{let e=new URL(t),r=e.pathname.split("/").filter(Boolean);if(r.length>=3){let t=e.searchParams.get("title_no")||"";return`${i}/${r[0]}/${r[1]}/${r[2]}/list?title_no=${t}`}}catch{}return""}(n[0].viewerLink);if(e)return e}throw Error(k(a,"error.cannotResolveDetail",{titleNo:e.titleNo}))}async function H(e={}){let t=await S(),n=await q(),i=s(e.comicId);if(!i)throw Error(k(t,"error.comicIdRequired"));let l=W(i,await _()),g=o(e.extern),p={allowR18:n,uiLang:t};s(g.href)&&(l.href=s(g.href)),"canvas"===s(g.type)&&(l.type="canvas"),s(g.lang)&&(l.lang=s(g.lang));let h=await V(l,p);l.href=h,l.type=z(h);let[m,f]=await Promise.all([K(h,p),J(l.titleNo,l.type,l.lang,p)]);m.titleNo&&(l.titleNo=m.titleNo);let w=U(l),y=f.map((e,t)=>{var r,a;let n=String(e.episodeNo),i=s(e.viewerLink);return{id:n,requestId:n,logicalKey:n,storageChapterId:n,name:s(e.episodeTitle)||`Ep. ${e.episodeNo}`,order:t+1,extern:{comicId:w,episodeNo:e.episodeNo,viewerLink:i,thumbnail:null!=(r=e.thumbnail)?r:"",exposureDateMillis:null!=(a=e.exposureDateMillis)?a:0}}}),v=m.genre?m.genre.split(",").map(e=>e.trim()).filter(Boolean):[],b=k(t,"canvas"===l.type?"type.canvas":"type.original");return{source:r,comicId:w,extern:{...g,href:h,type:l.type,lang:l.lang,titleNo:l.titleNo,mature:m.mature},scheme:{version:"1.0.0",type:"comicDetail",source:r},data:{normal:{comicInfo:{id:w,title:m.title||`WEBTOON #${l.titleNo}`,titleMeta:[k(t,"titleMeta.type",{type:b}),k(t,"titleMeta.chapters",{count:y.length}),k(t,"titleMeta.lang",{lang:l.lang})].map(e=>c(e)).filter(e=>e.length>0).map(e=>u(e)),creator:{id:"",name:"",avatar:{id:"",url:"",name:"",path:"",extern:{}},onTap:{},extern:{}},description:m.summary||"",cover:d({id:l.titleNo,url:m.thumbnail||a,name:"cover.jpg",path:`comic/${l.titleNo}/cover.jpg`}),metadata:[D("author",k(t,"meta.author"),m.author?[m.author]:[],l.lang),D("categories",k(t,"meta.categories"),v,l.lang)].filter(e=>null!=e),extern:{href:h,type:l.type,lang:l.lang,titleNo:l.titleNo,mature:m.mature}},eps:y,recommend:[],totalViews:0,totalLikes:0,totalComments:0,isFavourite:!1,isLiked:!1,allowComments:!1,allowLike:!1,allowCollected:!1,allowDownload:!0,extern:{href:h,type:l.type,lang:l.lang,titleNo:l.titleNo,mature:m.mature}},raw:{detail:m,episodes:f,parts:l}}}}async function Z(e){var t,r,a,n;let i=await S(),l=await q(),c=s(e.comicId);if(!c)throw Error(k(i,"error.comicIdRequired"));let u=await H({comicId:c,extern:e.extern}),d=u.data.normal.eps;if(!d.length)throw Error(k(i,"error.noEpisodes"));let g=s(e.chapterId),p=null!=(t=d.find(e=>e.requestId===g||e.id===g))?t:d[0],h=o(p.extern),m=s(h.viewerLink);if(!m){let e=W(c,await _()),t=(await J(e.titleNo,e.type,e.lang,{allowR18:l,uiLang:i})).find(e=>String(e.episodeNo)===p.id);m=s(null==t?void 0:t.viewerLink)}if(!m)throw Error(k(i,"error.noViewerLink",{id:p.id}));let{imageList:f}=await F(m,{allowR18:l,uiLang:i}),w=(a=u.comicId,n=p.storageChapterId,f.map((e,t)=>{var r,i,l;let o=s(e.url),c=function(e,t){try{let t=new URL(e).pathname.split("/").filter(Boolean).pop()||"";if(t)return t}catch{}return`${String(t+1).padStart(4,"0")}.jpg`}(o,t);return{id:`${n}-p-${t}`,name:c,path:`comic/${a}/${n}/${c}`,url:o,extern:{width:null!=(r=e.width)?r:0,height:null!=(i=e.height)?i:0,sortOrder:null!=(l=e.sortOrder)?l:t}}}));return{comicId:u.comicId,title:u.data.normal.comicInfo.title,chapter:{...p,pages:w,extern:{...h,viewerLink:m}},chapters:d,extern:null!=(r=e.extern)?r:null}}let Q={getInfo:async function(){return await R()},searchComic:async function(e={}){var t,a;let n=await S(),i=await q(),l=o(e.extern),c=Math.max(1,Number(null!=(t=e.page)?t:1)||1),u=s(null!=(a=e.keyword)?a:l.keyword);if(!u)throw Error(k(n,"error.keywordRequired"));let d=await _(),g=s(l.lang),p=(g&&B(g)?g:"")||d||"en",{results:h,hasNext:m}=await G(u,p,c,{allowR18:i,uiLang:n}),f=function(e=1,t=1,r=0,a=!0){return{page:e,pages:Math.max(1,t),total:r,hasReachedMax:a}}(c,m?c+1:c,h.length,!m);return{source:r,extern:{...l,keyword:u,lang:p,page:c},scheme:{version:"1.0.0",type:"searchResult",source:r,list:"comicGrid"},data:{paging:f,items:h},paging:f,items:h}},getComicDetail:H,getChapter:async function(e={}){let t=await Z(e);return{source:r,comicId:t.comicId,chapterId:t.chapter.id,extern:t.extern,scheme:{version:"1.0.0",type:"chapterContent",source:r},data:{comic:{id:t.comicId,source:r,title:t.title,extern:{}},chapter:t.chapter,chapters:t.chapters.map(e=>({id:e.id,requestId:e.requestId,logicalKey:e.logicalKey,storageChapterId:e.storageChapterId,name:e.name,order:e.order,extern:e.extern}))}}},getReadSnapshot:async function(e={}){let t=await Z(e);return{source:r,extern:t.extern,data:{comic:{id:t.comicId,source:r,title:t.title,extern:{}},chapter:t.chapter,chapters:t.chapters.map(e=>({id:e.id,name:e.name,order:e.order,extern:e.extern}))}}},fetchImageBytes:async function(e={}){var t;let r,a=await S(),i=await q(),l=s(e.url);if(!l)throw Error(k(a,"error.urlRequired"));let o=Number(null!=(t=e.timeoutMs)?t:3e4)||3e4,c=s(e.taskGroupKey);if(c&&await (r=c,bridge.call("runtime.is_task_group_cancelled",r)))return new Uint8Array(0);let u=await fetch(l,{method:"GET",headers:{"User-Agent":x,Referer:n,Cookie:E(i),"x-rquickjs-host-offload-binary-v1":"1"},signal:AbortSignal.timeout(o)});if(!u.ok)throw Error(k(a,"error.downloadFailed",{status:u.status,statusText:u.statusText}));return new Uint8Array(await u.arrayBuffer())},getSettingsBundle:async function(){let e=await S(),t=await A(),a=await _(),n=await q();return{source:r,scheme:{version:"1.0.0",type:"settings",sections:[{title:k(e,"settings.section.content"),fields:[{key:"content.lang",kind:"choice",label:k(e,"settings.lang.label"),options:[{label:k(e,"settings.lang.followSystem",{lang:a}),value:N},...L.map(e=>({label:e.label,value:e.value}))],fnPath:"onLangChanged",persist:!0},{key:"content.r18",kind:"switch",label:k(e,"settings.r18.label"),fnPath:"onR18Changed",persist:!0}]}]},data:{canShowUserInfo:!1,values:{"content.lang":t,"content.r18":n}}}},getCapabilitiesBundle:async function(){return{source:r,scheme:{version:"1.0.0",type:"capabilities",actions:[]},data:{}}},getAdvancedSearchScheme:async function(){let e=await S(),t=await _();return{source:r,scheme:{version:"1.0.0",type:"advancedSearch",title:k(e,"advancedSearch.title"),fields:[{key:"lang",kind:"choice",label:k(e,"advancedSearch.lang"),options:L.map(e=>({label:e.label,value:e.value}))}]},data:{values:{lang:t}}}},onLangChanged:async function(e){let t,r,a=s(e.key)||"content.lang",n=s(e.value)||N;return n===N||B(n)||(n=N),await (t=a,r=JSON.stringify({value:n}),bridge.call("save_plugin_config",t,r)),{ok:!0,value:n}},onR18Changed:async function(e){let t,r,a=s(e.key)||"content.r18",n=!0===e.value||"true"===e.value;return await (t=a,r=JSON.stringify({value:n}),bridge.call("save_plugin_config",t,r)),{ok:!0,value:n}}};module.exports=t})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "breeze-plugin-webtoon",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist"