@serifpersia/dango 3.5.2 → 3.5.3
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 +1 -1
- package/client/dist/assets/{AnimeCard-BVnAhrys.js → AnimeCard-B-Oa1rwo.js} +1 -1
- package/client/dist/assets/{AnimeInfo-DYBLIXmE.js → AnimeInfo-ChlZYgUR.js} +1 -1
- package/client/dist/assets/{AnimeInfoPage-DnXV4EMC.js → AnimeInfoPage-c5D-TJex.js} +2 -2
- package/client/dist/assets/{Asmr-Dwlv-Af8.js → Asmr-DXqSpC1N.js} +1 -1
- package/client/dist/assets/{AsmrResetProgressModal-CnF9ZTJQ.js → AsmrResetProgressModal-CMpmRa0N.js} +1 -1
- package/client/dist/assets/{AvSyncCalibrator-Cr9n1euF.js → AvSyncCalibrator-CuSfq8JX.js} +1 -1
- package/client/dist/assets/{Home-CUZPz_wy.js → Home-BU6A-hSp.js} +1 -1
- package/client/dist/assets/{Insights-hvaO1jbY.js → Insights-C2tEbstb.js} +1 -1
- package/client/dist/assets/{LibraryListPage-BeYz_I1y.js → LibraryListPage-BORCPjkW.js} +1 -1
- package/client/dist/assets/{ListeningList-D-D-W7JK.js → ListeningList-2m-nFdkp.js} +1 -1
- package/client/dist/assets/{Manga-DqIR2B6F.js → Manga-D5Jc19s1.js} +1 -1
- package/client/dist/assets/{MangaInfoPage-CWqxWbb3.js → MangaInfoPage-D4Yhgxsy.js} +1 -1
- package/client/dist/assets/{MangaReadPage-BlyJ-OdY.js → MangaReadPage-CSu-78zV.js} +1 -1
- package/client/dist/assets/{MangaResetProgressModal-gvz9_X7z.js → MangaResetProgressModal-CPzxCgcw.js} +1 -1
- package/client/dist/assets/{Mature-B1Cuj67a.js → Mature-x0I86Cnl.js} +1 -1
- package/client/dist/assets/{MediaCard-GwFTnacn.js → MediaCard-BNKk3aKd.js} +1 -1
- package/client/dist/assets/{Music-BEmRDuSo.js → Music-CX8iz56E.js} +1 -1
- package/client/dist/assets/{OptionListMenu-Dlk9eHM7.js → OptionListMenu-C6gay-Rv.js} +1 -1
- package/client/dist/assets/{Player-khTFa_o1.js → Player-qmH7gErX.js} +2 -2
- package/client/dist/assets/{PlayerSettings-B16FnAO_.js → PlayerSettings-C5IY-55v.js} +1 -1
- package/client/dist/assets/{QueueOptionsButton-DjBOibpt.js → QueueOptionsButton-CUt4vxlJ.js} +1 -1
- package/client/dist/assets/{QueueRail-DcLtEU46.js → QueueRail-DR9j0mJ7.js} +1 -1
- package/client/dist/assets/{Radio-rpaFuI72.js → Radio-DRNP3-Ug.js} +1 -1
- package/client/dist/assets/{ReadingList-DTnI5411.js → ReadingList-1UBbcIwL.js} +1 -1
- package/client/dist/assets/{ResetProgressModal-Bcv92v7c.js → ResetProgressModal-CxuA9Z7G.js} +1 -1
- package/client/dist/assets/{Search-DNxPl_On.js → Search-hVoQWcPJ.js} +1 -1
- package/client/dist/assets/{Settings-CQ-ykTG3.js → Settings-Bao74HiY.js} +1 -1
- package/client/dist/assets/{SkeletonGrid-ZN-kS9re.js → SkeletonGrid-B-ot2T5l.js} +1 -1
- package/client/dist/assets/{Trackers-EN1_ol5G.js → Trackers-RoIuI_sy.js} +1 -1
- package/client/dist/assets/{Tv-C-4wd-BS.js → Tv-CstPX8fN.js} +1 -1
- package/client/dist/assets/{TvInfo-Mpzun3PF.js → TvInfo-DaIK2hX4.js} +1 -1
- package/client/dist/assets/{TvPopup-YYgg9-7r.js → TvPopup-kZmcSBvG.js} +1 -1
- package/client/dist/assets/{TvSearch-CdL9EA-S.js → TvSearch-_tF8ou7f.js} +1 -1
- package/client/dist/assets/{TvWatchlist-DD6nRESU.js → TvWatchlist-B5rZ7zIT.js} +1 -1
- package/client/dist/assets/{Watchlist-CD8UqukO.js → Watchlist-aQitaI7a.js} +1 -1
- package/client/dist/assets/{hls-E94cMCjR.js → hls-hQKRlWEn.js} +1 -1
- package/client/dist/assets/{index-CZW1But9.js → index-mwdRstuO.js} +2 -2
- package/client/dist/assets/{useAnimeInfoData-C9tOyy6E.js → useAnimeInfoData-Cs0pIdnP.js} +1 -1
- package/client/dist/assets/{useAsmr-B4HAapZD.js → useAsmr-D8s--Tjy.js} +1 -1
- package/client/dist/assets/{useAsmrPopup-trIV7nUr.js → useAsmrPopup-Bf8gDlT6.js} +1 -1
- package/client/dist/assets/{useMangaLibrary-CZ2Gke8p.js → useMangaLibrary-Mm8wandT.js} +1 -1
- package/client/dist/assets/{useMangaPopup-80Daa4y-.js → useMangaPopup-DgtQ9fg4.js} +1 -1
- package/client/dist/assets/{useProviders-CqMq_6ue.js → useProviders-B-x6Wq6v.js} +1 -1
- package/client/dist/assets/{useTv-CHDhiKWu.js → useTv-B2zlWz3p.js} +1 -1
- package/client/dist/assets/{useTvLibrary-DWUGDtld.js → useTvLibrary-DDW03W6A.js} +1 -1
- package/client/dist/index.html +1 -1
- package/package.json +2 -2
- package/server/dist/lib/ytmusic.js +28 -2
- package/server/dist/trpc/routers/music.js +25 -3
- package/server/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as u,c as b,u as g,a as c}from"./vendor-query-BBT5_sHx.js";import{t as p,h as i,z as s}from"./index-
|
|
1
|
+
import{b as u,c as b,u as g,a as c}from"./vendor-query-BBT5_sHx.js";import{t as p,h as i,z as s}from"./index-mwdRstuO.js";import{T as Q}from"./vendor-core-DfaOB3Rn.js";const v=300*1e3,M={mangadex:"https://mangadex.org/",mangapill:"https://www.mangapill.com/"},f=(e,a)=>`/api/proxy?url=${encodeURIComponent(a)}&referer=${encodeURIComponent(M[e])}`,T=(e,a)=>a&&(e==="mangapill"?f(e,a):a),k=(e,a=!0)=>{const{provider:r,query:n,page:o,sort:t,status:m,type:d,rating:y,mature:l}=e;return u({queryKey:["mangaBrowse",r,n,o,t,m,d,y,l],queryFn:()=>p.manga.search.query({provider:r,q:n.trim()||void 0,page:o,sort:t||void 0,status:m||void 0,type:d||void 0,rating:y||void 0,mature:l?"1":void 0}),staleTime:v,enabled:a&&!!r})},E=(e,a=14)=>{const{provider:r,query:n,sort:o,status:t,type:m,rating:d,mature:y}=e;return b({queryKey:["mangaBrowseInfinite",r,n,o,t,m,d,y,a],queryFn:({pageParam:l=1})=>p.manga.search.query({provider:r,q:n.trim()||void 0,page:l,limit:a,sort:o||void 0,status:t||void 0,type:m||void 0,rating:d||void 0,mature:y?"1":void 0}),initialPageParam:1,getNextPageParam:(l,q)=>l.hasNext?q.length+1:void 0,staleTime:v,enabled:!!r})},O=(e,a,r="safe",n=!1)=>u({queryKey:["mangaDetail",e,a,r,n],queryFn:()=>p.manga.info.query({provider:e||"",id:a||"",rating:r,mature:n?"1":void 0}),enabled:!!e&&!!a,staleTime:v}),$=(e,a,r)=>u({queryKey:["mangaPages",e,a],queryFn:()=>p.manga.pages.query({provider:e||"",id:a||""}),enabled:!!e&&!!a,staleTime:1800*1e3}),B=()=>{const e=i();return u({...e.manga.trending.queryOptions(),staleTime:600*1e3,retry:1})},I=e=>e.contentRating==="erotica"||e.contentRating==="pornographic"||e.type==="doujinshi";function N(e,a){const r=e.titles??{};return a==="englishName"?r.en||e.title:a==="nativeName"&&(r.native||r.romaji||e.altTitle)||e.title}function A(e){return{englishName:e.titles?.en??e.title,nativeName:e.titles?.native??e.titles?.romaji??e.altTitle??void 0}}const h=/^anilist:ch:(\d+)$/;function w(e){if(!e)return null;const a=h.exec(e.trim());if(!a)return null;const r=Number.parseInt(a[1],10);return Number.isFinite(r)?r:null}function x(e,a){const r=String(a),n=e.find(o=>(o.number??"").trim()===r);return n||(e.find(o=>{const t=Number.parseFloat((o.number??"").trim());return Number.isFinite(t)&&t===a})??null)}const _=["Reading","Completed","On-Hold","Dropped","Planned"],L=(e,a)=>`${e.toLowerCase()}:${a}`,D=(e="All",a=1,r=24)=>{const n=i();return u(n.mangaLibrary.list.queryOptions({status:e,page:a,limit:r}))},P=()=>{const e=i();return u({...e.mangaLibrary.ids.queryOptions(),staleTime:1e3*60})},U=e=>{const a=i();return u({...a.mangaLibrary.check.queryOptions({id:e??""}),enabled:!!e,staleTime:1e3*60})},j=e=>{const a=i();return u({...a.mangaLibrary.entry.queryOptions({id:e??""}),enabled:!!e,staleTime:1e3*60})},H=()=>{const e=i(),a=g();return c(e.mangaLibrary.link.mutationOptions({onSuccess:r=>{s.success(r?.progressMigrated?"Linked — chapter progress carried over":"Linked to AniList entry"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to link: ${r.message}`)}}))},z=(e=24)=>{const a=i();return u(a.mangaProgress.continueReading.queryOptions({limit:e}))},V=e=>{const a=i();return u({...a.mangaProgress.byManga.queryOptions({mangaId:e??""}),enabled:!!e})},S=()=>{const e=i(),a=g();return c(e.mangaLibrary.add.mutationOptions({onSuccess:(r,n)=>{n.silent||s.success("Bookmarked"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]})},onError:r=>{s.error(`Failed to bookmark: ${r.message}`)}}))},F=()=>{const e=i(),a=g();return c(e.mangaLibrary.remove.mutationOptions({onSuccess:()=>{s.success("Bookmark removed"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to remove: ${r.message}`)}}))},Y=()=>{const e=i(),a=g();return c(e.mangaLibrary.setStatus.mutationOptions({onSuccess:()=>{s.success("Status updated"),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to update status: ${r.message}`)}}))},G=()=>{const e=i(),a=g();return c(e.mangaProgress.save.mutationOptions({onSuccess:(r,n)=>{a.invalidateQueries({queryKey:["manga-progress",n.mangaId]}),a.invalidateQueries({queryKey:["manga-continue-reading"]}),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries(e.mangaProgress.pathFilter())}}))},J=()=>{const e=i(),a=g();return c(e.mangaProgress.remove.mutationOptions({onSuccess:()=>{s.success("Progress reset"),a.invalidateQueries({queryKey:["manga-progress"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]}),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries(e.mangaProgress.pathFilter())},onError:r=>{s.error(`Failed to reset progress: ${r.message}`)}}))},W=()=>{const e=i(),a=g();return c(e.mangaLibrary.batchStatus.mutationOptions({onSuccess:r=>{s.success(`Status updated for ${r.updated??0} items`),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to update statuses: ${r.message}`)}}))},X=()=>{const e=i(),a=g();return c(e.mangaLibrary.removeMany.mutationOptions({onSuccess:r=>{const n=r.removed??0;s.success(`Removed ${n} ${n===1?"item":"items"} from reading list`),a.invalidateQueries(e.mangaLibrary.pathFilter()),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]})},onError:r=>{s.error(`Failed to remove: ${r.message}`)}}))},Z=()=>{const e=i(),a=g();return c(e.mangaProgress.removeMany.mutationOptions({onSuccess:r=>{const n=r.removed??0;s.success(`Reset progress for ${n} ${n===1?"item":"items"}`),a.invalidateQueries({queryKey:["manga-progress"]}),a.invalidateQueries({queryKey:["manga-continue-reading"]}),a.invalidateQueries({queryKey:["manga-library"]}),a.invalidateQueries(e.mangaProgress.pathFilter())},onError:r=>{s.error(`Failed to reset progress: ${r.message}`)}}))},ee=()=>{const e=S(),a=F(),{data:r}=P(),n=Q(()=>new Set(r?.ids||[]),[r]);return{toggle:t=>{const m=L(t.provider,t.id);n.has(m)?a.mutate(m):e.mutate({provider:t.provider,mangaId:t.id,title:t.title,cover:t.cover,altTitle:t.altTitle,contentRating:t.contentRating})},bookmarkedIds:n,pending:e.isPending||a.isPending}};export{Z as A,J as B,_ as M,E as a,T as b,A as c,z as d,B as e,k as f,j as g,S as h,I as i,H as j,O as k,U as l,L as m,V as n,F as o,Y as p,w as q,N as r,x as s,$ as t,ee as u,f as v,G as w,D as x,W as y,X as z};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{u as e,S as f,L as m}from"./vendor-core-DfaOB3Rn.js";import{I as l}from"./vendor-icons-DrybRNxP.js";import{k as y,r as T}from"./useMangaLibrary-
|
|
1
|
+
import{u as e,S as f,L as m}from"./vendor-core-DfaOB3Rn.js";import{I as l}from"./vendor-icons-DrybRNxP.js";import{k as y,r as T}from"./useMangaLibrary-Mm8wandT.js";import{d as I}from"./index-mwdRstuO.js";import{p as s,a as k}from"./MediaCard-BNKk3aKd.js";import{u as P}from"./usePopup-DS9jMzp6.js";const R=({data:i,anchorRect:d,bookmarked:r,onToggleBookmark:p,onMouseEnter:h,onMouseLeave:v,onRequestClose:g})=>{const{data:a,isLoading:N}=y(i.provider,i.mangaId,i.rating||"safe",i.mature||!1),{titlePreference:u}=I(),t=a?.chapters.length??0,c=[a?.status,a?.type].filter(Boolean).join(" · "),o=T({title:i.title,altTitle:a?.altTitle??i.altTitle},u);return e(k,{anchorRect:d,onMouseEnter:h,onMouseLeave:v,onRequestClose:g,children:N?e("div",{className:s.loading,children:[e("div",{className:s.spinner}),e("span",{children:"Fetching details..."})]}):e(f,{children:[e("div",{className:s.header,children:[e("div",{className:s.title,children:o}),a?.altTitle&&a.altTitle!==o&&e("div",{className:s.synopsis,children:["Also known as: ",a.altTitle]})]}),e("div",{className:s.body,children:[e("div",{className:s.metaRow,children:[c&&e("div",{className:s.metaItem,children:[e(l,{name:"book",size:14}),e("span",{children:c})]}),t>0&&e("div",{className:s.metaItem,children:e("span",{children:[t," chapter",t===1?"":"s"]})}),i.progressLabel&&e("div",{className:s.metaItem,children:[e(l,{name:"bookmark",size:12}),e("span",{children:i.progressLabel})]})]}),e("div",{className:s.synopsis,children:a?.description?a.description:"No synopsis available."}),Array.isArray(a?.genres)&&(a?.genres?.length??0)>0&&e("div",{className:s.details,children:e("div",{className:s.genres,children:a.genres.filter(Boolean).slice(0,4).map(n=>e("span",{className:s.genre,children:n},n))})})]}),e("div",{className:s.footer,children:[e("div",{className:s.primaryAction,children:e(m,{to:i.readTarget,className:s.watchBtn,children:[e(l,{name:"book",size:14}),"Read now"]})}),e("div",{className:s.secondaryActions,children:[e("button",{className:`${s.watchlistBtn} ${r?s.active:""}`,onClick:n=>{n.preventDefault(),n.stopPropagation(),p()},children:[r?e(l,{name:"check",size:12}):e(l,{name:"plus",size:12}),e("span",{children:r?"Remove":"Bookmark"})]}),e(m,{to:`/manga/${i.provider}/${encodeURIComponent(i.mangaId)}`,className:s.detailsBtn,children:"Read more"})]})]})]})})},$=()=>P();export{R as M,$ as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{T as o}from"./vendor-core-DfaOB3Rn.js";import{b as a}from"./vendor-query-BBT5_sHx.js";import{U as i}from"./index-
|
|
1
|
+
import{T as o}from"./vendor-core-DfaOB3Rn.js";import{b as a}from"./vendor-query-BBT5_sHx.js";import{U as i}from"./index-mwdRstuO.js";const n=300*1e3;function u(r){return{value:r.id,label:r.label,mature:r.mature,kind:r.kind,sub:r.sub,tier:r.tier,browse:r.browse,facets:r.facets,servers:r.servers}}const d=()=>{const r=a({queryKey:["providers"],queryFn:()=>i("/api/providers"),staleTime:n,retry:1}),e=Array.isArray(r.data)?r.data:null,t=o(()=>e&&e.length>0?e.filter(s=>s.loaded).map(u):[],[e]);return{...r,options:t,isFallback:!e||e.length===0}};export{d as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{N as c,u as r,S as d}from"./vendor-core-DfaOB3Rn.js";import{I as v}from"./vendor-icons-DrybRNxP.js";import{M as T}from"./MediaCard-
|
|
1
|
+
import{N as c,u as r,S as d}from"./vendor-core-DfaOB3Rn.js";import{I as v}from"./vendor-icons-DrybRNxP.js";import{M as T}from"./MediaCard-BNKk3aKd.js";import{T as g}from"./TvPopup-kZmcSBvG.js";import{c as m,i as f}from"./useTvLibrary-DDW03W6A.js";import{b as i}from"./vendor-query-BBT5_sHx.js";import{h as p}from"./index-mwdRstuO.js";const _=c(({item:e})=>{const o=e.type==="tv"||e.type==="tvSeries"||e.type==="tvMiniSeries",s=m(e.type,e.id);return r(T,{item:{id:String(e.id),title:e.title,thumbnail:e.image,typeBadge:o?"TV":"Movie",isAdult:f(e)},linkTo:s,hoverIcon:"info",showInfoButton:!0,metaRow:r(d,{children:[e.year&&r("span",{style:{opacity:.75},children:e.year}),e.vote_average!=null&&r("span",{style:{display:"inline-flex",alignItems:"center",gap:3},children:[r(v,{name:"star",size:10}),Number(e.vote_average).toFixed(1)]})]}),renderPopup:(a,t)=>r(g,{item:e,anchorRect:a,onMouseEnter:t.onMouseEnter,onMouseLeave:t.onMouseLeave,onRequestClose:t.close})})}),u=1e3*60*5,b=e=>{const o=p(),{query:s,type:a,genre:t,year:n,sort_by:l,page:y}=e;return i({...o.tv.search.queryOptions({q:s?.trim()||"",type:a||"multi",genre:t||"",year:n&&n!=="ALL"?n:"",sortBy:l||"popularity.desc",page:y||1}),staleTime:u,retry:1})},A=(e="all",o="week",s=1,a=!0)=>{const t=p();return i({...t.tv.trending.queryOptions({mediaType:e,timeWindow:o,page:s}),enabled:a,staleTime:u,retry:1})};export{_ as T,b as a,A as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{T as y}from"./vendor-core-DfaOB3Rn.js";import{b as v,u as o,a as n}from"./vendor-query-BBT5_sHx.js";import{h as a,z as i,t as p}from"./index-
|
|
1
|
+
import{T as y}from"./vendor-core-DfaOB3Rn.js";import{b as v,u as o,a as n}from"./vendor-query-BBT5_sHx.js";import{h as a,z as i,t as p}from"./index-mwdRstuO.js";const d=t=>String(t).toLowerCase()==="movie"?"movie":"tv",m=(t,e)=>`${d(t)}:${e}`,L=(t,e)=>{const r=d(t);return`/tv/${e}?type=${r}`},S=(t,e,r,s)=>{const u=new URLSearchParams;return u.set("type",d(t)),r!==void 0&&u.set("s",String(r)),s!==void 0&&u.set("e",String(s)),`/tv/${e}/watch?${u.toString()}`},F=t=>t.adult===!0||t.adult===1,K=["Watching","Completed","On-Hold","Dropped","Planned"],g=(t,e)=>m(t,e),$=(t="All",e=1,r=24)=>{const s=a();return v(s.tvLibrary.list.queryOptions({status:t,page:e,limit:r}))},h=()=>{const t=a();return v({...t.tvLibrary.ids.queryOptions(),staleTime:1e3*60})},C=t=>{const e=a();return v({...e.tvLibrary.check.queryOptions({id:t||""}),enabled:!!t,staleTime:1e3*60})},w=(t=24)=>{const e=a();return v(e.tvProgress.continueWatching.queryOptions({limit:t}))},O=t=>{const e=a();return v({...e.tvProgress.getByMedia.queryOptions({mediaId:t||""}),enabled:!!t})},f=(t,e,r)=>{const s=a();return v({...s.tvProgress.latest.queryOptions({mediaId:t||"",season:e,episode:r}),enabled:!!t,staleTime:0})},b=()=>{const t=a(),e=o();return n({mutationFn:async r=>{const{silent:s,...u}=r;return p.tvLibrary.add.mutate(u)},onSuccess:(r,s)=>{s.silent||i.success("Added to TV watchlist"),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter())},onError:r=>{i.error(`Failed to add: ${r.message}`)}})},Q=()=>{const t=a(),e=o();return n(t.tvLibrary.remove.mutationOptions({onSuccess:()=>{i.success("Removed from TV watchlist"),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to remove: ${r.message}`)}}))},k=()=>{const t=a(),e=o();return n(t.tvLibrary.setStatus.mutationOptions({onSuccess:()=>{i.success("Status updated"),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to update status: ${r.message}`)}}))},R=()=>{const t=a(),e=o();return n(t.tvProgress.save.mutationOptions({onSuccess:(r,s)=>{e.invalidateQueries({queryKey:["tv-progress",s.mediaId]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())}}))},B=()=>{const t=a(),e=o();return n(t.tvProgress.remove.mutationOptions({onSuccess:()=>{i.success("Progress reset"),e.invalidateQueries({queryKey:["tv-progress"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to reset progress: ${r.message}`)}}))},E=()=>{const t=a(),e=o();return n(t.tvLibrary.batchStatus.mutationOptions({onSuccess:r=>{i.success(`Status updated for ${r.updated??0} items`),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to update statuses: ${r.message}`)}}))},I=()=>{const t=a(),e=o();return n(t.tvLibrary.removeMany.mutationOptions({onSuccess:r=>{const s=r.removed??0;i.success(`Removed ${s} ${s===1?"item":"items"} from TV watchlist`),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to remove: ${r.message}`)}}))},A=()=>{const t=a(),e=o();return n(t.tvProgress.removeMany.mutationOptions({onSuccess:r=>{const s=r.removed??0;i.success(`Reset progress for ${s} ${s===1?"item":"items"}`),e.invalidateQueries({queryKey:["tv-progress"]}),e.invalidateQueries({queryKey:["tv-continue-watching"]}),e.invalidateQueries({queryKey:["tv-library"]}),e.invalidateQueries(t.tvLibrary.pathFilter()),e.invalidateQueries(t.tvProgress.pathFilter())},onError:r=>{i.error(`Failed to reset progress: ${r.message}`)}}))},M=()=>{const t=b(),e=Q(),{data:r}=h(),s=y(()=>new Set(r?.ids||[]),[r]);return{toggle:c=>{const l=g(c.mediaType,c.tmdbId);s.has(l)?e.mutate(l):t.mutate({...c,poster:c.poster||""})},bookmarkedIds:s,pending:t.isPending||e.isPending}};export{K as T,Q as a,B as b,L as c,m as d,C as e,M as f,R as g,k as h,F as i,f as j,O as k,$ as l,E as m,d as n,I as o,A as p,S as t,w as u};
|
package/client/dist/index.html
CHANGED
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
background-color: #0c0d12;
|
|
34
34
|
}
|
|
35
35
|
</style>
|
|
36
|
-
<script type="module" crossorigin src="/assets/index-
|
|
36
|
+
<script type="module" crossorigin src="/assets/index-mwdRstuO.js"></script>
|
|
37
37
|
<link rel="modulepreload" crossorigin href="/assets/vendor-core-DfaOB3Rn.js">
|
|
38
38
|
<link rel="modulepreload" crossorigin href="/assets/vendor-query-BBT5_sHx.js">
|
|
39
39
|
<link rel="modulepreload" crossorigin href="/assets/vendor-icons-DrybRNxP.js">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@serifpersia/dango",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.3",
|
|
4
4
|
"description": "A web application for watching anime.",
|
|
5
5
|
"main": "orchestrator.js",
|
|
6
6
|
"repository": {
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"allowScripts": {
|
|
84
84
|
"esbuild@0.28.2": true
|
|
85
85
|
},
|
|
86
|
-
"versionDate": "2026-10-08T09:
|
|
86
|
+
"versionDate": "2026-10-08T09:18:33.903Z"
|
|
87
87
|
}
|
|
@@ -96,8 +96,30 @@ export async function refreshAuthedInnertube() {
|
|
|
96
96
|
return null;
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
const AUTH_TTL_MS = 5 * 60 * 1000;
|
|
100
|
+
let authProbeAt = 0;
|
|
101
|
+
let authProbeOk = false;
|
|
102
|
+
export async function verifyMusicSession() {
|
|
103
|
+
if (!readCookie())
|
|
104
|
+
return false;
|
|
105
|
+
const now = Date.now();
|
|
106
|
+
if (now - authProbeAt < AUTH_TTL_MS)
|
|
107
|
+
return authProbeOk;
|
|
108
|
+
authProbeAt = now;
|
|
109
|
+
try {
|
|
110
|
+
const yt = await getAuthedInnertube();
|
|
111
|
+
if (!yt)
|
|
112
|
+
return false;
|
|
113
|
+
await yt.account.getInfo();
|
|
114
|
+
authProbeOk = true;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
authProbeOk = false;
|
|
118
|
+
}
|
|
119
|
+
return authProbeOk;
|
|
120
|
+
}
|
|
121
|
+
export async function getMusicAuthStatus() {
|
|
122
|
+
return { authenticated: await verifyMusicSession() };
|
|
101
123
|
}
|
|
102
124
|
export async function saveMusicCookie(cookie) {
|
|
103
125
|
const clean = cookie.trim();
|
|
@@ -122,6 +144,8 @@ export async function saveMusicCookie(cookie) {
|
|
|
122
144
|
}
|
|
123
145
|
fs.writeFileSync(COOKIE_PATH, clean, 'utf-8');
|
|
124
146
|
authedTube = trial;
|
|
147
|
+
authProbeAt = Date.now();
|
|
148
|
+
authProbeOk = true;
|
|
125
149
|
logger.info('[ytmusic] cookie sign-in validated and saved');
|
|
126
150
|
}
|
|
127
151
|
export async function signOutMusic() {
|
|
@@ -133,4 +157,6 @@ export async function signOutMusic() {
|
|
|
133
157
|
// ignore
|
|
134
158
|
}
|
|
135
159
|
authedTube = null;
|
|
160
|
+
authProbeAt = 0;
|
|
161
|
+
authProbeOk = false;
|
|
136
162
|
}
|
|
@@ -2,7 +2,7 @@ import { TRPCError } from '@trpc/server';
|
|
|
2
2
|
import { protectedProcedure, router } from '../index.js';
|
|
3
3
|
import { badRequest, defineSchema, failed, optStr, reqObj } from '../validation.js';
|
|
4
4
|
import logger from '../../logger.js';
|
|
5
|
-
import { getInnertube, getAuthedInnertube, refreshAuthedInnertube, saveMusicCookie, getMusicAuthStatus, signOutMusic, isParserVariantError, } from '../../lib/ytmusic.js';
|
|
5
|
+
import { getInnertube, getAuthedInnertube, refreshAuthedInnertube, saveMusicCookie, getMusicAuthStatus, signOutMusic, isParserVariantError, verifyMusicSession, } from '../../lib/ytmusic.js';
|
|
6
6
|
const NAME_SUFFIXES = [
|
|
7
7
|
/\s*(- topic)$/i,
|
|
8
8
|
/\s*vevo$/i,
|
|
@@ -150,6 +150,9 @@ function upnextToTrack(node, trustLike = false) {
|
|
|
150
150
|
...(liked !== null ? { liked } : {}),
|
|
151
151
|
};
|
|
152
152
|
}
|
|
153
|
+
function isSignInPrompt(endpoint) {
|
|
154
|
+
return !!endpoint?.payload && 'signInEndpoint' in endpoint.payload;
|
|
155
|
+
}
|
|
153
156
|
function parseUpnext(panel, trustLike) {
|
|
154
157
|
const tracks = [];
|
|
155
158
|
const shaped = panel;
|
|
@@ -592,6 +595,9 @@ export const musicRouter = router({
|
|
|
592
595
|
if (!yt) {
|
|
593
596
|
throw unauthorized('MUSIC_AUTH_REQUIRED');
|
|
594
597
|
}
|
|
598
|
+
if (!(await verifyMusicSession())) {
|
|
599
|
+
throw unauthorized('MUSIC_AUTH_REQUIRED');
|
|
600
|
+
}
|
|
595
601
|
const attempt = async (session) => {
|
|
596
602
|
const shaped = session;
|
|
597
603
|
const actions = shaped.actions ?? shaped.session?.actions;
|
|
@@ -600,12 +606,21 @@ export const musicRouter = router({
|
|
|
600
606
|
const panel = await session.music.getUpNext(id);
|
|
601
607
|
const contents = panel.contents ?? [];
|
|
602
608
|
let endpoint = null;
|
|
609
|
+
let signedOut = false;
|
|
603
610
|
for (const item of contents) {
|
|
604
611
|
const toggle = findLikeToggle(item, id);
|
|
605
|
-
|
|
606
|
-
if (
|
|
612
|
+
const picked = like ? toggle.like : toggle.unlike;
|
|
613
|
+
if (isSignInPrompt(picked)) {
|
|
614
|
+
signedOut = true;
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
if (picked) {
|
|
618
|
+
endpoint = picked;
|
|
607
619
|
break;
|
|
620
|
+
}
|
|
608
621
|
}
|
|
622
|
+
if (signedOut && !endpoint)
|
|
623
|
+
throw new Error('MUSIC_SESSION_EXPIRED');
|
|
609
624
|
if (!endpoint)
|
|
610
625
|
throw new Error('Like toggle not found for track');
|
|
611
626
|
await endpoint.call(actions);
|
|
@@ -614,6 +629,10 @@ export const musicRouter = router({
|
|
|
614
629
|
await attempt(yt);
|
|
615
630
|
}
|
|
616
631
|
catch (err) {
|
|
632
|
+
if (err.message === 'MUSIC_SESSION_EXPIRED') {
|
|
633
|
+
logger.warn('[music] like rejected, session expired');
|
|
634
|
+
throw unauthorized('MUSIC_AUTH_REQUIRED');
|
|
635
|
+
}
|
|
617
636
|
logger.warn({ err }, '[music] rate failed, retrying with a fresh saved-cookie session');
|
|
618
637
|
const fresh = await refreshAuthedInnertube();
|
|
619
638
|
if (!fresh)
|
|
@@ -622,6 +641,9 @@ export const musicRouter = router({
|
|
|
622
641
|
await attempt(fresh);
|
|
623
642
|
}
|
|
624
643
|
catch (retryErr) {
|
|
644
|
+
if (retryErr.message === 'MUSIC_SESSION_EXPIRED') {
|
|
645
|
+
throw unauthorized('MUSIC_AUTH_REQUIRED');
|
|
646
|
+
}
|
|
625
647
|
logger.error({ err: retryErr }, '[music] rate retry failed');
|
|
626
648
|
throw failed('Like action failed');
|
|
627
649
|
}
|