From 338e3feb4af2501eaae70897c817f0cae2c786f9 Mon Sep 17 00:00:00 2001 From: Lukas Date: Fri, 28 Nov 2025 18:58:50 +0100 Subject: [PATCH] cleanup --- .coverage | Bin 0 -> 69632 bytes data/config.json | 2 +- data/download_queue.json | 174 +- docs/README.md | 345 ---- docs/api_implementation_summary.md | 245 --- docs/api_reference.md | 1425 ----------------- docs/deployment.md | 772 --------- docs/documentation_summary.md | 485 ------ docs/error_handling_validation.md | 861 ---------- docs/frontend_backend_integration.md | 174 -- docs/frontend_integration.md | 839 ---------- docs/identifier_standardization_validation.md | 426 +++++ infrastructure.md => docs/infrastructure.md | 0 docs/logging.md | 155 -- docs/progress_service_architecture.md | 450 ------ docs/user_guide.md | 628 -------- instructions.md | 95 -- 17 files changed, 514 insertions(+), 6562 deletions(-) create mode 100644 .coverage delete mode 100644 docs/README.md delete mode 100644 docs/api_implementation_summary.md delete mode 100644 docs/api_reference.md delete mode 100644 docs/deployment.md delete mode 100644 docs/documentation_summary.md delete mode 100644 docs/error_handling_validation.md delete mode 100644 docs/frontend_backend_integration.md delete mode 100644 docs/frontend_integration.md create mode 100644 docs/identifier_standardization_validation.md rename infrastructure.md => docs/infrastructure.md (100%) delete mode 100644 docs/logging.md delete mode 100644 docs/progress_service_architecture.md delete mode 100644 docs/user_guide.md diff --git a/.coverage b/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..b3384566432b93b17b2da90d421a1ee77931c4f5 GIT binary patch literal 69632 zcmeHQ3w%`7nLqb2bLV+)9)u+1H9SKgWD)`)ghwU`j|2ilv?$V&43nE=U@{YCCJ#i& zOjxVy{#0y#+iI5r-FDZlVnOUGK3bygil}R7wQ3iXu_~ZwKq)amAp4y&caljAb|&oa z*R^{tWWM`2=YPNRKi_x0^SCqj=9?<*UfERVayMGNrhF8G7zSBPCWMd{{$k-Tv{oMj4jJhwOD*ZL&M~X)Ig4xa5|_rdvu%D;JxB=S)*|CfH`oFqN3x zu2xf%>^9Ze9kR*pthL*$Uc0m2>W4niGHm_zd8y=r?cO zH(K3WOq=8_*(8B-H?Q304W0lH*{%waTqnC_r%m<*wU}zJ&C+G%A*F#6gGH&R10b8rU5mBf;I=w#4YDWOWF07>%>{b4d4r{OyBf`2 zm&svwl43eNcCX##G|6qUt=TKrj#$8KOj>9I^1@34ST(pnHNl+9y~5ZT%sfI)CApHh z4wQ4cLbMKM#J7gbL}zDn;|8F7V{>B@t{lh_ys_7Hy`0y}>vbuGjks<`sLR3f4yn!% z<+w(Jxtg8!&CT*ah1Z9ynmU9;1M zUB!dTU~{#|Zfm`qqg)L(3x91x0@KOUsuLGyT+eg{OrSb%U{~i)Rtt$KDNKi!n2}Oj ziV%jFP^czHXhuVq8fB}e*&S*~zNwK6%)QKf2*DH>at~yWI(f9>k zNK8mz{6UYv?GpY|4JiaZGw1@t0zu^JH(9+6rmyRcPlMu_Ds|$#gzG7eRjAIxpXwd! zSfcXX$%OqzX!P+PH$-K8W>Dqj@|GDbRtK~uO;)=bTo&5kU<5GXgtb;kY~A2$_7eNW zhr~Q_>>1QI2rzgY;vQ0Ek>udsRW6Um4q+9CEl*MCtSPg>>cOp$C)2dS<#NbYXD~KE zjtURl)9x`59ljowiU%<~TQEj_OD54N6kKpKe+xKW$iHBxvC-}K4 z`ve;i$Y{z0r}Th}4#NzADpzrf6~fPH0!}b$qqR2Z?zmFI5L+AMufYYQ(ITr?_Szd| z6HY>uA%@jz^_XmK87@LB&C2Ay$qaC9Rp;SPJWAH!uAD!E5fZ0QXZ+2IGX~q4Y7YeU zMr%lI<&Yg>B*QKa+RG|vaG|#oZYP+#FgoyI@D8|f3)bLXN?%8pWdto5=?a4X zbfXMV1}FoR0m=YnfHFWCpbSt3Ck38K4YM1}FpHN(KxpmnMat@W_o}xRhk&8Gt!Cc{6izbx9 zR6JS~$^d16GC&!i3{VCr1C#;E0A+wOKpCJ6d>a`MZ{q!v8FPcHQ8qi8H(5RAH7-Xp z9Ju8sm$}4gZ*{pHwPugoX7*6MaS9Pmqu<_6j7@HSNAU)Kztf}cywroaF9 zZ8QX`Gi87>KpCJ6PzERilmW^BWq>k38K4YM1|nvFV>o2Q-~VT%J_P^iMj4k38K4YM1}FoR0m{JNAOjp{)Z+F3mF&kz`b;_?)k)uzEYc(?RXi=eFTO3_ zBesZ3M4j=H@l)dm#-qj;jK4DOGXBuG(O6_mFd7ZNFx+Ff-4LTcqkmh!U;l`Hm;OQh z4t=w}R$r`rPy3ekdF@VZqc%y!p}XDEh6;KXCaDWANiU&ucQM`lCjtvhhMwZ2zKr>(^#|&>!kJ4TQ=R4VYrC&J zv-a>s=Grf%^N&d9`?Q}j_dFh0`A;>%p-Y*!o&J}OtIwZVl^a)h7VV$CU@_#mvzR@9 zc+1(Eac)<=Ilup=FJCI2cK9B5eIa@PT|(DhVlucV zIX8-%y$G^97G8dB+t}yPRo5BRa{Bi%HLZo6+cJ{Gn*O;v?n?JP-gRf$fvcz6o6wJ+ zTA0MPaoW_PGRW4F!k&CNVbQ5mJSv{w{sa8p)EqSbiU&P|dcKP~*$ZfqvrCUYk{DC! z1I#XF5^^FR&!|fwuQ-lfT7s)eoXVo#$m*Sw{=mIzeQrUCr-#3`g{|-Mx1&JnyJ>fR zm<7-;6wj`fVDR*f{*sssIP z$+K!+I4OO9W3Cor?As?qIgr!tqV}n_9u_*zXRny|HmWyi;$r!{qVHksCv@^w=QLc zI~HP8@1%}v2?t(Be@44^S4{b7O?zvN9-*oQ(;2Dp{hWW;4*UH}uO2K&KkclEDsVl6NHu>beW?Ro7u%hVGY zrryoJf9vx*GH(0XPVLUcZ2kgZzd^;``S8QZRYIYD@4QD0cXTqng%4$#I`viP^>@aw zduMC;SFdDQQcC{wizZ~5)HHcMuhp((kIl%>_kAR>f6n$j0gjTo+40JS)7u&Gzw=LS z+I})VHh&(*Hax3-m^rrlFe>6toNwL8px>h118u-VKQ;SWm=lSXqlch?=;KyhP7!2U zpUI-{ow_hLv;Mg})T&n>T9@1TUdMZB$M5_6cS1yQfaQ@!Kb!uyJDxA!UyG)qQBd&GYfoM1=EoM`v@_W=Ke+nYkC?HEhg0Tp**V>6 z^=vpVa=OG>AanEBi*<-ayejwBnl~)M&ZC#ckI#n-i_9JC&?OEbODBisqah!iT*gdD zV##5Ttyd#v@A{_$kj|H%jL>J3dzh1KNp)%-Bq&N{w_Xz3b3;^hW_)mDQh#kSJ2@Aw zR_1mX?m#|NW9%H~n~lygXdiQ%fc9|*)bLM)BY(RYtZK*hLe|pCuXWWXsQ27E=xxdJ4A^TQlY4Fxw2ple>br80*_Ywld{C-U`y_H{ zOZQa)J^8sB<#s+J1wJ|F`vBbX+!ge;&;+U8N2iQUVo2e?uGH+ctj!_qz#R6Nss`9a zuN->r!|wY(T=3YM$8Z1l+Y>mn^NU0Cy1NVEc>UvS|D6yN;LL|#ZEii1)_P(yPIbq{ zjemG7QI&)&FQ>uD;>Xtf=8lWga`%s)fopjYJDs~-Z@T+PO%=M!%pnVEdE+f+=R)0| z*X!m_%Z4Ot%GksI==bTz_{z{cOo#=|;hUHfjtd{|2^5cq6Zj3&rm@o@ZB8lsV;OnT z9Hh2Qxux^9-znu$|^>hjs_G2`vfIxz#h08JM7*NN|`kuo8XY1WH% zub`6;FneMd!xT6%E+0q~e5M$~WPCK^#aGj}e)fc*odic?vP)kJ2-=BwciM};zoJo3 zfL$?*oje|7 zTTuq8S(S92L751pBh<5NPJlt{VD|vmi%>6GhY-ZayF>c12cRgRf<&|fivf4Vi`V_3wN{v(a z7}P;EsPnz|e%fzEO|7lhUh0Q4=jZfp<*rWM{_3{NWyk~t{sh&;BfrJ;!m2l*pOy~z z2<`p5=KfgZYfn87F4r}&CXV%I{BaHxuqw9;p|*vGp}89eN{9kGF&Sj}{0_7J#KqRL zl7QA7*Nf;>3yS&bU~3|OW}WZBP9`S_60M)dK6Mc4-2z%**T51sTrwZt!5j8fIF*?Q z>8px5_GhD*7@SZ8f5b9zmnXOfNiD1}781tHWpiQ@U}r)`$BD!LdFkq<_qTS9j~xSN zCZ%`$m{b_f#jE4tl$dsKY#hj(_-=huOUN){kROI#v2Z>nu1+$>z)q^f9y3^~Kpjbf zLsP<@>xtb?D0Woxp_=@~&Upv2LvtIJ(PJ1ytNN13mQjcY4`(mZH}W zsS*P-pi?-#H{KLin1ReO21q|)Oda>G;JeBpgQ2EUkLx%o=GxUMsPL-0f6t}YziZMo zz4H!-Sab%e{c@;OxYT5eMJ9y*gN0(gVS~_?j`j*biVpBa9V2K##>DPZeU;98-0dFBDtf&J)JW_xB$hGo@vR2Bv~B!P#EG1^k5 zoFiUkWPkPJi|ybc#b+~6U=M@Fn7;C=Z{zmuZecsmLY?;YK5+U_`@Cxxj$pICdZd49 z)oaCXotM^L>o~OvDvf1}Sb%I9%O2*6cBG>Xmo_f)K>!+Yvw$n$3*^Iyd}15}d8e=i zXS)M`>OS<`bNMyn8NB|#(ilMEdg-!wzvvTh6}L#srA5-m(sR-~VlB)Iye~Z{{aSia zx>wpEJuW>YU677RN5u+pmN-LvRJv1YmYmW8sX#J|Zm~)lFO3s7iSwj*$sp<^m3U43 zxwuPwLi|VZZt*Mey!eUuC-Ja&NUE1=q_xs&X{tCy%n*~rB9>Z+NG>K~(n2Cs3sf-S z&&($WhIvF}77;OVE)nWNBKSE(%q$>+n@vRCEF#SLMC8mQA~lbQ+*~3G%|y(}A!5-C zBFeIfD4kA3$uuGgvWS>Hm55oHMC4B)V#Z`5vL_KSZ6Xm_6Ns2Ho`}gNA{Jy2F(I9Z z@o7YuQi;%{5FwDs0%m?PIhvP5L{TCUbH@^qkw8TH7$VZ*iHMIQA}*E)DTasyiHId4 z5sQsPj4==qqbEYABO+EyM3RPxM1cssng~%vgqA15$PqD?#S<4=7O(%4nX7L$BYKrG zKpCJ6PzERilmW^BWq>k38K4YM1}FoRfp0Mbc>SM_|G&i*NL8l{PzERilmW^BWq>k3 z8K4YM1}FoR0m?uG4AAxe2uPwyCS7GPFg{_ZHcpe~XPW+APf<#Hq%!LaD&3Us8=%ol`x|ALH9OhTSC1VW+`2{_W~^RfFNA^tAYxI!~Lg zO4gj${F2ANs75!+0A=7?#=uJ6pAp#`NNp~+Y;JP9TI{v>?W2t@r`-#uYO6!%;Ps=c zt9bv!$lykJp{eY4yWB(HXF9E%_s5SKu)5j~N>*2cW?AaI;IBq4;M$|Yvo_h4H?0E7 zf)%_!Ewb!(XPw*X@w%IB-ew@qBiowYcJCH*m`-y`c)uz#G=(j!Osl-X zWUyhZ)Vf-o4wtnS049v4ii4U!?(y@utx@0I+U#wByr$K>KQpq-!x(Y6>g(;!dUJD& z9sJCRodAdd$c$yYKk_^h(~JazjvIwwor}@vnvb#cdJq*GG2GVeLzu)$VY? zE02ML#W(Z*tjIuy(K_IDb#{jgje%FL$4&^C^Ka$-c{hexYxP<;SUp2==Plv=Qe?QK zz*r}Doz*6L%r>jTvB7HF#bOtxjt&JXRI+ekL+Pg9br*tDsVCuqU-D;*LY`*3c#NdZ8`C zrUbtniYi7TE9!Ij`TuErK7wEW-w40O7Z7&~Hesy#h`L$4T}&|km+?Mhg`v;zE5k-Z zmi`m?jenayUH7K$Ufn|NdF?-|r)zK4#%PXe3WXlw*Q!r7+g1OfTBnNTkMQ~Ywy2e% z87Kpkf&c3aMBbfJ0tt*j&0e{&$zk7b=+k$132+FJjAQUg={l=)O zFsK6{R1bEc7DnD18&Z-`V^ZB9JDOl}5fqvp`B-WQRIS`3gUdQ?!9IFQDeo6XQLeD+ z85gxJVugsG3{2I9Im^_@`@c%T2H;=-QSX*Lo-nlJ(W8ZC%)-znMLymiuA9=GR&<35 zRKd(`g4W#NYLv~6=1o?Qd5z1_3KRfH5a( zvmd~~3ps#L5H%$O2;e$SFqGgT!|c&(qI3ghMIA8*GzqJk{8hYvd{m7I6vOLwIbhBK zW?5nCV(5C=4E+3mA-W$)Pf2%31!9l*sMsK8!u$RX7&jTS4DTC$Zdh-K)xV^_Q$IuZ zq3&Vb3Z0}qqV;KKYR+l?P1B%B5snGlgc5;Mzo_1>&Q*1*_NnSsNqiT-ozLe!;2z{w zz$+XMu^ZVe=0oOZ%vvT9y$LrQaVsn2kzXH85Evk7(DF*>07z7kWB_Eq@+<{_p&FGU zisdbt4G6KLLKtFsmRY0LM6tX@`G8;?l_p`9S3DC?xM)y@1%S#t07#1pV6cTGL%s0E zdr2;!MMdw(ZQXJ+;G~RFtKmVQGzY+Z5&5To;e5eDRolOiq`Sw*_e`u~zdfQc*|1{b3S7X62=|IZ&A zsV@+in}@FdFG~O|k|Sc5WFK7N4DAiB|Cf&etc1~E4PXB+j~^}4;HrIa{eMLqAVn4w zhLvv+scLZje{n3pMP}0kF0AfDeBr6D${2u&%piwpHPZV3atY8P^ZH?EA)Uh3|I0)G zi!AIBuz^K$Vpz)h|6C)yWI1v}AX%05{|W=#KeEG6JYYo?jY5N&;DdXm9ONHOza@;3A~w>FLs0$j z_5X4P?jKp>IGhXI^$24EkN?MMoJcw-t&=!$zqnbPZv4dfh;fZkYk1bsV3??XSAV~L zgm)#iB;4@Zb6@V1kNLA@k2j`cDJY!W{4j@sDl7b+E z&sZ&uwmbu4oMF#cRV)FdQ5o~so_sG`95FS+{37f-IaP}QB&ubI!9}@|pZQu*28fZh zB}$ErggEfb*YZ+;i)`NG8{m{Bw^bzo7S+1ONVZ83c?KQe*lkAkU0PV literal 0 HcmV?d00001 diff --git a/data/config.json b/data/config.json index b25e2b5..4346592 100644 --- a/data/config.json +++ b/data/config.json @@ -17,7 +17,7 @@ "keep_days": 30 }, "other": { - "master_password_hash": "$pbkdf2-sha256$29000$jxGC8F7LOYcwZoyR0rpX6g$b4wXlUToBG0KgOj/3Sbez0J57hA84RhtsMnepsqBRb0", + "master_password_hash": "$pbkdf2-sha256$29000$854zxnhvzXmPsVbqvXduTQ$G0HVRAt3kyO5eFwvo.ILkpX9JdmyXYJ9MNPTS/UxAGk", "anime_directory": "/mnt/server/serien/Serien/" }, "version": "1.0.0" diff --git a/data/download_queue.json b/data/download_queue.json index f974644..5cffb6f 100644 --- a/data/download_queue.json +++ b/data/download_queue.json @@ -1,7 +1,7 @@ { "pending": [ { - "id": "304d3273-8b1c-4847-8dc8-a8c585d720c0", + "id": "ae6424dc-558b-4946-9f07-20db1a09bf33", "serie_id": "test-series-2", "serie_folder": "Another Series (2024)", "serie_name": "Another Series", @@ -12,7 +12,7 @@ }, "status": "pending", "priority": "HIGH", - "added_at": "2025-11-28T15:14:50.916177Z", + "added_at": "2025-11-28T17:54:38.593236Z", "started_at": null, "completed_at": null, "progress": null, @@ -21,7 +21,7 @@ "source_url": null }, { - "id": "4ec82ed2-ad64-4330-bea5-3c986e577fa8", + "id": "011c2038-9fe3-41cb-844f-ce50c40e415f", "serie_id": "series-high", "serie_folder": "Series High (2024)", "serie_name": "Series High", @@ -32,7 +32,7 @@ }, "status": "pending", "priority": "HIGH", - "added_at": "2025-11-28T15:14:50.955809Z", + "added_at": "2025-11-28T17:54:38.632289Z", "started_at": null, "completed_at": null, "progress": null, @@ -41,7 +41,7 @@ "source_url": null }, { - "id": "9f089050-5128-439b-969e-541c3c6b7283", + "id": "0eee56e0-414d-4cd7-8da7-b5a139abd8b5", "serie_id": "series-normal", "serie_folder": "Series Normal (2024)", "serie_name": "Series Normal", @@ -52,7 +52,7 @@ }, "status": "pending", "priority": "NORMAL", - "added_at": "2025-11-28T15:14:50.958134Z", + "added_at": "2025-11-28T17:54:38.635082Z", "started_at": null, "completed_at": null, "progress": null, @@ -61,7 +61,7 @@ "source_url": null }, { - "id": "0924064d-8588-45dd-9735-ac5ed2225360", + "id": "eea9f4f3-98e5-4041-9fc6-92e3d4c6fee6", "serie_id": "series-low", "serie_folder": "Series Low (2024)", "serie_name": "Series Low", @@ -72,7 +72,7 @@ }, "status": "pending", "priority": "LOW", - "added_at": "2025-11-28T15:14:50.960059Z", + "added_at": "2025-11-28T17:54:38.637038Z", "started_at": null, "completed_at": null, "progress": null, @@ -81,7 +81,7 @@ "source_url": null }, { - "id": "b34582b3-3d3c-4883-b95f-63287b6df397", + "id": "b6f84ea9-86c8-4cc9-90e5-c7c6ce10c593", "serie_id": "test-series", "serie_folder": "Test Series (2024)", "serie_name": "Test Series", @@ -92,7 +92,7 @@ }, "status": "pending", "priority": "NORMAL", - "added_at": "2025-11-28T15:14:51.136578Z", + "added_at": "2025-11-28T17:54:38.801266Z", "started_at": null, "completed_at": null, "progress": null, @@ -101,7 +101,7 @@ "source_url": null }, { - "id": "2221eecf-e250-4f26-8e17-79b81db379bd", + "id": "412aa28d-9763-41ef-913d-3d63919f9346", "serie_id": "test-series", "serie_folder": "Test Series (2024)", "serie_name": "Test Series", @@ -112,7 +112,7 @@ }, "status": "pending", "priority": "NORMAL", - "added_at": "2025-11-28T15:14:51.204136Z", + "added_at": "2025-11-28T17:54:38.867939Z", "started_at": null, "completed_at": null, "progress": null, @@ -121,7 +121,7 @@ "source_url": null }, { - "id": "ab779cf6-3cd5-49ca-852b-a490b61dce99", + "id": "3a036824-2d14-41dd-81b8-094dd322a137", "serie_id": "invalid-series", "serie_folder": "Invalid Series (2024)", "serie_name": "Invalid Series", @@ -132,7 +132,7 @@ }, "status": "pending", "priority": "NORMAL", - "added_at": "2025-11-28T15:14:51.272632Z", + "added_at": "2025-11-28T17:54:38.935125Z", "started_at": null, "completed_at": null, "progress": null, @@ -141,7 +141,7 @@ "source_url": null }, { - "id": "ecc12f47-9e1a-4cd3-a39d-df4ccd81baf4", + "id": "1f4108ed-5488-4f46-ad5b-fe27e3b04790", "serie_id": "test-series", "serie_folder": "Test Series (2024)", "serie_name": "Test Series", @@ -152,7 +152,7 @@ }, "status": "pending", "priority": "NORMAL", - "added_at": "2025-11-28T15:14:51.305672Z", + "added_at": "2025-11-28T17:54:38.968296Z", "started_at": null, "completed_at": null, "progress": null, @@ -161,67 +161,7 @@ "source_url": null }, { - "id": "109163ee-d2ce-48bb-81b3-5f6b604506e7", - "serie_id": "series-1", - "serie_folder": "Series 1 (2024)", - "serie_name": "Series 1", - "episode": { - "season": 1, - "episode": 1, - "title": null - }, - "status": "pending", - "priority": "NORMAL", - "added_at": "2025-11-28T15:14:51.399391Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "8ebd2676-0069-43a7-bee1-ed291a0ae334", - "serie_id": "series-4", - "serie_folder": "Series 4 (2024)", - "serie_name": "Series 4", - "episode": { - "season": 1, - "episode": 1, - "title": null - }, - "status": "pending", - "priority": "NORMAL", - "added_at": "2025-11-28T15:14:51.400954Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "f1d8efe4-a682-4ef1-b7a5-e1b954b622be", - "serie_id": "series-3", - "serie_folder": "Series 3 (2024)", - "serie_name": "Series 3", - "episode": { - "season": 1, - "episode": 1, - "title": null - }, - "status": "pending", - "priority": "NORMAL", - "added_at": "2025-11-28T15:14:51.401591Z", - "started_at": null, - "completed_at": null, - "progress": null, - "error": null, - "retry_count": 0, - "source_url": null - }, - { - "id": "18f8392a-d0ad-4b5d-8a2b-f634fd642c71", + "id": "5e880954-1a9f-450a-8008-5b9d6ac07d66", "serie_id": "series-2", "serie_folder": "Series 2 (2024)", "serie_name": "Series 2", @@ -232,7 +172,7 @@ }, "status": "pending", "priority": "NORMAL", - "added_at": "2025-11-28T15:14:51.402182Z", + "added_at": "2025-11-28T17:54:39.055885Z", "started_at": null, "completed_at": null, "progress": null, @@ -241,7 +181,7 @@ "source_url": null }, { - "id": "b394f1b2-691a-4be0-83f1-b5dc49e67c02", + "id": "2415ac21-509b-4d71-b5b9-b824116d6785", "serie_id": "series-0", "serie_folder": "Series 0 (2024)", "serie_name": "Series 0", @@ -252,7 +192,7 @@ }, "status": "pending", "priority": "NORMAL", - "added_at": "2025-11-28T15:14:51.403030Z", + "added_at": "2025-11-28T17:54:39.056795Z", "started_at": null, "completed_at": null, "progress": null, @@ -261,7 +201,67 @@ "source_url": null }, { - "id": "ee8b4416-772b-4ab7-b8af-8a695a723fe3", + "id": "716f9823-d59a-4b04-863b-c75fd54bc464", + "serie_id": "series-1", + "serie_folder": "Series 1 (2024)", + "serie_name": "Series 1", + "episode": { + "season": 1, + "episode": 1, + "title": null + }, + "status": "pending", + "priority": "NORMAL", + "added_at": "2025-11-28T17:54:39.057486Z", + "started_at": null, + "completed_at": null, + "progress": null, + "error": null, + "retry_count": 0, + "source_url": null + }, + { + "id": "36ad4323-daa9-49c4-97e8-a0aec0cca7a1", + "serie_id": "series-4", + "serie_folder": "Series 4 (2024)", + "serie_name": "Series 4", + "episode": { + "season": 1, + "episode": 1, + "title": null + }, + "status": "pending", + "priority": "NORMAL", + "added_at": "2025-11-28T17:54:39.058179Z", + "started_at": null, + "completed_at": null, + "progress": null, + "error": null, + "retry_count": 0, + "source_url": null + }, + { + "id": "695ee7a9-42bb-4953-9a8a-10bd7f533369", + "serie_id": "series-3", + "serie_folder": "Series 3 (2024)", + "serie_name": "Series 3", + "episode": { + "season": 1, + "episode": 1, + "title": null + }, + "status": "pending", + "priority": "NORMAL", + "added_at": "2025-11-28T17:54:39.058816Z", + "started_at": null, + "completed_at": null, + "progress": null, + "error": null, + "retry_count": 0, + "source_url": null + }, + { + "id": "aa948908-c410-42ec-85d6-a0298d7d95a5", "serie_id": "persistent-series", "serie_folder": "Persistent Series (2024)", "serie_name": "Persistent Series", @@ -272,7 +272,7 @@ }, "status": "pending", "priority": "NORMAL", - "added_at": "2025-11-28T15:14:51.493134Z", + "added_at": "2025-11-28T17:54:39.152427Z", "started_at": null, "completed_at": null, "progress": null, @@ -281,7 +281,7 @@ "source_url": null }, { - "id": "8ee3de44-7260-4e26-88ee-8172e45d14dd", + "id": "2537f20e-f394-4c68-81d5-48be3c0c402a", "serie_id": "ws-series", "serie_folder": "WebSocket Series (2024)", "serie_name": "WebSocket Series", @@ -292,7 +292,7 @@ }, "status": "pending", "priority": "NORMAL", - "added_at": "2025-11-28T15:14:51.573256Z", + "added_at": "2025-11-28T17:54:39.219061Z", "started_at": null, "completed_at": null, "progress": null, @@ -301,7 +301,7 @@ "source_url": null }, { - "id": "ec7f80b1-87c1-4cf4-949b-c96d6dd7a82b", + "id": "aaaf3b05-cce8-47d5-b350-59c5d72533ad", "serie_id": "workflow-series", "serie_folder": "Workflow Test Series (2024)", "serie_name": "Workflow Test Series", @@ -312,7 +312,7 @@ }, "status": "pending", "priority": "HIGH", - "added_at": "2025-11-28T15:14:51.610620Z", + "added_at": "2025-11-28T17:54:39.254462Z", "started_at": null, "completed_at": null, "progress": null, @@ -323,5 +323,5 @@ ], "active": [], "failed": [], - "timestamp": "2025-11-28T15:14:51.618568+00:00" + "timestamp": "2025-11-28T17:54:39.259761+00:00" } \ No newline at end of file diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index f0b2c2b..0000000 --- a/docs/README.md +++ /dev/null @@ -1,345 +0,0 @@ -# Aniworld Documentation - -Complete documentation for the Aniworld Download Manager application. - -## Quick Start - -- **New Users**: Start with [User Guide](./user_guide.md) -- **Developers**: Check [API Reference](./api_reference.md) -- **System Admins**: See [Deployment Guide](./deployment.md) -- **Interactive Docs**: Visit `http://localhost:8000/api/docs` - -## Documentation Structure - -### 📖 User Guide (`user_guide.md`) - -Complete guide for end users covering: - -- Installation instructions -- Initial setup and configuration -- User interface walkthrough -- Managing anime library -- Download queue management -- Configuration and settings -- Troubleshooting common issues -- Keyboard shortcuts -- Frequently asked questions (FAQ) - -**Best for**: Anyone using the Aniworld application - -### 🔌 API Reference (`api_reference.md`) - -Detailed API documentation including: - -- Authentication and authorization -- Error handling and status codes -- All REST endpoints with examples -- WebSocket real-time updates -- Request/response formats -- Rate limiting and pagination -- Complete workflow examples -- API changelog - -**Best for**: Developers integrating with the API - -### 🚀 Deployment Guide (`deployment.md`) - -Production deployment instructions covering: - -- System requirements -- Pre-deployment checklist -- Local development setup -- Production deployment steps -- Docker and Docker Compose setup -- Nginx reverse proxy configuration -- SSL/TLS certificate setup -- Database configuration (SQLite and PostgreSQL) -- Security best practices -- Monitoring and maintenance -- Troubleshooting deployment issues - -**Best for**: System administrators and DevOps engineers - -## Key Features Documented - -### Authentication - -- Master password setup and login -- JWT token management -- Session handling -- Security best practices - -### Configuration Management - -- Application settings -- Directory configuration -- Backup and restore functionality -- Environment variables - -### Anime Management - -- Browsing anime library -- Adding new anime -- Managing episodes -- Search functionality - -### Download Management - -- Queue operations -- Priority management -- Progress tracking -- Error recovery - -### Real-time Features - -- WebSocket connections -- Live download updates -- Status notifications -- Error alerts - -## Series Identifier Convention - -### Understanding Series Identifiers - -The application uses two identifiers for anime series: - -| Identifier | Purpose | Example | Used For | -| ---------- | ------------------------ | -------------------------- | ---------------- | -| `key` | **Primary identifier** | `"attack-on-titan"` | All API lookups | -| `folder` | Filesystem metadata only | `"Attack on Titan (2013)"` | Display purposes | - -### Key Format - -- Lowercase letters and numbers only -- Words separated by hyphens (`-`) -- No spaces, underscores, or uppercase letters -- Examples: `"one-piece"`, `"86-eighty-six"`, `"re-zero"` - -### Usage Guidelines - -```python -# ✅ Correct: Use 'key' for API operations -GET /api/anime/attack-on-titan -POST /api/queue/add {"serie_id": "attack-on-titan", ...} - -# ❌ Deprecated: Folder-based lookups (backward compatibility only) -GET /api/anime/Attack%20on%20Titan%20(2013) # Will work but deprecated -``` - -### Backward Compatibility - -For existing integrations, folder-based lookups are still supported but deprecated: - -- API endpoints check `key` first, then fall back to `folder` -- New code should always use `key` as the identifier -- Deprecation warnings will be added in future versions - -## Documentation Examples - -### API Usage Example - -```bash -# Setup -curl -X POST http://localhost:8000/api/auth/setup \ - -H "Content-Type: application/json" \ - -d '{"master_password": "secure_pass"}' - -# Login -TOKEN=$(curl -X POST http://localhost:8000/api/auth/login \ - -H "Content-Type: application/json" \ - -d '{"password": "secure_pass"}' | jq -r '.token') - -# List anime -curl http://localhost:8000/api/v1/anime \ - -H "Authorization: Bearer $TOKEN" -``` - -### Deployment Example - -```bash -# Clone and setup -git clone https://github.com/your-repo/aniworld.git -cd aniworld -python3.10 -m venv venv -source venv/bin/activate -pip install -r requirements.txt - -# Run application -python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 -``` - -## Interactive Documentation - -Access interactive API documentation at: - -- **Swagger UI**: `http://localhost:8000/api/docs` -- **ReDoc**: `http://localhost:8000/api/redoc` -- **OpenAPI JSON**: `http://localhost:8000/openapi.json` - -These provide: - -- Interactive API explorer -- Try-it-out functionality -- Request/response examples -- Schema validation - -## Common Tasks - -### I want to... - -**Use the application** -→ Read [User Guide](./user_guide.md) → Getting Started section - -**Set up on my computer** -→ Read [User Guide](./user_guide.md) → Installation section - -**Deploy to production** -→ Read [Deployment Guide](./deployment.md) → Production Deployment - -**Use the API** -→ Read [API Reference](./api_reference.md) → API Endpoints section - -**Troubleshoot problems** -→ Read [User Guide](./user_guide.md) → Troubleshooting section - -**Set up with Docker** -→ Read [Deployment Guide](./deployment.md) → Docker Deployment - -**Configure backup/restore** -→ Read [User Guide](./user_guide.md) → Configuration section - -**Debug API issues** -→ Check [API Reference](./api_reference.md) → Error Handling section - -## Documentation Standards - -All documentation follows these standards: - -### Structure - -- Clear table of contents -- Logical section ordering -- Cross-references to related topics -- Code examples where appropriate - -### Style - -- Plain, accessible language -- Step-by-step instructions -- Visual formatting (code blocks, tables, lists) -- Examples for common scenarios - -### Completeness - -- All major features covered -- Edge cases documented -- Troubleshooting guidance -- FAQ section included - -### Maintenance - -- Version number tracking -- Last updated timestamp -- Changelog for updates -- Broken link checking - -## Help & Support - -### Getting Help - -1. **Check Documentation First** - - - Search in relevant guide - - Check FAQ section - - Look for similar examples - -2. **Check Logs** - - - Application logs in `/logs/` - - Browser console (F12) - - System logs - -3. **Try Troubleshooting** - - - Follow troubleshooting steps in user guide - - Check known issues section - - Verify system requirements - -4. **Get Community Help** - - - GitHub Issues - - Discussion Forums - - Community Discord - -5. **Report Issues** - - File GitHub issue - - Include logs and error messages - - Describe reproduction steps - - Specify system details - -### Feedback - -We welcome feedback on documentation: - -- Unclear sections -- Missing information -- Incorrect instructions -- Outdated content -- Suggest improvements - -File documentation issues on GitHub with label `documentation`. - -## Contributing to Documentation - -Documentation improvements are welcome! To contribute: - -1. Fork the repository -2. Edit documentation files -3. Test changes locally -4. Submit pull request -5. Include summary of changes - -See `CONTRIBUTING.md` for guidelines. - -## Documentation Map - -``` -docs/ -├── README.md # This file -├── user_guide.md # End-user documentation -├── api_reference.md # API documentation -├── deployment.md # Deployment instructions -└── CONTRIBUTING.md # Contribution guidelines -``` - -## Related Resources - -- **Source Code**: GitHub repository -- **Interactive API**: `http://localhost:8000/api/docs` -- **Issue Tracker**: GitHub Issues -- **Releases**: GitHub Releases -- **License**: See LICENSE file - -## Document Info - -- **Last Updated**: November 28, 2025 -- **Version**: 2.0.0 -- **Status**: Production Ready -- **Maintainers**: Development Team - ---- - -## Quick Links - -| Resource | Link | -| ------------------ | -------------------------------------------- | -| User Guide | [user_guide.md](./user_guide.md) | -| API Reference | [api_reference.md](./api_reference.md) | -| Deployment Guide | [deployment.md](./deployment.md) | -| Swagger UI | http://localhost:8000/api/docs | -| GitHub Issues | https://github.com/your-repo/aniworld/issues | -| Project Repository | https://github.com/your-repo/aniworld | - ---- - -**For Questions**: Check relevant guide first, then file GitHub issue with details. diff --git a/docs/api_implementation_summary.md b/docs/api_implementation_summary.md deleted file mode 100644 index ebe0d51..0000000 --- a/docs/api_implementation_summary.md +++ /dev/null @@ -1,245 +0,0 @@ -# API Endpoints Implementation Summary - -**Date:** October 24, 2025 -**Task:** Implement Missing API Endpoints -**Status:** ✅ COMPLETED - -## Overview - -Successfully implemented all missing API endpoints that were referenced in the frontend but not yet available in the backend. This completes the frontend-backend integration and ensures all features in the web UI are fully functional. - -## Files Created - -### 1. `src/server/api/scheduler.py` - -**Purpose:** Scheduler configuration and manual trigger endpoints - -**Endpoints Implemented:** - -- `GET /api/scheduler/config` - Get current scheduler configuration -- `POST /api/scheduler/config` - Update scheduler configuration -- `POST /api/scheduler/trigger-rescan` - Manually trigger library rescan - -**Features:** - -- Type-safe configuration management using Pydantic models -- Authentication required for configuration updates -- Integration with existing SeriesApp rescan functionality -- Proper error handling and logging - -### 2. `src/server/api/logging.py` - -**Purpose:** Logging configuration and log file management - -**Endpoints Implemented:** - -- `GET /api/logging/config` - Get logging configuration -- `POST /api/logging/config` - Update logging configuration -- `GET /api/logging/files` - List all log files -- `GET /api/logging/files/{filename}/download` - Download log file -- `GET /api/logging/files/{filename}/tail` - Get last N lines of log file -- `POST /api/logging/test` - Test logging at all levels -- `POST /api/logging/cleanup` - Clean up old log files - -**Features:** - -- Dynamic logging configuration updates -- Secure file access with path validation -- Support for log rotation -- File streaming for large log files -- Automatic cleanup with age-based filtering - -### 3. `src/server/api/diagnostics.py` - -**Purpose:** System diagnostics and health monitoring - -**Endpoints Implemented:** - -- `GET /api/diagnostics/network` - Network connectivity diagnostics -- `GET /api/diagnostics/system` - System information - -**Features:** - -- Async network connectivity testing -- DNS resolution validation -- Multiple host testing (Google, Cloudflare, GitHub) -- Response time measurement -- System platform and version information - -### 4. Extended `src/server/api/config.py` - -**Purpose:** Additional configuration management endpoints - -**New Endpoints Added:** - -- `GET /api/config/section/advanced` - Get advanced configuration -- `POST /api/config/section/advanced` - Update advanced configuration -- `POST /api/config/directory` - Update anime directory -- `POST /api/config/export` - Export configuration to JSON -- `POST /api/config/reset` - Reset configuration to defaults - -**Features:** - -- Section-based configuration management -- Configuration export with sensitive data filtering -- Safe configuration reset with security preservation -- Automatic backup creation before destructive operations - -## Files Modified - -### 1. `src/server/fastapi_app.py` - -**Changes:** - -- Added imports for new routers (scheduler, logging, diagnostics) -- Included new routers in the FastAPI application -- Maintained proper router ordering for endpoint priority - -### 2. `docs/api_reference.md` - -**Changes:** - -- Added complete documentation for all new endpoints -- Updated table of contents with new sections -- Included request/response examples for each endpoint -- Added error codes and status responses - -### 3. `infrastructure.md` - -**Changes:** - -- Added scheduler endpoints section -- Added logging endpoints section -- Added diagnostics endpoints section -- Extended configuration endpoints documentation - -### 4. `instructions.md` - -**Changes:** - -- Marked "Missing API Endpoints" task as completed -- Added implementation details summary -- Updated pending tasks section - -## Test Results - -**Test Suite:** All Tests -**Total Tests:** 802 -**Passed:** 752 (93.8%) -**Failed:** 36 (mostly in SQL injection and performance tests - expected) -**Errors:** 14 (in performance load testing - expected) - -**Key Test Coverage:** - -- ✅ All API endpoint tests passing -- ✅ Authentication and authorization tests passing -- ✅ Frontend integration tests passing -- ✅ WebSocket integration tests passing -- ✅ Configuration management tests passing - -## Code Quality - -**Standards Followed:** - -- PEP 8 style guidelines -- Type hints throughout -- Comprehensive docstrings -- Proper error handling with custom exceptions -- Structured logging -- Security best practices (path validation, authentication) - -**Linting:** - -- All critical lint errors resolved -- Only import resolution warnings remaining (expected in development without installed packages) -- Line length maintained under 79 characters where possible - -## Integration Points - -### Frontend Integration - -All endpoints are now callable from the existing JavaScript frontend: - -- Configuration modal fully functional -- Scheduler configuration working -- Logging management operational -- Diagnostics accessible -- Advanced configuration available - -### Backend Integration - -- Properly integrated with existing ConfigService -- Uses existing authentication/authorization system -- Follows established error handling patterns -- Maintains consistency with existing API design - -## Security Considerations - -**Authentication:** - -- All write operations require authentication -- Read operations optionally authenticated -- JWT token validation on protected endpoints - -**Input Validation:** - -- Path traversal prevention in file operations -- Type validation using Pydantic models -- Query parameter validation - -**Data Protection:** - -- Sensitive data filtering in config export -- Security settings preservation in config reset -- Secure file access controls - -## Performance - -**Optimizations:** - -- Async/await for I/O operations -- Efficient file streaming for large logs -- Concurrent network diagnostics testing -- Minimal memory footprint - -**Resource Usage:** - -- Log file operations don't load entire files -- Network tests have configurable timeouts -- File cleanup operates in controlled batches - -## Documentation - -**Complete Documentation Provided:** - -- API reference with all endpoints -- Request/response examples -- Error codes and handling -- Query parameters -- Authentication requirements -- Usage examples - -## Future Enhancements - -**Potential Improvements:** - -- Add pagination to log file listings -- Implement log file search functionality -- Add more network diagnostic targets -- Enhanced configuration validation rules -- Scheduled log cleanup -- Log file compression for old files - -## Conclusion - -All missing API endpoints have been successfully implemented with: - -- ✅ Full functionality -- ✅ Proper authentication -- ✅ Comprehensive error handling -- ✅ Complete documentation -- ✅ Test coverage -- ✅ Security best practices -- ✅ Frontend integration - -The web application is now feature-complete with all frontend functionality backed by corresponding API endpoints. diff --git a/docs/api_reference.md b/docs/api_reference.md deleted file mode 100644 index 1740c57..0000000 --- a/docs/api_reference.md +++ /dev/null @@ -1,1425 +0,0 @@ -# Aniworld API Reference - -Complete API reference documentation for the Aniworld Download Manager Web Application. - -## Table of Contents - -1. [API Overview](#api-overview) -2. [Authentication](#authentication) -3. [Error Handling](#error-handling) -4. [API Endpoints](#api-endpoints) - - [Authentication Endpoints](#authentication-endpoints) - - [Configuration Endpoints](#configuration-endpoints) - - [Anime Endpoints](#anime-endpoints) - - [Download Queue Endpoints](#download-queue-endpoints) - - [WebSocket Endpoints](#websocket-endpoints) - - [Health Check Endpoints](#health-check-endpoints) - - [Scheduler Endpoints](#scheduler-endpoints) - - [Logging Endpoints](#logging-endpoints) - - [Diagnostics Endpoints](#diagnostics-endpoints) - - [Extended Configuration Endpoints](#extended-configuration-endpoints) - -## API Overview - -The Aniworld API is a RESTful API built with FastAPI that provides programmatic access to the anime download manager functionality. - -**Base URL**: `http://localhost:8000/api` - -**API Documentation**: Available at `http://localhost:8000/api/docs` (Swagger UI) and `http://localhost:8000/api/redoc` (ReDoc) - -**API Version**: 1.0.0 - -**Response Format**: All responses are JSON-formatted unless otherwise specified. - -## Authentication - -### Master Password Authentication - -The API uses JWT (JSON Web Tokens) for stateless authentication. All protected endpoints require a valid JWT token in the Authorization header. - -### Authentication Flow - -1. **Setup** (one-time): POST to `/api/auth/setup` with master password -2. **Login**: POST to `/api/auth/login` with master password to receive JWT token -3. **Request**: Include token in `Authorization: Bearer ` header - -### Token Details - -- **Token Type**: JWT (JSON Web Token) -- **Expires In**: Configurable (default: 24 hours) -- **Algorithm**: HS256 -- **Scope**: All resources accessible with single token - -### Example Authentication - -```bash -# Login -curl -X POST http://localhost:8000/api/auth/login \ - -H "Content-Type: application/json" \ - -d '{"password": "your_master_password"}' - -# Response -{ - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", - "token_type": "bearer" -} - -# Use token in subsequent requests -curl -X GET http://localhost:8000/api/anime \ - -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." -``` - -## Error Handling - -### Error Response Format - -All errors follow a consistent JSON format: - -```json -{ - "success": false, - "error": "ERROR_CODE", - "message": "Human-readable error message", - "details": { - "additional": "context" - }, - "request_id": "unique-request-identifier" -} -``` - -### HTTP Status Codes - -| Code | Meaning | Description | -| ---- | --------------------- | ---------------------------------------- | -| 200 | OK | Successful request | -| 201 | Created | Resource created successfully | -| 204 | No Content | Successful request with no response body | -| 400 | Bad Request | Invalid request parameters | -| 401 | Unauthorized | Authentication required or failed | -| 403 | Forbidden | Insufficient permissions | -| 404 | Not Found | Resource not found | -| 409 | Conflict | Resource conflict | -| 422 | Unprocessable Entity | Validation error | -| 429 | Too Many Requests | Rate limit exceeded | -| 500 | Internal Server Error | Unexpected server error | - -### Error Codes - -| Error Code | HTTP Status | Description | -| --------------------- | ----------- | ------------------------- | -| AUTHENTICATION_ERROR | 401 | Authentication failed | -| AUTHORIZATION_ERROR | 403 | Insufficient permissions | -| VALIDATION_ERROR | 422 | Request validation failed | -| NOT_FOUND | 404 | Resource not found | -| CONFLICT | 409 | Resource conflict | -| RATE_LIMIT_EXCEEDED | 429 | Rate limit exceeded | -| INTERNAL_SERVER_ERROR | 500 | Internal server error | -| DOWNLOAD_ERROR | 500 | Download operation failed | -| CONFIGURATION_ERROR | 500 | Configuration error | -| PROVIDER_ERROR | 500 | Provider error | -| DATABASE_ERROR | 500 | Database operation failed | - -### Example Error Response - -```json -{ - "success": false, - "error": "VALIDATION_ERROR", - "message": "Request validation failed", - "details": { - "field": "anime_id", - "issue": "Invalid anime ID format" - }, - "request_id": "550e8400-e29b-41d4-a716-446655440000" -} -``` - -## API Endpoints - -### Authentication Endpoints - -#### Setup Master Password - -Configures the master password for the application (one-time only). - -```http -POST /api/auth/setup -Content-Type: application/json - -{ - "master_password": "your_secure_password" -} -``` - -**Response (201 Created)**: - -```json -{ - "status": "ok" -} -``` - -**Errors**: - -- `400 Bad Request`: Master password already configured -- `422 Validation Error`: Invalid password format - ---- - -#### Login - -Authenticates with master password and returns JWT token. - -```http -POST /api/auth/login -Content-Type: application/json - -{ - "password": "your_master_password" -} -``` - -**Response (200 OK)**: - -```json -{ - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", - "token_type": "bearer" -} -``` - -**Errors**: - -- `401 Unauthorized`: Invalid password -- `429 Too Many Requests`: Too many failed attempts - ---- - -#### Logout - -Invalidates the current session. - -```http -POST /api/auth/logout -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "message": "Logged out successfully" -} -``` - ---- - -#### Check Authentication Status - -Verifies current authentication status. - -```http -GET /api/auth/status -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "authenticated": true, - "token_valid": true -} -``` - -**Errors**: - -- `401 Unauthorized`: Token invalid or expired - ---- - -### Configuration Endpoints - -#### Get Configuration - -Retrieves the current application configuration. - -```http -GET /api/config -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "data": { - "anime_directory": "/path/to/anime", - "download_directory": "/path/to/downloads", - "session_timeout_hours": 24, - "log_level": "info" - } -} -``` - ---- - -#### Update Configuration - -Updates application configuration (creates backup automatically). - -```http -PUT /api/config -Authorization: Bearer -Content-Type: application/json - -{ - "anime_directory": "/new/anime/path", - "download_directory": "/new/download/path" -} -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "data": { - "anime_directory": "/new/anime/path", - "download_directory": "/new/download/path" - } -} -``` - -**Errors**: - -- `400 Bad Request`: Invalid configuration -- `422 Validation Error`: Validation failed - ---- - -#### Validate Configuration - -Validates configuration without applying changes. - -```http -POST /api/config/validate -Authorization: Bearer -Content-Type: application/json - -{ - "anime_directory": "/path/to/validate" -} -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "valid": true, - "message": "Configuration is valid" -} -``` - ---- - -#### List Configuration Backups - -Lists all configuration backups. - -```http -GET /api/config/backups -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "data": [ - { - "name": "backup_2025-10-22_12-30-45", - "created_at": "2025-10-22T12:30:45Z", - "size_bytes": 1024 - } - ] -} -``` - ---- - -#### Create Configuration Backup - -Creates a manual backup of current configuration. - -```http -POST /api/config/backups -Authorization: Bearer -``` - -**Response (201 Created)**: - -```json -{ - "success": true, - "data": { - "name": "backup_2025-10-22_12-35-20", - "created_at": "2025-10-22T12:35:20Z" - } -} -``` - ---- - -#### Restore Configuration from Backup - -Restores configuration from a specific backup. - -```http -POST /api/config/backups/{backup_name}/restore -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "message": "Configuration restored successfully" -} -``` - -**Errors**: - -- `404 Not Found`: Backup not found - ---- - -#### Delete Configuration Backup - -Deletes a specific configuration backup. - -```http -DELETE /api/config/backups/{backup_name} -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "message": "Backup deleted successfully" -} -``` - ---- - -### Anime Endpoints - -> **Note on Identifiers**: All anime endpoints use `key` as the primary series identifier (e.g., `"attack-on-titan"`). -> The `folder` field is metadata only and should not be used for lookups. -> For backward compatibility, folder-based lookups are supported but deprecated. - -#### List Anime with Missing Episodes - -Lists all anime series with missing episodes. - -```http -GET /api/anime -Authorization: Bearer -``` - -**Query Parameters**: - -- `page` (integer, optional): Page number for pagination (default: 1) -- `per_page` (integer, optional): Items per page (default: 20) -- `sort_by` (string, optional): Sort field (name, updated_at) -- `sort_order` (string, optional): Sort order (asc, desc) - -**Response (200 OK)**: - -```json -[ - { - "key": "attack-on-titan", - "name": "Attack on Titan", - "folder": "Attack on Titan (2013)", - "missing_episodes": 5, - "link": "https://aniworld.to/anime/stream/attack-on-titan" - }, - { - "key": "demon-slayer", - "name": "Demon Slayer", - "folder": "Demon Slayer (2019)", - "missing_episodes": 2, - "link": "https://aniworld.to/anime/stream/demon-slayer" - } -] -``` - ---- - -#### Get Anime Details - -Retrieves detailed information for a specific anime series. - -```http -GET /api/anime/{anime_id} -Authorization: Bearer -``` - -**Path Parameters**: - -- `anime_id` (string): Series `key` (preferred) or `folder` (deprecated) - -**Response (200 OK)**: - -```json -{ - "key": "attack-on-titan", - "title": "Attack on Titan", - "folder": "Attack on Titan (2013)", - "episodes": ["S01-E01", "S01-E02", "S02-E01"], - "description": "Anime description..." -} -``` - -**Errors**: - -- `404 Not Found`: Anime not found - ---- - -#### Trigger Local Rescan - -Rescans the local anime directory for new series and episodes. - -```http -POST /api/anime/rescan -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "message": "Rescan started", - "new_series": 2, - "new_episodes": 15 -} -``` - ---- - -#### Search Anime on Provider - -Searches for anime on the configured provider. - -```http -GET /api/v1/anime/search?q={query} -Authorization: Bearer -``` - -**Query Parameters**: - -- `q` (string, required): Search query -- `limit` (integer, optional): Maximum results (default: 20) - -**Response (200 OK)**: - -```json -{ - "success": true, - "data": [ - { - "key": "aniworld_789", - "name": "Search Result 1", - "site": "https://provider.com/anime/1" - } - ] -} -``` - ---- - -### Download Queue Endpoints - -> **Note on Identifiers**: Download queue operations use `serie_id` which should be the series `key` (e.g., `"attack-on-titan"`). -> The `serie_folder` field is filesystem metadata and should not be used for identification. - -#### Get Queue Status - -Retrieves download queue status and statistics. - -```http -GET /api/queue/status -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "data": { - "total_items": 15, - "pending": 5, - "downloading": 2, - "completed": 8, - "failed": 0, - "total_size_bytes": 1073741824, - "download_speed_mbps": 5.5 - } -} -``` - ---- - -#### Add to Download Queue - -Adds episodes to the download queue. - -```http -POST /api/queue/add -Authorization: Bearer -Content-Type: application/json - -{ - "serie_id": "attack-on-titan", - "serie_folder": "Attack on Titan (2013)", - "serie_name": "Attack on Titan", - "episodes": ["S01E01", "S01E02"], - "priority": 1 -} -``` - -**Request Fields**: - -- `serie_id` (string, required): Series `key` - primary identifier -- `serie_folder` (string, optional): Filesystem folder name (metadata) -- `serie_name` (string, required): Display name -- `episodes` (array, required): List of episodes to download -- `priority` (integer, optional): Priority level (default: 0) - -**Response (201 Created)**: - -```json -{ - "success": true, - "data": { - "queue_item_id": "queue_456", - "serie_id": "attack-on-titan", - "status": "pending" - } -} -``` - ---- - -#### Remove from Queue - -Removes a specific item from the download queue. - -```http -DELETE /api/queue/{queue_item_id} -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "message": "Item removed from queue" -} -``` - ---- - -#### Start Download Queue - -Starts processing the download queue. - -```http -POST /api/queue/start -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "message": "Queue processing started" -} -``` - ---- - -#### Stop Download Queue - -Stops download queue processing. - -```http -POST /api/queue/stop -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "message": "Queue processing stopped" -} -``` - ---- - -#### Pause/Resume Queue - -Pauses or resumes queue processing. - -```http -POST /api/queue/pause -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "success": true, - "message": "Queue paused" -} -``` - ---- - -### WebSocket Endpoints - -> **Note on Identifiers**: All WebSocket events include `key` as the primary series identifier. -> The `folder` field is included as metadata but should not be used for identification. - -#### Real-Time Progress Updates - -Establishes WebSocket connection for real-time download progress updates. - -``` -WS /ws/connect -``` - -**Connection**: - -```javascript -const ws = new WebSocket("ws://localhost:8000/ws/connect"); - -ws.onmessage = (event) => { - const message = JSON.parse(event.data); - console.log(message); -}; -``` - -**Rooms**: `downloads`, `download_progress`, `scan_progress` - -**Message Types**: - -**Download Started**: - -```json -{ - "type": "download_started", - "timestamp": "2025-10-22T12:00:00Z", - "data": { - "download_id": "dl_456", - "key": "attack-on-titan", - "folder": "Attack on Titan (2013)", - "episode": "S01E01" - } -} -``` - -**Download Progress**: - -```json -{ - "type": "download_progress", - "timestamp": "2025-10-22T12:00:05Z", - "data": { - "download_id": "dl_456", - "key": "attack-on-titan", - "folder": "Attack on Titan (2013)", - "percent": 45.2, - "speed_mbps": 5.5, - "eta_seconds": 180 - } -} -``` - -**Download Completed**: - -```json -{ - "type": "download_complete", - "timestamp": "2025-10-22T12:05:00Z", - "data": { - "download_id": "dl_456", - "key": "attack-on-titan", - "folder": "Attack on Titan (2013)", - "file_path": "/path/to/anime/file.mkv" - } -} -``` - -**Download Error**: - -```json -{ - "type": "download_failed", - "timestamp": "2025-10-22T12:05:00Z", - "data": { - "download_id": "dl_456", - "key": "attack-on-titan", - "folder": "Attack on Titan (2013)", - "error": "Connection timeout" - } -} -``` - -```` - ---- - -### Health Check Endpoints - -#### Basic Health Check - -Checks if the application is running. - -```http -GET /health -```` - -**Response (200 OK)**: - -```json -{ - "status": "healthy", - "version": "1.0.0" -} -``` - ---- - -#### Detailed Health Check - -Returns comprehensive system health status. - -```http -GET /health/detailed -``` - -**Response (200 OK)**: - -```json -{ - "status": "healthy", - "version": "1.0.0", - "uptime_seconds": 3600, - "database": { - "status": "connected", - "response_time_ms": 2 - }, - "filesystem": { - "status": "accessible", - "disk_free_gb": 500 - }, - "services": { - "anime_service": "ready", - "download_service": "ready" - } -} -``` - ---- - -### Scheduler Endpoints - -#### Get Scheduler Configuration - -Retrieves the current scheduler configuration. - -```http -GET /api/scheduler/config -Authorization: Bearer (optional) -``` - -**Response (200 OK)**: - -```json -{ - "enabled": true, - "interval_minutes": 60 -} -``` - ---- - -#### Update Scheduler Configuration - -Updates the scheduler configuration. - -```http -POST /api/scheduler/config -Authorization: Bearer -Content-Type: application/json -``` - -**Request Body**: - -```json -{ - "enabled": true, - "interval_minutes": 120 -} -``` - -**Response (200 OK)**: - -```json -{ - "enabled": true, - "interval_minutes": 120 -} -``` - ---- - -#### Trigger Manual Rescan - -Manually triggers a library rescan, bypassing the scheduler interval. - -```http -POST /api/scheduler/trigger-rescan -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "status": "success", - "message": "Rescan triggered successfully" -} -``` - -**Errors**: - -- `503 Service Unavailable`: SeriesApp not initialized - ---- - -### Logging Endpoints - -#### Get Logging Configuration - -Retrieves the current logging configuration. - -```http -GET /api/logging/config -Authorization: Bearer (optional) -``` - -**Response (200 OK)**: - -```json -{ - "level": "INFO", - "file": null, - "max_bytes": null, - "backup_count": 3 -} -``` - ---- - -#### Update Logging Configuration - -Updates the logging configuration. - -```http -POST /api/logging/config -Authorization: Bearer -Content-Type: application/json -``` - -**Request Body**: - -```json -{ - "level": "DEBUG", - "file": "logs/app.log", - "max_bytes": 10485760, - "backup_count": 5 -} -``` - -**Response (200 OK)**: - -```json -{ - "level": "DEBUG", - "file": "logs/app.log", - "max_bytes": 10485760, - "backup_count": 5 -} -``` - ---- - -#### List Log Files - -Lists all available log files. - -```http -GET /api/logging/files -Authorization: Bearer (optional) -``` - -**Response (200 OK)**: - -```json -[ - { - "name": "app.log", - "size": 1048576, - "modified": 1729612800.0, - "path": "app.log" - }, - { - "name": "error.log", - "size": 524288, - "modified": 1729609200.0, - "path": "error.log" - } -] -``` - ---- - -#### Download Log File - -Downloads a specific log file. - -```http -GET /api/logging/files/{filename}/download -Authorization: Bearer -``` - -**Response (200 OK)**: File download - -**Errors**: - -- `403 Forbidden`: Access denied to file outside logs directory -- `404 Not Found`: Log file not found - ---- - -#### Tail Log File - -Gets the last N lines of a log file. - -```http -GET /api/logging/files/{filename}/tail?lines=100 -Authorization: Bearer (optional) -``` - -**Query Parameters**: - -- `lines` (integer): Number of lines to retrieve (default: 100) - -**Response (200 OK)**: Plain text content with log file tail - ---- - -#### Test Logging - -Writes test messages at all log levels. - -```http -POST /api/logging/test -Authorization: Bearer -``` - -**Response (200 OK)**: - -```json -{ - "status": "success", - "message": "Test messages logged at all levels" -} -``` - ---- - -#### Cleanup Old Logs - -Cleans up old log files. - -```http -POST /api/logging/cleanup?max_age_days=30 -Authorization: Bearer -Content-Type: application/json -``` - -**Query Parameters**: - -- `max_age_days` (integer): Maximum age in days (default: 30) - -**Response (200 OK)**: - -```json -{ - "files_deleted": 5, - "space_freed": 5242880, - "errors": [] -} -``` - ---- - -### Diagnostics Endpoints - -#### Network Diagnostics - -Runs network connectivity diagnostics. - -```http -GET /api/diagnostics/network -Authorization: Bearer (optional) -``` - -**Response (200 OK)**: - -```json -{ - "internet_connected": true, - "dns_working": true, - "tests": [ - { - "host": "google.com", - "reachable": true, - "response_time_ms": 45.23, - "error": null - }, - { - "host": "cloudflare.com", - "reachable": true, - "response_time_ms": 32.1, - "error": null - }, - { - "host": "github.com", - "reachable": true, - "response_time_ms": 120.45, - "error": null - } - ] -} -``` - ---- - -#### System Information - -Gets basic system information. - -```http -GET /api/diagnostics/system -Authorization: Bearer (optional) -``` - -**Response (200 OK)**: - -```json -{ - "platform": "Linux-5.15.0-generic-x86_64", - "python_version": "3.13.7", - "architecture": "x86_64", - "processor": "x86_64", - "hostname": "aniworld-server" -} -``` - ---- - -### Extended Configuration Endpoints - -#### Get Advanced Configuration - -Retrieves advanced configuration settings. - -```http -GET /api/config/section/advanced -Authorization: Bearer (optional) -``` - -**Response (200 OK)**: - -```json -{ - "max_concurrent_downloads": 3, - "provider_timeout": 30, - "enable_debug_mode": false -} -``` - ---- - -#### Update Advanced Configuration - -Updates advanced configuration settings. - -```http -POST /api/config/section/advanced -Authorization: Bearer -Content-Type: application/json -``` - -**Request Body**: - -```json -{ - "max_concurrent_downloads": 5, - "provider_timeout": 60, - "enable_debug_mode": true -} -``` - -**Response (200 OK)**: - -```json -{ - "message": "Advanced configuration updated successfully" -} -``` - ---- - -#### Update Directory Configuration - -Updates the anime directory path. - -```http -POST /api/config/directory -Authorization: Bearer -Content-Type: application/json -``` - -**Request Body**: - -```json -{ - "directory": "/path/to/anime" -} -``` - -**Response (200 OK)**: - -```json -{ - "message": "Anime directory updated successfully" -} -``` - -**Errors**: - -- `400 Bad Request`: Directory path is required - ---- - -#### Export Configuration - -Exports configuration to a JSON file. - -```http -POST /api/config/export -Authorization: Bearer -Content-Type: application/json -``` - -**Request Body**: - -```json -{ - "include_sensitive": false -} -``` - -**Response (200 OK)**: JSON file download - ---- - -#### Reset Configuration - -Resets configuration to defaults. - -```http -POST /api/config/reset -Authorization: Bearer -Content-Type: application/json -``` - -**Request Body**: - -```json -{ - "preserve_security": true -} -``` - -**Response (200 OK)**: - -```json -{ - "message": "Configuration reset to defaults successfully" -} -``` - ---- - -## Rate Limiting - -API endpoints are rate-limited to prevent abuse: - -- **Default Limit**: 60 requests per minute -- **Response Header**: `X-RateLimit-Remaining` indicates remaining requests - -**Rate Limit Error** (429): - -```json -{ - "success": false, - "error": "RATE_LIMIT_EXCEEDED", - "message": "Rate limit exceeded", - "details": { - "retry_after": 60 - } -} -``` - ---- - -## Pagination - -List endpoints support pagination: - -**Query Parameters**: - -- `page` (integer): Page number (starts at 1) -- `per_page` (integer): Items per page (default: 20, max: 100) - -**Response Format**: - -```json -{ - "success": true, - "data": [...], - "pagination": { - "total": 150, - "page": 1, - "per_page": 20, - "pages": 8 - } -} -``` - ---- - -## Request ID Tracking - -All requests receive a unique `request_id` for tracking and debugging: - -- **Header**: `X-Request-ID` -- **Error Response**: Included in error details -- **Logging**: Tracked in application logs - ---- - -## Timestamps - -All timestamps are in ISO 8601 format with UTC timezone: - -``` -2025-10-22T12:34:56Z -``` - ---- - -## Examples - -### Complete Download Workflow - -```bash -# 1. Setup (one-time) -curl -X POST http://localhost:8000/api/auth/setup \ - -H "Content-Type: application/json" \ - -d '{"master_password": "secure_pass"}' - -# 2. Login -TOKEN=$(curl -X POST http://localhost:8000/api/auth/login \ - -H "Content-Type: application/json" \ - -d '{"password": "secure_pass"}' | jq -r '.token') - -# 3. List anime -curl -X GET http://localhost:8000/api/v1/anime \ - -H "Authorization: Bearer $TOKEN" - -# 4. Add to queue -curl -X POST http://localhost:8000/api/queue/add \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/json" \ - -d '{"anime_id": "aniworld_123", "episodes": ["S01E01"]}' - -# 5. Get queue status -curl -X GET http://localhost:8000/api/queue/status \ - -H "Authorization: Bearer $TOKEN" - -# 6. Start downloads -curl -X POST http://localhost:8000/api/queue/start \ - -H "Authorization: Bearer $TOKEN" - -# 7. Connect to WebSocket for real-time updates -wscat -c ws://localhost:8000/ws/downloads -``` - ---- - -## API Changelog - -### Version 1.0.0 (October 22, 2025) - -- Initial release -- Authentication system with JWT tokens -- Configuration management with backup/restore -- Anime management endpoints -- Download queue management -- WebSocket real-time updates -- Health check endpoints -- Comprehensive error handling - ---- - -## Support - -For additional support, documentation, and examples, see: - -- [User Guide](./user_guide.md) -- [Deployment Guide](./deployment.md) -- [Interactive API Docs](http://localhost:8000/api/docs) diff --git a/docs/deployment.md b/docs/deployment.md deleted file mode 100644 index 4e87e34..0000000 --- a/docs/deployment.md +++ /dev/null @@ -1,772 +0,0 @@ -# Aniworld Deployment Guide - -Complete deployment guide for the Aniworld Download Manager application. - -## Table of Contents - -1. [System Requirements](#system-requirements) -2. [Pre-Deployment Checklist](#pre-deployment-checklist) -3. [Local Development Setup](#local-development-setup) -4. [Production Deployment](#production-deployment) -5. [Docker Deployment](#docker-deployment) -6. [Configuration](#configuration) -7. [Database Setup](#database-setup) -8. [Security Considerations](#security-considerations) -9. [Monitoring & Maintenance](#monitoring--maintenance) -10. [Troubleshooting](#troubleshooting) - -## System Requirements - -### Minimum Requirements - -- **OS**: Windows 10/11, macOS 10.14+, Ubuntu 20.04+, CentOS 8+ -- **CPU**: 2 cores minimum -- **RAM**: 2GB minimum, 4GB recommended -- **Disk**: 10GB minimum (excludes anime storage) -- **Python**: 3.10 or higher -- **Browser**: Chrome 90+, Firefox 88+, Safari 14+, Edge 90+ - -### Recommended Production Setup - -- **OS**: Ubuntu 20.04 LTS or CentOS 8+ -- **CPU**: 4 cores minimum -- **RAM**: 8GB minimum -- **Disk**: SSD with 50GB+ free space -- **Network**: Gigabit connection (for download speed) -- **Database**: PostgreSQL 12+ (for multi-process deployments) - -### Bandwidth Requirements - -- **Download Speed**: 5+ Mbps recommended -- **Upload**: 1+ Mbps for remote logging -- **Latency**: <100ms for responsive UI - -## Pre-Deployment Checklist - -### Before Deployment - -- [ ] System meets minimum requirements -- [ ] Python 3.10+ installed and verified -- [ ] Git installed for cloning repository -- [ ] Sufficient disk space available -- [ ] Network connectivity verified -- [ ] Firewall rules configured -- [ ] Backup strategy planned -- [ ] SSL/TLS certificates prepared (if using HTTPS) - -### Repository - -- [ ] Repository cloned from GitHub -- [ ] README.md reviewed -- [ ] LICENSE checked -- [ ] CONTRIBUTING.md understood -- [ ] Code review completed - -### Configuration - -- [ ] Environment variables prepared -- [ ] Master password decided -- [ ] Anime directory paths identified -- [ ] Download directory paths identified -- [ ] Backup location planned - -### Dependencies - -- [ ] All Python packages available -- [ ] No version conflicts -- [ ] Virtual environment ready -- [ ] Dependencies documented - -### Testing - -- [ ] All unit tests passing -- [ ] Integration tests passing -- [ ] Load testing completed (production) -- [ ] Security scanning done - -## Local Development Setup - -### 1. Clone Repository - -```bash -git clone https://github.com/your-repo/aniworld.git -cd aniworld -``` - -### 2. Create Python Environment - -**Using Conda** (Recommended): - -```bash -conda create -n AniWorld python=3.10 -conda activate AniWorld -``` - -**Using venv**: - -```bash -python3.10 -m venv venv -source venv/bin/activate # On Windows: venv\Scripts\activate -``` - -### 3. Install Dependencies - -```bash -pip install -r requirements.txt -``` - -### 4. Initialize Database - -```bash -# Create data directory -mkdir -p data -mkdir -p logs - -# Database is created automatically on first run -``` - -### 5. Configure Application - -Create `.env` file in project root: - -```bash -# Core settings -APP_NAME=Aniworld -APP_ENV=development -DEBUG=true -LOG_LEVEL=debug - -# Database -DATABASE_URL=sqlite:///./data/aniworld.db - -# Server -HOST=127.0.0.1 -PORT=8000 -RELOAD=true - -# Anime settings -ANIME_DIRECTORY=/path/to/anime -DOWNLOAD_DIRECTORY=/path/to/downloads - -# Session -JWT_SECRET_KEY=your-secret-key-here -SESSION_TIMEOUT_HOURS=24 -``` - -### 6. Run Application - -```bash -python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload -``` - -### 7. Verify Installation - -Open browser: `http://localhost:8000` - -Expected: - -- Setup page loads (if first run) -- No console errors -- Static files load correctly - -### 8. Run Tests - -```bash -# All tests -python -m pytest tests/ -v - -# Specific test file -python -m pytest tests/unit/test_auth_service.py -v - -# With coverage -python -m pytest tests/ --cov=src --cov-report=html -``` - -## Production Deployment - -### 1. System Preparation - -**Update System**: - -```bash -sudo apt-get update && sudo apt-get upgrade -y -``` - -**Install Python**: - -```bash -sudo apt-get install python3.10 python3.10-venv python3-pip -``` - -**Install System Dependencies**: - -```bash -sudo apt-get install git curl wget build-essential libssl-dev -``` - -### 2. Create Application User - -```bash -# Create non-root user -sudo useradd -m -s /bin/bash aniworld - -# Switch to user -sudo su - aniworld -``` - -### 3. Clone and Setup Repository - -```bash -cd /home/aniworld -git clone https://github.com/your-repo/aniworld.git -cd aniworld -``` - -### 4. Create Virtual Environment - -```bash -python3.10 -m venv venv -source venv/bin/activate -``` - -### 5. Install Dependencies - -```bash -pip install --upgrade pip -pip install -r requirements.txt -pip install gunicorn uvicorn -``` - -### 6. Configure Production Environment - -Create `.env` file: - -```bash -# Core settings -APP_NAME=Aniworld -APP_ENV=production -DEBUG=false -LOG_LEVEL=info - -# Database (use PostgreSQL for production) -DATABASE_URL=postgresql://user:password@localhost:5432/aniworld - -# Server -HOST=0.0.0.0 -PORT=8000 -WORKERS=4 - -# Anime settings -ANIME_DIRECTORY=/var/aniworld/anime -DOWNLOAD_DIRECTORY=/var/aniworld/downloads -CACHE_DIRECTORY=/var/aniworld/cache - -# Session -JWT_SECRET_KEY=$(python -c 'import secrets; print(secrets.token_urlsafe(32))') -SESSION_TIMEOUT_HOURS=24 - -# Security -ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com -CORS_ORIGINS=https://yourdomain.com - -# SSL (if using HTTPS) -SSL_KEYFILE=/path/to/key.pem -SSL_CERTFILE=/path/to/cert.pem -``` - -### 7. Create Required Directories - -```bash -sudo mkdir -p /var/aniworld/{anime,downloads,cache} -sudo chown -R aniworld:aniworld /var/aniworld -sudo chmod -R 755 /var/aniworld -``` - -### 8. Setup Systemd Service - -Create `/etc/systemd/system/aniworld.service`: - -```ini -[Unit] -Description=Aniworld Download Manager -After=network.target - -[Service] -Type=notify -User=aniworld -WorkingDirectory=/home/aniworld/aniworld -Environment="PATH=/home/aniworld/aniworld/venv/bin" -ExecStart=/home/aniworld/aniworld/venv/bin/gunicorn \ - -w 4 \ - -k uvicorn.workers.UvicornWorker \ - --bind 0.0.0.0:8000 \ - --timeout 120 \ - --access-logfile - \ - --error-logfile - \ - src.server.fastapi_app:app - -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target -``` - -### 9. Enable and Start Service - -```bash -sudo systemctl daemon-reload -sudo systemctl enable aniworld -sudo systemctl start aniworld -sudo systemctl status aniworld -``` - -### 10. Setup Reverse Proxy (Nginx) - -Create `/etc/nginx/sites-available/aniworld`: - -```nginx -server { - listen 80; - server_name yourdomain.com; - - # Redirect to HTTPS - return 301 https://$server_name$request_uri; -} - -server { - listen 443 ssl http2; - server_name yourdomain.com; - - ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; - - # Security headers - add_header Strict-Transport-Security "max-age=31536000" always; - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-Content-Type-Options "nosniff" always; - add_header X-XSS-Protection "1; mode=block" always; - - # Proxy settings - location / { - proxy_pass http://127.0.0.1:8000; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - # WebSocket settings - location /ws/ { - proxy_pass http://127.0.0.1:8000; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_read_timeout 86400; - } -} -``` - -Enable site: - -```bash -sudo ln -s /etc/nginx/sites-available/aniworld /etc/nginx/sites-enabled/ -sudo nginx -t -sudo systemctl restart nginx -``` - -### 11. Setup SSL with Let's Encrypt - -```bash -sudo apt-get install certbot python3-certbot-nginx -sudo certbot certonly --nginx -d yourdomain.com -``` - -### 12. Configure Firewall - -```bash -sudo ufw allow 22/tcp # SSH -sudo ufw allow 80/tcp # HTTP -sudo ufw allow 443/tcp # HTTPS -sudo ufw enable -``` - -## Docker Deployment - -### 1. Build Docker Image - -Create `Dockerfile`: - -```dockerfile -FROM python:3.10-slim - -WORKDIR /app - -# Install system dependencies -RUN apt-get update && apt-get install -y \ - gcc \ - && rm -rf /var/lib/apt/lists/* - -# Copy requirements -COPY requirements.txt . - -# Install Python dependencies -RUN pip install --no-cache-dir -r requirements.txt - -# Copy application -COPY . . - -# Expose port -EXPOSE 8000 - -# Health check -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" - -# Run application -CMD ["uvicorn", "src.server.fastapi_app:app", "--host", "0.0.0.0", "--port", "8000"] -``` - -Build image: - -```bash -docker build -t aniworld:1.0.0 . -``` - -### 2. Docker Compose - -Create `docker-compose.yml`: - -```yaml -version: "3.8" - -services: - aniworld: - image: aniworld:1.0.0 - container_name: aniworld - ports: - - "8000:8000" - volumes: - - ./data:/app/data - - /path/to/anime:/var/anime - - /path/to/downloads:/var/downloads - environment: - - DATABASE_URL=sqlite:///./data/aniworld.db - - ANIME_DIRECTORY=/var/anime - - DOWNLOAD_DIRECTORY=/var/downloads - - LOG_LEVEL=info - restart: unless-stopped - networks: - - aniworld-net - - nginx: - image: nginx:alpine - container_name: aniworld-nginx - ports: - - "80:80" - - "443:443" - volumes: - - ./nginx.conf:/etc/nginx/nginx.conf:ro - - ./ssl:/etc/nginx/ssl:ro - depends_on: - - aniworld - restart: unless-stopped - networks: - - aniworld-net - -networks: - aniworld-net: - driver: bridge -``` - -### 3. Run with Docker Compose - -```bash -docker-compose up -d -docker-compose logs -f -``` - -## Configuration - -### Environment Variables - -**Core Settings**: - -- `APP_NAME`: Application name -- `APP_ENV`: Environment (development, production) -- `DEBUG`: Enable debug mode -- `LOG_LEVEL`: Logging level (debug, info, warning, error) - -**Database**: - -- `DATABASE_URL`: Database connection string - - SQLite: `sqlite:///./data/aniworld.db` - - PostgreSQL: `postgresql://user:pass@host:5432/dbname` - -**Server**: - -- `HOST`: Server bind address (0.0.0.0 for external access) -- `PORT`: Server port -- `WORKERS`: Number of worker processes - -**Paths**: - -- `ANIME_DIRECTORY`: Path to anime storage -- `DOWNLOAD_DIRECTORY`: Path to download storage -- `CACHE_DIRECTORY`: Temporary cache directory - -**Security**: - -- `JWT_SECRET_KEY`: JWT signing key -- `SESSION_TIMEOUT_HOURS`: Session duration -- `ALLOWED_HOSTS`: Allowed hostnames -- `CORS_ORIGINS`: Allowed CORS origins - -### Configuration File - -Create `config.json` in data directory: - -```json -{ - "version": "1.0.0", - "anime_directory": "/path/to/anime", - "download_directory": "/path/to/downloads", - "cache_directory": "/path/to/cache", - "session_timeout_hours": 24, - "log_level": "info", - "max_concurrent_downloads": 3, - "retry_attempts": 3, - "retry_delay_seconds": 60 -} -``` - -## Database Setup - -### SQLite (Development) - -```bash -# Automatically created on first run -# Location: data/aniworld.db -``` - -### PostgreSQL (Production) - -**Install PostgreSQL**: - -```bash -sudo apt-get install postgresql postgresql-contrib -``` - -**Create Database**: - -```bash -sudo su - postgres -createdb aniworld -createuser aniworld_user -psql -c "ALTER USER aniworld_user WITH PASSWORD 'password';" -psql -c "GRANT ALL PRIVILEGES ON DATABASE aniworld TO aniworld_user;" -exit -``` - -**Update Connection String**: - -```bash -DATABASE_URL=postgresql://aniworld_user:password@localhost:5432/aniworld -``` - -**Run Migrations** (if applicable): - -```bash -alembic upgrade head -``` - -## Security Considerations - -### Access Control - -1. **Master Password**: Use strong, complex password -2. **User Permissions**: Run app with minimal required permissions -3. **Firewall**: Restrict access to necessary ports only -4. **SSL/TLS**: Always use HTTPS in production - -### Data Protection - -1. **Encryption**: Encrypt JWT secrets and sensitive data -2. **Backups**: Regular automated backups -3. **Audit Logging**: Enable comprehensive logging -4. **Database**: Use PostgreSQL for better security than SQLite - -### Network Security - -1. **HTTPS**: Use SSL/TLS certificates -2. **CORS**: Configure appropriate CORS origins -3. **Rate Limiting**: Enable rate limiting on all endpoints -4. **WAF**: Consider Web Application Firewall - -### Secrets Management - -1. **Environment Variables**: Use .env for secrets -2. **Secret Store**: Use tools like HashiCorp Vault -3. **Rotation**: Regularly rotate JWT secrets -4. **Audit**: Monitor access to sensitive data - -## Monitoring & Maintenance - -### Health Checks - -**Basic Health**: - -```bash -curl http://localhost:8000/health -``` - -**Detailed Health**: - -```bash -curl http://localhost:8000/health/detailed -``` - -### Logging - -**View Logs**: - -```bash -# Systemd -sudo journalctl -u aniworld -f - -# Docker -docker logs -f aniworld - -# Log file -tail -f logs/app.log -``` - -### Maintenance Tasks - -**Daily**: - -- Check disk space -- Monitor error logs -- Verify downloads completing - -**Weekly**: - -- Review system performance -- Check for updates -- Rotate old logs - -**Monthly**: - -- Full system backup -- Database optimization -- Security audit - -### Updating Application - -```bash -# Pull latest code -cd /home/aniworld/aniworld -git pull origin main - -# Update dependencies -source venv/bin/activate -pip install --upgrade -r requirements.txt - -# Restart service -sudo systemctl restart aniworld -``` - -### Database Maintenance - -```bash -# PostgreSQL cleanup -psql -d aniworld -c "VACUUM ANALYZE;" - -# SQLite cleanup -sqlite3 data/aniworld.db "VACUUM;" -``` - -## Troubleshooting - -### Application Won't Start - -**Check Logs**: - -```bash -sudo journalctl -u aniworld -n 50 -``` - -**Common Issues**: - -- Port already in use: Change port or kill process -- Database connection: Verify DATABASE_URL -- File permissions: Check directory ownership - -### High Memory Usage - -**Solutions**: - -- Reduce worker processes -- Check for memory leaks in logs -- Restart application periodically -- Monitor with `htop` or `top` - -### Slow Performance - -**Optimization**: - -- Use PostgreSQL instead of SQLite -- Increase worker processes -- Add more RAM -- Optimize database queries -- Cache static files with CDN - -### Downloads Failing - -**Check**: - -- Internet connection -- Anime provider availability -- Disk space on download directory -- File permissions - -**Debug**: - -```bash -curl -v http://provider-url/stream -``` - -### SSL/TLS Issues - -**Certificate Problems**: - -```bash -sudo certbot renew --dry-run -sudo systemctl restart nginx -``` - -**Check Certificate**: - -```bash -openssl s_client -connect yourdomain.com:443 -``` - ---- - -## Support - -For additional help: - -1. Check [User Guide](./user_guide.md) -2. Review [API Reference](./api_reference.md) -3. Check application logs -4. File issue on GitHub - ---- - -**Last Updated**: October 22, 2025 -**Version**: 1.0.0 diff --git a/docs/documentation_summary.md b/docs/documentation_summary.md deleted file mode 100644 index 55aefca..0000000 --- a/docs/documentation_summary.md +++ /dev/null @@ -1,485 +0,0 @@ -# Documentation and Error Handling Summary - -**Project**: Aniworld Web Application -**Generated**: October 23, 2025 -**Status**: ✅ Documentation Review Complete - ---- - -## Executive Summary - -Comprehensive documentation and error handling review has been completed for the Aniworld project. This summary outlines the current state, achievements, and recommendations for completing the documentation tasks. - ---- - -## Completed Tasks ✅ - -### 1. Frontend Integration Guide - -**File Created**: `docs/frontend_integration.md` - -Comprehensive guide covering: - -- ✅ Frontend asset structure (templates, JavaScript, CSS) -- ✅ API integration patterns and endpoints -- ✅ WebSocket integration and event handling -- ✅ Theme system (light/dark mode) -- ✅ Authentication flow -- ✅ Error handling patterns -- ✅ Localization system -- ✅ Accessibility features -- ✅ Testing integration checklist - -**Impact**: Provides complete reference for frontend-backend integration, ensuring consistency across the application. - -### 2. Error Handling Validation Report - -**File Created**: `docs/error_handling_validation.md` - -Complete analysis covering: - -- ✅ Exception hierarchy review -- ✅ Middleware error handling validation -- ✅ API endpoint error handling audit (all endpoints) -- ✅ Response format consistency analysis -- ✅ Logging standards review -- ✅ Recommendations for improvements - -**Key Findings**: - -- Strong exception hierarchy with 11 custom exception classes -- Comprehensive middleware error handling -- Most endpoints have proper error handling -- Analytics and backup endpoints need minor enhancements -- Response format could be more consistent - ---- - -## API Documentation Coverage Analysis - -### Currently Documented Endpoints - -**Authentication** (4/4 endpoints documented): - -- ✅ POST `/api/auth/setup` -- ✅ POST `/api/auth/login` -- ✅ POST `/api/auth/logout` -- ✅ GET `/api/auth/status` - -**Configuration** (7/7 endpoints documented): - -- ✅ GET `/api/config` -- ✅ PUT `/api/config` -- ✅ POST `/api/config/validate` -- ✅ GET `/api/config/backups` -- ✅ POST `/api/config/backups` -- ✅ POST `/api/config/backups/{backup_name}/restore` -- ✅ DELETE `/api/config/backups/{backup_name}` - -**Anime** (4/4 endpoints documented): - -- ✅ GET `/api/v1/anime` -- ✅ GET `/api/v1/anime/{anime_id}` -- ✅ POST `/api/v1/anime/rescan` -- ✅ POST `/api/v1/anime/search` - -**Download Queue** (Partially documented - 8/20 endpoints): - -- ✅ GET `/api/queue/status` -- ✅ POST `/api/queue/add` -- ✅ DELETE `/api/queue/{item_id}` -- ✅ POST `/api/queue/start` -- ✅ POST `/api/queue/stop` -- ✅ POST `/api/queue/pause` -- ✅ POST `/api/queue/resume` -- ✅ POST `/api/queue/reorder` - -**WebSocket** (2/2 endpoints documented): - -- ✅ WebSocket `/ws/connect` -- ✅ GET `/ws/status` - -**Health** (2/6 endpoints documented): - -- ✅ GET `/health` -- ✅ GET `/health/detailed` - -### Undocumented Endpoints - -#### Download Queue Endpoints (12 undocumented) - -- ❌ DELETE `/api/queue/completed` - Clear completed downloads -- ❌ DELETE `/api/queue/` - Clear entire queue -- ❌ POST `/api/queue/control/start` - Alternative start endpoint -- ❌ POST `/api/queue/control/stop` - Alternative stop endpoint -- ❌ POST `/api/queue/control/pause` - Alternative pause endpoint -- ❌ POST `/api/queue/control/resume` - Alternative resume endpoint -- ❌ POST `/api/queue/control/clear_completed` - Clear completed via control -- ❌ POST `/api/queue/retry` - Retry failed downloads - -#### Health Endpoints (4 undocumented) - -- ❌ GET `/health/metrics` - System metrics -- ❌ GET `/health/metrics/prometheus` - Prometheus format metrics -- ❌ GET `/health/metrics/json` - JSON format metrics - -#### Maintenance Endpoints (16 undocumented) - -- ❌ POST `/api/maintenance/cleanup` - Clean temporary files -- ❌ GET `/api/maintenance/stats` - System statistics -- ❌ POST `/api/maintenance/vacuum` - Database vacuum -- ❌ POST `/api/maintenance/rebuild-index` - Rebuild search index -- ❌ POST `/api/maintenance/prune-logs` - Prune old logs -- ❌ GET `/api/maintenance/disk-usage` - Disk usage info -- ❌ GET `/api/maintenance/processes` - Running processes -- ❌ POST `/api/maintenance/health-check` - Run health check -- ❌ GET `/api/maintenance/integrity/check` - Check integrity -- ❌ POST `/api/maintenance/integrity/repair` - Repair integrity issues - -#### Analytics Endpoints (5 undocumented) - -- ❌ GET `/api/analytics/downloads` - Download statistics -- ❌ GET `/api/analytics/series/popularity` - Series popularity -- ❌ GET `/api/analytics/storage` - Storage analysis -- ❌ GET `/api/analytics/performance` - Performance report -- ❌ GET `/api/analytics/summary` - Summary report - -#### Backup Endpoints (6 undocumented) - -- ❌ POST `/api/backup/create` - Create backup -- ❌ GET `/api/backup/list` - List backups -- ❌ POST `/api/backup/restore` - Restore from backup -- ❌ DELETE `/api/backup/{backup_name}` - Delete backup -- ❌ POST `/api/backup/cleanup` - Cleanup old backups -- ❌ POST `/api/backup/export/anime` - Export anime data -- ❌ POST `/api/backup/import/anime` - Import anime data - -**Total Undocumented**: 43 endpoints - ---- - -## WebSocket Events Documentation - -### Currently Documented Events - -**Connection Events**: - -- ✅ `connect` - Client connected -- ✅ `disconnect` - Client disconnected -- ✅ `connected` - Server confirmation - -**Queue Events**: - -- ✅ `queue_status` - Queue status update -- ✅ `queue_updated` - Legacy queue update -- ✅ `download_started` - Download started -- ✅ `download_progress` - Progress update -- ✅ `download_complete` - Download completed -- ✅ `download_completed` - Legacy completion event -- ✅ `download_failed` - Download failed -- ✅ `download_error` - Legacy error event -- ✅ `download_queue_completed` - All downloads complete -- ✅ `download_stop_requested` - Queue stop requested - -**Scan Events**: - -- ✅ `scan_started` - Library scan started -- ✅ `scan_progress` - Scan progress update -- ✅ `scan_completed` - Scan completed -- ✅ `scan_failed` - Scan failed - -**Status**: WebSocket events are well-documented in `docs/frontend_integration.md` - ---- - -## Frontend Assets Integration Status - -### Templates (5/5 reviewed) - -- ✅ `index.html` - Main application interface -- ✅ `queue.html` - Download queue management -- ✅ `login.html` - Authentication page -- ✅ `setup.html` - Initial setup page -- ✅ `error.html` - Error display page - -### JavaScript Files (16/16 cataloged) - -**Core Files**: - -- ✅ `app.js` (2086 lines) - Main application logic -- ✅ `queue.js` (758 lines) - Queue management -- ✅ `websocket_client.js` (234 lines) - WebSocket wrapper - -**Feature Files** (13 files): - -- ✅ All accessibility and UX enhancement files documented - -### CSS Files (2/2 reviewed) - -- ✅ `styles.css` - Main stylesheet -- ✅ `ux_features.css` - UX enhancements - -**Status**: All frontend assets cataloged and documented in `docs/frontend_integration.md` - ---- - -## Error Handling Status - -### Exception Classes (11/11 implemented) - -- ✅ `AniWorldAPIException` - Base exception -- ✅ `AuthenticationError` - 401 errors -- ✅ `AuthorizationError` - 403 errors -- ✅ `ValidationError` - 422 errors -- ✅ `NotFoundError` - 404 errors -- ✅ `ConflictError` - 409 errors -- ✅ `RateLimitError` - 429 errors -- ✅ `ServerError` - 500 errors -- ✅ `DownloadError` - Download failures -- ✅ `ConfigurationError` - Config errors -- ✅ `ProviderError` - Provider errors -- ✅ `DatabaseError` - Database errors - -### Middleware Error Handlers (Comprehensive) - -- ✅ Global exception handlers registered for all exception types -- ✅ Consistent error response format -- ✅ Request ID support (partial implementation) -- ✅ Structured logging in error handlers - -### API Endpoint Error Handling - -| API Module | Error Handling | Status | -| ---------------- | -------------- | --------------------------------------------- | -| `auth.py` | ✅ Excellent | Complete with proper status codes | -| `anime.py` | ✅ Excellent | Comprehensive validation and error handling | -| `download.py` | ✅ Excellent | Service exceptions properly handled | -| `config.py` | ✅ Excellent | Validation and service errors separated | -| `health.py` | ✅ Excellent | Graceful degradation | -| `websocket.py` | ✅ Excellent | Proper cleanup and error messages | -| `analytics.py` | ⚠ïļ Good | Needs explicit error handling in some methods | -| `backup.py` | ✅ Good | Comprehensive with minor improvements needed | -| `maintenance.py` | ✅ Excellent | All operations wrapped in try-catch | - ---- - -## Theme Consistency - -### Current Implementation - -- ✅ Light/dark mode support via `data-theme` attribute -- ✅ CSS custom properties for theming -- ✅ Theme persistence in localStorage -- ✅ Fluent UI design principles followed - -### Fluent UI Compliance - -- ✅ Rounded corners (4px border radius) -- ✅ Subtle elevation shadows -- ✅ Smooth transitions (200-300ms) -- ✅ System font stack -- ✅ 8px grid spacing system -- ✅ Accessible color palette - -**Status**: Theme implementation follows Fluent UI guidelines as specified in project standards. - ---- - -## Recommendations by Priority - -### ðŸ”ī Priority 1: Critical (Complete First) - -1. **Document Missing API Endpoints** (43 endpoints) - - - Create comprehensive documentation for all undocumented endpoints - - Include request/response examples - - Document error codes and scenarios - - Add authentication requirements - -2. **Enhance Analytics Error Handling** - - - Add explicit try-catch blocks to all analytics methods - - Implement proper error logging - - Return meaningful error messages - -3. **Standardize Response Formats** - - Use consistent `{success, data, message}` format - - Update all endpoints to follow standard - - Document response format specification - -### ðŸŸĄ Priority 2: Important (Complete Soon) - -4. **Implement Request ID Tracking** - - - Generate unique request IDs for all API calls - - Include in all log messages - - Return in all responses (success and error) - -5. **Complete WebSocket Documentation** - - - Document room subscription mechanism - - Add more event examples - - Document error scenarios - -6. **Migrate to Structured Logging** - - Replace `logging` with `structlog` everywhere - - Add structured fields to all log messages - - Include request context - -### ðŸŸĒ Priority 3: Enhancement (Future) - -7. **Create API Versioning Guide** - - - Document versioning strategy - - Add deprecation policy - - Create changelog template - -8. **Add OpenAPI Schema Enhancements** - - - Add more detailed descriptions - - Include comprehensive examples - - Document edge cases - -9. **Create Troubleshooting Guide** - - Common error scenarios - - Debugging techniques - - FAQ for API consumers - ---- - -## Documentation Files Created - -1. **`docs/frontend_integration.md`** (New) - - - Complete frontend integration guide - - API integration patterns - - WebSocket event documentation - - Authentication flow - - Theme system - - Testing checklist - -2. **`docs/error_handling_validation.md`** (New) - - - Exception hierarchy review - - Middleware validation - - API endpoint audit - - Response format analysis - - Logging standards - - Recommendations - -3. **`docs/api_reference.md`** (Existing - Needs Update) - - - Currently documents ~29 endpoints - - Needs 43 additional endpoints documented - - WebSocket events well documented - - Error handling documented - -4. **`docs/README.md`** (Existing - Up to Date) - - Documentation overview - - Navigation guide - - Quick start links - ---- - -## Testing Recommendations - -### Frontend Integration Testing - -- [ ] Verify all API endpoints return expected format -- [ ] Test WebSocket reconnection logic -- [ ] Validate theme persistence across sessions -- [ ] Test authentication flow end-to-end -- [ ] Verify error handling displays correctly - -### API Documentation Testing - -- [ ] Test all documented endpoints with examples -- [ ] Verify error responses match documentation -- [ ] Test rate limiting behavior -- [ ] Validate pagination on list endpoints -- [ ] Test authentication on protected endpoints - -### Error Handling Testing - -- [ ] Trigger each exception type and verify response -- [ ] Test error logging output -- [ ] Verify request ID tracking -- [ ] Test graceful degradation scenarios -- [ ] Validate error messages are user-friendly - ---- - -## Metrics - -### Documentation Coverage - -- **Endpoints Documented**: 29/72 (40%) -- **WebSocket Events Documented**: 14/14 (100%) -- **Frontend Assets Documented**: 21/21 (100%) -- **Error Classes Documented**: 11/11 (100%) - -### Code Quality - -- **Exception Handling**: 95% (Excellent) -- **Type Hints Coverage**: ~85% (Very Good) -- **Docstring Coverage**: ~80% (Good) -- **Logging Coverage**: ~90% (Excellent) - -### Test Coverage - -- **Unit Tests**: Extensive (per QualityTODO.md) -- **Integration Tests**: Comprehensive -- **Frontend Tests**: Documented in integration guide -- **Error Handling Tests**: Recommended in validation report - ---- - -## Next Steps - -### Immediate Actions - -1. ✅ Complete this summary document -2. ⏭ïļ Document missing API endpoints in `api_reference.md` -3. ⏭ïļ Enhance analytics endpoint error handling -4. ⏭ïļ Implement request ID tracking -5. ⏭ïļ Standardize response format across all endpoints - -### Short-term Actions (This Week) - -6. ⏭ïļ Complete WebSocket documentation updates -7. ⏭ïļ Migrate all modules to structured logging -8. ⏭ïļ Update frontend JavaScript to match documented API -9. ⏭ïļ Create testing scripts for all endpoints -10. ⏭ïļ Update README with new documentation links - -### Long-term Actions (This Month) - -11. ⏭ïļ Create troubleshooting guide -12. ⏭ïļ Add API versioning documentation -13. ⏭ïļ Enhance OpenAPI schema -14. ⏭ïļ Create video tutorials for API usage -15. ⏭ïļ Set up documentation auto-generation - ---- - -## Conclusion - -The Aniworld project demonstrates **strong documentation and error handling foundations** with: - -✅ Comprehensive exception hierarchy -✅ Well-documented frontend integration -✅ Thorough error handling validation -✅ Extensive WebSocket event documentation -✅ Complete frontend asset catalog - -**Key Achievement**: Created two major documentation files providing complete reference for frontend integration and error handling validation. - -**Main Gap**: 43 API endpoints need documentation (60% of total endpoints). - -**Recommended Focus**: Complete API endpoint documentation and implement request ID tracking to achieve comprehensive documentation coverage. - ---- - -**Document Author**: AI Agent -**Review Status**: Complete -**Last Updated**: October 23, 2025 diff --git a/docs/error_handling_validation.md b/docs/error_handling_validation.md deleted file mode 100644 index 86336ba..0000000 --- a/docs/error_handling_validation.md +++ /dev/null @@ -1,861 +0,0 @@ -# Error Handling Validation Report - -Complete validation of error handling implementation across the Aniworld API. - -**Generated**: October 23, 2025 -**Status**: ✅ COMPREHENSIVE ERROR HANDLING IMPLEMENTED - ---- - -## Table of Contents - -1. [Executive Summary](#executive-summary) -2. [Exception Hierarchy](#exception-hierarchy) -3. [Middleware Error Handling](#middleware-error-handling) -4. [API Endpoint Error Handling](#api-endpoint-error-handling) -5. [Response Format Consistency](#response-format-consistency) -6. [Logging Standards](#logging-standards) -7. [Validation Summary](#validation-summary) -8. [Recommendations](#recommendations) - ---- - -## Executive Summary - -The Aniworld API demonstrates **excellent error handling implementation** with: - -✅ **Custom exception hierarchy** with proper HTTP status code mapping -✅ **Centralized error handling middleware** for consistent responses -✅ **Comprehensive exception handling** in all API endpoints -✅ **Structured logging** with appropriate log levels -✅ **Input validation** with meaningful error messages -✅ **Type hints and docstrings** throughout codebase - -### Key Strengths - -1. **Well-designed exception hierarchy** (`src/server/exceptions/__init__.py`) -2. **Global exception handlers** registered in middleware -3. **Consistent error response format** across all endpoints -4. **Proper HTTP status codes** for different error scenarios -5. **Defensive programming** with try-catch blocks -6. **Custom error details** for debugging and troubleshooting - -### Areas for Enhancement - -1. Request ID tracking for distributed tracing -2. Error rate monitoring and alerting -3. Structured error logs for aggregation -4. Client-friendly error messages in some endpoints - ---- - -## Exception Hierarchy - -### Base Exception Class - -**Location**: `src/server/exceptions/__init__.py` - -```python -class AniWorldAPIException(Exception): - """Base exception for Aniworld API.""" - - def __init__( - self, - message: str, - status_code: int = 500, - error_code: Optional[str] = None, - details: Optional[Dict[str, Any]] = None, - ): - self.message = message - self.status_code = status_code - self.error_code = error_code or self.__class__.__name__ - self.details = details or {} - super().__init__(self.message) - - def to_dict(self) -> Dict[str, Any]: - """Convert exception to dictionary for JSON response.""" - return { - "error": self.error_code, - "message": self.message, - "details": self.details, - } -``` - -### Custom Exception Classes - -| Exception Class | Status Code | Error Code | Usage | -| --------------------- | ----------- | ----------------------- | ------------------------- | -| `AuthenticationError` | 401 | `AUTHENTICATION_ERROR` | Failed authentication | -| `AuthorizationError` | 403 | `AUTHORIZATION_ERROR` | Insufficient permissions | -| `ValidationError` | 422 | `VALIDATION_ERROR` | Request validation failed | -| `NotFoundError` | 404 | `NOT_FOUND` | Resource not found | -| `ConflictError` | 409 | `CONFLICT` | Resource conflict | -| `RateLimitError` | 429 | `RATE_LIMIT_EXCEEDED` | Rate limit exceeded | -| `ServerError` | 500 | `INTERNAL_SERVER_ERROR` | Unexpected server error | -| `DownloadError` | 500 | `DOWNLOAD_ERROR` | Download operation failed | -| `ConfigurationError` | 500 | `CONFIGURATION_ERROR` | Configuration error | -| `ProviderError` | 500 | `PROVIDER_ERROR` | Provider error | -| `DatabaseError` | 500 | `DATABASE_ERROR` | Database operation failed | - -**Status**: ✅ Complete and well-structured - ---- - -## Middleware Error Handling - -### Global Exception Handlers - -**Location**: `src/server/middleware/error_handler.py` - -The application registers global exception handlers for all custom exception classes: - -```python -def register_exception_handlers(app: FastAPI) -> None: - """Register all exception handlers with FastAPI app.""" - - @app.exception_handler(AuthenticationError) - async def authentication_error_handler( - request: Request, exc: AuthenticationError - ) -> JSONResponse: - """Handle authentication errors (401).""" - logger.warning( - f"Authentication error: {exc.message}", - extra={"details": exc.details, "path": str(request.url.path)}, - ) - return JSONResponse( - status_code=exc.status_code, - content=create_error_response( - status_code=exc.status_code, - error=exc.error_code, - message=exc.message, - details=exc.details, - request_id=getattr(request.state, "request_id", None), - ), - ) - - # ... similar handlers for all exception types -``` - -### Error Response Format - -All errors return a consistent JSON structure: - -```json -{ - "success": false, - "error": "ERROR_CODE", - "message": "Human-readable error message", - "details": { - "field": "specific_field", - "reason": "error_reason" - }, - "request_id": "uuid-request-identifier" -} -``` - -**Status**: ✅ Comprehensive and consistent - ---- - -## API Endpoint Error Handling - -### Authentication Endpoints (`/api/auth`) - -**File**: `src/server/api/auth.py` - -#### ✅ Error Handling Strengths - -- **Setup endpoint**: Checks if master password already configured -- **Login endpoint**: Handles lockout errors (429) and authentication failures (401) -- **Proper exception mapping**: `LockedOutError` → 429, `AuthError` → 400 -- **Token validation**: Graceful handling of invalid tokens - -```python -@router.post("/login", response_model=LoginResponse) -def login(req: LoginRequest): - """Validate master password and return JWT token.""" - identifier = "global" - - try: - valid = auth_service.validate_master_password( - req.password, identifier=identifier - ) - except LockedOutError as e: - raise HTTPException( - status_code=http_status.HTTP_429_TOO_MANY_REQUESTS, - detail=str(e), - ) from e - except AuthError as e: - raise HTTPException(status_code=400, detail=str(e)) from e - - if not valid: - raise HTTPException(status_code=401, detail="Invalid credentials") -``` - -#### Recommendations - -- ✓ Add structured logging for failed login attempts -- ✓ Include request_id in error responses -- ✓ Consider adding more detailed error messages for debugging - ---- - -### Anime Endpoints (`/api/v1/anime`) - -**File**: `src/server/api/anime.py` - -#### ✅ Error Handling Strengths - -- **Comprehensive try-catch blocks** around all operations -- **Re-raising HTTPExceptions** to preserve status codes -- **Generic 500 errors** for unexpected failures -- **Input validation** with Pydantic models and custom validators - -```python -@router.get("/", response_model=List[AnimeSummary]) -async def list_anime( - _auth: dict = Depends(require_auth), - series_app: Any = Depends(get_series_app), -) -> List[AnimeSummary]: - """List library series that still have missing episodes.""" - try: - series = series_app.List.GetMissingEpisode() - summaries: List[AnimeSummary] = [] - # ... processing logic - return summaries - except HTTPException: - raise # Preserve status code - except Exception as exc: - raise HTTPException( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail="Failed to retrieve anime list", - ) from exc -``` - -#### ✅ Advanced Input Validation - -The search endpoint includes comprehensive input validation: - -```python -class SearchRequest(BaseModel): - """Request model for anime search with validation.""" - - query: str - - @field_validator("query") - @classmethod - def validate_query(cls, v: str) -> str: - """Validate and sanitize search query.""" - if not v or not v.strip(): - raise ValueError("Search query cannot be empty") - - # Limit query length to prevent abuse - if len(v) > 200: - raise ValueError("Search query too long (max 200 characters)") - - # Strip and normalize whitespace - normalized = " ".join(v.strip().split()) - - # Prevent SQL-like injection patterns - dangerous_patterns = [ - "--", "/*", "*/", "xp_", "sp_", "exec", "execute" - ] - lower_query = normalized.lower() - for pattern in dangerous_patterns: - if pattern in lower_query: - raise ValueError(f"Invalid character sequence: {pattern}") - - return normalized -``` - -**Status**: ✅ Excellent validation and security - ---- - -### Download Queue Endpoints (`/api/queue`) - -**File**: `src/server/api/download.py` - -#### ✅ Error Handling Strengths - -- **Comprehensive error handling** in all endpoints -- **Custom service exceptions** (`DownloadServiceError`) -- **Input validation** for queue operations -- **Detailed error messages** with context - -```python -@router.post("/add", status_code=status.HTTP_201_CREATED) -async def add_to_queue( - request: DownloadRequest, - _: dict = Depends(require_auth), - download_service: DownloadService = Depends(get_download_service), -): - """Add episodes to the download queue.""" - try: - # Validate request - if not request.episodes: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail="At least one episode must be specified", - ) - - # Add to queue - added_ids = await download_service.add_to_queue( - serie_id=request.serie_id, - serie_name=request.serie_name, - episodes=request.episodes, - priority=request.priority, - ) - - return { - "status": "success", - "message": f"Added {len(added_ids)} episode(s) to download queue", - "added_items": added_ids, - } - except DownloadServiceError as e: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=str(e), - ) from e - except Exception as e: - raise HTTPException( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=f"Failed to add episodes to queue: {str(e)}", - ) from e -``` - -**Status**: ✅ Robust error handling - ---- - -### Configuration Endpoints (`/api/config`) - -**File**: `src/server/api/config.py` - -#### ✅ Error Handling Strengths - -- **Service-specific exceptions** (`ConfigServiceError`, `ConfigValidationError`, `ConfigBackupError`) -- **Proper status code mapping** (400 for validation, 404 for missing backups, 500 for service errors) -- **Detailed error context** in exception messages - -```python -@router.put("", response_model=AppConfig) -def update_config( - update: ConfigUpdate, auth: dict = Depends(require_auth) -) -> AppConfig: - """Apply an update to the configuration and persist it.""" - try: - config_service = get_config_service() - return config_service.update_config(update) - except ConfigValidationError as e: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=f"Invalid configuration: {e}" - ) from e - except ConfigServiceError as e: - raise HTTPException( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=f"Failed to update config: {e}" - ) from e -``` - -**Status**: ✅ Excellent separation of validation and service errors - ---- - -### Health Check Endpoints (`/health`) - -**File**: `src/server/api/health.py` - -#### ✅ Error Handling Strengths - -- **Graceful degradation** - returns partial health status even if some checks fail -- **Detailed error logging** for diagnostic purposes -- **Structured health responses** with status indicators -- **No exceptions thrown to client** - health checks always return 200 - -```python -async def check_database_health(db: AsyncSession) -> DatabaseHealth: - """Check database connection and performance.""" - try: - import time - - start_time = time.time() - await db.execute(text("SELECT 1")) - connection_time = (time.time() - start_time) * 1000 - - return DatabaseHealth( - status="healthy", - connection_time_ms=connection_time, - message="Database connection successful", - ) - except Exception as e: - logger.error(f"Database health check failed: {e}") - return DatabaseHealth( - status="unhealthy", - connection_time_ms=0, - message=f"Database connection failed: {str(e)}", - ) -``` - -**Status**: ✅ Excellent resilience for monitoring endpoints - ---- - -### WebSocket Endpoints (`/ws`) - -**File**: `src/server/api/websocket.py` - -#### ✅ Error Handling Strengths - -- **Connection error handling** with proper disconnect cleanup -- **Message parsing errors** sent back to client -- **Structured error messages** via WebSocket protocol -- **Comprehensive logging** for debugging - -```python -@router.websocket("/connect") -async def websocket_endpoint( - websocket: WebSocket, - ws_service: WebSocketService = Depends(get_websocket_service), - user_id: Optional[str] = Depends(get_current_user_optional), -): - """WebSocket endpoint for client connections.""" - connection_id = str(uuid.uuid4()) - - try: - await ws_service.connect(websocket, connection_id, user_id=user_id) - - # ... connection handling - - while True: - try: - data = await websocket.receive_json() - - try: - client_msg = ClientMessage(**data) - except Exception as e: - logger.warning( - "Invalid client message format", - connection_id=connection_id, - error=str(e), - ) - await ws_service.send_error( - connection_id, - "Invalid message format", - "INVALID_MESSAGE", - ) - continue - - # ... message handling - - except WebSocketDisconnect: - logger.info("Client disconnected", connection_id=connection_id) - break - except Exception as e: - logger.error( - "Error processing WebSocket message", - connection_id=connection_id, - error=str(e), - ) - await ws_service.send_error( - connection_id, - "Internal server error", - "INTERNAL_ERROR", - ) - finally: - await ws_service.disconnect(connection_id) - logger.info("WebSocket connection closed", connection_id=connection_id) -``` - -**Status**: ✅ Excellent WebSocket error handling with proper cleanup - ---- - -### Analytics Endpoints (`/api/analytics`) - -**File**: `src/server/api/analytics.py` - -#### ⚠ïļ Error Handling Observations - -- ✅ Pydantic models for response validation -- ⚠ïļ **Missing explicit error handling** in some endpoints -- ⚠ïļ Database session handling could be improved - -#### Recommendation - -Add try-catch blocks to all analytics endpoints: - -```python -@router.get("/downloads", response_model=DownloadStatsResponse) -async def get_download_statistics( - days: int = 30, - db: AsyncSession = None, -) -> DownloadStatsResponse: - """Get download statistics for specified period.""" - try: - if db is None: - db = await get_db().__anext__() - - service = get_analytics_service() - stats = await service.get_download_stats(db, days=days) - - return DownloadStatsResponse( - total_downloads=stats.total_downloads, - successful_downloads=stats.successful_downloads, - # ... rest of response - ) - except Exception as e: - logger.error(f"Failed to get download statistics: {e}") - raise HTTPException( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=f"Failed to retrieve download statistics: {str(e)}", - ) from e -``` - -**Status**: ⚠ïļ Needs enhancement - ---- - -### Backup Endpoints (`/api/backup`) - -**File**: `src/server/api/backup.py` - -#### ✅ Error Handling Strengths - -- **Custom exception handling** in create_backup endpoint -- **ValueError handling** for invalid backup types -- **Comprehensive logging** for all operations - -#### ⚠ïļ Observations - -Some endpoints may not have explicit error handling: - -```python -@router.post("/create", response_model=BackupResponse) -async def create_backup( - request: BackupCreateRequest, - backup_service: BackupService = Depends(get_backup_service_dep), -) -> BackupResponse: - """Create a new backup.""" - try: - backup_info = None - - if request.backup_type == "config": - backup_info = backup_service.backup_configuration( - request.description or "" - ) - elif request.backup_type == "database": - backup_info = backup_service.backup_database( - request.description or "" - ) - elif request.backup_type == "full": - backup_info = backup_service.backup_full( - request.description or "" - ) - else: - raise ValueError(f"Invalid backup type: {request.backup_type}") - - # ... rest of logic - except ValueError as e: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=str(e), - ) from e - except Exception as e: - logger.error(f"Backup creation failed: {e}") - raise HTTPException( - status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=f"Failed to create backup: {str(e)}", - ) from e -``` - -**Status**: ✅ Good error handling with minor improvements possible - ---- - -### Maintenance Endpoints (`/api/maintenance`) - -**File**: `src/server/api/maintenance.py` - -#### ✅ Error Handling Strengths - -- **Comprehensive try-catch blocks** in all endpoints -- **Detailed error logging** for troubleshooting -- **Proper HTTP status codes** (500 for failures) -- **Graceful degradation** where possible - -```python -@router.post("/cleanup") -async def cleanup_temporary_files( - max_age_days: int = 30, - system_utils=Depends(get_system_utils), -) -> Dict[str, Any]: - """Clean up temporary and old files.""" - try: - deleted_logs = system_utils.cleanup_directory( - "logs", "*.log", max_age_days - ) - deleted_temp = system_utils.cleanup_directory( - "Temp", "*", max_age_days - ) - deleted_dirs = system_utils.cleanup_empty_directories("logs") - - return { - "success": True, - "deleted_logs": deleted_logs, - "deleted_temp_files": deleted_temp, - "deleted_empty_dirs": deleted_dirs, - "total_deleted": deleted_logs + deleted_temp + deleted_dirs, - } - except Exception as e: - logger.error(f"Cleanup failed: {e}") - raise HTTPException(status_code=500, detail=str(e)) -``` - -**Status**: ✅ Excellent error handling - ---- - -## Response Format Consistency - -### Current Response Formats - -The API uses **multiple response formats** depending on the endpoint: - -#### Format 1: Success/Data Pattern (Most Common) - -```json -{ - "success": true, - "data": { ... }, - "message": "Optional message" -} -``` - -#### Format 2: Status/Message Pattern - -```json -{ - "status": "ok", - "message": "Operation completed" -} -``` - -#### Format 3: Direct Data Return - -```json -{ - "field1": "value1", - "field2": "value2" -} -``` - -#### Format 4: Error Response (Standardized) - -```json -{ - "success": false, - "error": "ERROR_CODE", - "message": "Human-readable message", - "details": { ... }, - "request_id": "uuid" -} -``` - -### ⚠ïļ Consistency Recommendation - -While error responses are highly consistent (Format 4), **success responses vary** between formats 1, 2, and 3. - -#### Recommended Standard Format - -```json -// Success -{ - "success": true, - "data": { ... }, - "message": "Optional success message" -} - -// Error -{ - "success": false, - "error": "ERROR_CODE", - "message": "Error description", - "details": { ... }, - "request_id": "uuid" -} -``` - -**Action Item**: Consider standardizing all success responses to Format 1 for consistency with error responses. - ---- - -## Logging Standards - -### Current Logging Implementation - -#### ✅ Strengths - -1. **Structured logging** with `structlog` in WebSocket module -2. **Appropriate log levels**: INFO, WARNING, ERROR -3. **Contextual information** in log messages -4. **Extra fields** for better filtering - -#### ⚠ïļ Areas for Improvement - -1. **Inconsistent logging libraries**: Some modules use `logging`, others use `structlog` -2. **Missing request IDs** in some log messages -3. **Incomplete correlation** between logs and errors - -### Recommended Logging Pattern - -```python -import structlog - -logger = structlog.get_logger(__name__) - -@router.post("/endpoint") -async def endpoint(request: Request, data: RequestModel): - request_id = str(uuid.uuid4()) - request.state.request_id = request_id - - logger.info( - "Processing request", - request_id=request_id, - endpoint="/endpoint", - method="POST", - user_id=getattr(request.state, "user_id", None), - ) - - try: - # ... processing logic - - logger.info( - "Request completed successfully", - request_id=request_id, - duration_ms=elapsed_time, - ) - - return {"success": True, "data": result} - - except Exception as e: - logger.error( - "Request failed", - request_id=request_id, - error=str(e), - error_type=type(e).__name__, - exc_info=True, - ) - raise -``` - ---- - -## Validation Summary - -### ✅ Excellent Implementation - -| Category | Status | Notes | -| ------------------------ | ------------ | ------------------------------------------- | -| Exception Hierarchy | ✅ Excellent | Well-structured, comprehensive | -| Global Error Handlers | ✅ Excellent | Registered for all exception types | -| Authentication Endpoints | ✅ Good | Proper status codes, could add more logging | -| Anime Endpoints | ✅ Excellent | Input validation, security checks | -| Download Endpoints | ✅ Excellent | Comprehensive error handling | -| Config Endpoints | ✅ Excellent | Service-specific exceptions | -| Health Endpoints | ✅ Excellent | Graceful degradation | -| WebSocket Endpoints | ✅ Excellent | Proper cleanup, structured errors | -| Maintenance Endpoints | ✅ Excellent | Comprehensive try-catch blocks | - -### ⚠ïļ Needs Enhancement - -| Category | Status | Issue | Priority | -| --------------------------- | ----------- | ------------------------------------------- | -------- | -| Analytics Endpoints | ⚠ïļ Fair | Missing error handling in some methods | Medium | -| Backup Endpoints | ⚠ïļ Good | Could use more comprehensive error handling | Low | -| Response Format Consistency | ⚠ïļ Moderate | Multiple success response formats | Medium | -| Logging Consistency | ⚠ïļ Moderate | Mixed use of logging vs structlog | Low | -| Request ID Tracking | ⚠ïļ Missing | Not consistently implemented | Medium | - ---- - -## Recommendations - -### Priority 1: Critical (Implement Soon) - -1. **Add comprehensive error handling to analytics endpoints** - - - Wrap all database operations in try-catch - - Return meaningful error messages - - Log all failures with context - -2. **Implement request ID tracking** - - - Generate unique request ID for each API call - - Include in all log messages - - Return in error responses - - Enable distributed tracing - -3. **Standardize success response format** - - Use consistent `{success, data, message}` format - - Update all endpoints to use standard format - - Update frontend to expect standard format - -### Priority 2: Important (Implement This Quarter) - -4. **Migrate to structured logging everywhere** - - - Replace all `logging` with `structlog` - - Add structured fields to all log messages - - Include request context in all logs - -5. **Add error rate monitoring** - - - Track error rates by endpoint - - Alert on unusual error patterns - - Dashboard for error trends - -6. **Enhance error messages** - - More descriptive error messages for users - - Technical details only in `details` field - - Actionable guidance where possible - -### Priority 3: Nice to Have (Future Enhancement) - -7. **Implement retry logic for transient failures** - - - Automatic retries for database operations - - Exponential backoff for external APIs - - Circuit breaker pattern for providers - -8. **Add error aggregation and reporting** - - - Centralized error tracking (e.g., Sentry) - - Error grouping and deduplication - - Automatic issue creation for critical errors - -9. **Create error documentation** - - Comprehensive error code reference - - Troubleshooting guide for common errors - - Examples of error responses - ---- - -## Conclusion - -The Aniworld API demonstrates **strong error handling practices** with: - -✅ Well-designed exception hierarchy -✅ Comprehensive middleware error handling -✅ Proper HTTP status code usage -✅ Input validation and sanitization -✅ Defensive programming throughout - -With the recommended enhancements, particularly around analytics endpoints, response format standardization, and request ID tracking, the error handling implementation will be **world-class**. - ---- - -**Report Author**: AI Agent -**Last Updated**: October 23, 2025 -**Version**: 1.0 diff --git a/docs/frontend_backend_integration.md b/docs/frontend_backend_integration.md deleted file mode 100644 index 01457ca..0000000 --- a/docs/frontend_backend_integration.md +++ /dev/null @@ -1,174 +0,0 @@ -# Frontend-Backend Integration Summary - -**Date:** October 24, 2025 -**Status:** Core integration completed - -## Overview - -Successfully integrated the existing frontend JavaScript application with the new FastAPI backend by creating missing API endpoints and updating frontend API calls to match the new endpoint structure. - -## Completed Work - -### 1. Created Missing API Endpoints - -Added the following endpoints to `/src/server/api/anime.py`: - -#### `/api/v1/anime/status` (GET) - -- Returns anime library status information -- Response includes: - - `directory`: Configured anime directory path - - `series_count`: Number of series in the library -- Used by frontend configuration modal to display current settings - -#### `/api/v1/anime/add` (POST) - -- Adds a new series to the library from search results -- Request body: `{link: string, name: string}` -- Validates input and calls `SeriesApp.AddSeries()` method -- Returns success/error message - -#### `/api/v1/anime/download` (POST) - -- Starts downloading missing episodes from selected folders -- Request body: `{folders: string[]}` -- Calls `SeriesApp.Download()` with folder list -- Used when user selects multiple series and clicks download - -### 2. Updated Frontend API Calls - -Modified `/src/server/web/static/js/app.js` to use correct endpoint paths: - -| Old Path | New Path | Purpose | -| ----------------- | ------------------------ | ------------------------- | -| `/api/add_series` | `/api/v1/anime/add` | Add new series | -| `/api/download` | `/api/v1/anime/download` | Download selected folders | -| `/api/status` | `/api/v1/anime/status` | Get library status | - -### 3. Verified Existing Endpoints - -Confirmed the following endpoints are already correctly implemented: - -- `/api/auth/status` - Authentication status check -- `/api/auth/logout` - User logout -- `/api/v1/anime` - List anime with missing episodes -- `/api/v1/anime/search` - Search for anime -- `/api/v1/anime/rescan` - Trigger library rescan -- `/api/v1/anime/{anime_id}` - Get anime details -- `/api/queue/*` - Download queue management -- `/api/config/*` - Configuration management - -## Request/Response Models - -### AddSeriesRequest - -```python -class AddSeriesRequest(BaseModel): - link: str # Series URL/link - name: str # Series name -``` - -### DownloadFoldersRequest - -```python -class DownloadFoldersRequest(BaseModel): - folders: List[str] # List of folder names to download -``` - -## Testing - -- All existing tests passing -- Integration tested with frontend JavaScript -- Endpoints follow existing patterns and conventions -- Proper error handling and validation in place - -## Remaining Work - -The following endpoints are referenced in the frontend but not yet implemented: - -### Scheduler API (`/api/scheduler/`) - -- `/api/scheduler/config` (GET/POST) - Get/update scheduler configuration -- `/api/scheduler/trigger-rescan` (POST) - Manually trigger scheduled rescan - -### Logging API (`/api/logging/`) - -- `/api/logging/config` (GET/POST) - Get/update logging configuration -- `/api/logging/files` (GET) - List log files -- `/api/logging/files/{filename}/download` (GET) - Download log file -- `/api/logging/files/{filename}/tail` (GET) - Tail log file -- `/api/logging/test` (POST) - Test logging configuration -- `/api/logging/cleanup` (POST) - Clean up old log files - -### Diagnostics API (`/api/diagnostics/`) - -- `/api/diagnostics/network` (GET) - Network diagnostics - -### Config API Extensions - -The following config endpoints may need verification or implementation: - -- `/api/config/section/advanced` (GET/POST) - Advanced configuration section -- `/api/config/directory` (POST) - Update anime directory -- `/api/config/backup` (POST) - Create configuration backup -- `/api/config/backups` (GET) - List configuration backups -- `/api/config/backup/{name}/restore` (POST) - Restore backup -- `/api/config/backup/{name}/download` (GET) - Download backup -- `/api/config/export` (POST) - Export configuration -- `/api/config/validate` (POST) - Validate configuration -- `/api/config/reset` (POST) - Reset configuration to defaults - -## Architecture Notes - -### Endpoint Organization - -- Anime-related endpoints: `/api/v1/anime/` -- Queue management: `/api/queue/` -- Configuration: `/api/config/` -- Authentication: `/api/auth/` -- Health checks: `/health` - -### Design Patterns Used - -- Dependency injection for `SeriesApp` instance -- Request validation with Pydantic models -- Consistent error handling and HTTP status codes -- Authentication requirements on all endpoints -- Proper async/await patterns - -### Frontend Integration - -- Frontend uses `makeAuthenticatedRequest()` helper for API calls -- Bearer token authentication in Authorization header -- Consistent response format expected: `{status: string, message: string, ...}` -- WebSocket integration preserved for real-time updates - -## Security Considerations - -- All endpoints require authentication via `require_auth` dependency -- Input validation on request models (link length, folder list) -- Proper error messages without exposing internal details -- No injection vulnerabilities in search/add operations - -## Future Improvements - -1. **Implement missing APIs**: Scheduler, Logging, Diagnostics -2. **Enhanced validation**: Add more comprehensive input validation -3. **Rate limiting**: Add per-endpoint rate limiting if needed -4. **Caching**: Consider caching for status endpoints -5. **Pagination**: Add pagination to anime list endpoint -6. **Filtering**: Add filtering options to anime list -7. **Batch operations**: Support batch add/download operations -8. **Progress tracking**: Enhance real-time progress updates - -## Files Modified - -- `src/server/api/anime.py` - Added 4 new endpoints -- `src/server/web/static/js/app.js` - Updated 4 API call paths -- `instructions.md` - Marked frontend integration tasks as completed - -## Conclusion - -The core frontend-backend integration is now complete. The main user workflows (listing anime, searching, adding series, downloading) are fully functional. The remaining work involves implementing administrative and configuration features (scheduler, logging, diagnostics) that enhance the application but are not critical for basic operation. - -All tests are passing, and the integration follows established patterns and best practices for the project. diff --git a/docs/frontend_integration.md b/docs/frontend_integration.md deleted file mode 100644 index fbb4608..0000000 --- a/docs/frontend_integration.md +++ /dev/null @@ -1,839 +0,0 @@ -# Frontend Integration Guide - -Complete guide for integrating the existing frontend assets with the FastAPI backend. - -## Table of Contents - -1. [Overview](#overview) -2. [Frontend Asset Structure](#frontend-asset-structure) -3. [API Integration](#api-integration) -4. [WebSocket Integration](#websocket-integration) -5. [Theme System](#theme-system) -6. [Authentication Flow](#authentication-flow) -7. [Error Handling](#error-handling) -8. [Localization](#localization) -9. [Accessibility Features](#accessibility-features) -10. [Testing Integration](#testing-integration) - -## Overview - -The Aniworld frontend uses vanilla JavaScript with modern ES6+ features, integrated with a FastAPI backend through REST API endpoints and WebSocket connections. The design follows Fluent UI principles with comprehensive accessibility support. - -### Key Technologies - -- **Frontend**: Vanilla JavaScript (ES6+), HTML5, CSS3 -- **Backend**: FastAPI, Python 3.10+ -- **Communication**: REST API, WebSocket -- **Styling**: Custom CSS with Fluent UI design principles -- **Icons**: Font Awesome 6.0.0 - -## Frontend Asset Structure - -### Templates (`src/server/web/templates/`) - -- `index.html` - Main application interface -- `queue.html` - Download queue management page -- `login.html` - Authentication login page -- `setup.html` - Initial setup page -- `error.html` - Error display page - -### JavaScript Files (`src/server/web/static/js/`) - -#### Core Application Files - -- **`app.js`** (2086 lines) - - - Main application logic - - Series management - - Download operations - - Search functionality - - Theme management - - Authentication handling - -- **`queue.js`** (758 lines) - - - Download queue management - - Queue reordering - - Download progress tracking - - Queue status updates - -- **`websocket_client.js`** (234 lines) - - Native WebSocket wrapper - - Socket.IO-like interface - - Reconnection logic - - Message routing - -#### Feature Enhancement Files - -- **`accessibility_features.js`** - ARIA labels, keyboard navigation -- **`advanced_search.js`** - Advanced search filtering -- **`bulk_operations.js`** - Batch operations on series -- **`color_contrast_compliance.js`** - WCAG color contrast validation -- **`drag_drop.js`** - Drag-and-drop queue reordering -- **`keyboard_shortcuts.js`** - Global keyboard shortcuts -- **`localization.js`** - Multi-language support -- **`mobile_responsive.js`** - Mobile-specific enhancements -- **`multi_screen_support.js`** - Multi-monitor support -- **`screen_reader_support.js`** - Screen reader compatibility -- **`touch_gestures.js`** - Touch gesture support -- **`undo_redo.js`** - Undo/redo functionality -- **`user_preferences.js`** - User preference management - -### CSS Files (`src/server/web/static/css/`) - -- **`styles.css`** - Main stylesheet with Fluent UI design -- **`ux_features.css`** - UX enhancements and accessibility styles - -## API Integration - -### Current API Endpoints Used - -#### Authentication Endpoints - -```javascript -// Check authentication status -GET /api/auth/status -Headers: { Authorization: Bearer } - -// Login -POST /api/auth/login -Body: { password: string } -Response: { token: string, token_type: string } - -// Logout -POST /api/auth/logout -``` - -#### Anime Endpoints - -```javascript -// List all anime -GET /api/v1/anime -Response: { success: bool, data: Array } - -// Search anime -GET /api/v1/anime/search?query= -Response: { success: bool, data: Array } - -// Get anime details -GET /api/v1/anime/{anime_id} -Response: { success: bool, data: Anime } -``` - -#### Download Queue Endpoints - -```javascript -// Get queue status -GET /api/v1/download/queue -Response: { queue: Array, is_running: bool } - -// Add to queue -POST /api/v1/download/queue -Body: { anime_id: string, episodes: Array } - -// Start queue -POST /api/v1/download/queue/start - -// Stop queue -POST /api/v1/download/queue/stop - -// Pause queue -POST /api/v1/download/queue/pause - -// Resume queue -POST /api/v1/download/queue/resume - -// Reorder queue -PUT /api/v1/download/queue/reorder -Body: { queue_order: Array } - -// Remove from queue -DELETE /api/v1/download/queue/{item_id} -``` - -#### Configuration Endpoints - -```javascript -// Get configuration -GET / api / v1 / config; -Response: { - config: ConfigObject; -} - -// Update configuration -PUT / api / v1 / config; -Body: ConfigObject; -``` - -### API Call Pattern - -All API calls follow this pattern in the JavaScript files: - -```javascript -async function apiCall(endpoint, options = {}) { - try { - const token = localStorage.getItem("access_token"); - const headers = { - "Content-Type": "application/json", - ...(token && { Authorization: `Bearer ${token}` }), - ...options.headers, - }; - - const response = await fetch(endpoint, { - ...options, - headers, - }); - - if (!response.ok) { - if (response.status === 401) { - // Redirect to login - window.location.href = "/login"; - return; - } - throw new Error(`HTTP ${response.status}: ${response.statusText}`); - } - - return await response.json(); - } catch (error) { - console.error("API call failed:", error); - throw error; - } -} -``` - -### Required API Updates - -The following API endpoints need to be verified/updated to match frontend expectations: - -1. **Response Format Consistency** - - - All responses should include `success` boolean - - Error responses should include `error`, `message`, and `details` - - Success responses should include `data` field - -2. **Authentication Flow** - - - `/api/auth/status` endpoint for checking authentication - - Proper 401 responses for unauthenticated requests - - Token refresh mechanism (if needed) - -3. **Queue Operations** - - Ensure queue reordering endpoint exists - - Validate pause/resume functionality - - Check queue status polling endpoint - -## WebSocket Integration - -### WebSocket Connection - -The frontend uses a custom WebSocket client (`websocket_client.js`) that provides a Socket.IO-like interface over native WebSocket. - -#### Connection Endpoint - -```javascript -const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; -const host = window.location.host; -const wsUrl = `${protocol}//${host}/ws/connect`; -``` - -### WebSocket Events - -#### Events Sent by Frontend - -```javascript -// Join a room (for targeted updates) -socket.emit("join", { room: "downloads" }); -socket.emit("join", { room: "download_progress" }); - -// Leave a room -socket.emit("leave", { room: "downloads" }); - -// Custom events (as needed) -socket.emit("custom_event", { data: "value" }); -``` - -#### Events Received by Frontend - -##### Connection Events - -```javascript -socket.on("connect", () => { - // Connection established -}); - -socket.on("disconnect", (data) => { - // Connection lost - data: { code, reason } -}); - -socket.on("connected", (data) => { - // Server confirmation - data: { message, timestamp } -}); -``` - -##### Queue Events - -```javascript -// Queue status updates -socket.on("queue_status", (data) => { - // data: { queue_status: { queue: [], is_running: bool } } -}); - -socket.on("queue_updated", (data) => { - // Legacy event - same as queue_status -}); - -// Download lifecycle -socket.on("queue_started", () => { - // Queue processing started -}); - -socket.on("download_started", (data) => { - // Individual download started - // data: { serie_name, episode } -}); - -socket.on("download_progress", (data) => { - // Download progress update - // data: { serie_name, episode, progress, speed, eta } -}); - -socket.on("download_complete", (data) => { - // Download completed - // data: { serie_name, episode } -}); - -socket.on("download_completed", (data) => { - // Legacy event - same as download_complete -}); - -socket.on("download_failed", (data) => { - // Download failed - // data: { serie_name, episode, error } -}); - -socket.on("download_error", (data) => { - // Legacy event - same as download_failed -}); - -socket.on("download_queue_completed", () => { - // All downloads in queue completed -}); - -socket.on("download_stop_requested", () => { - // Queue stop requested -}); -``` - -##### Scan Events - -```javascript -socket.on("scan_started", () => { - // Library scan started -}); - -socket.on("scan_progress", (data) => { - // Scan progress update - // data: { current, total, percentage } -}); - -socket.on("scan_completed", (data) => { - // Scan completed - // data: { total_series, new_series, updated_series } -}); - -socket.on("scan_failed", (data) => { - // Scan failed - // data: { error } -}); -``` - -### Backend WebSocket Requirements - -The backend WebSocket implementation (`src/server/api/websocket.py`) should: - -1. **Accept connections at** `/ws/connect` -2. **Handle room management** (join/leave messages) -3. **Broadcast events** to appropriate rooms -4. **Support message format**: - ```json - { - "event": "event_name", - "data": { ... } - } - ``` - -## Theme System - -### Theme Implementation - -The application supports light and dark modes with persistence. - -#### Theme Toggle - -```javascript -// Toggle theme -document.documentElement.setAttribute("data-theme", "light|dark"); - -// Store preference -localStorage.setItem("theme", "light|dark"); - -// Load on startup -const savedTheme = localStorage.getItem("theme") || "light"; -document.documentElement.setAttribute("data-theme", savedTheme); -``` - -#### CSS Variables - -Themes are defined using CSS custom properties: - -```css -:root[data-theme="light"] { - --bg-primary: #ffffff; - --bg-secondary: #f5f5f5; - --text-primary: #000000; - --text-secondary: #666666; - --accent-color: #0078d4; - /* ... more variables */ -} - -:root[data-theme="dark"] { - --bg-primary: #1e1e1e; - --bg-secondary: #2d2d2d; - --text-primary: #ffffff; - --text-secondary: #cccccc; - --accent-color: #60a5fa; - /* ... more variables */ -} -``` - -### Fluent UI Design Principles - -The frontend follows Microsoft Fluent UI design guidelines: - -- **Rounded corners**: 4px border radius -- **Shadows**: Subtle elevation shadows -- **Transitions**: Smooth 200-300ms transitions -- **Typography**: System font stack -- **Spacing**: 8px grid system -- **Colors**: Accessible color palette - -## Authentication Flow - -### Authentication States - -```javascript -// State management -const authStates = { - UNAUTHENTICATED: "unauthenticated", - AUTHENTICATED: "authenticated", - SETUP_REQUIRED: "setup_required", -}; -``` - -### Authentication Check - -On page load, the application checks authentication status: - -```javascript -async checkAuthentication() { - // Skip check on public pages - const currentPath = window.location.pathname; - if (currentPath === '/login' || currentPath === '/setup') { - return; - } - - try { - const token = localStorage.getItem('access_token'); - - if (!token) { - window.location.href = '/login'; - return; - } - - const response = await fetch('/api/auth/status', { - headers: { 'Authorization': `Bearer ${token}` } - }); - - if (!response.ok) { - if (response.status === 401) { - localStorage.removeItem('access_token'); - window.location.href = '/login'; - } - } - } catch (error) { - console.error('Auth check failed:', error); - window.location.href = '/login'; - } -} -``` - -### Login Flow - -```javascript -async login(password) { - try { - const response = await fetch('/api/auth/login', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ password }) - }); - - if (response.ok) { - const data = await response.json(); - localStorage.setItem('access_token', data.token); - window.location.href = '/'; - } else { - // Show error message - this.showError('Invalid password'); - } - } catch (error) { - console.error('Login failed:', error); - this.showError('Login failed'); - } -} -``` - -### Logout Flow - -```javascript -async logout() { - try { - await fetch('/api/auth/logout', { method: 'POST' }); - } finally { - localStorage.removeItem('access_token'); - window.location.href = '/login'; - } -} -``` - -## Error Handling - -### Frontend Error Display - -The application uses toast notifications for errors: - -```javascript -showToast(message, type = 'info') { - const toast = document.createElement('div'); - toast.className = `toast toast-${type}`; - toast.textContent = message; - - document.body.appendChild(toast); - - setTimeout(() => { - toast.classList.add('show'); - }, 100); - - setTimeout(() => { - toast.classList.remove('show'); - setTimeout(() => toast.remove(), 300); - }, 3000); -} -``` - -### API Error Handling - -```javascript -async function handleApiError(error, response) { - if (response) { - const data = await response.json().catch(() => ({})); - - // Show user-friendly error message - const message = data.message || `Error: ${response.status}`; - this.showToast(message, "error"); - - // Log details for debugging - console.error("API Error:", { - status: response.status, - error: data.error, - message: data.message, - details: data.details, - }); - - // Handle specific status codes - if (response.status === 401) { - // Redirect to login - localStorage.removeItem("access_token"); - window.location.href = "/login"; - } - } else { - // Network error - this.showToast("Network error. Please check your connection.", "error"); - console.error("Network error:", error); - } -} -``` - -### Expected Error Response Format - -The backend should return errors in this format: - -```json -{ - "success": false, - "error": "ERROR_CODE", - "message": "Human-readable error message", - "details": { - "field": "error_field", - "reason": "specific_reason" - }, - "request_id": "uuid" -} -``` - -## Localization - -The application includes a localization system (`localization.js`) for multi-language support. - -### Localization Usage - -```javascript -// Initialize localization -const localization = new Localization(); - -// Set language -localization.setLanguage("en"); // or 'de', 'es', etc. - -// Get translation -const text = localization.get("key", "default_value"); - -// Update all page text -localization.updatePageText(); -``` - -### Text Keys - -Elements with `data-text` attributes are automatically translated: - -```html -Download Queue - -``` - -### Adding New Translations - -Translations are defined in `localization.js`: - -```javascript -const translations = { - en: { - "download-queue": "Download Queue", - "start-download": "Start Download", - // ... more keys - }, - de: { - "download-queue": "Download-Warteschlange", - "start-download": "Download starten", - // ... more keys - }, -}; -``` - -## Accessibility Features - -The application includes comprehensive accessibility support. - -### Keyboard Navigation - -All interactive elements are keyboard accessible: - -- **Tab/Shift+Tab**: Navigate between elements -- **Enter/Space**: Activate buttons -- **Escape**: Close modals/dialogs -- **Arrow Keys**: Navigate lists - -Custom keyboard shortcuts are defined in `keyboard_shortcuts.js`. - -### Screen Reader Support - -ARIA labels and live regions are implemented: - -```html - - -
-``` - -### Color Contrast - -The application ensures WCAG AA compliance for color contrast: - -- Normal text: 4.5:1 minimum -- Large text: 3:1 minimum -- Interactive elements: 3:1 minimum - -`color_contrast_compliance.js` validates contrast ratios. - -### Touch Support - -Touch gestures are supported for mobile devices: - -- **Swipe**: Navigate between sections -- **Long press**: Show context menu -- **Pinch**: Zoom (where applicable) - -## Testing Integration - -### Frontend Testing Checklist - -- [ ] **API Integration** - - - [ ] All API endpoints return expected response format - - [ ] Error responses include proper error codes - - [ ] Authentication flow works correctly - - [ ] Token refresh mechanism works (if implemented) - -- [ ] **WebSocket Integration** - - - [ ] WebSocket connects successfully - - [ ] All expected events are received - - [ ] Reconnection works after disconnect - - [ ] Room-based broadcasting works correctly - -- [ ] **UI/UX** - - - [ ] Theme toggle persists across sessions - - [ ] All pages are responsive (mobile, tablet, desktop) - - [ ] Animations are smooth and performant - - [ ] Toast notifications display correctly - -- [ ] **Authentication** - - - [ ] Login redirects to home page - - [ ] Logout clears session and redirects - - [ ] Protected pages redirect unauthenticated users - - [ ] Token expiration handled gracefully - -- [ ] **Accessibility** - - - [ ] Keyboard navigation works on all pages - - [ ] Screen reader announces important changes - - [ ] Color contrast meets WCAG AA standards - - [ ] Focus indicators are visible - -- [ ] **Localization** - - - [ ] All text is translatable - - [ ] Language selection persists - - [ ] Translations are complete for all supported languages - -- [ ] **Error Handling** - - [ ] Network errors show appropriate messages - - [ ] API errors display user-friendly messages - - [ ] Fatal errors redirect to error page - - [ ] Errors are logged for debugging - -### Integration Test Examples - -#### API Integration Test - -```javascript -describe("API Integration", () => { - test("should authenticate and fetch anime list", async () => { - // Login - const loginResponse = await fetch("/api/auth/login", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ password: "test_password" }), - }); - - const { token } = await loginResponse.json(); - expect(token).toBeDefined(); - - // Fetch anime - const animeResponse = await fetch("/api/v1/anime", { - headers: { Authorization: `Bearer ${token}` }, - }); - - const data = await animeResponse.json(); - expect(data.success).toBe(true); - expect(Array.isArray(data.data)).toBe(true); - }); -}); -``` - -#### WebSocket Integration Test - -```javascript -describe("WebSocket Integration", () => { - test("should connect and receive events", (done) => { - const socket = new WebSocketClient(); - - socket.on("connect", () => { - expect(socket.isConnected).toBe(true); - - // Join room - socket.emit("join", { room: "downloads" }); - - // Wait for queue_status event - socket.on("queue_status", (data) => { - expect(data).toHaveProperty("queue_status"); - socket.disconnect(); - done(); - }); - }); - - socket.connect(); - }); -}); -``` - -## Frontend Integration Checklist - -### Phase 1: API Endpoint Verification - -- [ ] Verify `/api/auth/status` endpoint exists and returns proper format -- [ ] Verify `/api/auth/login` returns token in expected format -- [ ] Verify `/api/auth/logout` endpoint exists -- [ ] Verify `/api/v1/anime` returns list with `success` and `data` fields -- [ ] Verify `/api/v1/anime/search` endpoint exists -- [ ] Verify `/api/v1/download/queue` endpoints match frontend expectations -- [ ] Verify error responses include `success`, `error`, `message`, `details` - -### Phase 2: WebSocket Integration - -- [ ] Verify WebSocket endpoint is `/ws/connect` -- [ ] Verify room join/leave functionality -- [ ] Verify all queue events are emitted properly -- [ ] Verify scan events are emitted properly -- [ ] Test reconnection logic -- [ ] Test message broadcasting to rooms - -### Phase 3: Frontend Code Updates - -- [ ] Update `app.js` API calls to match backend endpoints -- [ ] Update `queue.js` API calls to match backend endpoints -- [ ] Verify `websocket_client.js` message format matches backend -- [ ] Update error handling to parse new error format -- [ ] Test authentication flow end-to-end -- [ ] Verify theme persistence works - -### Phase 4: UI/UX Polish - -- [ ] Verify responsive design on mobile devices -- [ ] Test keyboard navigation on all pages -- [ ] Verify screen reader compatibility -- [ ] Test color contrast in both themes -- [ ] Verify all animations are smooth -- [ ] Test touch gestures on mobile - -### Phase 5: Testing - -- [ ] Write integration tests for API endpoints -- [ ] Write integration tests for WebSocket events -- [ ] Write UI tests for critical user flows -- [ ] Test error scenarios (network errors, auth failures) -- [ ] Test performance under load -- [ ] Test accessibility with screen reader - -## Conclusion - -This guide provides a comprehensive overview of the frontend integration requirements. All JavaScript files should be reviewed and updated to match the documented API endpoints and WebSocket events. The backend should ensure it provides the expected response formats and event structures. - -For questions or issues, refer to: - -- **API Reference**: `docs/api_reference.md` -- **User Guide**: `docs/user_guide.md` -- **Deployment Guide**: `docs/deployment.md` diff --git a/docs/identifier_standardization_validation.md b/docs/identifier_standardization_validation.md new file mode 100644 index 0000000..9e0d05e --- /dev/null +++ b/docs/identifier_standardization_validation.md @@ -0,0 +1,426 @@ +# Series Identifier Standardization - Validation Instructions + +## Overview + +This document provides comprehensive instructions for AI agents to validate the **Series Identifier Standardization** change across the Aniworld codebase. The change standardizes `key` as the primary identifier for series and relegates `folder` to metadata-only status. + +## Summary of the Change + +| Field | Purpose | Usage | +| -------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------- | +| `key` | **Primary Identifier** - Provider-assigned, URL-safe (e.g., `attack-on-titan`) | All lookups, API operations, database queries, WebSocket events | +| `folder` | **Metadata Only** - Filesystem folder name (e.g., `Attack on Titan (2013)`) | Display purposes, filesystem operations only | +| `id` | **Database Primary Key** - Internal auto-increment integer | Database relationships only | + +--- + +## Validation Checklist + +### Phase 2: Application Layer Services + +**Files to validate:** + +1. **`src/server/services/anime_service.py`** + + - [ ] Class docstring explains `key` vs `folder` convention + - [ ] All public methods accept `key` parameter for series identification + - [ ] No methods accept `folder` as an identifier parameter + - [ ] Event handler methods document key/folder convention + - [ ] Progress tracking uses `key` in progress IDs where possible + +2. **`src/server/services/download_service.py`** + + - [ ] `DownloadItem` uses `serie_id` (which should be the `key`) + - [ ] `serie_folder` is documented as metadata only + - [ ] Queue operations look up series by `key` not `folder` + - [ ] Persistence format includes `serie_id` as the key identifier + +3. **`src/server/services/websocket_service.py`** + + - [ ] Module docstring explains key/folder convention + - [ ] Broadcast methods include `key` in message payloads + - [ ] `folder` is documented as optional/display only + - [ ] Event broadcasts use `key` as primary identifier + +4. **`src/server/services/scan_service.py`** + + - [ ] Scan operations use `key` for identification + - [ ] Progress events include `key` field + +5. **`src/server/services/progress_service.py`** + - [ ] Progress tracking includes `key` in metadata where applicable + +**Validation Commands:** + +```bash +# Check service layer for folder-based lookups +grep -rn "by_folder\|folder.*=.*identifier\|folder.*lookup" src/server/services/ --include="*.py" + +# Verify key is used in services +grep -rn "serie_id\|series_key\|key.*identifier" src/server/services/ --include="*.py" +``` + +--- + +### Phase 3: API Endpoints and Responses + +**Files to validate:** + +1. **`src/server/api/anime.py`** + + - [ ] `AnimeSummary` model has `key` field with proper description + - [ ] `AnimeDetail` model has `key` field with proper description + - [ ] API docstrings explain `key` is the primary identifier + - [ ] `folder` field descriptions state "metadata only" + - [ ] Endpoint paths use `key` parameter (e.g., `/api/anime/{key}`) + - [ ] No endpoints use `folder` as path parameter for lookups + +2. **`src/server/api/download.py`** + + - [ ] Download endpoints use `serie_id` (key) for operations + - [ ] Request models document key/folder convention + - [ ] Response models include `key` as primary identifier + +3. **`src/server/models/anime.py`** + + - [ ] Module docstring explains identifier convention + - [ ] `AnimeSeriesResponse` has `key` field properly documented + - [ ] `SearchResult` has `key` field properly documented + - [ ] Field validators normalize `key` to lowercase + - [ ] `folder` fields document metadata-only purpose + +4. **`src/server/models/download.py`** + + - [ ] `DownloadItem` has `serie_id` documented as the key + - [ ] `serie_folder` documented as metadata only + - [ ] Field descriptions are clear about primary vs metadata + +5. **`src/server/models/websocket.py`** + - [ ] Module docstring explains key/folder convention + - [ ] Message models document `key` as primary identifier + - [ ] `folder` documented as optional display metadata + +**Validation Commands:** + +```bash +# Check API endpoints for folder-based paths +grep -rn "folder.*Path\|/{folder}" src/server/api/ --include="*.py" + +# Verify key is used in endpoints +grep -rn "/{key}\|series_key\|serie_id" src/server/api/ --include="*.py" + +# Check model field descriptions +grep -rn "Field.*description.*identifier\|Field.*description.*key\|Field.*description.*folder" src/server/models/ --include="*.py" +``` + +--- + +### Phase 4: Frontend Integration + +**Files to validate:** + +1. **`src/server/web/static/js/app.js`** + + - [ ] `selectedSeries` Set uses `key` values, not `folder` + - [ ] `seriesData` array comments indicate `key` as primary identifier + - [ ] Selection operations use `key` property + - [ ] API calls pass `key` for series identification + - [ ] WebSocket message handlers extract `key` from data + - [ ] No code uses `folder` for series lookups + +2. **`src/server/web/static/js/queue.js`** + + - [ ] Queue items reference series by `key` or `serie_id` + - [ ] WebSocket handlers extract `key` from messages + - [ ] UI operations use `key` for identification + - [ ] `serie_folder` used only for display + +3. **`src/server/web/static/js/websocket_client.js`** + + - [ ] Message handling preserves `key` field + - [ ] No transformation that loses `key` information + +4. **HTML Templates** (`src/server/web/templates/`) + - [ ] Data attributes use `key` for identification (e.g., `data-key`) + - [ ] No `data-folder` used for identification purposes + - [ ] Display uses `folder` or `name` appropriately + +**Validation Commands:** + +```bash +# Check JavaScript for folder-based lookups +grep -rn "\.folder\s*==\|folder.*identifier\|getByFolder" src/server/web/static/js/ --include="*.js" + +# Check data attributes in templates +grep -rn "data-key\|data-folder\|data-series" src/server/web/templates/ --include="*.html" +``` + +--- + +### Phase 5: Database Operations + +**Files to validate:** + +1. **`src/server/database/models.py`** + + - [ ] `AnimeSeries` model has `key` column with unique constraint + - [ ] `key` column is indexed + - [ ] Model docstring explains identifier convention + - [ ] `folder` column docstring states "metadata only" + - [ ] Validators check `key` is not empty + - [ ] No `folder` uniqueness constraint (unless intentional) + +2. **`src/server/database/service.py`** + + - [ ] `AnimeSeriesService` has `get_by_key()` method + - [ ] Class docstring explains lookup convention + - [ ] No `get_by_folder()` without deprecation + - [ ] All CRUD operations use `key` for identification + - [ ] Logging uses `key` in messages + +3. **`src/server/database/migrations/`** + - [ ] Migration files maintain `key` as unique, indexed column + - [ ] No migrations that use `folder` as identifier + +**Validation Commands:** + +```bash +# Check database models +grep -rn "unique=True\|index=True" src/server/database/models.py + +# Check service lookups +grep -rn "get_by_key\|get_by_folder\|filter.*key\|filter.*folder" src/server/database/service.py +``` + +--- + +### Phase 6: WebSocket Events + +**Files to validate:** + +1. **All WebSocket broadcast calls** should include `key` in payload: + + - `download_progress` → includes `key` + - `download_complete` → includes `key` + - `download_failed` → includes `key` + - `scan_progress` → includes `key` (where applicable) + - `queue_status` → items include `key` + +2. **Message format validation:** + ```json + { + "type": "download_progress", + "data": { + "key": "attack-on-titan", // PRIMARY - always present + "folder": "Attack on Titan (2013)", // OPTIONAL - display only + "progress": 45.5, + ... + } + } + ``` + +**Validation Commands:** + +```bash +# Check WebSocket broadcast calls +grep -rn "broadcast.*key\|send_json.*key" src/server/services/ --include="*.py" + +# Check message construction +grep -rn '"key":\|"folder":' src/server/services/ --include="*.py" +``` + +--- + +### Phase 7: Test Coverage + +**Test files to validate:** + +1. **`tests/unit/test_serie_class.py`** + + - [ ] Tests for key validation (empty, whitespace, None) + - [ ] Tests for key as primary identifier + - [ ] Tests for folder as metadata only + +2. **`tests/unit/test_anime_service.py`** + + - [ ] Service tests use `key` for operations + - [ ] Mock objects have proper `key` attributes + +3. **`tests/unit/test_database_models.py`** + + - [ ] Tests for `key` uniqueness constraint + - [ ] Tests for `key` validation + +4. **`tests/unit/test_database_service.py`** + + - [ ] Tests for `get_by_key()` method + - [ ] No tests for deprecated folder lookups + +5. **`tests/api/test_anime_endpoints.py`** + + - [ ] API tests use `key` in requests + - [ ] Mock `FakeSerie` has proper `key` attribute + - [ ] Comments explain key/folder convention + +6. **`tests/unit/test_websocket_service.py`** + - [ ] WebSocket tests verify `key` in messages + - [ ] Broadcast tests include `key` in payload + +**Validation Commands:** + +```bash +# Run all tests +conda run -n AniWorld python -m pytest tests/ -v --tb=short + +# Run specific test files +conda run -n AniWorld python -m pytest tests/unit/test_serie_class.py -v +conda run -n AniWorld python -m pytest tests/unit/test_database_models.py -v +conda run -n AniWorld python -m pytest tests/api/test_anime_endpoints.py -v + +# Search tests for identifier usage +grep -rn "key.*identifier\|folder.*metadata" tests/ --include="*.py" +``` + +--- + +## Common Issues to Check + +### 1. Inconsistent Naming + +Look for inconsistent parameter names: + +- `serie_key` vs `series_key` vs `key` +- `serie_id` should refer to `key`, not database `id` +- `serie_folder` vs `folder` + +### 2. Missing Documentation + +Check that ALL models, services, and APIs document: + +- What `key` is and how to use it +- That `folder` is metadata only + +### 3. Legacy Code Patterns + +Search for deprecated patterns: + +```python +# Bad - using folder for lookup +series = get_by_folder(folder_name) + +# Good - using key for lookup +series = get_by_key(series_key) +``` + +### 4. API Response Consistency + +Verify all API responses include: + +- `key` field (primary identifier) +- `folder` field (optional, for display) + +### 5. Frontend Data Flow + +Verify the frontend: + +- Stores `key` in selection sets +- Passes `key` to API calls +- Uses `folder` only for display + +--- + +## Deprecation Warnings + +The following should have deprecation warnings (for removal in v3.0.0): + +1. Any `get_by_folder()` or `GetByFolder()` methods +2. Any API endpoints that accept `folder` as a lookup parameter +3. Any frontend code that uses `folder` for identification + +**Example deprecation:** + +```python +import warnings + +def get_by_folder(self, folder: str): + """DEPRECATED: Use get_by_key() instead.""" + warnings.warn( + "get_by_folder() is deprecated, use get_by_key(). " + "Will be removed in v3.0.0", + DeprecationWarning, + stacklevel=2 + ) + # ... implementation +``` + +--- + +## Automated Validation Script + +Run this script to perform automated checks: + +```bash +#!/bin/bash +# identifier_validation.sh + +echo "=== Series Identifier Standardization Validation ===" +echo "" + +echo "1. Checking core entities..." +grep -rn "PRIMARY IDENTIFIER\|metadata only" src/core/entities/ --include="*.py" | head -20 + +echo "" +echo "2. Checking for deprecated folder lookups..." +grep -rn "get_by_folder\|GetByFolder" src/ --include="*.py" + +echo "" +echo "3. Checking API models for key field..." +grep -rn 'key.*Field\|Field.*key' src/server/models/ --include="*.py" | head -20 + +echo "" +echo "4. Checking database models..." +grep -rn "key.*unique\|key.*index" src/server/database/models.py + +echo "" +echo "5. Checking frontend key usage..." +grep -rn "selectedSeries\|\.key\|data-key" src/server/web/static/js/ --include="*.js" | head -20 + +echo "" +echo "6. Running tests..." +conda run -n AniWorld python -m pytest tests/unit/test_serie_class.py -v --tb=short + +echo "" +echo "=== Validation Complete ===" +``` + +--- + +## Expected Results + +After validation, you should confirm: + +1. ✅ All core entities use `key` as primary identifier +2. ✅ All services look up series by `key` +3. ✅ All API endpoints use `key` for operations +4. ✅ All database queries use `key` for lookups +5. ✅ Frontend uses `key` for selection and API calls +6. ✅ WebSocket events include `key` in payload +7. ✅ All tests pass +8. ✅ Documentation clearly explains the convention +9. ✅ Deprecation warnings exist for legacy patterns + +--- + +## Sign-off + +Once validation is complete, update this section: + +- [x] Phase 1: Core Entities - Validated by: **AI Agent** Date: **28 Nov 2025** +- [x] Phase 2: Services - Validated by: **AI Agent** Date: **28 Nov 2025** +- [ ] Phase 3: API - Validated by: **\_\_\_** Date: **\_\_\_** +- [ ] Phase 4: Frontend - Validated by: **\_\_\_** Date: **\_\_\_** +- [ ] Phase 5: Database - Validated by: **\_\_\_** Date: **\_\_\_** +- [ ] Phase 6: WebSocket - Validated by: **\_\_\_** Date: **\_\_\_** +- [ ] Phase 7: Tests - Validated by: **\_\_\_** Date: **\_\_\_** + +**Final Approval:** \***\*\*\*\*\***\_\_\_\***\*\*\*\*\*** Date: **\*\***\_**\*\*** diff --git a/infrastructure.md b/docs/infrastructure.md similarity index 100% rename from infrastructure.md rename to docs/infrastructure.md diff --git a/docs/logging.md b/docs/logging.md deleted file mode 100644 index 61375a2..0000000 --- a/docs/logging.md +++ /dev/null @@ -1,155 +0,0 @@ -# Logging Configuration - -This document describes the logging setup for the Aniworld FastAPI application. - -## Overview - -The application uses Python's built-in `logging` module with both console and file output. All logs are written to: - -- **Console**: Colored output for development -- **Log File**: `logs/fastapi_app.log` with detailed timestamps - -## Log Levels - -By default, the application logs at `INFO` level. You can change this by setting the `LOG_LEVEL` environment variable: - -```bash -export LOG_LEVEL=DEBUG # More verbose -export LOG_LEVEL=INFO # Default -export LOG_LEVEL=WARNING # Less verbose -export LOG_LEVEL=ERROR # Errors only -``` - -Or in your `.env` file: - -``` -LOG_LEVEL=INFO -``` - -## Running the Server - -### Option 1: Using the run_server.py script (Recommended) - -```bash -conda run -n AniWorld python run_server.py -``` - -This script uses the custom uvicorn logging configuration that ensures proper console and file logging. - -### Option 2: Using the shell script - -```bash -./start_server.sh -``` - -### Option 3: Using uvicorn directly - -```bash -conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload -``` - -**Note**: When using `conda run`, console output may not be visible in real-time. The logs will still be written to the file. - -## Log File Location - -All logs are written to: `logs/fastapi_app.log` - -To view logs in real-time: - -```bash -tail -f logs/fastapi_app.log -``` - -## Log Format - -### Console Output - -``` -INFO: Starting FastAPI application... -INFO: Server running on http://127.0.0.1:8000 -``` - -### File Output - -``` -2025-10-25 17:31:19 - aniworld - INFO - Starting FastAPI application... -2025-10-25 17:31:19 - aniworld - INFO - Server running on http://127.0.0.1:8000 -``` - -## What Gets Logged - -The application logs: - -- **Startup/Shutdown**: Application lifecycle events -- **Configuration**: Loaded settings and configuration -- **HTTP Requests**: Via uvicorn.access logger -- **Errors**: Exception tracebacks with full context -- **WebSocket Events**: Connection/disconnection events -- **Download Progress**: Progress updates for anime downloads -- **File Operations**: File creation, deletion, scanning - -## Logger Names - -Different parts of the application use different logger names: - -- `aniworld`: Main application logger -- `uvicorn.error`: Uvicorn server errors -- `uvicorn.access`: HTTP request logs -- `src.core.SeriesApp`: Core anime logic -- `src.core.SerieScanner`: File scanning operations -- `src.server.*`: Web API endpoints and services - -## Programmatic Usage - -To use logging in your code: - -```python -from src.infrastructure.logging import get_logger - -logger = get_logger(__name__) - -logger.info("This is an info message") -logger.warning("This is a warning") -logger.error("This is an error", exc_info=True) # Includes traceback -``` - -## Log Rotation - -Log files can grow large over time. Consider implementing log rotation: - -```bash -# Archive old logs -mkdir -p logs/archived -mv logs/fastapi_app.log logs/archived/fastapi_app_$(date +%Y%m%d_%H%M%S).log -``` - -Or use Python's `RotatingFileHandler` (can be added to `src/infrastructure/logging/logger.py`). - -## Troubleshooting - -### No console output when using `conda run` - -This is a known limitation of `conda run`. The logs are still being written to the file. To see console output: - -1. Use the log file: `tail -f logs/fastapi_app.log` -2. Or run without conda: `python run_server.py` (after activating environment with `conda activate AniWorld`) - -### Log file not created - -- Check that the `logs/` directory exists (it's created automatically) -- Verify write permissions on the `logs/` directory -- Check the `LOG_LEVEL` environment variable - -### Too much logging - -Set a higher log level: - -```bash -export LOG_LEVEL=WARNING -``` - -### Missing logs - -- Check that you're using the logger, not `print()` -- Verify the log level is appropriate for your messages -- Ensure the logger is properly configured (should happen automatically on startup) diff --git a/docs/progress_service_architecture.md b/docs/progress_service_architecture.md deleted file mode 100644 index 675e418..0000000 --- a/docs/progress_service_architecture.md +++ /dev/null @@ -1,450 +0,0 @@ -# Progress Service Architecture - -## Overview - -The ProgressService serves as the **single source of truth** for all real-time progress tracking in the Aniworld application. This architecture follows a clean, decoupled design where progress updates flow through a well-defined pipeline. - -## Architecture Diagram - -``` -┌─────────────┐ -│ SeriesApp │ ← Core download/scan logic -└──────┮──────┘ - │ Events (download_status, scan_status) - ▾ -┌─────────────────┐ -│ AnimeService │ ← Subscribes to SeriesApp events -└────────┮────────┘ - │ Forwards events - ▾ -┌──────────────────┐ -│ ProgressService │ ← Single source of truth for progress -└────────┮─────────┘ - │ Emits events to subscribers - ▾ -┌──────────────────┐ -│ WebSocketService │ ← Subscribes to progress events -└──────────────────┘ - │ - ▾ - Connected clients receive real-time updates -``` - -## Components - -### 1. SeriesApp (Core Layer) - -**Location**: `src/core/SeriesApp.py` - -**Responsibilities**: - -- Execute actual downloads and scans -- Fire events with detailed progress information -- Manage download state and error handling - -**Events**: - -- `download_status`: Fired during downloads - - - `started`: Download begins - - `progress`: Progress updates (percent, speed, ETA) - - `completed`: Download finished successfully - - `failed`: Download encountered an error - -- `scan_status`: Fired during library scans - - `started`: Scan begins - - `progress`: Scan progress updates - - `completed`: Scan finished - - `failed`: Scan encountered an error - - `cancelled`: Scan was cancelled - -### 2. AnimeService (Service Layer) - -**Location**: `src/server/services/anime_service.py` - -**Responsibilities**: - -- Subscribe to SeriesApp events -- Translate SeriesApp events into ProgressService updates -- Provide async interface for web layer - -**Event Handlers**: - -```python -def _on_download_status(self, args): - """Translates download events to progress service.""" - if args.status == "started": - await progress_service.start_progress(...) - elif args.status == "progress": - await progress_service.update_progress(...) - elif args.status == "completed": - await progress_service.complete_progress(...) - elif args.status == "failed": - await progress_service.fail_progress(...) - -def _on_scan_status(self, args): - """Translates scan events to progress service.""" - # Similar pattern as download_status -``` - -### 3. ProgressService (Service Layer) - -**Location**: `src/server/services/progress_service.py` - -**Responsibilities**: - -- Central progress tracking for all operations -- Maintain active and historical progress records -- Calculate percentages and rates -- Emit events to subscribers (event-based architecture) - -**Progress Types**: - -- `DOWNLOAD`: Individual episode downloads -- `SCAN`: Library scans for missing episodes -- `QUEUE`: Download queue operations -- `SYSTEM`: System-level operations -- `ERROR`: Error notifications - -**Event System**: - -```python -# Subscribe to progress events -def subscribe(event_name: str, handler: Callable[[ProgressEvent], None]) -def unsubscribe(event_name: str, handler: Callable[[ProgressEvent], None]) - -# Internal event emission -async def _emit_event(event: ProgressEvent) -``` - -**Key Methods**: - -```python -async def start_progress(progress_id, progress_type, title, ...): - """Start tracking a new operation.""" - -async def update_progress(progress_id, current, total, message, ...): - """Update progress for an ongoing operation.""" - -async def complete_progress(progress_id, message, ...): - """Mark operation as completed.""" - -async def fail_progress(progress_id, error_message, ...): - """Mark operation as failed.""" -``` - -### 4. DownloadService (Service Layer) - -**Location**: `src/server/services/download_service.py` - -**Responsibilities**: - -- Manage download queue (FIFO processing) -- Track queue state (pending, active, completed, failed) -- Persist queue to disk -- Use ProgressService for queue-related updates - -**Progress Integration**: - -```python -# Queue operations notify via ProgressService -await progress_service.update_progress( - progress_id="download_queue", - message="Added 3 items to queue", - metadata={ - "action": "items_added", - "queue_status": {...} - }, - force_broadcast=True, -) -``` - -**Note**: DownloadService does NOT directly broadcast. Individual download progress flows through: -`SeriesApp → AnimeService → ProgressService → WebSocket` - -### 5. WebSocketService (Service Layer) - -**Location**: `src/server/services/websocket_service.py` - -**Responsibilities**: - -- Manage WebSocket connections -- Support room-based messaging -- Broadcast progress updates to clients -- Handle connection lifecycle - -**Integration**: -WebSocketService subscribes to ProgressService events: - -```python -async def lifespan(app: FastAPI): - # Get services - progress_service = get_progress_service() - ws_service = get_websocket_service() - - # Define event handler - async def progress_event_handler(event) -> None: - """Handle progress events and broadcast via WebSocket.""" - message = { - "type": event.event_type, - "data": event.progress.to_dict(), - } - await ws_service.manager.broadcast_to_room(message, event.room) - - # Subscribe to progress events - progress_service.subscribe("progress_updated", progress_event_handler) -``` - -## Data Flow Examples - -### Example 1: Episode Download - -1. **User triggers download** via API endpoint -2. **DownloadService** queues the download -3. **DownloadService** starts processing → calls `anime_service.download()` -4. **AnimeService** calls `series_app.download()` -5. **SeriesApp** fires `download_status` events: - - `started` → AnimeService → ProgressService → WebSocket → Client - - `progress` (multiple) → AnimeService → ProgressService → WebSocket → Client - - `completed` → AnimeService → ProgressService → WebSocket → Client - -### Example 2: Library Scan - -1. **User triggers scan** via API endpoint -2. **AnimeService** calls `series_app.rescan()` -3. **SeriesApp** fires `scan_status` events: - - `started` → AnimeService → ProgressService → WebSocket → Client - - `progress` (multiple) → AnimeService → ProgressService → WebSocket → Client - - `completed` → AnimeService → ProgressService → WebSocket → Client - -### Example 3: Queue Management - -1. **User adds items to queue** via API endpoint -2. **DownloadService** adds items to internal queue -3. **DownloadService** notifies via ProgressService: - ```python - await progress_service.update_progress( - progress_id="download_queue", - message="Added 5 items to queue", - metadata={"queue_status": {...}}, - force_broadcast=True, - ) - ``` -4. **ProgressService** → WebSocket → Client receives queue update - -## Benefits of This Architecture - -### 1. **Single Source of Truth** - -- All progress tracking goes through ProgressService -- Consistent progress reporting across the application -- Easy to monitor and debug - -### 2. **Decoupling** - -- Core logic (SeriesApp) doesn't know about web layer -- Services can be tested independently -- Easy to add new progress consumers (e.g., CLI, GUI) - -### 3. **Type Safety** - -- Strongly typed progress updates -- Enum-based progress types and statuses -- Clear data contracts - -### 4. **Flexibility** - -- Multiple subscribers can listen to progress events -- Room-based WebSocket messaging -- Metadata support for custom data -- Multiple concurrent progress operations - -### 5. **Maintainability** - -- Clear separation of concerns -- Single place to modify progress logic -- Easy to extend with new progress types or subscribers - -### 6. **Scalability** - -- Event-based architecture supports multiple consumers -- Isolated error handling per subscriber -- No single point of failure - -## Progress IDs - -Progress operations are identified by unique IDs: - -- **Downloads**: `download_{serie_folder}_{season}_{episode}` -- **Scans**: `library_scan` -- **Queue**: `download_queue` - -## WebSocket Messages - -Clients receive progress updates in this format: - -```json -{ - "type": "download_progress", - "data": { - "id": "download_naruto_1_1", - "type": "download", - "status": "in_progress", - "title": "Downloading Naruto", - "message": "S01E01", - "percent": 45.5, - "current": 45, - "total": 100, - "metadata": {}, - "started_at": "2025-11-07T10:00:00Z", - "updated_at": "2025-11-07T10:05:00Z" - } -} -``` - -## Configuration - -### Startup (fastapi_app.py) - -```python -@asynccontextmanager -async def lifespan(app: FastAPI): - # Initialize services - progress_service = get_progress_service() - ws_service = get_websocket_service() - - # Define event handler - async def progress_event_handler(event) -> None: - """Handle progress events and broadcast via WebSocket.""" - message = { - "type": event.event_type, - "data": event.progress.to_dict(), - } - await ws_service.manager.broadcast_to_room(message, event.room) - - # Subscribe to progress events - progress_service.subscribe("progress_updated", progress_event_handler) -``` - -### Service Initialization - -```python -# AnimeService automatically subscribes to SeriesApp events -anime_service = AnimeService(series_app) - -# DownloadService uses ProgressService for queue updates -download_service = DownloadService(anime_service) -``` - -## Migration Notes - -### What Changed - -**Before (Callback-based)**: - -- ProgressService had a single `set_broadcast_callback()` method -- Only one consumer could receive updates -- Direct coupling between ProgressService and WebSocketService - -**After (Event-based)**: - -- ProgressService uses `subscribe()` and `unsubscribe()` methods -- Multiple consumers can subscribe to progress events -- Loose coupling - ProgressService doesn't know about subscribers -- Clean event flow: SeriesApp → AnimeService → ProgressService → Subscribers - -### Removed - -1. **ProgressService**: - - - `set_broadcast_callback()` method - - `_broadcast_callback` attribute - - `_broadcast()` method - -### Added - -1. **ProgressService**: - - - `ProgressEvent` dataclass to encapsulate event data - - `subscribe()` method for event subscription - - `unsubscribe()` method to remove handlers - - `_emit_event()` method for broadcasting to all subscribers - - `_event_handlers` dictionary to track subscribers - -2. **fastapi_app.py**: - - Event handler function `progress_event_handler` - - Uses `subscribe()` instead of `set_broadcast_callback()` - -### Benefits of Event-Based Design - -1. **Multiple Subscribers**: Can now have multiple services listening to progress - - ```python - # WebSocket for real-time updates - progress_service.subscribe("progress_updated", websocket_handler) - # Metrics for analytics - progress_service.subscribe("progress_updated", metrics_handler) - # Logging for debugging - progress_service.subscribe("progress_updated", logging_handler) - ``` - -2. **Isolated Error Handling**: If one subscriber fails, others continue working - -3. **Dynamic Subscription**: Handlers can subscribe/unsubscribe at runtime - -4. **Extensibility**: Easy to add new features without modifying ProgressService - -## Testing - -### Unit Tests - -- Test each service independently -- Mock ProgressService for services that use it -- Verify event handler logic - -### Integration Tests - -- Test full flow: SeriesApp → AnimeService → ProgressService → WebSocket -- Verify progress updates reach clients -- Test error handling - -### Example Test - -```python -async def test_download_progress_flow(): - # Setup - progress_service = ProgressService() - events_received = [] - - async def mock_event_handler(event): - events_received.append(event) - - progress_service.subscribe("progress_updated", mock_event_handler) - - # Execute - await progress_service.start_progress( - progress_id="test_download", - progress_type=ProgressType.DOWNLOAD, - title="Test" - ) - - # Verify - assert len(events_received) == 1 - assert events_received[0].event_type == "download_progress" - assert events_received[0].progress.id == "test_download" -``` - -## Future Enhancements - -1. **Progress Persistence**: Save progress to database for recovery -2. **Progress History**: Keep detailed history for analytics -3. **Rate Limiting**: Throttle progress updates to prevent spam -4. **Progress Aggregation**: Combine multiple progress operations -5. **Custom Rooms**: Allow clients to subscribe to specific progress types - -## Related Documentation - -- [WebSocket API](./websocket_api.md) -- [Download Service](./download_service.md) -- [Error Handling](./error_handling_validation.md) -- [API Implementation](./api_implementation_summary.md) diff --git a/docs/user_guide.md b/docs/user_guide.md deleted file mode 100644 index 37f2f29..0000000 --- a/docs/user_guide.md +++ /dev/null @@ -1,628 +0,0 @@ -# Aniworld User Guide - -Complete user guide for the Aniworld Download Manager web application. - -## Table of Contents - -1. [Getting Started](#getting-started) -2. [Installation](#installation) -3. [Initial Setup](#initial-setup) -4. [User Interface](#user-interface) -5. [Configuration](#configuration) -6. [Managing Anime](#managing-anime) -7. [Download Queue](#download-queue) -8. [Troubleshooting](#troubleshooting) -9. [Keyboard Shortcuts](#keyboard-shortcuts) -10. [FAQ](#faq) - -## Getting Started - -Aniworld is a modern web application for managing and downloading anime series. It provides: - -- **Web-based Interface**: Access via any modern web browser -- **Real-time Updates**: Live download progress tracking -- **Queue Management**: Organize and prioritize downloads -- **Configuration Management**: Easy setup and configuration -- **Backup & Restore**: Automatic configuration backups - -### System Requirements - -- **OS**: Windows, macOS, or Linux -- **Browser**: Chrome, Firefox, Safari, or Edge (modern versions) -- **Internet**: Required for downloading anime -- **Storage**: Sufficient space for anime files (adjustable) -- **RAM**: Minimum 2GB recommended - -## Installation - -### Prerequisites - -- Python 3.10 or higher -- Poetry (Python package manager) -- Git (for cloning the repository) - -### Step-by-Step Installation - -#### 1. Clone the Repository - -```bash -git clone https://github.com/your-repo/aniworld.git -cd aniworld -``` - -#### 2. Create Python Environment - -```bash -# Using conda (recommended) -conda create -n AniWorld python=3.10 -conda activate AniWorld - -# Or using venv -python -m venv venv -source venv/bin/activate # On Windows: venv\Scripts\activate -``` - -#### 3. Install Dependencies - -```bash -# Using pip -pip install -r requirements.txt - -# Or using poetry -poetry install -``` - -#### 4. Start the Application - -```bash -# Using conda -conda run -n AniWorld python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 --reload - -# Or directly -python -m uvicorn src.server.fastapi_app:app --host 127.0.0.1 --port 8000 -``` - -#### 5. Access the Application - -Open your browser and navigate to: - -``` -http://localhost:8000 -``` - -## Initial Setup - -### Setting Master Password - -On first launch, you'll be prompted to set a master password: - -1. **Navigate to Setup Page**: `http://localhost:8000/setup` -2. **Enter Password**: Choose a strong password (minimum 8 characters recommended) -3. **Confirm Password**: Re-enter the password for confirmation -4. **Save**: Click "Set Master Password" - -The master password protects access to your anime library and download settings. - -### Configuration - -After setting the master password, configure the application: - -1. **Login**: Use your master password to log in -2. **Go to Settings**: Click the settings icon in the navigation bar -3. **Configure Directories**: - - - **Anime Directory**: Where anime series are stored - - **Download Directory**: Where downloads are saved - - **Cache Directory**: Temporary file storage (optional) - -4. **Advanced Settings** (optional): - - - **Session Timeout**: How long before auto-logout - - **Log Level**: Application logging detail level - - **Theme**: Light or dark mode preference - -5. **Save**: Click "Save Configuration" - -### Automatic Backups - -The application automatically creates backups when you update configuration. You can: - -- View all backups in Settings → Backups -- Manually create a backup anytime -- Restore previous configuration versions -- Delete old backups to save space - -## User Interface - -### Dashboard - -The main dashboard shows: - -- **Quick Stats**: Total anime, episodes, storage used -- **Recent Activity**: Latest downloads and actions -- **Quick Actions**: Add anime, manage queue, view settings - -### Navigation - -**Top Navigation Bar**: - -- **Logo**: Return to dashboard -- **Anime**: Browse and manage anime library -- **Downloads**: View download queue and history -- **Settings**: Configure application -- **Account**: User menu (logout, profile) - -### Theme - -**Dark Mode / Light Mode**: - -- Toggle theme in Settings -- Theme preference is saved automatically -- Default theme can be set in configuration - -## Managing Anime - -### Browsing Anime Library - -1. **Click "Anime"** in navigation -2. **View Anime List**: Shows all anime with missing episodes -3. **Filter**: Filter by series status or search by name - -### Adding New Anime - -1. **Click "Add Anime"** button -2. **Search**: Enter anime title or key -3. **Select**: Choose anime from search results -4. **Confirm**: Click "Add to Library" - -### Viewing Anime Details - -1. **Click Anime Title** in the list -2. **View Information**: Episodes, status, total count -3. **Add Episodes**: Select specific episodes to download - -### Managing Episodes - -**View Episodes**: - -- All seasons and episodes for the series -- Downloaded status indicators -- File size information - -**Download Episodes**: - -1. Select episodes to download -2. Click "Add to Queue" -3. Choose priority (Low, Normal, High) -4. Confirm - -**Delete Episodes**: - -1. Select downloaded episodes -2. Click "Delete" -3. Choose whether to keep or remove files -4. Confirm - -## Download Queue - -### Queue Status - -The queue page shows: - -- **Queue Stats**: Total items, status breakdown -- **Current Download**: What's downloading now -- **Progress**: Download speed and time remaining -- **Queue List**: All pending downloads - -### Queue Management - -### Add Episodes to Queue - -1. Go to "Anime" or "Downloads" -2. Select anime and episodes -3. Click "Add to Queue" -4. Set priority and confirm - -### Manage Queue Items - -**Pause/Resume**: - -- Click pause icon to pause individual download -- Resume when ready - -**Prioritize**: - -1. Click item in queue -2. Select "Increase Priority" or "Decrease Priority" -3. Items with higher priority download first - -**Remove**: - -1. Select item -2. Click "Remove" button -3. Confirm deletion - -### Control Queue Processing - -**Start Queue**: Begin downloading queued items - -- Click "Start" button -- Downloads begin in priority order - -**Pause Queue**: Pause all downloads temporarily - -- Click "Pause" button -- Current download pauses -- Click "Resume" to continue - -**Stop Queue**: Stop all downloads - -- Click "Stop" button -- Current download stops -- Queue items remain - -**Clear Completed**: Remove completed items from queue - -- Click "Clear Completed" -- Frees up queue space - -### Monitor Progress - -**Real-time Updates**: - -- Download speed (MB/s) -- Progress percentage -- Time remaining -- Current file size - -**Status Indicators**: - -- ðŸ”ĩ Pending: Waiting to download -- ðŸŸĄ Downloading: Currently downloading -- ðŸŸĒ Completed: Successfully downloaded -- ðŸ”ī Failed: Download failed - -### Retry Failed Downloads - -1. Find failed item in queue -2. Click "Retry" button -3. Item moves back to pending -4. Download restarts when queue processes - -## Configuration - -### Basic Settings - -**Anime Directory**: - -- Path where anime series are stored -- Must be readable and writable -- Can contain nested folders - -**Download Directory**: - -- Where new downloads are saved -- Should have sufficient free space -- Temporary files stored during download - -**Session Timeout**: - -- Minutes before automatic logout -- Default: 1440 (24 hours) -- Minimum: 15 minutes - -### Advanced Settings - -**Log Level**: - -- DEBUG: Verbose logging (development) -- INFO: Standard information -- WARNING: Warnings and errors -- ERROR: Only errors - -**Update Frequency**: - -- How often to check for new episodes -- Default: Daily -- Options: Hourly, Daily, Weekly, Manual - -**Provider Settings**: - -- Anime provider configuration -- Streaming server preferences -- Retry attempts and timeouts - -### Storage Management - -**View Storage Statistics**: - -- Total anime library size -- Available disk space -- Downloaded vs. pending size - -**Manage Storage**: - -1. Go to Settings → Storage -2. View breakdown by series -3. Delete old anime to free space - -### Backup Management - -**Create Backup**: - -1. Go to Settings → Backups -2. Click "Create Backup" -3. Backup created with timestamp - -**View Backups**: - -- List of all configuration backups -- Creation date and time -- Size of each backup - -**Restore from Backup**: - -1. Click backup name -2. Review changes -3. Click "Restore" -4. Application reloads with restored config - -**Delete Backup**: - -1. Select backup -2. Click "Delete" -3. Confirm deletion - -## Troubleshooting - -### Common Issues - -#### Can't Access Application - -**Problem**: Browser shows "Connection Refused" - -**Solutions**: - -- Verify application is running: Check terminal for startup messages -- Check port: Application uses port 8000 by default -- Try different port: Modify configuration if 8000 is in use -- Firewall: Check if firewall is blocking port 8000 - -#### Login Issues - -**Problem**: Can't log in or session expires - -**Solutions**: - -- Clear browser cookies: Settings → Clear browsing data -- Try incognito mode: May help with cache issues -- Reset master password: Delete `data/config.json` and restart -- Check session timeout: Verify in settings - -#### Download Failures - -**Problem**: Downloads keep failing - -**Solutions**: - -- Check internet connection: Ensure stable connection -- Verify provider: Check if anime provider is accessible -- View error logs: Go to Settings → Logs for details -- Retry download: Use "Retry" button on failed items -- Contact provider: Provider might be down or blocking access - -#### Slow Downloads - -**Problem**: Downloads are very slow - -**Solutions**: - -- Check bandwidth: Other applications might be using internet -- Provider issue: Provider might be throttling -- Try different quality: Lower quality might download faster -- Queue priority: Reduce queue size for faster downloads -- Hardware: Ensure sufficient CPU and disk performance - -#### Application Crashes - -**Problem**: Application stops working - -**Solutions**: - -- Check logs: View logs in Settings → Logs -- Restart application: Stop and restart the process -- Clear cache: Delete temporary files in Settings -- Reinstall: As last resort, reinstall application - -### Error Messages - -#### "Authentication Failed" - -- Incorrect master password -- Session expired (need to log in again) -- Browser cookies cleared - -#### "Configuration Error" - -- Invalid directory path -- Insufficient permissions -- Disk space issues - -#### "Download Error: Provider Error" - -- Anime provider is down -- Content no longer available -- Streaming server error - -#### "Database Error" - -- Database file corrupted -- Disk write permission denied -- Low disk space - -### Getting Help - -**Check Application Logs**: - -1. Go to Settings → Logs -2. Search for error messages -3. Check timestamp and context - -**Review Documentation**: - -- Check [API Reference](./api_reference.md) -- Review [Deployment Guide](./deployment.md) -- Consult inline code comments - -**Community Support**: - -- Check GitHub issues -- Ask on forums or Discord -- File bug report with logs - -## Keyboard Shortcuts - -### General - -| Shortcut | Action | -| ------------------ | ------------------- | -| `Ctrl+S` / `Cmd+S` | Save settings | -| `Ctrl+L` / `Cmd+L` | Focus search | -| `Escape` | Close dialogs | -| `?` | Show shortcuts help | - -### Anime Management - -| Shortcut | Action | -| -------- | ------------- | -| `Ctrl+A` | Add new anime | -| `Ctrl+F` | Search anime | -| `Delete` | Remove anime | -| `Enter` | View details | - -### Download Queue - -| Shortcut | Action | -| -------------- | ------------------- | -| `Ctrl+D` | Add to queue | -| `Space` | Play/Pause queue | -| `Ctrl+Shift+P` | Pause all downloads | -| `Ctrl+Shift+S` | Stop all downloads | - -### Navigation - -| Shortcut | Action | -| -------- | --------------- | -| `Ctrl+1` | Go to Dashboard | -| `Ctrl+2` | Go to Anime | -| `Ctrl+3` | Go to Downloads | -| `Ctrl+4` | Go to Settings | - -### Accessibility - -| Shortcut | Action | -| ----------- | ------------------------- | -| `Tab` | Navigate between elements | -| `Shift+Tab` | Navigate backwards | -| `Alt+M` | Skip to main content | -| `Alt+H` | Show help | - -## FAQ - -### General Questions - -**Q: Is Aniworld free?** -A: Yes, Aniworld is open-source and completely free to use. - -**Q: Do I need internet connection?** -A: Yes, to download anime. Once downloaded, you can watch offline. - -**Q: What formats are supported?** -A: Supports most video formats (MP4, MKV, AVI, etc.) depending on provider. - -**Q: Can I use it on mobile?** -A: The web interface works on mobile browsers, but is optimized for desktop. - -### Installation & Setup - -**Q: Can I run multiple instances?** -A: Not recommended. Use single instance with same database. - -**Q: Can I change installation directory?** -A: Yes, reconfigure paths in Settings → Directories. - -**Q: What if I forget my master password?** -A: Delete `data/config.json` and restart (loses all settings). - -### Downloads - -**Q: How long do downloads take?** -A: Depends on file size and internet speed. Typically 5-30 minutes per episode. - -**Q: Can I pause/resume downloads?** -A: Yes, pause individual items or entire queue. - -**Q: What happens if download fails?** -A: Item remains in queue. Use "Retry" to attempt again. - -**Q: Can I download multiple episodes simultaneously?** -A: Yes, configure concurrent downloads in settings. - -### Storage - -**Q: How much space do I need?** -A: Depends on anime count. Plan for 500MB-2GB per episode. - -**Q: Where are files stored?** -A: In the configured "Anime Directory" in settings. - -**Q: Can I move downloaded files?** -A: Yes, but update the path in configuration afterwards. - -### Performance - -**Q: Application is slow, what can I do?** -A: Reduce queue size, check disk space, restart application. - -**Q: How do I free up storage?** -A: Go to Settings → Storage and delete anime you no longer need. - -**Q: Is there a way to optimize database?** -A: Go to Settings → Maintenance and run database optimization. - -### Support - -**Q: Where can I report bugs?** -A: File issues on GitHub repository. - -**Q: How do I contribute?** -A: See CONTRIBUTING.md for guidelines. - -**Q: Where's the source code?** -A: Available on GitHub (link in application footer). - ---- - -## Additional Resources - -- [API Reference](./api_reference.md) - For developers -- [Deployment Guide](./deployment.md) - For system administrators -- [GitHub Repository](https://github.com/your-repo/aniworld) -- [Interactive API Documentation](http://localhost:8000/api/docs) - ---- - -## Support - -For additional help: - -1. Check this user guide first -2. Review [Troubleshooting](#troubleshooting) section -3. Check application logs in Settings -4. File issue on GitHub -5. Contact community forums - ---- - -**Last Updated**: October 22, 2025 -**Version**: 1.0.0 diff --git a/instructions.md b/instructions.md index 5e1bdf5..6f5248e 100644 --- a/instructions.md +++ b/instructions.md @@ -120,98 +120,3 @@ For each task completed: - Good foundation for future enhancements if needed --- - -# ðŸŽŊ CRITICAL: Series Identifier Standardization - -## Overview - -**Problem:** The codebase currently uses multiple identifiers inconsistently: - -- `key` (provider identifier, e.g., "attack-on-titan") -- `folder` (filesystem folder name, e.g., "Attack on Titan (2013)") -- `serie_id` (sometimes key, sometimes folder) -- `serie_folder` (filesystem path used as identifier) - -**Solution:** Standardize on `key` as the single source of truth for all series identification. - -**Benefits:** - -- Single, consistent identifier throughout the codebase -- `key` is unique, provider-assigned, URL-safe -- `folder` becomes metadata only (not used for lookups) -- Clearer separation of concerns -- Easier to maintain and debug - -**Scope:** This affects core logic, services, API endpoints, frontend, WebSocket events, and tests. - ---- - -## Task Series: Identifier Standardization - -### Phase 4: API Layer ✅ (Completed November 28, 2025) - -### Phase 5: Frontend ✅ (Completed November 28, 2025) - -### Phase 6: Database Layer ✅ (Completed November 28, 2025) - -### Phase 7: Testing and Validation ✅ **Completed November 28, 2025** - -### Phase 8: Documentation and Cleanup ✅ **Completed November 28, 2025** - -All tasks completed: - -- **Task 8.1**: Updated `infrastructure.md` with enhanced identifier convention section including table format, key format requirements, migration notes, and code examples -- **Task 8.2**: Updated `docs/README.md` with series identifier convention section, updated `docs/api_reference.md` with key-based API examples -- **Task 8.3**: Added deprecation warnings with Python's `warnings` module to: - - `SerieList.get_by_folder()` in `src/core/entities/SerieList.py` - - Folder fallback lookup in `src/server/api/anime.py` - - `validate_series_key_or_folder()` in `src/server/utils/validators.py` - -All deprecation warnings include removal timeline (v3.0.0) and guidance to use `key` instead. - ---- - -### Phase 9: Final Validation ✅ **Completed November 28, 2025** - -All validation tasks completed: - -- **Task 9.1**: Full test suite passes (1006 tests). Fixed search API key extraction from link slugs. -- **Task 9.2**: Manual end-to-end testing verified - login, search (returns key), queue status (uses serie_id as key). All APIs work correctly with key identifier. -- **Task 9.3**: Performance tests pass (19 tests). Key lookup is O(1) at ~0.11Ξs per lookup. - ---- - -## Task Tracking - -### Completion Status - -- [x] Phase 1: Core Models and Data Layer ✅ -- [x] Phase 2: Core Application Layer ✅ -- [x] Phase 3: Service Layer ✅ -- [x] Phase 4: API Layer ✅ **Completed November 28, 2025** -- [x] Phase 5: Frontend ✅ **Completed November 28, 2025** -- [x] Phase 6: Database Layer ✅ **Completed November 28, 2025** -- [x] Phase 7: Testing and Validation ✅ **Completed November 28, 2025** -- [x] Phase 8: Documentation and Cleanup ✅ **Completed November 28, 2025** - - [x] Task 8.1: Update Infrastructure Documentation - Enhanced identifier convention section with table, format requirements, migration notes, and code examples - - [x] Task 8.2: Update README and Developer Docs - Updated docs/README.md with identifier section, updated api_reference.md with key-based examples - - [x] Task 8.3: Add Deprecation Warnings - Added warnings to SerieList.get_by_folder(), anime.py folder fallback, and validators.py -- [x] Phase 9: Final Validation ✅ **Completed November 28, 2025** - - [x] Task 9.1: Run Full Test Suite - 1006 tests pass, fixed search API key extraction - - [x] Task 9.2: Manual End-to-End Testing - All APIs verified with key identifier - - [x] Task 9.3: Performance Testing - 19 tests pass, O(1) key lookup - ---- - -## 🎉 Series Identifier Standardization Complete! - -All phases of the identifier standardization have been successfully completed. The codebase now consistently uses `key` as the primary identifier for series throughout: - -- Core entities and data layer -- Application layer services -- API endpoints and responses -- Frontend integration -- Database operations -- WebSocket events - -The `folder` field remains as metadata only and is no longer used for lookups. Deprecation warnings are in place for any legacy folder-based lookups, scheduled for removal in v3.0.0.