@ file : Opt In ( K tor Experimental Locations API :: class ) Ċ Ċ package Ġio . skin ny d oo . articles Ċ Ċ import Ġarrow . core . Either Ċ import Ġarrow . core . getOrElse Ċ import Ġio . ktor . application . Application Ċ import Ġio . ktor . application . call Ċ import Ġio . ktor . auth . authenticate Ċ import Ġio . ktor . auth . principal Ċ import Ġio . ktor . http . HttpStatusCode Ċ import Ġio . ktor . locations .* Ċ import Ġio . ktor . request . receive Ċ import Ġio . ktor . response . respond Ċ import Ġio . ktor . routing . Route Ċ import Ġio . ktor . routing . route Ċ import Ġio . ktor . routing . routing Ċ import Ġio . skin ny d oo . API _ V 1 Ċ import Ġio . skin ny d oo . articles . tags . Tag Ċ import Ġio . skin ny d oo . common .* Ċ import Ġio . skin ny d oo . users . User Ċ import Ġorg . k oin . core . qual ifier . named Ċ import Ġorg . k oin . ktor . ext . inject Ċ import Ġjava . util .* Ċ Ċ const Ġval ĠA RT IC LES Ġ= Ġ"/ articles " Ċ Ċ @ Location ( ARTIC LES ) Ċ data Ġclass ĠArticles Route ( ĊĠ Ġval Ġtag : ĠString Ġ= Ġ"", ĊĠ Ġval Ġauthor : ĠString Ġ= Ġ"", ĊĠ Ġval Ġfavor ited : ĠString Ġ= Ġ"", ĊĠ Ġval Ġlimit : ĠInt Ġ= Ġ 2 0 , ĊĠ Ġval Ġoffset : ĠInt Ġ= Ġ 0 , Ċ ) Ċ Ċ @ Location ("$ ARTIC LES / feed ") Ċ data Ġclass ĠArticle Feed Route ( val Ġlimit : ĠInt Ġ= Ġ 2 0 , Ġval Ġoffset : ĠInt Ġ= Ġ 0 ) Ċ Ċ @ Location ("$ ARTIC LES /{ slug }") Ċ data Ġclass ĠArticle Route ( val Ġslug : ĠString ) Ġ{ ĊĊĠ Ġ@ Location ("/ comments ") ĊĠ Ġdata Ġclass ĠComments ( val Ġparent : ĠArticle Route ) Ġ{ ĊĊĠĠĠ Ġ@ Location ("/ { id }") ĊĠĠĠ Ġdata Ġclass ĠComment ( val Ġparent : ĠComments , Ġval Ġid : ĠInt ) ĊĠ Ġ} ĊĊĠ Ġ@ Location ("/ favorite ") ĊĠ Ġdata Ġclass ĠF avorite ( val Ġparent : ĠArticle Route ) Ċ } Ċ Ċ /** Ċ Ġ* ĠGet Ġmost Ġrecent Ġarticles Ġglobally . ĠAuth Ġis Ġoptional . Ċ Ġ*/ Ċ fun ĠRoute . all Articles () Ġ{ ĊĠ Ġval ĠgetAll Articles Ġby Ġinject < GetAll Articles UseCase >( named (" all Articles ")) ĊĊĠ Ġauthenticate (" auth - jwt ", Ġoptional Ġ= Ġtrue ) Ġ{ ĊĠĠĠ Ġget < Articles Route > Ġ{ Ġparams Ġ-> ĊĠĠĠĠĠ Ġval Ġself Id Ġ= Ġcall . principal < User >() ?. id ĊĊĠĠĠĠĠ Ġval Ġtag Ġ= Ġparams . tag . if Empty Ġ{ Ġnull Ġ} ?. let (:: Tag ) ĊĠĠĠĠĠ Ġval Ġfavor ited By Ġ= Ġparams . f avor ited . if Empty Ġ{ Ġnull Ġ} ?. let (:: Username ) ĊĠĠĠĠĠ Ġval Ġusername Ġ= Ġparams . author . if Empty Ġ{ Ġnull Ġ} ?. let (:: Username ) ĊĠĠĠĠĠ Ġval Ġlimit Ġ= ĠLimit . from Int ( params . limit ). getOrElse Ġ{ ĠLimit . default Ġ} ĊĠĠĠĠĠ Ġval Ġoffset Ġ= ĠOffset . from Int ( params . offset ). getOrElse Ġ{ ĠOffset . default Ġ} ĊĊĠĠĠĠĠ ĠgetAll Articles ( self Id , Ġtag , Ġusername , Ġfavor ited By , Ġlimit , Ġoffset ) ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ ĠArticle ListResponse ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}, Ġ{ Ġcall . respond ( it ) Ġ}) ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠGet Ġmost Ġrecent Ġarticles Ġfrom Ġusers Ġyou Ġfollow . ĠAuth Ġis Ġrequired Ċ Ġ*/ Ċ fun ĠRoute . article Feed () Ġ{ ĊĠ Ġval Ġfeed Articles Ġby Ġinject < Get Feed Articles UseCase >( named (" feed ")) ĊĊĠ Ġauthenticate (" auth - jwt ") Ġ{ ĊĠĠĠ Ġget < Article Feed Route > Ġ{ Ġparams Ġ-> ĊĠĠĠĠĠ Ġval Ġself Ġ= Ġcall . principal < User >() ĊĠĠĠĠĠĠĠ Ġ?: Ġreturn @ get Ġcall . respond ( HttpStatusCode . Unauthorized , ĠError Envelope ( map Of (" body " Ġto ĠlistOf (" Unauthorized ")) )) ĊĊĠĠĠĠĠ Ġval Ġlimit Ġ= ĠLimit . from Int ( params . limit ). getOrElse Ġ{ ĠLimit . default Ġ} ĊĠĠĠĠĠ Ġval Ġoffset Ġ= ĠOffset . from Int ( params . offset ). getOrElse Ġ{ ĠOffset . default Ġ} ĊĠĠĠĠĠ Ġfeed Articles ( self . id , Ġlimit , Ġoffset ) ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ ĠArticle ListResponse ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}, Ġ{ Ġcall . respond ( it ) Ġ}) ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠCreate Ġan Ġarticle . ĠAuth Ġis Ġrequired Ċ Ġ*/ Ċ fun ĠRoute . create Article () Ġ{ ĊĠ Ġval Ġadd Article Ġby Ġinject < Add Article UseCase >( named (" add Article ")) ĊĊĠ Ġauthenticate (" auth - jwt ") Ġ{ ĊĠĠĠ Ġpost < Articles Route > Ġ{ ĊĠĠĠĠĠ Ġval Ġbody Ġ= Ġcall . receive < Create Article Request >(). article ĊĊĠĠĠĠĠ Ġval Ġself Ġ= Ġcall . principal < User >() ĊĠĠĠĠĠĠĠ Ġ?: Ġreturn @ post Ġcall . respond ( ĊĠĠĠĠĠĠĠĠĠ ĠHttpStatusCode . Unauthorized , ĊĠĠĠĠĠĠĠĠĠ ĠError Envelope ( map Of (" body " Ġto ĠlistOf (" Unauthorized "))) ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠ Ġadd Article ( body , Ġself . id ) ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ ĠArticle Response ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}) Ġ{ Ġcall . respond ( HttpStatusCode . Created , Ġit ) Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠGet Ġan Ġarticle . ĠAuth Ġis Ġoptional Ċ Ġ*/ Ċ fun ĠRoute . get Article With Slug () Ġ{ ĊĠ Ġval Ġget Article With Slug Ġby Ġinject < Get Article With Slug UseCase >( named (" get Article ")) ĊĊĠ Ġauthenticate (" auth - jwt ", Ġoptional Ġ= Ġtrue ) Ġ{ ĊĠĠĠ Ġget < Article Route > Ġ{ Ġparams Ġ-> ĊĠĠĠĠĠ Ġval ĠuserId Ġ= Ġcall . principal < User >() ?. id ĊĊĠĠĠĠĠ ĠEither . catch Ġ{ ĠUUID . fromString ( params . slug ) Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Left Ġ{ ĠInvalid Slug ( it . localized Message ) Ġ} ĊĠĠĠĠĠĠĠ Ġ. map (:: Slug ) ĊĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}) Ġ{ Ġs Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġget Article With Slug ( s , ĠuserId ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ ĠArticle Response ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}) Ġ{ Ġcall . respond ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠUpdate Ġan Ġarticle . ĠAuth Ġis Ġrequired Ċ Ġ*/ Ċ fun ĠRoute . update Article () Ġ{ ĊĠ Ġval Ġupdate Article Ġby Ġinject < Update Article UseCase >( named (" update Article ")) ĊĊĠ Ġauthenticate (" auth - jwt ") Ġ{ ĊĠĠĠ Ġput < Article Route > Ġ{ Ġparams Ġ-> ĊĠĠĠĠĠ Ġval Ġself Ġ= Ġcall . principal < User >() ĊĠĠĠĠĠĠĠ Ġ?: Ġreturn @ put Ġcall . respond ( HttpStatusCode . Unauthorized , ĠError Envelope ( map Of (" body " Ġto ĠlistOf (" Unauthorized ")) )) ĊĊĠĠĠĠĠ Ġval Ġbody Ġ= Ġcall . receive < Update Article Request >(). article ĊĊĠĠĠĠĠ ĠSl ug . fromString ( params . slug ) ĊĠĠĠĠĠĠĠ Ġ. to Either Ġ{ ĠInvalid Slug () Ġ} ĊĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}) Ġ{ Ġslug Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġupdate Article ( slug , Ġbody , Ġself . id ). map Ġ{ ĠArticle Response ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}, Ġ{ Ġcall . respond ( it ) Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠDelete Ġan Ġarticle . ĠAuth Ġis Ġrequired Ċ Ġ*/ Ċ fun ĠRoute . delete Article () Ġ{ ĊĠ Ġval Ġdelete Article With Slug Ġby Ġinject < Delete Article UseCase >( named (" delete Article ")) ĊĊĠ Ġauthenticate (" auth - jwt ") Ġ{ ĊĠĠĠ Ġdelete < Article Route > Ġ{ Ġparams Ġ-> ĊĠĠĠĠĠ Ġval Ġuser Ġ= Ġcall . principal < User >() ĊĠĠĠĠĠĠĠ Ġ?: Ġreturn @ delete Ġcall . respond ( ĊĠĠĠĠĠĠĠĠĠ Ġstatus Ġ= ĠHttpStatusCode . Unauthorized , ĊĠĠĠĠĠĠĠĠĠ Ġmessage Ġ= ĠError Envelope ( map Of (" body " Ġto ĠlistOf (" Unauthorized "))) ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠ ĠSl ug . fromString ( params . slug ) ĊĠĠĠĠĠĠĠ Ġ. to Either Ġ{ ĠInvalid Slug () Ġ} ĊĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}) Ġ{ Ġslug Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġdelete Article With Slug ( slug , Ġuser . id ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}, Ġ{ Ġcall . respond ( HttpStatusCode . No Content ) Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ fun ĠRoute . favorite Article () Ġ{ ĊĠ Ġval Ġfavor Article Ġby Ġinject < F avor Article UseCase >( named (" f avor Article ")) ĊĊĠ Ġauthenticate (" auth - jwt ") Ġ{ ĊĠĠĠ Ġpost < Article Route . Favorite > Ġ{ Ġparams Ġ-> ĊĠĠĠĠĠ Ġval Ġuser Ġ= Ġcall . principal < User >() ĊĠĠĠĠĠĠĠ Ġ?: Ġreturn @ post Ġcall . respond ( ĊĠĠĠĠĠĠĠĠĠ Ġstatus Ġ= ĠHttpStatusCode . Unauthorized , ĊĠĠĠĠĠĠĠĠĠ Ġmessage Ġ= ĠError Envelope ( map Of (" body " Ġto ĠlistOf (" Unauthorized "))) ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠ ĠSl ug . fromString ( params . parent . slug ) ĊĠĠĠĠĠĠĠ Ġ. to Either Ġ{ ĠInvalid Slug () Ġ} ĊĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}) Ġ{ Ġslug Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġfavor Article ( slug , Ġuser . id ). map Ġ{ ĠArticle Response ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}, Ġ{ Ġcall . respond ( it ) Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ fun ĠRoute . un Favorite Article () Ġ{ ĊĠ Ġval Ġun F avor Article Ġby Ġinject < Un F avor Article UseCase >( named (" un F avor Article ")) ĊĊĠ Ġauthenticate (" auth - jwt ") Ġ{ ĊĠĠĠ Ġdelete < Article Route . Favorite > Ġ{ Ġparams Ġ-> ĊĠĠĠĠĠ Ġval Ġuser Ġ= Ġcall . principal < User >() ĊĠĠĠĠĠĠĠ Ġ?: Ġreturn @ delete Ġcall . respond ( ĊĠĠĠĠĠĠĠĠĠ Ġstatus Ġ= ĠHttpStatusCode . Unauthorized , ĊĠĠĠĠĠĠĠĠĠ Ġmessage Ġ= ĠError Envelope ( map Of (" body " Ġto ĠlistOf (" Unauthorized "))) ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠ ĠSl ug . fromString ( params . parent . slug ) ĊĠĠĠĠĠĠĠ Ġ. to Either Ġ{ ĠInvalid Slug () Ġ} ĊĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}) Ġ{ Ġslug Ġ-> ĊĠĠĠĠĠĠĠĠĠ Ġun F avor Article ( slug , Ġuser . id ). map Ġ{ ĠArticle Response ( it ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. fold ({ Ġhandle Errors ( it ) Ġ}, Ġ{ Ġcall . respond ( it ) Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ Ċ fun ĠApplication . register Article Routes () Ġ{ ĊĠ Ġrouting Ġ{ ĊĠĠĠ Ġroute ( API _ V 1 ) Ġ{ ĊĠĠĠĠĠ Ġcreate Article () ĊĠĠĠĠĠ Ġget Article With Slug () ĊĠĠĠĠĠ Ġupdate Article () ĊĠĠĠĠĠ Ġdelete Article () ĊĠĠĠĠĠ Ġall Articles () ĊĠĠĠĠĠ Ġarticle Feed () ĊĠĠĠĠĠ Ġfavorite Article () ĊĠĠĠĠĠ Ġun Favorite Article () ĊĠĠĠ Ġ} ĊĠ Ġ} Ċ } Ċ