/* Ċ Ġ* ĠCopyright Ġ( c ) Ġ 2 0 1 9 - present ĠM ik ha el ĠS oko lov Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ @ file : Suppress (" Member Visibility Can Be Private ") Ċ Ċ package Ġru . so kom ish al ov . sk raper . provider . reddit Ċ Ċ import Ġcom . fasterxml . jackson . databind . JsonNode Ċ import Ġkotlinx . coroutines . flow . Flow Ċ import Ġkotlinx . coroutines . flow . first OrNull Ċ import Ġkotlinx . coroutines . flow . flow Ċ import Ġru . so kom ish al ov . sk raper . Sk raper Ċ import Ġru . so kom ish al ov . sk raper . Sk rap ers Ċ import Ġru . so kom ish al ov . sk raper . client . HttpRequest Ċ import Ġru . so kom ish al ov . sk raper . client . Sk raper Client Ċ import Ġru . so kom ish al ov . sk raper . client . fetch Json Ċ import Ġru . so kom ish al ov . sk raper . client . fetch Open Graph Media Ċ import Ġru . so kom ish al ov . sk raper . internal . consts . DEFAULT _ POST S _ BATCH Ċ import Ġru . so kom ish al ov . sk raper . internal . iterable . emit Batch Ċ import Ġru . so kom ish al ov . sk raper . internal . net . host Ċ import Ġru . so kom ish al ov . sk raper . internal . net . path Ċ import Ġru . so kom ish al ov . sk raper . internal . number . div Ċ import Ġru . so kom ish al ov . sk raper . internal . serialization .* Ċ import Ġru . so kom ish al ov . sk raper . model .* Ċ import Ġjava . time . Instant Ċ Ċ open Ġclass ĠRed dit Sk raper Ġ@ Jvm Over loads Ġconstructor ( ĊĠĠĠ Ġoverride Ġval Ġclient : ĠSk raper Client Ġ= ĠSk rap ers . client Ċ ) Ġ: ĠSk raper Ġ{ ĊĊĠĠĠ Ġoverride Ġfun Ġget Posts ( path : ĠString ): ĠFlow < Post > Ġ= Ġflow Ġ{ ĊĠĠĠĠĠĠĠ Ġvar Ġnext Page : ĠString ? Ġ= Ġnull ĊĊĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġclient . fetch Json ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠHttpRequest ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġurl Ġ= ĠBASE _ URL . build Full URL ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpath Ġ= Ġ"${ path . remove Suffix ("/") }. json ", ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠqueryParams Ġ= Ġmap Of (" limit " Ġto ĠDEFAULT _ POST S _ BATCH , Ġ" after " Ġto Ġnext Page ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġraw Posts Ġ= Ġresponse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . getFirst By Path (" data . children ", Ġ" 0 . data . children ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . map NotNull Ġ{ Ġit [" data "] Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( raw Posts . isNull OrEmpty ()) Ġbreak ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġemit Batch ( raw Posts ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPost ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġid Ġ= ĠgetString (" id "). or Empty (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtext Ġ= Ġextract Text (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpublished At Ġ= Ġget Long (" created _ utc ") ?. let Ġ{ ĠInstant . of Epoch Second ( it ) Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstatistics Ġ= ĠPost Statistics ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlikes Ġ= Ġget Int (" score "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomments Ġ= Ġget Int (" num _ comments "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmedia Ġ= Ġextract Post Media Items () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġnext Page Ġ= Ġresponse . getString (" data . after ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġget Page Info ( path : ĠString ): ĠPage Info ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġresponse Ġ= Ġclient . fetch Json ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠHttpRequest ( url Ġ= ĠBASE _ URL . build Full URL ( path Ġ= Ġ"${ path . remove Suffix ("/") }/ about . json ")) ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġval Ġis User Ġ= Ġpath . remove Prefix ("/ "). startsWith (" u ") ĊĊĠĠĠĠĠĠĠ Ġreturn Ġresponse ?. get (" data ") ?. run Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis User Ġ-> ĠPage Info ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnick Ġ= ĠgetString (" sub reddit . display _ name _ prefix ed "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġname Ġ= ĠgetString (" sub reddit . display _ name "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdescription Ġ= ĠgetString (" sub reddit . public _ description "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġavatar Ġ= ĠgetString (" sub reddit . icon _ img ") ?. to Image (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcover Ġ= ĠgetString (" sub reddit . banner _ img ") ?. to Image () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĠPage Info ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnick Ġ= ĠgetString (" display _ name _ prefix ed "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġname Ġ= ĠgetString (" display _ name "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdescription Ġ= ĠgetString (" public _ description "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġavatar Ġ= ĠgetString (" icon _ img ") ?. to Image (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcover Ġ= ĠgetString (" banner _ background _ image ") ?. to Image () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġsupports ( media : ĠMedia ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġ" reddit . com " Ġin Ġmedia . url . host ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġresolve ( media : ĠMedia ): ĠMedia Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ( media ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠImage Ġ-> Ġclient . fetch Open Graph Media ( media ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠVideo Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġget Posts ( path Ġ= Ġmedia . url . path ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. first OrNull () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . media ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . first OrNull () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġmedia ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġmedia ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠJsonNode . extract Text (): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn ĠlistOf ( getString (" title "), ĠgetString (" self text ")) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Not Ġ{ Ġs Ġ-> Ġs . isNull OrEmpty () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. join ToString ("\ n ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠJsonNode . extract Post Media Items (): ĠList < Media > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġpreview Media Ġ= ĠgetBy Path (" preview . images ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . toList () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. or Empty () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. map NotNull Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġit . get (" source ") ?. let Ġ{ Ġsource Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠImage ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġurl Ġ= Ġsource . getString (" url "). or Empty (). replace ("& amp ;", Ġ"& "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaspect Ratio Ġ= Ġsource . getDouble (" width ") Ġ/ Ġsource . getDouble (" height ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġis Video Ġ= Ġthis [" media "]. isEmpty . not () ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġis Video Ġ-> ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠVideo ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġurl Ġ= ĠgetString (" url "). or Empty (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaspect Ratio Ġ= Ġpreview Media . first OrNull ()?. aspect Ratio , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthumbnail Ġ= Ġpreview Media . first OrNull () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġpreview Media ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠBASE _ URL : ĠString Ġ= Ġ" https :// reddit . com " ĊĠĠĠ Ġ} Ċ }