package Ġspace . jetbrains . api . runtime Ċ Ċ import Ġio . ktor . client . HttpClient Ċ import Ġio . ktor . client . HttpClient Config Ċ import Ġio . ktor . client . engine .* Ċ import Ġio . ktor . client . request .* Ċ import Ġio . ktor . client . statement . HttpResponse Ċ import Ġio . ktor . client . statement . read Text Ċ import Ġio . ktor . http .* Ċ import Ġio . ktor . http . content . Text Content Ċ import Ġio . ktor . utils . io . char sets . Charsets Ċ import Ġio . ktor . utils . io . errors . IOException Ċ import Ġkotlinx . datetime . Clock . System Ċ import Ġkotlinx . datetime . DateTime Unit Ċ import Ġkotlinx . datetime . plus Ċ import Ġmu . Kotlin Logging Ċ import Ġspace . jetbrains . api . runtime . epoch . Epoch Tracking Feature Ċ Ċ public Ġfun ĠHttpClient Config <* >. configure K tor Client For Space () Ġ{ ĊĠĠĠ Ġexpect Success Ġ= Ġfalse ĊĠĠĠ Ġinstall ( Epoch Tracking Feature ) Ċ } Ċ Ċ public Ġfun Ġk tor Client For Space ( block : ĠHttpClient Config <* >. () Ġ-> ĠUnit Ġ= Ġ{} ): ĠHttpClient Ġ= ĠHttpClient Ġ{ ĊĠĠĠ Ġblock () ĊĠĠĠ Ġconfigure K tor Client For Space () Ċ } Ċ Ċ public Ġfun Ġk tor Client For Space ( ĊĠĠĠ Ġengine : ĠHttpClient Engine , ĊĠĠĠ Ġblock : ĠHttpClient Config <* >. () Ġ-> ĠUnit , Ċ ): ĠHttpClient Ġ= ĠHttpClient ( engine ) Ġ{ ĊĠĠĠ Ġblock () ĊĠĠĠ Ġconfigure K tor Client For Space () Ċ } Ċ Ċ public Ġfun Ġ< T Ġ: ĠHttpClient Engine Config > Ġk tor Client For Space ( ĊĠĠĠ Ġengine Factory : ĠHttpClient Engine Factory < T >, ĊĠĠĠ Ġblock : ĠHttpClient Config < T >. () Ġ-> ĠUnit Ġ= Ġ{}, Ċ ): ĠHttpClient Ġ= ĠHttpClient ( engine Factory ) Ġ{ ĊĠĠĠ Ġblock () ĊĠĠĠ Ġconfigure K tor Client For Space () Ċ } Ċ Ċ @ Deprecated ( ĊĠĠĠ Ġ" Use ĠHttpClient Ġfrom Ġk tor Client For Space () Ġor Ġconfigured Ġwith Ġconfigure K tor Client For Space ()", ĊĠĠĠ ĠReplace With (" HttpClient ", Ġ" io . ktor . client . HttpClient ") Ċ ) Ċ public Ġtype alias ĠSpace HttpClient Ġ= ĠHttpClient Ċ Ċ @ Deprecated ( ĊĠĠĠ Ġ" Use ĠHttpClient Ġfrom Ġk tor Client For Space () Ġor Ġconfigured Ġwith Ġconfigure K tor Client For Space ()", ĊĠĠĠ ĠReplace With (" ktor Client . config Ġ{ Ġconfigure K tor Client For Space () Ġ} ") Ċ ) Ċ @ Suppress (" FunctionName ") Ċ public Ġfun ĠSpace HttpClient ( ktor Client : ĠHttpClient ): ĠHttpClient Ġ= Ġk tor Client . config Ġ{ Ġconfigure K tor Client For Space () Ġ} Ċ Ċ private Ġval Ġlog Ġ= ĠKotlin Logging . logger Ġ{} Ċ Ċ @ Suppress (" Deprecated Callable Add Replace With ") Ċ @ Deprecated (" Use ĠSpace Client Ġto Ġcall ĠSpace ĠAPI ") Ċ public Ġsuspend Ġfun ĠHttpClient . call ( ĊĠĠĠ Ġfunction Name : ĠString , ĊĠĠĠ Ġapp Instance : ĠSpace App Instance , ĊĠĠĠ Ġauth : ĠSpace Auth , ĊĠĠĠ Ġcall Method : ĠHttpMethod , ĊĠĠĠ Ġpath : ĠString , ĊĠĠĠ Ġpartial : ĠPartial Builder . Explicit ?, ĊĠĠĠ Ġparameters : ĠParameters Ġ= ĠParameters . Empty , ĊĠĠĠ Ġrequest Body : ĠJson Value ? Ġ= Ġnull Ċ ): ĠDeserial ization Context Ġ= Ġcall Space Api ( ĊĠĠĠ Ġk tor Client Ġ= Ġthis , ĊĠĠĠ Ġfunction Name Ġ= Ġfunction Name , ĊĠĠĠ Ġapp Instance Ġ= Ġapp Instance , ĊĠĠĠ Ġauth Ġ= Ġauth , ĊĠĠĠ Ġcall Method Ġ= Ġcall Method , ĊĠĠĠ Ġpath Ġ= Ġpath , ĊĠĠĠ Ġpartial Ġ= Ġpartial , ĊĠĠĠ Ġparameters Ġ= Ġparameters , ĊĠĠĠ Ġrequest Body Ġ= Ġrequest Body Ċ ) Ċ Ċ internal Ġsuspend Ġfun Ġcall Space Api ( ĊĠĠĠ Ġk tor Client : ĠHttpClient , ĊĠĠĠ Ġfunction Name : ĠString , ĊĠĠĠ Ġapp Instance : ĠSpace App Instance , ĊĠĠĠ Ġauth : ĠSpace Auth , ĊĠĠĠ Ġcall Method : ĠHttpMethod , ĊĠĠĠ Ġpath : ĠString , ĊĠĠĠ Ġpartial : ĠPartial Builder . Explicit ?, ĊĠĠĠ Ġparameters : ĠParameters Ġ= ĠParameters . Empty , ĊĠĠĠ Ġrequest Body : ĠJson Value ? Ġ= Ġnull Ċ ): ĠDeserial ization Context Ġ{ ĊĠĠĠ Ġval Ġtemplate Request Ġ= ĠHttpRequest Builder (). apply Ġ{ ĊĠĠĠĠĠĠĠ Ġurl Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtake From ( app Instance . space Server . api BaseUrl . remove Suffix ("/") Ġ+ Ġ"/" Ġ+ Ġpath . remove Prefix ("/ ")) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . parameters . append All ( parameters ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( partial Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthis . parameters . append ("\ $ fields ", Ġpartial . build Query ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġmethod Ġ= Ġcall Method ĊĠĠĠĠĠĠĠ Ġaccept ( ContentType . Application . Json ) ĊĊĊĠĠĠĠĠĠĠ Ġrequest Body ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġbody Ġ= ĠText Content ( it . print (), ĠContentType . Application . Json ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġrequest Ġ= ĠHttpRequest Builder (). take From ( template Request ) ĊĠĠĠĠĠĠĠ Ġauth . token ( ktor Client , Ġapp Instance ). accessToken . take If Ġ{ Ġit . isNotEmpty () Ġ} ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequest . header ( HttpHeaders . Authorization , Ġ" Bearer Ġ$ it ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġk tor Client . request < HttpResponse >( request ) ĊĠĠĠĠĠĠĠ Ġval Ġresponse Text Ġ= Ġresponse . read Text ( Charsets . UTF _ 8 ) ĊĠĠĠĠĠĠĠ Ġlog . trace Ġ{ Ġ" Response Ġfor Ġ${ request . method . value } Ġrequest Ġto Ġ${ request . url . build String ()} :\ n $ responseText " Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġcontent Ġ= Ġresponse Text . let (:: parse Json ) ĊĠĠĠĠĠĠĠ Ġif Ġ(! throw Error Or Return Whether To Retry ( response , Ġcontent , Ġcall Method , Ġpath )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠDeserial ization Context ( content , ĠReference Chain Link ( function Name ), Ġpartial ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ internal Ġsuspend Ġfun Ġauth ( ktor Client : ĠHttpClient , Ġurl : ĠString , Ġmethod Body : ĠParameters , Ġauth HeaderValue : ĠString ): ĠSpace Token Info Ġ{ ĊĠĠĠ Ġval Ġhttp Method Ġ= ĠHttpMethod . Post ĊĠĠĠ Ġval Ġresponse Ġ= Ġk tor Client . request < HttpResponse >( url ) Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . method Ġ= Ġhttp Method ĊĠĠĠĠĠĠĠ Ġthis . accept ( ContentType . Application . Json ) ĊĊĠĠĠĠĠĠĠ Ġthis . header ( HttpHeaders . Authorization , Ġauth HeaderValue ) ĊĊĠĠĠĠĠĠĠ Ġmethod Body . take If Ġ{ Ġ! it . isEmpty () Ġ} ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis . body Ġ= ĠText Content ( it . form Url Encode (), ĠContentType . Application . Form Url Encoded ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġval Ġresponse Time Ġ= ĠSystem . now () ĊĊĠĠĠ Ġval Ġtoken Json Ġ= Ġresponse . read Text ( Charsets . UTF _ 8 ). let (:: parse Json ) ĊĠĠĠ Ġthrow Error Or Return Whether To Retry ( response , Ġtoken Json , Ġhttp Method , Ġurl ) ĊĊĠĠĠ Ġval Ġde serialization Ġ= ĠDeserial ization Context ( token Json , ĠReference Chain Link (" auth "), Ġnull ) ĊĠĠĠ Ġreturn ĠSpace Token Info ( ĊĠĠĠĠĠĠĠ ĠaccessToken Ġ= Ġde serialization . child (" access _ token "). let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġit . require Json (). asString ( it . link ) ĊĠĠĠĠĠĠĠ Ġ}, ĊĠĠĠĠĠĠĠ Ġexpires Ġ= Ġresponse Time . plus ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvalue Ġ= Ġde serialization . child (" expires _ in "). let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . require Json (). as Number ( it . link ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. to Long (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġunit Ġ= ĠDateTime Unit . SECOND , ĊĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠ Ġrefresh Token Ġ= Ġde serialization . child (" refresh _ token "). let Ġ{ Ġit . json ?. asString ( it . link ) Ġ}, ĊĠĠĠ Ġ) Ċ } Ċ Ċ private Ġfun Ġthrow Error Or Return Whether To Retry ( ĊĠĠĠ Ġresponse : ĠHttpResponse , ĊĠĠĠ Ġresponse Content : ĠJson Value ?, ĊĠĠĠ Ġcall Method : ĠHttpMethod , ĊĠĠĠ Ġpath : ĠString Ċ ): ĠBoolean Ġ{ ĊĠĠĠ Ġif Ġ(! response . status . is Success ()) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġerror Description Ġ= Ġresponse Content ?. getField (" error _ description ") ?. asString OrNull () ĊĠĠĠĠĠĠĠ Ġthrow Ġwhen Ġ( response Content ?. getField (" error ") ?. asString OrNull ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠError Codes . VALIDATION _ ERROR Ġ-> ĠValidation Exception ( error Description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠError Codes . AUTHENT ICATION _ REQUIRED Ġ-> Ġwhen Ġ( error Description ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Access Ġtoken Ġhas Ġexpired " Ġ-> Ġreturn Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Refresh Ġtoken Ġassociated Ġwith Ġthe Ġaccess Ġtoken Ġis Ġrev oked " Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠRefresh Token Rev oked Exception ( error Description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĠAuthentication Required Exception ( error Description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ ĠError Codes . PERMISSION _ DEN IED Ġ-> ĠPermission Denied Exception ( error Description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠError Codes . DUPLIC ATED _ ENTITY Ġ-> ĠD uplicated Entity Exception ( error Description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠError Codes . REQUEST _ ERROR Ġ-> ĠRequest Exception ( error Description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠError Codes . NOT _ FOUND Ġ-> ĠNotFound Exception ( error Description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠError Codes . RATE _ LIMIT ED Ġ-> ĠRate Limit ed Exception ( error Description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠError Codes . PAYLOAD _ TOO _ LARGE Ġ-> ĠPayload Too Large Exception ( error Description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠError Codes . INTERNAL _ SERVER _ ERROR Ġ-> ĠInternal ServerError Exception ( error Description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġwhen Ġ( response . status ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHttpStatusCode . BadRequest Ġ-> ĠRequest Exception ( HttpStatusCode . BadRequest . description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHttpStatusCode . Unauthorized Ġ-> ĠAuthentication Required Exception ( HttpStatusCode . BadRequest . description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHttpStatusCode . Forbidden Ġ-> ĠPermission Denied Exception ( HttpStatusCode . Forbidden . description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHttpStatusCode . NotFound Ġ-> ĠNotFound Exception ( HttpStatusCode . NotFound . description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHttpStatusCode . Too Many Requests Ġ-> ĠRate Limit ed Exception ( HttpStatusCode . Too Many Requests . description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHttpStatusCode . Payload Too Large Ġ-> ĠPayload Too Large Exception ( HttpStatusCode . Payload Too Large . description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHttpStatusCode . InternalServerError Ġ-> ĠInternal ServerError Exception ( HttpStatusCode . InternalServerError . description , Ġresponse ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĠIOException ("${ call Method . value } Ġrequest Ġto Ġ$ path Ġfailed ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġfalse Ċ }