/* Ċ Ġ* Ġ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 . Ċ Ġ*/ Ċ package Ġru . so kom ish al ov . sk raper . provider . facebook Ċ Ċ import Ġcom . fasterxml . jackson . databind . JsonNode Ċ import Ġkotlinx . coroutines . flow . Flow Ċ import Ġkotlinx . coroutines . flow . flow Ċ import Ġorg . js oup . J soup Ċ import Ġorg . js oup . nodes . Document Ċ import Ġorg . js oup . nodes . Element Ċ 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 .* Ċ import Ġru . so kom ish al ov . sk raper . internal . iterable . emit Batch Ċ import Ġru . so kom ish al ov . sk raper . internal . js oup . getFirst Element By AttributeValue Ċ import Ġru . so kom ish al ov . sk raper . internal . js oup . getFirst Element By Class Ċ import Ġru . so kom ish al ov . sk raper . internal . js oup . getFirst Element By Tag Ċ import Ġru . so kom ish al ov . sk raper . internal . net . host Ċ import Ġru . so kom ish al ov . sk raper . internal . number . div Ċ import Ġru . so kom ish al ov . sk raper . internal . serialization . getDouble Ċ import Ġru . so kom ish al ov . sk raper . internal . serialization . getLong Ċ import Ġru . so kom ish al ov . sk raper . internal . serialization . getString Ċ import Ġru . so kom ish al ov . sk raper . internal . serialization . read Json Nodes Ċ import Ġru . so kom ish al ov . sk raper . internal . string . un escape Json Ċ import Ġru . so kom ish al ov . sk raper . model .* Ċ import Ġjava . time . Instant ĊĊ Ċ /** Ċ Ġ* Ġ@ author Ġs ok om ish al ov Ċ Ġ*/ Ċ open Ġclass ĠFacebook 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 Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġposts Path Ġ= Ġpath . substring Before ("/ posts ") Ġ+ Ġ"/ posts " ĊĠĠĠĠĠĠĠ Ġvar Ġnext Path Ġ= Ġposts Path ĊĠĠĠĠĠĠĠ Ġwhile Ġ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfetch Result Ġ= Ġclient . fetch String ( HttpRequest ( url Ġ= ĠM OB ILE _ BASE _ URL . build Full URL ( path Ġ= Ġnext Path ))) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġ( document , Ġnext Page ) Ġ= Ġfetch Result ?. extract Document And Next Page () Ġ?: Ġbreak ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnext Path Ġ= Ġnext Page Ġ?: Ġbreak ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġraw Posts Ġ= Ġdocument ?. getElementsBy Tag (" article ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( raw Posts . isNull OrEmpty ()) Ġbreak ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġemit Batch ( raw Posts ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdata Ft Ġ= Ġattr (" data - ft "). read Json Nodes () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPost ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġid Ġ= Ġdata Ft . extract Post Id (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtext Ġ= Ġextract Post Text (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpublished At Ġ= Ġdata Ft . extract Post Published At (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstatistics Ġ= ĠPost Statistics ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlikes Ġ= Ġextract Post Lik es (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcomments Ġ= Ġextract Post Comments Count (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġmedia Ġ= Ġextract Post Media () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġget Page Info ( path : ĠString ): ĠPage Info ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġabout Path Ġ= Ġpath . substring Before ("/ posts ") ĊĊĠĠĠĠĠĠĠ Ġval Ġpage Ġ= Ġclient . fetch Document ( HttpRequest ( url Ġ= ĠBASE _ URL . build Full URL ( path Ġ= Ġabout Path ))) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġpage ?. run Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġis Community Ġ= Ġget First Element By AttributeValue (" data - key ", Ġ" tab _ community ") Ġ!= Ġnull ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Community Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġserver Json Data Ġ= Ġextract Json Data () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠPage Info ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnick Ġ= Ġpath . remove Prefix ("/ "). remove Prefix (" pg / "). substring Before ("/ "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġname Ġ= Ġserver Json Data ?. extract Community Name (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdescription Ġ= Ġextract Community Description (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġavatar Ġ= Ġextract Community Avatar ()?. to Image (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcover Ġ= Ġserver Json Data ?. extract Community Cover ()?. to Image () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĠPage Info ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnick Ġ= Ġpath . remove Prefix ("/ "). substring Before ("/ "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġname Ġ= Ġextract UserName (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdescription Ġ= Ġextract User Description (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġavatar Ġ= Ġextract User Avatar ()?. to Image (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcover Ġ= Ġextract User Cover ()?. to Image () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġsupports ( media : ĠMedia ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġ" facebook . com " Ġin Ġmedia . url . host ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġresolve ( media : ĠMedia ): ĠMedia Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġclient . fetch Open Graph Media ( media ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠString . extract Document And Next Page (): ĠPair < Document ?, ĠString ?> Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġstart sWith (" for Ġ( ;; ); ") Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnext Path Ġ= Ġ"/ page _ content [^ \"] +\ "" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. to Regex () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. find ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . group Values ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . first OrNull () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . substring Before Last ("\\ \" ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . un escape Json () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . un escape Json () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdoc Ġ= Ġsubstring After (" for Ġ( ;; ); ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. read Json Nodes () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . getString (" payload . actions . 0 . html ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . let Ġ{ ĠJ soup . parse ( it ) Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdoc Ġto Ġnext Path ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnext Path Ġ= Ġ"/ page _ content [^ \"] +\ "" ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. to Regex () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. find ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . group Values ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . first OrNull () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ? . substring Before Last ("\" ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdoc Ġ= ĠJ soup . parse ( this ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġdoc Ġto Ġnext Path ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠJsonNode ?. extract Post Id (): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġthis ?. getString (" top _ level _ post _ id "). or Empty () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠElement . extract Post Text (): ĠString Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġget Elements By Tag (" p "). join ToString ( separator Ġ= Ġ"\ n \ n ") Ġ{ Ġit . whole Text () Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠJsonNode ?. extract Post Published At (): ĠInstant ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġthis ?. get (" page _ insights ") ?. first OrNull ()?. getLong (" post _ context . publish _ time ") ?. let Ġ{ ĠInstant . of Epoch Second ( it ) Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠElement . extract Post Lik es (): ĠInt ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġget First Element By Class (" like _ def ") ?. whole Text ()?. substring After Last (": ") ?. trim ()?. toInt OrNull () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠElement . extract Post Comments Count (): ĠInt ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġget First Element By Class (" cmt _ def ") ?. whole Text ()?. substring After Last (": ") ?. trim ()?. toInt OrNull () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠElement . extract Post Media (): ĠList < Media > Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnative Video Node Ġ= Ġget First Element By AttributeValue (" data - sig il ", Ġ" inline Video ") ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnative Video Node Ġ!= Ġnull Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdata Store Ġ= Ġnative Video Node . attr (" data - store "). read Json Nodes () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠlistOf ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠVideo ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġurl Ġ= Ġdata Store ?. getString (" src "). or Empty (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaspect Ratio Ġ= Ġdata Store ?. getDouble (" width ") Ġ/ Ġdata Store ?. getDouble (" height ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlinks Ġ= Ġget Elements By Tag (" a "). drop ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlinks . map NotNull Ġ{ Ġnode Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġimg Node Ġ= Ġnode . getFirst Element By Tag (" img ") ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnode . hasClass (" touch able ") Ġ-> ĠVideo ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġurl Ġ= Ġnode ?. attr (" href "). or Empty (), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġimg Node Ġ!= Ġnull Ġ-> Ġwith ( img Node ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠImage ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġurl Ġ= Ġattr (" src "), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaspect Ratio Ġ= Ġattr (" width "). toDouble OrNull () Ġ/ Ġattr (" height "). toDouble OrNull () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠDocument ?. extract Json Data (): ĠJsonNode ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġinfo Json Prefix Ġ= Ġ" new Ġ( require (\" Server JS \" )) (). handle (" ĊĠĠĠĠĠĠĠ Ġval Ġinfo Json Suffix Ġ= Ġ"); " ĊĊĠĠĠĠĠĠĠ Ġreturn Ġthis ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . getElementsBy Tag (" script ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . map NotNull Ġ{ Ġit . html () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . find Ġ{ Ġs Ġ-> Ġs . startsWith ( info Json Prefix ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . remove Prefix ( info Json Prefix ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . remove Suffix ( info Json Suffix ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . read Json Nodes () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠJsonNode . extract Community Cover (): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġfind Path (" cover Photo Data ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . getString (" uri ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠDocument . extract Community Avatar (): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġget First Element By AttributeValue (" property ", Ġ" og : image ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . attr (" content ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠElement . extract Community Description (): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġget First Element By AttributeValue (" property ", Ġ" og : description ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . attr (" content ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . split ("[ 0 - 9 ]+ . Ġ". to Regex ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . last OrNull () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠJsonNode . extract Community Name (): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġfind Path (" page Name ") ?. as Text () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠElement . extract User Description (): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġget Elements By Class (" experience ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. get OrNull ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . all Elements ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . last OrNull () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . whole Text () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠElement . extract UserName (): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġget First Element By AttributeValue (" data - test id ", Ġ" profile _ name _ in _ profile _ page ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . whole Text () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠElement . extract User Avatar (): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġget First Element By Class (" profile Pic Thumb ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . getFirst Element By Tag (" img ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . attr (" src ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun ĠElement . extract User Cover (): ĠString ? Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġget First Element By Class (" cover Photo Img ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . attr (" src ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠBASE _ URL : ĠString Ġ= Ġ" https :// facebook . com " ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠM OB ILE _ BASE _ URL : ĠString Ġ= Ġ" https :// m . facebook . com " ĊĠĠĠ Ġ} Ċ }