package Ġcom . tim cast el ij ns . chat exchange . chat Ċ Ċ import Ġcom . google . gson . JsonArray Ċ import Ġcom . google . gson . JsonObject Ċ import Ġjava . time . Instant Ċ import Ġjava . util . regex . Pattern Ċ Ċ internal Ġfun ĠJsonObject . extract Users (): ĠList < User > Ġ= ĊĠĠĠĠĠĠĠ Ġget (" users ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. as JsonArray ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . as JsonObject Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwith ( it ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġid Ġ= Ġget (" id "). as Long ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠuserName Ġ= Ġget (" name "). asString ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġre putation Ġ= Ġget (" re putation "). as Int ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġis Mod erator Ġ= Ġif Ġ( get (" is _ mod erator "). is Json Null ) Ġfalse Ġelse Ġget (" is _ mod erator "). as Boolean ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġis Room Owner Ġ= Ġif Ġ( get (" is _ owner "). is Json Null ) Ġfalse Ġelse Ġget (" is _ owner "). as Boolean ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlast Seen Ġ= Ġif Ġ( get (" last _ seen "). is Json Null ) Ġnull Ġelse ĠInstant . of Epoch Second ( get (" last _ seen "). as Long ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlast Post Ġ= Ġif Ġ( get (" last _ post "). is Json Null ) Ġnull Ġelse ĠInstant . of Epoch Second ( get (" last _ post "). as Long ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠUser ( id , ĠuserName , Ġre putation , Ġis Mod erator , Ġis Room Owner , Ġlast Seen , Ġlast Post ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ċ Ċ internal Ġfun ĠJsonObject . extract Events For Room ( room : ĠRoom ): ĠList < Event > Ġ= ĊĠĠĠĠĠĠĠ Ġentry Set () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . key Ġ== Ġ" r ${ room . roomId }" Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . value Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . as JsonObject Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map NotNull Ġ{ Ġit . get (" e ") Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . as JsonArray Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. first OrNull () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . to Events ( room ) Ġ?: Ġempty List () Ċ Ċ private Ġfun ĠJson Array . to Events ( room : ĠRoom ): ĠList < Event > Ġ{ ĊĠĠĠ Ġ// ĠK ick ed ? ĊĠĠĠ Ġif Ġ( size () Ġ== Ġ 2 Ġ&& Ġhas EventType ( 4 ) Ġ&& Ġhas EventType ( 1 5 )) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠlistOf ( Kick ed Event ( this , Ġroom )) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠTODO : Ġhandle Ġfeeds Ġ( userId Ġ= Ġ- 2 ) ĊĠĠĠ Ġ// ĠTODO : Ġhandle Ġunhandled Ġevents ĊĠĠĠ Ġreturn Ġmap Ġ{ Ġit . as JsonObject Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ(! it . has (" user _ id ") Ġ|| Ġit . get (" user _ id "). as Long Ġ> Ġ 0 ) Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . get (" room _ id "). as Int Ġ== Ġroom . roomId ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map NotNull Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( Stack Exchange EventType . from Code ( it . get (" event _ type "). as Int )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStack Exchange EventType . MESSAGE _ POST ED Ġ-> ĠMessage Posted Event ( it , Ġroom ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStack Exchange EventType . MESSAGE _ EDIT ED Ġ-> ĠMessage Edited Event ( it , Ġroom ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStack Exchange EventType . MESSAGE _ STAR RED Ġ-> ĠMessage Star red Event ( it , Ġroom ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStack Exchange EventType . MESSAGE _ DELETED Ġ-> ĠMessage Deleted Event ( it , Ġroom ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStack Exchange EventType . USER _ ENTER ED Ġ-> ĠUser Entered Event ( it , Ġroom ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStack Exchange EventType . USER _ LEFT Ġ-> ĠUser Left Event ( it , Ġroom ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStack Exchange EventType . USER _ MENT ION ED Ġ-> ĠUser Mention ed Event ( it , Ġroom ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStack Exchange EventType . ACCESS _ LEVEL _ CHANGED Ġ-> ĠAccess Level Changed Event ( it , Ġroom ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStack Exchange EventType . USER _ NOTIFICATION Ġ-> ĠUser Notification Event ( it , Ġroom ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠStack Exchange EventType . MESSAGE _ REPLY Ġ-> ĠMessage Rep lied To Event ( it , Ġroom ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprintln (" Unhandled Ġevent : Ġ$ it ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. toList () Ċ } Ċ Ċ private Ġfun ĠJson Array . has EventType ( eventType : ĠInt ) Ġ= ĊĠĠĠĠĠĠĠ Ġmap Ġ{ Ġit . as JsonObject Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. any Ġ{ Ġit . get (" event _ type "). as Int Ġ== ĠeventType Ġ} ĊĊĊ Ċ private Ġconst Ġval ĠMAX _ CHAT _ MESSAGE _ LENGTH Ġ= Ġ 5 0 0 Ċ private Ġval ĠMARK DOWN _ LINK _ PATTERN Ġ= ĠPattern . compile ("\\ [( \\\\ ] |[ ^ \\ ]]) + \\ ]\\ (( https ?: )? // ( \\\\ \\ )| \\\\ \\ ( |[ ^ \\ s )( ])+ \\ )") Ċ Ċ internal Ġfun ĠString . to Parts ( max Part Length : ĠInt Ġ= ĠMAX _ CHAT _ MESSAGE _ LENGTH ): ĠList < String > Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġmessage Ġ= Ġthis ĊĠĠĠĠĠĠĠ Ġif Ġ( message . length Ġ<= Ġmax Part Length Ġ|| Ġ( message . trim (). contains ("\ n ") Ġ&& Ġ! message . trim (). endsWith ("\ n "))) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠlistOf ( message ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġmessages Ġ= Ġmutable ListOf < String >() ĊĠĠĠĠĠĠĠ Ġwhile Ġ( message . length Ġ> Ġmax Part Length ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnon Break ing Indices Ġ= Ġmessage . identify Non Break ing Indexes () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġbreak Index Ġ= Ġmessage . lastIndexOf (' Ġ', Ġmax Part Length ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( break Index Ġ< Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak Index Ġ= Ġmax Part Length ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġnon Break ing Indices . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it [ 0 ] Ġ< Ġbreak Index Ġ&& Ġbreak Index Ġ< Ġit [ 1 ]) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbreak Index Ġ= Ġit [ 0 ] Ġ- Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn @ forEach ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( break Index Ġ< Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġwe Ġdid Ġour Ġbest , Ġbut Ġthis Ġpart Ġstarts Ġwith Ġa Ġnon Ġbreaking Ġindex , Ġand Ġends Ġfurther Ġthan Ġwhat Ġis Ġallowed ... ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠChat OperationException (" Cannot Ġsend Ġmessage : Ġit Ġis Ġlonger Ġthan Ġ$ max Part Length Ġcharacters Ġand Ġcannot Ġbe Ġbroken Ġinto Ġa de qu ate Ġparts ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġmessages . add ( message . substring ( 0 , Ġbreak Index )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmessage Ġ= Ġmessage . substring ( break Index Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġif Ġ(! message . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmessages . add ( message ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn Ġmessages Ċ } Ċ Ċ private Ġfun ĠString . identify Non Break ing Indexes (): ĠList < IntArray > Ġ{ ĊĠĠĠ Ġval Ġnon Break ing Parts Ġ= Ġmutable ListOf < IntArray >() ĊĠĠĠ Ġval Ġmatcher Ġ= ĠMARK DOWN _ LINK _ PATTERN . matcher ( this ) ĊĊĠĠĠ Ġwhile Ġ( matcher . find ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġnon Break ing Parts . add ( int ArrayOf ( matcher . start (), Ġmatcher . end ())) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġnon Break ing Parts Ċ } Ċ