package Ġcom . he a 3 ven . id ol sc raper . ui Ċ Ċ import Ġcom . he a 3 ven . id ol sc raper . Config Ċ import Ġcom . he a 3 ven . id ol sc raper . Preserve Original Save Strategy Ċ import Ġcom . he a 3 ven . id ol sc raper . get FileName Strategy Ċ import Ġcom . he a 3 ven . id ol sc raper . get Save Strategy Ċ import Ġcom . he a 3 ven . id ol sc raper . page . Sc rap ing Task Ċ import Ġcom . he a 3 ven . id ol sc raper . page . getPage Handler Ċ import Ġjava . awt .* Ċ import Ġjava . awt . event . ActionEvent Ċ import Ġjava . awt . event . Focus Event Ċ import Ġjava . awt . event . Focus Listener Ċ import Ġjava . io . Buffered InputStream Ċ import Ġjava . io . InputStream Ċ import Ġjava . io . PrintWriter Ċ import Ġjava . io . String Writer Ċ import Ġjava . net . ID N Ċ import Ġjava . net . Malformed URLException Ċ import Ġjava . net . URL Ċ import Ġjava . nio . file . Files Ċ import Ġjava . nio . file . Paths Ċ import Ġjavax . image io . Image IO Ċ import Ġjavax . swing .* Ċ import Ġjavax . swing . border . Empty Border Ċ Ċ class ĠMainWindow Ġ: ĠJ Frame (" Id ol ĠSc raper ") Ġ{ ĊĊ ĉ private Ġval Ġdir Chooser Ġ= ĠJ FileChooser (). apply Ġ{ Ċĉ ĉ dialog Title Ġ= Ġ" Target Ġdestination " Ċĉ ĉ file Selection Mode Ġ= ĠJ FileChooser . DIRECT ORIES _ ONLY Ċĉ ĉ is Accept All File Filter Used Ġ= Ġfalse Ċĉ ĉ selected File Ġ= ĠConfig . get Destination Dir () Ċ ĉ } ĊĊ ĉ init Ġ{ Ċĉ ĉ default Close Operation Ġ= ĠEXIT _ ON _ CLOSE Ċĉ ĉ size Ġ= ĠDimension ( 6 0 0 , Ġ 9 0 0 ) ĊĊĉ ĉ layout Ġ= ĠGrid BagLayout () ĊĊĉ ĉ val Ġurl Lbl Ġ= ĠJLabel (" URL :") Ċĉ ĉ url Lbl . border Ġ= ĠEmpty Border ( 0 , Ġ 5 , Ġ 0 , Ġ 0 ) Ċĉ ĉ val Ġurl Txt Ġ= ĠJTextField () Ċĉ ĉ url Txt . add Focus Listener ( object Ġ: ĠFocus Listener Ġ{ Ċĉĉ ĉ override Ġfun Ġfocus Lost ( e : ĠFocus Event ?) Ġ{ Ċĉĉ ĉ } ĊĊĉĉ ĉ override Ġfun Ġfocus G ained ( e : ĠFocus Event ?) Ġ{ Ċĉĉĉ ĉ url Txt . select ( 0 , Ġurl Txt . text . length ) Ċĉĉ ĉ } Ċĉ ĉ }) ĊĊĉ ĉ val Ġdest Lbl Ġ= ĠJLabel (" Destination :") Ċĉ ĉ dest Lbl . border Ġ= ĠEmpty Border ( 0 , Ġ 5 , Ġ 0 , Ġ 0 ) Ċĉ ĉ val Ġdest Txt Ġ= ĠJTextField ( Config . get Destination Dir ()?. absolute Path Ġ?: Ġ"") Ċĉ ĉ dest Txt . add Focus Listener ( object Ġ: ĠFocus Listener Ġ{ Ċĉĉ ĉ override Ġfun Ġfocus Lost ( e : ĠFocus Event ?) Ġ{ Ċĉĉ ĉ } ĊĊĉĉ ĉ override Ġfun Ġfocus G ained ( e : ĠFocus Event ?) Ġ{ Ċĉĉĉ ĉ dest Txt . select ( 0 , Ġdest Txt . text . length ) Ċĉĉ ĉ } Ċĉ ĉ }) Ċĉ ĉ val Ġdest Btn Ġ= ĠJButton () Ċĉ ĉ dest Btn . action Ġ= Ġobject Ġ: ĠAbstract Action () Ġ{ Ċĉĉ ĉ override Ġfun ĠactionPerformed ( e : ĠAction Event ?) Ġ{ Ċĉĉĉ ĉ if Ġ( dir Chooser . show Open Dialog ( this @ MainWindow ) Ġ== ĠJ FileChooser . APPRO VE _ OPTION ) Ġ{ Ċĉĉĉĉ ĉ dest Txt . text Ġ= Ġdir Chooser . selected File . absolute Path Ċĉĉĉĉ ĉ Config . set Destination Dir ( dir Chooser . selected File ) Ċĉĉĉ ĉ } Ċĉĉ ĉ } Ċĉ ĉ } Ċĉ ĉ dest Btn . text Ġ= Ġ" ..." ĊĊĉ ĉ val Ġformat Lbl Ġ= ĠJLabel (" Format :") Ċĉ ĉ format Lbl . border Ġ= ĠEmpty Border ( 0 , Ġ 5 , Ġ 0 , Ġ 0 ) Ċĉ ĉ val Ġformat Cb Ġ= ĠJ ComboBox ( array Of (" original ", Ġ" png ", Ġ" jpg ")) Ċĉ ĉ format Cb . preferred Size Ġ= ĠDimension ( 1 0 0 , Ġ 2 5 ) Ċĉ ĉ format Cb . border Ġ= ĠEmpty Border ( 2 , Ġ 2 , Ġ 2 , Ġ 5 ) Ċĉ ĉ format Cb . selected Item Ġ= ĠConfig . get Format () Ċĉ ĉ format Cb . action Ġ= Ġobject Ġ: ĠAbstract Action () Ġ{ Ċĉĉ ĉ override Ġfun ĠactionPerformed ( e : ĠAction Event ?) Ġ{ Ċĉĉĉ ĉ Config . set Format ( format Cb . selected Item Ġas ĠString ?) Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ val ĠfileName Lbl Ġ= ĠJLabel (" File ĠName :") Ċĉ ĉ fileName Lbl . border Ġ= ĠEmpty Border ( 0 , Ġ 5 , Ġ 0 , Ġ 0 ) Ċĉ ĉ val ĠfileName Cb Ġ= ĠJ ComboBox ( array Of (" original ", Ġ" number ed ")) Ċĉ ĉ fileName Cb . preferred Size Ġ= ĠDimension ( 1 0 0 , Ġ 2 5 ) Ċĉ ĉ fileName Cb . border Ġ= ĠEmpty Border ( 2 , Ġ 2 , Ġ 2 , Ġ 5 ) Ċĉ ĉ fileName Cb . selected Item Ġ= ĠConfig . get FileName Format () Ċĉ ĉ fileName Cb . action Ġ= Ġobject Ġ: ĠAbstract Action () Ġ{ Ċĉĉ ĉ override Ġfun ĠactionPerformed ( e : ĠAction Event ?) Ġ{ Ċĉĉĉ ĉ Config . set FileName Format ( fileName Cb . selected Item Ġas ĠString ?) Ċĉĉ ĉ } Ċĉ ĉ } ĊĊĉ ĉ val Ġscan Btn Ġ= ĠJButton () Ċĉ ĉ scan Btn . preferred Size Ġ= ĠDimension ( 7 2 , Ġ 2 2 ) ĊĊĉ ĉ val Ġlog Txt Area Ġ= ĠJ TextArea () Ċĉ ĉ log Txt Area . is Editable Ġ= Ġfalse Ċĉ ĉ val Ġlog Txt Area Sc rl Pn Ġ= ĠJ ScrollPane ( log Txt Area ) ĊĊĉ ĉ scan Btn . action Ġ= Ġobject Ġ: ĠAbstract Action () Ġ{ ĊĊĉĉ ĉ override Ġfun ĠactionPerformed ( e : ĠAction Event ?) Ġ{ Ċĉĉĉ ĉ val Ġdest Dir 1 Ġ= ĠPaths . get ( dest Txt . text ) Ċĉĉĉ ĉ if Ġ( dest Txt . text . length Ġ== Ġ 0 Ġ|| Ġ! Files . exists ( dest Dir 1 ) Ġ|| Ġ! Files . isDirectory ( dest Dir 1 )) Ġ{ Ċĉĉĉĉ ĉ log Txt Area . text Ġ+= Ġ" Invalid Ġdestination Ġdirectory " Ċĉĉĉĉ ĉ return Ċĉĉĉ ĉ } ĊĊĉĉĉ ĉ val ĠfileName St gy Ġ= ĠfileName Cb . selected Item Ġas ĠString Ċĉĉĉ ĉ val Ġformat St gy Ġ= Ġformat Cb . selected Item Ġas ĠString Ċĉĉĉ ĉ val Ġtask Ġ= ĠSc rap ing Task ( dest Dir 1 , Ġget Save Strategy ( format St gy ), Ċĉĉĉĉĉ ĉ get FileName Strategy ( fileName St gy )) ĊĊĉĉĉ ĉ val Ġworker Ġ= Ġobject Ġ: ĠSw ing Worker < Any , ĠString >() Ġ{ Ċĉĉĉĉ ĉ override Ġfun Ġdo In Background () Ġ{ Ċĉĉĉĉĉ ĉ task . log Ġ= Ġ{ Ġpublish ( it ) Ġ} Ċĉĉĉĉĉ ĉ try Ġ{ Ċĉĉĉĉĉĉ ĉ val Ġurl Ġ= ĠURL ( url Txt . text ) Ċĉĉĉĉĉĉ ĉ task . url Ġ= ĠURL ( url . protocol , ĠID N . to ASCII ( url . host ), Ġurl . port , Ġurl . file ) Ċĉĉĉĉĉ ĉ } Ġcatch ( e : ĠMal formed URLException ) Ġ{ Ċĉĉĉĉĉĉ ĉ task . log (" Invalid Ġurl ") Ċĉĉĉĉĉĉ ĉ return Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ val Ġpage Handler Ġ= Ġget Page Handler ( task . url ) Ċĉĉĉĉĉ ĉ page Handler . handle ( task , Ġtask . url ) Ċĉĉĉĉĉ ĉ try Ġ{ Ċĉĉĉĉĉĉ ĉ task . images . forEach Ġ{ Ċĉĉĉĉĉĉĉ ĉ download Image ( it ) Ċĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉĉ ĉ task . log (" Done ") Ċĉĉĉĉĉ ĉ } Ġcatch ( e : ĠException ) Ġ{ Ċĉĉĉĉĉĉ ĉ val Ġss Ġ= ĠString Writer () Ċĉĉĉĉĉĉ ĉ e . printStackTrace ( PrintWriter ( ss )) Ċĉĉĉĉĉĉ ĉ task . log (" Unknown Ġerror : Ġ" Ġ+ Ġss . toString ()) Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ return Ċĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ private Ġfun Ġdownload Image ( url String : ĠString ) Ġ{ ĊĊĉĉĉĉĉ ĉ val Ġurl : ĠURL Ċĉĉĉĉĉ ĉ try Ġ{ Ċĉĉĉĉĉĉ ĉ url Ġ= ĠURL ( task . url , Ġurl String ) Ċĉĉĉĉĉ ĉ } Ġcatch ( e : ĠMal formed URLException ) Ġ{ Ċĉĉĉĉĉĉ ĉ task . log (" Bad Ġurl Ġ" Ġ+ Ġurl String ) Ċĉĉĉĉĉĉ ĉ return Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ try Ġ{ Ċĉĉĉĉĉĉ ĉ val Ġconn Ġ= Ġurl . open Connection () Ċĉĉĉĉĉĉ ĉ Buffered InputStream ( conn . inputStream ). use Ġ{ Ġstream Ġ-> Ċĉĉĉĉĉĉĉ ĉ if Ġ( conn . contentType Ġ== Ġ" video / mp 4 ") Ġ{ Ċĉĉĉĉĉĉĉĉ ĉ Preserve Original Save Strategy (). save ( task , Ġconn , Ġstream ) Ċĉĉĉĉĉĉĉ ĉ } Ġelse Ġ{ Ċĉĉĉĉĉĉĉĉ ĉ stream . mark ( Int . MAX _ VALUE ) Ċĉĉĉĉĉĉĉĉ ĉ val Ġsize Ġ= ĠgetImage Size ( stream ) Ċĉĉĉĉĉĉĉĉ ĉ if Ġ( size Ġ== Ġnull ) Ġ{ Ċĉĉĉĉĉĉĉĉĉ ĉ task . log (" ĠĠĠĠĠĠĠ ĠError : Ġunable Ġto Ġdownload ") Ċĉĉĉĉĉĉĉĉĉ ĉ return Ċĉĉĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉĉĉĉ ĉ stream . reset () Ċĉĉĉĉĉĉĉĉ ĉ if Ġ( size . first Ġ< Ġ 3 0 0 Ġ|| Ġsize . second Ġ< Ġ 3 0 0 ) Ġ{ Ċĉĉĉĉĉĉĉĉĉ ĉ // ĠIgnore Ġreally Ġsmall Ġimages Ċĉĉĉĉĉĉĉĉĉ ĉ return Ċĉĉĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉĉĉĉ ĉ task . log (" Downloading Ġimage Ġ" Ġ+ Ġurl ) Ċĉĉĉĉĉĉĉĉ ĉ task . log (" ĠĠĠĠĠĠĠ ĠSize Ġ" Ġ+ Ġsize . first Ġ+ Ġ" x " Ġ+ Ġsize . second ) ĊĊĉĉĉĉĉĉĉĉ ĉ if Ġ(( size . first Ġ< Ġ 8 0 0 Ġ|| Ġsize . second Ġ< Ġ 8 0 0 ) Ċĉĉĉĉĉĉĉĉĉĉ ĉ && Ġ( size . first Ġ* Ġsize . second Ġ< Ġ 6 0 0 Ġ* Ġ 6 0 0 )) Ġ{ Ċĉĉĉĉĉĉĉĉĉ ĉ task . log (" ĠĠĠĠĠĠĠ ĠToo Ġsmall , Ġnot Ġsaving ") Ċĉĉĉĉĉĉĉĉĉ ĉ return Ċĉĉĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉĉĉĉ ĉ task . save Strategy . save ( task , Ġconn , Ġstream ) Ċĉĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ } Ġcatch ( e : ĠException ) Ġ{ Ċĉĉĉĉĉĉ ĉ task . log (" ĠĠĠĠĠĠĠ ĠError : Ġ" Ġ+ Ġe . toString ()) Ċĉĉĉĉĉĉ ĉ return Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ private Ġfun ĠgetImage Size ( stream : ĠInputStream ): ĠPair < Int , ĠInt >? Ġ{ Ċĉĉĉĉĉ ĉ Image IO . create Image InputStream ( stream ). use Ġ{ Ċĉĉĉĉĉĉ ĉ val Ġreaders Ġ= ĠImage IO . getImage Read ers ( it ) Ċĉĉĉĉĉĉ ĉ if Ġ( readers . hasNext ()) Ġ{ Ċĉĉĉĉĉĉĉ ĉ val Ġreader Ġ= Ġreaders . next () Ċĉĉĉĉĉĉĉ ĉ try Ġ{ Ċĉĉĉĉĉĉĉĉ ĉ reader . input Ġ= Ġit Ċĉĉĉĉĉĉĉĉ ĉ return Ġreader . getWidth ( 0 ) Ġto Ġreader . getHeight ( 0 ) Ċĉĉĉĉĉĉĉ ĉ } Ġfinally Ġ{ Ċĉĉĉĉĉĉĉĉ ĉ reader . dispose () Ċĉĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ } Ċĉĉĉĉĉ ĉ return Ġnull Ċĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ override Ġfun Ġprocess ( chunks : ĠMutable List < String >) Ġ{ Ċĉĉĉĉĉ ĉ val Ġvert Scroll Ġ= Ġlog Txt Area Sc rl Pn . vertical ScrollBar Ċĉĉĉĉĉ ĉ val Ġdo Scroll Ġ= Ġvert Scroll . value Ġ== Ġvert Scroll . maximum Ċĉĉĉĉĉ ĉ chunks . forEach Ġ{ Ġlog Txt Area . text Ġ+= Ġit Ġ+ Ġ"\ n " Ġ} Ċĉĉĉĉĉ ĉ if Ġ( do Scroll ) Ċĉĉĉĉĉĉ ĉ vert Scroll . value Ġ= Ġvert Scroll . maximum Ċĉĉĉĉ ĉ } ĊĊĉĉĉĉ ĉ override Ġfun Ġdone () Ġ{ Ċĉĉĉĉĉ ĉ super . done () Ċĉĉĉĉĉ ĉ scan Btn . isEnabled Ġ= Ġtrue Ċĉĉĉĉ ĉ } ĊĊĉĉĉ ĉ } Ċĉĉĉ ĉ scan Btn . isEnabled Ġ= Ġfalse Ċĉĉĉ ĉ worker . execute () Ċĉĉ ĉ } ĊĊĉ ĉ } Ċĉ ĉ scan Btn . text Ġ= Ġ" Scan " ĊĊĉ ĉ add ( url Lbl , ĠGridBagConstraints (). apply Ġ{ Ċĉĉ ĉ gridy Ġ= Ġ 0 Ċĉĉ ĉ fill Ġ= ĠGridBagConstraints . HORIZONTAL Ċĉĉ ĉ weight x Ġ= Ġ 0 . 0 Ċĉĉ ĉ weight y Ġ= Ġ 0 . 0 Ċĉ ĉ }) ĊĊĉ ĉ add ( JPanel (). apply Ġ{ Ċĉĉ ĉ border Ġ= ĠEmpty Border ( 5 , Ġ 2 , Ġ 2 , Ġ 5 ) Ċĉĉ ĉ layout Ġ= ĠBorderLayout () Ċĉĉ ĉ add ( url Txt , ĠBorderLayout . CENTER ) Ċĉ ĉ }, ĠGridBagConstraints (). apply Ġ{ Ċĉĉ ĉ gridy Ġ= Ġ 0 Ċĉĉ ĉ gridx Ġ= Ġ 1 Ċĉĉ ĉ grid width Ġ= Ġ 2 Ċĉĉ ĉ fill Ġ= ĠGridBagConstraints . HORIZONTAL Ċĉĉ ĉ weight x Ġ= Ġ 1 . 0 Ċĉĉ ĉ weight y Ġ= Ġ 0 . 0 Ċĉ ĉ }) Ċĉ ĉ add ( dest Lbl , ĠGridBagConstraints (). apply Ġ{ Ċĉĉ ĉ gridy Ġ= Ġ 1 Ċĉĉ ĉ fill Ġ= ĠGridBagConstraints . HORIZONTAL Ċĉĉ ĉ weight x Ġ= Ġ 0 . 0 Ċĉĉ ĉ weight y Ġ= Ġ 0 . 0 Ċĉ ĉ }) ĊĊĉ ĉ add ( JPanel (). apply Ġ{ Ċĉĉ ĉ layout Ġ= ĠGrid BagLayout () Ċĉĉ ĉ border Ġ= ĠEmpty Border ( 2 , Ġ 2 , Ġ 2 , Ġ 5 ) Ċĉĉ ĉ add ( dest Txt , ĠGridBagConstraints (). apply Ġ{ Ċĉĉĉ ĉ weight x Ġ= Ġ 1 . 0 Ċĉĉĉ ĉ fill Ġ= ĠGridBagConstraints . HORIZONTAL Ċĉĉ ĉ }) Ċĉĉ ĉ add ( dest Btn , ĠGridBagConstraints (). apply Ġ{ Ċĉĉĉ ĉ weight x Ġ= Ġ 0 . 0 Ċĉĉ ĉ }) Ċĉ ĉ }, ĠGridBagConstraints (). apply Ġ{ Ċĉĉ ĉ gridy Ġ= Ġ 1 Ċĉĉ ĉ gridx Ġ= Ġ 1 Ċĉĉ ĉ grid width Ġ= Ġ 2 Ċĉĉ ĉ fill Ġ= ĠGridBagConstraints . HORIZONTAL Ċĉĉ ĉ weight x Ġ= Ġ 1 . 0 Ċĉĉ ĉ weight y Ġ= Ġ 0 . 0 Ċĉ ĉ }) Ċĉ ĉ add ( JPanel (). apply Ġ{ Ċĉĉ ĉ layout Ġ= ĠFlow Layout ( Flow Layout . LEFT , Ġ 0 , Ġ 0 ) Ċĉĉ ĉ add ( format Lbl ) Ċĉĉ ĉ add ( format Cb ) Ċĉĉ ĉ add ( fileName Lbl ) Ċĉĉ ĉ add ( fileName Cb ) Ċĉ ĉ }, ĠGridBagConstraints (). apply Ġ{ Ċĉĉ ĉ gridy Ġ= Ġ 2 Ċĉĉ ĉ grid width Ġ= Ġ 2 Ċĉĉ ĉ fill Ġ= ĠGridBagConstraints . HORIZONTAL Ċĉĉ ĉ weight x Ġ= Ġ 0 . 0 Ċĉĉ ĉ weight y Ġ= Ġ 0 . 0 Ċĉ ĉ }) ĊĊĉ ĉ add ( JPanel (), ĠGridBagConstraints (). apply Ġ{ Ċĉĉ ĉ gridy Ġ= Ġ 3 Ċĉĉ ĉ gridx Ġ= Ġ 1 Ċĉĉ ĉ fill Ġ= ĠGridBagConstraints . HORIZONTAL Ċĉĉ ĉ weight x Ġ= Ġ 1 . 0 Ċĉ ĉ }) ĊĊĉ ĉ add ( JPanel (). apply Ġ{ Ċĉĉ ĉ add ( scan Btn ) Ċĉ ĉ }, ĠGridBagConstraints (). apply Ġ{ Ċĉĉ ĉ gridy Ġ= Ġ 3 Ċĉĉ ĉ gridx Ġ= Ġ 2 Ċĉĉ ĉ fill Ġ= ĠGridBagConstraints . NONE Ċĉĉ ĉ weight x Ġ= Ġ 0 . 0 Ċĉĉ ĉ weight y Ġ= Ġ 0 . 0 Ċĉ ĉ }) ĊĊĉ ĉ add ( JPanel (). apply Ġ{ Ċĉĉ ĉ layout Ġ= ĠBorderLayout () Ċĉĉ ĉ border Ġ= ĠEmpty Border ( 0 , Ġ 5 , Ġ 5 , Ġ 5 ) Ċĉĉ ĉ add ( log Txt Area Sc rl Pn , ĠBorderLayout . CENTER ) Ċĉ ĉ }, ĠGridBagConstraints (). apply Ġ{ Ċĉĉ ĉ gridy Ġ= Ġ 4 Ċĉĉ ĉ gridx Ġ= Ġ 0 Ċĉĉ ĉ grid width Ġ= Ġ 3 Ċĉĉ ĉ fill Ġ= ĠGridBagConstraints . BOTH Ċĉĉ ĉ weight x Ġ= Ġ 1 . 0 Ċĉĉ ĉ weight y Ġ= Ġ 1 . 0 Ċĉ ĉ }) Ċ ĉ } Ċ } ĊĊ