package Ġme . k ony aco . pix iv util Ċ Ċ import Ġio . ktor . client .* Ċ import Ġio . ktor . client . engine .* Ċ import Ġio . ktor . client . engine . java .* Ċ import Ġkotlinx . cli .* Ċ import Ġkotlinx . coroutines .* Ċ import Ġkotlinx . coroutines . channels . Channel Ċ import Ġkotlinx . coroutines . channels . Receive Channel Ċ import Ġkotlinx . coroutines . channels . produce Ċ import Ġkotlinx . coroutines . sync . Mutex Ċ import Ġkotlinx . coroutines . sync . with Lock Ċ import Ġme . k ony aco . pix iv lib . Pix iv Factory Ċ import Ġme . k ony aco . pix iv lib . features . Rank Mode Ċ import Ġme . k ony aco . pix iv lib . model . Image Ċ Ċ private Ġlateinit Ġvar ĠhttpClient : ĠHttpClient Ċ Ċ val Ġparser Ġ= ĠArg Parser (" pix iv util ") Ċ val Ġopt _ proxy Ġby Ġparser . option ( Arg Type . String , Ġ" proxy ", Ġ" p ", Ġ" HTTP Ġproxy Ġurl .") Ċ val Ġdownload Ġ= ĠDownload () Ċ val Ġrank Ġ= ĠRank () Ċ Ċ @ Experimental Cli Ċ fun Ġmain ( args : ĠArray < String >): ĠUnit Ġ= Ġrun Blocking Ġ{ ĊĠĠĠ Ġparser . sub commands ( download , Ġrank ) ĊĠĠĠ Ġparser . parse ( args ) Ċ } Ċ Ċ class ĠDownload Ġ: ĠSub command (" download ", Ġ" Download Ġan Ġart work ") Ġ{ ĊĠĠĠ Ġval Ġid Ġby Ġargument ( Arg Type . String , Ġ" id ", Ġ" Artwork ĠID .") ĊĠĠĠ Ġval Ġoutput Directory Ġby Ġoption ( Arg Type . String , Ġ" out _ dir ", Ġ" o ", Ġ" Output Ġdirectory . "). default (" download ") ĊĊĠĠĠ Ġoverride Ġfun Ġexecute () Ġ{ ĊĠĠĠĠĠĠĠ Ġdownload Single Artwork ( id , Ġoutput Directory ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ class ĠRank Ġ: ĠSub command (" rank ", Ġ" Get Ġand Ġdownload Ġrank ") Ġ{ ĊĠĠĠ Ġval Ġmode Ġby Ġargument ( Arg Type . Choice ( listOf (" daily ", Ġ" weekly ", Ġ" monthly "), Ġ{ Ġit Ġ}), Ġ" mode ", Ġ" Rank Ġmode ") ĊĠĠĠ Ġval Ġthread Ġby Ġoption ( Arg Type . Int , Ġ" thread ", Ġ" t ", Ġ" Download Ġthread . "). default ( 6 ) ĊĠĠĠ Ġval Ġoutput Directory Ġby Ġoption ( Arg Type . String , Ġ" out _ dir ", Ġ" o ", Ġ" Output Ġdirectory .") ĊĊĠĠĠ Ġoverride Ġfun Ġexecute () Ġ= Ġrun Blocking Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġrank Mode Ġ= Ġwhen Ġ( mode ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" daily " Ġ-> ĠRank Mode . DA IL Y ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" weekly " Ġ-> ĠRank Mode . WEEK LY ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" monthly " Ġ-> ĠRank Mode . MONTH LY ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġerror (" Unknown Ġrank Ġmode ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġdownload Rank ( rank Mode , Ġthread ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun Ġget HttpClient () Ġ{ ĊĠĠĠ ĠhttpClient Ġ= ĠHttpClient ( Java ) Ġ{ ĊĠĠĠĠĠĠĠ Ġengine Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġopt _ proxy ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġproxy Ġ= ĠProxy Builder . http ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġdownload Single Artwork ( id : ĠString , Ġout Dir : ĠString ) Ġ= Ġrun Blocking Ġ{ ĊĠĠĠ Ġget HttpClient () ĊĠĠĠ Ġval Ġdown loader Ġ= ĠDown loader ( httpClient , Ġout Dir ) ĊĠĠĠ Ġval Ġart work Ġ= ĠP ix iv Factory . create ( httpClient ). get Artwork ( id ) ĊĊĠĠĠ Ġart work . get Images (). forEach Ġ{ ĊĠĠĠĠĠĠĠ Ġval ĠfileName Ġ= ĠUtils . build Art Name ( id , Ġit . page ) ĊĠĠĠĠĠĠĠ Ġdown loader . download ( fileName , Ġit . urls . original ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun Ġdownload Rank ( rank Mode : ĠRank Mode , Ġthread : ĠInt ) Ġ= Ġrun Blocking Ġ{ ĊĠĠĠ Ġget HttpClient () ĊĠĠĠ Ġval Ġdown loader Ġ= ĠDown loader ( httpClient , Ġ" download /" Ġ+ ĠUtils . build Download Dir Name ( rank Mode )) ĊĠĠĠ Ġval Ġrank Ġ= ĠP ix iv Factory . create ( httpClient ). get Rank ( rank Mode ) ĊĊĠĠĠ Ġprintln (" Getting Ġ${ rank Mode . mode Name } Ġrank .. ") ĊĠĠĠ Ġprintln (" Got Ġ${ rank . get Artwork Count ()} Ġart works !") Ġ// ĠGot Ġ 5 0 Ġart works ! ĊĊĠĠĠ Ġval Ġart works Ġ= Ġrank . get Art works () ĊĠĠĠ Ġvar Ġart works Channel Ġ= Ġproduce Ġ{ Ġart works . forEach Ġ{ Ġsend ( it ) Ġ} Ġ} ĊĊĠĠĠ Ġval Ġmiddle Channel Ġ= ĠChannel < Pair < me . k ony aco . pix iv lib . features . Rank . Rank Artwork , ĠImage >>( Channel . UN LIMIT ED ) ĊĊĠĠĠ Ġlaunch Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġfailed Art works Ġ= Ġmutable ListOf < me . k ony aco . pix iv lib . features . Rank . Rank Artwork >() ĊĠĠĠĠĠĠĠ Ġval Ġmutex Ġ= ĠMutex () ĊĊĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcoroutine Scope Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrepeat ( 6 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlaunch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( art work Ġin Ġart works Channel ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġart work . art work . get Images (). forEach Ġ{ Ġimage Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmiddle Channel . send ( art work Ġto Ġimage ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmutex . with Lock Ġ{ Ġfailed Art works . add ( art work ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" Failed Ġto Ġget Ġimage Ġof Ġ${ art work . art work . id }: Ġ${ e . message }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġjoin All () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( failed Art works . size Ġ== Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmiddle Channel . close () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprint (" There Ġare Ġ${ failed Art works . size } Ġart works Ġfailed Ġto Ġresolve , Ġtry Ġagain ? Ġ( Y / n ) Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( readLine ()?. equals (" n ", Ġtrue ) Ġ== Ġtrue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmiddle Channel . close () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtemp Ġ= Ġmutex . with Lock Ġ{ Ġfailed Art works . toList () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġart works Channel Ġ= Ġproduce Ġ{ Ġtemp . forEach Ġ{ Ġsend ( it ) Ġ} Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġvar Ġimage Channel : ĠReceive Channel < Pair < me . k ony aco . pix iv lib . features . Rank . Rank Artwork , ĠImage >> Ġ= Ġmiddle Channel ĊĊĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmutex Ġ= ĠMutex () ĊĠĠĠĠĠĠĠ Ġval Ġerror Artwork Ġ= Ġmutable ListOf < Pair < me . k ony aco . pix iv lib . features . Rank . Rank Artwork , ĠImage >>() ĊĊĠĠĠĠĠĠĠ Ġcoroutine Scope Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrepeat ( thread ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlaunch Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( item , Ġimage ) Ġin Ġimage Channel ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠfileName Ġ= ĠUtils . build FileName ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġitem . index In Rank , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġitem . art work . id , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġitem . art work . getTitle (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġitem . art work . get Author (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġimage . page ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdown loader . download ( fileName , Ġimage . urls . original ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠC ancellation Exception ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow Ġe ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" Download Ġfailed : Ġ${ e . message }") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmutex . with Lock Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerror Artwork . add ( item Ġto Ġimage ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġjoin All () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġif Ġ( error Artwork . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" All Ġtasks Ġare Ġcompleted !") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ run Blocking ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprint (" There Ġare Ġ${ error Artwork . size } Ġart works Ġhaven 't Ġbeen Ġdownloaded , Ġretry ? Ġ( Y / n ) Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( readLine ()?. equals (" n ", Ġtrue ) Ġ== Ġtrue ) Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġimage Channel Ġ= Ġproduce Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġerror Artwork . forEach Ġ{ Ġsend ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }