package Ġjp . ne phy . tweet storm Ċ Ċ import Ġjp . ne phy . json kt . Json Model Ċ import Ġjp . ne phy . json kt . set Ċ import Ġjp . ne phy . json kt . string Ċ import Ġjp . ne phy . pen ic ill in . Pen ic ill in Client Ċ import Ġjp . ne phy . pen ic ill in . model . Status Ċ import Ġjp . ne phy . pen ic ill in . request . List Action Ċ import Ġjp . ne phy . tweet storm . session . Authenticated Stream Ċ import Ġmu . Kotlin Logging Ċ import Ġjava . time . Duration Ċ import Ġjava . time . Instant Ċ import Ġjava . util . concurrent . Copy On Write ArrayList Ċ import Ġjava . util . concurrent . Executors Ċ import Ġjava . util . concurrent . TimeUnit Ċ Ċ class ĠFetch er Ġ{ ĊĠĠĠ Ġprivate Ġval Ġlogger Ġ= ĠKotlin Logging . logger (" Tweet storm . Fetcher ") ĊĠĠĠ Ġprivate Ġval Ġexecutor Ġ= ĠExec utors . new Cached ThreadPool () ĊĠĠĠ Ġprivate Ġval Ġtasks Ġ= ĠCopy On Write ArrayList < Fetcher . Task >() ĊĊĠĠĠ Ġfun Ġstart IfNot Running ( stream : ĠAuth enticated Stream ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġtask Ġ= Ġtasks . find Ġ{ Ġit . account Ġ== Ġstream . account Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ( task Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtasks . add ( Task ( stream . account , Ġstream )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġtask . bind ( stream ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinner Ġclass ĠTask ( val Ġaccount : ĠConfig . Account , Ġinitial Stream : ĠAuth enticated Stream ) Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġclient Ġ= ĠPen ic ill in Client . build Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġapplication ( account . ck , Ġaccount . cs ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtoken ( account . at , Ġaccount . ats ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġstreams Ġ= ĠCopy On Write ArrayList < Authenticated Stream >(). also Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . add ( initial Stream ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġfun Ġbind ( stream : ĠAuth enticated Stream ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( stream Ġ! in Ġstreams ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstreams . add ( stream ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexecutor . execute Ġ{ Ġfriends ( stream ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" A ĠStream Ġhas Ġbeen Ġbind Ġto Ġ@ ${ account . sn } ." Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġsend All ( model : ĠJson Model ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstreams . forEach Ġ{ Ġit . send ( model ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexecutor . execute Ġ{ Ġif Ġ( account . list Id Ġ!= Ġnull ) Ġlist Timeline () Ġelse Ġhome Timeline () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexecutor . execute Ġ{ Ġdirect Message () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexecutor . execute Ġ{ Ġactivity () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexecutor . execute Ġ{ Ġstreams . forEach Ġ{ Ġfriends ( it ) Ġ} Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexecutor . execute Ġ{ Ġdelete () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Fetch Task : Ġ@ ${ account . sn } Ġhas Ġstarted ." Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġlist Timeline () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtimeline ( 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclient . list . timeline ( list Id Ġ= Ġaccount . list Id , Ġcount Ġ= Ġ 2 0 0 , Ġsince Id Ġ= Ġit , Ġinclude RT s Ġ= Ġtrue , Ġinclude Entities Ġ= Ġtrue , Ġoptions Ġ= Ġ* array Of (" tweet _ mode " Ġto Ġ" extended ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġhome Timeline () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtimeline ( 6 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġclient . timeline . home ( count Ġ= Ġ 2 0 0 , Ġsince Id Ġ= Ġit , Ġinclude Entities Ġ= Ġtrue , Ġoptions Ġ= Ġ* array Of (" tweet _ mode " Ġto Ġ" extended ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġtimeline ( sleep Sec : ĠInt , Ġsource : Ġ( last Id : ĠLong ?) Ġ-> ĠList Action < Status >) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġlast Id : ĠLong ? Ġ= Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( streams . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtry Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtimeline Ġ= Ġsource ( last Id ). complete () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( timeline . result . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠFor Ġcompatibility ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtimeline . result . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . json [" text "] Ġ= Ġit . json [" full _ text "]. string ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( last Id Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtimeline . result . reversed (). forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( account . mark Via ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . json [" source "] Ġ= Ġit . source . value . replace ("</ a >", Ġ" Ġ[ Tweet storm ]</ a >") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsend All ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlast Id Ġ= Ġtimeline . result . first (). id ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( timeline . rate Limit . has Limit ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . debug Ġ{ Ġ"[ Timeline ] ĠRate Ġlimit : Ġ${ timeline . rate Limit . remaining }/${ timeline . rate Limit . limit } Ġ(${ timeline . rate Limit . reset At })" Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġduration Ġ= ĠDuration . between ( Instant . now (), Ġtimeline . rate Limit . reset At !!. to Instant ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( timeline . rate Limit . remaining !! Ġ* Ġsleep Sec Ġ* Ġ 1 . 0 Ġ/ Ġduration . seconds Ġ< Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . warn Ġ{ Ġ"[ Timeline ] ĠRate Ġlimit : ĠAPI Ġcalls Ġseem Ġto Ġbe Ġfrequent Ġthan Ġexpected . ĠSleep Ġ 5 Ġsecs ." Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTimeUnit . SECONDS . sleep ( 5 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġcatch Ġ( e : ĠException ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . error ( e ) Ġ{ Ġ"[ Timeline ] ĠAn Ġerror Ġoccurred Ġwhile Ġgetting Ġtimeline Ġfor Ġ@ ${ account . sn } ." Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġfinally Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠTimeUnit . SECONDS . sleep ( sleep Sec . to Long ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġdirect Message () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġactivity () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġfriends ( target : ĠAuth enticated Stream ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfriends Ġ= Ġclient . friend . list Ids (). complete (). until Last (). flatMap Ġ{ Ġit . result . ids Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( target . stringify Friend Ids ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtarget . send (" friends _ str " Ġto Ġfriends . map Ġ{ Ġ"$ it " Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtarget . send (" friends " Ġto Ġfriends ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġdelete () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠTODO ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ