package Ġdev . ael lo . tb at w itter updates . web hooks Ċ Ċ import Ġcom . fasterxml . jackson . databind . Deserialization Feature Ċ import Ġcom . fasterxml . jackson . databind . Property Naming Strategy Ċ import Ġcom . fasterxml . jackson . module . kotlin . register Kotlin Module Ċ import Ġdev . ael lo . tb at w itter updates . components . Config Ċ import Ġdev . ael lo . tb at w itter updates . mapping . Match Score Response Ċ import Ġdev . ael lo . tb at w itter updates . mapping . Ping Response Ċ import Ġdev . ael lo . tb at w itter updates . mapping . Response Ċ import Ġdev . ael lo . tb at w itter updates . mapping . Verification Response Ċ import Ġdev . ael lo . twitter . Twitter Ċ import Ġdev . ael lo . twitter . utils . Twitter Credentials Ċ import Ġio . ktor . application . call Ċ import Ġio . ktor . application . install Ċ import Ġio . ktor . features . BadRequest Exception Ċ import Ġio . ktor . features . Content Neg otiation Ċ import Ġio . ktor . features . Status Pages Ċ import Ġio . ktor . http . HttpStatusCode Ċ import Ġio . ktor . jackson . jackson Ċ import Ġio . ktor . request . Application Receive Pipeline Ċ import Ġio . ktor . request . Application Receive Request Ċ import Ġio . ktor . request . header Ċ import Ġio . ktor . request . receive Ċ import Ġio . ktor . response . respond Ċ import Ġio . ktor . routing .* Ċ import Ġio . ktor . server . engine . embedded Server Ċ import Ġio . ktor . server . netty . Net ty Ċ import Ġio . ktor . util . K tor Experimental API Ċ import Ġio . ktor . util . toByteArray Ċ import Ġio . ktor . utils . io . Byte Read Channel Ċ import Ġmu . Kotlin Logging Ċ import Ġorg . apache . commons . codec . digest . Digest Utils Ċ Ċ class ĠT BA Webhook ( port : ĠInt , Ġprivate Ġval Ġteam : ĠString , Ġprivate Ġval Ġconfig : ĠConfig ) Ġ{ ĊĠĠĠ Ġprivate Ġval Ġlogger Ġ= ĠKotlin Logging . logger ( this :: class . java . simple Name ) ĊĊĠĠĠ Ġ@ K tor Experimental API ĊĠĠĠ Ġ@ Experimental Std lib Api ĊĠĠĠ Ġprivate Ġval Ġserver Ġ= Ġembedded Server ( Net ty , Ġport Ġ= Ġport ) Ġ{ ĊĠĠĠĠĠĠĠ Ġrouting Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġinstall ( Status Pages ) Ġ{ Ġexception < Exception > Ġ{} Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreceive Pipeline . intercept ( Application Receive Pipeline . Transform ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Received Ġrequest !" Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvalue Ġ= Ġit . value ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( value Ġ! is ĠByte Read Channel ) Ġreturn @ intercept ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( it . type Ġ== ĠByte Read Channel :: class ) Ġreturn @ intercept ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbytes Ġ= Ġvalue . toByteArray () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbody Ġ= Ġbytes . decode ToString () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġchecksum Header Ġ= Ġcall . request . header (" X - T BA - Checksum ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( checksum Header Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall . respond ( HttpStatusCode . BadRequest ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . error Ġ{ Ġ" No Ġchecksum Ġheader !" Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠBadRequest Exception (" No Ġchecksum Ġheader !") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( config [" secret "] Ġ!= Ġ"" Ġ&& Ġ! verify Integr ity ( checksum Header . toString (), Ġbody )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall . respond ( HttpStatusCode . BadRequest ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlogger . error Ġ{ Ġ" Request Ġintegrity Ġcould Ġnot Ġbe Ġverified !" Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠBadRequest Exception (" Request Ġintegrity Ġcannot Ġbe Ġverified !") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġproceed With ( Application Receive Request ( it . type Info , ĠByte Read Channel ( bytes ))) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġinstall ( Content Neg otiation ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġj ack son Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġproperty Naming Strategy Ġ= ĠProperty Naming Strategy . S NA KE _ CASE ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconfigure ( Deserialization Feature . FAIL _ ON _ UNKNOWN _ PROPERTIES , Ġfalse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġregister Kotlin Module () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġpost ("/") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠstatusCode Ġ= Ġwhen Ġ( val Ġresponse Ġ= Ġcall . receive < Response >()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠPing Response Ġ-> Ġhandle Ping Request ( response ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠMatch Score Response Ġ-> Ġhandle Match Score Request ( response ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠVerification Response Ġ-> Ġhandle Verification Request ( response ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĠHttpStatusCode . BadRequest ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcall . respond ( statusCode ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ K tor Experimental API ĊĠĠĠ Ġ@ Experimental Std lib Api ĊĠĠĠ Ġfun Ġstart () Ġ{ ĊĠĠĠĠĠĠĠ Ġserver . start ( wait Ġ= Ġtrue ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġverify Integr ity ( checksum Header : ĠString , Ġrequest Body : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġchecksum Ġ= ĠDigest Utils . sha 1 Hex ( config [" secret "] Ġ+ Ġrequest Body ). toLowerCase () ĊĠĠĠĠĠĠĠ Ġreturn Ġchecksum Ġ== Ġchecksum Header ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġhandle Ping Request ( response : ĠPing Response ): ĠHttpStatusCode Ġ{ ĊĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Ping Ġreceived ! ĠMessage : Ġ" Ġ+ Ġresponse . message Data . desc Ġ} ĊĠĠĠĠĠĠĠ Ġreturn ĠHttpStatusCode . OK ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġhandle Verification Request ( response : ĠVerification Response ): ĠHttpStatusCode Ġ{ ĊĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Verification Ġkey : Ġ" Ġ+ Ġresponse . message Data . verification Key Ġ} ĊĠĠĠĠĠĠĠ Ġreturn ĠHttpStatusCode . OK ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġval Ġcomp Level Map Ġ= Ġmap Of (" qm " Ġto Ġ" Qual s ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" ef " Ġto Ġ" E ighth s ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" qf " Ġto Ġ" Qu ar ters ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" sf " Ġto Ġ" Sem is ", ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" f " Ġto Ġ" Final s ") ĊĊĠĠĠ Ġprivate Ġfun Ġhandle Match Score Request ( response : ĠMatch Score Response ): ĠHttpStatusCode Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmatch Ġ= Ġresponse . message Data . match ĊĠĠĠĠĠĠĠ Ġval Ġteam Al liance Ġ= Ġif Ġ( team Ġin Ġmatch . al li ances . blue . teams ) Ġ" blue " Ġelse Ġ" red " ĊĠĠĠĠĠĠĠ Ġval Ġopp osing Al liance Score : ĠInt ĊĠĠĠĠĠĠĠ Ġval Ġal liance Members : ĠList < String > ĊĠĠĠĠĠĠĠ Ġval Ġscore : ĠInt ĊĊĠĠĠĠĠĠĠ Ġif Ġ( team Al liance Ġ== Ġ" blue ") Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġopp osing Al liance Score Ġ= Ġmatch . al li ances . red . score ĊĠĠĠĠĠĠĠĠĠĠĠ Ġscore Ġ= Ġmatch . al li ances . blue . score ĊĠĠĠĠĠĠĠĠĠĠĠ Ġal liance Members Ġ= Ġmatch . al li ances . blue . teams ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġopp osing Al liance Score Ġ= Ġmatch . al li ances . blue . score ĊĠĠĠĠĠĠĠĠĠĠĠ Ġscore Ġ= Ġmatch . al li ances . red . score ĊĠĠĠĠĠĠĠĠĠĠĠ Ġal liance Members Ġ= Ġmatch . al li ances . red . teams ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġresult Ġ= Ġif Ġ( score Ġ> Ġopp osing Al liance Score ) Ġ" Win " Ġelse Ġ" Loss " ĊĠĠĠĠĠĠĠ Ġval Ġcomp Level Ġ= Ġcomp Level Map [ match . comp Level ] ĊĊĠĠĠĠĠĠĠ Ġval Ġtweet Ġ= Ġ"- Ġ$ comp Level Ġ# ${ match . match Number } Ġ- \ n " Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Result : Ġ$ result \ n " Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Score : Ġ$ score Ġ- Ġ$ op posing Al liance Score \ n \ n " Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Team Ġ${ config [" team "]. replace (" f rc ", Ġ"") } Ġplayed Ġon Ġthe Ġ$ team Al liance Ġal liance Ġw / Ġteams Ġ${ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġal liance Members . filter Ġ{ Ġit Ġ!= Ġconfig [" team "] Ġ}. join ToString (" Ġand Ġ") Ġ{ Ġit . replace (" f rc ", Ġ"") Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ." ĊĊĠĠĠĠĠĠĠ Ġval Ġcredentials Ġ= ĠTwitter Credentials ( config [" accessToken "], ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconfig [" accessToken Secret "], ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconfig [" consumer ApiKey "], ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġconfig [" consumer ApiKey Secret "]) ĊĊĠĠĠĠĠĠĠ ĠTwitter ( credentials ). update Status ( tweet ) ĊĠĠĠĠĠĠĠ Ġlogger . info Ġ{ Ġ" Received Ġmatch Ġscore Ġrequest ! ĠTweet Ġsent ." Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn ĠHttpStatusCode . OK ĊĠĠĠ Ġ} Ċ }