converse-no-dependencies.js 1.5 MB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755197561975719758197591976019761197621976319764197651976619767197681976919770197711977219773197741977519776197771977819779197801978119782197831978419785197861978719788197891979019791197921979319794197951979619797197981979919800198011980219803198041980519806198071980819809198101981119812198131981419815198161981719818198191982019821198221982319824198251982619827198281982919830198311983219833198341983519836198371983819839198401984119842198431984419845198461984719848198491985019851198521985319854198551985619857198581985919860198611986219863198641986519866198671986819869198701987119872198731987419875198761987719878198791988019881198821988319884198851988619887198881988919890198911989219893198941989519896198971989819899199001990119902199031990419905199061990719908199091991019911199121991319914199151991619917199181991919920199211992219923199241992519926199271992819929199301993119932199331993419935199361993719938199391994019941199421994319944199451994619947199481994919950199511995219953199541995519956199571995819959199601996119962199631996419965199661996719968199691997019971199721997319974199751997619977199781997919980199811998219983199841998519986199871998819989199901999119992199931999419995199961999719998199992000020001200022000320004200052000620007200082000920010200112001220013200142001520016200172001820019200202002120022200232002420025200262002720028200292003020031200322003320034200352003620037200382003920040200412004220043200442004520046200472004820049200502005120052200532005420055200562005720058200592006020061200622006320064200652006620067200682006920070200712007220073200742007520076200772007820079200802008120082200832008420085200862008720088200892009020091200922009320094200952009620097200982009920100201012010220103201042010520106201072010820109201102011120112201132011420115201162011720118201192012020121201222012320124201252012620127201282012920130201312013220133201342013520136201372013820139201402014120142201432014420145201462014720148201492015020151201522015320154201552015620157201582015920160201612016220163201642016520166201672016820169201702017120172201732017420175201762017720178201792018020181201822018320184201852018620187201882018920190201912019220193201942019520196201972019820199202002020120202202032020420205202062020720208202092021020211202122021320214202152021620217202182021920220202212022220223202242022520226202272022820229202302023120232202332023420235202362023720238202392024020241202422024320244202452024620247202482024920250202512025220253202542025520256202572025820259202602026120262202632026420265202662026720268202692027020271202722027320274202752027620277202782027920280202812028220283202842028520286202872028820289202902029120292202932029420295202962029720298202992030020301203022030320304203052030620307203082030920310203112031220313203142031520316203172031820319203202032120322203232032420325203262032720328203292033020331203322033320334203352033620337203382033920340203412034220343203442034520346203472034820349203502035120352203532035420355203562035720358203592036020361203622036320364203652036620367203682036920370203712037220373203742037520376203772037820379203802038120382203832038420385203862038720388203892039020391203922039320394203952039620397203982039920400204012040220403204042040520406204072040820409204102041120412204132041420415204162041720418204192042020421204222042320424204252042620427204282042920430204312043220433204342043520436204372043820439204402044120442204432044420445204462044720448204492045020451204522045320454204552045620457204582045920460204612046220463204642046520466204672046820469204702047120472204732047420475204762047720478204792048020481204822048320484204852048620487204882048920490204912049220493204942049520496204972049820499205002050120502205032050420505205062050720508205092051020511205122051320514205152051620517205182051920520205212052220523205242052520526205272052820529205302053120532205332053420535205362053720538205392054020541205422054320544205452054620547205482054920550205512055220553205542055520556205572055820559205602056120562205632056420565205662056720568205692057020571205722057320574205752057620577205782057920580205812058220583205842058520586205872058820589205902059120592205932059420595205962059720598205992060020601206022060320604206052060620607206082060920610206112061220613206142061520616206172061820619206202062120622206232062420625206262062720628206292063020631206322063320634206352063620637206382063920640206412064220643206442064520646206472064820649206502065120652206532065420655206562065720658206592066020661206622066320664206652066620667206682066920670206712067220673206742067520676206772067820679206802068120682206832068420685206862068720688206892069020691206922069320694206952069620697206982069920700207012070220703207042070520706207072070820709207102071120712207132071420715207162071720718207192072020721207222072320724207252072620727207282072920730207312073220733207342073520736207372073820739207402074120742207432074420745207462074720748207492075020751207522075320754207552075620757207582075920760207612076220763207642076520766207672076820769207702077120772207732077420775207762077720778207792078020781207822078320784207852078620787207882078920790207912079220793207942079520796207972079820799208002080120802208032080420805208062080720808208092081020811208122081320814208152081620817208182081920820208212082220823208242082520826208272082820829208302083120832208332083420835208362083720838208392084020841208422084320844208452084620847208482084920850208512085220853208542085520856208572085820859208602086120862208632086420865208662086720868208692087020871208722087320874208752087620877208782087920880208812088220883208842088520886208872088820889208902089120892208932089420895208962089720898208992090020901209022090320904209052090620907209082090920910209112091220913209142091520916209172091820919209202092120922209232092420925209262092720928209292093020931209322093320934209352093620937209382093920940209412094220943209442094520946209472094820949209502095120952209532095420955209562095720958209592096020961209622096320964209652096620967209682096920970209712097220973209742097520976209772097820979209802098120982209832098420985209862098720988209892099020991209922099320994209952099620997209982099921000210012100221003210042100521006210072100821009210102101121012210132101421015210162101721018210192102021021210222102321024210252102621027210282102921030210312103221033210342103521036210372103821039210402104121042210432104421045210462104721048210492105021051210522105321054210552105621057210582105921060210612106221063210642106521066210672106821069210702107121072210732107421075210762107721078210792108021081210822108321084210852108621087210882108921090210912109221093210942109521096210972109821099211002110121102211032110421105211062110721108211092111021111211122111321114211152111621117211182111921120211212112221123211242112521126211272112821129211302113121132211332113421135211362113721138211392114021141211422114321144211452114621147211482114921150211512115221153211542115521156211572115821159211602116121162211632116421165211662116721168211692117021171211722117321174211752117621177211782117921180211812118221183211842118521186211872118821189211902119121192211932119421195211962119721198211992120021201212022120321204212052120621207212082120921210212112121221213212142121521216212172121821219212202122121222212232122421225212262122721228212292123021231212322123321234212352123621237212382123921240212412124221243212442124521246212472124821249212502125121252212532125421255212562125721258212592126021261212622126321264212652126621267212682126921270212712127221273212742127521276212772127821279212802128121282212832128421285212862128721288212892129021291212922129321294212952129621297212982129921300213012130221303213042130521306213072130821309213102131121312213132131421315213162131721318213192132021321213222132321324213252132621327213282132921330213312133221333213342133521336213372133821339213402134121342213432134421345213462134721348213492135021351213522135321354213552135621357213582135921360213612136221363213642136521366213672136821369213702137121372213732137421375213762137721378213792138021381213822138321384213852138621387213882138921390213912139221393213942139521396213972139821399214002140121402214032140421405214062140721408214092141021411214122141321414214152141621417214182141921420214212142221423214242142521426214272142821429214302143121432214332143421435214362143721438214392144021441214422144321444214452144621447214482144921450214512145221453214542145521456214572145821459214602146121462214632146421465214662146721468214692147021471214722147321474214752147621477214782147921480214812148221483214842148521486214872148821489214902149121492214932149421495214962149721498214992150021501215022150321504215052150621507215082150921510215112151221513215142151521516215172151821519215202152121522215232152421525215262152721528215292153021531215322153321534215352153621537215382153921540215412154221543215442154521546215472154821549215502155121552215532155421555215562155721558215592156021561215622156321564215652156621567215682156921570215712157221573215742157521576215772157821579215802158121582215832158421585215862158721588215892159021591215922159321594215952159621597215982159921600216012160221603216042160521606216072160821609216102161121612216132161421615216162161721618216192162021621216222162321624216252162621627216282162921630216312163221633216342163521636216372163821639216402164121642216432164421645216462164721648216492165021651216522165321654216552165621657216582165921660216612166221663216642166521666216672166821669216702167121672216732167421675216762167721678216792168021681216822168321684216852168621687216882168921690216912169221693216942169521696216972169821699217002170121702217032170421705217062170721708217092171021711217122171321714217152171621717217182171921720217212172221723217242172521726217272172821729217302173121732217332173421735217362173721738217392174021741217422174321744217452174621747217482174921750217512175221753217542175521756217572175821759217602176121762217632176421765217662176721768217692177021771217722177321774217752177621777217782177921780217812178221783217842178521786217872178821789217902179121792217932179421795
  1. /** Converse.js
  2. *
  3. * An XMPP chat client that runs in the browser.
  4. *
  5. * Version: 3.2.0-rc
  6. */
  7. /* jshint ignore:start */
  8. (function (root, factory) {
  9. if (typeof define === 'function' && define.amd) {
  10. //Allow using this built library as an AMD module
  11. //in another project. That other project will only
  12. //see this AMD call, not the internal modules in
  13. //the closure below.
  14. define([], factory);
  15. } else {
  16. //Browser globals case.
  17. root.converse = factory();
  18. }
  19. }(this, function () {
  20. //almond, and your modules will be inlined here
  21. /* jshint ignore:end */
  22. /**
  23. * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
  24. * Released under MIT license, http://github.com/requirejs/almond/LICENSE
  25. */
  26. //Going sloppy to avoid 'use strict' string cost, but strict practices should
  27. //be followed.
  28. /*global setTimeout: false */
  29. var requirejs, require, define;
  30. (function (undef) {
  31. var main, req, makeMap, handlers,
  32. defined = {},
  33. waiting = {},
  34. config = {},
  35. defining = {},
  36. hasOwn = Object.prototype.hasOwnProperty,
  37. aps = [].slice,
  38. jsSuffixRegExp = /\.js$/;
  39. function hasProp(obj, prop) {
  40. return hasOwn.call(obj, prop);
  41. }
  42. /**
  43. * Given a relative module name, like ./something, normalize it to
  44. * a real name that can be mapped to a path.
  45. * @param {String} name the relative name
  46. * @param {String} baseName a real name that the name arg is relative
  47. * to.
  48. * @returns {String} normalized name
  49. */
  50. function normalize(name, baseName) {
  51. var nameParts, nameSegment, mapValue, foundMap, lastIndex,
  52. foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
  53. baseParts = baseName && baseName.split("/"),
  54. map = config.map,
  55. starMap = (map && map['*']) || {};
  56. //Adjust any relative paths.
  57. if (name) {
  58. name = name.split('/');
  59. lastIndex = name.length - 1;
  60. // If wanting node ID compatibility, strip .js from end
  61. // of IDs. Have to do this here, and not in nameToUrl
  62. // because node allows either .js or non .js to map
  63. // to same file.
  64. if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
  65. name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
  66. }
  67. // Starts with a '.' so need the baseName
  68. if (name[0].charAt(0) === '.' && baseParts) {
  69. //Convert baseName to array, and lop off the last part,
  70. //so that . matches that 'directory' and not name of the baseName's
  71. //module. For instance, baseName of 'one/two/three', maps to
  72. //'one/two/three.js', but we want the directory, 'one/two' for
  73. //this normalization.
  74. normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
  75. name = normalizedBaseParts.concat(name);
  76. }
  77. //start trimDots
  78. for (i = 0; i < name.length; i++) {
  79. part = name[i];
  80. if (part === '.') {
  81. name.splice(i, 1);
  82. i -= 1;
  83. } else if (part === '..') {
  84. // If at the start, or previous value is still ..,
  85. // keep them so that when converted to a path it may
  86. // still work when converted to a path, even though
  87. // as an ID it is less than ideal. In larger point
  88. // releases, may be better to just kick out an error.
  89. if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
  90. continue;
  91. } else if (i > 0) {
  92. name.splice(i - 1, 2);
  93. i -= 2;
  94. }
  95. }
  96. }
  97. //end trimDots
  98. name = name.join('/');
  99. }
  100. //Apply map config if available.
  101. if ((baseParts || starMap) && map) {
  102. nameParts = name.split('/');
  103. for (i = nameParts.length; i > 0; i -= 1) {
  104. nameSegment = nameParts.slice(0, i).join("/");
  105. if (baseParts) {
  106. //Find the longest baseName segment match in the config.
  107. //So, do joins on the biggest to smallest lengths of baseParts.
  108. for (j = baseParts.length; j > 0; j -= 1) {
  109. mapValue = map[baseParts.slice(0, j).join('/')];
  110. //baseName segment has config, find if it has one for
  111. //this name.
  112. if (mapValue) {
  113. mapValue = mapValue[nameSegment];
  114. if (mapValue) {
  115. //Match, update name to the new value.
  116. foundMap = mapValue;
  117. foundI = i;
  118. break;
  119. }
  120. }
  121. }
  122. }
  123. if (foundMap) {
  124. break;
  125. }
  126. //Check for a star map match, but just hold on to it,
  127. //if there is a shorter segment match later in a matching
  128. //config, then favor over this star map.
  129. if (!foundStarMap && starMap && starMap[nameSegment]) {
  130. foundStarMap = starMap[nameSegment];
  131. starI = i;
  132. }
  133. }
  134. if (!foundMap && foundStarMap) {
  135. foundMap = foundStarMap;
  136. foundI = starI;
  137. }
  138. if (foundMap) {
  139. nameParts.splice(0, foundI, foundMap);
  140. name = nameParts.join('/');
  141. }
  142. }
  143. return name;
  144. }
  145. function makeRequire(relName, forceSync) {
  146. return function () {
  147. //A version of a require function that passes a moduleName
  148. //value for items that may need to
  149. //look up paths relative to the moduleName
  150. var args = aps.call(arguments, 0);
  151. //If first arg is not require('string'), and there is only
  152. //one arg, it is the array form without a callback. Insert
  153. //a null so that the following concat is correct.
  154. if (typeof args[0] !== 'string' && args.length === 1) {
  155. args.push(null);
  156. }
  157. return req.apply(undef, args.concat([relName, forceSync]));
  158. };
  159. }
  160. function makeNormalize(relName) {
  161. return function (name) {
  162. return normalize(name, relName);
  163. };
  164. }
  165. function makeLoad(depName) {
  166. return function (value) {
  167. defined[depName] = value;
  168. };
  169. }
  170. function callDep(name) {
  171. if (hasProp(waiting, name)) {
  172. var args = waiting[name];
  173. delete waiting[name];
  174. defining[name] = true;
  175. main.apply(undef, args);
  176. }
  177. if (!hasProp(defined, name) && !hasProp(defining, name)) {
  178. throw new Error('No ' + name);
  179. }
  180. return defined[name];
  181. }
  182. //Turns a plugin!resource to [plugin, resource]
  183. //with the plugin being undefined if the name
  184. //did not have a plugin prefix.
  185. function splitPrefix(name) {
  186. var prefix,
  187. index = name ? name.indexOf('!') : -1;
  188. if (index > -1) {
  189. prefix = name.substring(0, index);
  190. name = name.substring(index + 1, name.length);
  191. }
  192. return [prefix, name];
  193. }
  194. //Creates a parts array for a relName where first part is plugin ID,
  195. //second part is resource ID. Assumes relName has already been normalized.
  196. function makeRelParts(relName) {
  197. return relName ? splitPrefix(relName) : [];
  198. }
  199. /**
  200. * Makes a name map, normalizing the name, and using a plugin
  201. * for normalization if necessary. Grabs a ref to plugin
  202. * too, as an optimization.
  203. */
  204. makeMap = function (name, relParts) {
  205. var plugin,
  206. parts = splitPrefix(name),
  207. prefix = parts[0],
  208. relResourceName = relParts[1];
  209. name = parts[1];
  210. if (prefix) {
  211. prefix = normalize(prefix, relResourceName);
  212. plugin = callDep(prefix);
  213. }
  214. //Normalize according
  215. if (prefix) {
  216. if (plugin && plugin.normalize) {
  217. name = plugin.normalize(name, makeNormalize(relResourceName));
  218. } else {
  219. name = normalize(name, relResourceName);
  220. }
  221. } else {
  222. name = normalize(name, relResourceName);
  223. parts = splitPrefix(name);
  224. prefix = parts[0];
  225. name = parts[1];
  226. if (prefix) {
  227. plugin = callDep(prefix);
  228. }
  229. }
  230. //Using ridiculous property names for space reasons
  231. return {
  232. f: prefix ? prefix + '!' + name : name, //fullName
  233. n: name,
  234. pr: prefix,
  235. p: plugin
  236. };
  237. };
  238. function makeConfig(name) {
  239. return function () {
  240. return (config && config.config && config.config[name]) || {};
  241. };
  242. }
  243. handlers = {
  244. require: function (name) {
  245. return makeRequire(name);
  246. },
  247. exports: function (name) {
  248. var e = defined[name];
  249. if (typeof e !== 'undefined') {
  250. return e;
  251. } else {
  252. return (defined[name] = {});
  253. }
  254. },
  255. module: function (name) {
  256. return {
  257. id: name,
  258. uri: '',
  259. exports: defined[name],
  260. config: makeConfig(name)
  261. };
  262. }
  263. };
  264. main = function (name, deps, callback, relName) {
  265. var cjsModule, depName, ret, map, i, relParts,
  266. args = [],
  267. callbackType = typeof callback,
  268. usingExports;
  269. //Use name if no relName
  270. relName = relName || name;
  271. relParts = makeRelParts(relName);
  272. //Call the callback to define the module, if necessary.
  273. if (callbackType === 'undefined' || callbackType === 'function') {
  274. //Pull out the defined dependencies and pass the ordered
  275. //values to the callback.
  276. //Default to [require, exports, module] if no deps
  277. deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
  278. for (i = 0; i < deps.length; i += 1) {
  279. map = makeMap(deps[i], relParts);
  280. depName = map.f;
  281. //Fast path CommonJS standard dependencies.
  282. if (depName === "require") {
  283. args[i] = handlers.require(name);
  284. } else if (depName === "exports") {
  285. //CommonJS module spec 1.1
  286. args[i] = handlers.exports(name);
  287. usingExports = true;
  288. } else if (depName === "module") {
  289. //CommonJS module spec 1.1
  290. cjsModule = args[i] = handlers.module(name);
  291. } else if (hasProp(defined, depName) ||
  292. hasProp(waiting, depName) ||
  293. hasProp(defining, depName)) {
  294. args[i] = callDep(depName);
  295. } else if (map.p) {
  296. map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
  297. args[i] = defined[depName];
  298. } else {
  299. throw new Error(name + ' missing ' + depName);
  300. }
  301. }
  302. ret = callback ? callback.apply(defined[name], args) : undefined;
  303. if (name) {
  304. //If setting exports via "module" is in play,
  305. //favor that over return value and exports. After that,
  306. //favor a non-undefined return value over exports use.
  307. if (cjsModule && cjsModule.exports !== undef &&
  308. cjsModule.exports !== defined[name]) {
  309. defined[name] = cjsModule.exports;
  310. } else if (ret !== undef || !usingExports) {
  311. //Use the return value from the function.
  312. defined[name] = ret;
  313. }
  314. }
  315. } else if (name) {
  316. //May just be an object definition for the module. Only
  317. //worry about defining if have a module name.
  318. defined[name] = callback;
  319. }
  320. };
  321. requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
  322. if (typeof deps === "string") {
  323. if (handlers[deps]) {
  324. //callback in this case is really relName
  325. return handlers[deps](callback);
  326. }
  327. //Just return the module wanted. In this scenario, the
  328. //deps arg is the module name, and second arg (if passed)
  329. //is just the relName.
  330. //Normalize module name, if it contains . or ..
  331. return callDep(makeMap(deps, makeRelParts(callback)).f);
  332. } else if (!deps.splice) {
  333. //deps is a config object, not an array.
  334. config = deps;
  335. if (config.deps) {
  336. req(config.deps, config.callback);
  337. }
  338. if (!callback) {
  339. return;
  340. }
  341. if (callback.splice) {
  342. //callback is an array, which means it is a dependency list.
  343. //Adjust args if there are dependencies
  344. deps = callback;
  345. callback = relName;
  346. relName = null;
  347. } else {
  348. deps = undef;
  349. }
  350. }
  351. //Support require(['a'])
  352. callback = callback || function () {};
  353. //If relName is a function, it is an errback handler,
  354. //so remove it.
  355. if (typeof relName === 'function') {
  356. relName = forceSync;
  357. forceSync = alt;
  358. }
  359. //Simulate async callback;
  360. if (forceSync) {
  361. main(undef, deps, callback, relName);
  362. } else {
  363. //Using a non-zero value because of concern for what old browsers
  364. //do, and latest browsers "upgrade" to 4 if lower value is used:
  365. //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
  366. //If want a value immediately, use require('id') instead -- something
  367. //that works in almond on the global level, but not guaranteed and
  368. //unlikely to work in other AMD implementations.
  369. setTimeout(function () {
  370. main(undef, deps, callback, relName);
  371. }, 4);
  372. }
  373. return req;
  374. };
  375. /**
  376. * Just drops the config on the floor, but returns req in case
  377. * the config return value is used.
  378. */
  379. req.config = function (cfg) {
  380. return req(cfg);
  381. };
  382. /**
  383. * Expose module registry for debugging and tooling
  384. */
  385. requirejs._defined = defined;
  386. define = function (name, deps, callback) {
  387. if (typeof name !== 'string') {
  388. throw new Error('See almond README: incorrect module build, no module name');
  389. }
  390. //This module may not have dependencies
  391. if (!deps.splice) {
  392. //deps is not an array, so probably means
  393. //an object literal or factory function for
  394. //the value. Adjust args.
  395. callback = deps;
  396. deps = [];
  397. }
  398. if (!hasProp(defined, name) && !hasProp(waiting, name)) {
  399. waiting[name] = [name, deps, callback];
  400. }
  401. };
  402. define.amd = {
  403. jQuery: true
  404. };
  405. }());
  406. define("almond", function(){});
  407. /*!
  408. * Sizzle CSS Selector Engine v2.2.1
  409. * http://sizzlejs.com/
  410. *
  411. * Copyright jQuery Foundation and other contributors
  412. * Released under the MIT license
  413. * http://jquery.org/license
  414. *
  415. * Date: 2015-10-17
  416. */
  417. (function( window ) {
  418. var i,
  419. support,
  420. Expr,
  421. getText,
  422. isXML,
  423. tokenize,
  424. compile,
  425. select,
  426. outermostContext,
  427. sortInput,
  428. hasDuplicate,
  429. // Local document vars
  430. setDocument,
  431. document,
  432. docElem,
  433. documentIsHTML,
  434. rbuggyQSA,
  435. rbuggyMatches,
  436. matches,
  437. contains,
  438. // Instance-specific data
  439. expando = "sizzle" + 1 * new Date(),
  440. preferredDoc = window.document,
  441. dirruns = 0,
  442. done = 0,
  443. classCache = createCache(),
  444. tokenCache = createCache(),
  445. compilerCache = createCache(),
  446. sortOrder = function( a, b ) {
  447. if ( a === b ) {
  448. hasDuplicate = true;
  449. }
  450. return 0;
  451. },
  452. // General-purpose constants
  453. MAX_NEGATIVE = 1 << 31,
  454. // Instance methods
  455. hasOwn = ({}).hasOwnProperty,
  456. arr = [],
  457. pop = arr.pop,
  458. push_native = arr.push,
  459. push = arr.push,
  460. slice = arr.slice,
  461. // Use a stripped-down indexOf as it's faster than native
  462. // http://jsperf.com/thor-indexof-vs-for/5
  463. indexOf = function( list, elem ) {
  464. var i = 0,
  465. len = list.length;
  466. for ( ; i < len; i++ ) {
  467. if ( list[i] === elem ) {
  468. return i;
  469. }
  470. }
  471. return -1;
  472. },
  473. booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
  474. // Regular expressions
  475. // http://www.w3.org/TR/css3-selectors/#whitespace
  476. whitespace = "[\\x20\\t\\r\\n\\f]",
  477. // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
  478. identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
  479. // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
  480. attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
  481. // Operator (capture 2)
  482. "*([*^$|!~]?=)" + whitespace +
  483. // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
  484. "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
  485. "*\\]",
  486. pseudos = ":(" + identifier + ")(?:\\((" +
  487. // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
  488. // 1. quoted (capture 3; capture 4 or capture 5)
  489. "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
  490. // 2. simple (capture 6)
  491. "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
  492. // 3. anything else (capture 2)
  493. ".*" +
  494. ")\\)|)",
  495. // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
  496. rwhitespace = new RegExp( whitespace + "+", "g" ),
  497. rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
  498. rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
  499. rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
  500. rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
  501. rpseudo = new RegExp( pseudos ),
  502. ridentifier = new RegExp( "^" + identifier + "$" ),
  503. matchExpr = {
  504. "ID": new RegExp( "^#(" + identifier + ")" ),
  505. "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
  506. "TAG": new RegExp( "^(" + identifier + "|[*])" ),
  507. "ATTR": new RegExp( "^" + attributes ),
  508. "PSEUDO": new RegExp( "^" + pseudos ),
  509. "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
  510. "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
  511. "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
  512. "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
  513. // For use in libraries implementing .is()
  514. // We use this for POS matching in `select`
  515. "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
  516. whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
  517. },
  518. rinputs = /^(?:input|select|textarea|button)$/i,
  519. rheader = /^h\d$/i,
  520. rnative = /^[^{]+\{\s*\[native \w/,
  521. // Easily-parseable/retrievable ID or TAG or CLASS selectors
  522. rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
  523. rsibling = /[+~]/,
  524. rescape = /'|\\/g,
  525. // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
  526. runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
  527. funescape = function( _, escaped, escapedWhitespace ) {
  528. var high = "0x" + escaped - 0x10000;
  529. // NaN means non-codepoint
  530. // Support: Firefox<24
  531. // Workaround erroneous numeric interpretation of +"0x"
  532. return high !== high || escapedWhitespace ?
  533. escaped :
  534. high < 0 ?
  535. // BMP codepoint
  536. String.fromCharCode( high + 0x10000 ) :
  537. // Supplemental Plane codepoint (surrogate pair)
  538. String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
  539. },
  540. // Used for iframes
  541. // See setDocument()
  542. // Removing the function wrapper causes a "Permission Denied"
  543. // error in IE
  544. unloadHandler = function() {
  545. setDocument();
  546. };
  547. // Optimize for push.apply( _, NodeList )
  548. try {
  549. push.apply(
  550. (arr = slice.call( preferredDoc.childNodes )),
  551. preferredDoc.childNodes
  552. );
  553. // Support: Android<4.0
  554. // Detect silently failing push.apply
  555. arr[ preferredDoc.childNodes.length ].nodeType;
  556. } catch ( e ) {
  557. push = { apply: arr.length ?
  558. // Leverage slice if possible
  559. function( target, els ) {
  560. push_native.apply( target, slice.call(els) );
  561. } :
  562. // Support: IE<9
  563. // Otherwise append directly
  564. function( target, els ) {
  565. var j = target.length,
  566. i = 0;
  567. // Can't trust NodeList.length
  568. while ( (target[j++] = els[i++]) ) {}
  569. target.length = j - 1;
  570. }
  571. };
  572. }
  573. function Sizzle( selector, context, results, seed ) {
  574. var m, i, elem, nid, nidselect, match, groups, newSelector,
  575. newContext = context && context.ownerDocument,
  576. // nodeType defaults to 9, since context defaults to document
  577. nodeType = context ? context.nodeType : 9;
  578. results = results || [];
  579. // Return early from calls with invalid selector or context
  580. if ( typeof selector !== "string" || !selector ||
  581. nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
  582. return results;
  583. }
  584. // Try to shortcut find operations (as opposed to filters) in HTML documents
  585. if ( !seed ) {
  586. if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
  587. setDocument( context );
  588. }
  589. context = context || document;
  590. if ( documentIsHTML ) {
  591. // If the selector is sufficiently simple, try using a "get*By*" DOM method
  592. // (excepting DocumentFragment context, where the methods don't exist)
  593. if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
  594. // ID selector
  595. if ( (m = match[1]) ) {
  596. // Document context
  597. if ( nodeType === 9 ) {
  598. if ( (elem = context.getElementById( m )) ) {
  599. // Support: IE, Opera, Webkit
  600. // TODO: identify versions
  601. // getElementById can match elements by name instead of ID
  602. if ( elem.id === m ) {
  603. results.push( elem );
  604. return results;
  605. }
  606. } else {
  607. return results;
  608. }
  609. // Element context
  610. } else {
  611. // Support: IE, Opera, Webkit
  612. // TODO: identify versions
  613. // getElementById can match elements by name instead of ID
  614. if ( newContext && (elem = newContext.getElementById( m )) &&
  615. contains( context, elem ) &&
  616. elem.id === m ) {
  617. results.push( elem );
  618. return results;
  619. }
  620. }
  621. // Type selector
  622. } else if ( match[2] ) {
  623. push.apply( results, context.getElementsByTagName( selector ) );
  624. return results;
  625. // Class selector
  626. } else if ( (m = match[3]) && support.getElementsByClassName &&
  627. context.getElementsByClassName ) {
  628. push.apply( results, context.getElementsByClassName( m ) );
  629. return results;
  630. }
  631. }
  632. // Take advantage of querySelectorAll
  633. if ( support.qsa &&
  634. !compilerCache[ selector + " " ] &&
  635. (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
  636. if ( nodeType !== 1 ) {
  637. newContext = context;
  638. newSelector = selector;
  639. // qSA looks outside Element context, which is not what we want
  640. // Thanks to Andrew Dupont for this workaround technique
  641. // Support: IE <=8
  642. // Exclude object elements
  643. } else if ( context.nodeName.toLowerCase() !== "object" ) {
  644. // Capture the context ID, setting it first if necessary
  645. if ( (nid = context.getAttribute( "id" )) ) {
  646. nid = nid.replace( rescape, "\\$&" );
  647. } else {
  648. context.setAttribute( "id", (nid = expando) );
  649. }
  650. // Prefix every selector in the list
  651. groups = tokenize( selector );
  652. i = groups.length;
  653. nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']";
  654. while ( i-- ) {
  655. groups[i] = nidselect + " " + toSelector( groups[i] );
  656. }
  657. newSelector = groups.join( "," );
  658. // Expand context for sibling selectors
  659. newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
  660. context;
  661. }
  662. if ( newSelector ) {
  663. try {
  664. push.apply( results,
  665. newContext.querySelectorAll( newSelector )
  666. );
  667. return results;
  668. } catch ( qsaError ) {
  669. } finally {
  670. if ( nid === expando ) {
  671. context.removeAttribute( "id" );
  672. }
  673. }
  674. }
  675. }
  676. }
  677. }
  678. // All others
  679. return select( selector.replace( rtrim, "$1" ), context, results, seed );
  680. }
  681. /**
  682. * Create key-value caches of limited size
  683. * @returns {function(string, object)} Returns the Object data after storing it on itself with
  684. * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
  685. * deleting the oldest entry
  686. */
  687. function createCache() {
  688. var keys = [];
  689. function cache( key, value ) {
  690. // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
  691. if ( keys.push( key + " " ) > Expr.cacheLength ) {
  692. // Only keep the most recent entries
  693. delete cache[ keys.shift() ];
  694. }
  695. return (cache[ key + " " ] = value);
  696. }
  697. return cache;
  698. }
  699. /**
  700. * Mark a function for special use by Sizzle
  701. * @param {Function} fn The function to mark
  702. */
  703. function markFunction( fn ) {
  704. fn[ expando ] = true;
  705. return fn;
  706. }
  707. /**
  708. * Support testing using an element
  709. * @param {Function} fn Passed the created div and expects a boolean result
  710. */
  711. function assert( fn ) {
  712. var div = document.createElement("div");
  713. try {
  714. return !!fn( div );
  715. } catch (e) {
  716. return false;
  717. } finally {
  718. // Remove from its parent by default
  719. if ( div.parentNode ) {
  720. div.parentNode.removeChild( div );
  721. }
  722. // release memory in IE
  723. div = null;
  724. }
  725. }
  726. /**
  727. * Adds the same handler for all of the specified attrs
  728. * @param {String} attrs Pipe-separated list of attributes
  729. * @param {Function} handler The method that will be applied
  730. */
  731. function addHandle( attrs, handler ) {
  732. var arr = attrs.split("|"),
  733. i = arr.length;
  734. while ( i-- ) {
  735. Expr.attrHandle[ arr[i] ] = handler;
  736. }
  737. }
  738. /**
  739. * Checks document order of two siblings
  740. * @param {Element} a
  741. * @param {Element} b
  742. * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
  743. */
  744. function siblingCheck( a, b ) {
  745. var cur = b && a,
  746. diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
  747. ( ~b.sourceIndex || MAX_NEGATIVE ) -
  748. ( ~a.sourceIndex || MAX_NEGATIVE );
  749. // Use IE sourceIndex if available on both nodes
  750. if ( diff ) {
  751. return diff;
  752. }
  753. // Check if b follows a
  754. if ( cur ) {
  755. while ( (cur = cur.nextSibling) ) {
  756. if ( cur === b ) {
  757. return -1;
  758. }
  759. }
  760. }
  761. return a ? 1 : -1;
  762. }
  763. /**
  764. * Returns a function to use in pseudos for input types
  765. * @param {String} type
  766. */
  767. function createInputPseudo( type ) {
  768. return function( elem ) {
  769. var name = elem.nodeName.toLowerCase();
  770. return name === "input" && elem.type === type;
  771. };
  772. }
  773. /**
  774. * Returns a function to use in pseudos for buttons
  775. * @param {String} type
  776. */
  777. function createButtonPseudo( type ) {
  778. return function( elem ) {
  779. var name = elem.nodeName.toLowerCase();
  780. return (name === "input" || name === "button") && elem.type === type;
  781. };
  782. }
  783. /**
  784. * Returns a function to use in pseudos for positionals
  785. * @param {Function} fn
  786. */
  787. function createPositionalPseudo( fn ) {
  788. return markFunction(function( argument ) {
  789. argument = +argument;
  790. return markFunction(function( seed, matches ) {
  791. var j,
  792. matchIndexes = fn( [], seed.length, argument ),
  793. i = matchIndexes.length;
  794. // Match elements found at the specified indexes
  795. while ( i-- ) {
  796. if ( seed[ (j = matchIndexes[i]) ] ) {
  797. seed[j] = !(matches[j] = seed[j]);
  798. }
  799. }
  800. });
  801. });
  802. }
  803. /**
  804. * Checks a node for validity as a Sizzle context
  805. * @param {Element|Object=} context
  806. * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
  807. */
  808. function testContext( context ) {
  809. return context && typeof context.getElementsByTagName !== "undefined" && context;
  810. }
  811. // Expose support vars for convenience
  812. support = Sizzle.support = {};
  813. /**
  814. * Detects XML nodes
  815. * @param {Element|Object} elem An element or a document
  816. * @returns {Boolean} True iff elem is a non-HTML XML node
  817. */
  818. isXML = Sizzle.isXML = function( elem ) {
  819. // documentElement is verified for cases where it doesn't yet exist
  820. // (such as loading iframes in IE - #4833)
  821. var documentElement = elem && (elem.ownerDocument || elem).documentElement;
  822. return documentElement ? documentElement.nodeName !== "HTML" : false;
  823. };
  824. /**
  825. * Sets document-related variables once based on the current document
  826. * @param {Element|Object} [doc] An element or document object to use to set the document
  827. * @returns {Object} Returns the current document
  828. */
  829. setDocument = Sizzle.setDocument = function( node ) {
  830. var hasCompare, parent,
  831. doc = node ? node.ownerDocument || node : preferredDoc;
  832. // Return early if doc is invalid or already selected
  833. if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
  834. return document;
  835. }
  836. // Update global variables
  837. document = doc;
  838. docElem = document.documentElement;
  839. documentIsHTML = !isXML( document );
  840. // Support: IE 9-11, Edge
  841. // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
  842. if ( (parent = document.defaultView) && parent.top !== parent ) {
  843. // Support: IE 11
  844. if ( parent.addEventListener ) {
  845. parent.addEventListener( "unload", unloadHandler, false );
  846. // Support: IE 9 - 10 only
  847. } else if ( parent.attachEvent ) {
  848. parent.attachEvent( "onunload", unloadHandler );
  849. }
  850. }
  851. /* Attributes
  852. ---------------------------------------------------------------------- */
  853. // Support: IE<8
  854. // Verify that getAttribute really returns attributes and not properties
  855. // (excepting IE8 booleans)
  856. support.attributes = assert(function( div ) {
  857. div.className = "i";
  858. return !div.getAttribute("className");
  859. });
  860. /* getElement(s)By*
  861. ---------------------------------------------------------------------- */
  862. // Check if getElementsByTagName("*") returns only elements
  863. support.getElementsByTagName = assert(function( div ) {
  864. div.appendChild( document.createComment("") );
  865. return !div.getElementsByTagName("*").length;
  866. });
  867. // Support: IE<9
  868. support.getElementsByClassName = rnative.test( document.getElementsByClassName );
  869. // Support: IE<10
  870. // Check if getElementById returns elements by name
  871. // The broken getElementById methods don't pick up programatically-set names,
  872. // so use a roundabout getElementsByName test
  873. support.getById = assert(function( div ) {
  874. docElem.appendChild( div ).id = expando;
  875. return !document.getElementsByName || !document.getElementsByName( expando ).length;
  876. });
  877. // ID find and filter
  878. if ( support.getById ) {
  879. Expr.find["ID"] = function( id, context ) {
  880. if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
  881. var m = context.getElementById( id );
  882. return m ? [ m ] : [];
  883. }
  884. };
  885. Expr.filter["ID"] = function( id ) {
  886. var attrId = id.replace( runescape, funescape );
  887. return function( elem ) {
  888. return elem.getAttribute("id") === attrId;
  889. };
  890. };
  891. } else {
  892. // Support: IE6/7
  893. // getElementById is not reliable as a find shortcut
  894. delete Expr.find["ID"];
  895. Expr.filter["ID"] = function( id ) {
  896. var attrId = id.replace( runescape, funescape );
  897. return function( elem ) {
  898. var node = typeof elem.getAttributeNode !== "undefined" &&
  899. elem.getAttributeNode("id");
  900. return node && node.value === attrId;
  901. };
  902. };
  903. }
  904. // Tag
  905. Expr.find["TAG"] = support.getElementsByTagName ?
  906. function( tag, context ) {
  907. if ( typeof context.getElementsByTagName !== "undefined" ) {
  908. return context.getElementsByTagName( tag );
  909. // DocumentFragment nodes don't have gEBTN
  910. } else if ( support.qsa ) {
  911. return context.querySelectorAll( tag );
  912. }
  913. } :
  914. function( tag, context ) {
  915. var elem,
  916. tmp = [],
  917. i = 0,
  918. // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
  919. results = context.getElementsByTagName( tag );
  920. // Filter out possible comments
  921. if ( tag === "*" ) {
  922. while ( (elem = results[i++]) ) {
  923. if ( elem.nodeType === 1 ) {
  924. tmp.push( elem );
  925. }
  926. }
  927. return tmp;
  928. }
  929. return results;
  930. };
  931. // Class
  932. Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
  933. if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
  934. return context.getElementsByClassName( className );
  935. }
  936. };
  937. /* QSA/matchesSelector
  938. ---------------------------------------------------------------------- */
  939. // QSA and matchesSelector support
  940. // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
  941. rbuggyMatches = [];
  942. // qSa(:focus) reports false when true (Chrome 21)
  943. // We allow this because of a bug in IE8/9 that throws an error
  944. // whenever `document.activeElement` is accessed on an iframe
  945. // So, we allow :focus to pass through QSA all the time to avoid the IE error
  946. // See http://bugs.jquery.com/ticket/13378
  947. rbuggyQSA = [];
  948. if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
  949. // Build QSA regex
  950. // Regex strategy adopted from Diego Perini
  951. assert(function( div ) {
  952. // Select is set to empty string on purpose
  953. // This is to test IE's treatment of not explicitly
  954. // setting a boolean content attribute,
  955. // since its presence should be enough
  956. // http://bugs.jquery.com/ticket/12359
  957. docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
  958. "<select id='" + expando + "-\r\\' msallowcapture=''>" +
  959. "<option selected=''></option></select>";
  960. // Support: IE8, Opera 11-12.16
  961. // Nothing should be selected when empty strings follow ^= or $= or *=
  962. // The test attribute must be unknown in Opera but "safe" for WinRT
  963. // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
  964. if ( div.querySelectorAll("[msallowcapture^='']").length ) {
  965. rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
  966. }
  967. // Support: IE8
  968. // Boolean attributes and "value" are not treated correctly
  969. if ( !div.querySelectorAll("[selected]").length ) {
  970. rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
  971. }
  972. // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
  973. if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
  974. rbuggyQSA.push("~=");
  975. }
  976. // Webkit/Opera - :checked should return selected option elements
  977. // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  978. // IE8 throws error here and will not see later tests
  979. if ( !div.querySelectorAll(":checked").length ) {
  980. rbuggyQSA.push(":checked");
  981. }
  982. // Support: Safari 8+, iOS 8+
  983. // https://bugs.webkit.org/show_bug.cgi?id=136851
  984. // In-page `selector#id sibing-combinator selector` fails
  985. if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
  986. rbuggyQSA.push(".#.+[+~]");
  987. }
  988. });
  989. assert(function( div ) {
  990. // Support: Windows 8 Native Apps
  991. // The type and name attributes are restricted during .innerHTML assignment
  992. var input = document.createElement("input");
  993. input.setAttribute( "type", "hidden" );
  994. div.appendChild( input ).setAttribute( "name", "D" );
  995. // Support: IE8
  996. // Enforce case-sensitivity of name attribute
  997. if ( div.querySelectorAll("[name=d]").length ) {
  998. rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
  999. }
  1000. // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
  1001. // IE8 throws error here and will not see later tests
  1002. if ( !div.querySelectorAll(":enabled").length ) {
  1003. rbuggyQSA.push( ":enabled", ":disabled" );
  1004. }
  1005. // Opera 10-11 does not throw on post-comma invalid pseudos
  1006. div.querySelectorAll("*,:x");
  1007. rbuggyQSA.push(",.*:");
  1008. });
  1009. }
  1010. if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
  1011. docElem.webkitMatchesSelector ||
  1012. docElem.mozMatchesSelector ||
  1013. docElem.oMatchesSelector ||
  1014. docElem.msMatchesSelector) )) ) {
  1015. assert(function( div ) {
  1016. // Check to see if it's possible to do matchesSelector
  1017. // on a disconnected node (IE 9)
  1018. support.disconnectedMatch = matches.call( div, "div" );
  1019. // This should fail with an exception
  1020. // Gecko does not error, returns false instead
  1021. matches.call( div, "[s!='']:x" );
  1022. rbuggyMatches.push( "!=", pseudos );
  1023. });
  1024. }
  1025. rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
  1026. rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
  1027. /* Contains
  1028. ---------------------------------------------------------------------- */
  1029. hasCompare = rnative.test( docElem.compareDocumentPosition );
  1030. // Element contains another
  1031. // Purposefully self-exclusive
  1032. // As in, an element does not contain itself
  1033. contains = hasCompare || rnative.test( docElem.contains ) ?
  1034. function( a, b ) {
  1035. var adown = a.nodeType === 9 ? a.documentElement : a,
  1036. bup = b && b.parentNode;
  1037. return a === bup || !!( bup && bup.nodeType === 1 && (
  1038. adown.contains ?
  1039. adown.contains( bup ) :
  1040. a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
  1041. ));
  1042. } :
  1043. function( a, b ) {
  1044. if ( b ) {
  1045. while ( (b = b.parentNode) ) {
  1046. if ( b === a ) {
  1047. return true;
  1048. }
  1049. }
  1050. }
  1051. return false;
  1052. };
  1053. /* Sorting
  1054. ---------------------------------------------------------------------- */
  1055. // Document order sorting
  1056. sortOrder = hasCompare ?
  1057. function( a, b ) {
  1058. // Flag for duplicate removal
  1059. if ( a === b ) {
  1060. hasDuplicate = true;
  1061. return 0;
  1062. }
  1063. // Sort on method existence if only one input has compareDocumentPosition
  1064. var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
  1065. if ( compare ) {
  1066. return compare;
  1067. }
  1068. // Calculate position if both inputs belong to the same document
  1069. compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
  1070. a.compareDocumentPosition( b ) :
  1071. // Otherwise we know they are disconnected
  1072. 1;
  1073. // Disconnected nodes
  1074. if ( compare & 1 ||
  1075. (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
  1076. // Choose the first element that is related to our preferred document
  1077. if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
  1078. return -1;
  1079. }
  1080. if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
  1081. return 1;
  1082. }
  1083. // Maintain original order
  1084. return sortInput ?
  1085. ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  1086. 0;
  1087. }
  1088. return compare & 4 ? -1 : 1;
  1089. } :
  1090. function( a, b ) {
  1091. // Exit early if the nodes are identical
  1092. if ( a === b ) {
  1093. hasDuplicate = true;
  1094. return 0;
  1095. }
  1096. var cur,
  1097. i = 0,
  1098. aup = a.parentNode,
  1099. bup = b.parentNode,
  1100. ap = [ a ],
  1101. bp = [ b ];
  1102. // Parentless nodes are either documents or disconnected
  1103. if ( !aup || !bup ) {
  1104. return a === document ? -1 :
  1105. b === document ? 1 :
  1106. aup ? -1 :
  1107. bup ? 1 :
  1108. sortInput ?
  1109. ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
  1110. 0;
  1111. // If the nodes are siblings, we can do a quick check
  1112. } else if ( aup === bup ) {
  1113. return siblingCheck( a, b );
  1114. }
  1115. // Otherwise we need full lists of their ancestors for comparison
  1116. cur = a;
  1117. while ( (cur = cur.parentNode) ) {
  1118. ap.unshift( cur );
  1119. }
  1120. cur = b;
  1121. while ( (cur = cur.parentNode) ) {
  1122. bp.unshift( cur );
  1123. }
  1124. // Walk down the tree looking for a discrepancy
  1125. while ( ap[i] === bp[i] ) {
  1126. i++;
  1127. }
  1128. return i ?
  1129. // Do a sibling check if the nodes have a common ancestor
  1130. siblingCheck( ap[i], bp[i] ) :
  1131. // Otherwise nodes in our document sort first
  1132. ap[i] === preferredDoc ? -1 :
  1133. bp[i] === preferredDoc ? 1 :
  1134. 0;
  1135. };
  1136. return document;
  1137. };
  1138. Sizzle.matches = function( expr, elements ) {
  1139. return Sizzle( expr, null, null, elements );
  1140. };
  1141. Sizzle.matchesSelector = function( elem, expr ) {
  1142. // Set document vars if needed
  1143. if ( ( elem.ownerDocument || elem ) !== document ) {
  1144. setDocument( elem );
  1145. }
  1146. // Make sure that attribute selectors are quoted
  1147. expr = expr.replace( rattributeQuotes, "='$1']" );
  1148. if ( support.matchesSelector && documentIsHTML &&
  1149. !compilerCache[ expr + " " ] &&
  1150. ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
  1151. ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
  1152. try {
  1153. var ret = matches.call( elem, expr );
  1154. // IE 9's matchesSelector returns false on disconnected nodes
  1155. if ( ret || support.disconnectedMatch ||
  1156. // As well, disconnected nodes are said to be in a document
  1157. // fragment in IE 9
  1158. elem.document && elem.document.nodeType !== 11 ) {
  1159. return ret;
  1160. }
  1161. } catch (e) {}
  1162. }
  1163. return Sizzle( expr, document, null, [ elem ] ).length > 0;
  1164. };
  1165. Sizzle.contains = function( context, elem ) {
  1166. // Set document vars if needed
  1167. if ( ( context.ownerDocument || context ) !== document ) {
  1168. setDocument( context );
  1169. }
  1170. return contains( context, elem );
  1171. };
  1172. Sizzle.attr = function( elem, name ) {
  1173. // Set document vars if needed
  1174. if ( ( elem.ownerDocument || elem ) !== document ) {
  1175. setDocument( elem );
  1176. }
  1177. var fn = Expr.attrHandle[ name.toLowerCase() ],
  1178. // Don't get fooled by Object.prototype properties (jQuery #13807)
  1179. val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
  1180. fn( elem, name, !documentIsHTML ) :
  1181. undefined;
  1182. return val !== undefined ?
  1183. val :
  1184. support.attributes || !documentIsHTML ?
  1185. elem.getAttribute( name ) :
  1186. (val = elem.getAttributeNode(name)) && val.specified ?
  1187. val.value :
  1188. null;
  1189. };
  1190. Sizzle.error = function( msg ) {
  1191. throw new Error( "Syntax error, unrecognized expression: " + msg );
  1192. };
  1193. /**
  1194. * Document sorting and removing duplicates
  1195. * @param {ArrayLike} results
  1196. */
  1197. Sizzle.uniqueSort = function( results ) {
  1198. var elem,
  1199. duplicates = [],
  1200. j = 0,
  1201. i = 0;
  1202. // Unless we *know* we can detect duplicates, assume their presence
  1203. hasDuplicate = !support.detectDuplicates;
  1204. sortInput = !support.sortStable && results.slice( 0 );
  1205. results.sort( sortOrder );
  1206. if ( hasDuplicate ) {
  1207. while ( (elem = results[i++]) ) {
  1208. if ( elem === results[ i ] ) {
  1209. j = duplicates.push( i );
  1210. }
  1211. }
  1212. while ( j-- ) {
  1213. results.splice( duplicates[ j ], 1 );
  1214. }
  1215. }
  1216. // Clear input after sorting to release objects
  1217. // See https://github.com/jquery/sizzle/pull/225
  1218. sortInput = null;
  1219. return results;
  1220. };
  1221. /**
  1222. * Utility function for retrieving the text value of an array of DOM nodes
  1223. * @param {Array|Element} elem
  1224. */
  1225. getText = Sizzle.getText = function( elem ) {
  1226. var node,
  1227. ret = "",
  1228. i = 0,
  1229. nodeType = elem.nodeType;
  1230. if ( !nodeType ) {
  1231. // If no nodeType, this is expected to be an array
  1232. while ( (node = elem[i++]) ) {
  1233. // Do not traverse comment nodes
  1234. ret += getText( node );
  1235. }
  1236. } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
  1237. // Use textContent for elements
  1238. // innerText usage removed for consistency of new lines (jQuery #11153)
  1239. if ( typeof elem.textContent === "string" ) {
  1240. return elem.textContent;
  1241. } else {
  1242. // Traverse its children
  1243. for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  1244. ret += getText( elem );
  1245. }
  1246. }
  1247. } else if ( nodeType === 3 || nodeType === 4 ) {
  1248. return elem.nodeValue;
  1249. }
  1250. // Do not include comment or processing instruction nodes
  1251. return ret;
  1252. };
  1253. Expr = Sizzle.selectors = {
  1254. // Can be adjusted by the user
  1255. cacheLength: 50,
  1256. createPseudo: markFunction,
  1257. match: matchExpr,
  1258. attrHandle: {},
  1259. find: {},
  1260. relative: {
  1261. ">": { dir: "parentNode", first: true },
  1262. " ": { dir: "parentNode" },
  1263. "+": { dir: "previousSibling", first: true },
  1264. "~": { dir: "previousSibling" }
  1265. },
  1266. preFilter: {
  1267. "ATTR": function( match ) {
  1268. match[1] = match[1].replace( runescape, funescape );
  1269. // Move the given value to match[3] whether quoted or unquoted
  1270. match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
  1271. if ( match[2] === "~=" ) {
  1272. match[3] = " " + match[3] + " ";
  1273. }
  1274. return match.slice( 0, 4 );
  1275. },
  1276. "CHILD": function( match ) {
  1277. /* matches from matchExpr["CHILD"]
  1278. 1 type (only|nth|...)
  1279. 2 what (child|of-type)
  1280. 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
  1281. 4 xn-component of xn+y argument ([+-]?\d*n|)
  1282. 5 sign of xn-component
  1283. 6 x of xn-component
  1284. 7 sign of y-component
  1285. 8 y of y-component
  1286. */
  1287. match[1] = match[1].toLowerCase();
  1288. if ( match[1].slice( 0, 3 ) === "nth" ) {
  1289. // nth-* requires argument
  1290. if ( !match[3] ) {
  1291. Sizzle.error( match[0] );
  1292. }
  1293. // numeric x and y parameters for Expr.filter.CHILD
  1294. // remember that false/true cast respectively to 0/1
  1295. match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
  1296. match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
  1297. // other types prohibit arguments
  1298. } else if ( match[3] ) {
  1299. Sizzle.error( match[0] );
  1300. }
  1301. return match;
  1302. },
  1303. "PSEUDO": function( match ) {
  1304. var excess,
  1305. unquoted = !match[6] && match[2];
  1306. if ( matchExpr["CHILD"].test( match[0] ) ) {
  1307. return null;
  1308. }
  1309. // Accept quoted arguments as-is
  1310. if ( match[3] ) {
  1311. match[2] = match[4] || match[5] || "";
  1312. // Strip excess characters from unquoted arguments
  1313. } else if ( unquoted && rpseudo.test( unquoted ) &&
  1314. // Get excess from tokenize (recursively)
  1315. (excess = tokenize( unquoted, true )) &&
  1316. // advance to the next closing parenthesis
  1317. (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
  1318. // excess is a negative index
  1319. match[0] = match[0].slice( 0, excess );
  1320. match[2] = unquoted.slice( 0, excess );
  1321. }
  1322. // Return only captures needed by the pseudo filter method (type and argument)
  1323. return match.slice( 0, 3 );
  1324. }
  1325. },
  1326. filter: {
  1327. "TAG": function( nodeNameSelector ) {
  1328. var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
  1329. return nodeNameSelector === "*" ?
  1330. function() { return true; } :
  1331. function( elem ) {
  1332. return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
  1333. };
  1334. },
  1335. "CLASS": function( className ) {
  1336. var pattern = classCache[ className + " " ];
  1337. return pattern ||
  1338. (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
  1339. classCache( className, function( elem ) {
  1340. return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
  1341. });
  1342. },
  1343. "ATTR": function( name, operator, check ) {
  1344. return function( elem ) {
  1345. var result = Sizzle.attr( elem, name );
  1346. if ( result == null ) {
  1347. return operator === "!=";
  1348. }
  1349. if ( !operator ) {
  1350. return true;
  1351. }
  1352. result += "";
  1353. return operator === "=" ? result === check :
  1354. operator === "!=" ? result !== check :
  1355. operator === "^=" ? check && result.indexOf( check ) === 0 :
  1356. operator === "*=" ? check && result.indexOf( check ) > -1 :
  1357. operator === "$=" ? check && result.slice( -check.length ) === check :
  1358. operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
  1359. operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
  1360. false;
  1361. };
  1362. },
  1363. "CHILD": function( type, what, argument, first, last ) {
  1364. var simple = type.slice( 0, 3 ) !== "nth",
  1365. forward = type.slice( -4 ) !== "last",
  1366. ofType = what === "of-type";
  1367. return first === 1 && last === 0 ?
  1368. // Shortcut for :nth-*(n)
  1369. function( elem ) {
  1370. return !!elem.parentNode;
  1371. } :
  1372. function( elem, context, xml ) {
  1373. var cache, uniqueCache, outerCache, node, nodeIndex, start,
  1374. dir = simple !== forward ? "nextSibling" : "previousSibling",
  1375. parent = elem.parentNode,
  1376. name = ofType && elem.nodeName.toLowerCase(),
  1377. useCache = !xml && !ofType,
  1378. diff = false;
  1379. if ( parent ) {
  1380. // :(first|last|only)-(child|of-type)
  1381. if ( simple ) {
  1382. while ( dir ) {
  1383. node = elem;
  1384. while ( (node = node[ dir ]) ) {
  1385. if ( ofType ?
  1386. node.nodeName.toLowerCase() === name :
  1387. node.nodeType === 1 ) {
  1388. return false;
  1389. }
  1390. }
  1391. // Reverse direction for :only-* (if we haven't yet done so)
  1392. start = dir = type === "only" && !start && "nextSibling";
  1393. }
  1394. return true;
  1395. }
  1396. start = [ forward ? parent.firstChild : parent.lastChild ];
  1397. // non-xml :nth-child(...) stores cache data on `parent`
  1398. if ( forward && useCache ) {
  1399. // Seek `elem` from a previously-cached index
  1400. // ...in a gzip-friendly way
  1401. node = parent;
  1402. outerCache = node[ expando ] || (node[ expando ] = {});
  1403. // Support: IE <9 only
  1404. // Defend against cloned attroperties (jQuery gh-1709)
  1405. uniqueCache = outerCache[ node.uniqueID ] ||
  1406. (outerCache[ node.uniqueID ] = {});
  1407. cache = uniqueCache[ type ] || [];
  1408. nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
  1409. diff = nodeIndex && cache[ 2 ];
  1410. node = nodeIndex && parent.childNodes[ nodeIndex ];
  1411. while ( (node = ++nodeIndex && node && node[ dir ] ||
  1412. // Fallback to seeking `elem` from the start
  1413. (diff = nodeIndex = 0) || start.pop()) ) {
  1414. // When found, cache indexes on `parent` and break
  1415. if ( node.nodeType === 1 && ++diff && node === elem ) {
  1416. uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
  1417. break;
  1418. }
  1419. }
  1420. } else {
  1421. // Use previously-cached element index if available
  1422. if ( useCache ) {
  1423. // ...in a gzip-friendly way
  1424. node = elem;
  1425. outerCache = node[ expando ] || (node[ expando ] = {});
  1426. // Support: IE <9 only
  1427. // Defend against cloned attroperties (jQuery gh-1709)
  1428. uniqueCache = outerCache[ node.uniqueID ] ||
  1429. (outerCache[ node.uniqueID ] = {});
  1430. cache = uniqueCache[ type ] || [];
  1431. nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
  1432. diff = nodeIndex;
  1433. }
  1434. // xml :nth-child(...)
  1435. // or :nth-last-child(...) or :nth(-last)?-of-type(...)
  1436. if ( diff === false ) {
  1437. // Use the same loop as above to seek `elem` from the start
  1438. while ( (node = ++nodeIndex && node && node[ dir ] ||
  1439. (diff = nodeIndex = 0) || start.pop()) ) {
  1440. if ( ( ofType ?
  1441. node.nodeName.toLowerCase() === name :
  1442. node.nodeType === 1 ) &&
  1443. ++diff ) {
  1444. // Cache the index of each encountered element
  1445. if ( useCache ) {
  1446. outerCache = node[ expando ] || (node[ expando ] = {});
  1447. // Support: IE <9 only
  1448. // Defend against cloned attroperties (jQuery gh-1709)
  1449. uniqueCache = outerCache[ node.uniqueID ] ||
  1450. (outerCache[ node.uniqueID ] = {});
  1451. uniqueCache[ type ] = [ dirruns, diff ];
  1452. }
  1453. if ( node === elem ) {
  1454. break;
  1455. }
  1456. }
  1457. }
  1458. }
  1459. }
  1460. // Incorporate the offset, then check against cycle size
  1461. diff -= last;
  1462. return diff === first || ( diff % first === 0 && diff / first >= 0 );
  1463. }
  1464. };
  1465. },
  1466. "PSEUDO": function( pseudo, argument ) {
  1467. // pseudo-class names are case-insensitive
  1468. // http://www.w3.org/TR/selectors/#pseudo-classes
  1469. // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
  1470. // Remember that setFilters inherits from pseudos
  1471. var args,
  1472. fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
  1473. Sizzle.error( "unsupported pseudo: " + pseudo );
  1474. // The user may use createPseudo to indicate that
  1475. // arguments are needed to create the filter function
  1476. // just as Sizzle does
  1477. if ( fn[ expando ] ) {
  1478. return fn( argument );
  1479. }
  1480. // But maintain support for old signatures
  1481. if ( fn.length > 1 ) {
  1482. args = [ pseudo, pseudo, "", argument ];
  1483. return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
  1484. markFunction(function( seed, matches ) {
  1485. var idx,
  1486. matched = fn( seed, argument ),
  1487. i = matched.length;
  1488. while ( i-- ) {
  1489. idx = indexOf( seed, matched[i] );
  1490. seed[ idx ] = !( matches[ idx ] = matched[i] );
  1491. }
  1492. }) :
  1493. function( elem ) {
  1494. return fn( elem, 0, args );
  1495. };
  1496. }
  1497. return fn;
  1498. }
  1499. },
  1500. pseudos: {
  1501. // Potentially complex pseudos
  1502. "not": markFunction(function( selector ) {
  1503. // Trim the selector passed to compile
  1504. // to avoid treating leading and trailing
  1505. // spaces as combinators
  1506. var input = [],
  1507. results = [],
  1508. matcher = compile( selector.replace( rtrim, "$1" ) );
  1509. return matcher[ expando ] ?
  1510. markFunction(function( seed, matches, context, xml ) {
  1511. var elem,
  1512. unmatched = matcher( seed, null, xml, [] ),
  1513. i = seed.length;
  1514. // Match elements unmatched by `matcher`
  1515. while ( i-- ) {
  1516. if ( (elem = unmatched[i]) ) {
  1517. seed[i] = !(matches[i] = elem);
  1518. }
  1519. }
  1520. }) :
  1521. function( elem, context, xml ) {
  1522. input[0] = elem;
  1523. matcher( input, null, xml, results );
  1524. // Don't keep the element (issue #299)
  1525. input[0] = null;
  1526. return !results.pop();
  1527. };
  1528. }),
  1529. "has": markFunction(function( selector ) {
  1530. return function( elem ) {
  1531. return Sizzle( selector, elem ).length > 0;
  1532. };
  1533. }),
  1534. "contains": markFunction(function( text ) {
  1535. text = text.replace( runescape, funescape );
  1536. return function( elem ) {
  1537. return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
  1538. };
  1539. }),
  1540. // "Whether an element is represented by a :lang() selector
  1541. // is based solely on the element's language value
  1542. // being equal to the identifier C,
  1543. // or beginning with the identifier C immediately followed by "-".
  1544. // The matching of C against the element's language value is performed case-insensitively.
  1545. // The identifier C does not have to be a valid language name."
  1546. // http://www.w3.org/TR/selectors/#lang-pseudo
  1547. "lang": markFunction( function( lang ) {
  1548. // lang value must be a valid identifier
  1549. if ( !ridentifier.test(lang || "") ) {
  1550. Sizzle.error( "unsupported lang: " + lang );
  1551. }
  1552. lang = lang.replace( runescape, funescape ).toLowerCase();
  1553. return function( elem ) {
  1554. var elemLang;
  1555. do {
  1556. if ( (elemLang = documentIsHTML ?
  1557. elem.lang :
  1558. elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
  1559. elemLang = elemLang.toLowerCase();
  1560. return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
  1561. }
  1562. } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
  1563. return false;
  1564. };
  1565. }),
  1566. // Miscellaneous
  1567. "target": function( elem ) {
  1568. var hash = window.location && window.location.hash;
  1569. return hash && hash.slice( 1 ) === elem.id;
  1570. },
  1571. "root": function( elem ) {
  1572. return elem === docElem;
  1573. },
  1574. "focus": function( elem ) {
  1575. return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
  1576. },
  1577. // Boolean properties
  1578. "enabled": function( elem ) {
  1579. return elem.disabled === false;
  1580. },
  1581. "disabled": function( elem ) {
  1582. return elem.disabled === true;
  1583. },
  1584. "checked": function( elem ) {
  1585. // In CSS3, :checked should return both checked and selected elements
  1586. // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
  1587. var nodeName = elem.nodeName.toLowerCase();
  1588. return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
  1589. },
  1590. "selected": function( elem ) {
  1591. // Accessing this property makes selected-by-default
  1592. // options in Safari work properly
  1593. if ( elem.parentNode ) {
  1594. elem.parentNode.selectedIndex;
  1595. }
  1596. return elem.selected === true;
  1597. },
  1598. // Contents
  1599. "empty": function( elem ) {
  1600. // http://www.w3.org/TR/selectors/#empty-pseudo
  1601. // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
  1602. // but not by others (comment: 8; processing instruction: 7; etc.)
  1603. // nodeType < 6 works because attributes (2) do not appear as children
  1604. for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
  1605. if ( elem.nodeType < 6 ) {
  1606. return false;
  1607. }
  1608. }
  1609. return true;
  1610. },
  1611. "parent": function( elem ) {
  1612. return !Expr.pseudos["empty"]( elem );
  1613. },
  1614. // Element/input types
  1615. "header": function( elem ) {
  1616. return rheader.test( elem.nodeName );
  1617. },
  1618. "input": function( elem ) {
  1619. return rinputs.test( elem.nodeName );
  1620. },
  1621. "button": function( elem ) {
  1622. var name = elem.nodeName.toLowerCase();
  1623. return name === "input" && elem.type === "button" || name === "button";
  1624. },
  1625. "text": function( elem ) {
  1626. var attr;
  1627. return elem.nodeName.toLowerCase() === "input" &&
  1628. elem.type === "text" &&
  1629. // Support: IE<8
  1630. // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
  1631. ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
  1632. },
  1633. // Position-in-collection
  1634. "first": createPositionalPseudo(function() {
  1635. return [ 0 ];
  1636. }),
  1637. "last": createPositionalPseudo(function( matchIndexes, length ) {
  1638. return [ length - 1 ];
  1639. }),
  1640. "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
  1641. return [ argument < 0 ? argument + length : argument ];
  1642. }),
  1643. "even": createPositionalPseudo(function( matchIndexes, length ) {
  1644. var i = 0;
  1645. for ( ; i < length; i += 2 ) {
  1646. matchIndexes.push( i );
  1647. }
  1648. return matchIndexes;
  1649. }),
  1650. "odd": createPositionalPseudo(function( matchIndexes, length ) {
  1651. var i = 1;
  1652. for ( ; i < length; i += 2 ) {
  1653. matchIndexes.push( i );
  1654. }
  1655. return matchIndexes;
  1656. }),
  1657. "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  1658. var i = argument < 0 ? argument + length : argument;
  1659. for ( ; --i >= 0; ) {
  1660. matchIndexes.push( i );
  1661. }
  1662. return matchIndexes;
  1663. }),
  1664. "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
  1665. var i = argument < 0 ? argument + length : argument;
  1666. for ( ; ++i < length; ) {
  1667. matchIndexes.push( i );
  1668. }
  1669. return matchIndexes;
  1670. })
  1671. }
  1672. };
  1673. Expr.pseudos["nth"] = Expr.pseudos["eq"];
  1674. // Add button/input type pseudos
  1675. for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
  1676. Expr.pseudos[ i ] = createInputPseudo( i );
  1677. }
  1678. for ( i in { submit: true, reset: true } ) {
  1679. Expr.pseudos[ i ] = createButtonPseudo( i );
  1680. }
  1681. // Easy API for creating new setFilters
  1682. function setFilters() {}
  1683. setFilters.prototype = Expr.filters = Expr.pseudos;
  1684. Expr.setFilters = new setFilters();
  1685. tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
  1686. var matched, match, tokens, type,
  1687. soFar, groups, preFilters,
  1688. cached = tokenCache[ selector + " " ];
  1689. if ( cached ) {
  1690. return parseOnly ? 0 : cached.slice( 0 );
  1691. }
  1692. soFar = selector;
  1693. groups = [];
  1694. preFilters = Expr.preFilter;
  1695. while ( soFar ) {
  1696. // Comma and first run
  1697. if ( !matched || (match = rcomma.exec( soFar )) ) {
  1698. if ( match ) {
  1699. // Don't consume trailing commas as valid
  1700. soFar = soFar.slice( match[0].length ) || soFar;
  1701. }
  1702. groups.push( (tokens = []) );
  1703. }
  1704. matched = false;
  1705. // Combinators
  1706. if ( (match = rcombinators.exec( soFar )) ) {
  1707. matched = match.shift();
  1708. tokens.push({
  1709. value: matched,
  1710. // Cast descendant combinators to space
  1711. type: match[0].replace( rtrim, " " )
  1712. });
  1713. soFar = soFar.slice( matched.length );
  1714. }
  1715. // Filters
  1716. for ( type in Expr.filter ) {
  1717. if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
  1718. (match = preFilters[ type ]( match ))) ) {
  1719. matched = match.shift();
  1720. tokens.push({
  1721. value: matched,
  1722. type: type,
  1723. matches: match
  1724. });
  1725. soFar = soFar.slice( matched.length );
  1726. }
  1727. }
  1728. if ( !matched ) {
  1729. break;
  1730. }
  1731. }
  1732. // Return the length of the invalid excess
  1733. // if we're just parsing
  1734. // Otherwise, throw an error or return tokens
  1735. return parseOnly ?
  1736. soFar.length :
  1737. soFar ?
  1738. Sizzle.error( selector ) :
  1739. // Cache the tokens
  1740. tokenCache( selector, groups ).slice( 0 );
  1741. };
  1742. function toSelector( tokens ) {
  1743. var i = 0,
  1744. len = tokens.length,
  1745. selector = "";
  1746. for ( ; i < len; i++ ) {
  1747. selector += tokens[i].value;
  1748. }
  1749. return selector;
  1750. }
  1751. function addCombinator( matcher, combinator, base ) {
  1752. var dir = combinator.dir,
  1753. checkNonElements = base && dir === "parentNode",
  1754. doneName = done++;
  1755. return combinator.first ?
  1756. // Check against closest ancestor/preceding element
  1757. function( elem, context, xml ) {
  1758. while ( (elem = elem[ dir ]) ) {
  1759. if ( elem.nodeType === 1 || checkNonElements ) {
  1760. return matcher( elem, context, xml );
  1761. }
  1762. }
  1763. } :
  1764. // Check against all ancestor/preceding elements
  1765. function( elem, context, xml ) {
  1766. var oldCache, uniqueCache, outerCache,
  1767. newCache = [ dirruns, doneName ];
  1768. // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
  1769. if ( xml ) {
  1770. while ( (elem = elem[ dir ]) ) {
  1771. if ( elem.nodeType === 1 || checkNonElements ) {
  1772. if ( matcher( elem, context, xml ) ) {
  1773. return true;
  1774. }
  1775. }
  1776. }
  1777. } else {
  1778. while ( (elem = elem[ dir ]) ) {
  1779. if ( elem.nodeType === 1 || checkNonElements ) {
  1780. outerCache = elem[ expando ] || (elem[ expando ] = {});
  1781. // Support: IE <9 only
  1782. // Defend against cloned attroperties (jQuery gh-1709)
  1783. uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
  1784. if ( (oldCache = uniqueCache[ dir ]) &&
  1785. oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
  1786. // Assign to newCache so results back-propagate to previous elements
  1787. return (newCache[ 2 ] = oldCache[ 2 ]);
  1788. } else {
  1789. // Reuse newcache so results back-propagate to previous elements
  1790. uniqueCache[ dir ] = newCache;
  1791. // A match means we're done; a fail means we have to keep checking
  1792. if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
  1793. return true;
  1794. }
  1795. }
  1796. }
  1797. }
  1798. }
  1799. };
  1800. }
  1801. function elementMatcher( matchers ) {
  1802. return matchers.length > 1 ?
  1803. function( elem, context, xml ) {
  1804. var i = matchers.length;
  1805. while ( i-- ) {
  1806. if ( !matchers[i]( elem, context, xml ) ) {
  1807. return false;
  1808. }
  1809. }
  1810. return true;
  1811. } :
  1812. matchers[0];
  1813. }
  1814. function multipleContexts( selector, contexts, results ) {
  1815. var i = 0,
  1816. len = contexts.length;
  1817. for ( ; i < len; i++ ) {
  1818. Sizzle( selector, contexts[i], results );
  1819. }
  1820. return results;
  1821. }
  1822. function condense( unmatched, map, filter, context, xml ) {
  1823. var elem,
  1824. newUnmatched = [],
  1825. i = 0,
  1826. len = unmatched.length,
  1827. mapped = map != null;
  1828. for ( ; i < len; i++ ) {
  1829. if ( (elem = unmatched[i]) ) {
  1830. if ( !filter || filter( elem, context, xml ) ) {
  1831. newUnmatched.push( elem );
  1832. if ( mapped ) {
  1833. map.push( i );
  1834. }
  1835. }
  1836. }
  1837. }
  1838. return newUnmatched;
  1839. }
  1840. function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
  1841. if ( postFilter && !postFilter[ expando ] ) {
  1842. postFilter = setMatcher( postFilter );
  1843. }
  1844. if ( postFinder && !postFinder[ expando ] ) {
  1845. postFinder = setMatcher( postFinder, postSelector );
  1846. }
  1847. return markFunction(function( seed, results, context, xml ) {
  1848. var temp, i, elem,
  1849. preMap = [],
  1850. postMap = [],
  1851. preexisting = results.length,
  1852. // Get initial elements from seed or context
  1853. elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
  1854. // Prefilter to get matcher input, preserving a map for seed-results synchronization
  1855. matcherIn = preFilter && ( seed || !selector ) ?
  1856. condense( elems, preMap, preFilter, context, xml ) :
  1857. elems,
  1858. matcherOut = matcher ?
  1859. // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
  1860. postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
  1861. // ...intermediate processing is necessary
  1862. [] :
  1863. // ...otherwise use results directly
  1864. results :
  1865. matcherIn;
  1866. // Find primary matches
  1867. if ( matcher ) {
  1868. matcher( matcherIn, matcherOut, context, xml );
  1869. }
  1870. // Apply postFilter
  1871. if ( postFilter ) {
  1872. temp = condense( matcherOut, postMap );
  1873. postFilter( temp, [], context, xml );
  1874. // Un-match failing elements by moving them back to matcherIn
  1875. i = temp.length;
  1876. while ( i-- ) {
  1877. if ( (elem = temp[i]) ) {
  1878. matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
  1879. }
  1880. }
  1881. }
  1882. if ( seed ) {
  1883. if ( postFinder || preFilter ) {
  1884. if ( postFinder ) {
  1885. // Get the final matcherOut by condensing this intermediate into postFinder contexts
  1886. temp = [];
  1887. i = matcherOut.length;
  1888. while ( i-- ) {
  1889. if ( (elem = matcherOut[i]) ) {
  1890. // Restore matcherIn since elem is not yet a final match
  1891. temp.push( (matcherIn[i] = elem) );
  1892. }
  1893. }
  1894. postFinder( null, (matcherOut = []), temp, xml );
  1895. }
  1896. // Move matched elements from seed to results to keep them synchronized
  1897. i = matcherOut.length;
  1898. while ( i-- ) {
  1899. if ( (elem = matcherOut[i]) &&
  1900. (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
  1901. seed[temp] = !(results[temp] = elem);
  1902. }
  1903. }
  1904. }
  1905. // Add elements to results, through postFinder if defined
  1906. } else {
  1907. matcherOut = condense(
  1908. matcherOut === results ?
  1909. matcherOut.splice( preexisting, matcherOut.length ) :
  1910. matcherOut
  1911. );
  1912. if ( postFinder ) {
  1913. postFinder( null, results, matcherOut, xml );
  1914. } else {
  1915. push.apply( results, matcherOut );
  1916. }
  1917. }
  1918. });
  1919. }
  1920. function matcherFromTokens( tokens ) {
  1921. var checkContext, matcher, j,
  1922. len = tokens.length,
  1923. leadingRelative = Expr.relative[ tokens[0].type ],
  1924. implicitRelative = leadingRelative || Expr.relative[" "],
  1925. i = leadingRelative ? 1 : 0,
  1926. // The foundational matcher ensures that elements are reachable from top-level context(s)
  1927. matchContext = addCombinator( function( elem ) {
  1928. return elem === checkContext;
  1929. }, implicitRelative, true ),
  1930. matchAnyContext = addCombinator( function( elem ) {
  1931. return indexOf( checkContext, elem ) > -1;
  1932. }, implicitRelative, true ),
  1933. matchers = [ function( elem, context, xml ) {
  1934. var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
  1935. (checkContext = context).nodeType ?
  1936. matchContext( elem, context, xml ) :
  1937. matchAnyContext( elem, context, xml ) );
  1938. // Avoid hanging onto element (issue #299)
  1939. checkContext = null;
  1940. return ret;
  1941. } ];
  1942. for ( ; i < len; i++ ) {
  1943. if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
  1944. matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
  1945. } else {
  1946. matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
  1947. // Return special upon seeing a positional matcher
  1948. if ( matcher[ expando ] ) {
  1949. // Find the next relative operator (if any) for proper handling
  1950. j = ++i;
  1951. for ( ; j < len; j++ ) {
  1952. if ( Expr.relative[ tokens[j].type ] ) {
  1953. break;
  1954. }
  1955. }
  1956. return setMatcher(
  1957. i > 1 && elementMatcher( matchers ),
  1958. i > 1 && toSelector(
  1959. // If the preceding token was a descendant combinator, insert an implicit any-element `*`
  1960. tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
  1961. ).replace( rtrim, "$1" ),
  1962. matcher,
  1963. i < j && matcherFromTokens( tokens.slice( i, j ) ),
  1964. j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
  1965. j < len && toSelector( tokens )
  1966. );
  1967. }
  1968. matchers.push( matcher );
  1969. }
  1970. }
  1971. return elementMatcher( matchers );
  1972. }
  1973. function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
  1974. var bySet = setMatchers.length > 0,
  1975. byElement = elementMatchers.length > 0,
  1976. superMatcher = function( seed, context, xml, results, outermost ) {
  1977. var elem, j, matcher,
  1978. matchedCount = 0,
  1979. i = "0",
  1980. unmatched = seed && [],
  1981. setMatched = [],
  1982. contextBackup = outermostContext,
  1983. // We must always have either seed elements or outermost context
  1984. elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
  1985. // Use integer dirruns iff this is the outermost matcher
  1986. dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
  1987. len = elems.length;
  1988. if ( outermost ) {
  1989. outermostContext = context === document || context || outermost;
  1990. }
  1991. // Add elements passing elementMatchers directly to results
  1992. // Support: IE<9, Safari
  1993. // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
  1994. for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
  1995. if ( byElement && elem ) {
  1996. j = 0;
  1997. if ( !context && elem.ownerDocument !== document ) {
  1998. setDocument( elem );
  1999. xml = !documentIsHTML;
  2000. }
  2001. while ( (matcher = elementMatchers[j++]) ) {
  2002. if ( matcher( elem, context || document, xml) ) {
  2003. results.push( elem );
  2004. break;
  2005. }
  2006. }
  2007. if ( outermost ) {
  2008. dirruns = dirrunsUnique;
  2009. }
  2010. }
  2011. // Track unmatched elements for set filters
  2012. if ( bySet ) {
  2013. // They will have gone through all possible matchers
  2014. if ( (elem = !matcher && elem) ) {
  2015. matchedCount--;
  2016. }
  2017. // Lengthen the array for every element, matched or not
  2018. if ( seed ) {
  2019. unmatched.push( elem );
  2020. }
  2021. }
  2022. }
  2023. // `i` is now the count of elements visited above, and adding it to `matchedCount`
  2024. // makes the latter nonnegative.
  2025. matchedCount += i;
  2026. // Apply set filters to unmatched elements
  2027. // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
  2028. // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
  2029. // no element matchers and no seed.
  2030. // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
  2031. // case, which will result in a "00" `matchedCount` that differs from `i` but is also
  2032. // numerically zero.
  2033. if ( bySet && i !== matchedCount ) {
  2034. j = 0;
  2035. while ( (matcher = setMatchers[j++]) ) {
  2036. matcher( unmatched, setMatched, context, xml );
  2037. }
  2038. if ( seed ) {
  2039. // Reintegrate element matches to eliminate the need for sorting
  2040. if ( matchedCount > 0 ) {
  2041. while ( i-- ) {
  2042. if ( !(unmatched[i] || setMatched[i]) ) {
  2043. setMatched[i] = pop.call( results );
  2044. }
  2045. }
  2046. }
  2047. // Discard index placeholder values to get only actual matches
  2048. setMatched = condense( setMatched );
  2049. }
  2050. // Add matches to results
  2051. push.apply( results, setMatched );
  2052. // Seedless set matches succeeding multiple successful matchers stipulate sorting
  2053. if ( outermost && !seed && setMatched.length > 0 &&
  2054. ( matchedCount + setMatchers.length ) > 1 ) {
  2055. Sizzle.uniqueSort( results );
  2056. }
  2057. }
  2058. // Override manipulation of globals by nested matchers
  2059. if ( outermost ) {
  2060. dirruns = dirrunsUnique;
  2061. outermostContext = contextBackup;
  2062. }
  2063. return unmatched;
  2064. };
  2065. return bySet ?
  2066. markFunction( superMatcher ) :
  2067. superMatcher;
  2068. }
  2069. compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
  2070. var i,
  2071. setMatchers = [],
  2072. elementMatchers = [],
  2073. cached = compilerCache[ selector + " " ];
  2074. if ( !cached ) {
  2075. // Generate a function of recursive functions that can be used to check each element
  2076. if ( !match ) {
  2077. match = tokenize( selector );
  2078. }
  2079. i = match.length;
  2080. while ( i-- ) {
  2081. cached = matcherFromTokens( match[i] );
  2082. if ( cached[ expando ] ) {
  2083. setMatchers.push( cached );
  2084. } else {
  2085. elementMatchers.push( cached );
  2086. }
  2087. }
  2088. // Cache the compiled function
  2089. cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
  2090. // Save selector and tokenization
  2091. cached.selector = selector;
  2092. }
  2093. return cached;
  2094. };
  2095. /**
  2096. * A low-level selection function that works with Sizzle's compiled
  2097. * selector functions
  2098. * @param {String|Function} selector A selector or a pre-compiled
  2099. * selector function built with Sizzle.compile
  2100. * @param {Element} context
  2101. * @param {Array} [results]
  2102. * @param {Array} [seed] A set of elements to match against
  2103. */
  2104. select = Sizzle.select = function( selector, context, results, seed ) {
  2105. var i, tokens, token, type, find,
  2106. compiled = typeof selector === "function" && selector,
  2107. match = !seed && tokenize( (selector = compiled.selector || selector) );
  2108. results = results || [];
  2109. // Try to minimize operations if there is only one selector in the list and no seed
  2110. // (the latter of which guarantees us context)
  2111. if ( match.length === 1 ) {
  2112. // Reduce context if the leading compound selector is an ID
  2113. tokens = match[0] = match[0].slice( 0 );
  2114. if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
  2115. support.getById && context.nodeType === 9 && documentIsHTML &&
  2116. Expr.relative[ tokens[1].type ] ) {
  2117. context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
  2118. if ( !context ) {
  2119. return results;
  2120. // Precompiled matchers will still verify ancestry, so step up a level
  2121. } else if ( compiled ) {
  2122. context = context.parentNode;
  2123. }
  2124. selector = selector.slice( tokens.shift().value.length );
  2125. }
  2126. // Fetch a seed set for right-to-left matching
  2127. i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
  2128. while ( i-- ) {
  2129. token = tokens[i];
  2130. // Abort if we hit a combinator
  2131. if ( Expr.relative[ (type = token.type) ] ) {
  2132. break;
  2133. }
  2134. if ( (find = Expr.find[ type ]) ) {
  2135. // Search, expanding context for leading sibling combinators
  2136. if ( (seed = find(
  2137. token.matches[0].replace( runescape, funescape ),
  2138. rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
  2139. )) ) {
  2140. // If seed is empty or no tokens remain, we can return early
  2141. tokens.splice( i, 1 );
  2142. selector = seed.length && toSelector( tokens );
  2143. if ( !selector ) {
  2144. push.apply( results, seed );
  2145. return results;
  2146. }
  2147. break;
  2148. }
  2149. }
  2150. }
  2151. }
  2152. // Compile and execute a filtering function if one is not provided
  2153. // Provide `match` to avoid retokenization if we modified the selector above
  2154. ( compiled || compile( selector, match ) )(
  2155. seed,
  2156. context,
  2157. !documentIsHTML,
  2158. results,
  2159. !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
  2160. );
  2161. return results;
  2162. };
  2163. // One-time assignments
  2164. // Sort stability
  2165. support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
  2166. // Support: Chrome 14-35+
  2167. // Always assume duplicates if they aren't passed to the comparison function
  2168. support.detectDuplicates = !!hasDuplicate;
  2169. // Initialize against the default document
  2170. setDocument();
  2171. // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
  2172. // Detached nodes confoundingly follow *each other*
  2173. support.sortDetached = assert(function( div1 ) {
  2174. // Should return 1, but returns 4 (following)
  2175. return div1.compareDocumentPosition( document.createElement("div") ) & 1;
  2176. });
  2177. // Support: IE<8
  2178. // Prevent attribute/property "interpolation"
  2179. // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
  2180. if ( !assert(function( div ) {
  2181. div.innerHTML = "<a href='#'></a>";
  2182. return div.firstChild.getAttribute("href") === "#" ;
  2183. }) ) {
  2184. addHandle( "type|href|height|width", function( elem, name, isXML ) {
  2185. if ( !isXML ) {
  2186. return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
  2187. }
  2188. });
  2189. }
  2190. // Support: IE<9
  2191. // Use defaultValue in place of getAttribute("value")
  2192. if ( !support.attributes || !assert(function( div ) {
  2193. div.innerHTML = "<input/>";
  2194. div.firstChild.setAttribute( "value", "" );
  2195. return div.firstChild.getAttribute( "value" ) === "";
  2196. }) ) {
  2197. addHandle( "value", function( elem, name, isXML ) {
  2198. if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
  2199. return elem.defaultValue;
  2200. }
  2201. });
  2202. }
  2203. // Support: IE<9
  2204. // Use getAttributeNode to fetch booleans when getAttribute lies
  2205. if ( !assert(function( div ) {
  2206. return div.getAttribute("disabled") == null;
  2207. }) ) {
  2208. addHandle( booleans, function( elem, name, isXML ) {
  2209. var val;
  2210. if ( !isXML ) {
  2211. return elem[ name ] === true ? name.toLowerCase() :
  2212. (val = elem.getAttributeNode( name )) && val.specified ?
  2213. val.value :
  2214. null;
  2215. }
  2216. });
  2217. }
  2218. // EXPOSE
  2219. if ( typeof define === "function" && define.amd ) {
  2220. define('sizzle',[],function() { return Sizzle; });
  2221. // Sizzle requires that there be a global window in Common-JS like environments
  2222. } else if ( typeof module !== "undefined" && module.exports ) {
  2223. module.exports = Sizzle;
  2224. } else {
  2225. window.Sizzle = Sizzle;
  2226. }
  2227. // EXPOSE
  2228. })( window );
  2229. /*!
  2230. * @overview es6-promise - a tiny implementation of Promises/A+.
  2231. * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
  2232. * @license Licensed under MIT license
  2233. * See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
  2234. * @version 4.1.1
  2235. */
  2236. (function (global, factory) {
  2237. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  2238. typeof define === 'function' && define.amd ? define('es6-promise',factory) :
  2239. (global.ES6Promise = factory());
  2240. }(this, (function () { 'use strict';
  2241. function objectOrFunction(x) {
  2242. var type = typeof x;
  2243. return x !== null && (type === 'object' || type === 'function');
  2244. }
  2245. function isFunction(x) {
  2246. return typeof x === 'function';
  2247. }
  2248. var _isArray = undefined;
  2249. if (Array.isArray) {
  2250. _isArray = Array.isArray;
  2251. } else {
  2252. _isArray = function (x) {
  2253. return Object.prototype.toString.call(x) === '[object Array]';
  2254. };
  2255. }
  2256. var isArray = _isArray;
  2257. var len = 0;
  2258. var vertxNext = undefined;
  2259. var customSchedulerFn = undefined;
  2260. var asap = function asap(callback, arg) {
  2261. queue[len] = callback;
  2262. queue[len + 1] = arg;
  2263. len += 2;
  2264. if (len === 2) {
  2265. // If len is 2, that means that we need to schedule an async flush.
  2266. // If additional callbacks are queued before the queue is flushed, they
  2267. // will be processed by this flush that we are scheduling.
  2268. if (customSchedulerFn) {
  2269. customSchedulerFn(flush);
  2270. } else {
  2271. scheduleFlush();
  2272. }
  2273. }
  2274. };
  2275. function setScheduler(scheduleFn) {
  2276. customSchedulerFn = scheduleFn;
  2277. }
  2278. function setAsap(asapFn) {
  2279. asap = asapFn;
  2280. }
  2281. var browserWindow = typeof window !== 'undefined' ? window : undefined;
  2282. var browserGlobal = browserWindow || {};
  2283. var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;
  2284. var isNode = typeof self === 'undefined' && typeof process !== 'undefined' && ({}).toString.call(process) === '[object process]';
  2285. // test for web worker but not in IE10
  2286. var isWorker = typeof Uint8ClampedArray !== 'undefined' && typeof importScripts !== 'undefined' && typeof MessageChannel !== 'undefined';
  2287. // node
  2288. function useNextTick() {
  2289. // node version 0.10.x displays a deprecation warning when nextTick is used recursively
  2290. // see https://github.com/cujojs/when/issues/410 for details
  2291. return function () {
  2292. return process.nextTick(flush);
  2293. };
  2294. }
  2295. // vertx
  2296. function useVertxTimer() {
  2297. if (typeof vertxNext !== 'undefined') {
  2298. return function () {
  2299. vertxNext(flush);
  2300. };
  2301. }
  2302. return useSetTimeout();
  2303. }
  2304. function useMutationObserver() {
  2305. var iterations = 0;
  2306. var observer = new BrowserMutationObserver(flush);
  2307. var node = document.createTextNode('');
  2308. observer.observe(node, { characterData: true });
  2309. return function () {
  2310. node.data = iterations = ++iterations % 2;
  2311. };
  2312. }
  2313. // web worker
  2314. function useMessageChannel() {
  2315. var channel = new MessageChannel();
  2316. channel.port1.onmessage = flush;
  2317. return function () {
  2318. return channel.port2.postMessage(0);
  2319. };
  2320. }
  2321. function useSetTimeout() {
  2322. // Store setTimeout reference so es6-promise will be unaffected by
  2323. // other code modifying setTimeout (like sinon.useFakeTimers())
  2324. var globalSetTimeout = setTimeout;
  2325. return function () {
  2326. return globalSetTimeout(flush, 1);
  2327. };
  2328. }
  2329. var queue = new Array(1000);
  2330. function flush() {
  2331. for (var i = 0; i < len; i += 2) {
  2332. var callback = queue[i];
  2333. var arg = queue[i + 1];
  2334. callback(arg);
  2335. queue[i] = undefined;
  2336. queue[i + 1] = undefined;
  2337. }
  2338. len = 0;
  2339. }
  2340. function attemptVertx() {
  2341. try {
  2342. var r = require;
  2343. var vertx = r('vertx');
  2344. vertxNext = vertx.runOnLoop || vertx.runOnContext;
  2345. return useVertxTimer();
  2346. } catch (e) {
  2347. return useSetTimeout();
  2348. }
  2349. }
  2350. var scheduleFlush = undefined;
  2351. // Decide what async method to use to triggering processing of queued callbacks:
  2352. if (isNode) {
  2353. scheduleFlush = useNextTick();
  2354. } else if (BrowserMutationObserver) {
  2355. scheduleFlush = useMutationObserver();
  2356. } else if (isWorker) {
  2357. scheduleFlush = useMessageChannel();
  2358. } else if (browserWindow === undefined && typeof require === 'function') {
  2359. scheduleFlush = attemptVertx();
  2360. } else {
  2361. scheduleFlush = useSetTimeout();
  2362. }
  2363. function then(onFulfillment, onRejection) {
  2364. var _arguments = arguments;
  2365. var parent = this;
  2366. var child = new this.constructor(noop);
  2367. if (child[PROMISE_ID] === undefined) {
  2368. makePromise(child);
  2369. }
  2370. var _state = parent._state;
  2371. if (_state) {
  2372. (function () {
  2373. var callback = _arguments[_state - 1];
  2374. asap(function () {
  2375. return invokeCallback(_state, child, callback, parent._result);
  2376. });
  2377. })();
  2378. } else {
  2379. subscribe(parent, child, onFulfillment, onRejection);
  2380. }
  2381. return child;
  2382. }
  2383. /**
  2384. `Promise.resolve` returns a promise that will become resolved with the
  2385. passed `value`. It is shorthand for the following:
  2386. ```javascript
  2387. let promise = new Promise(function(resolve, reject){
  2388. resolve(1);
  2389. });
  2390. promise.then(function(value){
  2391. // value === 1
  2392. });
  2393. ```
  2394. Instead of writing the above, your code now simply becomes the following:
  2395. ```javascript
  2396. let promise = Promise.resolve(1);
  2397. promise.then(function(value){
  2398. // value === 1
  2399. });
  2400. ```
  2401. @method resolve
  2402. @static
  2403. @param {Any} value value that the returned promise will be resolved with
  2404. Useful for tooling.
  2405. @return {Promise} a promise that will become fulfilled with the given
  2406. `value`
  2407. */
  2408. function resolve$1(object) {
  2409. /*jshint validthis:true */
  2410. var Constructor = this;
  2411. if (object && typeof object === 'object' && object.constructor === Constructor) {
  2412. return object;
  2413. }
  2414. var promise = new Constructor(noop);
  2415. resolve(promise, object);
  2416. return promise;
  2417. }
  2418. var PROMISE_ID = Math.random().toString(36).substring(16);
  2419. function noop() {}
  2420. var PENDING = void 0;
  2421. var FULFILLED = 1;
  2422. var REJECTED = 2;
  2423. var GET_THEN_ERROR = new ErrorObject();
  2424. function selfFulfillment() {
  2425. return new TypeError("You cannot resolve a promise with itself");
  2426. }
  2427. function cannotReturnOwn() {
  2428. return new TypeError('A promises callback cannot return that same promise.');
  2429. }
  2430. function getThen(promise) {
  2431. try {
  2432. return promise.then;
  2433. } catch (error) {
  2434. GET_THEN_ERROR.error = error;
  2435. return GET_THEN_ERROR;
  2436. }
  2437. }
  2438. function tryThen(then$$1, value, fulfillmentHandler, rejectionHandler) {
  2439. try {
  2440. then$$1.call(value, fulfillmentHandler, rejectionHandler);
  2441. } catch (e) {
  2442. return e;
  2443. }
  2444. }
  2445. function handleForeignThenable(promise, thenable, then$$1) {
  2446. asap(function (promise) {
  2447. var sealed = false;
  2448. var error = tryThen(then$$1, thenable, function (value) {
  2449. if (sealed) {
  2450. return;
  2451. }
  2452. sealed = true;
  2453. if (thenable !== value) {
  2454. resolve(promise, value);
  2455. } else {
  2456. fulfill(promise, value);
  2457. }
  2458. }, function (reason) {
  2459. if (sealed) {
  2460. return;
  2461. }
  2462. sealed = true;
  2463. reject(promise, reason);
  2464. }, 'Settle: ' + (promise._label || ' unknown promise'));
  2465. if (!sealed && error) {
  2466. sealed = true;
  2467. reject(promise, error);
  2468. }
  2469. }, promise);
  2470. }
  2471. function handleOwnThenable(promise, thenable) {
  2472. if (thenable._state === FULFILLED) {
  2473. fulfill(promise, thenable._result);
  2474. } else if (thenable._state === REJECTED) {
  2475. reject(promise, thenable._result);
  2476. } else {
  2477. subscribe(thenable, undefined, function (value) {
  2478. return resolve(promise, value);
  2479. }, function (reason) {
  2480. return reject(promise, reason);
  2481. });
  2482. }
  2483. }
  2484. function handleMaybeThenable(promise, maybeThenable, then$$1) {
  2485. if (maybeThenable.constructor === promise.constructor && then$$1 === then && maybeThenable.constructor.resolve === resolve$1) {
  2486. handleOwnThenable(promise, maybeThenable);
  2487. } else {
  2488. if (then$$1 === GET_THEN_ERROR) {
  2489. reject(promise, GET_THEN_ERROR.error);
  2490. GET_THEN_ERROR.error = null;
  2491. } else if (then$$1 === undefined) {
  2492. fulfill(promise, maybeThenable);
  2493. } else if (isFunction(then$$1)) {
  2494. handleForeignThenable(promise, maybeThenable, then$$1);
  2495. } else {
  2496. fulfill(promise, maybeThenable);
  2497. }
  2498. }
  2499. }
  2500. function resolve(promise, value) {
  2501. if (promise === value) {
  2502. reject(promise, selfFulfillment());
  2503. } else if (objectOrFunction(value)) {
  2504. handleMaybeThenable(promise, value, getThen(value));
  2505. } else {
  2506. fulfill(promise, value);
  2507. }
  2508. }
  2509. function publishRejection(promise) {
  2510. if (promise._onerror) {
  2511. promise._onerror(promise._result);
  2512. }
  2513. publish(promise);
  2514. }
  2515. function fulfill(promise, value) {
  2516. if (promise._state !== PENDING) {
  2517. return;
  2518. }
  2519. promise._result = value;
  2520. promise._state = FULFILLED;
  2521. if (promise._subscribers.length !== 0) {
  2522. asap(publish, promise);
  2523. }
  2524. }
  2525. function reject(promise, reason) {
  2526. if (promise._state !== PENDING) {
  2527. return;
  2528. }
  2529. promise._state = REJECTED;
  2530. promise._result = reason;
  2531. asap(publishRejection, promise);
  2532. }
  2533. function subscribe(parent, child, onFulfillment, onRejection) {
  2534. var _subscribers = parent._subscribers;
  2535. var length = _subscribers.length;
  2536. parent._onerror = null;
  2537. _subscribers[length] = child;
  2538. _subscribers[length + FULFILLED] = onFulfillment;
  2539. _subscribers[length + REJECTED] = onRejection;
  2540. if (length === 0 && parent._state) {
  2541. asap(publish, parent);
  2542. }
  2543. }
  2544. function publish(promise) {
  2545. var subscribers = promise._subscribers;
  2546. var settled = promise._state;
  2547. if (subscribers.length === 0) {
  2548. return;
  2549. }
  2550. var child = undefined,
  2551. callback = undefined,
  2552. detail = promise._result;
  2553. for (var i = 0; i < subscribers.length; i += 3) {
  2554. child = subscribers[i];
  2555. callback = subscribers[i + settled];
  2556. if (child) {
  2557. invokeCallback(settled, child, callback, detail);
  2558. } else {
  2559. callback(detail);
  2560. }
  2561. }
  2562. promise._subscribers.length = 0;
  2563. }
  2564. function ErrorObject() {
  2565. this.error = null;
  2566. }
  2567. var TRY_CATCH_ERROR = new ErrorObject();
  2568. function tryCatch(callback, detail) {
  2569. try {
  2570. return callback(detail);
  2571. } catch (e) {
  2572. TRY_CATCH_ERROR.error = e;
  2573. return TRY_CATCH_ERROR;
  2574. }
  2575. }
  2576. function invokeCallback(settled, promise, callback, detail) {
  2577. var hasCallback = isFunction(callback),
  2578. value = undefined,
  2579. error = undefined,
  2580. succeeded = undefined,
  2581. failed = undefined;
  2582. if (hasCallback) {
  2583. value = tryCatch(callback, detail);
  2584. if (value === TRY_CATCH_ERROR) {
  2585. failed = true;
  2586. error = value.error;
  2587. value.error = null;
  2588. } else {
  2589. succeeded = true;
  2590. }
  2591. if (promise === value) {
  2592. reject(promise, cannotReturnOwn());
  2593. return;
  2594. }
  2595. } else {
  2596. value = detail;
  2597. succeeded = true;
  2598. }
  2599. if (promise._state !== PENDING) {
  2600. // noop
  2601. } else if (hasCallback && succeeded) {
  2602. resolve(promise, value);
  2603. } else if (failed) {
  2604. reject(promise, error);
  2605. } else if (settled === FULFILLED) {
  2606. fulfill(promise, value);
  2607. } else if (settled === REJECTED) {
  2608. reject(promise, value);
  2609. }
  2610. }
  2611. function initializePromise(promise, resolver) {
  2612. try {
  2613. resolver(function resolvePromise(value) {
  2614. resolve(promise, value);
  2615. }, function rejectPromise(reason) {
  2616. reject(promise, reason);
  2617. });
  2618. } catch (e) {
  2619. reject(promise, e);
  2620. }
  2621. }
  2622. var id = 0;
  2623. function nextId() {
  2624. return id++;
  2625. }
  2626. function makePromise(promise) {
  2627. promise[PROMISE_ID] = id++;
  2628. promise._state = undefined;
  2629. promise._result = undefined;
  2630. promise._subscribers = [];
  2631. }
  2632. function Enumerator$1(Constructor, input) {
  2633. this._instanceConstructor = Constructor;
  2634. this.promise = new Constructor(noop);
  2635. if (!this.promise[PROMISE_ID]) {
  2636. makePromise(this.promise);
  2637. }
  2638. if (isArray(input)) {
  2639. this.length = input.length;
  2640. this._remaining = input.length;
  2641. this._result = new Array(this.length);
  2642. if (this.length === 0) {
  2643. fulfill(this.promise, this._result);
  2644. } else {
  2645. this.length = this.length || 0;
  2646. this._enumerate(input);
  2647. if (this._remaining === 0) {
  2648. fulfill(this.promise, this._result);
  2649. }
  2650. }
  2651. } else {
  2652. reject(this.promise, validationError());
  2653. }
  2654. }
  2655. function validationError() {
  2656. return new Error('Array Methods must be provided an Array');
  2657. }
  2658. Enumerator$1.prototype._enumerate = function (input) {
  2659. for (var i = 0; this._state === PENDING && i < input.length; i++) {
  2660. this._eachEntry(input[i], i);
  2661. }
  2662. };
  2663. Enumerator$1.prototype._eachEntry = function (entry, i) {
  2664. var c = this._instanceConstructor;
  2665. var resolve$$1 = c.resolve;
  2666. if (resolve$$1 === resolve$1) {
  2667. var _then = getThen(entry);
  2668. if (_then === then && entry._state !== PENDING) {
  2669. this._settledAt(entry._state, i, entry._result);
  2670. } else if (typeof _then !== 'function') {
  2671. this._remaining--;
  2672. this._result[i] = entry;
  2673. } else if (c === Promise$3) {
  2674. var promise = new c(noop);
  2675. handleMaybeThenable(promise, entry, _then);
  2676. this._willSettleAt(promise, i);
  2677. } else {
  2678. this._willSettleAt(new c(function (resolve$$1) {
  2679. return resolve$$1(entry);
  2680. }), i);
  2681. }
  2682. } else {
  2683. this._willSettleAt(resolve$$1(entry), i);
  2684. }
  2685. };
  2686. Enumerator$1.prototype._settledAt = function (state, i, value) {
  2687. var promise = this.promise;
  2688. if (promise._state === PENDING) {
  2689. this._remaining--;
  2690. if (state === REJECTED) {
  2691. reject(promise, value);
  2692. } else {
  2693. this._result[i] = value;
  2694. }
  2695. }
  2696. if (this._remaining === 0) {
  2697. fulfill(promise, this._result);
  2698. }
  2699. };
  2700. Enumerator$1.prototype._willSettleAt = function (promise, i) {
  2701. var enumerator = this;
  2702. subscribe(promise, undefined, function (value) {
  2703. return enumerator._settledAt(FULFILLED, i, value);
  2704. }, function (reason) {
  2705. return enumerator._settledAt(REJECTED, i, reason);
  2706. });
  2707. };
  2708. /**
  2709. `Promise.all` accepts an array of promises, and returns a new promise which
  2710. is fulfilled with an array of fulfillment values for the passed promises, or
  2711. rejected with the reason of the first passed promise to be rejected. It casts all
  2712. elements of the passed iterable to promises as it runs this algorithm.
  2713. Example:
  2714. ```javascript
  2715. let promise1 = resolve(1);
  2716. let promise2 = resolve(2);
  2717. let promise3 = resolve(3);
  2718. let promises = [ promise1, promise2, promise3 ];
  2719. Promise.all(promises).then(function(array){
  2720. // The array here would be [ 1, 2, 3 ];
  2721. });
  2722. ```
  2723. If any of the `promises` given to `all` are rejected, the first promise
  2724. that is rejected will be given as an argument to the returned promises's
  2725. rejection handler. For example:
  2726. Example:
  2727. ```javascript
  2728. let promise1 = resolve(1);
  2729. let promise2 = reject(new Error("2"));
  2730. let promise3 = reject(new Error("3"));
  2731. let promises = [ promise1, promise2, promise3 ];
  2732. Promise.all(promises).then(function(array){
  2733. // Code here never runs because there are rejected promises!
  2734. }, function(error) {
  2735. // error.message === "2"
  2736. });
  2737. ```
  2738. @method all
  2739. @static
  2740. @param {Array} entries array of promises
  2741. @param {String} label optional string for labeling the promise.
  2742. Useful for tooling.
  2743. @return {Promise} promise that is fulfilled when all `promises` have been
  2744. fulfilled, or rejected if any of them become rejected.
  2745. @static
  2746. */
  2747. function all$1(entries) {
  2748. return new Enumerator$1(this, entries).promise;
  2749. }
  2750. /**
  2751. `Promise.race` returns a new promise which is settled in the same way as the
  2752. first passed promise to settle.
  2753. Example:
  2754. ```javascript
  2755. let promise1 = new Promise(function(resolve, reject){
  2756. setTimeout(function(){
  2757. resolve('promise 1');
  2758. }, 200);
  2759. });
  2760. let promise2 = new Promise(function(resolve, reject){
  2761. setTimeout(function(){
  2762. resolve('promise 2');
  2763. }, 100);
  2764. });
  2765. Promise.race([promise1, promise2]).then(function(result){
  2766. // result === 'promise 2' because it was resolved before promise1
  2767. // was resolved.
  2768. });
  2769. ```
  2770. `Promise.race` is deterministic in that only the state of the first
  2771. settled promise matters. For example, even if other promises given to the
  2772. `promises` array argument are resolved, but the first settled promise has
  2773. become rejected before the other promises became fulfilled, the returned
  2774. promise will become rejected:
  2775. ```javascript
  2776. let promise1 = new Promise(function(resolve, reject){
  2777. setTimeout(function(){
  2778. resolve('promise 1');
  2779. }, 200);
  2780. });
  2781. let promise2 = new Promise(function(resolve, reject){
  2782. setTimeout(function(){
  2783. reject(new Error('promise 2'));
  2784. }, 100);
  2785. });
  2786. Promise.race([promise1, promise2]).then(function(result){
  2787. // Code here never runs
  2788. }, function(reason){
  2789. // reason.message === 'promise 2' because promise 2 became rejected before
  2790. // promise 1 became fulfilled
  2791. });
  2792. ```
  2793. An example real-world use case is implementing timeouts:
  2794. ```javascript
  2795. Promise.race([ajax('foo.json'), timeout(5000)])
  2796. ```
  2797. @method race
  2798. @static
  2799. @param {Array} promises array of promises to observe
  2800. Useful for tooling.
  2801. @return {Promise} a promise which settles in the same way as the first passed
  2802. promise to settle.
  2803. */
  2804. function race$1(entries) {
  2805. /*jshint validthis:true */
  2806. var Constructor = this;
  2807. if (!isArray(entries)) {
  2808. return new Constructor(function (_, reject) {
  2809. return reject(new TypeError('You must pass an array to race.'));
  2810. });
  2811. } else {
  2812. return new Constructor(function (resolve, reject) {
  2813. var length = entries.length;
  2814. for (var i = 0; i < length; i++) {
  2815. Constructor.resolve(entries[i]).then(resolve, reject);
  2816. }
  2817. });
  2818. }
  2819. }
  2820. /**
  2821. `Promise.reject` returns a promise rejected with the passed `reason`.
  2822. It is shorthand for the following:
  2823. ```javascript
  2824. let promise = new Promise(function(resolve, reject){
  2825. reject(new Error('WHOOPS'));
  2826. });
  2827. promise.then(function(value){
  2828. // Code here doesn't run because the promise is rejected!
  2829. }, function(reason){
  2830. // reason.message === 'WHOOPS'
  2831. });
  2832. ```
  2833. Instead of writing the above, your code now simply becomes the following:
  2834. ```javascript
  2835. let promise = Promise.reject(new Error('WHOOPS'));
  2836. promise.then(function(value){
  2837. // Code here doesn't run because the promise is rejected!
  2838. }, function(reason){
  2839. // reason.message === 'WHOOPS'
  2840. });
  2841. ```
  2842. @method reject
  2843. @static
  2844. @param {Any} reason value that the returned promise will be rejected with.
  2845. Useful for tooling.
  2846. @return {Promise} a promise rejected with the given `reason`.
  2847. */
  2848. function reject$1(reason) {
  2849. /*jshint validthis:true */
  2850. var Constructor = this;
  2851. var promise = new Constructor(noop);
  2852. reject(promise, reason);
  2853. return promise;
  2854. }
  2855. function needsResolver() {
  2856. throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
  2857. }
  2858. function needsNew() {
  2859. throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
  2860. }
  2861. /**
  2862. Promise objects represent the eventual result of an asynchronous operation. The
  2863. primary way of interacting with a promise is through its `then` method, which
  2864. registers callbacks to receive either a promise's eventual value or the reason
  2865. why the promise cannot be fulfilled.
  2866. Terminology
  2867. -----------
  2868. - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
  2869. - `thenable` is an object or function that defines a `then` method.
  2870. - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
  2871. - `exception` is a value that is thrown using the throw statement.
  2872. - `reason` is a value that indicates why a promise was rejected.
  2873. - `settled` the final resting state of a promise, fulfilled or rejected.
  2874. A promise can be in one of three states: pending, fulfilled, or rejected.
  2875. Promises that are fulfilled have a fulfillment value and are in the fulfilled
  2876. state. Promises that are rejected have a rejection reason and are in the
  2877. rejected state. A fulfillment value is never a thenable.
  2878. Promises can also be said to *resolve* a value. If this value is also a
  2879. promise, then the original promise's settled state will match the value's
  2880. settled state. So a promise that *resolves* a promise that rejects will
  2881. itself reject, and a promise that *resolves* a promise that fulfills will
  2882. itself fulfill.
  2883. Basic Usage:
  2884. ------------
  2885. ```js
  2886. let promise = new Promise(function(resolve, reject) {
  2887. // on success
  2888. resolve(value);
  2889. // on failure
  2890. reject(reason);
  2891. });
  2892. promise.then(function(value) {
  2893. // on fulfillment
  2894. }, function(reason) {
  2895. // on rejection
  2896. });
  2897. ```
  2898. Advanced Usage:
  2899. ---------------
  2900. Promises shine when abstracting away asynchronous interactions such as
  2901. `XMLHttpRequest`s.
  2902. ```js
  2903. function getJSON(url) {
  2904. return new Promise(function(resolve, reject){
  2905. let xhr = new XMLHttpRequest();
  2906. xhr.open('GET', url);
  2907. xhr.onreadystatechange = handler;
  2908. xhr.responseType = 'json';
  2909. xhr.setRequestHeader('Accept', 'application/json');
  2910. xhr.send();
  2911. function handler() {
  2912. if (this.readyState === this.DONE) {
  2913. if (this.status === 200) {
  2914. resolve(this.response);
  2915. } else {
  2916. reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
  2917. }
  2918. }
  2919. };
  2920. });
  2921. }
  2922. getJSON('/posts.json').then(function(json) {
  2923. // on fulfillment
  2924. }, function(reason) {
  2925. // on rejection
  2926. });
  2927. ```
  2928. Unlike callbacks, promises are great composable primitives.
  2929. ```js
  2930. Promise.all([
  2931. getJSON('/posts'),
  2932. getJSON('/comments')
  2933. ]).then(function(values){
  2934. values[0] // => postsJSON
  2935. values[1] // => commentsJSON
  2936. return values;
  2937. });
  2938. ```
  2939. @class Promise
  2940. @param {function} resolver
  2941. Useful for tooling.
  2942. @constructor
  2943. */
  2944. function Promise$3(resolver) {
  2945. this[PROMISE_ID] = nextId();
  2946. this._result = this._state = undefined;
  2947. this._subscribers = [];
  2948. if (noop !== resolver) {
  2949. typeof resolver !== 'function' && needsResolver();
  2950. this instanceof Promise$3 ? initializePromise(this, resolver) : needsNew();
  2951. }
  2952. }
  2953. Promise$3.all = all$1;
  2954. Promise$3.race = race$1;
  2955. Promise$3.resolve = resolve$1;
  2956. Promise$3.reject = reject$1;
  2957. Promise$3._setScheduler = setScheduler;
  2958. Promise$3._setAsap = setAsap;
  2959. Promise$3._asap = asap;
  2960. Promise$3.prototype = {
  2961. constructor: Promise$3,
  2962. /**
  2963. The primary way of interacting with a promise is through its `then` method,
  2964. which registers callbacks to receive either a promise's eventual value or the
  2965. reason why the promise cannot be fulfilled.
  2966. ```js
  2967. findUser().then(function(user){
  2968. // user is available
  2969. }, function(reason){
  2970. // user is unavailable, and you are given the reason why
  2971. });
  2972. ```
  2973. Chaining
  2974. --------
  2975. The return value of `then` is itself a promise. This second, 'downstream'
  2976. promise is resolved with the return value of the first promise's fulfillment
  2977. or rejection handler, or rejected if the handler throws an exception.
  2978. ```js
  2979. findUser().then(function (user) {
  2980. return user.name;
  2981. }, function (reason) {
  2982. return 'default name';
  2983. }).then(function (userName) {
  2984. // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
  2985. // will be `'default name'`
  2986. });
  2987. findUser().then(function (user) {
  2988. throw new Error('Found user, but still unhappy');
  2989. }, function (reason) {
  2990. throw new Error('`findUser` rejected and we're unhappy');
  2991. }).then(function (value) {
  2992. // never reached
  2993. }, function (reason) {
  2994. // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
  2995. // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
  2996. });
  2997. ```
  2998. If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
  2999. ```js
  3000. findUser().then(function (user) {
  3001. throw new PedagogicalException('Upstream error');
  3002. }).then(function (value) {
  3003. // never reached
  3004. }).then(function (value) {
  3005. // never reached
  3006. }, function (reason) {
  3007. // The `PedgagocialException` is propagated all the way down to here
  3008. });
  3009. ```
  3010. Assimilation
  3011. ------------
  3012. Sometimes the value you want to propagate to a downstream promise can only be
  3013. retrieved asynchronously. This can be achieved by returning a promise in the
  3014. fulfillment or rejection handler. The downstream promise will then be pending
  3015. until the returned promise is settled. This is called *assimilation*.
  3016. ```js
  3017. findUser().then(function (user) {
  3018. return findCommentsByAuthor(user);
  3019. }).then(function (comments) {
  3020. // The user's comments are now available
  3021. });
  3022. ```
  3023. If the assimliated promise rejects, then the downstream promise will also reject.
  3024. ```js
  3025. findUser().then(function (user) {
  3026. return findCommentsByAuthor(user);
  3027. }).then(function (comments) {
  3028. // If `findCommentsByAuthor` fulfills, we'll have the value here
  3029. }, function (reason) {
  3030. // If `findCommentsByAuthor` rejects, we'll have the reason here
  3031. });
  3032. ```
  3033. Simple Example
  3034. --------------
  3035. Synchronous Example
  3036. ```javascript
  3037. let result;
  3038. try {
  3039. result = findResult();
  3040. // success
  3041. } catch(reason) {
  3042. // failure
  3043. }
  3044. ```
  3045. Errback Example
  3046. ```js
  3047. findResult(function(result, err){
  3048. if (err) {
  3049. // failure
  3050. } else {
  3051. // success
  3052. }
  3053. });
  3054. ```
  3055. Promise Example;
  3056. ```javascript
  3057. findResult().then(function(result){
  3058. // success
  3059. }, function(reason){
  3060. // failure
  3061. });
  3062. ```
  3063. Advanced Example
  3064. --------------
  3065. Synchronous Example
  3066. ```javascript
  3067. let author, books;
  3068. try {
  3069. author = findAuthor();
  3070. books = findBooksByAuthor(author);
  3071. // success
  3072. } catch(reason) {
  3073. // failure
  3074. }
  3075. ```
  3076. Errback Example
  3077. ```js
  3078. function foundBooks(books) {
  3079. }
  3080. function failure(reason) {
  3081. }
  3082. findAuthor(function(author, err){
  3083. if (err) {
  3084. failure(err);
  3085. // failure
  3086. } else {
  3087. try {
  3088. findBoooksByAuthor(author, function(books, err) {
  3089. if (err) {
  3090. failure(err);
  3091. } else {
  3092. try {
  3093. foundBooks(books);
  3094. } catch(reason) {
  3095. failure(reason);
  3096. }
  3097. }
  3098. });
  3099. } catch(error) {
  3100. failure(err);
  3101. }
  3102. // success
  3103. }
  3104. });
  3105. ```
  3106. Promise Example;
  3107. ```javascript
  3108. findAuthor().
  3109. then(findBooksByAuthor).
  3110. then(function(books){
  3111. // found books
  3112. }).catch(function(reason){
  3113. // something went wrong
  3114. });
  3115. ```
  3116. @method then
  3117. @param {Function} onFulfilled
  3118. @param {Function} onRejected
  3119. Useful for tooling.
  3120. @return {Promise}
  3121. */
  3122. then: then,
  3123. /**
  3124. `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
  3125. as the catch block of a try/catch statement.
  3126. ```js
  3127. function findAuthor(){
  3128. throw new Error('couldn't find that author');
  3129. }
  3130. // synchronous
  3131. try {
  3132. findAuthor();
  3133. } catch(reason) {
  3134. // something went wrong
  3135. }
  3136. // async with promises
  3137. findAuthor().catch(function(reason){
  3138. // something went wrong
  3139. });
  3140. ```
  3141. @method catch
  3142. @param {Function} onRejection
  3143. Useful for tooling.
  3144. @return {Promise}
  3145. */
  3146. 'catch': function _catch(onRejection) {
  3147. return this.then(null, onRejection);
  3148. }
  3149. };
  3150. /*global self*/
  3151. function polyfill$1() {
  3152. var local = undefined;
  3153. if (typeof global !== 'undefined') {
  3154. local = global;
  3155. } else if (typeof self !== 'undefined') {
  3156. local = self;
  3157. } else {
  3158. try {
  3159. local = Function('return this')();
  3160. } catch (e) {
  3161. throw new Error('polyfill failed because global object is unavailable in this environment');
  3162. }
  3163. }
  3164. var P = local.Promise;
  3165. if (P) {
  3166. var promiseToString = null;
  3167. try {
  3168. promiseToString = Object.prototype.toString.call(P.resolve());
  3169. } catch (e) {
  3170. // silently ignored
  3171. }
  3172. if (promiseToString === '[object Promise]' && !P.cast) {
  3173. return;
  3174. }
  3175. }
  3176. local.Promise = Promise$3;
  3177. }
  3178. // Strange compat..
  3179. Promise$3.polyfill = polyfill$1;
  3180. Promise$3.Promise = Promise$3;
  3181. Promise$3.polyfill();
  3182. return Promise$3;
  3183. })));
  3184. //# sourceMappingURL=es6-promise.auto.map
  3185. ;
  3186. if (!String.prototype.endsWith) {
  3187. String.prototype.endsWith = function (searchString, position) {
  3188. var subjectString = this.toString();
  3189. if (position === undefined || position > subjectString.length) {
  3190. position = subjectString.length;
  3191. }
  3192. position -= searchString.length;
  3193. var lastIndex = subjectString.indexOf(searchString, position);
  3194. return lastIndex !== -1 && lastIndex === position;
  3195. };
  3196. }
  3197. if (!String.prototype.startsWith) {
  3198. String.prototype.startsWith = function (searchString, position) {
  3199. position = position || 0;
  3200. return this.substr(position, searchString.length) === searchString;
  3201. };
  3202. }
  3203. if (!String.prototype.splitOnce) {
  3204. String.prototype.splitOnce = function (delimiter) {
  3205. var components = this.split(delimiter);
  3206. return [components.shift(), components.join(delimiter)];
  3207. };
  3208. }
  3209. if (!String.prototype.trim) {
  3210. String.prototype.trim = function () {
  3211. return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
  3212. };
  3213. }
  3214. ;
  3215. define("polyfill", function(){});
  3216. /*!
  3217. * jQuery Browser Plugin 0.1.0
  3218. * https://github.com/gabceb/jquery-browser-plugin
  3219. *
  3220. * Original jquery-browser code Copyright 2005, 2015 jQuery Foundation, Inc. and other contributors
  3221. * http://jquery.org/license
  3222. *
  3223. * Modifications Copyright 2015 Gabriel Cebrian
  3224. * https://github.com/gabceb
  3225. *
  3226. * Released under the MIT license
  3227. *
  3228. * Date: 05-07-2015
  3229. */
  3230. /*global window: false */
  3231. (function (factory) {
  3232. if (typeof define === 'function' && define.amd) {
  3233. // AMD. Register as an anonymous module.
  3234. define('jquery.browser',['jquery'], function ($) {
  3235. return factory($);
  3236. });
  3237. } else if (typeof module === 'object' && typeof module.exports === 'object') {
  3238. // Node-like environment
  3239. module.exports = factory(require('jquery'));
  3240. } else {
  3241. // Browser globals
  3242. factory(window.jQuery);
  3243. }
  3244. }(function(jQuery) {
  3245. "use strict";
  3246. function uaMatch( ua ) {
  3247. // If an UA is not provided, default to the current browser UA.
  3248. if ( ua === undefined ) {
  3249. ua = window.navigator.userAgent;
  3250. }
  3251. ua = ua.toLowerCase();
  3252. var match = /(edge)\/([\w.]+)/.exec( ua ) ||
  3253. /(opr)[\/]([\w.]+)/.exec( ua ) ||
  3254. /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
  3255. /(iemobile)[\/]([\w.]+)/.exec( ua ) ||
  3256. /(version)(applewebkit)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec( ua ) ||
  3257. /(webkit)[ \/]([\w.]+).*(version)[ \/]([\w.]+).*(safari)[ \/]([\w.]+)/.exec( ua ) ||
  3258. /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
  3259. /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
  3260. /(msie) ([\w.]+)/.exec( ua ) ||
  3261. ua.indexOf("trident") >= 0 && /(rv)(?::| )([\w.]+)/.exec( ua ) ||
  3262. ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
  3263. [];
  3264. var platform_match = /(ipad)/.exec( ua ) ||
  3265. /(ipod)/.exec( ua ) ||
  3266. /(windows phone)/.exec( ua ) ||
  3267. /(iphone)/.exec( ua ) ||
  3268. /(kindle)/.exec( ua ) ||
  3269. /(silk)/.exec( ua ) ||
  3270. /(android)/.exec( ua ) ||
  3271. /(win)/.exec( ua ) ||
  3272. /(mac)/.exec( ua ) ||
  3273. /(linux)/.exec( ua ) ||
  3274. /(cros)/.exec( ua ) ||
  3275. /(playbook)/.exec( ua ) ||
  3276. /(bb)/.exec( ua ) ||
  3277. /(blackberry)/.exec( ua ) ||
  3278. [];
  3279. var browser = {},
  3280. matched = {
  3281. browser: match[ 5 ] || match[ 3 ] || match[ 1 ] || "",
  3282. version: match[ 2 ] || match[ 4 ] || "0",
  3283. versionNumber: match[ 4 ] || match[ 2 ] || "0",
  3284. platform: platform_match[ 0 ] || ""
  3285. };
  3286. if ( matched.browser ) {
  3287. browser[ matched.browser ] = true;
  3288. browser.version = matched.version;
  3289. browser.versionNumber = parseInt(matched.versionNumber, 10);
  3290. }
  3291. if ( matched.platform ) {
  3292. browser[ matched.platform ] = true;
  3293. }
  3294. // These are all considered mobile platforms, meaning they run a mobile browser
  3295. if ( browser.android || browser.bb || browser.blackberry || browser.ipad || browser.iphone ||
  3296. browser.ipod || browser.kindle || browser.playbook || browser.silk || browser[ "windows phone" ]) {
  3297. browser.mobile = true;
  3298. }
  3299. // These are all considered desktop platforms, meaning they run a desktop browser
  3300. if ( browser.cros || browser.mac || browser.linux || browser.win ) {
  3301. browser.desktop = true;
  3302. }
  3303. // Chrome, Opera 15+ and Safari are webkit based browsers
  3304. if ( browser.chrome || browser.opr || browser.safari ) {
  3305. browser.webkit = true;
  3306. }
  3307. // IE11 has a new token so we will assign it msie to avoid breaking changes
  3308. if ( browser.rv || browser.iemobile) {
  3309. var ie = "msie";
  3310. matched.browser = ie;
  3311. browser[ie] = true;
  3312. }
  3313. // Edge is officially known as Microsoft Edge, so rewrite the key to match
  3314. if ( browser.edge ) {
  3315. delete browser.edge;
  3316. var msedge = "msedge";
  3317. matched.browser = msedge;
  3318. browser[msedge] = true;
  3319. }
  3320. // Blackberry browsers are marked as Safari on BlackBerry
  3321. if ( browser.safari && browser.blackberry ) {
  3322. var blackberry = "blackberry";
  3323. matched.browser = blackberry;
  3324. browser[blackberry] = true;
  3325. }
  3326. // Playbook browsers are marked as Safari on Playbook
  3327. if ( browser.safari && browser.playbook ) {
  3328. var playbook = "playbook";
  3329. matched.browser = playbook;
  3330. browser[playbook] = true;
  3331. }
  3332. // BB10 is a newer OS version of BlackBerry
  3333. if ( browser.bb ) {
  3334. var bb = "blackberry";
  3335. matched.browser = bb;
  3336. browser[bb] = true;
  3337. }
  3338. // Opera 15+ are identified as opr
  3339. if ( browser.opr ) {
  3340. var opera = "opera";
  3341. matched.browser = opera;
  3342. browser[opera] = true;
  3343. }
  3344. // Stock Android browsers are marked as Safari on Android.
  3345. if ( browser.safari && browser.android ) {
  3346. var android = "android";
  3347. matched.browser = android;
  3348. browser[android] = true;
  3349. }
  3350. // Kindle browsers are marked as Safari on Kindle
  3351. if ( browser.safari && browser.kindle ) {
  3352. var kindle = "kindle";
  3353. matched.browser = kindle;
  3354. browser[kindle] = true;
  3355. }
  3356. // Kindle Silk browsers are marked as Safari on Kindle
  3357. if ( browser.safari && browser.silk ) {
  3358. var silk = "silk";
  3359. matched.browser = silk;
  3360. browser[silk] = true;
  3361. }
  3362. // Assign the name and platform variable
  3363. browser.name = matched.browser;
  3364. browser.platform = matched.platform;
  3365. return browser;
  3366. }
  3367. // Run the matching process, also assign the function to the returned object
  3368. // for manual, jQuery-free use if desired
  3369. window.jQBrowser = uaMatch( window.navigator.userAgent );
  3370. window.jQBrowser.uaMatch = uaMatch;
  3371. // Only assign to jQuery.browser if jQuery is loaded
  3372. if ( jQuery ) {
  3373. jQuery.browser = window.jQBrowser;
  3374. }
  3375. return window.jQBrowser;
  3376. }));
  3377. /*
  3378. jed.js
  3379. v0.5.0beta
  3380. https://github.com/SlexAxton/Jed
  3381. -----------
  3382. A gettext compatible i18n library for modern JavaScript Applications
  3383. by Alex Sexton - AlexSexton [at] gmail - @SlexAxton
  3384. WTFPL license for use
  3385. Dojo CLA for contributions
  3386. Jed offers the entire applicable GNU gettext spec'd set of
  3387. functions, but also offers some nicer wrappers around them.
  3388. The api for gettext was written for a language with no function
  3389. overloading, so Jed allows a little more of that.
  3390. Many thanks to Joshua I. Miller - unrtst@cpan.org - who wrote
  3391. gettext.js back in 2008. I was able to vet a lot of my ideas
  3392. against his. I also made sure Jed passed against his tests
  3393. in order to offer easy upgrades -- jsgettext.berlios.de
  3394. */
  3395. (function (root, undef) {
  3396. // Set up some underscore-style functions, if you already have
  3397. // underscore, feel free to delete this section, and use it
  3398. // directly, however, the amount of functions used doesn't
  3399. // warrant having underscore as a full dependency.
  3400. // Underscore 1.3.0 was used to port and is licensed
  3401. // under the MIT License by Jeremy Ashkenas.
  3402. var ArrayProto = Array.prototype,
  3403. ObjProto = Object.prototype,
  3404. slice = ArrayProto.slice,
  3405. hasOwnProp = ObjProto.hasOwnProperty,
  3406. nativeForEach = ArrayProto.forEach,
  3407. breaker = {};
  3408. // We're not using the OOP style _ so we don't need the
  3409. // extra level of indirection. This still means that you
  3410. // sub out for real `_` though.
  3411. var _ = {
  3412. forEach : function( obj, iterator, context ) {
  3413. var i, l, key;
  3414. if ( obj === null ) {
  3415. return;
  3416. }
  3417. if ( nativeForEach && obj.forEach === nativeForEach ) {
  3418. obj.forEach( iterator, context );
  3419. }
  3420. else if ( obj.length === +obj.length ) {
  3421. for ( i = 0, l = obj.length; i < l; i++ ) {
  3422. if ( i in obj && iterator.call( context, obj[i], i, obj ) === breaker ) {
  3423. return;
  3424. }
  3425. }
  3426. }
  3427. else {
  3428. for ( key in obj) {
  3429. if ( hasOwnProp.call( obj, key ) ) {
  3430. if ( iterator.call (context, obj[key], key, obj ) === breaker ) {
  3431. return;
  3432. }
  3433. }
  3434. }
  3435. }
  3436. },
  3437. extend : function( obj ) {
  3438. this.forEach( slice.call( arguments, 1 ), function ( source ) {
  3439. for ( var prop in source ) {
  3440. obj[prop] = source[prop];
  3441. }
  3442. });
  3443. return obj;
  3444. }
  3445. };
  3446. // END Miniature underscore impl
  3447. // Jed is a constructor function
  3448. var Jed = function ( options ) {
  3449. // Some minimal defaults
  3450. this.defaults = {
  3451. "locale_data" : {
  3452. "messages" : {
  3453. "" : {
  3454. "domain" : "messages",
  3455. "lang" : "en",
  3456. "plural_forms" : "nplurals=2; plural=(n != 1);"
  3457. }
  3458. // There are no default keys, though
  3459. }
  3460. },
  3461. // The default domain if one is missing
  3462. "domain" : "messages"
  3463. };
  3464. // Mix in the sent options with the default options
  3465. this.options = _.extend( {}, this.defaults, options );
  3466. this.textdomain( this.options.domain );
  3467. if ( options.domain && ! this.options.locale_data[ this.options.domain ] ) {
  3468. throw new Error('Text domain set to non-existent domain: `' + options.domain + '`');
  3469. }
  3470. };
  3471. // The gettext spec sets this character as the default
  3472. // delimiter for context lookups.
  3473. // e.g.: context\u0004key
  3474. // If your translation company uses something different,
  3475. // just change this at any time and it will use that instead.
  3476. Jed.context_delimiter = String.fromCharCode( 4 );
  3477. function getPluralFormFunc ( plural_form_string ) {
  3478. return Jed.PF.compile( plural_form_string || "nplurals=2; plural=(n != 1);");
  3479. }
  3480. function Chain( key, i18n ){
  3481. this._key = key;
  3482. this._i18n = i18n;
  3483. }
  3484. // Create a chainable api for adding args prettily
  3485. _.extend( Chain.prototype, {
  3486. onDomain : function ( domain ) {
  3487. this._domain = domain;
  3488. return this;
  3489. },
  3490. withContext : function ( context ) {
  3491. this._context = context;
  3492. return this;
  3493. },
  3494. ifPlural : function ( num, pkey ) {
  3495. this._val = num;
  3496. this._pkey = pkey;
  3497. return this;
  3498. },
  3499. fetch : function ( sArr ) {
  3500. if ( {}.toString.call( sArr ) != '[object Array]' ) {
  3501. sArr = [].slice.call(arguments);
  3502. }
  3503. return ( sArr && sArr.length ? Jed.sprintf : function(x){ return x; } )(
  3504. this._i18n.dcnpgettext(this._domain, this._context, this._key, this._pkey, this._val),
  3505. sArr
  3506. );
  3507. }
  3508. });
  3509. // Add functions to the Jed prototype.
  3510. // These will be the functions on the object that's returned
  3511. // from creating a `new Jed()`
  3512. // These seem redundant, but they gzip pretty well.
  3513. _.extend( Jed.prototype, {
  3514. // The sexier api start point
  3515. translate : function ( key ) {
  3516. return new Chain( key, this );
  3517. },
  3518. textdomain : function ( domain ) {
  3519. if ( ! domain ) {
  3520. return this._textdomain;
  3521. }
  3522. this._textdomain = domain;
  3523. },
  3524. gettext : function ( key ) {
  3525. return this.dcnpgettext.call( this, undef, undef, key );
  3526. },
  3527. dgettext : function ( domain, key ) {
  3528. return this.dcnpgettext.call( this, domain, undef, key );
  3529. },
  3530. dcgettext : function ( domain , key /*, category */ ) {
  3531. // Ignores the category anyways
  3532. return this.dcnpgettext.call( this, domain, undef, key );
  3533. },
  3534. ngettext : function ( skey, pkey, val ) {
  3535. return this.dcnpgettext.call( this, undef, undef, skey, pkey, val );
  3536. },
  3537. dngettext : function ( domain, skey, pkey, val ) {
  3538. return this.dcnpgettext.call( this, domain, undef, skey, pkey, val );
  3539. },
  3540. dcngettext : function ( domain, skey, pkey, val/*, category */) {
  3541. return this.dcnpgettext.call( this, domain, undef, skey, pkey, val );
  3542. },
  3543. pgettext : function ( context, key ) {
  3544. return this.dcnpgettext.call( this, undef, context, key );
  3545. },
  3546. dpgettext : function ( domain, context, key ) {
  3547. return this.dcnpgettext.call( this, domain, context, key );
  3548. },
  3549. dcpgettext : function ( domain, context, key/*, category */) {
  3550. return this.dcnpgettext.call( this, domain, context, key );
  3551. },
  3552. npgettext : function ( context, skey, pkey, val ) {
  3553. return this.dcnpgettext.call( this, undef, context, skey, pkey, val );
  3554. },
  3555. dnpgettext : function ( domain, context, skey, pkey, val ) {
  3556. return this.dcnpgettext.call( this, domain, context, skey, pkey, val );
  3557. },
  3558. // The most fully qualified gettext function. It has every option.
  3559. // Since it has every option, we can use it from every other method.
  3560. // This is the bread and butter.
  3561. // Technically there should be one more argument in this function for 'Category',
  3562. // but since we never use it, we might as well not waste the bytes to define it.
  3563. dcnpgettext : function ( domain, context, singular_key, plural_key, val ) {
  3564. // Set some defaults
  3565. plural_key = plural_key || singular_key;
  3566. // Use the global domain default if one
  3567. // isn't explicitly passed in
  3568. domain = domain || this._textdomain;
  3569. // Default the value to the singular case
  3570. val = typeof val == 'undefined' ? 1 : val;
  3571. var fallback;
  3572. // Handle special cases
  3573. // No options found
  3574. if ( ! this.options ) {
  3575. // There's likely something wrong, but we'll return the correct key for english
  3576. // We do this by instantiating a brand new Jed instance with the default set
  3577. // for everything that could be broken.
  3578. fallback = new Jed();
  3579. return fallback.dcnpgettext.call( fallback, undefined, undefined, singular_key, plural_key, val );
  3580. }
  3581. // No translation data provided
  3582. if ( ! this.options.locale_data ) {
  3583. throw new Error('No locale data provided.');
  3584. }
  3585. if ( ! this.options.locale_data[ domain ] ) {
  3586. throw new Error('Domain `' + domain + '` was not found.');
  3587. }
  3588. if ( ! this.options.locale_data[ domain ][ "" ] ) {
  3589. throw new Error('No locale meta information provided.');
  3590. }
  3591. // Make sure we have a truthy key. Otherwise we might start looking
  3592. // into the empty string key, which is the options for the locale
  3593. // data.
  3594. if ( ! singular_key ) {
  3595. throw new Error('No translation key found.');
  3596. }
  3597. // Handle invalid numbers, but try casting strings for good measure
  3598. if ( typeof val != 'number' ) {
  3599. val = parseInt( val, 10 );
  3600. if ( isNaN( val ) ) {
  3601. throw new Error('The number that was passed in is not a number.');
  3602. }
  3603. }
  3604. var key = context ? context + Jed.context_delimiter + singular_key : singular_key,
  3605. locale_data = this.options.locale_data,
  3606. dict = locale_data[ domain ],
  3607. pluralForms = dict[""].plural_forms || (locale_data.messages || this.defaults.locale_data.messages)[""].plural_forms,
  3608. val_idx = getPluralFormFunc(pluralForms)(val) + 1,
  3609. val_list,
  3610. res;
  3611. // Throw an error if a domain isn't found
  3612. if ( ! dict ) {
  3613. throw new Error('No domain named `' + domain + '` could be found.');
  3614. }
  3615. val_list = dict[ key ];
  3616. // If there is no match, then revert back to
  3617. // english style singular/plural with the keys passed in.
  3618. if ( ! val_list || val_idx >= val_list.length ) {
  3619. if (this.options.missing_key_callback) {
  3620. this.options.missing_key_callback(key);
  3621. }
  3622. res = [ null, singular_key, plural_key ];
  3623. return res[ getPluralFormFunc(pluralForms)( val ) + 1 ];
  3624. }
  3625. res = val_list[ val_idx ];
  3626. // This includes empty strings on purpose
  3627. if ( ! res ) {
  3628. res = [ null, singular_key, plural_key ];
  3629. return res[ getPluralFormFunc(pluralForms)( val ) + 1 ];
  3630. }
  3631. return res;
  3632. }
  3633. });
  3634. // We add in sprintf capabilities for post translation value interolation
  3635. // This is not internally used, so you can remove it if you have this
  3636. // available somewhere else, or want to use a different system.
  3637. // We _slightly_ modify the normal sprintf behavior to more gracefully handle
  3638. // undefined values.
  3639. /**
  3640. sprintf() for JavaScript 0.7-beta1
  3641. http://www.diveintojavascript.com/projects/javascript-sprintf
  3642. Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
  3643. All rights reserved.
  3644. Redistribution and use in source and binary forms, with or without
  3645. modification, are permitted provided that the following conditions are met:
  3646. * Redistributions of source code must retain the above copyright
  3647. notice, this list of conditions and the following disclaimer.
  3648. * Redistributions in binary form must reproduce the above copyright
  3649. notice, this list of conditions and the following disclaimer in the
  3650. documentation and/or other materials provided with the distribution.
  3651. * Neither the name of sprintf() for JavaScript nor the
  3652. names of its contributors may be used to endorse or promote products
  3653. derived from this software without specific prior written permission.
  3654. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  3655. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  3656. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  3657. DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY
  3658. DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  3659. (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  3660. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  3661. ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  3662. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  3663. SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  3664. */
  3665. var sprintf = (function() {
  3666. function get_type(variable) {
  3667. return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
  3668. }
  3669. function str_repeat(input, multiplier) {
  3670. for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
  3671. return output.join('');
  3672. }
  3673. var str_format = function() {
  3674. if (!str_format.cache.hasOwnProperty(arguments[0])) {
  3675. str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
  3676. }
  3677. return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
  3678. };
  3679. str_format.format = function(parse_tree, argv) {
  3680. var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
  3681. for (i = 0; i < tree_length; i++) {
  3682. node_type = get_type(parse_tree[i]);
  3683. if (node_type === 'string') {
  3684. output.push(parse_tree[i]);
  3685. }
  3686. else if (node_type === 'array') {
  3687. match = parse_tree[i]; // convenience purposes only
  3688. if (match[2]) { // keyword argument
  3689. arg = argv[cursor];
  3690. for (k = 0; k < match[2].length; k++) {
  3691. if (!arg.hasOwnProperty(match[2][k])) {
  3692. throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
  3693. }
  3694. arg = arg[match[2][k]];
  3695. }
  3696. }
  3697. else if (match[1]) { // positional argument (explicit)
  3698. arg = argv[match[1]];
  3699. }
  3700. else { // positional argument (implicit)
  3701. arg = argv[cursor++];
  3702. }
  3703. if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
  3704. throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
  3705. }
  3706. // Jed EDIT
  3707. if ( typeof arg == 'undefined' || arg === null ) {
  3708. arg = '';
  3709. }
  3710. // Jed EDIT
  3711. switch (match[8]) {
  3712. case 'b': arg = arg.toString(2); break;
  3713. case 'c': arg = String.fromCharCode(arg); break;
  3714. case 'd': arg = parseInt(arg, 10); break;
  3715. case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
  3716. case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
  3717. case 'o': arg = arg.toString(8); break;
  3718. case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
  3719. case 'u': arg = Math.abs(arg); break;
  3720. case 'x': arg = arg.toString(16); break;
  3721. case 'X': arg = arg.toString(16).toUpperCase(); break;
  3722. }
  3723. arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
  3724. pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
  3725. pad_length = match[6] - String(arg).length;
  3726. pad = match[6] ? str_repeat(pad_character, pad_length) : '';
  3727. output.push(match[5] ? arg + pad : pad + arg);
  3728. }
  3729. }
  3730. return output.join('');
  3731. };
  3732. str_format.cache = {};
  3733. str_format.parse = function(fmt) {
  3734. var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
  3735. while (_fmt) {
  3736. if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
  3737. parse_tree.push(match[0]);
  3738. }
  3739. else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
  3740. parse_tree.push('%');
  3741. }
  3742. else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
  3743. if (match[2]) {
  3744. arg_names |= 1;
  3745. var field_list = [], replacement_field = match[2], field_match = [];
  3746. if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
  3747. field_list.push(field_match[1]);
  3748. while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
  3749. if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
  3750. field_list.push(field_match[1]);
  3751. }
  3752. else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
  3753. field_list.push(field_match[1]);
  3754. }
  3755. else {
  3756. throw('[sprintf] huh?');
  3757. }
  3758. }
  3759. }
  3760. else {
  3761. throw('[sprintf] huh?');
  3762. }
  3763. match[2] = field_list;
  3764. }
  3765. else {
  3766. arg_names |= 2;
  3767. }
  3768. if (arg_names === 3) {
  3769. throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
  3770. }
  3771. parse_tree.push(match);
  3772. }
  3773. else {
  3774. throw('[sprintf] huh?');
  3775. }
  3776. _fmt = _fmt.substring(match[0].length);
  3777. }
  3778. return parse_tree;
  3779. };
  3780. return str_format;
  3781. })();
  3782. var vsprintf = function(fmt, argv) {
  3783. argv.unshift(fmt);
  3784. return sprintf.apply(null, argv);
  3785. };
  3786. Jed.parse_plural = function ( plural_forms, n ) {
  3787. plural_forms = plural_forms.replace(/n/g, n);
  3788. return Jed.parse_expression(plural_forms);
  3789. };
  3790. Jed.sprintf = function ( fmt, args ) {
  3791. if ( {}.toString.call( args ) == '[object Array]' ) {
  3792. return vsprintf( fmt, [].slice.call(args) );
  3793. }
  3794. return sprintf.apply(this, [].slice.call(arguments) );
  3795. };
  3796. Jed.prototype.sprintf = function () {
  3797. return Jed.sprintf.apply(this, arguments);
  3798. };
  3799. // END sprintf Implementation
  3800. // Start the Plural forms section
  3801. // This is a full plural form expression parser. It is used to avoid
  3802. // running 'eval' or 'new Function' directly against the plural
  3803. // forms.
  3804. //
  3805. // This can be important if you get translations done through a 3rd
  3806. // party vendor. I encourage you to use this instead, however, I
  3807. // also will provide a 'precompiler' that you can use at build time
  3808. // to output valid/safe function representations of the plural form
  3809. // expressions. This means you can build this code out for the most
  3810. // part.
  3811. Jed.PF = {};
  3812. Jed.PF.parse = function ( p ) {
  3813. var plural_str = Jed.PF.extractPluralExpr( p );
  3814. return Jed.PF.parser.parse.call(Jed.PF.parser, plural_str);
  3815. };
  3816. Jed.PF.compile = function ( p ) {
  3817. // Handle trues and falses as 0 and 1
  3818. function imply( val ) {
  3819. return (val === true ? 1 : val ? val : 0);
  3820. }
  3821. var ast = Jed.PF.parse( p );
  3822. return function ( n ) {
  3823. return imply( Jed.PF.interpreter( ast )( n ) );
  3824. };
  3825. };
  3826. Jed.PF.interpreter = function ( ast ) {
  3827. return function ( n ) {
  3828. var res;
  3829. switch ( ast.type ) {
  3830. case 'GROUP':
  3831. return Jed.PF.interpreter( ast.expr )( n );
  3832. case 'TERNARY':
  3833. if ( Jed.PF.interpreter( ast.expr )( n ) ) {
  3834. return Jed.PF.interpreter( ast.truthy )( n );
  3835. }
  3836. return Jed.PF.interpreter( ast.falsey )( n );
  3837. case 'OR':
  3838. return Jed.PF.interpreter( ast.left )( n ) || Jed.PF.interpreter( ast.right )( n );
  3839. case 'AND':
  3840. return Jed.PF.interpreter( ast.left )( n ) && Jed.PF.interpreter( ast.right )( n );
  3841. case 'LT':
  3842. return Jed.PF.interpreter( ast.left )( n ) < Jed.PF.interpreter( ast.right )( n );
  3843. case 'GT':
  3844. return Jed.PF.interpreter( ast.left )( n ) > Jed.PF.interpreter( ast.right )( n );
  3845. case 'LTE':
  3846. return Jed.PF.interpreter( ast.left )( n ) <= Jed.PF.interpreter( ast.right )( n );
  3847. case 'GTE':
  3848. return Jed.PF.interpreter( ast.left )( n ) >= Jed.PF.interpreter( ast.right )( n );
  3849. case 'EQ':
  3850. return Jed.PF.interpreter( ast.left )( n ) == Jed.PF.interpreter( ast.right )( n );
  3851. case 'NEQ':
  3852. return Jed.PF.interpreter( ast.left )( n ) != Jed.PF.interpreter( ast.right )( n );
  3853. case 'MOD':
  3854. return Jed.PF.interpreter( ast.left )( n ) % Jed.PF.interpreter( ast.right )( n );
  3855. case 'VAR':
  3856. return n;
  3857. case 'NUM':
  3858. return ast.val;
  3859. default:
  3860. throw new Error("Invalid Token found.");
  3861. }
  3862. };
  3863. };
  3864. Jed.PF.extractPluralExpr = function ( p ) {
  3865. // trim first
  3866. p = p.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
  3867. if (! /;\s*$/.test(p)) {
  3868. p = p.concat(';');
  3869. }
  3870. var nplurals_re = /nplurals\=(\d+);/,
  3871. plural_re = /plural\=(.*);/,
  3872. nplurals_matches = p.match( nplurals_re ),
  3873. res = {},
  3874. plural_matches;
  3875. // Find the nplurals number
  3876. if ( nplurals_matches.length > 1 ) {
  3877. res.nplurals = nplurals_matches[1];
  3878. }
  3879. else {
  3880. throw new Error('nplurals not found in plural_forms string: ' + p );
  3881. }
  3882. // remove that data to get to the formula
  3883. p = p.replace( nplurals_re, "" );
  3884. plural_matches = p.match( plural_re );
  3885. if (!( plural_matches && plural_matches.length > 1 ) ) {
  3886. throw new Error('`plural` expression not found: ' + p);
  3887. }
  3888. return plural_matches[ 1 ];
  3889. };
  3890. /* Jison generated parser */
  3891. Jed.PF.parser = (function(){
  3892. var parser = {trace: function trace() { },
  3893. yy: {},
  3894. symbols_: {"error":2,"expressions":3,"e":4,"EOF":5,"?":6,":":7,"||":8,"&&":9,"<":10,"<=":11,">":12,">=":13,"!=":14,"==":15,"%":16,"(":17,")":18,"n":19,"NUMBER":20,"$accept":0,"$end":1},
  3895. terminals_: {2:"error",5:"EOF",6:"?",7:":",8:"||",9:"&&",10:"<",11:"<=",12:">",13:">=",14:"!=",15:"==",16:"%",17:"(",18:")",19:"n",20:"NUMBER"},
  3896. productions_: [0,[3,2],[4,5],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,1],[4,1]],
  3897. performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
  3898. var $0 = $$.length - 1;
  3899. switch (yystate) {
  3900. case 1: return { type : 'GROUP', expr: $$[$0-1] };
  3901. break;
  3902. case 2:this.$ = { type: 'TERNARY', expr: $$[$0-4], truthy : $$[$0-2], falsey: $$[$0] };
  3903. break;
  3904. case 3:this.$ = { type: "OR", left: $$[$0-2], right: $$[$0] };
  3905. break;
  3906. case 4:this.$ = { type: "AND", left: $$[$0-2], right: $$[$0] };
  3907. break;
  3908. case 5:this.$ = { type: 'LT', left: $$[$0-2], right: $$[$0] };
  3909. break;
  3910. case 6:this.$ = { type: 'LTE', left: $$[$0-2], right: $$[$0] };
  3911. break;
  3912. case 7:this.$ = { type: 'GT', left: $$[$0-2], right: $$[$0] };
  3913. break;
  3914. case 8:this.$ = { type: 'GTE', left: $$[$0-2], right: $$[$0] };
  3915. break;
  3916. case 9:this.$ = { type: 'NEQ', left: $$[$0-2], right: $$[$0] };
  3917. break;
  3918. case 10:this.$ = { type: 'EQ', left: $$[$0-2], right: $$[$0] };
  3919. break;
  3920. case 11:this.$ = { type: 'MOD', left: $$[$0-2], right: $$[$0] };
  3921. break;
  3922. case 12:this.$ = { type: 'GROUP', expr: $$[$0-1] };
  3923. break;
  3924. case 13:this.$ = { type: 'VAR' };
  3925. break;
  3926. case 14:this.$ = { type: 'NUM', val: Number(yytext) };
  3927. break;
  3928. }
  3929. },
  3930. table: [{3:1,4:2,17:[1,3],19:[1,4],20:[1,5]},{1:[3]},{5:[1,6],6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{4:17,17:[1,3],19:[1,4],20:[1,5]},{5:[2,13],6:[2,13],7:[2,13],8:[2,13],9:[2,13],10:[2,13],11:[2,13],12:[2,13],13:[2,13],14:[2,13],15:[2,13],16:[2,13],18:[2,13]},{5:[2,14],6:[2,14],7:[2,14],8:[2,14],9:[2,14],10:[2,14],11:[2,14],12:[2,14],13:[2,14],14:[2,14],15:[2,14],16:[2,14],18:[2,14]},{1:[2,1]},{4:18,17:[1,3],19:[1,4],20:[1,5]},{4:19,17:[1,3],19:[1,4],20:[1,5]},{4:20,17:[1,3],19:[1,4],20:[1,5]},{4:21,17:[1,3],19:[1,4],20:[1,5]},{4:22,17:[1,3],19:[1,4],20:[1,5]},{4:23,17:[1,3],19:[1,4],20:[1,5]},{4:24,17:[1,3],19:[1,4],20:[1,5]},{4:25,17:[1,3],19:[1,4],20:[1,5]},{4:26,17:[1,3],19:[1,4],20:[1,5]},{4:27,17:[1,3],19:[1,4],20:[1,5]},{6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[1,28]},{6:[1,7],7:[1,29],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{5:[2,3],6:[2,3],7:[2,3],8:[2,3],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,3]},{5:[2,4],6:[2,4],7:[2,4],8:[2,4],9:[2,4],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,4]},{5:[2,5],6:[2,5],7:[2,5],8:[2,5],9:[2,5],10:[2,5],11:[2,5],12:[2,5],13:[2,5],14:[2,5],15:[2,5],16:[1,16],18:[2,5]},{5:[2,6],6:[2,6],7:[2,6],8:[2,6],9:[2,6],10:[2,6],11:[2,6],12:[2,6],13:[2,6],14:[2,6],15:[2,6],16:[1,16],18:[2,6]},{5:[2,7],6:[2,7],7:[2,7],8:[2,7],9:[2,7],10:[2,7],11:[2,7],12:[2,7],13:[2,7],14:[2,7],15:[2,7],16:[1,16],18:[2,7]},{5:[2,8],6:[2,8],7:[2,8],8:[2,8],9:[2,8],10:[2,8],11:[2,8],12:[2,8],13:[2,8],14:[2,8],15:[2,8],16:[1,16],18:[2,8]},{5:[2,9],6:[2,9],7:[2,9],8:[2,9],9:[2,9],10:[2,9],11:[2,9],12:[2,9],13:[2,9],14:[2,9],15:[2,9],16:[1,16],18:[2,9]},{5:[2,10],6:[2,10],7:[2,10],8:[2,10],9:[2,10],10:[2,10],11:[2,10],12:[2,10],13:[2,10],14:[2,10],15:[2,10],16:[1,16],18:[2,10]},{5:[2,11],6:[2,11],7:[2,11],8:[2,11],9:[2,11],10:[2,11],11:[2,11],12:[2,11],13:[2,11],14:[2,11],15:[2,11],16:[2,11],18:[2,11]},{5:[2,12],6:[2,12],7:[2,12],8:[2,12],9:[2,12],10:[2,12],11:[2,12],12:[2,12],13:[2,12],14:[2,12],15:[2,12],16:[2,12],18:[2,12]},{4:30,17:[1,3],19:[1,4],20:[1,5]},{5:[2,2],6:[1,7],7:[2,2],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,2]}],
  3931. defaultActions: {6:[2,1]},
  3932. parseError: function parseError(str, hash) {
  3933. throw new Error(str);
  3934. },
  3935. parse: function parse(input) {
  3936. var self = this,
  3937. stack = [0],
  3938. vstack = [null], // semantic value stack
  3939. lstack = [], // location stack
  3940. table = this.table,
  3941. yytext = '',
  3942. yylineno = 0,
  3943. yyleng = 0,
  3944. recovering = 0,
  3945. TERROR = 2,
  3946. EOF = 1;
  3947. //this.reductionCount = this.shiftCount = 0;
  3948. this.lexer.setInput(input);
  3949. this.lexer.yy = this.yy;
  3950. this.yy.lexer = this.lexer;
  3951. if (typeof this.lexer.yylloc == 'undefined')
  3952. this.lexer.yylloc = {};
  3953. var yyloc = this.lexer.yylloc;
  3954. lstack.push(yyloc);
  3955. if (typeof this.yy.parseError === 'function')
  3956. this.parseError = this.yy.parseError;
  3957. function popStack (n) {
  3958. stack.length = stack.length - 2*n;
  3959. vstack.length = vstack.length - n;
  3960. lstack.length = lstack.length - n;
  3961. }
  3962. function lex() {
  3963. var token;
  3964. token = self.lexer.lex() || 1; // $end = 1
  3965. // if token isn't its numeric value, convert
  3966. if (typeof token !== 'number') {
  3967. token = self.symbols_[token] || token;
  3968. }
  3969. return token;
  3970. }
  3971. var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected;
  3972. while (true) {
  3973. // retreive state number from top of stack
  3974. state = stack[stack.length-1];
  3975. // use default actions if available
  3976. if (this.defaultActions[state]) {
  3977. action = this.defaultActions[state];
  3978. } else {
  3979. if (symbol == null)
  3980. symbol = lex();
  3981. // read action for current state and first input
  3982. action = table[state] && table[state][symbol];
  3983. }
  3984. // handle parse error
  3985. _handle_error:
  3986. if (typeof action === 'undefined' || !action.length || !action[0]) {
  3987. if (!recovering) {
  3988. // Report error
  3989. expected = [];
  3990. for (p in table[state]) if (this.terminals_[p] && p > 2) {
  3991. expected.push("'"+this.terminals_[p]+"'");
  3992. }
  3993. var errStr = '';
  3994. if (this.lexer.showPosition) {
  3995. errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'";
  3996. } else {
  3997. errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " +
  3998. (symbol == 1 /*EOF*/ ? "end of input" :
  3999. ("'"+(this.terminals_[symbol] || symbol)+"'"));
  4000. }
  4001. this.parseError(errStr,
  4002. {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected});
  4003. }
  4004. // just recovered from another error
  4005. if (recovering == 3) {
  4006. if (symbol == EOF) {
  4007. throw new Error(errStr || 'Parsing halted.');
  4008. }
  4009. // discard current lookahead and grab another
  4010. yyleng = this.lexer.yyleng;
  4011. yytext = this.lexer.yytext;
  4012. yylineno = this.lexer.yylineno;
  4013. yyloc = this.lexer.yylloc;
  4014. symbol = lex();
  4015. }
  4016. // try to recover from error
  4017. while (1) {
  4018. // check for error recovery rule in this state
  4019. if ((TERROR.toString()) in table[state]) {
  4020. break;
  4021. }
  4022. if (state == 0) {
  4023. throw new Error(errStr || 'Parsing halted.');
  4024. }
  4025. popStack(1);
  4026. state = stack[stack.length-1];
  4027. }
  4028. preErrorSymbol = symbol; // save the lookahead token
  4029. symbol = TERROR; // insert generic error symbol as new lookahead
  4030. state = stack[stack.length-1];
  4031. action = table[state] && table[state][TERROR];
  4032. recovering = 3; // allow 3 real symbols to be shifted before reporting a new error
  4033. }
  4034. // this shouldn't happen, unless resolve defaults are off
  4035. if (action[0] instanceof Array && action.length > 1) {
  4036. throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol);
  4037. }
  4038. switch (action[0]) {
  4039. case 1: // shift
  4040. //this.shiftCount++;
  4041. stack.push(symbol);
  4042. vstack.push(this.lexer.yytext);
  4043. lstack.push(this.lexer.yylloc);
  4044. stack.push(action[1]); // push state
  4045. symbol = null;
  4046. if (!preErrorSymbol) { // normal execution/no error
  4047. yyleng = this.lexer.yyleng;
  4048. yytext = this.lexer.yytext;
  4049. yylineno = this.lexer.yylineno;
  4050. yyloc = this.lexer.yylloc;
  4051. if (recovering > 0)
  4052. recovering--;
  4053. } else { // error just occurred, resume old lookahead f/ before error
  4054. symbol = preErrorSymbol;
  4055. preErrorSymbol = null;
  4056. }
  4057. break;
  4058. case 2: // reduce
  4059. //this.reductionCount++;
  4060. len = this.productions_[action[1]][1];
  4061. // perform semantic action
  4062. yyval.$ = vstack[vstack.length-len]; // default to $$ = $1
  4063. // default location, uses first token for firsts, last for lasts
  4064. yyval._$ = {
  4065. first_line: lstack[lstack.length-(len||1)].first_line,
  4066. last_line: lstack[lstack.length-1].last_line,
  4067. first_column: lstack[lstack.length-(len||1)].first_column,
  4068. last_column: lstack[lstack.length-1].last_column
  4069. };
  4070. r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack);
  4071. if (typeof r !== 'undefined') {
  4072. return r;
  4073. }
  4074. // pop off stack
  4075. if (len) {
  4076. stack = stack.slice(0,-1*len*2);
  4077. vstack = vstack.slice(0, -1*len);
  4078. lstack = lstack.slice(0, -1*len);
  4079. }
  4080. stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce)
  4081. vstack.push(yyval.$);
  4082. lstack.push(yyval._$);
  4083. // goto new state = table[STATE][NONTERMINAL]
  4084. newState = table[stack[stack.length-2]][stack[stack.length-1]];
  4085. stack.push(newState);
  4086. break;
  4087. case 3: // accept
  4088. return true;
  4089. }
  4090. }
  4091. return true;
  4092. }};/* Jison generated lexer */
  4093. var lexer = (function(){
  4094. var lexer = ({EOF:1,
  4095. parseError:function parseError(str, hash) {
  4096. if (this.yy.parseError) {
  4097. this.yy.parseError(str, hash);
  4098. } else {
  4099. throw new Error(str);
  4100. }
  4101. },
  4102. setInput:function (input) {
  4103. this._input = input;
  4104. this._more = this._less = this.done = false;
  4105. this.yylineno = this.yyleng = 0;
  4106. this.yytext = this.matched = this.match = '';
  4107. this.conditionStack = ['INITIAL'];
  4108. this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0};
  4109. return this;
  4110. },
  4111. input:function () {
  4112. var ch = this._input[0];
  4113. this.yytext+=ch;
  4114. this.yyleng++;
  4115. this.match+=ch;
  4116. this.matched+=ch;
  4117. var lines = ch.match(/\n/);
  4118. if (lines) this.yylineno++;
  4119. this._input = this._input.slice(1);
  4120. return ch;
  4121. },
  4122. unput:function (ch) {
  4123. this._input = ch + this._input;
  4124. return this;
  4125. },
  4126. more:function () {
  4127. this._more = true;
  4128. return this;
  4129. },
  4130. pastInput:function () {
  4131. var past = this.matched.substr(0, this.matched.length - this.match.length);
  4132. return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, "");
  4133. },
  4134. upcomingInput:function () {
  4135. var next = this.match;
  4136. if (next.length < 20) {
  4137. next += this._input.substr(0, 20-next.length);
  4138. }
  4139. return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, "");
  4140. },
  4141. showPosition:function () {
  4142. var pre = this.pastInput();
  4143. var c = new Array(pre.length + 1).join("-");
  4144. return pre + this.upcomingInput() + "\n" + c+"^";
  4145. },
  4146. next:function () {
  4147. if (this.done) {
  4148. return this.EOF;
  4149. }
  4150. if (!this._input) this.done = true;
  4151. var token,
  4152. match,
  4153. col,
  4154. lines;
  4155. if (!this._more) {
  4156. this.yytext = '';
  4157. this.match = '';
  4158. }
  4159. var rules = this._currentRules();
  4160. for (var i=0;i < rules.length; i++) {
  4161. match = this._input.match(this.rules[rules[i]]);
  4162. if (match) {
  4163. lines = match[0].match(/\n.*/g);
  4164. if (lines) this.yylineno += lines.length;
  4165. this.yylloc = {first_line: this.yylloc.last_line,
  4166. last_line: this.yylineno+1,
  4167. first_column: this.yylloc.last_column,
  4168. last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length}
  4169. this.yytext += match[0];
  4170. this.match += match[0];
  4171. this.matches = match;
  4172. this.yyleng = this.yytext.length;
  4173. this._more = false;
  4174. this._input = this._input.slice(match[0].length);
  4175. this.matched += match[0];
  4176. token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]);
  4177. if (token) return token;
  4178. else return;
  4179. }
  4180. }
  4181. if (this._input === "") {
  4182. return this.EOF;
  4183. } else {
  4184. this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(),
  4185. {text: "", token: null, line: this.yylineno});
  4186. }
  4187. },
  4188. lex:function lex() {
  4189. var r = this.next();
  4190. if (typeof r !== 'undefined') {
  4191. return r;
  4192. } else {
  4193. return this.lex();
  4194. }
  4195. },
  4196. begin:function begin(condition) {
  4197. this.conditionStack.push(condition);
  4198. },
  4199. popState:function popState() {
  4200. return this.conditionStack.pop();
  4201. },
  4202. _currentRules:function _currentRules() {
  4203. return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules;
  4204. },
  4205. topState:function () {
  4206. return this.conditionStack[this.conditionStack.length-2];
  4207. },
  4208. pushState:function begin(condition) {
  4209. this.begin(condition);
  4210. }});
  4211. lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) {
  4212. var YYSTATE=YY_START;
  4213. switch($avoiding_name_collisions) {
  4214. case 0:/* skip whitespace */
  4215. break;
  4216. case 1:return 20
  4217. break;
  4218. case 2:return 19
  4219. break;
  4220. case 3:return 8
  4221. break;
  4222. case 4:return 9
  4223. break;
  4224. case 5:return 6
  4225. break;
  4226. case 6:return 7
  4227. break;
  4228. case 7:return 11
  4229. break;
  4230. case 8:return 13
  4231. break;
  4232. case 9:return 10
  4233. break;
  4234. case 10:return 12
  4235. break;
  4236. case 11:return 14
  4237. break;
  4238. case 12:return 15
  4239. break;
  4240. case 13:return 16
  4241. break;
  4242. case 14:return 17
  4243. break;
  4244. case 15:return 18
  4245. break;
  4246. case 16:return 5
  4247. break;
  4248. case 17:return 'INVALID'
  4249. break;
  4250. }
  4251. };
  4252. lexer.rules = [/^\s+/,/^[0-9]+(\.[0-9]+)?\b/,/^n\b/,/^\|\|/,/^&&/,/^\?/,/^:/,/^<=/,/^>=/,/^</,/^>/,/^!=/,/^==/,/^%/,/^\(/,/^\)/,/^$/,/^./];
  4253. lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],"inclusive":true}};return lexer;})()
  4254. parser.lexer = lexer;
  4255. return parser;
  4256. })();
  4257. // End parser
  4258. // Handle node, amd, and global systems
  4259. if (typeof exports !== 'undefined') {
  4260. if (typeof module !== 'undefined' && module.exports) {
  4261. exports = module.exports = Jed;
  4262. }
  4263. exports.Jed = Jed;
  4264. }
  4265. else {
  4266. if (typeof define === 'function' && define.amd) {
  4267. define('jed', [],function() {
  4268. return Jed;
  4269. });
  4270. }
  4271. // Leak a global regardless of module system
  4272. root['Jed'] = Jed;
  4273. }
  4274. })(this);
  4275. /**
  4276. * @license text 2.0.15 Copyright jQuery Foundation and other contributors.
  4277. * Released under MIT license, http://github.com/requirejs/text/LICENSE
  4278. */
  4279. /*jslint regexp: true */
  4280. /*global require, XMLHttpRequest, ActiveXObject,
  4281. define, window, process, Packages,
  4282. java, location, Components, FileUtils */
  4283. define('text',['module'], function (module) {
  4284. 'use strict';
  4285. var text, fs, Cc, Ci, xpcIsWindows,
  4286. progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'],
  4287. xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,
  4288. bodyRegExp = /<body[^>]*>\s*([\s\S]+)\s*<\/body>/im,
  4289. hasLocation = typeof location !== 'undefined' && location.href,
  4290. defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''),
  4291. defaultHostName = hasLocation && location.hostname,
  4292. defaultPort = hasLocation && (location.port || undefined),
  4293. buildMap = {},
  4294. masterConfig = (module.config && module.config()) || {};
  4295. function useDefault(value, defaultValue) {
  4296. return value === undefined || value === '' ? defaultValue : value;
  4297. }
  4298. //Allow for default ports for http and https.
  4299. function isSamePort(protocol1, port1, protocol2, port2) {
  4300. if (port1 === port2) {
  4301. return true;
  4302. } else if (protocol1 === protocol2) {
  4303. if (protocol1 === 'http') {
  4304. return useDefault(port1, '80') === useDefault(port2, '80');
  4305. } else if (protocol1 === 'https') {
  4306. return useDefault(port1, '443') === useDefault(port2, '443');
  4307. }
  4308. }
  4309. return false;
  4310. }
  4311. text = {
  4312. version: '2.0.15',
  4313. strip: function (content) {
  4314. //Strips <?xml ...?> declarations so that external SVG and XML
  4315. //documents can be added to a document without worry. Also, if the string
  4316. //is an HTML document, only the part inside the body tag is returned.
  4317. if (content) {
  4318. content = content.replace(xmlRegExp, "");
  4319. var matches = content.match(bodyRegExp);
  4320. if (matches) {
  4321. content = matches[1];
  4322. }
  4323. } else {
  4324. content = "";
  4325. }
  4326. return content;
  4327. },
  4328. jsEscape: function (content) {
  4329. return content.replace(/(['\\])/g, '\\$1')
  4330. .replace(/[\f]/g, "\\f")
  4331. .replace(/[\b]/g, "\\b")
  4332. .replace(/[\n]/g, "\\n")
  4333. .replace(/[\t]/g, "\\t")
  4334. .replace(/[\r]/g, "\\r")
  4335. .replace(/[\u2028]/g, "\\u2028")
  4336. .replace(/[\u2029]/g, "\\u2029");
  4337. },
  4338. createXhr: masterConfig.createXhr || function () {
  4339. //Would love to dump the ActiveX crap in here. Need IE 6 to die first.
  4340. var xhr, i, progId;
  4341. if (typeof XMLHttpRequest !== "undefined") {
  4342. return new XMLHttpRequest();
  4343. } else if (typeof ActiveXObject !== "undefined") {
  4344. for (i = 0; i < 3; i += 1) {
  4345. progId = progIds[i];
  4346. try {
  4347. xhr = new ActiveXObject(progId);
  4348. } catch (e) {}
  4349. if (xhr) {
  4350. progIds = [progId]; // so faster next time
  4351. break;
  4352. }
  4353. }
  4354. }
  4355. return xhr;
  4356. },
  4357. /**
  4358. * Parses a resource name into its component parts. Resource names
  4359. * look like: module/name.ext!strip, where the !strip part is
  4360. * optional.
  4361. * @param {String} name the resource name
  4362. * @returns {Object} with properties "moduleName", "ext" and "strip"
  4363. * where strip is a boolean.
  4364. */
  4365. parseName: function (name) {
  4366. var modName, ext, temp,
  4367. strip = false,
  4368. index = name.lastIndexOf("."),
  4369. isRelative = name.indexOf('./') === 0 ||
  4370. name.indexOf('../') === 0;
  4371. if (index !== -1 && (!isRelative || index > 1)) {
  4372. modName = name.substring(0, index);
  4373. ext = name.substring(index + 1);
  4374. } else {
  4375. modName = name;
  4376. }
  4377. temp = ext || modName;
  4378. index = temp.indexOf("!");
  4379. if (index !== -1) {
  4380. //Pull off the strip arg.
  4381. strip = temp.substring(index + 1) === "strip";
  4382. temp = temp.substring(0, index);
  4383. if (ext) {
  4384. ext = temp;
  4385. } else {
  4386. modName = temp;
  4387. }
  4388. }
  4389. return {
  4390. moduleName: modName,
  4391. ext: ext,
  4392. strip: strip
  4393. };
  4394. },
  4395. xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/,
  4396. /**
  4397. * Is an URL on another domain. Only works for browser use, returns
  4398. * false in non-browser environments. Only used to know if an
  4399. * optimized .js version of a text resource should be loaded
  4400. * instead.
  4401. * @param {String} url
  4402. * @returns Boolean
  4403. */
  4404. useXhr: function (url, protocol, hostname, port) {
  4405. var uProtocol, uHostName, uPort,
  4406. match = text.xdRegExp.exec(url);
  4407. if (!match) {
  4408. return true;
  4409. }
  4410. uProtocol = match[2];
  4411. uHostName = match[3];
  4412. uHostName = uHostName.split(':');
  4413. uPort = uHostName[1];
  4414. uHostName = uHostName[0];
  4415. return (!uProtocol || uProtocol === protocol) &&
  4416. (!uHostName || uHostName.toLowerCase() === hostname.toLowerCase()) &&
  4417. ((!uPort && !uHostName) || isSamePort(uProtocol, uPort, protocol, port));
  4418. },
  4419. finishLoad: function (name, strip, content, onLoad) {
  4420. content = strip ? text.strip(content) : content;
  4421. if (masterConfig.isBuild) {
  4422. buildMap[name] = content;
  4423. }
  4424. onLoad(content);
  4425. },
  4426. load: function (name, req, onLoad, config) {
  4427. //Name has format: some.module.filext!strip
  4428. //The strip part is optional.
  4429. //if strip is present, then that means only get the string contents
  4430. //inside a body tag in an HTML string. For XML/SVG content it means
  4431. //removing the <?xml ...?> declarations so the content can be inserted
  4432. //into the current doc without problems.
  4433. // Do not bother with the work if a build and text will
  4434. // not be inlined.
  4435. if (config && config.isBuild && !config.inlineText) {
  4436. onLoad();
  4437. return;
  4438. }
  4439. masterConfig.isBuild = config && config.isBuild;
  4440. var parsed = text.parseName(name),
  4441. nonStripName = parsed.moduleName +
  4442. (parsed.ext ? '.' + parsed.ext : ''),
  4443. url = req.toUrl(nonStripName),
  4444. useXhr = (masterConfig.useXhr) ||
  4445. text.useXhr;
  4446. // Do not load if it is an empty: url
  4447. if (url.indexOf('empty:') === 0) {
  4448. onLoad();
  4449. return;
  4450. }
  4451. //Load the text. Use XHR if possible and in a browser.
  4452. if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) {
  4453. text.get(url, function (content) {
  4454. text.finishLoad(name, parsed.strip, content, onLoad);
  4455. }, function (err) {
  4456. if (onLoad.error) {
  4457. onLoad.error(err);
  4458. }
  4459. });
  4460. } else {
  4461. //Need to fetch the resource across domains. Assume
  4462. //the resource has been optimized into a JS module. Fetch
  4463. //by the module name + extension, but do not include the
  4464. //!strip part to avoid file system issues.
  4465. req([nonStripName], function (content) {
  4466. text.finishLoad(parsed.moduleName + '.' + parsed.ext,
  4467. parsed.strip, content, onLoad);
  4468. });
  4469. }
  4470. },
  4471. write: function (pluginName, moduleName, write, config) {
  4472. if (buildMap.hasOwnProperty(moduleName)) {
  4473. var content = text.jsEscape(buildMap[moduleName]);
  4474. write.asModule(pluginName + "!" + moduleName,
  4475. "define(function () { return '" +
  4476. content +
  4477. "';});\n");
  4478. }
  4479. },
  4480. writeFile: function (pluginName, moduleName, req, write, config) {
  4481. var parsed = text.parseName(moduleName),
  4482. extPart = parsed.ext ? '.' + parsed.ext : '',
  4483. nonStripName = parsed.moduleName + extPart,
  4484. //Use a '.js' file name so that it indicates it is a
  4485. //script that can be loaded across domains.
  4486. fileName = req.toUrl(parsed.moduleName + extPart) + '.js';
  4487. //Leverage own load() method to load plugin value, but only
  4488. //write out values that do not have the strip argument,
  4489. //to avoid any potential issues with ! in file names.
  4490. text.load(nonStripName, req, function (value) {
  4491. //Use own write() method to construct full module value.
  4492. //But need to create shell that translates writeFile's
  4493. //write() to the right interface.
  4494. var textWrite = function (contents) {
  4495. return write(fileName, contents);
  4496. };
  4497. textWrite.asModule = function (moduleName, contents) {
  4498. return write.asModule(moduleName, fileName, contents);
  4499. };
  4500. text.write(pluginName, nonStripName, textWrite, config);
  4501. }, config);
  4502. }
  4503. };
  4504. if (masterConfig.env === 'node' || (!masterConfig.env &&
  4505. typeof process !== "undefined" &&
  4506. process.versions &&
  4507. !!process.versions.node &&
  4508. !process.versions['node-webkit'] &&
  4509. !process.versions['atom-shell'])) {
  4510. //Using special require.nodeRequire, something added by r.js.
  4511. fs = require.nodeRequire('fs');
  4512. text.get = function (url, callback, errback) {
  4513. try {
  4514. var file = fs.readFileSync(url, 'utf8');
  4515. //Remove BOM (Byte Mark Order) from utf8 files if it is there.
  4516. if (file[0] === '\uFEFF') {
  4517. file = file.substring(1);
  4518. }
  4519. callback(file);
  4520. } catch (e) {
  4521. if (errback) {
  4522. errback(e);
  4523. }
  4524. }
  4525. };
  4526. } else if (masterConfig.env === 'xhr' || (!masterConfig.env &&
  4527. text.createXhr())) {
  4528. text.get = function (url, callback, errback, headers) {
  4529. var xhr = text.createXhr(), header;
  4530. xhr.open('GET', url, true);
  4531. //Allow plugins direct access to xhr headers
  4532. if (headers) {
  4533. for (header in headers) {
  4534. if (headers.hasOwnProperty(header)) {
  4535. xhr.setRequestHeader(header.toLowerCase(), headers[header]);
  4536. }
  4537. }
  4538. }
  4539. //Allow overrides specified in config
  4540. if (masterConfig.onXhr) {
  4541. masterConfig.onXhr(xhr, url);
  4542. }
  4543. xhr.onreadystatechange = function (evt) {
  4544. var status, err;
  4545. //Do not explicitly handle errors, those should be
  4546. //visible via console output in the browser.
  4547. if (xhr.readyState === 4) {
  4548. status = xhr.status || 0;
  4549. if (status > 399 && status < 600) {
  4550. //An http 4xx or 5xx error. Signal an error.
  4551. err = new Error(url + ' HTTP status: ' + status);
  4552. err.xhr = xhr;
  4553. if (errback) {
  4554. errback(err);
  4555. }
  4556. } else {
  4557. callback(xhr.responseText);
  4558. }
  4559. if (masterConfig.onXhrComplete) {
  4560. masterConfig.onXhrComplete(xhr, url);
  4561. }
  4562. }
  4563. };
  4564. xhr.send(null);
  4565. };
  4566. } else if (masterConfig.env === 'rhino' || (!masterConfig.env &&
  4567. typeof Packages !== 'undefined' && typeof java !== 'undefined')) {
  4568. //Why Java, why is this so awkward?
  4569. text.get = function (url, callback) {
  4570. var stringBuffer, line,
  4571. encoding = "utf-8",
  4572. file = new java.io.File(url),
  4573. lineSeparator = java.lang.System.getProperty("line.separator"),
  4574. input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)),
  4575. content = '';
  4576. try {
  4577. stringBuffer = new java.lang.StringBuffer();
  4578. line = input.readLine();
  4579. // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324
  4580. // http://www.unicode.org/faq/utf_bom.html
  4581. // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK:
  4582. // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058
  4583. if (line && line.length() && line.charAt(0) === 0xfeff) {
  4584. // Eat the BOM, since we've already found the encoding on this file,
  4585. // and we plan to concatenating this buffer with others; the BOM should
  4586. // only appear at the top of a file.
  4587. line = line.substring(1);
  4588. }
  4589. if (line !== null) {
  4590. stringBuffer.append(line);
  4591. }
  4592. while ((line = input.readLine()) !== null) {
  4593. stringBuffer.append(lineSeparator);
  4594. stringBuffer.append(line);
  4595. }
  4596. //Make sure we return a JavaScript string and not a Java string.
  4597. content = String(stringBuffer.toString()); //String
  4598. } finally {
  4599. input.close();
  4600. }
  4601. callback(content);
  4602. };
  4603. } else if (masterConfig.env === 'xpconnect' || (!masterConfig.env &&
  4604. typeof Components !== 'undefined' && Components.classes &&
  4605. Components.interfaces)) {
  4606. //Avert your gaze!
  4607. Cc = Components.classes;
  4608. Ci = Components.interfaces;
  4609. Components.utils['import']('resource://gre/modules/FileUtils.jsm');
  4610. xpcIsWindows = ('@mozilla.org/windows-registry-key;1' in Cc);
  4611. text.get = function (url, callback) {
  4612. var inStream, convertStream, fileObj,
  4613. readData = {};
  4614. if (xpcIsWindows) {
  4615. url = url.replace(/\//g, '\\');
  4616. }
  4617. fileObj = new FileUtils.File(url);
  4618. //XPCOM, you so crazy
  4619. try {
  4620. inStream = Cc['@mozilla.org/network/file-input-stream;1']
  4621. .createInstance(Ci.nsIFileInputStream);
  4622. inStream.init(fileObj, 1, 0, false);
  4623. convertStream = Cc['@mozilla.org/intl/converter-input-stream;1']
  4624. .createInstance(Ci.nsIConverterInputStream);
  4625. convertStream.init(inStream, "utf-8", inStream.available(),
  4626. Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
  4627. convertStream.readString(inStream.available(), readData);
  4628. convertStream.close();
  4629. inStream.close();
  4630. callback(readData.value);
  4631. } catch (e) {
  4632. throw new Error((fileObj && fileObj.path || '') + ': ' + e);
  4633. }
  4634. };
  4635. }
  4636. return text;
  4637. });
  4638. define('text!ca',[],function () { return '{\n "domain": "converse",\n "locale_data": {\n "converse": {\n "": {\n "domain": "converse",\n "plural_forms": "nplurals=2; plural=(n != 1);",\n "lang": "ca"\n },\n "Bookmark this room": [\n null,\n ""\n ],\n "The name for this bookmark:": [\n null,\n ""\n ],\n "Would you like this room to be automatically joined upon startup?": [\n null,\n ""\n ],\n "What should your nickname for this room be?": [\n null,\n ""\n ],\n "Save": [\n null,\n "Desa"\n ],\n "Cancel": [\n null,\n "Cancel·la"\n ],\n "Bookmarks": [\n null,\n ""\n ],\n "Remove this bookmark": [\n null,\n ""\n ],\n "Show more information on this room": [\n null,\n "Mostra més informació d\'aquesta sala"\n ],\n "Click to open this room": [\n null,\n "Feu clic per obrir aquesta sala"\n ],\n "Close this chat box": [\n null,\n "Tanca aquest quadre del xat"\n ],\n "Personal message": [\n null,\n "Missatge personal"\n ],\n "Send": [\n null,\n ""\n ],\n "me": [\n null,\n "jo"\n ],\n "A very large message has been received.This might be due to an attack meant to degrade the chat performance.Output has been shortened.": [\n null,\n ""\n ],\n "Typing from another device": [\n null,\n ""\n ],\n "is typing": [\n null,\n "està escrivint"\n ],\n "Stopped typing on the other device": [\n null,\n ""\n ],\n "has stopped typing": [\n null,\n "ha deixat d\'escriure"\n ],\n "has gone away": [\n null,\n "ha marxat"\n ],\n "Show this menu": [\n null,\n "Mostra aquest menú"\n ],\n "Write in the third person": [\n null,\n "Escriu en tercera persona"\n ],\n "Remove messages": [\n null,\n "Elimina els missatges"\n ],\n "Are you sure you want to clear the messages from this chat box?": [\n null,\n "Segur que voleu esborrar els missatges d\'aquest quadre del xat?"\n ],\n "has gone offline": [\n null,\n "s\'ha desconnectat"\n ],\n "is busy": [\n null,\n "està ocupat"\n ],\n "Clear all messages": [\n null,\n "Esborra tots els missatges"\n ],\n "Insert a smiley": [\n null,\n "Insereix una cara somrient"\n ],\n "Start a call": [\n null,\n "Inicia una trucada"\n ],\n "Contacts": [\n null,\n "Contactes"\n ],\n "XMPP Username:": [\n null,\n "Nom d\'usuari XMPP:"\n ],\n "Password:": [\n null,\n "Contrasenya:"\n ],\n "Click here to log in anonymously": [\n null,\n "Feu clic aquí per iniciar la sessió de manera anònima"\n ],\n "Log In": [\n null,\n "Inicia la sessió"\n ],\n "user@server": [\n null,\n "usuari@servidor"\n ],\n "password": [\n null,\n "contrasenya"\n ],\n "Sign in": [\n null,\n "Inicia la sessió"\n ],\n "I am %1$s": [\n null,\n "Estic %1$s"\n ],\n "Click here to write a custom status message": [\n null,\n "Feu clic aquí per escriure un missatge d\'estat personalitzat"\n ],\n "Click to change your chat status": [\n null,\n "Feu clic per canviar l\'estat del xat"\n ],\n "Custom status": [\n null,\n "Estat personalitzat"\n ],\n "online": [\n null,\n "en línia"\n ],\n "busy": [\n null,\n "ocupat"\n ],\n "away for long": [\n null,\n "absent durant una estona"\n ],\n "away": [\n null,\n "absent"\n ],\n "offline": [\n null,\n "desconnectat"\n ],\n "Online": [\n null,\n "En línia"\n ],\n "Busy": [\n null,\n "Ocupat"\n ],\n "Away": [\n null,\n "Absent"\n ],\n "Offline": [\n null,\n "Desconnectat"\n ],\n "Log out": [\n null,\n "Tanca la sessió"\n ],\n "Click to add new chat contacts": [\n null,\n "Feu clic per afegir contactes nous al xat"\n ],\n "Add a contact": [\n null,\n "Afegeix un contacte"\n ],\n "Contact name": [\n null,\n "Nom del contacte"\n ],\n "Search": [\n null,\n "Cerca"\n ],\n "Add": [\n null,\n "Afegeix"\n ],\n "No users found": [\n null,\n "No s\'ha trobat cap usuari"\n ],\n "This client does not allow presence subscriptions": [\n null,\n "Aquest client no admet les subscripcions de presència"\n ],\n "Click to hide these contacts": [\n null,\n "Feu clic per amagar aquests contactes"\n ],\n "Minimize this chat box": [\n null,\n "Minimitza aquest quadre del xat"\n ],\n "Click to restore this chat": [\n null,\n "Feu clic per restaurar aquest xat"\n ],\n "Minimized": [\n null,\n "Minimitzat"\n ],\n "This room is not anonymous": [\n null,\n "Aquesta sala no és anònima"\n ],\n "This room now shows unavailable members": [\n null,\n "Aquesta sala ara mostra membres no disponibles"\n ],\n "This room does not show unavailable members": [\n null,\n "Aquesta sala no mostra membres no disponibles"\n ],\n "Room logging is now enabled": [\n null,\n "El registre de la sala està habilitat"\n ],\n "Room logging is now disabled": [\n null,\n "El registre de la sala està deshabilitat"\n ],\n "This room is now semi-anonymous": [\n null,\n "Aquesta sala ara és parcialment anònima"\n ],\n "This room is now fully-anonymous": [\n null,\n "Aquesta sala ara és totalment anònima"\n ],\n "A new room has been created": [\n null,\n "S\'ha creat una sala nova"\n ],\n "You have been banned from this room": [\n null,\n "Se us ha expulsat d\'aquesta sala"\n ],\n "You have been kicked from this room": [\n null,\n "Se us ha expulsat d\'aquesta sala"\n ],\n "You have been removed from this room because of an affiliation change": [\n null,\n "Se us ha eliminat d\'aquesta sala a causa d\'un canvi d\'afiliació"\n ],\n "You have been removed from this room because the room has changed to members-only and you\'re not a member": [\n null,\n "Se us ha eliminat d\'aquesta sala perquè ara només permet membres i no en sou membre"\n ],\n "You have been removed from this room because the MUC (Multi-user chat) service is being shut down.": [\n null,\n "Se us ha eliminat d\'aquesta sala perquè s\'està tancant el servei MUC (xat multiusuari)."\n ],\n "Message": [\n null,\n "Missatge"\n ],\n "Hide the list of occupants": [\n null,\n "Amaga la llista d\'ocupants"\n ],\n "${command}": [\n null,\n ""\n ],\n "Are you sure you want to clear the messages from this room?": [\n null,\n "Segur que voleu esborrar els missatges d\'aquesta sala?"\n ],\n "Error: could not execute the command": [\n null,\n "Error: no s\'ha pogut executar l\'ordre"\n ],\n "Change user\'s affiliation to admin": [\n null,\n "Canvia l\'afiliació de l\'usuari a administrador"\n ],\n "Ban user from room": [\n null,\n "Expulsa l\'usuari de la sala"\n ],\n "Change user role to occupant": [\n null,\n "Canvia el rol de l\'usuari a ocupant"\n ],\n "Kick user from room": [\n null,\n "Expulsa l\'usuari de la sala"\n ],\n "Write in 3rd person": [\n null,\n "Escriu en tercera persona"\n ],\n "Grant membership to a user": [\n null,\n "Atorga una afiliació a un usuari"\n ],\n "Remove user\'s ability to post messages": [\n null,\n "Elimina la capacitat de l\'usuari de publicar missatges"\n ],\n "Change your nickname": [\n null,\n "Canvieu el vostre àlies"\n ],\n "Grant moderator role to user": [\n null,\n "Atorga el rol de moderador a l\'usuari"\n ],\n "Grant ownership of this room": [\n null,\n "Atorga la propietat d\'aquesta sala"\n ],\n "Revoke user\'s membership": [\n null,\n "Revoca l\'afiliació de l\'usuari"\n ],\n "Set room subject (alias for /subject)": [\n null,\n ""\n ],\n "Allow muted user to post messages": [\n null,\n "Permet que un usuari silenciat publiqui missatges"\n ],\n "The nickname you chose is reserved or currently in use, please choose a different one.": [\n null,\n ""\n ],\n "Nickname": [\n null,\n "Àlies"\n ],\n "This chatroom requires a password": [\n null,\n "Aquesta sala de xat requereix una contrasenya"\n ],\n "Password: ": [\n null,\n "Contrasenya:"\n ],\n "Submit": [\n null,\n "Envia"\n ],\n "${notification.reason}": [\n null,\n ""\n ],\n " has left the room. \\"": [\n null,\n ""\n ],\n " has joined the room. \\"": [\n null,\n ""\n ],\n " has joined the room.": [\n null,\n ""\n ],\n "Topic set by %1$s to: %2$s": [\n null,\n "Tema definit per %1$s en: %2$s"\n ],\n "Occupants": [\n null,\n "Ocupants"\n ],\n "Hidden": [\n null,\n "Amagat"\n ],\n "Message archiving": [\n null,\n ""\n ],\n "Members only": [\n null,\n ""\n ],\n "Moderated": [\n null,\n "Moderada"\n ],\n "Non-anonymous": [\n null,\n "No és anònima"\n ],\n "Persistent": [\n null,\n ""\n ],\n "Public": [\n null,\n "Pública"\n ],\n "Semi-anonymous": [\n null,\n "Semianònima"\n ],\n "Unmoderated": [\n null,\n "No moderada"\n ],\n "Unsecured": [\n null,\n ""\n ],\n "Messages are archived on the server": [\n null,\n ""\n ],\n "All other room occupants can see your XMPP username": [\n null,\n ""\n ],\n "This room persists even if it\'s unoccupied": [\n null,\n ""\n ],\n "Only moderators can see your XMPP username": [\n null,\n ""\n ],\n "This room will disappear once the last person leaves": [\n null,\n ""\n ],\n "You are about to invite %1$s to the chat room \\"%2$s\\". ": [\n null,\n "Esteu a punt de convidar %1$s a la sala de xat \\"%2$s\\". "\n ],\n "You may optionally include a message, explaining the reason for the invitation.": [\n null,\n "Teniu l\'opció d\'incloure un missatge per explicar el motiu de la invitació."\n ],\n "Please enter a valid XMPP username": [\n null,\n ""\n ],\n "Room name": [\n null,\n "Nom de la sala"\n ],\n "Server": [\n null,\n "Servidor"\n ],\n "Join Room": [\n null,\n "Uneix-me a la sala"\n ],\n "Show rooms": [\n null,\n "Mostra les sales"\n ],\n "Rooms": [\n null,\n "Sales"\n ],\n "No rooms on %1$s": [\n null,\n "No hi ha cap sala a %1$s"\n ],\n "Description:": [\n null,\n "Descripció:"\n ],\n "Room Address (JID):": [\n null,\n ""\n ],\n "Occupants:": [\n null,\n "Ocupants:"\n ],\n "Features:": [\n null,\n "Característiques:"\n ],\n "Requires authentication": [\n null,\n "Cal autenticar-se"\n ],\n "Requires an invitation": [\n null,\n "Cal tenir una invitació"\n ],\n "Open room": [\n null,\n "Obre la sala"\n ],\n "Permanent room": [\n null,\n "Sala permanent"\n ],\n "Temporary room": [\n null,\n "Sala temporal"\n ],\n "%1$s has invited you to join a chat room: %2$s": [\n null,\n "%1$s us ha convidat a unir-vos a una sala de xat: %2$s"\n ],\n "%1$s has invited you to join a chat room: %2$s, and left the following reason: \\"%3$s\\"": [\n null,\n "%1$s us ha convidat a unir-vos a una sala de xat (%2$s) i ha deixat el següent motiu: \\"%3$s\\""\n ],\n "Notification from %1$s": [\n null,\n ""\n ],\n "%1$s says": [\n null,\n ""\n ],\n "wants to be your contact": [\n null,\n ""\n ],\n "Re-establishing encrypted session": [\n null,\n "S\'està tornant a establir la sessió xifrada"\n ],\n "Generating private key.": [\n null,\n "S\'està generant la clau privada"\n ],\n "Your browser might become unresponsive.": [\n null,\n "És possible que el navegador no respongui."\n ],\n "Authentication request from %1$s\\n\\nYour chat contact is attempting to verify your identity, by asking you the question below.\\n\\n%2$s": [\n null,\n "Sol·licitud d\'autenticació de %1$s\\n\\nEl contacte del xat està intentant verificar la vostra identitat mitjançant la pregunta següent.\\n\\n%2$s"\n ],\n "Could not verify this user\'s identify.": [\n null,\n "No s\'ha pogut verificar la identitat d\'aquest usuari."\n ],\n "Exchanging private key with contact.": [\n null,\n "S\'està intercanviant la clau privada amb el contacte."\n ],\n "Your messages are not encrypted anymore": [\n null,\n "Els vostres missatges ja no estan xifrats"\n ],\n "Your messages are now encrypted but your contact\'s identity has not been verified.": [\n null,\n "Ara, els vostres missatges estan xifrats, però no s\'ha verificat la identitat del contacte."\n ],\n "Your contact\'s identify has been verified.": [\n null,\n "S\'ha verificat la identitat del contacte."\n ],\n "Your contact has ended encryption on their end, you should do the same.": [\n null,\n "El contacte ha conclòs el xifratge; cal que feu el mateix."\n ],\n "Your message could not be sent": [\n null,\n "No s\'ha pogut enviar el missatge"\n ],\n "We received an unencrypted message": [\n null,\n "Hem rebut un missatge sense xifrar"\n ],\n "We received an unreadable encrypted message": [\n null,\n "Hem rebut un missatge xifrat il·legible"\n ],\n "Here are the fingerprints, please confirm them with %1$s, outside of this chat.\\n\\nFingerprint for you, %2$s: %3$s\\n\\nFingerprint for %1$s: %4$s\\n\\nIf you have confirmed that the fingerprints match, click OK, otherwise click Cancel.": [\n null,\n "Aquí es mostren les empremtes. Confirmeu-les amb %1$s fora d\'aquest xat.\\n\\nEmpremta de l\'usuari %2$s: %3$s\\n\\nEmpremta de %1$s: %4$s\\n\\nSi heu confirmat que les empremtes coincideixen, feu clic a D\'acord; en cas contrari, feu clic a Cancel·la."\n ],\n "You will be prompted to provide a security question and then an answer to that question.\\n\\nYour contact will then be prompted the same question and if they type the exact same answer (case sensitive), their identity will be verified.": [\n null,\n "Se us demanarà que indiqueu una pregunta de seguretat i la resposta corresponent.\\n\\nEs farà la mateixa pregunta al vostre contacte i, si escriu exactament la mateixa resposta (es distingeix majúscules de minúscules), se\'n verificarà la identitat."\n ],\n "What is your security question?": [\n null,\n "Quina és la vostra pregunta de seguretat?"\n ],\n "What is the answer to the security question?": [\n null,\n "Quina és la resposta a la pregunta de seguretat?"\n ],\n "Invalid authentication scheme provided": [\n null,\n "S\'ha indicat un esquema d\'autenticació no vàlid"\n ],\n "Your messages are not encrypted. Click here to enable OTR encryption.": [\n null,\n "Els vostres missatges no estan xifrats. Feu clic aquí per habilitar el xifratge OTR."\n ],\n "Your messages are encrypted, but your contact has not been verified.": [\n null,\n "Els vostres missatges estan xifrats, però no s\'ha verificat el contacte."\n ],\n "Your messages are encrypted and your contact verified.": [\n null,\n "Els vostres missatges estan xifrats i s\'ha verificat el contacte."\n ],\n "Your contact has closed their end of the private session, you should do the same": [\n null,\n "El vostre contacte ha tancat la seva sessió privada; cal que feu el mateix."\n ],\n "End encrypted conversation": [\n null,\n "Finalitza la conversa xifrada"\n ],\n "Refresh encrypted conversation": [\n null,\n "Actualitza la conversa xifrada"\n ],\n "Start encrypted conversation": [\n null,\n "Comença la conversa xifrada"\n ],\n "Verify with fingerprints": [\n null,\n "Verifica amb empremtes"\n ],\n "Verify with SMP": [\n null,\n "Verifica amb SMP"\n ],\n "What\'s this?": [\n null,\n "Què és això?"\n ],\n "unencrypted": [\n null,\n "sense xifrar"\n ],\n "unverified": [\n null,\n "sense verificar"\n ],\n "verified": [\n null,\n "verificat"\n ],\n "finished": [\n null,\n "acabat"\n ],\n " e.g. conversejs.org": [\n null,\n "p. ex. conversejs.org"\n ],\n "Your XMPP provider\'s domain name:": [\n null,\n "Nom de domini del vostre proveïdor XMPP:"\n ],\n "Fetch registration form": [\n null,\n "Obtingues un formulari de registre"\n ],\n "Tip: A list of public XMPP providers is available": [\n null,\n "Consell: hi ha disponible una llista de proveïdors XMPP públics"\n ],\n "here": [\n null,\n "aquí"\n ],\n "Register": [\n null,\n "Registre"\n ],\n "Sorry, the given provider does not support in band account registration. Please try with a different provider.": [\n null,\n "El proveïdor indicat no admet el registre del compte. Proveu-ho amb un altre proveïdor."\n ],\n "Requesting a registration form from the XMPP server": [\n null,\n "S\'està sol·licitant un formulari de registre del servidor XMPP"\n ],\n "Something went wrong while establishing a connection with \\"%1$s\\". Are you sure it exists?": [\n null,\n "Ha passat alguna cosa mentre s\'establia la connexió amb \\"%1$s\\". Segur que existeix?"\n ],\n "Now logging you in": [\n null,\n "S\'està iniciant la vostra sessió"\n ],\n "Registered successfully": [\n null,\n "Registre correcte"\n ],\n "The provider rejected your registration attempt. Please check the values you entered for correctness.": [\n null,\n "El proveïdor ha rebutjat l\'intent de registre. Comproveu que els valors que heu introduït siguin correctes."\n ],\n "Retry": [\n null,\n ""\n ],\n "This contact is busy": [\n null,\n "Aquest contacte està ocupat"\n ],\n "This contact is online": [\n null,\n "Aquest contacte està en línia"\n ],\n "This contact is offline": [\n null,\n "Aquest contacte està desconnectat"\n ],\n "This contact is unavailable": [\n null,\n "Aquest contacte no està disponible"\n ],\n "This contact is away for an extended period": [\n null,\n "Aquest contacte està absent durant un període prolongat"\n ],\n "This contact is away": [\n null,\n "Aquest contacte està absent"\n ],\n "Groups": [\n null,\n "Grups"\n ],\n "My contacts": [\n null,\n "Els meus contactes"\n ],\n "Pending contacts": [\n null,\n "Contactes pendents"\n ],\n "Contact requests": [\n null,\n "Sol·licituds de contacte"\n ],\n "Ungrouped": [\n null,\n "Sense agrupar"\n ],\n "Filter": [\n null,\n ""\n ],\n "State": [\n null,\n ""\n ],\n "Any": [\n null,\n ""\n ],\n "Unread": [\n null,\n ""\n ],\n "Chatty": [\n null,\n ""\n ],\n "Extended Away": [\n null,\n ""\n ],\n "Click to chat with this contact": [\n null,\n "Feu clic per conversar amb aquest contacte"\n ],\n "Name": [\n null,\n "Nom"\n ],\n "Are you sure you want to remove this contact?": [\n null,\n "Segur que voleu eliminar aquest contacte?"\n ],\n "Are you sure you want to decline this contact request?": [\n null,\n "Segur que voleu rebutjar aquesta sol·licitud de contacte?"\n ]\n }\n }\n}';});
  4639. /* Lo-Dash Template Loader v1.0.1
  4640. * Copyright 2015, Tim Branyen (@tbranyen).
  4641. * loader.js may be freely distributed under the MIT license.
  4642. */
  4643. (function(global) {
  4644. "use strict";
  4645. // Cache used to map configuration options between load and write.
  4646. var buildMap = {};
  4647. // Alias the correct `nodeRequire` method.
  4648. var nodeRequire = typeof requirejs === "function" && requirejs.nodeRequire;
  4649. // Strips trailing `/` from url fragments.
  4650. var stripTrailing = function(prop) {
  4651. return prop.replace(/(\/$)/, '');
  4652. };
  4653. // Define the plugin using the CommonJS syntax.
  4654. define('tpl',['require','exports','module','lodash'],function(require, exports) {
  4655. var _ = require("lodash");
  4656. exports.version = "1.0.1";
  4657. // Invoked by the AMD builder, passed the path to resolve, the require
  4658. // function, done callback, and the configuration options.
  4659. exports.load = function(name, req, load, config) {
  4660. var isDojo;
  4661. // Dojo provides access to the config object through the req function.
  4662. if (!config) {
  4663. config = require.rawConfig;
  4664. isDojo = true;
  4665. }
  4666. var contents = "";
  4667. var settings = configure(config);
  4668. // If the baseUrl and root are the same, just null out the root.
  4669. if (stripTrailing(config.baseUrl) === stripTrailing(settings.root)) {
  4670. settings.root = '';
  4671. }
  4672. var url = require.toUrl(settings.root + name + settings.ext);
  4673. if (isDojo && url.indexOf(config.baseUrl) !== 0) {
  4674. url = stripTrailing(config.baseUrl) + url;
  4675. }
  4676. // Builds with r.js require Node.js to be installed.
  4677. if (config.isBuild) {
  4678. // If in Node, get access to the filesystem.
  4679. var fs = nodeRequire("fs");
  4680. try {
  4681. // First try reading the filepath as-is.
  4682. contents = String(fs.readFileSync(url));
  4683. } catch(ex) {
  4684. // If it failed, it's most likely because of a leading `/` and not an
  4685. // absolute path. Remove the leading slash and try again.
  4686. if (url.slice(0, 1) === "/") {
  4687. url = url.slice(1);
  4688. }
  4689. // Try reading again with the leading `/`.
  4690. contents = String(fs.readFileSync(url));
  4691. }
  4692. // Read in the file synchronously, as RequireJS expects, and return the
  4693. // contents. Process as a Lo-Dash template.
  4694. buildMap[name] = _.template(contents);
  4695. return load();
  4696. }
  4697. // Create a basic XHR.
  4698. var xhr = new XMLHttpRequest();
  4699. // Wait for it to load.
  4700. xhr.onreadystatechange = function() {
  4701. if (xhr.readyState === 4) {
  4702. var templateSettings = _.clone(settings.templateSettings);
  4703. // Attach the sourceURL.
  4704. templateSettings.sourceURL = url;
  4705. // Process as a Lo-Dash template and cache.
  4706. buildMap[name] = _.template(xhr.responseText, templateSettings);
  4707. // Return the compiled template.
  4708. load(buildMap[name]);
  4709. }
  4710. };
  4711. // Initiate the fetch.
  4712. xhr.open("GET", url, true);
  4713. xhr.send(null);
  4714. };
  4715. // Also invoked by the AMD builder, this writes out a compatible define
  4716. // call that will work with loaders such as almond.js that cannot read
  4717. // the configuration data.
  4718. exports.write = function(pluginName, moduleName, write) {
  4719. var template = buildMap[moduleName].source;
  4720. // Write out the actual definition
  4721. write(strDefine(pluginName, moduleName, template));
  4722. };
  4723. // This is for curl.js/cram.js build-time support.
  4724. exports.compile = function(pluginName, moduleName, req, io, config) {
  4725. configure(config);
  4726. // Ask cram to fetch the template file (resId) and pass it to `write`.
  4727. io.read(moduleName, write, io.error);
  4728. function write(template) {
  4729. // Write-out define(id,function(){return{/* template */}});
  4730. io.write(strDefine(pluginName, moduleName, template));
  4731. }
  4732. };
  4733. // Crafts the written definition form of the module during a build.
  4734. function strDefine(pluginName, moduleName, template) {
  4735. return [
  4736. "define('", pluginName, "!", moduleName, "', ", "['lodash'], ",
  4737. [
  4738. "function(_) {",
  4739. "return ", template, ";",
  4740. "}"
  4741. ].join(""),
  4742. ");\n"
  4743. ].join("");
  4744. }
  4745. function configure(config) {
  4746. // Default settings point to the project root and using html files.
  4747. var settings = _.extend({
  4748. ext: ".html",
  4749. root: config.baseUrl,
  4750. templateSettings: {}
  4751. }, config.lodashLoader);
  4752. // Ensure the root has been properly configured with a trailing slash,
  4753. // unless it's an empty string or undefined, in which case work off the
  4754. // baseUrl.
  4755. if (settings.root && settings.root.slice(-1) !== "/") {
  4756. settings.root += "/";
  4757. }
  4758. // Set the custom passed in template settings.
  4759. _.extend(_.templateSettings, settings.templateSettings);
  4760. return settings;
  4761. }
  4762. });
  4763. })(typeof global === "object" ? global : this);
  4764. define('tpl!field', ['lodash'], function(_) {return function(obj) {
  4765. obj || (obj = {});
  4766. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  4767. function print() { __p += __j.call(arguments, '') }
  4768. with (obj) {
  4769. __p += '<field var="' +
  4770. __e(name) +
  4771. '">';
  4772. if (_.isArray(value)) { ;
  4773. __p += '\n ';
  4774. _.each(value,function(arrayValue) { ;
  4775. __p += '<value>' +
  4776. __e(arrayValue) +
  4777. '</value>';
  4778. }); ;
  4779. __p += '\n';
  4780. } else { ;
  4781. __p += '\n <value>' +
  4782. __e(value) +
  4783. '</value>\n';
  4784. } ;
  4785. __p += '</field>\n';
  4786. }
  4787. return __p
  4788. };});
  4789. define('tpl!select_option', ['lodash'], function(_) {return function(obj) {
  4790. obj || (obj = {});
  4791. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  4792. function print() { __p += __j.call(arguments, '') }
  4793. with (obj) {
  4794. __p += '<option value="' +
  4795. __e(value) +
  4796. '" ';
  4797. if (selected) { ;
  4798. __p += ' selected="selected" ';
  4799. } ;
  4800. __p += ' >' +
  4801. __e(label) +
  4802. '</option>\n';
  4803. }
  4804. return __p
  4805. };});
  4806. define('tpl!form_select', ['lodash'], function(_) {return function(obj) {
  4807. obj || (obj = {});
  4808. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  4809. function print() { __p += __j.call(arguments, '') }
  4810. with (obj) {
  4811. __p += '<label>' +
  4812. __e(label) +
  4813. '</label>\n<select name="' +
  4814. __e(name) +
  4815. '" ';
  4816. if (multiple) { ;
  4817. __p += ' multiple="multiple" ';
  4818. } ;
  4819. __p += '>' +
  4820. ((__t = (options)) == null ? '' : __t) +
  4821. '</select>\n';
  4822. }
  4823. return __p
  4824. };});
  4825. define('tpl!form_textarea', ['lodash'], function(_) {return function(obj) {
  4826. obj || (obj = {});
  4827. var __t, __p = '', __e = _.escape;
  4828. with (obj) {
  4829. __p += '<label class="label-ta">' +
  4830. __e(label) +
  4831. '</label>\n<textarea name="' +
  4832. __e(name) +
  4833. '">' +
  4834. __e(value) +
  4835. '</textarea>\n';
  4836. }
  4837. return __p
  4838. };});
  4839. define('tpl!form_checkbox', ['lodash'], function(_) {return function(obj) {
  4840. obj || (obj = {});
  4841. var __t, __p = '', __e = _.escape;
  4842. with (obj) {
  4843. __p += '<label>' +
  4844. __e(label) +
  4845. '</label>\n<input name="' +
  4846. __e(name) +
  4847. '" type="' +
  4848. __e(type) +
  4849. '" ' +
  4850. __e(checked) +
  4851. '>\n';
  4852. }
  4853. return __p
  4854. };});
  4855. define('tpl!form_username', ['lodash'], function(_) {return function(obj) {
  4856. obj || (obj = {});
  4857. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  4858. function print() { __p += __j.call(arguments, '') }
  4859. with (obj) {
  4860. if (label) { ;
  4861. __p += '\n<label>\n ' +
  4862. __e(label) +
  4863. '\n</label>\n';
  4864. } ;
  4865. __p += '\n<div class="input-group">\n <input name="' +
  4866. __e(name) +
  4867. '" type="' +
  4868. __e(type) +
  4869. '"\n ';
  4870. if (value) { ;
  4871. __p += ' value="' +
  4872. __e(value) +
  4873. '" ';
  4874. } ;
  4875. __p += '\n ';
  4876. if (required) { ;
  4877. __p += ' class="required" ';
  4878. } ;
  4879. __p += ' />\n <span title="' +
  4880. __e(domain) +
  4881. '">' +
  4882. __e(domain) +
  4883. '</span>\n</div>\n';
  4884. }
  4885. return __p
  4886. };});
  4887. define('tpl!form_input', ['lodash'], function(_) {return function(obj) {
  4888. obj || (obj = {});
  4889. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  4890. function print() { __p += __j.call(arguments, '') }
  4891. with (obj) {
  4892. if (label) { ;
  4893. __p += '\n<label>\n ' +
  4894. __e(label) +
  4895. '\n</label>\n';
  4896. } ;
  4897. __p += '\n<input name="' +
  4898. __e(name) +
  4899. '" type="' +
  4900. __e(type) +
  4901. '" \n ';
  4902. if (value) { ;
  4903. __p += ' value="' +
  4904. __e(value) +
  4905. '" ';
  4906. } ;
  4907. __p += '\n ';
  4908. if (required) { ;
  4909. __p += ' class="required" ';
  4910. } ;
  4911. __p += ' >\n';
  4912. }
  4913. return __p
  4914. };});
  4915. define('tpl!form_captcha', ['lodash'], function(_) {return function(obj) {
  4916. obj || (obj = {});
  4917. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  4918. function print() { __p += __j.call(arguments, '') }
  4919. with (obj) {
  4920. if (label) { ;
  4921. __p += '\n<label>\n ' +
  4922. __e(label) +
  4923. '\n</label>\n';
  4924. } ;
  4925. __p += '\n<img src="data:' +
  4926. __e(type) +
  4927. ';base64,' +
  4928. __e(data) +
  4929. '">\n<input name="' +
  4930. __e(name) +
  4931. '" type="text" ';
  4932. if (required) { ;
  4933. __p += ' class="required" ';
  4934. } ;
  4935. __p += ' >\n\n\n';
  4936. }
  4937. return __p
  4938. };});
  4939. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
  4940. /*global define, escape, locales, Jed */
  4941. (function (root, factory) {
  4942. define('utils',["jquery.noconflict", "sizzle", "es6-promise", "jquery.browser", "lodash.noconflict", "locales", "moment_with_locales", "strophe", "tpl!field", "tpl!select_option", "tpl!form_select", "tpl!form_textarea", "tpl!form_checkbox", "tpl!form_username", "tpl!form_input", "tpl!form_captcha"], factory);
  4943. })(undefined, function ($, sizzle, Promise, dummy, _, locales, moment, Strophe, tpl_field, tpl_select_option, tpl_form_select, tpl_form_textarea, tpl_form_checkbox, tpl_form_username, tpl_form_input, tpl_form_captcha) {
  4944. "use strict";
  4945. locales = locales || {};
  4946. var b64_sha1 = Strophe.SHA1.b64_sha1;
  4947. Strophe = Strophe.Strophe;
  4948. var URL_REGEX = /\b(https?:\/\/|www\.|https?:\/\/www\.)[^\s<>]{2,200}\b/g;
  4949. var XFORM_TYPE_MAP = {
  4950. 'text-private': 'password',
  4951. 'text-single': 'text',
  4952. 'fixed': 'label',
  4953. 'boolean': 'checkbox',
  4954. 'hidden': 'hidden',
  4955. 'jid-multi': 'textarea',
  4956. 'list-single': 'dropdown',
  4957. 'list-multi': 'dropdown'
  4958. };
  4959. var afterAnimationEnd = function afterAnimationEnd(el, callback) {
  4960. el.classList.remove('visible');
  4961. if (_.isFunction(callback)) {
  4962. callback();
  4963. }
  4964. };
  4965. var unescapeHTML = function unescapeHTML(htmlEscapedText) {
  4966. /* Helper method that replace HTML-escaped symbols with equivalent characters
  4967. * (e.g. transform occurrences of '&amp;' to '&')
  4968. *
  4969. * Parameters:
  4970. * (String) htmlEscapedText: a String containing the HTML-escaped symbols.
  4971. */
  4972. var div = document.createElement('div');
  4973. div.innerHTML = htmlEscapedText;
  4974. return div.innerText;
  4975. };
  4976. var isImage = function isImage(url) {
  4977. return new Promise(function (resolve, reject) {
  4978. var img = new Image();
  4979. var timer = window.setTimeout(function () {
  4980. reject(new Error("Could not determine whether it's an image"));
  4981. img = null;
  4982. }, 3000);
  4983. img.onerror = img.onabort = function () {
  4984. clearTimeout(timer);
  4985. reject(new Error("Could not determine whether it's an image"));
  4986. };
  4987. img.onload = function () {
  4988. clearTimeout(timer);
  4989. resolve(img);
  4990. };
  4991. img.src = url;
  4992. });
  4993. };
  4994. $.fn.hasScrollBar = function () {
  4995. if (!$.contains(document, this.get(0))) {
  4996. return false;
  4997. }
  4998. if (this.parent().height() < this.get(0).scrollHeight) {
  4999. return true;
  5000. }
  5001. return false;
  5002. };
  5003. function calculateSlideStep(height) {
  5004. if (height > 100) {
  5005. return 10;
  5006. } else if (height > 50) {
  5007. return 5;
  5008. } else {
  5009. return 1;
  5010. }
  5011. }
  5012. var utils = {};
  5013. // Translation machinery
  5014. // ---------------------
  5015. utils.__ = function (str) {
  5016. if (!utils.isConverseLocale(this.locale) || this.locale === 'en') {
  5017. return Jed.sprintf.apply(Jed, arguments);
  5018. }
  5019. if (typeof this.jed === "undefined") {
  5020. this.jed = new Jed(window.JSON.parse(locales[this.locale]));
  5021. }
  5022. var t = this.jed.translate(str);
  5023. if (arguments.length > 1) {
  5024. return t.fetch.apply(t, [].slice.call(arguments, 1));
  5025. } else {
  5026. return t.fetch();
  5027. }
  5028. };
  5029. utils.___ = function (str) {
  5030. /* XXX: This is part of a hack to get gettext to scan strings to be
  5031. * translated. Strings we cannot send to the function above because
  5032. * they require variable interpolation and we don't yet have the
  5033. * variables at scan time.
  5034. *
  5035. * See actionInfoMessages in src/converse-muc.js
  5036. */
  5037. return str;
  5038. };
  5039. utils.isLocaleAvailable = function (locale, available) {
  5040. /* Check whether the locale or sub locale (e.g. en-US, en) is supported.
  5041. *
  5042. * Parameters:
  5043. * (Function) available - returns a boolean indicating whether the locale is supported
  5044. */
  5045. if (available(locale)) {
  5046. return locale;
  5047. } else {
  5048. var sublocale = locale.split("-")[0];
  5049. if (sublocale !== locale && available(sublocale)) {
  5050. return sublocale;
  5051. }
  5052. }
  5053. };
  5054. utils.addHyperlinks = function (text) {
  5055. var list = text.match(URL_REGEX) || [];
  5056. var links = [];
  5057. _.each(list, function (match) {
  5058. var prot = match.indexOf('http://') === 0 || match.indexOf('https://') === 0 ? '' : 'http://';
  5059. var url = prot + encodeURI(decodeURI(match)).replace(/[!'()]/g, escape).replace(/\*/g, "%2A");
  5060. var a = '<a target="_blank" rel="noopener" href="' + url + '">' + _.escape(match) + '</a>';
  5061. // We first insert a hash of the code that will be inserted, and
  5062. // then later replace that with the code itself. That way we avoid
  5063. // issues when some matches are substrings of others.
  5064. links.push(a);
  5065. text = text.replace(match, b64_sha1(a));
  5066. });
  5067. while (links.length) {
  5068. var a = links.pop();
  5069. text = text.replace(b64_sha1(a), a);
  5070. }
  5071. return text;
  5072. };
  5073. utils.renderImageURLs = function (obj) {
  5074. var list = obj.textContent.match(URL_REGEX) || [];
  5075. _.forEach(list, function (url) {
  5076. isImage(url).then(function (img) {
  5077. img.className = 'chat-image';
  5078. var anchors = sizzle("a[href=\"" + url + "\"]", obj);
  5079. _.each(anchors, function (a) {
  5080. a.innerHTML = img.outerHTML;
  5081. });
  5082. });
  5083. });
  5084. return obj;
  5085. };
  5086. utils.slideInAllElements = function (elements) {
  5087. return Promise.all(_.map(elements, _.partial(utils.slideIn, _, 600)));
  5088. };
  5089. utils.slideToggleElement = function (el) {
  5090. if (_.includes(el.classList, 'collapsed')) {
  5091. return utils.slideOut(el);
  5092. } else {
  5093. return utils.slideIn(el);
  5094. }
  5095. };
  5096. utils.slideOut = function (el) {
  5097. var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 900;
  5098. /* Shows/expands an element by sliding it out of itself. */
  5099. function calculateEndHeight(el) {
  5100. return _.reduce(el.children, function (result, child) {
  5101. return result + child.offsetHeight;
  5102. }, 0);
  5103. }
  5104. function wrapup(el) {
  5105. el.removeAttribute('data-slider-marker');
  5106. el.classList.remove('collapsed');
  5107. el.style.overflow = "";
  5108. el.style.height = "";
  5109. }
  5110. return new Promise(function (resolve, reject) {
  5111. if (_.isNil(el)) {
  5112. var err = "Undefined or null element passed into slideOut";
  5113. console.warn(err);
  5114. reject(new Error(err));
  5115. return;
  5116. }
  5117. var interval_marker = el.getAttribute('data-slider-marker');
  5118. if (interval_marker) {
  5119. el.removeAttribute('data-slider-marker');
  5120. window.clearInterval(interval_marker);
  5121. }
  5122. var end_height = calculateEndHeight(el);
  5123. if ($.fx.off) {
  5124. // Effects are disabled (for tests)
  5125. el.style.height = end_height + 'px';
  5126. wrapup(el);
  5127. resolve();
  5128. return;
  5129. }
  5130. var step = calculateSlideStep(end_height),
  5131. interval = end_height / duration * step;
  5132. var h = 0;
  5133. interval_marker = window.setInterval(function () {
  5134. h += step;
  5135. if (h < end_height) {
  5136. el.style.height = h + 'px';
  5137. } else {
  5138. // We recalculate the height to work around an apparent
  5139. // browser bug where browsers don't know the correct
  5140. // offsetHeight beforehand.
  5141. el.style.height = calculateEndHeight(el) + 'px';
  5142. window.clearInterval(interval_marker);
  5143. wrapup(el);
  5144. resolve();
  5145. }
  5146. }, interval);
  5147. el.setAttribute('data-slider-marker', interval_marker);
  5148. });
  5149. };
  5150. utils.slideIn = function (el) {
  5151. var duration = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 600;
  5152. /* Hides/collapses an element by sliding it into itself. */
  5153. return new Promise(function (resolve, reject) {
  5154. if (_.isNil(el)) {
  5155. var err = "Undefined or null element passed into slideIn";
  5156. console.warn(err);
  5157. return reject(new Error(err));
  5158. } else if (_.includes(el.classList, 'collapsed')) {
  5159. return resolve();
  5160. } else if ($.fx.off) {
  5161. // Effects are disabled (for tests)
  5162. el.classList.add('collapsed');
  5163. el.style.height = "";
  5164. return resolve();
  5165. }
  5166. var interval_marker = el.getAttribute('data-slider-marker');
  5167. if (interval_marker) {
  5168. el.removeAttribute('data-slider-marker');
  5169. window.clearInterval(interval_marker);
  5170. }
  5171. var h = el.offsetHeight;
  5172. var step = calculateSlideStep(h),
  5173. interval = h / duration * step;
  5174. el.style.overflow = 'hidden';
  5175. interval_marker = window.setInterval(function () {
  5176. h -= step;
  5177. if (h > 0) {
  5178. el.style.height = h + 'px';
  5179. } else {
  5180. el.removeAttribute('data-slider-marker');
  5181. window.clearInterval(interval_marker);
  5182. el.classList.add('collapsed');
  5183. el.style.height = "";
  5184. resolve();
  5185. }
  5186. }, interval);
  5187. el.setAttribute('data-slider-marker', interval_marker);
  5188. });
  5189. };
  5190. utils.fadeIn = function (el, callback) {
  5191. if (_.isNil(el)) {
  5192. console.warn("Undefined or null element passed into fadeIn");
  5193. }
  5194. if ($.fx.off) {
  5195. el.classList.remove('hidden');
  5196. if (_.isFunction(callback)) {
  5197. callback();
  5198. }
  5199. return;
  5200. }
  5201. if (_.includes(el.classList, 'hidden')) {
  5202. /* XXX: This doesn't appear to be working...
  5203. el.addEventListener("webkitAnimationEnd", _.partial(afterAnimationEnd, el, callback), false);
  5204. el.addEventListener("animationend", _.partial(afterAnimationEnd, el, callback), false);
  5205. */
  5206. setTimeout(_.partial(afterAnimationEnd, el, callback), 351);
  5207. el.classList.add('visible');
  5208. el.classList.remove('hidden');
  5209. } else {
  5210. afterAnimationEnd(el, callback);
  5211. }
  5212. };
  5213. utils.isSameBareJID = function (jid1, jid2) {
  5214. return Strophe.getBareJidFromJid(jid1).toLowerCase() === Strophe.getBareJidFromJid(jid2).toLowerCase();
  5215. };
  5216. utils.isNewMessage = function (message) {
  5217. /* Given a stanza, determine whether it's a new
  5218. * message, i.e. not a MAM archived one.
  5219. */
  5220. if (message instanceof Element) {
  5221. return !sizzle('result[xmlns="' + Strophe.NS.MAM + '"]', message).length;
  5222. } else {
  5223. return !message.get('archive_id');
  5224. }
  5225. };
  5226. utils.isOTRMessage = function (message) {
  5227. var body = message.querySelector('body'),
  5228. text = !_.isNull(body) ? body.textContent : undefined;
  5229. return text && !!text.match(/^\?OTR/);
  5230. };
  5231. utils.isHeadlineMessage = function (message) {
  5232. var from_jid = message.getAttribute('from');
  5233. if (message.getAttribute('type') === 'headline') {
  5234. return true;
  5235. }
  5236. if (message.getAttribute('type') !== 'error' && !_.isNil(from_jid) && !_.includes(from_jid, '@')) {
  5237. // Some servers (I'm looking at you Prosody) don't set the message
  5238. // type to "headline" when sending server messages. For now we
  5239. // check if an @ signal is included, and if not, we assume it's
  5240. // a headline message.
  5241. return true;
  5242. }
  5243. return false;
  5244. };
  5245. utils.merge = function merge(first, second) {
  5246. /* Merge the second object into the first one.
  5247. */
  5248. for (var k in second) {
  5249. if (_.isObject(first[k])) {
  5250. merge(first[k], second[k]);
  5251. } else {
  5252. first[k] = second[k];
  5253. }
  5254. }
  5255. };
  5256. utils.applyUserSettings = function applyUserSettings(context, settings, user_settings) {
  5257. /* Configuration settings might be nested objects. We only want to
  5258. * add settings which are whitelisted.
  5259. */
  5260. for (var k in settings) {
  5261. if (_.isUndefined(user_settings[k])) {
  5262. continue;
  5263. }
  5264. if (_.isObject(settings[k]) && !_.isArray(settings[k])) {
  5265. applyUserSettings(context[k], settings[k], user_settings[k]);
  5266. } else {
  5267. context[k] = user_settings[k];
  5268. }
  5269. }
  5270. };
  5271. utils.refreshWebkit = function () {
  5272. /* This works around a webkit bug. Refreshes the browser's viewport,
  5273. * otherwise chatboxes are not moved along when one is closed.
  5274. */
  5275. if ($.browser.webkit && window.requestAnimationFrame) {
  5276. window.requestAnimationFrame(function () {
  5277. var conversejs = document.getElementById('conversejs');
  5278. conversejs.style.display = 'none';
  5279. var tmp = conversejs.offsetHeight; // jshint ignore:line
  5280. conversejs.style.display = 'block';
  5281. });
  5282. }
  5283. };
  5284. utils.webForm2xForm = function (field) {
  5285. /* Takes an HTML DOM and turns it into an XForm field.
  5286. *
  5287. * Parameters:
  5288. * (DOMElement) field - the field to convert
  5289. */
  5290. var $input = $(field),
  5291. value;
  5292. if ($input.is('[type=checkbox]')) {
  5293. value = $input.is(':checked') && 1 || 0;
  5294. } else if ($input.is('textarea')) {
  5295. value = [];
  5296. var lines = $input.val().split('\n');
  5297. for (var vk = 0; vk < lines.length; vk++) {
  5298. var val = $.trim(lines[vk]);
  5299. if (val === '') continue;
  5300. value.push(val);
  5301. }
  5302. } else {
  5303. value = $input.val();
  5304. }
  5305. return $(tpl_field({
  5306. name: $input.attr('name'),
  5307. value: value
  5308. }))[0];
  5309. };
  5310. utils.contains = function (attr, query) {
  5311. return function (item) {
  5312. if ((typeof attr === "undefined" ? "undefined" : _typeof(attr)) === 'object') {
  5313. var value = false;
  5314. _.forEach(attr, function (a) {
  5315. value = value || _.includes(item.get(a).toLowerCase(), query.toLowerCase());
  5316. });
  5317. return value;
  5318. } else if (typeof attr === 'string') {
  5319. return _.includes(item.get(attr).toLowerCase(), query.toLowerCase());
  5320. } else {
  5321. throw new TypeError('contains: wrong attribute type. Must be string or array.');
  5322. }
  5323. };
  5324. };
  5325. utils.xForm2webForm = function ($field, $stanza) {
  5326. /* Takes a field in XMPP XForm (XEP-004: Data Forms) format
  5327. * and turns it into a HTML DOM field.
  5328. *
  5329. * Parameters:
  5330. * (XMLElement) field - the field to convert
  5331. */
  5332. // FIXME: take <required> into consideration
  5333. var options = [],
  5334. j,
  5335. $options,
  5336. $values,
  5337. value,
  5338. values;
  5339. if ($field.attr('type') === 'list-single' || $field.attr('type') === 'list-multi') {
  5340. values = [];
  5341. $values = $field.children('value');
  5342. for (j = 0; j < $values.length; j++) {
  5343. values.push($($values[j]).text());
  5344. }
  5345. $options = $field.children('option');
  5346. for (j = 0; j < $options.length; j++) {
  5347. value = $($options[j]).find('value').text();
  5348. options.push(tpl_select_option({
  5349. value: value,
  5350. label: $($options[j]).attr('label'),
  5351. selected: _.startsWith(values, value),
  5352. required: $field.find('required').length
  5353. }));
  5354. }
  5355. return tpl_form_select({
  5356. name: $field.attr('var'),
  5357. label: $field.attr('label'),
  5358. options: options.join(''),
  5359. multiple: $field.attr('type') === 'list-multi',
  5360. required: $field.find('required').length
  5361. });
  5362. } else if ($field.attr('type') === 'fixed') {
  5363. return $('<p class="form-help">').text($field.find('value').text());
  5364. } else if ($field.attr('type') === 'jid-multi') {
  5365. return tpl_form_textarea({
  5366. name: $field.attr('var'),
  5367. label: $field.attr('label') || '',
  5368. value: $field.find('value').text(),
  5369. required: $field.find('required').length
  5370. });
  5371. } else if ($field.attr('type') === 'boolean') {
  5372. return tpl_form_checkbox({
  5373. name: $field.attr('var'),
  5374. type: XFORM_TYPE_MAP[$field.attr('type')],
  5375. label: $field.attr('label') || '',
  5376. checked: $field.find('value').text() === "1" && 'checked="1"' || '',
  5377. required: $field.find('required').length
  5378. });
  5379. } else if ($field.attr('type') && $field.attr('var') === 'username') {
  5380. return tpl_form_username({
  5381. domain: ' @' + this.domain,
  5382. name: $field.attr('var'),
  5383. type: XFORM_TYPE_MAP[$field.attr('type')],
  5384. label: $field.attr('label') || '',
  5385. value: $field.find('value').text(),
  5386. required: $field.find('required').length
  5387. });
  5388. } else if ($field.attr('type')) {
  5389. return tpl_form_input({
  5390. name: $field.attr('var'),
  5391. type: XFORM_TYPE_MAP[$field.attr('type')],
  5392. label: $field.attr('label') || '',
  5393. value: $field.find('value').text(),
  5394. required: $field.find('required').length
  5395. });
  5396. } else {
  5397. if ($field.attr('var') === 'ocr') {
  5398. // Captcha
  5399. return _.reduce(_.map($field.find('uri'), $.proxy(function (uri) {
  5400. return tpl_form_captcha({
  5401. label: this.$field.attr('label'),
  5402. name: this.$field.attr('var'),
  5403. data: this.$stanza.find('data[cid="' + uri.textContent.replace(/^cid:/, '') + '"]').text(),
  5404. type: uri.getAttribute('type'),
  5405. required: this.$field.find('required').length
  5406. });
  5407. }, { '$stanza': $stanza, '$field': $field })), function (memo, num) {
  5408. return memo + num;
  5409. }, '');
  5410. }
  5411. }
  5412. };
  5413. utils.detectLocale = function (library_check) {
  5414. /* Determine which locale is supported by the user's system as well
  5415. * as by the relevant library (e.g. converse.js or moment.js).
  5416. *
  5417. * Parameters:
  5418. * (Function) library_check - returns a boolean indicating whether
  5419. * the locale is supported.
  5420. */
  5421. var locale, i;
  5422. if (window.navigator.userLanguage) {
  5423. locale = utils.isLocaleAvailable(window.navigator.userLanguage, library_check);
  5424. }
  5425. if (window.navigator.languages && !locale) {
  5426. for (i = 0; i < window.navigator.languages.length && !locale; i++) {
  5427. locale = utils.isLocaleAvailable(window.navigator.languages[i], library_check);
  5428. }
  5429. }
  5430. if (window.navigator.browserLanguage && !locale) {
  5431. locale = utils.isLocaleAvailable(window.navigator.browserLanguage, library_check);
  5432. }
  5433. if (window.navigator.language && !locale) {
  5434. locale = utils.isLocaleAvailable(window.navigator.language, library_check);
  5435. }
  5436. if (window.navigator.systemLanguage && !locale) {
  5437. locale = utils.isLocaleAvailable(window.navigator.systemLanguage, library_check);
  5438. }
  5439. return locale || 'en';
  5440. };
  5441. utils.isConverseLocale = function (locale) {
  5442. if (!_.isString(locale)) {
  5443. return false;
  5444. }
  5445. return _.includes(_.keys(locales || {}), locale);
  5446. };
  5447. utils.isMomentLocale = function (locale) {
  5448. if (!_.isString(locale)) {
  5449. return false;
  5450. }
  5451. return moment.locale() !== moment.locale(locale);
  5452. };
  5453. utils.getLocale = function (preferred_locale, isSupportedByLibrary) {
  5454. if (_.isString(preferred_locale)) {
  5455. if (preferred_locale === 'en' || isSupportedByLibrary(preferred_locale)) {
  5456. return preferred_locale;
  5457. }
  5458. try {
  5459. var obj = window.JSON.parse(preferred_locale);
  5460. return obj.locale_data.converse[""].lang;
  5461. } catch (e) {
  5462. console.log(e);
  5463. }
  5464. }
  5465. return utils.detectLocale(isSupportedByLibrary) || 'en';
  5466. };
  5467. utils.isOfType = function (type, item) {
  5468. return item.get('type') == type;
  5469. };
  5470. utils.isInstance = function (type, item) {
  5471. return item instanceof type;
  5472. };
  5473. utils.getAttribute = function (key, item) {
  5474. return item.get(key);
  5475. };
  5476. utils.contains.not = function (attr, query) {
  5477. return function (item) {
  5478. return !utils.contains(attr, query)(item);
  5479. };
  5480. };
  5481. utils.createFragmentFromText = function (markup) {
  5482. /* Returns a DocumentFragment containing DOM nodes based on the
  5483. * passed-in markup text.
  5484. */
  5485. // http://stackoverflow.com/questions/9334645/create-node-from-markup-string
  5486. var frag = document.createDocumentFragment(),
  5487. tmp = document.createElement('body'),
  5488. child;
  5489. tmp.innerHTML = markup;
  5490. // Append elements in a loop to a DocumentFragment, so that the
  5491. // browser does not re-render the document for each node.
  5492. while (child = tmp.firstChild) {
  5493. // eslint-disable-line no-cond-assign
  5494. frag.appendChild(child);
  5495. }
  5496. return frag;
  5497. };
  5498. utils.addEmoji = function (_converse, emojione, text) {
  5499. if (_converse.use_emojione) {
  5500. return emojione.toImage(text);
  5501. } else {
  5502. return emojione.shortnameToUnicode(text);
  5503. }
  5504. };
  5505. utils.getEmojisByCategory = function (_converse, emojione) {
  5506. /* Return a dict of emojis with the categories as keys and
  5507. * lists of emojis in that category as values.
  5508. */
  5509. if (_.isUndefined(_converse.emojis_by_category)) {
  5510. var emojis = _.values(_.mapValues(emojione.emojioneList, function (value, key, o) {
  5511. value._shortname = key;
  5512. return value;
  5513. }));
  5514. var tones = [':tone1:', ':tone2:', ':tone3:', ':tone4:', ':tone5:'];
  5515. var excluded = [':kiss_ww:', ':kiss_mm:', ':kiss_woman_man:'];
  5516. var excluded_substrings = [':woman', ':man', ':women_', ':men_', '_man_', '_woman_', '_woman:', '_man:'];
  5517. var excluded_categories = ['modifier', 'regional'];
  5518. var categories = _.difference(_.uniq(_.map(emojis, _.partial(_.get, _, 'category'))), excluded_categories);
  5519. var emojis_by_category = {};
  5520. _.forEach(categories, function (cat) {
  5521. var list = _.sortBy(_.filter(emojis, ['category', cat]), ['uc_base']);
  5522. list = _.filter(list, function (item) {
  5523. return !_.includes(_.concat(tones, excluded), item._shortname) && !_.some(excluded_substrings, _.partial(_.includes, item._shortname));
  5524. });
  5525. if (cat === 'people') {
  5526. var idx = _.findIndex(list, ['uc_base', '1f600']);
  5527. list = _.union(_.slice(list, idx), _.slice(list, 0, idx + 1));
  5528. } else if (cat === 'activity') {
  5529. list = _.union(_.slice(list, 27 - 1), _.slice(list, 0, 27));
  5530. } else if (cat === 'objects') {
  5531. list = _.union(_.slice(list, 24 - 1), _.slice(list, 0, 24));
  5532. } else if (cat === 'travel') {
  5533. list = _.union(_.slice(list, 17 - 1), _.slice(list, 0, 17));
  5534. } else if (cat === 'symbols') {
  5535. list = _.union(_.slice(list, 60 - 1), _.slice(list, 0, 60));
  5536. }
  5537. emojis_by_category[cat] = list;
  5538. });
  5539. _converse.emojis_by_category = emojis_by_category;
  5540. }
  5541. return _converse.emojis_by_category;
  5542. };
  5543. utils.getTonedEmojis = function (_converse) {
  5544. _converse.toned_emojis = _.uniq(_.map(_.filter(utils.getEmojisByCategory(_converse).people, function (person) {
  5545. return _.includes(person._shortname, '_tone');
  5546. }), function (person) {
  5547. return person._shortname.replace(/_tone[1-5]/, '');
  5548. }));
  5549. return _converse.toned_emojis;
  5550. };
  5551. utils.isPersistableModel = function (model) {
  5552. return model.collection && model.collection.browserStorage;
  5553. };
  5554. utils.getWrappedPromise = function () {
  5555. var wrapper = {};
  5556. wrapper.promise = new Promise(function (resolve, reject) {
  5557. wrapper.resolve = resolve;
  5558. wrapper.reject = reject;
  5559. });
  5560. return wrapper;
  5561. };
  5562. utils.safeSave = function (model, attributes) {
  5563. if (utils.isPersistableModel(model)) {
  5564. model.save(attributes);
  5565. } else {
  5566. model.set(attributes);
  5567. }
  5568. };
  5569. return utils;
  5570. });
  5571. //# sourceMappingURL=utils.js.map;
  5572. (function (global, factory) {
  5573. if (typeof define === "function" && define.amd) {
  5574. define('pluggable',['exports', 'lodash'], factory);
  5575. } else if (typeof exports !== "undefined") {
  5576. factory(exports, require('lodash'));
  5577. } else {
  5578. var mod = {
  5579. exports: {}
  5580. };
  5581. factory(mod.exports, global._);
  5582. global.pluggable = mod.exports;
  5583. }
  5584. })(this, function (exports, _lodash) {
  5585. 'use strict';
  5586. Object.defineProperty(exports, "__esModule", {
  5587. value: true
  5588. });
  5589. exports.enable = undefined;
  5590. var _ = _interopRequireWildcard(_lodash);
  5591. function _interopRequireWildcard(obj) {
  5592. if (obj && obj.__esModule) {
  5593. return obj;
  5594. } else {
  5595. var newObj = {};
  5596. if (obj != null) {
  5597. for (var key in obj) {
  5598. if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key];
  5599. }
  5600. }
  5601. newObj.default = obj;
  5602. return newObj;
  5603. }
  5604. }
  5605. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  5606. return typeof obj;
  5607. } : function (obj) {
  5608. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  5609. };
  5610. // The `PluginSocket` class contains the plugin architecture, and gets
  5611. // created whenever `pluggable.enable(obj);` is called on the object
  5612. // that you want to make pluggable.
  5613. // You can also see it as the thing into which the plugins are plugged.
  5614. // It takes two parameters, first, the object being made pluggable, and
  5615. // then the name by which the pluggable object may be referenced on the
  5616. // __super__ object (inside overrides).
  5617. function PluginSocket(plugged, name) {
  5618. this.name = name;
  5619. this.plugged = plugged;
  5620. if (typeof this.plugged.__super__ === 'undefined') {
  5621. this.plugged.__super__ = {};
  5622. } else if (typeof this.plugged.__super__ === 'string') {
  5623. this.plugged.__super__ = { '__string__': this.plugged.__super__ };
  5624. }
  5625. this.plugged.__super__[name] = this.plugged;
  5626. this.plugins = {};
  5627. this.initialized_plugins = [];
  5628. }
  5629. // Now we add methods to the PluginSocket by adding them to its
  5630. // prototype.
  5631. _.extend(PluginSocket.prototype, {
  5632. // `wrappedOverride` creates a partially applied wrapper function
  5633. // that makes sure to set the proper super method when the
  5634. // overriding method is called. This is done to enable
  5635. // chaining of plugin methods, all the way up to the
  5636. // original method.
  5637. wrappedOverride: function wrappedOverride(key, value, super_method, default_super) {
  5638. if (typeof super_method === "function") {
  5639. if (typeof this.__super__ === "undefined") {
  5640. /* We're not on the context of the plugged object.
  5641. * This can happen when the overridden method is called via
  5642. * an event handler or when it's a constructor.
  5643. *
  5644. * In this case, we simply tack on the __super__ obj.
  5645. */
  5646. this.__super__ = default_super;
  5647. }
  5648. this.__super__[key] = super_method.bind(this);
  5649. }
  5650. return value.apply(this, _.drop(arguments, 4));
  5651. },
  5652. // `_overrideAttribute` overrides an attribute on the original object
  5653. // (the thing being plugged into).
  5654. //
  5655. // If the attribute being overridden is a function, then the original
  5656. // function will still be available via the `__super__` attribute.
  5657. //
  5658. // If the same function is being overridden multiple times, then
  5659. // the original function will be available at the end of a chain of
  5660. // functions, starting from the most recent override, all the way
  5661. // back to the original function, each being referenced by the
  5662. // previous' __super__ attribute.
  5663. //
  5664. // For example:
  5665. //
  5666. // `plugin2.MyFunc.__super__.myFunc => plugin1.MyFunc.__super__.myFunc => original.myFunc`
  5667. _overrideAttribute: function _overrideAttribute(key, plugin) {
  5668. var value = plugin.overrides[key];
  5669. if (typeof value === "function") {
  5670. var default_super = {};
  5671. default_super[this.name] = this.plugged;
  5672. var wrapped_function = _.partial(this.wrappedOverride, key, value, this.plugged[key], default_super);
  5673. this.plugged[key] = wrapped_function;
  5674. } else {
  5675. this.plugged[key] = value;
  5676. }
  5677. },
  5678. _extendObject: function _extendObject(obj, attributes) {
  5679. if (!obj.prototype.__super__) {
  5680. obj.prototype.__super__ = {};
  5681. obj.prototype.__super__[this.name] = this.plugged;
  5682. }
  5683. var that = this;
  5684. _.each(attributes, function (value, key) {
  5685. if (key === 'events') {
  5686. obj.prototype[key] = _.extend(value, obj.prototype[key]);
  5687. } else if (typeof value === 'function') {
  5688. // We create a partially applied wrapper function, that
  5689. // makes sure to set the proper super method when the
  5690. // overriding method is called. This is done to enable
  5691. // chaining of plugin methods, all the way up to the
  5692. // original method.
  5693. var default_super = {};
  5694. default_super[that.name] = that.plugged;
  5695. var wrapped_function = _.partial(that.wrappedOverride, key, value, obj.prototype[key], default_super);
  5696. obj.prototype[key] = wrapped_function;
  5697. } else {
  5698. obj.prototype[key] = value;
  5699. }
  5700. });
  5701. },
  5702. // Plugins can specify optional dependencies (by means of the
  5703. // `optional_dependencies` list attribute) which refers to dependencies
  5704. // which will be initialized first, before the plugin itself gets initialized.
  5705. // They are optional in the sense that if they aren't available, an
  5706. // error won't be thrown.
  5707. // However, if you want to make these dependencies strict (i.e.
  5708. // non-optional), you can set the `strict_plugin_dependencies` attribute to `true`
  5709. // on the object being made pluggable (i.e. the object passed to
  5710. // `pluggable.enable`).
  5711. loadOptionalDependencies: function loadOptionalDependencies(plugin) {
  5712. var _this = this;
  5713. _.each(plugin.optional_dependencies, function (name) {
  5714. var dep = _this.plugins[name];
  5715. if (dep) {
  5716. if (_.includes(dep.optional_dependencies, plugin.__name__)) {
  5717. /* FIXME: circular dependency checking is only one level deep. */
  5718. throw "Found a circular dependency between the plugins \"" + plugin.__name__ + "\" and \"" + name + "\"";
  5719. }
  5720. _this.initializePlugin(dep);
  5721. } else {
  5722. _this.throwUndefinedDependencyError("Could not find optional dependency \"" + name + "\" " + "for the plugin \"" + plugin.__name__ + "\". " + "If it's needed, make sure it's loaded by require.js");
  5723. }
  5724. });
  5725. },
  5726. throwUndefinedDependencyError: function throwUndefinedDependencyError(msg) {
  5727. if (this.plugged.strict_plugin_dependencies) {
  5728. throw msg;
  5729. } else {
  5730. console.log(msg);
  5731. return;
  5732. }
  5733. },
  5734. // `applyOverrides` is called by initializePlugin. It applies any
  5735. // and all overrides of methods or Backbone views and models that
  5736. // are defined on any of the plugins.
  5737. applyOverrides: function applyOverrides(plugin) {
  5738. var _this2 = this;
  5739. _.each(Object.keys(plugin.overrides || {}), function (key) {
  5740. var override = plugin.overrides[key];
  5741. if ((typeof override === 'undefined' ? 'undefined' : _typeof(override)) === "object") {
  5742. if (typeof _this2.plugged[key] === 'undefined') {
  5743. _this2.throwUndefinedDependencyError("Error: Plugin \"" + plugin.__name__ + "\" tried to override " + key + " but it's not found.");
  5744. } else {
  5745. _this2._extendObject(_this2.plugged[key], override);
  5746. }
  5747. } else {
  5748. _this2._overrideAttribute(key, plugin);
  5749. }
  5750. });
  5751. },
  5752. // `initializePlugin` applies the overrides (if any) defined on all
  5753. // the registered plugins and then calls the initialize method for each plugin.
  5754. initializePlugin: function initializePlugin(plugin) {
  5755. if (!_.includes(_.keys(this.allowed_plugins), plugin.__name__)) {
  5756. /* Don't initialize disallowed plugins. */
  5757. return;
  5758. }
  5759. if (_.includes(this.initialized_plugins, plugin.__name__)) {
  5760. /* Don't initialize plugins twice, otherwise we get
  5761. * infinite recursion in overridden methods.
  5762. */
  5763. return;
  5764. }
  5765. _.extend(plugin, this.properties);
  5766. if (plugin.optional_dependencies) {
  5767. this.loadOptionalDependencies(plugin);
  5768. }
  5769. this.applyOverrides(plugin);
  5770. if (typeof plugin.initialize === "function") {
  5771. plugin.initialize.bind(plugin)(this);
  5772. }
  5773. this.initialized_plugins.push(plugin.__name__);
  5774. },
  5775. // `registerPlugin` registers (or inserts, if you'd like) a plugin,
  5776. // by adding it to the `plugins` map on the PluginSocket instance.
  5777. registerPlugin: function registerPlugin(name, plugin) {
  5778. if (name in this.plugins) {
  5779. throw new Error('Error: Plugin name ' + name + ' is already taken');
  5780. }
  5781. plugin.__name__ = name;
  5782. this.plugins[name] = plugin;
  5783. },
  5784. // `initializePlugins` should get called once all plugins have been
  5785. // registered. It will then iterate through all the plugins, calling
  5786. // `initializePlugin` for each.
  5787. // The passed in properties variable is an object with attributes and methods
  5788. // which will be attached to the plugins.
  5789. initializePlugins: function initializePlugins() {
  5790. var properties = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  5791. var whitelist = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  5792. var blacklist = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
  5793. if (!_.size(this.plugins)) {
  5794. return;
  5795. }
  5796. this.properties = properties;
  5797. this.allowed_plugins = _.pickBy(this.plugins, function (plugin, key) {
  5798. return (!whitelist.length || whitelist.length && _.includes(whitelist, key)) && !_.includes(blacklist, key);
  5799. });
  5800. _.each(_.values(this.allowed_plugins), this.initializePlugin.bind(this));
  5801. }
  5802. });
  5803. function enable(object, name, attrname) {
  5804. // Call the `enable` method to make an object pluggable
  5805. //
  5806. // It takes three parameters:
  5807. // - `object`: The object that gets made pluggable.
  5808. // - `name`: The string name by which the now pluggable object
  5809. // may be referenced on the __super__ obj (in overrides).
  5810. // The default value is "plugged".
  5811. // - `attrname`: The string name of the attribute on the now
  5812. // pluggable object, which refers to the PluginSocket instance
  5813. // that gets created.
  5814. if (typeof attrname === "undefined") {
  5815. attrname = "pluginSocket";
  5816. }
  5817. if (typeof name === 'undefined') {
  5818. name = 'plugged';
  5819. }
  5820. var ref = {};
  5821. ref[attrname] = new PluginSocket(object, name);
  5822. return _.extend(object, ref);
  5823. }
  5824. exports.enable = enable;
  5825. exports.default = {
  5826. enable: enable
  5827. };
  5828. });
  5829. //# sourceMappingURL=pluggable.js.map
  5830. ;
  5831. // Converse.js (A browser based XMPP chat client)
  5832. // http://conversejs.org
  5833. //
  5834. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  5835. // Licensed under the Mozilla Public License (MPLv2)
  5836. //
  5837. /*global Backbone, define, window, document, JSON */
  5838. (function (root, factory) {
  5839. define('converse-core',["sizzle", "es6-promise", "lodash.noconflict", "lodash.converter", "polyfill", "utils", "moment_with_locales", "strophe", "pluggable", "backbone.noconflict", "backbone.browserStorage", "backbone.overview"], factory);
  5840. })(undefined, function (sizzle, Promise, _, lodashConverter, polyfill, utils, moment, Strophe, pluggable, Backbone) {
  5841. /* Cannot use this due to Safari bug.
  5842. * See https://github.com/jcbrand/converse.js/issues/196
  5843. */
  5844. // "use strict";
  5845. // Create the FP (functional programming) version of lodash
  5846. var fp = lodashConverter(_.runInContext());
  5847. // Strophe globals
  5848. var _Strophe = Strophe,
  5849. $build = _Strophe.$build,
  5850. $iq = _Strophe.$iq,
  5851. $msg = _Strophe.$msg,
  5852. $pres = _Strophe.$pres;
  5853. var b64_sha1 = Strophe.SHA1.b64_sha1;
  5854. Strophe = Strophe.Strophe;
  5855. // Use Mustache style syntax for variable interpolation
  5856. /* Configuration of Lodash templates (this config is distinct to the
  5857. * config of requirejs-tpl in main.js). This one is for normal inline templates.
  5858. */
  5859. _.templateSettings = {
  5860. 'escape': /\{\{\{([\s\S]+?)\}\}\}/g,
  5861. 'evaluate': /\{\[([\s\S]+?)\]\}/g,
  5862. 'interpolate': /\{\{([\s\S]+?)\}\}/g
  5863. };
  5864. var _converse = {
  5865. 'templates': {},
  5866. 'promises': {}
  5867. };
  5868. _.extend(_converse, Backbone.Events);
  5869. _converse.core_plugins = ['converse-bookmarks', 'converse-chatview', 'converse-controlbox', 'converse-core', 'converse-disco', 'converse-dragresize', 'converse-headline', 'converse-mam', 'converse-minimize', 'converse-muc', 'converse-notification', 'converse-otr', 'converse-ping', 'converse-register', 'converse-roomslist', 'converse-rosterview', 'converse-vcard'];
  5870. // Make converse pluggable
  5871. pluggable.enable(_converse, '_converse', 'pluggable');
  5872. // Module-level constants
  5873. _converse.STATUS_WEIGHTS = {
  5874. 'offline': 6,
  5875. 'unavailable': 5,
  5876. 'xa': 4,
  5877. 'away': 3,
  5878. 'dnd': 2,
  5879. 'chat': 1, // We currently don't differentiate between "chat" and "online"
  5880. 'online': 1
  5881. };
  5882. _converse.PRETTY_CHAT_STATUS = {
  5883. 'offline': 'Offline',
  5884. 'unavailable': 'Unavailable',
  5885. 'xa': 'Extended Away',
  5886. 'away': 'Away',
  5887. 'dnd': 'Do not disturb',
  5888. 'chat': 'Chattty',
  5889. 'online': 'Online'
  5890. };
  5891. _converse.ANONYMOUS = "anonymous";
  5892. _converse.CLOSED = 'closed';
  5893. _converse.EXTERNAL = "external";
  5894. _converse.LOGIN = "login";
  5895. _converse.LOGOUT = "logout";
  5896. _converse.OPENED = 'opened';
  5897. _converse.PREBIND = "prebind";
  5898. var PRETTY_CONNECTION_STATUS = {
  5899. 0: 'ERROR',
  5900. 1: 'CONNECTING',
  5901. 2: 'CONNFAIL',
  5902. 3: 'AUTHENTICATING',
  5903. 4: 'AUTHFAIL',
  5904. 5: 'CONNECTED',
  5905. 6: 'DISCONNECTED',
  5906. 7: 'DISCONNECTING',
  5907. 8: 'ATTACHED',
  5908. 9: 'REDIRECT'
  5909. };
  5910. var DEFAULT_IMAGE_TYPE = 'image/png';
  5911. var DEFAULT_IMAGE = "iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAIAAABt+uBvAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gwHCy455JBsggAABkJJREFUeNrtnM1PE1sUwHvvTD8otWLHST/Gimi1CEgr6M6FEWuIBo2pujDVsNDEP8GN/4MbN7oxrlipG2OCgZgYlxAbkRYw1KqkIDRCSkM7nXvvW8x7vjyNeQ9m7p1p3z1LQk/v/Dhz7vkEXL161cHl9wI5Ag6IA+KAOCAOiAPigDggLhwQB2S+iNZ+PcYY/SWEEP2HAAAIoSAIoihCCP+ngDDGtVotGAz29/cfOXJEUZSOjg6n06lp2sbGRqlUWlhYyGazS0tLbrdbEASrzgksyeYJId3d3el0uqenRxRFAAAA4KdfIIRgjD9+/Pj8+fOpqSndslofEIQwHA6Pjo4mEon//qmFhYXHjx8vLi4ihBgDEnp7e9l8E0Jo165dQ0NDd+/eDYVC2/qsJElDQ0OEkKWlpa2tLZamxAhQo9EIBoOjo6MXL17csZLe3l5FUT59+lQul5l5JRaAVFWNRqN37tw5ceKEQVWRSOTw4cOFQuHbt2+iKLYCIISQLMu3b99OJpOmKAwEAgcPHszn8+vr6wzsiG6UQQhxuVyXLl0aGBgwUW0sFstkMl6v90fo1KyAMMYDAwPnzp0zXfPg4GAqlWo0Gk0MiBAiy/L58+edTqf5Aa4onj59OhaLYYybFRCEMBaL0fNxBw4cSCQStN0QRUBut3t4eJjq6U+dOiVJElVPRBFQIBDo6+ujCqirqyscDlONGykC2lYyYSR6pBoQQapHZwAoHo/TuARYAOrs7GQASFEUqn6aIiBJkhgA6ujooFpUo6iaTa7koFwnaoWadLNe81tbWwzoaJrWrICWl5cZAFpbW6OabVAEtLi4yABQsVjUNK0pAWWzWQaAcrlcswKanZ1VVZUqHYRQEwOq1Wpv3ryhCmh6erpcLjdrNl+v1ycnJ+l5UELI27dvv3//3qxxEADgy5cvExMT9Mznw4cPtFtAdAPFarU6Pj5eKpVM17yxsfHy5cvV1VXazXu62gVBKBQKT58+rdVqJqrFGL948eLdu3dU8/g/H4FBUaJYLAqC0NPTY9brMD4+PjY25mDSracOCABACJmZmXE6nUePHjWu8NWrV48ePSKEsGlAs7Agfd5nenq6Wq0mk0kjDzY2NvbkyRMIIbP2PLvhBUEQ8vl8NpuNx+M+n29bzhVjvLKycv/+/YmJCcazQuwA6YzW1tYmJyf1SY+2trZ/rRk1Go1SqfT69esHDx4UCgVmNaa/zZ/9ABUhRFXVYDB48uTJeDweiUQkSfL7/T9MA2NcqVTK5fLy8vL8/PzU1FSxWHS5XJaM4wGr9sUwxqqqer3eUCgkSZJuUBBCfTRvc3OzXC6vrKxUKhWn02nhCJ5lM4oQQo/HgxD6+vXr58+fHf8sDOp+HQDg8XgclorFU676dKLlo6yWRdItIBwQB8QBcUCtfosRQjRNQwhhjPUC4w46WXryBSHU1zgEQWBz99EFhDGu1+t+v//48ePxeFxRlD179ng8nh0Efgiher2+vr6ur3HMzMysrq7uTJVdACGEurq6Ll++nEgkPB7Pj9jPoDHqOxyqqubz+WfPnuVyuV9XPeyeagAAAoHArVu3BgcHab8CuVzu4cOHpVKJUnfA5GweY+xyuc6cOXPv3r1IJMLAR8iyPDw8XK/Xi8Wiqqqmm5KZgBBC7e3tN27cuHbtGuPVpf7+/lAoNDs7W61WzfVKpgHSSzw3b95MpVKW3MfRaDQSiczNzVUqFRMZmQOIEOL1eq9fv3727FlL1t50URRFluX5+flqtWpWEGAOIFEUU6nUlStXLKSjy759+xwOx9zcnKZpphzGHMzhcDiTydgk9r1w4YIp7RPTAAmCkMlk2FeLf/tIEKbTab/fbwtAhJBoNGrutpNx6e7uPnTokC1eMU3T0um0DZPMkZER6wERQnw+n/FFSxpy7Nix3bt3WwwIIcRgIWnHkkwmjecfRgGx7DtuV/r6+iwGhDHev3+/bQF1dnYaH6E2CkiWZdsC2rt3r8WAHA5HW1ubbQGZcjajgOwTH/4qNko1Wlg4IA6IA+KAOKBWBUQIsfNojyliKIoRRfH9+/dut9umf3wzpoUNNQ4BAJubmwz+ic+OxefzWWlBhJD29nbug7iT5sIBcUAcEAfEAXFAHBAHxOVn+QMrmWpuPZx12gAAAABJRU5ErkJggg==";
  5912. _converse.log = function (message, level) {
  5913. if (message instanceof Error) {
  5914. message = message.stack;
  5915. }
  5916. var logger = _.assignIn({
  5917. 'debug': _.noop,
  5918. 'error': _.noop,
  5919. 'info': _.noop,
  5920. 'warn': _.noop
  5921. }, console);
  5922. if (level === Strophe.LogLevel.ERROR) {
  5923. if (_converse.debug) {
  5924. logger.trace("ERROR: " + message);
  5925. } else {
  5926. logger.error("ERROR: " + message);
  5927. }
  5928. } else if (level === Strophe.LogLevel.WARN) {
  5929. logger.warn("WARNING: " + message);
  5930. } else if (level === Strophe.LogLevel.FATAL) {
  5931. if (_converse.debug) {
  5932. logger.error("FATAL: " + message);
  5933. } else {
  5934. logger.error("FATAL: " + message);
  5935. }
  5936. } else if (_converse.debug) {
  5937. if (level === Strophe.LogLevel.DEBUG) {
  5938. logger.debug("DEBUG: " + message);
  5939. } else {
  5940. logger.info("INFO: " + message);
  5941. }
  5942. }
  5943. };
  5944. var PROMISES = ['cachedRoster', 'chatBoxesFetched', 'pluginsInitialized', 'roster', 'rosterContactsFetched', 'rosterGroupsFetched', 'rosterInitialized', 'statusInitialized'];
  5945. function addPromise(promise) {
  5946. /* Private function, used to add a new promise to the ones already
  5947. * available via the `waitUntil` api method.
  5948. */
  5949. _converse.promises[promise] = utils.getWrappedPromise();
  5950. }
  5951. _converse.emit = function (name) {
  5952. /* Event emitter and promise resolver */
  5953. _converse.trigger.apply(this, arguments);
  5954. var promise = _converse.promises[name];
  5955. if (!_.isUndefined(promise)) {
  5956. promise.resolve();
  5957. }
  5958. };
  5959. _converse.initialize = function (settings, callback) {
  5960. "use strict";
  5961. var _this = this;
  5962. settings = !_.isUndefined(settings) ? settings : {};
  5963. var init_promise = utils.getWrappedPromise();
  5964. _.each(PROMISES, addPromise);
  5965. if (!_.isUndefined(_converse.chatboxes)) {
  5966. // Looks like _converse.initialized was called again without logging
  5967. // out or disconnecting in the previous session.
  5968. // This happens in tests. We therefore first clean up.
  5969. _converse.connection.reset();
  5970. _converse.off();
  5971. _converse.stopListening();
  5972. _converse._tearDown();
  5973. }
  5974. var unloadevent = void 0;
  5975. if ('onpagehide' in window) {
  5976. // Pagehide gets thrown in more cases than unload. Specifically it
  5977. // gets thrown when the page is cached and not just
  5978. // closed/destroyed. It's the only viable event on mobile Safari.
  5979. // https://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/
  5980. unloadevent = 'pagehide';
  5981. } else if ('onbeforeunload' in window) {
  5982. unloadevent = 'beforeunload';
  5983. } else if ('onunload' in window) {
  5984. unloadevent = 'unload';
  5985. }
  5986. // Logging
  5987. Strophe.log = function (level, msg) {
  5988. _converse.log(level + ' ' + msg, level);
  5989. };
  5990. Strophe.error = function (msg) {
  5991. _converse.log(msg, Strophe.LogLevel.ERROR);
  5992. };
  5993. // Add Strophe Namespaces
  5994. Strophe.addNamespace('CARBONS', 'urn:xmpp:carbons:2');
  5995. Strophe.addNamespace('CHATSTATES', 'http://jabber.org/protocol/chatstates');
  5996. Strophe.addNamespace('CSI', 'urn:xmpp:csi:0');
  5997. Strophe.addNamespace('DELAY', 'urn:xmpp:delay');
  5998. Strophe.addNamespace('HINTS', 'urn:xmpp:hints');
  5999. Strophe.addNamespace('MAM', 'urn:xmpp:mam:2');
  6000. Strophe.addNamespace('NICK', 'http://jabber.org/protocol/nick');
  6001. Strophe.addNamespace('PUBSUB', 'http://jabber.org/protocol/pubsub');
  6002. Strophe.addNamespace('ROSTERX', 'http://jabber.org/protocol/rosterx');
  6003. Strophe.addNamespace('RSM', 'http://jabber.org/protocol/rsm');
  6004. Strophe.addNamespace('XFORM', 'jabber:x:data');
  6005. // Instance level constants
  6006. this.TIMEOUTS = { // Set as module attr so that we can override in tests.
  6007. 'PAUSED': 10000,
  6008. 'INACTIVE': 90000
  6009. };
  6010. // Internationalization
  6011. this.locale = utils.getLocale(settings.i18n, utils.isConverseLocale);
  6012. if (!moment.locale) {
  6013. //moment.lang is deprecated after 2.8.1, use moment.locale instead
  6014. moment.locale = moment.lang;
  6015. }
  6016. moment.locale(utils.getLocale(settings.i18n, utils.isMomentLocale));
  6017. var __ = _converse.__ = utils.__.bind(_converse);
  6018. _converse.___ = utils.___;
  6019. // XEP-0085 Chat states
  6020. // http://xmpp.org/extensions/xep-0085.html
  6021. this.INACTIVE = 'inactive';
  6022. this.ACTIVE = 'active';
  6023. this.COMPOSING = 'composing';
  6024. this.PAUSED = 'paused';
  6025. this.GONE = 'gone';
  6026. // Default configuration values
  6027. // ----------------------------
  6028. this.default_settings = {
  6029. allow_contact_requests: true,
  6030. allow_non_roster_messaging: false,
  6031. animate: true,
  6032. authentication: 'login', // Available values are "login", "prebind", "anonymous" and "external".
  6033. auto_away: 0, // Seconds after which user status is set to 'away'
  6034. auto_login: false, // Currently only used in connection with anonymous login
  6035. auto_reconnect: false,
  6036. auto_subscribe: false,
  6037. auto_xa: 0, // Seconds after which user status is set to 'xa'
  6038. blacklisted_plugins: [],
  6039. bosh_service_url: undefined,
  6040. connection_options: {},
  6041. credentials_url: null, // URL from where login credentials can be fetched
  6042. csi_waiting_time: 0, // Support for XEP-0352. Seconds before client is considered idle and CSI is sent out.
  6043. debug: false,
  6044. default_state: 'online',
  6045. expose_rid_and_sid: false,
  6046. filter_by_resource: false,
  6047. forward_messages: false,
  6048. hide_offline_users: false,
  6049. include_offline_state: false,
  6050. jid: undefined,
  6051. keepalive: true,
  6052. locked_domain: undefined,
  6053. message_carbons: true,
  6054. message_storage: 'session',
  6055. password: undefined,
  6056. prebind_url: null,
  6057. priority: 0,
  6058. registration_domain: '',
  6059. rid: undefined,
  6060. roster_groups: true,
  6061. show_only_online_users: false,
  6062. show_send_button: false,
  6063. sid: undefined,
  6064. storage: 'session',
  6065. strict_plugin_dependencies: false,
  6066. synchronize_availability: true,
  6067. websocket_url: undefined,
  6068. whitelisted_plugins: [],
  6069. xhr_custom_status: false,
  6070. xhr_custom_status_url: ''
  6071. };
  6072. _.assignIn(this, this.default_settings);
  6073. // Allow only whitelisted configuration attributes to be overwritten
  6074. _.assignIn(this, _.pick(settings, _.keys(this.default_settings)));
  6075. if (this.authentication === _converse.ANONYMOUS) {
  6076. if (this.auto_login && !this.jid) {
  6077. throw new Error("Config Error: you need to provide the server's " + "domain via the 'jid' option when using anonymous " + "authentication with auto_login.");
  6078. }
  6079. }
  6080. // Module-level variables
  6081. // ----------------------
  6082. this.callback = callback || _.noop;
  6083. /* When reloading the page:
  6084. * For new sessions, we need to send out a presence stanza to notify
  6085. * the server/network that we're online.
  6086. * When re-attaching to an existing session (e.g. via the keepalive
  6087. * option), we don't need to again send out a presence stanza, because
  6088. * it's as if "we never left" (see onConnectStatusChanged).
  6089. * https://github.com/jcbrand/converse.js/issues/521
  6090. */
  6091. this.send_initial_presence = true;
  6092. this.msg_counter = 0;
  6093. this.user_settings = settings; // Save the user settings so that they can be used by plugins
  6094. // Module-level functions
  6095. // ----------------------
  6096. this.getViewForChatBox = function (chatbox) {
  6097. if (!chatbox) {
  6098. return;
  6099. }
  6100. return _converse.chatboxviews.get(chatbox.get('id'));
  6101. };
  6102. this.generateResource = function () {
  6103. return "/converse.js-" + Math.floor(Math.random() * 139749825).toString();
  6104. };
  6105. this.sendCSI = function (stat) {
  6106. /* Send out a Chat Status Notification (XEP-0352)
  6107. *
  6108. * Parameters:
  6109. * (String) stat: The user's chat status
  6110. */
  6111. /* Send out a Chat Status Notification (XEP-0352) */
  6112. // XXX if (converse.features[Strophe.NS.CSI] || true) {
  6113. _converse.connection.send($build(stat, { xmlns: Strophe.NS.CSI }));
  6114. _converse.inactive = stat === _converse.INACTIVE ? true : false;
  6115. };
  6116. this.onUserActivity = function () {
  6117. /* Resets counters and flags relating to CSI and auto_away/auto_xa */
  6118. if (_converse.idle_seconds > 0) {
  6119. _converse.idle_seconds = 0;
  6120. }
  6121. if (!_converse.connection.authenticated) {
  6122. // We can't send out any stanzas when there's no authenticated connection.
  6123. // converse can happen when the connection reconnects.
  6124. return;
  6125. }
  6126. if (_converse.inactive) {
  6127. _converse.sendCSI(_converse.ACTIVE);
  6128. }
  6129. if (_converse.auto_changed_status === true) {
  6130. _converse.auto_changed_status = false;
  6131. // XXX: we should really remember the original state here, and
  6132. // then set it back to that...
  6133. _converse.xmppstatus.setStatus(_converse.default_state);
  6134. }
  6135. };
  6136. this.onEverySecond = function () {
  6137. /* An interval handler running every second.
  6138. * Used for CSI and the auto_away and auto_xa features.
  6139. */
  6140. if (!_converse.connection.authenticated) {
  6141. // We can't send out any stanzas when there's no authenticated connection.
  6142. // This can happen when the connection reconnects.
  6143. return;
  6144. }
  6145. var stat = _converse.xmppstatus.getStatus();
  6146. _converse.idle_seconds++;
  6147. if (_converse.csi_waiting_time > 0 && _converse.idle_seconds > _converse.csi_waiting_time && !_converse.inactive) {
  6148. _converse.sendCSI(_converse.INACTIVE);
  6149. }
  6150. if (_converse.auto_away > 0 && _converse.idle_seconds > _converse.auto_away && stat !== 'away' && stat !== 'xa' && stat !== 'dnd') {
  6151. _converse.auto_changed_status = true;
  6152. _converse.xmppstatus.setStatus('away');
  6153. } else if (_converse.auto_xa > 0 && _converse.idle_seconds > _converse.auto_xa && stat !== 'xa' && stat !== 'dnd') {
  6154. _converse.auto_changed_status = true;
  6155. _converse.xmppstatus.setStatus('xa');
  6156. }
  6157. };
  6158. this.registerIntervalHandler = function () {
  6159. /* Set an interval of one second and register a handler for it.
  6160. * Required for the auto_away, auto_xa and csi_waiting_time features.
  6161. */
  6162. if (_converse.auto_away < 1 && _converse.auto_xa < 1 && _converse.csi_waiting_time < 1) {
  6163. // Waiting time of less then one second means features aren't used.
  6164. return;
  6165. }
  6166. _converse.idle_seconds = 0;
  6167. _converse.auto_changed_status = false; // Was the user's status changed by _converse.js?
  6168. window.addEventListener('click', _converse.onUserActivity);
  6169. window.addEventListener('focus', _converse.onUserActivity);
  6170. window.addEventListener('keypress', _converse.onUserActivity);
  6171. window.addEventListener('mousemove', _converse.onUserActivity);
  6172. window.addEventListener(unloadevent, _converse.onUserActivity);
  6173. _converse.everySecondTrigger = window.setInterval(_converse.onEverySecond, 1000);
  6174. };
  6175. this.giveFeedback = function (subject, klass, message) {
  6176. _.forEach(document.querySelectorAll('.conn-feedback'), function (el) {
  6177. el.classList.add('conn-feedback');
  6178. el.textContent = subject;
  6179. if (klass) {
  6180. el.classList.add(klass);
  6181. } else {
  6182. el.classList.remove('error');
  6183. }
  6184. });
  6185. _converse.emit('feedback', {
  6186. 'klass': klass,
  6187. 'message': message,
  6188. 'subject': subject
  6189. });
  6190. };
  6191. this.rejectPresenceSubscription = function (jid, message) {
  6192. /* Reject or cancel another user's subscription to our presence updates.
  6193. *
  6194. * Parameters:
  6195. * (String) jid - The Jabber ID of the user whose subscription
  6196. * is being canceled.
  6197. * (String) message - An optional message to the user
  6198. */
  6199. var pres = $pres({ to: jid, type: "unsubscribed" });
  6200. if (message && message !== "") {
  6201. pres.c("status").t(message);
  6202. }
  6203. _converse.connection.send(pres);
  6204. };
  6205. this.reconnect = _.debounce(function () {
  6206. _converse.log('RECONNECTING');
  6207. _converse.log('The connection has dropped, attempting to reconnect.');
  6208. _converse.giveFeedback(__("Reconnecting"), 'warn', __('The connection has dropped, attempting to reconnect.'));
  6209. _converse.connection.reconnecting = true;
  6210. _converse._tearDown();
  6211. _converse.logIn(null, true);
  6212. }, 3000, { 'leading': true });
  6213. this.disconnect = function () {
  6214. _converse.log('DISCONNECTED');
  6215. delete _converse.connection.reconnecting;
  6216. _converse.connection.reset();
  6217. _converse._tearDown();
  6218. _converse.chatboxviews.closeAllChatBoxes();
  6219. _converse.emit('disconnected');
  6220. };
  6221. this.onDisconnected = function () {
  6222. /* Gets called once strophe's status reaches Strophe.Status.DISCONNECTED.
  6223. * Will either start a teardown process for converse.js or attempt
  6224. * to reconnect.
  6225. */
  6226. if (_converse.disconnection_cause === Strophe.Status.AUTHFAIL) {
  6227. if (_converse.credentials_url && _converse.auto_reconnect) {
  6228. /* In this case, we reconnect, because we might be receiving
  6229. * expirable tokens from the credentials_url.
  6230. */
  6231. _converse.emit('will-reconnect');
  6232. return _converse.reconnect();
  6233. } else {
  6234. return _converse.disconnect();
  6235. }
  6236. } else if (_converse.disconnection_cause === _converse.LOGOUT || _converse.disconnection_reason === "host-unknown" || !_converse.auto_reconnect) {
  6237. return _converse.disconnect();
  6238. }
  6239. _converse.emit('will-reconnect');
  6240. _converse.reconnect();
  6241. };
  6242. this.setDisconnectionCause = function (cause, reason, override) {
  6243. /* Used to keep track of why we got disconnected, so that we can
  6244. * decide on what the next appropriate action is (in onDisconnected)
  6245. */
  6246. if (_.isUndefined(cause)) {
  6247. delete _converse.disconnection_cause;
  6248. delete _converse.disconnection_reason;
  6249. } else if (_.isUndefined(_converse.disconnection_cause) || override) {
  6250. _converse.disconnection_cause = cause;
  6251. _converse.disconnection_reason = reason;
  6252. }
  6253. };
  6254. this.onConnectStatusChanged = function (status, condition) {
  6255. /* Callback method called by Strophe as the Strophe.Connection goes
  6256. * through various states while establishing or tearing down a
  6257. * connection.
  6258. */
  6259. _converse.log("Status changed to: " + PRETTY_CONNECTION_STATUS[status]);
  6260. if (status === Strophe.Status.CONNECTED || status === Strophe.Status.ATTACHED) {
  6261. // By default we always want to send out an initial presence stanza.
  6262. _converse.send_initial_presence = true;
  6263. _converse.setDisconnectionCause();
  6264. if (_converse.connection.reconnecting) {
  6265. _converse.log(status === Strophe.Status.CONNECTED ? 'Reconnected' : 'Reattached');
  6266. _converse.onConnected(true);
  6267. } else {
  6268. _converse.log(status === Strophe.Status.CONNECTED ? 'Connected' : 'Attached');
  6269. if (_converse.connection.restored) {
  6270. // No need to send an initial presence stanza when
  6271. // we're restoring an existing session.
  6272. _converse.send_initial_presence = false;
  6273. }
  6274. _converse.onConnected();
  6275. }
  6276. } else if (status === Strophe.Status.DISCONNECTED) {
  6277. _converse.setDisconnectionCause(status, condition);
  6278. _converse.onDisconnected();
  6279. } else if (status === Strophe.Status.ERROR) {
  6280. _converse.giveFeedback(__('Connection error'), 'error', __('An error occurred while connecting to the chat server.'));
  6281. } else if (status === Strophe.Status.CONNECTING) {
  6282. _converse.giveFeedback(__('Connecting'));
  6283. } else if (status === Strophe.Status.AUTHENTICATING) {
  6284. _converse.giveFeedback(__('Authenticating'));
  6285. } else if (status === Strophe.Status.AUTHFAIL) {
  6286. _converse.giveFeedback(__('Authentication Failed'), 'error');
  6287. _converse.setDisconnectionCause(status, condition, true);
  6288. _converse.onDisconnected();
  6289. } else if (status === Strophe.Status.CONNFAIL) {
  6290. _converse.giveFeedback(__('Connection failed'), 'error', __("An error occurred while connecting to the chat server: " + condition));
  6291. _converse.setDisconnectionCause(status, condition);
  6292. } else if (status === Strophe.Status.DISCONNECTING) {
  6293. _converse.setDisconnectionCause(status, condition);
  6294. }
  6295. };
  6296. this.incrementMsgCounter = function () {
  6297. this.msg_counter += 1;
  6298. var unreadMsgCount = this.msg_counter;
  6299. if (document.title.search(/^Messages \(\d+\) /) === -1) {
  6300. document.title = "Messages (" + unreadMsgCount + ") " + document.title;
  6301. } else {
  6302. document.title = document.title.replace(/^Messages \(\d+\) /, "Messages (" + unreadMsgCount + ") ");
  6303. }
  6304. };
  6305. this.clearMsgCounter = function () {
  6306. this.msg_counter = 0;
  6307. if (document.title.search(/^Messages \(\d+\) /) !== -1) {
  6308. document.title = document.title.replace(/^Messages \(\d+\) /, "");
  6309. }
  6310. };
  6311. this.initStatus = function () {
  6312. return new Promise(function (resolve, reject) {
  6313. var promise = new utils.getWrappedPromise();
  6314. _this.xmppstatus = new _this.XMPPStatus();
  6315. var id = b64_sha1("converse.xmppstatus-" + _converse.bare_jid);
  6316. _this.xmppstatus.id = id; // Appears to be necessary for backbone.browserStorage
  6317. _this.xmppstatus.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
  6318. _this.xmppstatus.fetch({
  6319. success: resolve,
  6320. error: resolve
  6321. });
  6322. _converse.emit('statusInitialized');
  6323. });
  6324. };
  6325. this.initSession = function () {
  6326. this.session = new Backbone.Model();
  6327. var id = b64_sha1('converse.bosh-session');
  6328. this.session.id = id; // Appears to be necessary for backbone.browserStorage
  6329. this.session.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
  6330. this.session.fetch();
  6331. };
  6332. this.clearSession = function () {
  6333. if (!_.isUndefined(this.roster)) {
  6334. this.roster.browserStorage._clear();
  6335. }
  6336. if (!_.isUndefined(this.session) && this.session.browserStorage) {
  6337. this.session.browserStorage._clear();
  6338. }
  6339. };
  6340. this.logOut = function () {
  6341. _converse.chatboxviews.closeAllChatBoxes();
  6342. _converse.clearSession();
  6343. _converse.setDisconnectionCause(_converse.LOGOUT, undefined, true);
  6344. if (!_.isUndefined(_converse.connection)) {
  6345. _converse.connection.disconnect();
  6346. } else {
  6347. _converse._tearDown();
  6348. }
  6349. _converse.emit('logout');
  6350. };
  6351. this.saveWindowState = function (ev, hidden) {
  6352. // XXX: eventually we should be able to just use
  6353. // document.visibilityState (when we drop support for older
  6354. // browsers).
  6355. var state = void 0;
  6356. var event_map = {
  6357. 'focus': "visible",
  6358. 'focusin': "visible",
  6359. 'pageshow': "visible",
  6360. 'blur': "hidden",
  6361. 'focusout': "hidden",
  6362. 'pagehide': "hidden"
  6363. };
  6364. ev = ev || document.createEvent('Events');
  6365. if (ev.type in event_map) {
  6366. state = event_map[ev.type];
  6367. } else {
  6368. state = document[hidden] ? "hidden" : "visible";
  6369. }
  6370. if (state === 'visible') {
  6371. _converse.clearMsgCounter();
  6372. }
  6373. _converse.windowState = state;
  6374. _converse.emit('windowStateChanged', { state: state });
  6375. };
  6376. this.registerGlobalEventHandlers = function () {
  6377. // Taken from:
  6378. // http://stackoverflow.com/questions/1060008/is-there-a-way-to-detect-if-a-browser-window-is-not-currently-active
  6379. var hidden = "hidden";
  6380. // Standards:
  6381. if (hidden in document) {
  6382. document.addEventListener("visibilitychange", _.partial(_converse.saveWindowState, _, hidden));
  6383. } else if ((hidden = "mozHidden") in document) {
  6384. document.addEventListener("mozvisibilitychange", _.partial(_converse.saveWindowState, _, hidden));
  6385. } else if ((hidden = "webkitHidden") in document) {
  6386. document.addEventListener("webkitvisibilitychange", _.partial(_converse.saveWindowState, _, hidden));
  6387. } else if ((hidden = "msHidden") in document) {
  6388. document.addEventListener("msvisibilitychange", _.partial(_converse.saveWindowState, _, hidden));
  6389. } else if ("onfocusin" in document) {
  6390. // IE 9 and lower:
  6391. document.onfocusin = document.onfocusout = _.partial(_converse.saveWindowState, _, hidden);
  6392. } else {
  6393. // All others:
  6394. window.onpageshow = window.onpagehide = window.onfocus = window.onblur = _.partial(_converse.saveWindowState, _, hidden);
  6395. }
  6396. // set the initial state (but only if browser supports the Page Visibility API)
  6397. if (document[hidden] !== undefined) {
  6398. _.partial(_converse.saveWindowState, _, hidden)({ type: document[hidden] ? "blur" : "focus" });
  6399. }
  6400. };
  6401. this.enableCarbons = function () {
  6402. var _this2 = this;
  6403. /* Ask the XMPP server to enable Message Carbons
  6404. * See XEP-0280 https://xmpp.org/extensions/xep-0280.html#enabling
  6405. */
  6406. if (!this.message_carbons || this.session.get('carbons_enabled')) {
  6407. return;
  6408. }
  6409. var carbons_iq = new Strophe.Builder('iq', {
  6410. from: this.connection.jid,
  6411. id: 'enablecarbons',
  6412. type: 'set'
  6413. }).c('enable', { xmlns: Strophe.NS.CARBONS });
  6414. this.connection.addHandler(function (iq) {
  6415. if (iq.querySelectorAll('error').length > 0) {
  6416. _converse.log('An error occured while trying to enable message carbons.', Strophe.LogLevel.ERROR);
  6417. } else {
  6418. _this2.session.save({ carbons_enabled: true });
  6419. _converse.log('Message carbons have been enabled.');
  6420. }
  6421. }, null, "iq", null, "enablecarbons");
  6422. this.connection.send(carbons_iq);
  6423. };
  6424. this.initRoster = function () {
  6425. /* Initialize the Bakcbone collections that represent the contats
  6426. * roster and the roster groups.
  6427. */
  6428. _converse.roster = new _converse.RosterContacts();
  6429. _converse.roster.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.contacts-" + _converse.bare_jid));
  6430. _converse.rostergroups = new _converse.RosterGroups();
  6431. _converse.rostergroups.browserStorage = new Backbone.BrowserStorage.session(b64_sha1("converse.roster.groups" + _converse.bare_jid));
  6432. _converse.emit('rosterInitialized');
  6433. };
  6434. this.populateRoster = function () {
  6435. /* Fetch all the roster groups, and then the roster contacts.
  6436. * Emit an event after fetching is done in each case.
  6437. */
  6438. _converse.rostergroups.fetchRosterGroups().then(function () {
  6439. _converse.emit('rosterGroupsFetched');
  6440. _converse.roster.fetchRosterContacts().then(function () {
  6441. _converse.emit('rosterContactsFetched');
  6442. _converse.sendInitialPresence();
  6443. });
  6444. });
  6445. };
  6446. this.unregisterPresenceHandler = function () {
  6447. if (!_.isUndefined(_converse.presence_ref)) {
  6448. _converse.connection.deleteHandler(_converse.presence_ref);
  6449. delete _converse.presence_ref;
  6450. }
  6451. };
  6452. this.registerPresenceHandler = function () {
  6453. _converse.unregisterPresenceHandler();
  6454. _converse.presence_ref = _converse.connection.addHandler(function (presence) {
  6455. _converse.roster.presenceHandler(presence);
  6456. return true;
  6457. }, null, 'presence', null);
  6458. };
  6459. this.sendInitialPresence = function () {
  6460. if (_converse.send_initial_presence) {
  6461. _converse.xmppstatus.sendPresence();
  6462. }
  6463. };
  6464. this.onStatusInitialized = function (reconnecting) {
  6465. /* Continue with session establishment (e.g. fetching chat boxes,
  6466. * populating the roster etc.) necessary once the connection has
  6467. * been established.
  6468. */
  6469. if (reconnecting) {
  6470. // No need to recreate the roster, otherwise we lose our
  6471. // cached data. However we still emit an event, to give
  6472. // event handlers a chance to register views for the
  6473. // roster and its groups, before we start populating.
  6474. _converse.emit('rosterReadyAfterReconnection');
  6475. } else {
  6476. _converse.registerIntervalHandler();
  6477. _converse.initRoster();
  6478. }
  6479. // First set up chat boxes, before populating the roster, so that
  6480. // the controlbox is properly set up and ready for the rosterview.
  6481. _converse.roster.onConnected();
  6482. _converse.chatboxes.onConnected();
  6483. _converse.populateRoster();
  6484. _converse.registerPresenceHandler();
  6485. _converse.giveFeedback(__('Contacts'));
  6486. if (reconnecting) {
  6487. _converse.xmppstatus.sendPresence();
  6488. } else {
  6489. init_promise.resolve();
  6490. _converse.emit('initialized');
  6491. }
  6492. };
  6493. this.setUserJid = function () {
  6494. _converse.jid = _converse.connection.jid;
  6495. _converse.bare_jid = Strophe.getBareJidFromJid(_converse.connection.jid);
  6496. _converse.resource = Strophe.getResourceFromJid(_converse.connection.jid);
  6497. _converse.domain = Strophe.getDomainFromJid(_converse.connection.jid);
  6498. };
  6499. this.onConnected = function (reconnecting) {
  6500. /* Called as soon as a new connection has been established, either
  6501. * by logging in or by attaching to an existing BOSH session.
  6502. */
  6503. // Solves problem of returned PubSub BOSH response not received
  6504. // by browser.
  6505. _converse.connection.flush();
  6506. _converse.setUserJid();
  6507. _converse.initSession();
  6508. _converse.enableCarbons();
  6509. // If there's no xmppstatus obj, then we were never connected to
  6510. // begin with, so we set reconnecting to false.
  6511. reconnecting = _.isUndefined(_converse.xmppstatus) ? false : reconnecting;
  6512. if (reconnecting) {
  6513. _converse.onStatusInitialized(true);
  6514. _converse.emit('reconnected');
  6515. } else {
  6516. _converse.chatboxviews.closeAllChatBoxes();
  6517. _converse.initStatus().then(_.partial(_converse.onStatusInitialized, false), _.partial(_converse.onStatusInitialized, false)).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  6518. _converse.emit('connected');
  6519. }
  6520. };
  6521. this.RosterContact = Backbone.Model.extend({
  6522. defaults: {
  6523. 'bookmarked': false,
  6524. 'chat_state': undefined,
  6525. 'chat_status': 'offline',
  6526. 'groups': [],
  6527. 'image': DEFAULT_IMAGE,
  6528. 'image_type': DEFAULT_IMAGE_TYPE,
  6529. 'num_unread': 0,
  6530. 'status': ''
  6531. },
  6532. initialize: function initialize(attributes) {
  6533. var _this3 = this;
  6534. var jid = attributes.jid;
  6535. var bare_jid = Strophe.getBareJidFromJid(jid).toLowerCase();
  6536. var resource = Strophe.getResourceFromJid(jid);
  6537. attributes.jid = bare_jid;
  6538. this.set(_.assignIn({
  6539. 'id': bare_jid,
  6540. 'jid': bare_jid,
  6541. 'fullname': bare_jid,
  6542. 'user_id': Strophe.getNodeFromJid(jid),
  6543. 'resources': resource ? { resource: 0 } : {}
  6544. }, attributes));
  6545. this.on('destroy', function () {
  6546. _this3.removeFromRoster();
  6547. });
  6548. this.on('change:chat_status', function (item) {
  6549. _converse.emit('contactStatusChanged', item.attributes);
  6550. });
  6551. },
  6552. subscribe: function subscribe(message) {
  6553. /* Send a presence subscription request to this roster contact
  6554. *
  6555. * Parameters:
  6556. * (String) message - An optional message to explain the
  6557. * reason for the subscription request.
  6558. */
  6559. this.save('ask', "subscribe"); // ask === 'subscribe' Means we have ask to subscribe to them.
  6560. var pres = $pres({ to: this.get('jid'), type: "subscribe" });
  6561. if (message && message !== "") {
  6562. pres.c("status").t(message).up();
  6563. }
  6564. var nick = _converse.xmppstatus.get('fullname');
  6565. if (nick && nick !== "") {
  6566. pres.c('nick', { 'xmlns': Strophe.NS.NICK }).t(nick).up();
  6567. }
  6568. _converse.connection.send(pres);
  6569. return this;
  6570. },
  6571. ackSubscribe: function ackSubscribe() {
  6572. /* Upon receiving the presence stanza of type "subscribed",
  6573. * the user SHOULD acknowledge receipt of that subscription
  6574. * state notification by sending a presence stanza of type
  6575. * "subscribe" to the contact
  6576. */
  6577. _converse.connection.send($pres({
  6578. 'type': 'subscribe',
  6579. 'to': this.get('jid')
  6580. }));
  6581. },
  6582. ackUnsubscribe: function ackUnsubscribe() {
  6583. /* Upon receiving the presence stanza of type "unsubscribed",
  6584. * the user SHOULD acknowledge receipt of that subscription state
  6585. * notification by sending a presence stanza of type "unsubscribe"
  6586. * this step lets the user's server know that it MUST no longer
  6587. * send notification of the subscription state change to the user.
  6588. * Parameters:
  6589. * (String) jid - The Jabber ID of the user who is unsubscribing
  6590. */
  6591. _converse.connection.send($pres({ 'type': 'unsubscribe', 'to': this.get('jid') }));
  6592. this.destroy(); // Will cause removeFromRoster to be called.
  6593. },
  6594. unauthorize: function unauthorize(message) {
  6595. /* Unauthorize this contact's presence subscription
  6596. * Parameters:
  6597. * (String) message - Optional message to send to the person being unauthorized
  6598. */
  6599. _converse.rejectPresenceSubscription(this.get('jid'), message);
  6600. return this;
  6601. },
  6602. authorize: function authorize(message) {
  6603. /* Authorize presence subscription
  6604. * Parameters:
  6605. * (String) message - Optional message to send to the person being authorized
  6606. */
  6607. var pres = $pres({ to: this.get('jid'), type: "subscribed" });
  6608. if (message && message !== "") {
  6609. pres.c("status").t(message);
  6610. }
  6611. _converse.connection.send(pres);
  6612. return this;
  6613. },
  6614. addResource: function addResource(presence) {
  6615. /* Adds a new resource and it's associated attributes as taken
  6616. * from the passed in presence stanza.
  6617. *
  6618. * Also updates the contact's chat_status if the presence has
  6619. * higher priority (and is newer).
  6620. */
  6621. var jid = presence.getAttribute('from'),
  6622. chat_status = _.propertyOf(presence.querySelector('show'))('textContent') || 'online',
  6623. resource = Strophe.getResourceFromJid(jid),
  6624. delay = presence.querySelector("delay[xmlns=\"" + Strophe.NS.DELAY + "\"]"),
  6625. timestamp = _.isNull(delay) ? moment().format() : moment(delay.getAttribute('stamp')).format();
  6626. var priority = _.propertyOf(presence.querySelector('priority'))('textContent') || 0;
  6627. priority = _.isNaN(parseInt(priority, 10)) ? 0 : parseInt(priority, 10);
  6628. var resources = _.isObject(this.get('resources')) ? this.get('resources') : {};
  6629. resources[resource] = {
  6630. 'priority': priority,
  6631. 'status': chat_status,
  6632. 'timestamp': timestamp
  6633. };
  6634. var changed = { 'resources': resources };
  6635. var hpr = this.getHighestPriorityResource();
  6636. if (priority == hpr.priority && timestamp == hpr.timestamp) {
  6637. // Only set the chat status if this is the newest resource
  6638. // with the highest priority
  6639. changed.chat_status = chat_status;
  6640. }
  6641. this.save(changed);
  6642. return resources;
  6643. },
  6644. removeResource: function removeResource(resource) {
  6645. /* Remove the passed in resource from the contact's resources map.
  6646. *
  6647. * Also recomputes the chat_status given that there's one less
  6648. * resource.
  6649. */
  6650. var resources = this.get('resources');
  6651. if (!_.isObject(resources)) {
  6652. resources = {};
  6653. } else {
  6654. delete resources[resource];
  6655. }
  6656. this.save({
  6657. 'resources': resources,
  6658. 'chat_status': _.propertyOf(this.getHighestPriorityResource())('status') || 'offline'
  6659. });
  6660. },
  6661. getHighestPriorityResource: function getHighestPriorityResource() {
  6662. /* Return the resource with the highest priority.
  6663. *
  6664. * If multiple resources have the same priority, take the
  6665. * newest one.
  6666. */
  6667. var resources = this.get('resources');
  6668. if (_.isObject(resources) && _.size(resources)) {
  6669. var val = _.flow(_.values, _.partial(_.sortBy, _, ['priority', 'timestamp']), _.reverse)(resources)[0];
  6670. if (!_.isUndefined(val)) {
  6671. return val;
  6672. }
  6673. }
  6674. },
  6675. removeFromRoster: function removeFromRoster(callback) {
  6676. /* Instruct the XMPP server to remove this contact from our roster
  6677. * Parameters:
  6678. * (Function) callback
  6679. */
  6680. var iq = $iq({ type: 'set' }).c('query', { xmlns: Strophe.NS.ROSTER }).c('item', { jid: this.get('jid'), subscription: "remove" });
  6681. _converse.connection.sendIQ(iq, callback, callback);
  6682. return this;
  6683. }
  6684. });
  6685. this.RosterContacts = Backbone.Collection.extend({
  6686. model: _converse.RosterContact,
  6687. comparator: function comparator(contact1, contact2) {
  6688. var status1 = contact1.get('chat_status') || 'offline';
  6689. var status2 = contact2.get('chat_status') || 'offline';
  6690. if (_converse.STATUS_WEIGHTS[status1] === _converse.STATUS_WEIGHTS[status2]) {
  6691. var name1 = contact1.get('fullname').toLowerCase();
  6692. var name2 = contact2.get('fullname').toLowerCase();
  6693. return name1 < name2 ? -1 : name1 > name2 ? 1 : 0;
  6694. } else {
  6695. return _converse.STATUS_WEIGHTS[status1] < _converse.STATUS_WEIGHTS[status2] ? -1 : 1;
  6696. }
  6697. },
  6698. onConnected: function onConnected() {
  6699. /* Called as soon as the connection has been established
  6700. * (either after initial login, or after reconnection).
  6701. *
  6702. * Use the opportunity to register stanza handlers.
  6703. */
  6704. this.registerRosterHandler();
  6705. this.registerRosterXHandler();
  6706. },
  6707. registerRosterHandler: function registerRosterHandler() {
  6708. /* Register a handler for roster IQ "set" stanzas, which update
  6709. * roster contacts.
  6710. */
  6711. _converse.connection.addHandler(_converse.roster.onRosterPush.bind(_converse.roster), Strophe.NS.ROSTER, 'iq', "set");
  6712. },
  6713. registerRosterXHandler: function registerRosterXHandler() {
  6714. /* Register a handler for RosterX message stanzas, which are
  6715. * used to suggest roster contacts to a user.
  6716. */
  6717. var t = 0;
  6718. _converse.connection.addHandler(function (msg) {
  6719. window.setTimeout(function () {
  6720. _converse.connection.flush();
  6721. _converse.roster.subscribeToSuggestedItems.bind(_converse.roster)(msg);
  6722. }, t);
  6723. t += msg.querySelectorAll('item').length * 250;
  6724. return true;
  6725. }, Strophe.NS.ROSTERX, 'message', null);
  6726. },
  6727. fetchRosterContacts: function fetchRosterContacts() {
  6728. var _this4 = this;
  6729. /* Fetches the roster contacts, first by trying the
  6730. * sessionStorage cache, and if that's empty, then by querying
  6731. * the XMPP server.
  6732. *
  6733. * Returns a promise which resolves once the contacts have been
  6734. * fetched.
  6735. */
  6736. return new Promise(function (resolve, reject) {
  6737. _this4.fetch({
  6738. add: true,
  6739. success: function success(collection) {
  6740. if (collection.length === 0) {
  6741. /* We don't have any roster contacts stored in sessionStorage,
  6742. * so lets fetch the roster from the XMPP server. We pass in
  6743. * 'sendPresence' as callback method, because after initially
  6744. * fetching the roster we are ready to receive presence
  6745. * updates from our contacts.
  6746. */
  6747. _converse.send_initial_presence = true;
  6748. _converse.roster.fetchFromServer(resolve);
  6749. } else {
  6750. _converse.emit('cachedRoster', collection);
  6751. resolve();
  6752. }
  6753. }
  6754. });
  6755. });
  6756. },
  6757. subscribeToSuggestedItems: function subscribeToSuggestedItems(msg) {
  6758. _.each(msg.querySelectorAll('item'), function (item) {
  6759. if (item.getAttribute('action') === 'add') {
  6760. _converse.roster.addAndSubscribe(item.getAttribute('jid'), null, _converse.xmppstatus.get('fullname'));
  6761. }
  6762. });
  6763. return true;
  6764. },
  6765. isSelf: function isSelf(jid) {
  6766. return utils.isSameBareJID(jid, _converse.connection.jid);
  6767. },
  6768. addAndSubscribe: function addAndSubscribe(jid, name, groups, message, attributes) {
  6769. /* Add a roster contact and then once we have confirmation from
  6770. * the XMPP server we subscribe to that contact's presence updates.
  6771. * Parameters:
  6772. * (String) jid - The Jabber ID of the user being added and subscribed to.
  6773. * (String) name - The name of that user
  6774. * (Array of Strings) groups - Any roster groups the user might belong to
  6775. * (String) message - An optional message to explain the
  6776. * reason for the subscription request.
  6777. * (Object) attributes - Any additional attributes to be stored on the user's model.
  6778. */
  6779. var handler = function handler(contact) {
  6780. if (contact instanceof _converse.RosterContact) {
  6781. contact.subscribe(message);
  6782. }
  6783. };
  6784. this.addContact(jid, name, groups, attributes).then(handler, handler);
  6785. },
  6786. sendContactAddIQ: function sendContactAddIQ(jid, name, groups, callback, errback) {
  6787. /* Send an IQ stanza to the XMPP server to add a new roster contact.
  6788. *
  6789. * Parameters:
  6790. * (String) jid - The Jabber ID of the user being added
  6791. * (String) name - The name of that user
  6792. * (Array of Strings) groups - Any roster groups the user might belong to
  6793. * (Function) callback - A function to call once the IQ is returned
  6794. * (Function) errback - A function to call if an error occured
  6795. */
  6796. name = _.isEmpty(name) ? jid : name;
  6797. var iq = $iq({ type: 'set' }).c('query', { xmlns: Strophe.NS.ROSTER }).c('item', { jid: jid, name: name });
  6798. _.each(groups, function (group) {
  6799. iq.c('group').t(group).up();
  6800. });
  6801. _converse.connection.sendIQ(iq, callback, errback);
  6802. },
  6803. addContact: function addContact(jid, name, groups, attributes) {
  6804. var _this5 = this;
  6805. /* Adds a RosterContact instance to _converse.roster and
  6806. * registers the contact on the XMPP server.
  6807. * Returns a promise which is resolved once the XMPP server has
  6808. * responded.
  6809. *
  6810. * Parameters:
  6811. * (String) jid - The Jabber ID of the user being added and subscribed to.
  6812. * (String) name - The name of that user
  6813. * (Array of Strings) groups - Any roster groups the user might belong to
  6814. * (Object) attributes - Any additional attributes to be stored on the user's model.
  6815. */
  6816. return new Promise(function (resolve, reject) {
  6817. groups = groups || [];
  6818. name = _.isEmpty(name) ? jid : name;
  6819. _this5.sendContactAddIQ(jid, name, groups, function () {
  6820. var contact = _this5.create(_.assignIn({
  6821. ask: undefined,
  6822. fullname: name,
  6823. groups: groups,
  6824. jid: jid,
  6825. requesting: false,
  6826. subscription: 'none'
  6827. }, attributes), { sort: false });
  6828. resolve(contact);
  6829. }, function (err) {
  6830. alert(__("Sorry, there was an error while trying to add " + name + " as a contact."));
  6831. _converse.log(err, Strophe.LogLevel.ERROR);
  6832. resolve(err);
  6833. });
  6834. });
  6835. },
  6836. subscribeBack: function subscribeBack(bare_jid) {
  6837. var contact = this.get(bare_jid);
  6838. if (contact instanceof _converse.RosterContact) {
  6839. contact.authorize().subscribe();
  6840. } else {
  6841. // Can happen when a subscription is retried or roster was deleted
  6842. var handler = function handler(contact) {
  6843. if (contact instanceof _converse.RosterContact) {
  6844. contact.authorize().subscribe();
  6845. }
  6846. };
  6847. this.addContact(bare_jid, '', [], { 'subscription': 'from' }).then(handler, handler);
  6848. }
  6849. },
  6850. getNumOnlineContacts: function getNumOnlineContacts() {
  6851. var ignored = ['offline', 'unavailable'];
  6852. if (_converse.show_only_online_users) {
  6853. ignored = _.union(ignored, ['dnd', 'xa', 'away']);
  6854. }
  6855. return _.sum(this.models.filter(function (model) {
  6856. return !_.includes(ignored, model.get('chat_status'));
  6857. }));
  6858. },
  6859. onRosterPush: function onRosterPush(iq) {
  6860. /* Handle roster updates from the XMPP server.
  6861. * See: https://xmpp.org/rfcs/rfc6121.html#roster-syntax-actions-push
  6862. *
  6863. * Parameters:
  6864. * (XMLElement) IQ - The IQ stanza received from the XMPP server.
  6865. */
  6866. var id = iq.getAttribute('id');
  6867. var from = iq.getAttribute('from');
  6868. if (from && from !== "" && Strophe.getBareJidFromJid(from) !== _converse.bare_jid) {
  6869. // Receiving client MUST ignore stanza unless it has no from or from = user's bare JID.
  6870. // XXX: Some naughty servers apparently send from a full
  6871. // JID so we need to explicitly compare bare jids here.
  6872. // https://github.com/jcbrand/converse.js/issues/493
  6873. _converse.connection.send($iq({ type: 'error', id: id, from: _converse.connection.jid }).c('error', { 'type': 'cancel' }).c('service-unavailable', { 'xmlns': Strophe.NS.ROSTER }));
  6874. return true;
  6875. }
  6876. _converse.connection.send($iq({ type: 'result', id: id, from: _converse.connection.jid }));
  6877. var items = sizzle("query[xmlns=\"" + Strophe.NS.ROSTER + "\"] item", iq);
  6878. _.each(items, this.updateContact.bind(this));
  6879. _converse.emit('rosterPush', iq);
  6880. return true;
  6881. },
  6882. fetchFromServer: function fetchFromServer(callback) {
  6883. var _this6 = this,
  6884. _arguments = arguments;
  6885. /* Get the roster from the XMPP server */
  6886. var iq = $iq({ type: 'get', 'id': _converse.connection.getUniqueId('roster') }).c('query', { xmlns: Strophe.NS.ROSTER });
  6887. return _converse.connection.sendIQ(iq, function (iq) {
  6888. _this6.onReceivedFromServer(iq);
  6889. callback.apply(_this6, _arguments);
  6890. });
  6891. },
  6892. onReceivedFromServer: function onReceivedFromServer(iq) {
  6893. /* An IQ stanza containing the roster has been received from
  6894. * the XMPP server.
  6895. */
  6896. var items = sizzle("query[xmlns=\"" + Strophe.NS.ROSTER + "\"] item", iq);
  6897. _.each(items, this.updateContact.bind(this));
  6898. _converse.emit('roster', iq);
  6899. },
  6900. updateContact: function updateContact(item) {
  6901. /* Update or create RosterContact models based on items
  6902. * received in the IQ from the server.
  6903. */
  6904. var jid = item.getAttribute('jid');
  6905. if (this.isSelf(jid)) {
  6906. return;
  6907. }
  6908. var contact = this.get(jid),
  6909. subscription = item.getAttribute("subscription"),
  6910. ask = item.getAttribute("ask"),
  6911. groups = _.map(item.getElementsByTagName('group'), Strophe.getText);
  6912. if (!contact) {
  6913. if (subscription === "none" && ask === null || subscription === "remove") {
  6914. return; // We're lazy when adding contacts.
  6915. }
  6916. this.create({
  6917. ask: ask,
  6918. fullname: item.getAttribute("name") || jid,
  6919. groups: groups,
  6920. jid: jid,
  6921. subscription: subscription
  6922. }, { sort: false });
  6923. } else {
  6924. if (subscription === "remove") {
  6925. return contact.destroy(); // will trigger removeFromRoster
  6926. }
  6927. // We only find out about requesting contacts via the
  6928. // presence handler, so if we receive a contact
  6929. // here, we know they aren't requesting anymore.
  6930. // see docs/DEVELOPER.rst
  6931. contact.save({
  6932. subscription: subscription,
  6933. ask: ask,
  6934. requesting: null,
  6935. groups: groups
  6936. });
  6937. }
  6938. },
  6939. createRequestingContact: function createRequestingContact(presence) {
  6940. /* Creates a Requesting Contact.
  6941. *
  6942. * Note: this method gets completely overridden by converse-vcard.js
  6943. */
  6944. var bare_jid = Strophe.getBareJidFromJid(presence.getAttribute('from')),
  6945. nick_el = presence.querySelector("nick[xmlns=\"" + Strophe.NS.NICK + "\"]");
  6946. var user_data = {
  6947. jid: bare_jid,
  6948. subscription: 'none',
  6949. ask: null,
  6950. requesting: true,
  6951. fullname: nick_el && nick_el.textContent || bare_jid
  6952. };
  6953. this.create(user_data);
  6954. _converse.emit('contactRequest', user_data);
  6955. },
  6956. handleIncomingSubscription: function handleIncomingSubscription(presence) {
  6957. var jid = presence.getAttribute('from'),
  6958. bare_jid = Strophe.getBareJidFromJid(jid),
  6959. contact = this.get(bare_jid);
  6960. if (!_converse.allow_contact_requests) {
  6961. _converse.rejectPresenceSubscription(jid, __("This client does not allow presence subscriptions"));
  6962. }
  6963. if (_converse.auto_subscribe) {
  6964. if (!contact || contact.get('subscription') !== 'to') {
  6965. this.subscribeBack(bare_jid);
  6966. } else {
  6967. contact.authorize();
  6968. }
  6969. } else {
  6970. if (contact) {
  6971. if (contact.get('subscription') !== 'none') {
  6972. contact.authorize();
  6973. } else if (contact.get('ask') === "subscribe") {
  6974. contact.authorize();
  6975. }
  6976. } else {
  6977. this.createRequestingContact(presence);
  6978. }
  6979. }
  6980. },
  6981. presenceHandler: function presenceHandler(presence) {
  6982. var presence_type = presence.getAttribute('type');
  6983. if (presence_type === 'error') {
  6984. return true;
  6985. }
  6986. var jid = presence.getAttribute('from'),
  6987. bare_jid = Strophe.getBareJidFromJid(jid),
  6988. resource = Strophe.getResourceFromJid(jid),
  6989. chat_status = _.propertyOf(presence.querySelector('show'))('textContent') || 'online',
  6990. status_message = _.propertyOf(presence.querySelector('status'))('textContent'),
  6991. contact = this.get(bare_jid);
  6992. if (this.isSelf(bare_jid)) {
  6993. if (_converse.connection.jid !== jid && presence_type !== 'unavailable' && (_converse.synchronize_availability === true || _converse.synchronize_availability === resource)) {
  6994. // Another resource has changed its status and
  6995. // synchronize_availability option set to update,
  6996. // we'll update ours as well.
  6997. _converse.xmppstatus.save({ 'status': chat_status });
  6998. if (status_message) {
  6999. _converse.xmppstatus.save({ 'status_message': status_message });
  7000. }
  7001. }
  7002. return;
  7003. } else if (sizzle("query[xmlns=\"" + Strophe.NS.MUC + "\"]", presence).length) {
  7004. return; // Ignore MUC
  7005. }
  7006. if (contact && status_message !== contact.get('status')) {
  7007. contact.save({ 'status': status_message });
  7008. }
  7009. if (presence_type === 'subscribed' && contact) {
  7010. contact.ackSubscribe();
  7011. } else if (presence_type === 'unsubscribed' && contact) {
  7012. contact.ackUnsubscribe();
  7013. } else if (presence_type === 'unsubscribe') {
  7014. return;
  7015. } else if (presence_type === 'subscribe') {
  7016. this.handleIncomingSubscription(presence);
  7017. } else if (presence_type === 'unavailable' && contact) {
  7018. contact.removeResource(resource);
  7019. } else if (contact) {
  7020. // presence_type is undefined
  7021. contact.addResource(presence);
  7022. }
  7023. }
  7024. });
  7025. this.RosterGroup = Backbone.Model.extend({
  7026. initialize: function initialize(attributes) {
  7027. this.set(_.assignIn({
  7028. description: __('Click to hide these contacts'),
  7029. state: _converse.OPENED
  7030. }, attributes));
  7031. // Collection of contacts belonging to this group.
  7032. this.contacts = new _converse.RosterContacts();
  7033. }
  7034. });
  7035. this.RosterGroups = Backbone.Collection.extend({
  7036. model: _converse.RosterGroup,
  7037. fetchRosterGroups: function fetchRosterGroups() {
  7038. var _this7 = this;
  7039. /* Fetches all the roster groups from sessionStorage.
  7040. *
  7041. * Returns a promise which resolves once the groups have been
  7042. * returned.
  7043. */
  7044. return new Promise(function (resolve, reject) {
  7045. _this7.fetch({
  7046. silent: true, // We need to first have all groups before
  7047. // we can start positioning them, so we set
  7048. // 'silent' to true.
  7049. success: resolve
  7050. });
  7051. });
  7052. }
  7053. });
  7054. this.Message = Backbone.Model.extend({
  7055. defaults: function defaults() {
  7056. return {
  7057. msgid: _converse.connection.getUniqueId()
  7058. };
  7059. }
  7060. });
  7061. this.Messages = Backbone.Collection.extend({
  7062. model: _converse.Message,
  7063. comparator: 'time'
  7064. });
  7065. this.ChatBox = Backbone.Model.extend({
  7066. defaults: {
  7067. 'type': 'chatbox',
  7068. 'bookmarked': false,
  7069. 'chat_state': undefined,
  7070. 'num_unread': 0,
  7071. 'url': ''
  7072. },
  7073. initialize: function initialize() {
  7074. this.messages = new _converse.Messages();
  7075. this.messages.browserStorage = new Backbone.BrowserStorage[_converse.message_storage](b64_sha1("converse.messages" + this.get('jid') + _converse.bare_jid));
  7076. this.save({
  7077. // The chat_state will be set to ACTIVE once the chat box is opened
  7078. // and we listen for change:chat_state, so shouldn't set it to ACTIVE here.
  7079. 'box_id': b64_sha1(this.get('jid')),
  7080. 'time_opened': this.get('time_opened') || moment().valueOf(),
  7081. 'user_id': Strophe.getNodeFromJid(this.get('jid'))
  7082. });
  7083. },
  7084. getMessageBody: function getMessageBody(message) {
  7085. var type = message.getAttribute('type');
  7086. return type === 'error' ? _.propertyOf(message.querySelector('error text'))('textContent') : _.propertyOf(message.querySelector('body'))('textContent');
  7087. },
  7088. getMessageAttributes: function getMessageAttributes(message, delay, original_stanza) {
  7089. delay = delay || message.querySelector('delay');
  7090. var type = message.getAttribute('type'),
  7091. body = this.getMessageBody(message);
  7092. var delayed = !_.isNull(delay),
  7093. is_groupchat = type === 'groupchat',
  7094. chat_state = message.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || message.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || message.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || message.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || message.getElementsByTagName(_converse.GONE).length && _converse.GONE;
  7095. var from = void 0;
  7096. if (is_groupchat) {
  7097. from = Strophe.unescapeNode(Strophe.getResourceFromJid(message.getAttribute('from')));
  7098. } else {
  7099. from = Strophe.getBareJidFromJid(message.getAttribute('from'));
  7100. }
  7101. var time = delayed ? delay.getAttribute('stamp') : moment().format();
  7102. var sender = void 0,
  7103. fullname = void 0;
  7104. if (is_groupchat && from === this.get('nick') || !is_groupchat && from === _converse.bare_jid) {
  7105. sender = 'me';
  7106. fullname = _converse.xmppstatus.get('fullname') || from;
  7107. } else {
  7108. sender = 'them';
  7109. fullname = this.get('fullname') || from;
  7110. }
  7111. return {
  7112. 'type': type,
  7113. 'chat_state': chat_state,
  7114. 'delayed': delayed,
  7115. 'fullname': fullname,
  7116. 'message': body || undefined,
  7117. 'msgid': message.getAttribute('id'),
  7118. 'sender': sender,
  7119. 'time': time
  7120. };
  7121. },
  7122. createMessage: function createMessage(message, delay, original_stanza) {
  7123. return this.messages.create(this.getMessageAttributes.apply(this, arguments));
  7124. },
  7125. newMessageWillBeHidden: function newMessageWillBeHidden() {
  7126. /* Returns a boolean to indicate whether a newly received
  7127. * message will be visible to the user or not.
  7128. */
  7129. return this.get('hidden') || this.get('minimized') || this.isScrolledUp() || _converse.windowState === 'hidden';
  7130. },
  7131. incrementUnreadMsgCounter: function incrementUnreadMsgCounter(stanza) {
  7132. /* Given a newly received message, update the unread counter if
  7133. * necessary.
  7134. */
  7135. if (_.isNull(stanza.querySelector('body'))) {
  7136. return; // The message has no text
  7137. }
  7138. if (utils.isNewMessage(stanza) && this.newMessageWillBeHidden()) {
  7139. this.save({ 'num_unread': this.get('num_unread') + 1 });
  7140. _converse.incrementMsgCounter();
  7141. }
  7142. },
  7143. clearUnreadMsgCounter: function clearUnreadMsgCounter() {
  7144. this.save({ 'num_unread': 0 });
  7145. },
  7146. isScrolledUp: function isScrolledUp() {
  7147. return this.get('scrolled', true);
  7148. }
  7149. });
  7150. this.ChatBoxes = Backbone.Collection.extend({
  7151. comparator: 'time_opened',
  7152. model: function model(attrs, options) {
  7153. return new _converse.ChatBox(attrs, options);
  7154. },
  7155. registerMessageHandler: function registerMessageHandler() {
  7156. _converse.connection.addHandler(this.onMessage.bind(this), null, 'message', 'chat');
  7157. _converse.connection.addHandler(this.onErrorMessage.bind(this), null, 'message', 'error');
  7158. },
  7159. chatBoxMayBeShown: function chatBoxMayBeShown(chatbox) {
  7160. return true;
  7161. },
  7162. onChatBoxesFetched: function onChatBoxesFetched(collection) {
  7163. var _this8 = this;
  7164. /* Show chat boxes upon receiving them from sessionStorage
  7165. *
  7166. * This method gets overridden entirely in src/converse-controlbox.js
  7167. * if the controlbox plugin is active.
  7168. */
  7169. collection.each(function (chatbox) {
  7170. if (_this8.chatBoxMayBeShown(chatbox)) {
  7171. chatbox.trigger('show');
  7172. }
  7173. });
  7174. _converse.emit('chatBoxesFetched');
  7175. },
  7176. onConnected: function onConnected() {
  7177. this.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.chatboxes-" + _converse.bare_jid));
  7178. this.registerMessageHandler();
  7179. this.fetch({
  7180. add: true,
  7181. success: this.onChatBoxesFetched.bind(this)
  7182. });
  7183. },
  7184. onErrorMessage: function onErrorMessage(message) {
  7185. /* Handler method for all incoming error message stanzas
  7186. */
  7187. // TODO: we can likely just reuse "onMessage" below
  7188. var from_jid = Strophe.getBareJidFromJid(message.getAttribute('from'));
  7189. if (utils.isSameBareJID(from_jid, _converse.bare_jid)) {
  7190. return true;
  7191. }
  7192. // Get chat box, but only create a new one when the message has a body.
  7193. var chatbox = this.getChatBox(from_jid);
  7194. if (!chatbox) {
  7195. return true;
  7196. }
  7197. chatbox.createMessage(message, null, message);
  7198. return true;
  7199. },
  7200. onMessage: function onMessage(message) {
  7201. /* Handler method for all incoming single-user chat "message"
  7202. * stanzas.
  7203. */
  7204. var contact_jid = void 0,
  7205. delay = void 0,
  7206. resource = void 0,
  7207. from_jid = message.getAttribute('from'),
  7208. to_jid = message.getAttribute('to');
  7209. var original_stanza = message,
  7210. to_resource = Strophe.getResourceFromJid(to_jid),
  7211. is_carbon = !_.isNull(message.querySelector("received[xmlns=\"" + Strophe.NS.CARBONS + "\"]"));
  7212. if (_converse.filter_by_resource && to_resource && to_resource !== _converse.resource) {
  7213. _converse.log("onMessage: Ignoring incoming message intended for a different resource: " + to_jid, Strophe.LogLevel.INFO);
  7214. return true;
  7215. } else if (utils.isHeadlineMessage(message)) {
  7216. // XXX: Ideally we wouldn't have to check for headline
  7217. // messages, but Prosody sends headline messages with the
  7218. // wrong type ('chat'), so we need to filter them out here.
  7219. _converse.log("onMessage: Ignoring incoming headline message sent with type 'chat' from JID: " + from_jid, Strophe.LogLevel.INFO);
  7220. return true;
  7221. }
  7222. var forwarded = message.querySelector('forwarded');
  7223. if (!_.isNull(forwarded)) {
  7224. var forwarded_message = forwarded.querySelector('message');
  7225. var forwarded_from = forwarded_message.getAttribute('from');
  7226. if (is_carbon && Strophe.getBareJidFromJid(forwarded_from) !== from_jid) {
  7227. // Prevent message forging via carbons
  7228. //
  7229. // https://xmpp.org/extensions/xep-0280.html#security
  7230. return true;
  7231. }
  7232. message = forwarded_message;
  7233. delay = forwarded.querySelector('delay');
  7234. from_jid = message.getAttribute('from');
  7235. to_jid = message.getAttribute('to');
  7236. }
  7237. var from_bare_jid = Strophe.getBareJidFromJid(from_jid),
  7238. from_resource = Strophe.getResourceFromJid(from_jid),
  7239. is_me = from_bare_jid === _converse.bare_jid;
  7240. if (is_me) {
  7241. // I am the sender, so this must be a forwarded message...
  7242. contact_jid = Strophe.getBareJidFromJid(to_jid);
  7243. resource = Strophe.getResourceFromJid(to_jid);
  7244. } else {
  7245. contact_jid = from_bare_jid;
  7246. resource = from_resource;
  7247. }
  7248. // Get chat box, but only create a new one when the message has a body.
  7249. var chatbox = this.getChatBox(contact_jid, !_.isNull(message.querySelector('body'))),
  7250. msgid = message.getAttribute('id');
  7251. if (chatbox) {
  7252. var messages = msgid && chatbox.messages.findWhere({ msgid: msgid }) || [];
  7253. if (_.isEmpty(messages)) {
  7254. // Only create the message when we're sure it's not a
  7255. // duplicate
  7256. chatbox.incrementUnreadMsgCounter(original_stanza);
  7257. chatbox.createMessage(message, delay, original_stanza);
  7258. }
  7259. }
  7260. _converse.emit('message', { 'stanza': original_stanza, 'chatbox': chatbox });
  7261. return true;
  7262. },
  7263. createChatBox: function createChatBox(jid, attrs) {
  7264. /* Creates a chat box
  7265. *
  7266. * Parameters:
  7267. * (String) jid - The JID of the user for whom a chat box
  7268. * gets created.
  7269. * (Object) attrs - Optional chat box atributes.
  7270. */
  7271. var bare_jid = Strophe.getBareJidFromJid(jid),
  7272. roster_item = _converse.roster.get(bare_jid);
  7273. var roster_info = {};
  7274. if (!_.isUndefined(roster_item)) {
  7275. roster_info = {
  7276. 'fullname': _.isEmpty(roster_item.get('fullname')) ? jid : roster_item.get('fullname'),
  7277. 'image_type': roster_item.get('image_type'),
  7278. 'image': roster_item.get('image'),
  7279. 'url': roster_item.get('url')
  7280. };
  7281. } else if (!_converse.allow_non_roster_messaging) {
  7282. _converse.log("Could not get roster item for JID " + bare_jid + ' and allow_non_roster_messaging is set to false', Strophe.LogLevel.ERROR);
  7283. return;
  7284. }
  7285. return this.create(_.assignIn({
  7286. 'id': bare_jid,
  7287. 'jid': bare_jid,
  7288. 'fullname': jid,
  7289. 'image_type': DEFAULT_IMAGE_TYPE,
  7290. 'image': DEFAULT_IMAGE,
  7291. 'url': ''
  7292. }, roster_info, attrs || {}));
  7293. },
  7294. getChatBox: function getChatBox(jid, create, attrs) {
  7295. /* Returns a chat box or optionally return a newly
  7296. * created one if one doesn't exist.
  7297. *
  7298. * Parameters:
  7299. * (String) jid - The JID of the user whose chat box we want
  7300. * (Boolean) create - Should a new chat box be created if none exists?
  7301. * (Object) attrs - Optional chat box atributes.
  7302. */
  7303. jid = jid.toLowerCase();
  7304. var chatbox = this.get(Strophe.getBareJidFromJid(jid));
  7305. if (!chatbox && create) {
  7306. chatbox = this.createChatBox(jid, attrs);
  7307. }
  7308. return chatbox;
  7309. }
  7310. });
  7311. this.ChatBoxViews = Backbone.Overview.extend({
  7312. initialize: function initialize() {
  7313. this.model.on("add", this.onChatBoxAdded, this);
  7314. this.model.on("destroy", this.removeChat, this);
  7315. },
  7316. _ensureElement: function _ensureElement() {
  7317. /* Override method from backbone.js
  7318. * If the #conversejs element doesn't exist, create it.
  7319. */
  7320. if (!this.el) {
  7321. var el = document.querySelector('#conversejs');
  7322. if (_.isNull(el)) {
  7323. el = document.createElement('div');
  7324. el.setAttribute('id', 'conversejs');
  7325. // Converse.js expects a <body> tag to be present.
  7326. document.querySelector('body').appendChild(el);
  7327. }
  7328. el.innerHTML = '';
  7329. this.setElement(el, false);
  7330. } else {
  7331. this.setElement(_.result(this, 'el'), false);
  7332. }
  7333. },
  7334. onChatBoxAdded: function onChatBoxAdded(item) {
  7335. // Views aren't created here, since the core code doesn't
  7336. // contain any views. Instead, they're created in overrides in
  7337. // plugins, such as in converse-chatview.js and converse-muc.js
  7338. return this.get(item.get('id'));
  7339. },
  7340. removeChat: function removeChat(item) {
  7341. this.remove(item.get('id'));
  7342. },
  7343. closeAllChatBoxes: function closeAllChatBoxes() {
  7344. /* This method gets overridden in src/converse-controlbox.js if
  7345. * the controlbox plugin is active.
  7346. */
  7347. this.each(function (view) {
  7348. view.close();
  7349. });
  7350. return this;
  7351. },
  7352. chatBoxMayBeShown: function chatBoxMayBeShown(chatbox) {
  7353. return this.model.chatBoxMayBeShown(chatbox);
  7354. },
  7355. getChatBox: function getChatBox(attrs, create) {
  7356. var chatbox = this.model.get(attrs.jid);
  7357. if (!chatbox && create) {
  7358. chatbox = this.model.create(attrs, {
  7359. 'error': function error(model, response) {
  7360. _converse.log(response.responseText);
  7361. }
  7362. });
  7363. }
  7364. return chatbox;
  7365. },
  7366. showChat: function showChat(attrs) {
  7367. /* Find the chat box and show it (if it may be shown).
  7368. * If it doesn't exist, create it.
  7369. */
  7370. var chatbox = this.getChatBox(attrs, true);
  7371. if (this.chatBoxMayBeShown(chatbox)) {
  7372. chatbox.trigger('show', true);
  7373. }
  7374. return chatbox;
  7375. }
  7376. });
  7377. this.XMPPStatus = Backbone.Model.extend({
  7378. initialize: function initialize() {
  7379. var _this9 = this;
  7380. this.set({
  7381. 'status': this.getStatus()
  7382. });
  7383. this.on('change', function (item) {
  7384. if (_.has(item.changed, 'status')) {
  7385. _converse.emit('statusChanged', _this9.get('status'));
  7386. }
  7387. if (_.has(item.changed, 'status_message')) {
  7388. _converse.emit('statusMessageChanged', _this9.get('status_message'));
  7389. }
  7390. });
  7391. },
  7392. constructPresence: function constructPresence(type, status_message) {
  7393. var presence = void 0;
  7394. type = _.isString(type) ? type : this.get('status') || _converse.default_state;
  7395. status_message = _.isString(status_message) ? status_message : undefined;
  7396. // Most of these presence types are actually not explicitly sent,
  7397. // but I add all of them here for reference and future proofing.
  7398. if (type === 'unavailable' || type === 'probe' || type === 'error' || type === 'unsubscribe' || type === 'unsubscribed' || type === 'subscribe' || type === 'subscribed') {
  7399. presence = $pres({ 'type': type });
  7400. } else if (type === 'offline') {
  7401. presence = $pres({ 'type': 'unavailable' });
  7402. } else if (type === 'online') {
  7403. presence = $pres();
  7404. } else {
  7405. presence = $pres().c('show').t(type).up();
  7406. }
  7407. if (status_message) {
  7408. presence.c('status').t(status_message).up();
  7409. }
  7410. presence.c('priority').t(_.isNaN(Number(_converse.priority)) ? 0 : _converse.priority);
  7411. return presence;
  7412. },
  7413. sendPresence: function sendPresence(type, status_message) {
  7414. _converse.connection.send(this.constructPresence(type, status_message));
  7415. },
  7416. setStatus: function setStatus(value) {
  7417. this.sendPresence(value);
  7418. this.save({ 'status': value });
  7419. },
  7420. getStatus: function getStatus() {
  7421. return this.get('status') || _converse.default_state;
  7422. },
  7423. setStatusMessage: function setStatusMessage(status_message) {
  7424. this.sendPresence(this.getStatus(), status_message);
  7425. this.save({ 'status_message': status_message });
  7426. if (this.xhr_custom_status) {
  7427. var xhr = new XMLHttpRequest();
  7428. xhr.open('POST', this.xhr_custom_status_url, true);
  7429. xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
  7430. xhr.send({ 'msg': status_message });
  7431. }
  7432. var prev_status = this.get('status_message');
  7433. if (prev_status === status_message) {
  7434. this.trigger("update-status-ui", this);
  7435. }
  7436. }
  7437. });
  7438. this.setUpXMLLogging = function () {
  7439. Strophe.log = function (level, msg) {
  7440. _converse.log(msg, level);
  7441. };
  7442. if (this.debug) {
  7443. this.connection.xmlInput = function (body) {
  7444. _converse.log(body.outerHTML, Strophe.LogLevel.DEBUG);
  7445. };
  7446. this.connection.xmlOutput = function (body) {
  7447. _converse.log(body.outerHTML, Strophe.LogLevel.DEBUG);
  7448. };
  7449. }
  7450. };
  7451. this.fetchLoginCredentials = function () {
  7452. return new Promise(function (resolve, reject) {
  7453. var xhr = new XMLHttpRequest();
  7454. xhr.open('GET', _converse.credentials_url, true);
  7455. xhr.setRequestHeader('Accept', "application/json, text/javascript");
  7456. xhr.onload = function () {
  7457. if (xhr.status >= 200 && xhr.status < 400) {
  7458. var data = JSON.parse(xhr.responseText);
  7459. resolve({
  7460. 'jid': data.jid,
  7461. 'password': data.password
  7462. });
  7463. } else {
  7464. xhr.onerror();
  7465. }
  7466. };
  7467. xhr.onerror = function () {
  7468. delete _converse.connection;
  7469. _converse.emit('noResumeableSession');
  7470. reject(xhr.responseText);
  7471. };
  7472. xhr.send();
  7473. });
  7474. };
  7475. this.startNewBOSHSession = function () {
  7476. var xhr = new XMLHttpRequest();
  7477. xhr.open('GET', _converse.prebind_url, true);
  7478. xhr.setRequestHeader('Accept', "application/json, text/javascript");
  7479. xhr.onload = function () {
  7480. if (xhr.status >= 200 && xhr.status < 400) {
  7481. var data = JSON.parse(xhr.responseText);
  7482. _converse.connection.attach(data.jid, data.sid, data.rid, _converse.onConnectStatusChanged);
  7483. } else {
  7484. xhr.onerror();
  7485. }
  7486. };
  7487. xhr.onerror = function () {
  7488. delete _converse.connection;
  7489. _converse.emit('noResumeableSession');
  7490. };
  7491. xhr.send();
  7492. };
  7493. this.restoreBOSHSession = function (jid_is_required) {
  7494. /* Tries to restore a cached BOSH session. */
  7495. if (!this.jid) {
  7496. var msg = "restoreBOSHSession: tried to restore a \"keepalive\" session " + "but we don't have the JID for the user!";
  7497. if (jid_is_required) {
  7498. throw new Error(msg);
  7499. } else {
  7500. _converse.log(msg);
  7501. }
  7502. }
  7503. try {
  7504. this.connection.restore(this.jid, this.onConnectStatusChanged);
  7505. return true;
  7506. } catch (e) {
  7507. this.log("Could not restore session for jid: " + this.jid + " Error message: " + e.message);
  7508. this.clearSession(); // If there's a roster, we want to clear it (see #555)
  7509. return false;
  7510. }
  7511. };
  7512. this.attemptPreboundSession = function (reconnecting) {
  7513. /* Handle session resumption or initialization when prebind is
  7514. * being used.
  7515. */
  7516. if (!reconnecting) {
  7517. if (this.keepalive && this.restoreBOSHSession(true)) {
  7518. return;
  7519. }
  7520. // No keepalive, or session resumption has failed.
  7521. if (this.jid && this.sid && this.rid) {
  7522. return this.connection.attach(this.jid, this.sid, this.rid, this.onConnectStatusChanged);
  7523. }
  7524. }
  7525. if (this.prebind_url) {
  7526. return this.startNewBOSHSession();
  7527. } else {
  7528. throw new Error("attemptPreboundSession: If you use prebind and not keepalive, " + "then you MUST supply JID, RID and SID values or a prebind_url.");
  7529. }
  7530. };
  7531. this.attemptNonPreboundSession = function (credentials, reconnecting) {
  7532. /* Handle session resumption or initialization when prebind is not being used.
  7533. *
  7534. * Two potential options exist and are handled in this method:
  7535. * 1. keepalive
  7536. * 2. auto_login
  7537. */
  7538. if (!reconnecting && this.keepalive && this.restoreBOSHSession()) {
  7539. return;
  7540. }
  7541. if (this.auto_login) {
  7542. if (credentials) {
  7543. // When credentials are passed in, they override prebinding
  7544. // or credentials fetching via HTTP
  7545. this.autoLogin(credentials);
  7546. } else if (this.credentials_url) {
  7547. this.fetchLoginCredentials().then(this.autoLogin.bind(this), this.autoLogin.bind(this));
  7548. } else if (!this.jid) {
  7549. throw new Error("attemptNonPreboundSession: If you use auto_login, " + "you also need to give either a jid value (and if " + "applicable a password) or you need to pass in a URL " + "from where the username and password can be fetched " + "(via credentials_url).");
  7550. } else {
  7551. this.autoLogin(); // Probably ANONYMOUS login
  7552. }
  7553. } else if (reconnecting) {
  7554. this.autoLogin();
  7555. }
  7556. };
  7557. this.autoLogin = function (credentials) {
  7558. if (credentials) {
  7559. // If passed in, the credentials come from credentials_url,
  7560. // so we set them on the converse object.
  7561. this.jid = credentials.jid;
  7562. }
  7563. if (this.authentication === _converse.ANONYMOUS) {
  7564. if (!this.jid) {
  7565. throw new Error("Config Error: when using anonymous login " + "you need to provide the server's domain via the 'jid' option. " + "Either when calling converse.initialize, or when calling " + "_converse.api.user.login.");
  7566. }
  7567. if (!this.connection.reconnecting) {
  7568. this.connection.reset();
  7569. }
  7570. this.connection.connect(this.jid.toLowerCase(), null, this.onConnectStatusChanged);
  7571. } else if (this.authentication === _converse.LOGIN) {
  7572. var password = _.isNil(credentials) ? _converse.connection.pass || this.password : credentials.password;
  7573. if (!password) {
  7574. if (this.auto_login) {
  7575. throw new Error("initConnection: If you use auto_login and " + "authentication='login' then you also need to provide a password.");
  7576. }
  7577. _converse.setDisconnectionCause(Strophe.Status.AUTHFAIL, undefined, true);
  7578. _converse.disconnect();
  7579. return;
  7580. }
  7581. var resource = Strophe.getResourceFromJid(this.jid);
  7582. if (!resource) {
  7583. this.jid = this.jid.toLowerCase() + _converse.generateResource();
  7584. } else {
  7585. this.jid = Strophe.getBareJidFromJid(this.jid).toLowerCase() + '/' + resource;
  7586. }
  7587. if (!this.connection.reconnecting) {
  7588. this.connection.reset();
  7589. }
  7590. this.connection.connect(this.jid, password, this.onConnectStatusChanged);
  7591. }
  7592. };
  7593. this.logIn = function (credentials, reconnecting) {
  7594. // We now try to resume or automatically set up a new session.
  7595. // Otherwise the user will be shown a login form.
  7596. if (this.authentication === _converse.PREBIND) {
  7597. this.attemptPreboundSession(reconnecting);
  7598. } else {
  7599. this.attemptNonPreboundSession(credentials, reconnecting);
  7600. }
  7601. };
  7602. this.initConnection = function () {
  7603. if (this.connection) {
  7604. return;
  7605. }
  7606. if (!this.bosh_service_url && !this.websocket_url) {
  7607. throw new Error("initConnection: you must supply a value for either the bosh_service_url or websocket_url or both.");
  7608. }
  7609. if (('WebSocket' in window || 'MozWebSocket' in window) && this.websocket_url) {
  7610. this.connection = new Strophe.Connection(this.websocket_url, this.connection_options);
  7611. } else if (this.bosh_service_url) {
  7612. this.connection = new Strophe.Connection(this.bosh_service_url, _.assignIn(this.connection_options, { 'keepalive': this.keepalive }));
  7613. } else {
  7614. throw new Error("initConnection: this browser does not support websockets and bosh_service_url wasn't specified.");
  7615. }
  7616. };
  7617. this._tearDown = function () {
  7618. /* Remove those views which are only allowed with a valid
  7619. * connection.
  7620. */
  7621. _converse.emit('beforeTearDown');
  7622. this.unregisterPresenceHandler();
  7623. if (this.roster) {
  7624. this.roster.off().reset(); // Removes roster contacts
  7625. }
  7626. this.chatboxes.remove(); // Don't call off(), events won't get re-registered upon reconnect.
  7627. delete this.chatboxes.browserStorage;
  7628. this.session.destroy();
  7629. window.removeEventListener('click', _converse.onUserActivity);
  7630. window.removeEventListener('focus', _converse.onUserActivity);
  7631. window.removeEventListener('keypress', _converse.onUserActivity);
  7632. window.removeEventListener('mousemove', _converse.onUserActivity);
  7633. window.removeEventListener(unloadevent, _converse.onUserActivity);
  7634. window.clearInterval(_converse.everySecondTrigger);
  7635. _converse.emit('afterTearDown');
  7636. return this;
  7637. };
  7638. this.initChatBoxes = function () {
  7639. this.chatboxes = new this.ChatBoxes();
  7640. this.chatboxviews = new this.ChatBoxViews({ model: this.chatboxes });
  7641. };
  7642. this.initPlugins = function () {
  7643. // If initialize gets called a second time (e.g. during tests), then we
  7644. // need to re-apply all plugins (for a new converse instance), and we
  7645. // therefore need to clear this array that prevents plugins from being
  7646. // initialized twice.
  7647. // If initialize is called for the first time, then this array is empty
  7648. // in any case.
  7649. _converse.pluggable.initialized_plugins = [];
  7650. var whitelist = _converse.core_plugins.concat(_converse.whitelisted_plugins);
  7651. _converse.pluggable.initializePlugins({
  7652. 'updateSettings': function updateSettings() {
  7653. _converse.log("(DEPRECATION) " + "The `updateSettings` method has been deprecated. " + "Please use `_converse.api.settings.update` instead.", Strophe.LogLevel.WARN);
  7654. _converse.api.settings.update.apply(_converse, arguments);
  7655. },
  7656. '_converse': _converse
  7657. }, whitelist, _converse.blacklisted_plugins);
  7658. _converse.emit('pluginsInitialized');
  7659. };
  7660. // Initialization
  7661. // --------------
  7662. // This is the end of the initialize method.
  7663. if (settings.connection) {
  7664. this.connection = settings.connection;
  7665. }
  7666. _converse.initPlugins();
  7667. _converse.initChatBoxes();
  7668. _converse.initConnection();
  7669. _converse.setUpXMLLogging();
  7670. _converse.logIn();
  7671. _converse.registerGlobalEventHandlers();
  7672. if (!_.isUndefined(_converse.connection) && _converse.connection.service === 'jasmine tests') {
  7673. return _converse;
  7674. } else {
  7675. return init_promise.promise;
  7676. }
  7677. };
  7678. // API methods only available to plugins
  7679. _converse.api = {
  7680. 'connection': {
  7681. 'connected': function connected() {
  7682. return _converse.connection && _converse.connection.connected || false;
  7683. },
  7684. 'disconnect': function disconnect() {
  7685. _converse.connection.disconnect();
  7686. }
  7687. },
  7688. 'emit': function emit() {
  7689. _converse.emit.apply(_converse, arguments);
  7690. },
  7691. 'user': {
  7692. 'jid': function jid() {
  7693. return _converse.connection.jid;
  7694. },
  7695. 'login': function login(credentials) {
  7696. _converse.initConnection();
  7697. _converse.logIn(credentials);
  7698. },
  7699. 'logout': function logout() {
  7700. _converse.logOut();
  7701. },
  7702. 'status': {
  7703. 'get': function get() {
  7704. return _converse.xmppstatus.get('status');
  7705. },
  7706. 'set': function set(value, message) {
  7707. var data = { 'status': value };
  7708. if (!_.includes(_.keys(_converse.STATUS_WEIGHTS), value)) {
  7709. throw new Error('Invalid availability value. See https://xmpp.org/rfcs/rfc3921.html#rfc.section.2.2.2.1');
  7710. }
  7711. if (_.isString(message)) {
  7712. data.status_message = message;
  7713. }
  7714. _converse.xmppstatus.sendPresence(value);
  7715. _converse.xmppstatus.save(data);
  7716. },
  7717. 'message': {
  7718. 'get': function get() {
  7719. return _converse.xmppstatus.get('status_message');
  7720. },
  7721. 'set': function set(stat) {
  7722. _converse.xmppstatus.save({ 'status_message': stat });
  7723. }
  7724. }
  7725. }
  7726. },
  7727. 'settings': {
  7728. 'update': function update(settings) {
  7729. utils.merge(_converse.default_settings, settings);
  7730. utils.merge(_converse, settings);
  7731. utils.applyUserSettings(_converse, settings, _converse.user_settings);
  7732. },
  7733. 'get': function get(key) {
  7734. if (_.includes(_.keys(_converse.default_settings), key)) {
  7735. return _converse[key];
  7736. }
  7737. },
  7738. 'set': function set(key, val) {
  7739. var o = {};
  7740. if (_.isObject(key)) {
  7741. _.assignIn(_converse, _.pick(key, _.keys(_converse.default_settings)));
  7742. } else if (_.isString("string")) {
  7743. o[key] = val;
  7744. _.assignIn(_converse, _.pick(o, _.keys(_converse.default_settings)));
  7745. }
  7746. }
  7747. },
  7748. 'promises': {
  7749. 'add': function add(promises) {
  7750. promises = _.isArray(promises) ? promises : [promises];
  7751. _.each(promises, addPromise);
  7752. }
  7753. },
  7754. 'contacts': {
  7755. 'get': function get(jids) {
  7756. var _transform = function _transform(jid) {
  7757. var contact = _converse.roster.get(Strophe.getBareJidFromJid(jid));
  7758. if (contact) {
  7759. return contact.attributes;
  7760. }
  7761. return null;
  7762. };
  7763. if (_.isUndefined(jids)) {
  7764. jids = _converse.roster.pluck('jid');
  7765. } else if (_.isString(jids)) {
  7766. return _transform(jids);
  7767. }
  7768. return _.map(jids, _transform);
  7769. },
  7770. 'add': function add(jid, name) {
  7771. if (!_.isString(jid) || !_.includes(jid, '@')) {
  7772. throw new TypeError('contacts.add: invalid jid');
  7773. }
  7774. _converse.roster.addAndSubscribe(jid, _.isEmpty(name) ? jid : name);
  7775. }
  7776. },
  7777. 'chats': {
  7778. 'open': function open(jids, attrs) {
  7779. if (_.isUndefined(jids)) {
  7780. _converse.log("chats.open: You need to provide at least one JID", Strophe.LogLevel.ERROR);
  7781. return null;
  7782. } else if (_.isString(jids)) {
  7783. return _converse.getViewForChatBox(_converse.chatboxes.getChatBox(jids, true, attrs).trigger('show'));
  7784. }
  7785. return _.map(jids, function (jid) {
  7786. return _converse.getViewForChatBox(_converse.chatboxes.getChatBox(jid, true, attrs).trigger('show'));
  7787. });
  7788. },
  7789. 'get': function get(jids) {
  7790. if (_.isUndefined(jids)) {
  7791. var result = [];
  7792. _converse.chatboxes.each(function (chatbox) {
  7793. // FIXME: Leaky abstraction from MUC. We need to add a
  7794. // base type for chat boxes, and check for that.
  7795. if (chatbox.get('type') !== 'chatroom') {
  7796. result.push(_converse.getViewForChatBox(chatbox));
  7797. }
  7798. });
  7799. return result;
  7800. } else if (_.isString(jids)) {
  7801. return _converse.getViewForChatBox(_converse.chatboxes.getChatBox(jids));
  7802. }
  7803. return _.map(jids, _.partial(_.flow(_converse.chatboxes.getChatBox.bind(_converse.chatboxes), _converse.getViewForChatBox.bind(_converse)), _, true));
  7804. }
  7805. },
  7806. 'tokens': {
  7807. 'get': function get(id) {
  7808. if (!_converse.expose_rid_and_sid || _.isUndefined(_converse.connection)) {
  7809. return null;
  7810. }
  7811. if (id.toLowerCase() === 'rid') {
  7812. return _converse.connection.rid || _converse.connection._proto.rid;
  7813. } else if (id.toLowerCase() === 'sid') {
  7814. return _converse.connection.sid || _converse.connection._proto.sid;
  7815. }
  7816. }
  7817. },
  7818. 'listen': {
  7819. 'once': _converse.once.bind(_converse),
  7820. 'on': _converse.on.bind(_converse),
  7821. 'not': _converse.off.bind(_converse),
  7822. 'stanza': function stanza(name, options, handler) {
  7823. if (_.isFunction(options)) {
  7824. handler = options;
  7825. options = {};
  7826. } else {
  7827. options = options || {};
  7828. }
  7829. _converse.connection.addHandler(handler, options.ns, name, options.type, options.id, options.from, options);
  7830. }
  7831. },
  7832. 'waitUntil': function waitUntil(name) {
  7833. var promise = _converse.promises[name];
  7834. if (_.isUndefined(promise)) {
  7835. return null;
  7836. }
  7837. return promise.promise;
  7838. },
  7839. 'send': function send(stanza) {
  7840. _converse.connection.send(stanza);
  7841. }
  7842. };
  7843. // The public API
  7844. return {
  7845. 'initialize': function initialize(settings, callback) {
  7846. return _converse.initialize(settings, callback);
  7847. },
  7848. 'plugins': {
  7849. 'add': function add(name, plugin) {
  7850. plugin.__name__ = name;
  7851. if (!_.isUndefined(_converse.pluggable.plugins[name])) {
  7852. throw new TypeError("Error: plugin with name \"" + name + "\" has already been " + 'registered!');
  7853. } else {
  7854. _converse.pluggable.plugins[name] = plugin;
  7855. }
  7856. }
  7857. },
  7858. 'env': {
  7859. '$build': $build,
  7860. '$iq': $iq,
  7861. '$msg': $msg,
  7862. '$pres': $pres,
  7863. 'Backbone': Backbone,
  7864. 'Promise': Promise,
  7865. 'Strophe': Strophe,
  7866. '_': _,
  7867. 'b64_sha1': b64_sha1,
  7868. 'fp': fp,
  7869. 'moment': moment,
  7870. 'sizzle': sizzle,
  7871. 'utils': utils
  7872. }
  7873. };
  7874. });
  7875. //# sourceMappingURL=converse-core.js.map;
  7876. /* jshint maxerr: 10000 */
  7877. /* jslint unused: true */
  7878. /* jshint shadow: true */
  7879. /* jshint -W075 */
  7880. (function(ns){
  7881. // this list must be ordered from largest length of the value array, index 0, to the shortest
  7882. ns.emojioneList = {":kiss_mm:":{"uc_base":"1f468-2764-1f48b-1f468","uc_output":"1f468-200d-2764-fe0f-200d-1f48b-200d-1f468","uc_match":"1f468-2764-fe0f-1f48b-1f468","uc_greedy":"1f468-2764-1f48b-1f468","shortnames":[":couplekiss_mm:"],"category":"people"},":kiss_woman_man:":{"uc_base":"1f469-2764-1f48b-1f468","uc_output":"1f469-200d-2764-fe0f-200d-1f48b-200d-1f468","uc_match":"1f469-2764-fe0f-1f48b-1f468","uc_greedy":"1f469-2764-1f48b-1f468","shortnames":[],"category":"people"},":kiss_ww:":{"uc_base":"1f469-2764-1f48b-1f469","uc_output":"1f469-200d-2764-fe0f-200d-1f48b-200d-1f469","uc_match":"1f469-2764-fe0f-1f48b-1f469","uc_greedy":"1f469-2764-1f48b-1f469","shortnames":[":couplekiss_ww:"],"category":"people"},":england:":{"uc_base":"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f","uc_output":"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f","uc_match":"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f","uc_greedy":"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f","shortnames":[],"category":"flags"},":scotland:":{"uc_base":"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f","uc_output":"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f","uc_match":"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f","uc_greedy":"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f","shortnames":[],"category":"flags"},":wales:":{"uc_base":"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f","uc_output":"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f","uc_match":"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f","uc_greedy":"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f","shortnames":[],"category":"flags"},":family_mmbb:":{"uc_base":"1f468-1f468-1f466-1f466","uc_output":"1f468-200d-1f468-200d-1f466-200d-1f466","uc_match":"1f468-1f468-1f466-1f466","uc_greedy":"1f468-1f468-1f466-1f466","shortnames":[],"category":"people"},":family_mmgb:":{"uc_base":"1f468-1f468-1f467-1f466","uc_output":"1f468-200d-1f468-200d-1f467-200d-1f466","uc_match":"1f468-1f468-1f467-1f466","uc_greedy":"1f468-1f468-1f467-1f466","shortnames":[],"category":"people"},":family_mmgg:":{"uc_base":"1f468-1f468-1f467-1f467","uc_output":"1f468-200d-1f468-200d-1f467-200d-1f467","uc_match":"1f468-1f468-1f467-1f467","uc_greedy":"1f468-1f468-1f467-1f467","shortnames":[],"category":"people"},":family_mwbb:":{"uc_base":"1f468-1f469-1f466-1f466","uc_output":"1f468-200d-1f469-200d-1f466-200d-1f466","uc_match":"1f468-1f469-1f466-1f466","uc_greedy":"1f468-1f469-1f466-1f466","shortnames":[],"category":"people"},":family_mwgb:":{"uc_base":"1f468-1f469-1f467-1f466","uc_output":"1f468-200d-1f469-200d-1f467-200d-1f466","uc_match":"1f468-1f469-1f467-1f466","uc_greedy":"1f468-1f469-1f467-1f466","shortnames":[],"category":"people"},":family_mwgg:":{"uc_base":"1f468-1f469-1f467-1f467","uc_output":"1f468-200d-1f469-200d-1f467-200d-1f467","uc_match":"1f468-1f469-1f467-1f467","uc_greedy":"1f468-1f469-1f467-1f467","shortnames":[],"category":"people"},":family_wwbb:":{"uc_base":"1f469-1f469-1f466-1f466","uc_output":"1f469-200d-1f469-200d-1f466-200d-1f466","uc_match":"1f469-1f469-1f466-1f466","uc_greedy":"1f469-1f469-1f466-1f466","shortnames":[],"category":"people"},":family_wwgb:":{"uc_base":"1f469-1f469-1f467-1f466","uc_output":"1f469-200d-1f469-200d-1f467-200d-1f466","uc_match":"1f469-1f469-1f467-1f466","uc_greedy":"1f469-1f469-1f467-1f466","shortnames":[],"category":"people"},":family_wwgg:":{"uc_base":"1f469-1f469-1f467-1f467","uc_output":"1f469-200d-1f469-200d-1f467-200d-1f467","uc_match":"1f469-1f469-1f467-1f467","uc_greedy":"1f469-1f469-1f467-1f467","shortnames":[],"category":"people"},":couple_mm:":{"uc_base":"1f468-2764-1f468","uc_output":"1f468-200d-2764-fe0f-200d-1f468","uc_match":"1f468-2764-fe0f-1f468","uc_greedy":"1f468-2764-1f468","shortnames":[":couple_with_heart_mm:"],"category":"people"},":couple_with_heart_woman_man:":{"uc_base":"1f469-2764-1f468","uc_output":"1f469-200d-2764-fe0f-200d-1f468","uc_match":"1f469-2764-fe0f-1f468","uc_greedy":"1f469-2764-1f468","shortnames":[],"category":"people"},":couple_ww:":{"uc_base":"1f469-2764-1f469","uc_output":"1f469-200d-2764-fe0f-200d-1f469","uc_match":"1f469-2764-fe0f-1f469","uc_greedy":"1f469-2764-1f469","shortnames":[":couple_with_heart_ww:"],"category":"people"},":family_man_boy_boy:":{"uc_base":"1f468-1f466-1f466","uc_output":"1f468-200d-1f466-200d-1f466","uc_match":"1f468-1f466-1f466","uc_greedy":"1f468-1f466-1f466","shortnames":[],"category":"people"},":family_man_girl_boy:":{"uc_base":"1f468-1f467-1f466","uc_output":"1f468-200d-1f467-200d-1f466","uc_match":"1f468-1f467-1f466","uc_greedy":"1f468-1f467-1f466","shortnames":[],"category":"people"},":family_man_girl_girl:":{"uc_base":"1f468-1f467-1f467","uc_output":"1f468-200d-1f467-200d-1f467","uc_match":"1f468-1f467-1f467","uc_greedy":"1f468-1f467-1f467","shortnames":[],"category":"people"},":family_man_woman_boy:":{"uc_base":"1f468-1f469-1f466","uc_output":"1f468-200d-1f469-200d-1f466","uc_match":"1f468-1f469-1f466","uc_greedy":"1f468-1f469-1f466","shortnames":[],"category":"people"},":family_mmb:":{"uc_base":"1f468-1f468-1f466","uc_output":"1f468-200d-1f468-200d-1f466","uc_match":"1f468-1f468-1f466","uc_greedy":"1f468-1f468-1f466","shortnames":[],"category":"people"},":family_mmg:":{"uc_base":"1f468-1f468-1f467","uc_output":"1f468-200d-1f468-200d-1f467","uc_match":"1f468-1f468-1f467","uc_greedy":"1f468-1f468-1f467","shortnames":[],"category":"people"},":family_mwg:":{"uc_base":"1f468-1f469-1f467","uc_output":"1f468-200d-1f469-200d-1f467","uc_match":"1f468-1f469-1f467","uc_greedy":"1f468-1f469-1f467","shortnames":[],"category":"people"},":family_woman_boy_boy:":{"uc_base":"1f469-1f466-1f466","uc_output":"1f469-200d-1f466-200d-1f466","uc_match":"1f469-1f466-1f466","uc_greedy":"1f469-1f466-1f466","shortnames":[],"category":"people"},":family_woman_girl_boy:":{"uc_base":"1f469-1f467-1f466","uc_output":"1f469-200d-1f467-200d-1f466","uc_match":"1f469-1f467-1f466","uc_greedy":"1f469-1f467-1f466","shortnames":[],"category":"people"},":family_woman_girl_girl:":{"uc_base":"1f469-1f467-1f467","uc_output":"1f469-200d-1f467-200d-1f467","uc_match":"1f469-1f467-1f467","uc_greedy":"1f469-1f467-1f467","shortnames":[],"category":"people"},":family_wwb:":{"uc_base":"1f469-1f469-1f466","uc_output":"1f469-200d-1f469-200d-1f466","uc_match":"1f469-1f469-1f466","uc_greedy":"1f469-1f469-1f466","shortnames":[],"category":"people"},":family_wwg:":{"uc_base":"1f469-1f469-1f467","uc_output":"1f469-200d-1f469-200d-1f467","uc_match":"1f469-1f469-1f467","uc_greedy":"1f469-1f469-1f467","shortnames":[],"category":"people"},":blond-haired_man_tone1:":{"uc_base":"1f471-1f3fb-2642","uc_output":"1f471-1f3fb-200d-2642-fe0f","uc_match":"1f471-1f3fb-2642-fe0f","uc_greedy":"1f471-1f3fb-2642","shortnames":[":blond-haired_man_light_skin_tone:"],"category":"people"},":blond-haired_man_tone2:":{"uc_base":"1f471-1f3fc-2642","uc_output":"1f471-1f3fc-200d-2642-fe0f","uc_match":"1f471-1f3fc-2642-fe0f","uc_greedy":"1f471-1f3fc-2642","shortnames":[":blond-haired_man_medium_light_skin_tone:"],"category":"people"},":blond-haired_man_tone3:":{"uc_base":"1f471-1f3fd-2642","uc_output":"1f471-1f3fd-200d-2642-fe0f","uc_match":"1f471-1f3fd-2642-fe0f","uc_greedy":"1f471-1f3fd-2642","shortnames":[":blond-haired_man_medium_skin_tone:"],"category":"people"},":blond-haired_man_tone4:":{"uc_base":"1f471-1f3fe-2642","uc_output":"1f471-1f3fe-200d-2642-fe0f","uc_match":"1f471-1f3fe-2642-fe0f","uc_greedy":"1f471-1f3fe-2642","shortnames":[":blond-haired_man_medium_dark_skin_tone:"],"category":"people"},":blond-haired_man_tone5:":{"uc_base":"1f471-1f3ff-2642","uc_output":"1f471-1f3ff-200d-2642-fe0f","uc_match":"1f471-1f3ff-2642-fe0f","uc_greedy":"1f471-1f3ff-2642","shortnames":[":blond-haired_man_dark_skin_tone:"],"category":"people"},":blond-haired_woman_tone1:":{"uc_base":"1f471-1f3fb-2640","uc_output":"1f471-1f3fb-200d-2640-fe0f","uc_match":"1f471-1f3fb-2640-fe0f","uc_greedy":"1f471-1f3fb-2640","shortnames":[":blond-haired_woman_light_skin_tone:"],"category":"people"},":blond-haired_woman_tone2:":{"uc_base":"1f471-1f3fc-2640","uc_output":"1f471-1f3fc-200d-2640-fe0f","uc_match":"1f471-1f3fc-2640-fe0f","uc_greedy":"1f471-1f3fc-2640","shortnames":[":blond-haired_woman_medium_light_skin_tone:"],"category":"people"},":blond-haired_woman_tone3:":{"uc_base":"1f471-1f3fd-2640","uc_output":"1f471-1f3fd-200d-2640-fe0f","uc_match":"1f471-1f3fd-2640-fe0f","uc_greedy":"1f471-1f3fd-2640","shortnames":[":blond-haired_woman_medium_skin_tone:"],"category":"people"},":blond-haired_woman_tone4:":{"uc_base":"1f471-1f3fe-2640","uc_output":"1f471-1f3fe-200d-2640-fe0f","uc_match":"1f471-1f3fe-2640-fe0f","uc_greedy":"1f471-1f3fe-2640","shortnames":[":blond-haired_woman_medium_dark_skin_tone:"],"category":"people"},":blond-haired_woman_tone5:":{"uc_base":"1f471-1f3ff-2640","uc_output":"1f471-1f3ff-200d-2640-fe0f","uc_match":"1f471-1f3ff-2640-fe0f","uc_greedy":"1f471-1f3ff-2640","shortnames":[":blond-haired_woman_dark_skin_tone:"],"category":"people"},":eye_in_speech_bubble:":{"uc_base":"1f441-1f5e8","uc_output":"1f441-fe0f-200d-1f5e8-fe0f","uc_match":"1f441-fe0f-1f5e8-fe0f","uc_greedy":"1f441-1f5e8","shortnames":[],"category":"symbols"},":man_biking_tone1:":{"uc_base":"1f6b4-1f3fb-2642","uc_output":"1f6b4-1f3fb-200d-2642-fe0f","uc_match":"1f6b4-1f3fb-2642-fe0f","uc_greedy":"1f6b4-1f3fb-2642","shortnames":[":man_biking_light_skin_tone:"],"category":"activity"},":man_biking_tone2:":{"uc_base":"1f6b4-1f3fc-2642","uc_output":"1f6b4-1f3fc-200d-2642-fe0f","uc_match":"1f6b4-1f3fc-2642-fe0f","uc_greedy":"1f6b4-1f3fc-2642","shortnames":[":man_biking_medium_light_skin_tone:"],"category":"activity"},":man_biking_tone3:":{"uc_base":"1f6b4-1f3fd-2642","uc_output":"1f6b4-1f3fd-200d-2642-fe0f","uc_match":"1f6b4-1f3fd-2642-fe0f","uc_greedy":"1f6b4-1f3fd-2642","shortnames":[":man_biking_medium_skin_tone:"],"category":"activity"},":man_biking_tone4:":{"uc_base":"1f6b4-1f3fe-2642","uc_output":"1f6b4-1f3fe-200d-2642-fe0f","uc_match":"1f6b4-1f3fe-2642-fe0f","uc_greedy":"1f6b4-1f3fe-2642","shortnames":[":man_biking_medium_dark_skin_tone:"],"category":"activity"},":man_biking_tone5:":{"uc_base":"1f6b4-1f3ff-2642","uc_output":"1f6b4-1f3ff-200d-2642-fe0f","uc_match":"1f6b4-1f3ff-2642-fe0f","uc_greedy":"1f6b4-1f3ff-2642","shortnames":[":man_biking_dark_skin_tone:"],"category":"activity"},":man_bowing_tone1:":{"uc_base":"1f647-1f3fb-2642","uc_output":"1f647-1f3fb-200d-2642-fe0f","uc_match":"1f647-1f3fb-2642-fe0f","uc_greedy":"1f647-1f3fb-2642","shortnames":[":man_bowing_light_skin_tone:"],"category":"people"},":man_bowing_tone2:":{"uc_base":"1f647-1f3fc-2642","uc_output":"1f647-1f3fc-200d-2642-fe0f","uc_match":"1f647-1f3fc-2642-fe0f","uc_greedy":"1f647-1f3fc-2642","shortnames":[":man_bowing_medium_light_skin_tone:"],"category":"people"},":man_bowing_tone3:":{"uc_base":"1f647-1f3fd-2642","uc_output":"1f647-1f3fd-200d-2642-fe0f","uc_match":"1f647-1f3fd-2642-fe0f","uc_greedy":"1f647-1f3fd-2642","shortnames":[":man_bowing_medium_skin_tone:"],"category":"people"},":man_bowing_tone4:":{"uc_base":"1f647-1f3fe-2642","uc_output":"1f647-1f3fe-200d-2642-fe0f","uc_match":"1f647-1f3fe-2642-fe0f","uc_greedy":"1f647-1f3fe-2642","shortnames":[":man_bowing_medium_dark_skin_tone:"],"category":"people"},":man_bowing_tone5:":{"uc_base":"1f647-1f3ff-2642","uc_output":"1f647-1f3ff-200d-2642-fe0f","uc_match":"1f647-1f3ff-2642-fe0f","uc_greedy":"1f647-1f3ff-2642","shortnames":[":man_bowing_dark_skin_tone:"],"category":"people"},":man_cartwheeling_tone1:":{"uc_base":"1f938-1f3fb-2642","uc_output":"1f938-1f3fb-200d-2642-fe0f","uc_match":"1f938-1f3fb-2642-fe0f","uc_greedy":"1f938-1f3fb-2642","shortnames":[":man_cartwheeling_light_skin_tone:"],"category":"activity"},":man_cartwheeling_tone2:":{"uc_base":"1f938-1f3fc-2642","uc_output":"1f938-1f3fc-200d-2642-fe0f","uc_match":"1f938-1f3fc-2642-fe0f","uc_greedy":"1f938-1f3fc-2642","shortnames":[":man_cartwheeling_medium_light_skin_tone:"],"category":"activity"},":man_cartwheeling_tone3:":{"uc_base":"1f938-1f3fd-2642","uc_output":"1f938-1f3fd-200d-2642-fe0f","uc_match":"1f938-1f3fd-2642-fe0f","uc_greedy":"1f938-1f3fd-2642","shortnames":[":man_cartwheeling_medium_skin_tone:"],"category":"activity"},":man_cartwheeling_tone4:":{"uc_base":"1f938-1f3fe-2642","uc_output":"1f938-1f3fe-200d-2642-fe0f","uc_match":"1f938-1f3fe-2642-fe0f","uc_greedy":"1f938-1f3fe-2642","shortnames":[":man_cartwheeling_medium_dark_skin_tone:"],"category":"activity"},":man_cartwheeling_tone5:":{"uc_base":"1f938-1f3ff-2642","uc_output":"1f938-1f3ff-200d-2642-fe0f","uc_match":"1f938-1f3ff-2642-fe0f","uc_greedy":"1f938-1f3ff-2642","shortnames":[":man_cartwheeling_dark_skin_tone:"],"category":"activity"},":man_climbing_tone1:":{"uc_base":"1f9d7-1f3fb-2642","uc_output":"1f9d7-1f3fb-200d-2642-fe0f","uc_match":"1f9d7-1f3fb-2642-fe0f","uc_greedy":"1f9d7-1f3fb-2642","shortnames":[":man_climbing_light_skin_tone:"],"category":"activity"},":man_climbing_tone2:":{"uc_base":"1f9d7-1f3fc-2642","uc_output":"1f9d7-1f3fc-200d-2642-fe0f","uc_match":"1f9d7-1f3fc-2642-fe0f","uc_greedy":"1f9d7-1f3fc-2642","shortnames":[":man_climbing_medium_light_skin_tone:"],"category":"activity"},":man_climbing_tone3:":{"uc_base":"1f9d7-1f3fd-2642","uc_output":"1f9d7-1f3fd-200d-2642-fe0f","uc_match":"1f9d7-1f3fd-2642-fe0f","uc_greedy":"1f9d7-1f3fd-2642","shortnames":[":man_climbing_medium_skin_tone:"],"category":"activity"},":man_climbing_tone4:":{"uc_base":"1f9d7-1f3fe-2642","uc_output":"1f9d7-1f3fe-200d-2642-fe0f","uc_match":"1f9d7-1f3fe-2642-fe0f","uc_greedy":"1f9d7-1f3fe-2642","shortnames":[":man_climbing_medium_dark_skin_tone:"],"category":"activity"},":man_climbing_tone5:":{"uc_base":"1f9d7-1f3ff-2642","uc_output":"1f9d7-1f3ff-200d-2642-fe0f","uc_match":"1f9d7-1f3ff-2642-fe0f","uc_greedy":"1f9d7-1f3ff-2642","shortnames":[":man_climbing_dark_skin_tone:"],"category":"activity"},":man_construction_worker_tone1:":{"uc_base":"1f477-1f3fb-2642","uc_output":"1f477-1f3fb-200d-2642-fe0f","uc_match":"1f477-1f3fb-2642-fe0f","uc_greedy":"1f477-1f3fb-2642","shortnames":[":man_construction_worker_light_skin_tone:"],"category":"people"},":man_construction_worker_tone2:":{"uc_base":"1f477-1f3fc-2642","uc_output":"1f477-1f3fc-200d-2642-fe0f","uc_match":"1f477-1f3fc-2642-fe0f","uc_greedy":"1f477-1f3fc-2642","shortnames":[":man_construction_worker_medium_light_skin_tone:"],"category":"people"},":man_construction_worker_tone3:":{"uc_base":"1f477-1f3fd-2642","uc_output":"1f477-1f3fd-200d-2642-fe0f","uc_match":"1f477-1f3fd-2642-fe0f","uc_greedy":"1f477-1f3fd-2642","shortnames":[":man_construction_worker_medium_skin_tone:"],"category":"people"},":man_construction_worker_tone4:":{"uc_base":"1f477-1f3fe-2642","uc_output":"1f477-1f3fe-200d-2642-fe0f","uc_match":"1f477-1f3fe-2642-fe0f","uc_greedy":"1f477-1f3fe-2642","shortnames":[":man_construction_worker_medium_dark_skin_tone:"],"category":"people"},":man_construction_worker_tone5:":{"uc_base":"1f477-1f3ff-2642","uc_output":"1f477-1f3ff-200d-2642-fe0f","uc_match":"1f477-1f3ff-2642-fe0f","uc_greedy":"1f477-1f3ff-2642","shortnames":[":man_construction_worker_dark_skin_tone:"],"category":"people"},":man_detective_tone1:":{"uc_base":"1f575-1f3fb-2642","uc_output":"1f575-1f3fb-200d-2642-fe0f","uc_match":"1f575-fe0f-1f3fb-2642-fe0f","uc_greedy":"1f575-1f3fb-2642","shortnames":[":man_detective_light_skin_tone:"],"category":"people"},":man_detective_tone2:":{"uc_base":"1f575-1f3fc-2642","uc_output":"1f575-1f3fc-200d-2642-fe0f","uc_match":"1f575-fe0f-1f3fc-2642-fe0f","uc_greedy":"1f575-1f3fc-2642","shortnames":[":man_detective_medium_light_skin_tone:"],"category":"people"},":man_detective_tone3:":{"uc_base":"1f575-1f3fd-2642","uc_output":"1f575-1f3fd-200d-2642-fe0f","uc_match":"1f575-fe0f-1f3fd-2642-fe0f","uc_greedy":"1f575-1f3fd-2642","shortnames":[":man_detective_medium_skin_tone:"],"category":"people"},":man_detective_tone4:":{"uc_base":"1f575-1f3fe-2642","uc_output":"1f575-1f3fe-200d-2642-fe0f","uc_match":"1f575-fe0f-1f3fe-2642-fe0f","uc_greedy":"1f575-1f3fe-2642","shortnames":[":man_detective_medium_dark_skin_tone:"],"category":"people"},":man_detective_tone5:":{"uc_base":"1f575-1f3ff-2642","uc_output":"1f575-1f3ff-200d-2642-fe0f","uc_match":"1f575-fe0f-1f3ff-2642-fe0f","uc_greedy":"1f575-1f3ff-2642","shortnames":[":man_detective_dark_skin_tone:"],"category":"people"},":man_elf_tone1:":{"uc_base":"1f9dd-1f3fb-2642","uc_output":"1f9dd-1f3fb-200d-2642-fe0f","uc_match":"1f9dd-1f3fb-2642-fe0f","uc_greedy":"1f9dd-1f3fb-2642","shortnames":[":man_elf_light_skin_tone:"],"category":"people"},":man_elf_tone2:":{"uc_base":"1f9dd-1f3fc-2642","uc_output":"1f9dd-1f3fc-200d-2642-fe0f","uc_match":"1f9dd-1f3fc-2642-fe0f","uc_greedy":"1f9dd-1f3fc-2642","shortnames":[":man_elf_medium_light_skin_tone:"],"category":"people"},":man_elf_tone3:":{"uc_base":"1f9dd-1f3fd-2642","uc_output":"1f9dd-1f3fd-200d-2642-fe0f","uc_match":"1f9dd-1f3fd-2642-fe0f","uc_greedy":"1f9dd-1f3fd-2642","shortnames":[":man_elf_medium_skin_tone:"],"category":"people"},":man_elf_tone4:":{"uc_base":"1f9dd-1f3fe-2642","uc_output":"1f9dd-1f3fe-200d-2642-fe0f","uc_match":"1f9dd-1f3fe-2642-fe0f","uc_greedy":"1f9dd-1f3fe-2642","shortnames":[":man_elf_medium_dark_skin_tone:"],"category":"people"},":man_elf_tone5:":{"uc_base":"1f9dd-1f3ff-2642","uc_output":"1f9dd-1f3ff-200d-2642-fe0f","uc_match":"1f9dd-1f3ff-2642-fe0f","uc_greedy":"1f9dd-1f3ff-2642","shortnames":[":man_elf_dark_skin_tone:"],"category":"people"},":man_facepalming_tone1:":{"uc_base":"1f926-1f3fb-2642","uc_output":"1f926-1f3fb-200d-2642-fe0f","uc_match":"1f926-1f3fb-2642-fe0f","uc_greedy":"1f926-1f3fb-2642","shortnames":[":man_facepalming_light_skin_tone:"],"category":"people"},":man_facepalming_tone2:":{"uc_base":"1f926-1f3fc-2642","uc_output":"1f926-1f3fc-200d-2642-fe0f","uc_match":"1f926-1f3fc-2642-fe0f","uc_greedy":"1f926-1f3fc-2642","shortnames":[":man_facepalming_medium_light_skin_tone:"],"category":"people"},":man_facepalming_tone3:":{"uc_base":"1f926-1f3fd-2642","uc_output":"1f926-1f3fd-200d-2642-fe0f","uc_match":"1f926-1f3fd-2642-fe0f","uc_greedy":"1f926-1f3fd-2642","shortnames":[":man_facepalming_medium_skin_tone:"],"category":"people"},":man_facepalming_tone4:":{"uc_base":"1f926-1f3fe-2642","uc_output":"1f926-1f3fe-200d-2642-fe0f","uc_match":"1f926-1f3fe-2642-fe0f","uc_greedy":"1f926-1f3fe-2642","shortnames":[":man_facepalming_medium_dark_skin_tone:"],"category":"people"},":man_facepalming_tone5:":{"uc_base":"1f926-1f3ff-2642","uc_output":"1f926-1f3ff-200d-2642-fe0f","uc_match":"1f926-1f3ff-2642-fe0f","uc_greedy":"1f926-1f3ff-2642","shortnames":[":man_facepalming_dark_skin_tone:"],"category":"people"},":man_fairy_tone1:":{"uc_base":"1f9da-1f3fb-2642","uc_output":"1f9da-1f3fb-200d-2642-fe0f","uc_match":"1f9da-1f3fb-2642-fe0f","uc_greedy":"1f9da-1f3fb-2642","shortnames":[":man_fairy_light_skin_tone:"],"category":"people"},":man_fairy_tone2:":{"uc_base":"1f9da-1f3fc-2642","uc_output":"1f9da-1f3fc-200d-2642-fe0f","uc_match":"1f9da-1f3fc-2642-fe0f","uc_greedy":"1f9da-1f3fc-2642","shortnames":[":man_fairy_medium_light_skin_tone:"],"category":"people"},":man_fairy_tone3:":{"uc_base":"1f9da-1f3fd-2642","uc_output":"1f9da-1f3fd-200d-2642-fe0f","uc_match":"1f9da-1f3fd-2642-fe0f","uc_greedy":"1f9da-1f3fd-2642","shortnames":[":man_fairy_medium_skin_tone:"],"category":"people"},":man_fairy_tone4:":{"uc_base":"1f9da-1f3fe-2642","uc_output":"1f9da-1f3fe-200d-2642-fe0f","uc_match":"1f9da-1f3fe-2642-fe0f","uc_greedy":"1f9da-1f3fe-2642","shortnames":[":man_fairy_medium_dark_skin_tone:"],"category":"people"},":man_fairy_tone5:":{"uc_base":"1f9da-1f3ff-2642","uc_output":"1f9da-1f3ff-200d-2642-fe0f","uc_match":"1f9da-1f3ff-2642-fe0f","uc_greedy":"1f9da-1f3ff-2642","shortnames":[":man_fairy_dark_skin_tone:"],"category":"people"},":man_frowning_tone1:":{"uc_base":"1f64d-1f3fb-2642","uc_output":"1f64d-1f3fb-200d-2642-fe0f","uc_match":"1f64d-1f3fb-2642-fe0f","uc_greedy":"1f64d-1f3fb-2642","shortnames":[":man_frowning_light_skin_tone:"],"category":"people"},":man_frowning_tone2:":{"uc_base":"1f64d-1f3fc-2642","uc_output":"1f64d-1f3fc-200d-2642-fe0f","uc_match":"1f64d-1f3fc-2642-fe0f","uc_greedy":"1f64d-1f3fc-2642","shortnames":[":man_frowning_medium_light_skin_tone:"],"category":"people"},":man_frowning_tone3:":{"uc_base":"1f64d-1f3fd-2642","uc_output":"1f64d-1f3fd-200d-2642-fe0f","uc_match":"1f64d-1f3fd-2642-fe0f","uc_greedy":"1f64d-1f3fd-2642","shortnames":[":man_frowning_medium_skin_tone:"],"category":"people"},":man_frowning_tone4:":{"uc_base":"1f64d-1f3fe-2642","uc_output":"1f64d-1f3fe-200d-2642-fe0f","uc_match":"1f64d-1f3fe-2642-fe0f","uc_greedy":"1f64d-1f3fe-2642","shortnames":[":man_frowning_medium_dark_skin_tone:"],"category":"people"},":man_frowning_tone5:":{"uc_base":"1f64d-1f3ff-2642","uc_output":"1f64d-1f3ff-200d-2642-fe0f","uc_match":"1f64d-1f3ff-2642-fe0f","uc_greedy":"1f64d-1f3ff-2642","shortnames":[":man_frowning_dark_skin_tone:"],"category":"people"},":man_gesturing_no_tone1:":{"uc_base":"1f645-1f3fb-2642","uc_output":"1f645-1f3fb-200d-2642-fe0f","uc_match":"1f645-1f3fb-2642-fe0f","uc_greedy":"1f645-1f3fb-2642","shortnames":[":man_gesturing_no_light_skin_tone:"],"category":"people"},":man_gesturing_no_tone2:":{"uc_base":"1f645-1f3fc-2642","uc_output":"1f645-1f3fc-200d-2642-fe0f","uc_match":"1f645-1f3fc-2642-fe0f","uc_greedy":"1f645-1f3fc-2642","shortnames":[":man_gesturing_no_medium_light_skin_tone:"],"category":"people"},":man_gesturing_no_tone3:":{"uc_base":"1f645-1f3fd-2642","uc_output":"1f645-1f3fd-200d-2642-fe0f","uc_match":"1f645-1f3fd-2642-fe0f","uc_greedy":"1f645-1f3fd-2642","shortnames":[":man_gesturing_no_medium_skin_tone:"],"category":"people"},":man_gesturing_no_tone4:":{"uc_base":"1f645-1f3fe-2642","uc_output":"1f645-1f3fe-200d-2642-fe0f","uc_match":"1f645-1f3fe-2642-fe0f","uc_greedy":"1f645-1f3fe-2642","shortnames":[":man_gesturing_no_medium_dark_skin_tone:"],"category":"people"},":man_gesturing_no_tone5:":{"uc_base":"1f645-1f3ff-2642","uc_output":"1f645-1f3ff-200d-2642-fe0f","uc_match":"1f645-1f3ff-2642-fe0f","uc_greedy":"1f645-1f3ff-2642","shortnames":[":man_gesturing_no_dark_skin_tone:"],"category":"people"},":man_gesturing_ok_tone1:":{"uc_base":"1f646-1f3fb-2642","uc_output":"1f646-1f3fb-200d-2642-fe0f","uc_match":"1f646-1f3fb-2642-fe0f","uc_greedy":"1f646-1f3fb-2642","shortnames":[":man_gesturing_ok_light_skin_tone:"],"category":"people"},":man_gesturing_ok_tone2:":{"uc_base":"1f646-1f3fc-2642","uc_output":"1f646-1f3fc-200d-2642-fe0f","uc_match":"1f646-1f3fc-2642-fe0f","uc_greedy":"1f646-1f3fc-2642","shortnames":[":man_gesturing_ok_medium_light_skin_tone:"],"category":"people"},":man_gesturing_ok_tone3:":{"uc_base":"1f646-1f3fd-2642","uc_output":"1f646-1f3fd-200d-2642-fe0f","uc_match":"1f646-1f3fd-2642-fe0f","uc_greedy":"1f646-1f3fd-2642","shortnames":[":man_gesturing_ok_medium_skin_tone:"],"category":"people"},":man_gesturing_ok_tone4:":{"uc_base":"1f646-1f3fe-2642","uc_output":"1f646-1f3fe-200d-2642-fe0f","uc_match":"1f646-1f3fe-2642-fe0f","uc_greedy":"1f646-1f3fe-2642","shortnames":[":man_gesturing_ok_medium_dark_skin_tone:"],"category":"people"},":man_gesturing_ok_tone5:":{"uc_base":"1f646-1f3ff-2642","uc_output":"1f646-1f3ff-200d-2642-fe0f","uc_match":"1f646-1f3ff-2642-fe0f","uc_greedy":"1f646-1f3ff-2642","shortnames":[":man_gesturing_ok_dark_skin_tone:"],"category":"people"},":man_getting_face_massage_tone1:":{"uc_base":"1f486-1f3fb-2642","uc_output":"1f486-1f3fb-200d-2642-fe0f","uc_match":"1f486-1f3fb-2642-fe0f","uc_greedy":"1f486-1f3fb-2642","shortnames":[":man_getting_face_massage_light_skin_tone:"],"category":"people"},":man_getting_face_massage_tone2:":{"uc_base":"1f486-1f3fc-2642","uc_output":"1f486-1f3fc-200d-2642-fe0f","uc_match":"1f486-1f3fc-2642-fe0f","uc_greedy":"1f486-1f3fc-2642","shortnames":[":man_getting_face_massage_medium_light_skin_tone:"],"category":"people"},":man_getting_face_massage_tone3:":{"uc_base":"1f486-1f3fd-2642","uc_output":"1f486-1f3fd-200d-2642-fe0f","uc_match":"1f486-1f3fd-2642-fe0f","uc_greedy":"1f486-1f3fd-2642","shortnames":[":man_getting_face_massage_medium_skin_tone:"],"category":"people"},":man_getting_face_massage_tone4:":{"uc_base":"1f486-1f3fe-2642","uc_output":"1f486-1f3fe-200d-2642-fe0f","uc_match":"1f486-1f3fe-2642-fe0f","uc_greedy":"1f486-1f3fe-2642","shortnames":[":man_getting_face_massage_medium_dark_skin_tone:"],"category":"people"},":man_getting_face_massage_tone5:":{"uc_base":"1f486-1f3ff-2642","uc_output":"1f486-1f3ff-200d-2642-fe0f","uc_match":"1f486-1f3ff-2642-fe0f","uc_greedy":"1f486-1f3ff-2642","shortnames":[":man_getting_face_massage_dark_skin_tone:"],"category":"people"},":man_getting_haircut_tone1:":{"uc_base":"1f487-1f3fb-2642","uc_output":"1f487-1f3fb-200d-2642-fe0f","uc_match":"1f487-1f3fb-2642-fe0f","uc_greedy":"1f487-1f3fb-2642","shortnames":[":man_getting_haircut_light_skin_tone:"],"category":"people"},":man_getting_haircut_tone2:":{"uc_base":"1f487-1f3fc-2642","uc_output":"1f487-1f3fc-200d-2642-fe0f","uc_match":"1f487-1f3fc-2642-fe0f","uc_greedy":"1f487-1f3fc-2642","shortnames":[":man_getting_haircut_medium_light_skin_tone:"],"category":"people"},":man_getting_haircut_tone3:":{"uc_base":"1f487-1f3fd-2642","uc_output":"1f487-1f3fd-200d-2642-fe0f","uc_match":"1f487-1f3fd-2642-fe0f","uc_greedy":"1f487-1f3fd-2642","shortnames":[":man_getting_haircut_medium_skin_tone:"],"category":"people"},":man_getting_haircut_tone4:":{"uc_base":"1f487-1f3fe-2642","uc_output":"1f487-1f3fe-200d-2642-fe0f","uc_match":"1f487-1f3fe-2642-fe0f","uc_greedy":"1f487-1f3fe-2642","shortnames":[":man_getting_haircut_medium_dark_skin_tone:"],"category":"people"},":man_getting_haircut_tone5:":{"uc_base":"1f487-1f3ff-2642","uc_output":"1f487-1f3ff-200d-2642-fe0f","uc_match":"1f487-1f3ff-2642-fe0f","uc_greedy":"1f487-1f3ff-2642","shortnames":[":man_getting_haircut_dark_skin_tone:"],"category":"people"},":man_golfing_tone1:":{"uc_base":"1f3cc-1f3fb-2642","uc_output":"1f3cc-1f3fb-200d-2642-fe0f","uc_match":"1f3cc-fe0f-1f3fb-2642-fe0f","uc_greedy":"1f3cc-1f3fb-2642","shortnames":[":man_golfing_light_skin_tone:"],"category":"activity"},":man_golfing_tone2:":{"uc_base":"1f3cc-1f3fc-2642","uc_output":"1f3cc-1f3fc-200d-2642-fe0f","uc_match":"1f3cc-fe0f-1f3fc-2642-fe0f","uc_greedy":"1f3cc-1f3fc-2642","shortnames":[":man_golfing_medium_light_skin_tone:"],"category":"activity"},":man_golfing_tone3:":{"uc_base":"1f3cc-1f3fd-2642","uc_output":"1f3cc-1f3fd-200d-2642-fe0f","uc_match":"1f3cc-fe0f-1f3fd-2642-fe0f","uc_greedy":"1f3cc-1f3fd-2642","shortnames":[":man_golfing_medium_skin_tone:"],"category":"activity"},":man_golfing_tone4:":{"uc_base":"1f3cc-1f3fe-2642","uc_output":"1f3cc-1f3fe-200d-2642-fe0f","uc_match":"1f3cc-fe0f-1f3fe-2642-fe0f","uc_greedy":"1f3cc-1f3fe-2642","shortnames":[":man_golfing_medium_dark_skin_tone:"],"category":"activity"},":man_golfing_tone5:":{"uc_base":"1f3cc-1f3ff-2642","uc_output":"1f3cc-1f3ff-200d-2642-fe0f","uc_match":"1f3cc-fe0f-1f3ff-2642-fe0f","uc_greedy":"1f3cc-1f3ff-2642","shortnames":[":man_golfing_dark_skin_tone:"],"category":"activity"},":man_guard_tone1:":{"uc_base":"1f482-1f3fb-2642","uc_output":"1f482-1f3fb-200d-2642-fe0f","uc_match":"1f482-1f3fb-2642-fe0f","uc_greedy":"1f482-1f3fb-2642","shortnames":[":man_guard_light_skin_tone:"],"category":"people"},":man_guard_tone2:":{"uc_base":"1f482-1f3fc-2642","uc_output":"1f482-1f3fc-200d-2642-fe0f","uc_match":"1f482-1f3fc-2642-fe0f","uc_greedy":"1f482-1f3fc-2642","shortnames":[":man_guard_medium_light_skin_tone:"],"category":"people"},":man_guard_tone3:":{"uc_base":"1f482-1f3fd-2642","uc_output":"1f482-1f3fd-200d-2642-fe0f","uc_match":"1f482-1f3fd-2642-fe0f","uc_greedy":"1f482-1f3fd-2642","shortnames":[":man_guard_medium_skin_tone:"],"category":"people"},":man_guard_tone4:":{"uc_base":"1f482-1f3fe-2642","uc_output":"1f482-1f3fe-200d-2642-fe0f","uc_match":"1f482-1f3fe-2642-fe0f","uc_greedy":"1f482-1f3fe-2642","shortnames":[":man_guard_medium_dark_skin_tone:"],"category":"people"},":man_guard_tone5:":{"uc_base":"1f482-1f3ff-2642","uc_output":"1f482-1f3ff-200d-2642-fe0f","uc_match":"1f482-1f3ff-2642-fe0f","uc_greedy":"1f482-1f3ff-2642","shortnames":[":man_guard_dark_skin_tone:"],"category":"people"},":man_health_worker_tone1:":{"uc_base":"1f468-1f3fb-2695","uc_output":"1f468-1f3fb-200d-2695-fe0f","uc_match":"1f468-1f3fb-2695-fe0f","uc_greedy":"1f468-1f3fb-2695","shortnames":[":man_health_worker_light_skin_tone:"],"category":"people"},":man_health_worker_tone2:":{"uc_base":"1f468-1f3fc-2695","uc_output":"1f468-1f3fc-200d-2695-fe0f","uc_match":"1f468-1f3fc-2695-fe0f","uc_greedy":"1f468-1f3fc-2695","shortnames":[":man_health_worker_medium_light_skin_tone:"],"category":"people"},":man_health_worker_tone3:":{"uc_base":"1f468-1f3fd-2695","uc_output":"1f468-1f3fd-200d-2695-fe0f","uc_match":"1f468-1f3fd-2695-fe0f","uc_greedy":"1f468-1f3fd-2695","shortnames":[":man_health_worker_medium_skin_tone:"],"category":"people"},":man_health_worker_tone4:":{"uc_base":"1f468-1f3fe-2695","uc_output":"1f468-1f3fe-200d-2695-fe0f","uc_match":"1f468-1f3fe-2695-fe0f","uc_greedy":"1f468-1f3fe-2695","shortnames":[":man_health_worker_medium_dark_skin_tone:"],"category":"people"},":man_health_worker_tone5:":{"uc_base":"1f468-1f3ff-2695","uc_output":"1f468-1f3ff-200d-2695-fe0f","uc_match":"1f468-1f3ff-2695-fe0f","uc_greedy":"1f468-1f3ff-2695","shortnames":[":man_health_worker_dark_skin_tone:"],"category":"people"},":man_in_lotus_position_tone1:":{"uc_base":"1f9d8-1f3fb-2642","uc_output":"1f9d8-1f3fb-200d-2642-fe0f","uc_match":"1f9d8-1f3fb-2642-fe0f","uc_greedy":"1f9d8-1f3fb-2642","shortnames":[":man_in_lotus_position_light_skin_tone:"],"category":"activity"},":man_in_lotus_position_tone2:":{"uc_base":"1f9d8-1f3fc-2642","uc_output":"1f9d8-1f3fc-200d-2642-fe0f","uc_match":"1f9d8-1f3fc-2642-fe0f","uc_greedy":"1f9d8-1f3fc-2642","shortnames":[":man_in_lotus_position_medium_light_skin_tone:"],"category":"activity"},":man_in_lotus_position_tone3:":{"uc_base":"1f9d8-1f3fd-2642","uc_output":"1f9d8-1f3fd-200d-2642-fe0f","uc_match":"1f9d8-1f3fd-2642-fe0f","uc_greedy":"1f9d8-1f3fd-2642","shortnames":[":man_in_lotus_position_medium_skin_tone:"],"category":"activity"},":man_in_lotus_position_tone4:":{"uc_base":"1f9d8-1f3fe-2642","uc_output":"1f9d8-1f3fe-200d-2642-fe0f","uc_match":"1f9d8-1f3fe-2642-fe0f","uc_greedy":"1f9d8-1f3fe-2642","shortnames":[":man_in_lotus_position_medium_dark_skin_tone:"],"category":"activity"},":man_in_lotus_position_tone5:":{"uc_base":"1f9d8-1f3ff-2642","uc_output":"1f9d8-1f3ff-200d-2642-fe0f","uc_match":"1f9d8-1f3ff-2642-fe0f","uc_greedy":"1f9d8-1f3ff-2642","shortnames":[":man_in_lotus_position_dark_skin_tone:"],"category":"activity"},":man_in_steamy_room_tone1:":{"uc_base":"1f9d6-1f3fb-2642","uc_output":"1f9d6-1f3fb-200d-2642-fe0f","uc_match":"1f9d6-1f3fb-2642-fe0f","uc_greedy":"1f9d6-1f3fb-2642","shortnames":[":man_in_steamy_room_light_skin_tone:"],"category":"activity"},":man_in_steamy_room_tone2:":{"uc_base":"1f9d6-1f3fc-2642","uc_output":"1f9d6-1f3fc-200d-2642-fe0f","uc_match":"1f9d6-1f3fc-2642-fe0f","uc_greedy":"1f9d6-1f3fc-2642","shortnames":[":man_in_steamy_room_medium_light_skin_tone:"],"category":"activity"},":man_in_steamy_room_tone3:":{"uc_base":"1f9d6-1f3fd-2642","uc_output":"1f9d6-1f3fd-200d-2642-fe0f","uc_match":"1f9d6-1f3fd-2642-fe0f","uc_greedy":"1f9d6-1f3fd-2642","shortnames":[":man_in_steamy_room_medium_skin_tone:"],"category":"activity"},":man_in_steamy_room_tone4:":{"uc_base":"1f9d6-1f3fe-2642","uc_output":"1f9d6-1f3fe-200d-2642-fe0f","uc_match":"1f9d6-1f3fe-2642-fe0f","uc_greedy":"1f9d6-1f3fe-2642","shortnames":[":man_in_steamy_room_medium_dark_skin_tone:"],"category":"activity"},":man_in_steamy_room_tone5:":{"uc_base":"1f9d6-1f3ff-2642","uc_output":"1f9d6-1f3ff-200d-2642-fe0f","uc_match":"1f9d6-1f3ff-2642-fe0f","uc_greedy":"1f9d6-1f3ff-2642","shortnames":[":man_in_steamy_room_dark_skin_tone:"],"category":"activity"},":man_judge_tone1:":{"uc_base":"1f468-1f3fb-2696","uc_output":"1f468-1f3fb-200d-2696-fe0f","uc_match":"1f468-1f3fb-2696-fe0f","uc_greedy":"1f468-1f3fb-2696","shortnames":[":man_judge_light_skin_tone:"],"category":"people"},":man_judge_tone2:":{"uc_base":"1f468-1f3fc-2696","uc_output":"1f468-1f3fc-200d-2696-fe0f","uc_match":"1f468-1f3fc-2696-fe0f","uc_greedy":"1f468-1f3fc-2696","shortnames":[":man_judge_medium_light_skin_tone:"],"category":"people"},":man_judge_tone3:":{"uc_base":"1f468-1f3fd-2696","uc_output":"1f468-1f3fd-200d-2696-fe0f","uc_match":"1f468-1f3fd-2696-fe0f","uc_greedy":"1f468-1f3fd-2696","shortnames":[":man_judge_medium_skin_tone:"],"category":"people"},":man_judge_tone4:":{"uc_base":"1f468-1f3fe-2696","uc_output":"1f468-1f3fe-200d-2696-fe0f","uc_match":"1f468-1f3fe-2696-fe0f","uc_greedy":"1f468-1f3fe-2696","shortnames":[":man_judge_medium_dark_skin_tone:"],"category":"people"},":man_judge_tone5:":{"uc_base":"1f468-1f3ff-2696","uc_output":"1f468-1f3ff-200d-2696-fe0f","uc_match":"1f468-1f3ff-2696-fe0f","uc_greedy":"1f468-1f3ff-2696","shortnames":[":man_judge_dark_skin_tone:"],"category":"people"},":man_juggling_tone1:":{"uc_base":"1f939-1f3fb-2642","uc_output":"1f939-1f3fb-200d-2642-fe0f","uc_match":"1f939-1f3fb-2642-fe0f","uc_greedy":"1f939-1f3fb-2642","shortnames":[":man_juggling_light_skin_tone:"],"category":"activity"},":man_juggling_tone2:":{"uc_base":"1f939-1f3fc-2642","uc_output":"1f939-1f3fc-200d-2642-fe0f","uc_match":"1f939-1f3fc-2642-fe0f","uc_greedy":"1f939-1f3fc-2642","shortnames":[":man_juggling_medium_light_skin_tone:"],"category":"activity"},":man_juggling_tone3:":{"uc_base":"1f939-1f3fd-2642","uc_output":"1f939-1f3fd-200d-2642-fe0f","uc_match":"1f939-1f3fd-2642-fe0f","uc_greedy":"1f939-1f3fd-2642","shortnames":[":man_juggling_medium_skin_tone:"],"category":"activity"},":man_juggling_tone4:":{"uc_base":"1f939-1f3fe-2642","uc_output":"1f939-1f3fe-200d-2642-fe0f","uc_match":"1f939-1f3fe-2642-fe0f","uc_greedy":"1f939-1f3fe-2642","shortnames":[":man_juggling_medium_dark_skin_tone:"],"category":"activity"},":man_juggling_tone5:":{"uc_base":"1f939-1f3ff-2642","uc_output":"1f939-1f3ff-200d-2642-fe0f","uc_match":"1f939-1f3ff-2642-fe0f","uc_greedy":"1f939-1f3ff-2642","shortnames":[":man_juggling_dark_skin_tone:"],"category":"activity"},":man_lifting_weights_tone1:":{"uc_base":"1f3cb-1f3fb-2642","uc_output":"1f3cb-1f3fb-200d-2642-fe0f","uc_match":"1f3cb-fe0f-1f3fb-2642-fe0f","uc_greedy":"1f3cb-1f3fb-2642","shortnames":[":man_lifting_weights_light_skin_tone:"],"category":"activity"},":man_lifting_weights_tone2:":{"uc_base":"1f3cb-1f3fc-2642","uc_output":"1f3cb-1f3fc-200d-2642-fe0f","uc_match":"1f3cb-fe0f-1f3fc-2642-fe0f","uc_greedy":"1f3cb-1f3fc-2642","shortnames":[":man_lifting_weights_medium_light_skin_tone:"],"category":"activity"},":man_lifting_weights_tone3:":{"uc_base":"1f3cb-1f3fd-2642","uc_output":"1f3cb-1f3fd-200d-2642-fe0f","uc_match":"1f3cb-fe0f-1f3fd-2642-fe0f","uc_greedy":"1f3cb-1f3fd-2642","shortnames":[":man_lifting_weights_medium_skin_tone:"],"category":"activity"},":man_lifting_weights_tone4:":{"uc_base":"1f3cb-1f3fe-2642","uc_output":"1f3cb-1f3fe-200d-2642-fe0f","uc_match":"1f3cb-fe0f-1f3fe-2642-fe0f","uc_greedy":"1f3cb-1f3fe-2642","shortnames":[":man_lifting_weights_medium_dark_skin_tone:"],"category":"activity"},":man_lifting_weights_tone5:":{"uc_base":"1f3cb-1f3ff-2642","uc_output":"1f3cb-1f3ff-200d-2642-fe0f","uc_match":"1f3cb-fe0f-1f3ff-2642-fe0f","uc_greedy":"1f3cb-1f3ff-2642","shortnames":[":man_lifting_weights_dark_skin_tone:"],"category":"activity"},":man_mage_tone1:":{"uc_base":"1f9d9-1f3fb-2642","uc_output":"1f9d9-1f3fb-200d-2642-fe0f","uc_match":"1f9d9-1f3fb-2642-fe0f","uc_greedy":"1f9d9-1f3fb-2642","shortnames":[":man_mage_light_skin_tone:"],"category":"people"},":man_mage_tone2:":{"uc_base":"1f9d9-1f3fc-2642","uc_output":"1f9d9-1f3fc-200d-2642-fe0f","uc_match":"1f9d9-1f3fc-2642-fe0f","uc_greedy":"1f9d9-1f3fc-2642","shortnames":[":man_mage_medium_light_skin_tone:"],"category":"people"},":man_mage_tone3:":{"uc_base":"1f9d9-1f3fd-2642","uc_output":"1f9d9-1f3fd-200d-2642-fe0f","uc_match":"1f9d9-1f3fd-2642-fe0f","uc_greedy":"1f9d9-1f3fd-2642","shortnames":[":man_mage_medium_skin_tone:"],"category":"people"},":man_mage_tone4:":{"uc_base":"1f9d9-1f3fe-2642","uc_output":"1f9d9-1f3fe-200d-2642-fe0f","uc_match":"1f9d9-1f3fe-2642-fe0f","uc_greedy":"1f9d9-1f3fe-2642","shortnames":[":man_mage_medium_dark_skin_tone:"],"category":"people"},":man_mage_tone5:":{"uc_base":"1f9d9-1f3ff-2642","uc_output":"1f9d9-1f3ff-200d-2642-fe0f","uc_match":"1f9d9-1f3ff-2642-fe0f","uc_greedy":"1f9d9-1f3ff-2642","shortnames":[":man_mage_dark_skin_tone:"],"category":"people"},":man_mountain_biking_tone1:":{"uc_base":"1f6b5-1f3fb-2642","uc_output":"1f6b5-1f3fb-200d-2642-fe0f","uc_match":"1f6b5-1f3fb-2642-fe0f","uc_greedy":"1f6b5-1f3fb-2642","shortnames":[":man_mountain_biking_light_skin_tone:"],"category":"activity"},":man_mountain_biking_tone2:":{"uc_base":"1f6b5-1f3fc-2642","uc_output":"1f6b5-1f3fc-200d-2642-fe0f","uc_match":"1f6b5-1f3fc-2642-fe0f","uc_greedy":"1f6b5-1f3fc-2642","shortnames":[":man_mountain_biking_medium_light_skin_tone:"],"category":"activity"},":man_mountain_biking_tone3:":{"uc_base":"1f6b5-1f3fd-2642","uc_output":"1f6b5-1f3fd-200d-2642-fe0f","uc_match":"1f6b5-1f3fd-2642-fe0f","uc_greedy":"1f6b5-1f3fd-2642","shortnames":[":man_mountain_biking_medium_skin_tone:"],"category":"activity"},":man_mountain_biking_tone4:":{"uc_base":"1f6b5-1f3fe-2642","uc_output":"1f6b5-1f3fe-200d-2642-fe0f","uc_match":"1f6b5-1f3fe-2642-fe0f","uc_greedy":"1f6b5-1f3fe-2642","shortnames":[":man_mountain_biking_medium_dark_skin_tone:"],"category":"activity"},":man_mountain_biking_tone5:":{"uc_base":"1f6b5-1f3ff-2642","uc_output":"1f6b5-1f3ff-200d-2642-fe0f","uc_match":"1f6b5-1f3ff-2642-fe0f","uc_greedy":"1f6b5-1f3ff-2642","shortnames":[":man_mountain_biking_dark_skin_tone:"],"category":"activity"},":man_pilot_tone1:":{"uc_base":"1f468-1f3fb-2708","uc_output":"1f468-1f3fb-200d-2708-fe0f","uc_match":"1f468-1f3fb-2708-fe0f","uc_greedy":"1f468-1f3fb-2708","shortnames":[":man_pilot_light_skin_tone:"],"category":"people"},":man_pilot_tone2:":{"uc_base":"1f468-1f3fc-2708","uc_output":"1f468-1f3fc-200d-2708-fe0f","uc_match":"1f468-1f3fc-2708-fe0f","uc_greedy":"1f468-1f3fc-2708","shortnames":[":man_pilot_medium_light_skin_tone:"],"category":"people"},":man_pilot_tone3:":{"uc_base":"1f468-1f3fd-2708","uc_output":"1f468-1f3fd-200d-2708-fe0f","uc_match":"1f468-1f3fd-2708-fe0f","uc_greedy":"1f468-1f3fd-2708","shortnames":[":man_pilot_medium_skin_tone:"],"category":"people"},":man_pilot_tone4:":{"uc_base":"1f468-1f3fe-2708","uc_output":"1f468-1f3fe-200d-2708-fe0f","uc_match":"1f468-1f3fe-2708-fe0f","uc_greedy":"1f468-1f3fe-2708","shortnames":[":man_pilot_medium_dark_skin_tone:"],"category":"people"},":man_pilot_tone5:":{"uc_base":"1f468-1f3ff-2708","uc_output":"1f468-1f3ff-200d-2708-fe0f","uc_match":"1f468-1f3ff-2708-fe0f","uc_greedy":"1f468-1f3ff-2708","shortnames":[":man_pilot_dark_skin_tone:"],"category":"people"},":man_playing_handball_tone1:":{"uc_base":"1f93e-1f3fb-2642","uc_output":"1f93e-1f3fb-200d-2642-fe0f","uc_match":"1f93e-1f3fb-2642-fe0f","uc_greedy":"1f93e-1f3fb-2642","shortnames":[":man_playing_handball_light_skin_tone:"],"category":"activity"},":man_playing_handball_tone2:":{"uc_base":"1f93e-1f3fc-2642","uc_output":"1f93e-1f3fc-200d-2642-fe0f","uc_match":"1f93e-1f3fc-2642-fe0f","uc_greedy":"1f93e-1f3fc-2642","shortnames":[":man_playing_handball_medium_light_skin_tone:"],"category":"activity"},":man_playing_handball_tone3:":{"uc_base":"1f93e-1f3fd-2642","uc_output":"1f93e-1f3fd-200d-2642-fe0f","uc_match":"1f93e-1f3fd-2642-fe0f","uc_greedy":"1f93e-1f3fd-2642","shortnames":[":man_playing_handball_medium_skin_tone:"],"category":"activity"},":man_playing_handball_tone4:":{"uc_base":"1f93e-1f3fe-2642","uc_output":"1f93e-1f3fe-200d-2642-fe0f","uc_match":"1f93e-1f3fe-2642-fe0f","uc_greedy":"1f93e-1f3fe-2642","shortnames":[":man_playing_handball_medium_dark_skin_tone:"],"category":"activity"},":man_playing_handball_tone5:":{"uc_base":"1f93e-1f3ff-2642","uc_output":"1f93e-1f3ff-200d-2642-fe0f","uc_match":"1f93e-1f3ff-2642-fe0f","uc_greedy":"1f93e-1f3ff-2642","shortnames":[":man_playing_handball_dark_skin_tone:"],"category":"activity"},":man_playing_water_polo_tone1:":{"uc_base":"1f93d-1f3fb-2642","uc_output":"1f93d-1f3fb-200d-2642-fe0f","uc_match":"1f93d-1f3fb-2642-fe0f","uc_greedy":"1f93d-1f3fb-2642","shortnames":[":man_playing_water_polo_light_skin_tone:"],"category":"activity"},":man_playing_water_polo_tone2:":{"uc_base":"1f93d-1f3fc-2642","uc_output":"1f93d-1f3fc-200d-2642-fe0f","uc_match":"1f93d-1f3fc-2642-fe0f","uc_greedy":"1f93d-1f3fc-2642","shortnames":[":man_playing_water_polo_medium_light_skin_tone:"],"category":"activity"},":man_playing_water_polo_tone3:":{"uc_base":"1f93d-1f3fd-2642","uc_output":"1f93d-1f3fd-200d-2642-fe0f","uc_match":"1f93d-1f3fd-2642-fe0f","uc_greedy":"1f93d-1f3fd-2642","shortnames":[":man_playing_water_polo_medium_skin_tone:"],"category":"activity"},":man_playing_water_polo_tone4:":{"uc_base":"1f93d-1f3fe-2642","uc_output":"1f93d-1f3fe-200d-2642-fe0f","uc_match":"1f93d-1f3fe-2642-fe0f","uc_greedy":"1f93d-1f3fe-2642","shortnames":[":man_playing_water_polo_medium_dark_skin_tone:"],"category":"activity"},":man_playing_water_polo_tone5:":{"uc_base":"1f93d-1f3ff-2642","uc_output":"1f93d-1f3ff-200d-2642-fe0f","uc_match":"1f93d-1f3ff-2642-fe0f","uc_greedy":"1f93d-1f3ff-2642","shortnames":[":man_playing_water_polo_dark_skin_tone:"],"category":"activity"},":man_police_officer_tone1:":{"uc_base":"1f46e-1f3fb-2642","uc_output":"1f46e-1f3fb-200d-2642-fe0f","uc_match":"1f46e-1f3fb-2642-fe0f","uc_greedy":"1f46e-1f3fb-2642","shortnames":[":man_police_officer_light_skin_tone:"],"category":"people"},":man_police_officer_tone2:":{"uc_base":"1f46e-1f3fc-2642","uc_output":"1f46e-1f3fc-200d-2642-fe0f","uc_match":"1f46e-1f3fc-2642-fe0f","uc_greedy":"1f46e-1f3fc-2642","shortnames":[":man_police_officer_medium_light_skin_tone:"],"category":"people"},":man_police_officer_tone3:":{"uc_base":"1f46e-1f3fd-2642","uc_output":"1f46e-1f3fd-200d-2642-fe0f","uc_match":"1f46e-1f3fd-2642-fe0f","uc_greedy":"1f46e-1f3fd-2642","shortnames":[":man_police_officer_medium_skin_tone:"],"category":"people"},":man_police_officer_tone4:":{"uc_base":"1f46e-1f3fe-2642","uc_output":"1f46e-1f3fe-200d-2642-fe0f","uc_match":"1f46e-1f3fe-2642-fe0f","uc_greedy":"1f46e-1f3fe-2642","shortnames":[":man_police_officer_medium_dark_skin_tone:"],"category":"people"},":man_police_officer_tone5:":{"uc_base":"1f46e-1f3ff-2642","uc_output":"1f46e-1f3ff-200d-2642-fe0f","uc_match":"1f46e-1f3ff-2642-fe0f","uc_greedy":"1f46e-1f3ff-2642","shortnames":[":man_police_officer_dark_skin_tone:"],"category":"people"},":man_pouting_tone1:":{"uc_base":"1f64e-1f3fb-2642","uc_output":"1f64e-1f3fb-200d-2642-fe0f","uc_match":"1f64e-1f3fb-2642-fe0f","uc_greedy":"1f64e-1f3fb-2642","shortnames":[":man_pouting_light_skin_tone:"],"category":"people"},":man_pouting_tone2:":{"uc_base":"1f64e-1f3fc-2642","uc_output":"1f64e-1f3fc-200d-2642-fe0f","uc_match":"1f64e-1f3fc-2642-fe0f","uc_greedy":"1f64e-1f3fc-2642","shortnames":[":man_pouting_medium_light_skin_tone:"],"category":"people"},":man_pouting_tone3:":{"uc_base":"1f64e-1f3fd-2642","uc_output":"1f64e-1f3fd-200d-2642-fe0f","uc_match":"1f64e-1f3fd-2642-fe0f","uc_greedy":"1f64e-1f3fd-2642","shortnames":[":man_pouting_medium_skin_tone:"],"category":"people"},":man_pouting_tone4:":{"uc_base":"1f64e-1f3fe-2642","uc_output":"1f64e-1f3fe-200d-2642-fe0f","uc_match":"1f64e-1f3fe-2642-fe0f","uc_greedy":"1f64e-1f3fe-2642","shortnames":[":man_pouting_medium_dark_skin_tone:"],"category":"people"},":man_pouting_tone5:":{"uc_base":"1f64e-1f3ff-2642","uc_output":"1f64e-1f3ff-200d-2642-fe0f","uc_match":"1f64e-1f3ff-2642-fe0f","uc_greedy":"1f64e-1f3ff-2642","shortnames":[":man_pouting_dark_skin_tone:"],"category":"people"},":man_raising_hand_tone1:":{"uc_base":"1f64b-1f3fb-2642","uc_output":"1f64b-1f3fb-200d-2642-fe0f","uc_match":"1f64b-1f3fb-2642-fe0f","uc_greedy":"1f64b-1f3fb-2642","shortnames":[":man_raising_hand_light_skin_tone:"],"category":"people"},":man_raising_hand_tone2:":{"uc_base":"1f64b-1f3fc-2642","uc_output":"1f64b-1f3fc-200d-2642-fe0f","uc_match":"1f64b-1f3fc-2642-fe0f","uc_greedy":"1f64b-1f3fc-2642","shortnames":[":man_raising_hand_medium_light_skin_tone:"],"category":"people"},":man_raising_hand_tone3:":{"uc_base":"1f64b-1f3fd-2642","uc_output":"1f64b-1f3fd-200d-2642-fe0f","uc_match":"1f64b-1f3fd-2642-fe0f","uc_greedy":"1f64b-1f3fd-2642","shortnames":[":man_raising_hand_medium_skin_tone:"],"category":"people"},":man_raising_hand_tone4:":{"uc_base":"1f64b-1f3fe-2642","uc_output":"1f64b-1f3fe-200d-2642-fe0f","uc_match":"1f64b-1f3fe-2642-fe0f","uc_greedy":"1f64b-1f3fe-2642","shortnames":[":man_raising_hand_medium_dark_skin_tone:"],"category":"people"},":man_raising_hand_tone5:":{"uc_base":"1f64b-1f3ff-2642","uc_output":"1f64b-1f3ff-200d-2642-fe0f","uc_match":"1f64b-1f3ff-2642-fe0f","uc_greedy":"1f64b-1f3ff-2642","shortnames":[":man_raising_hand_dark_skin_tone:"],"category":"people"},":man_rowing_boat_tone1:":{"uc_base":"1f6a3-1f3fb-2642","uc_output":"1f6a3-1f3fb-200d-2642-fe0f","uc_match":"1f6a3-1f3fb-2642-fe0f","uc_greedy":"1f6a3-1f3fb-2642","shortnames":[":man_rowing_boat_light_skin_tone:"],"category":"activity"},":man_rowing_boat_tone2:":{"uc_base":"1f6a3-1f3fc-2642","uc_output":"1f6a3-1f3fc-200d-2642-fe0f","uc_match":"1f6a3-1f3fc-2642-fe0f","uc_greedy":"1f6a3-1f3fc-2642","shortnames":[":man_rowing_boat_medium_light_skin_tone:"],"category":"activity"},":man_rowing_boat_tone3:":{"uc_base":"1f6a3-1f3fd-2642","uc_output":"1f6a3-1f3fd-200d-2642-fe0f","uc_match":"1f6a3-1f3fd-2642-fe0f","uc_greedy":"1f6a3-1f3fd-2642","shortnames":[":man_rowing_boat_medium_skin_tone:"],"category":"activity"},":man_rowing_boat_tone4:":{"uc_base":"1f6a3-1f3fe-2642","uc_output":"1f6a3-1f3fe-200d-2642-fe0f","uc_match":"1f6a3-1f3fe-2642-fe0f","uc_greedy":"1f6a3-1f3fe-2642","shortnames":[":man_rowing_boat_medium_dark_skin_tone:"],"category":"activity"},":man_rowing_boat_tone5:":{"uc_base":"1f6a3-1f3ff-2642","uc_output":"1f6a3-1f3ff-200d-2642-fe0f","uc_match":"1f6a3-1f3ff-2642-fe0f","uc_greedy":"1f6a3-1f3ff-2642","shortnames":[":man_rowing_boat_dark_skin_tone:"],"category":"activity"},":man_running_tone1:":{"uc_base":"1f3c3-1f3fb-2642","uc_output":"1f3c3-1f3fb-200d-2642-fe0f","uc_match":"1f3c3-1f3fb-2642-fe0f","uc_greedy":"1f3c3-1f3fb-2642","shortnames":[":man_running_light_skin_tone:"],"category":"people"},":man_running_tone2:":{"uc_base":"1f3c3-1f3fc-2642","uc_output":"1f3c3-1f3fc-200d-2642-fe0f","uc_match":"1f3c3-1f3fc-2642-fe0f","uc_greedy":"1f3c3-1f3fc-2642","shortnames":[":man_running_medium_light_skin_tone:"],"category":"people"},":man_running_tone3:":{"uc_base":"1f3c3-1f3fd-2642","uc_output":"1f3c3-1f3fd-200d-2642-fe0f","uc_match":"1f3c3-1f3fd-2642-fe0f","uc_greedy":"1f3c3-1f3fd-2642","shortnames":[":man_running_medium_skin_tone:"],"category":"people"},":man_running_tone4:":{"uc_base":"1f3c3-1f3fe-2642","uc_output":"1f3c3-1f3fe-200d-2642-fe0f","uc_match":"1f3c3-1f3fe-2642-fe0f","uc_greedy":"1f3c3-1f3fe-2642","shortnames":[":man_running_medium_dark_skin_tone:"],"category":"people"},":man_running_tone5:":{"uc_base":"1f3c3-1f3ff-2642","uc_output":"1f3c3-1f3ff-200d-2642-fe0f","uc_match":"1f3c3-1f3ff-2642-fe0f","uc_greedy":"1f3c3-1f3ff-2642","shortnames":[":man_running_dark_skin_tone:"],"category":"people"},":man_shrugging_tone1:":{"uc_base":"1f937-1f3fb-2642","uc_output":"1f937-1f3fb-200d-2642-fe0f","uc_match":"1f937-1f3fb-2642-fe0f","uc_greedy":"1f937-1f3fb-2642","shortnames":[":man_shrugging_light_skin_tone:"],"category":"people"},":man_shrugging_tone2:":{"uc_base":"1f937-1f3fc-2642","uc_output":"1f937-1f3fc-200d-2642-fe0f","uc_match":"1f937-1f3fc-2642-fe0f","uc_greedy":"1f937-1f3fc-2642","shortnames":[":man_shrugging_medium_light_skin_tone:"],"category":"people"},":man_shrugging_tone3:":{"uc_base":"1f937-1f3fd-2642","uc_output":"1f937-1f3fd-200d-2642-fe0f","uc_match":"1f937-1f3fd-2642-fe0f","uc_greedy":"1f937-1f3fd-2642","shortnames":[":man_shrugging_medium_skin_tone:"],"category":"people"},":man_shrugging_tone4:":{"uc_base":"1f937-1f3fe-2642","uc_output":"1f937-1f3fe-200d-2642-fe0f","uc_match":"1f937-1f3fe-2642-fe0f","uc_greedy":"1f937-1f3fe-2642","shortnames":[":man_shrugging_medium_dark_skin_tone:"],"category":"people"},":man_shrugging_tone5:":{"uc_base":"1f937-1f3ff-2642","uc_output":"1f937-1f3ff-200d-2642-fe0f","uc_match":"1f937-1f3ff-2642-fe0f","uc_greedy":"1f937-1f3ff-2642","shortnames":[":man_shrugging_dark_skin_tone:"],"category":"people"},":man_surfing_tone1:":{"uc_base":"1f3c4-1f3fb-2642","uc_output":"1f3c4-1f3fb-200d-2642-fe0f","uc_match":"1f3c4-1f3fb-2642-fe0f","uc_greedy":"1f3c4-1f3fb-2642","shortnames":[":man_surfing_light_skin_tone:"],"category":"activity"},":man_surfing_tone2:":{"uc_base":"1f3c4-1f3fc-2642","uc_output":"1f3c4-1f3fc-200d-2642-fe0f","uc_match":"1f3c4-1f3fc-2642-fe0f","uc_greedy":"1f3c4-1f3fc-2642","shortnames":[":man_surfing_medium_light_skin_tone:"],"category":"activity"},":man_surfing_tone3:":{"uc_base":"1f3c4-1f3fd-2642","uc_output":"1f3c4-1f3fd-200d-2642-fe0f","uc_match":"1f3c4-1f3fd-2642-fe0f","uc_greedy":"1f3c4-1f3fd-2642","shortnames":[":man_surfing_medium_skin_tone:"],"category":"activity"},":man_surfing_tone4:":{"uc_base":"1f3c4-1f3fe-2642","uc_output":"1f3c4-1f3fe-200d-2642-fe0f","uc_match":"1f3c4-1f3fe-2642-fe0f","uc_greedy":"1f3c4-1f3fe-2642","shortnames":[":man_surfing_medium_dark_skin_tone:"],"category":"activity"},":man_surfing_tone5:":{"uc_base":"1f3c4-1f3ff-2642","uc_output":"1f3c4-1f3ff-200d-2642-fe0f","uc_match":"1f3c4-1f3ff-2642-fe0f","uc_greedy":"1f3c4-1f3ff-2642","shortnames":[":man_surfing_dark_skin_tone:"],"category":"activity"},":man_swimming_tone1:":{"uc_base":"1f3ca-1f3fb-2642","uc_output":"1f3ca-1f3fb-200d-2642-fe0f","uc_match":"1f3ca-1f3fb-2642-fe0f","uc_greedy":"1f3ca-1f3fb-2642","shortnames":[":man_swimming_light_skin_tone:"],"category":"activity"},":man_swimming_tone2:":{"uc_base":"1f3ca-1f3fc-2642","uc_output":"1f3ca-1f3fc-200d-2642-fe0f","uc_match":"1f3ca-1f3fc-2642-fe0f","uc_greedy":"1f3ca-1f3fc-2642","shortnames":[":man_swimming_medium_light_skin_tone:"],"category":"activity"},":man_swimming_tone3:":{"uc_base":"1f3ca-1f3fd-2642","uc_output":"1f3ca-1f3fd-200d-2642-fe0f","uc_match":"1f3ca-1f3fd-2642-fe0f","uc_greedy":"1f3ca-1f3fd-2642","shortnames":[":man_swimming_medium_skin_tone:"],"category":"activity"},":man_swimming_tone4:":{"uc_base":"1f3ca-1f3fe-2642","uc_output":"1f3ca-1f3fe-200d-2642-fe0f","uc_match":"1f3ca-1f3fe-2642-fe0f","uc_greedy":"1f3ca-1f3fe-2642","shortnames":[":man_swimming_medium_dark_skin_tone:"],"category":"activity"},":man_swimming_tone5:":{"uc_base":"1f3ca-1f3ff-2642","uc_output":"1f3ca-1f3ff-200d-2642-fe0f","uc_match":"1f3ca-1f3ff-2642-fe0f","uc_greedy":"1f3ca-1f3ff-2642","shortnames":[":man_swimming_dark_skin_tone:"],"category":"activity"},":man_tipping_hand_tone1:":{"uc_base":"1f481-1f3fb-2642","uc_output":"1f481-1f3fb-200d-2642-fe0f","uc_match":"1f481-1f3fb-2642-fe0f","uc_greedy":"1f481-1f3fb-2642","shortnames":[":man_tipping_hand_light_skin_tone:"],"category":"people"},":man_tipping_hand_tone2:":{"uc_base":"1f481-1f3fc-2642","uc_output":"1f481-1f3fc-200d-2642-fe0f","uc_match":"1f481-1f3fc-2642-fe0f","uc_greedy":"1f481-1f3fc-2642","shortnames":[":man_tipping_hand_medium_light_skin_tone:"],"category":"people"},":man_tipping_hand_tone3:":{"uc_base":"1f481-1f3fd-2642","uc_output":"1f481-1f3fd-200d-2642-fe0f","uc_match":"1f481-1f3fd-2642-fe0f","uc_greedy":"1f481-1f3fd-2642","shortnames":[":man_tipping_hand_medium_skin_tone:"],"category":"people"},":man_tipping_hand_tone4:":{"uc_base":"1f481-1f3fe-2642","uc_output":"1f481-1f3fe-200d-2642-fe0f","uc_match":"1f481-1f3fe-2642-fe0f","uc_greedy":"1f481-1f3fe-2642","shortnames":[":man_tipping_hand_medium_dark_skin_tone:"],"category":"people"},":man_tipping_hand_tone5:":{"uc_base":"1f481-1f3ff-2642","uc_output":"1f481-1f3ff-200d-2642-fe0f","uc_match":"1f481-1f3ff-2642-fe0f","uc_greedy":"1f481-1f3ff-2642","shortnames":[":man_tipping_hand_dark_skin_tone:"],"category":"people"},":man_vampire_tone1:":{"uc_base":"1f9db-1f3fb-2642","uc_output":"1f9db-1f3fb-200d-2642-fe0f","uc_match":"1f9db-1f3fb-2642-fe0f","uc_greedy":"1f9db-1f3fb-2642","shortnames":[":man_vampire_light_skin_tone:"],"category":"people"},":man_vampire_tone2:":{"uc_base":"1f9db-1f3fc-2642","uc_output":"1f9db-1f3fc-200d-2642-fe0f","uc_match":"1f9db-1f3fc-2642-fe0f","uc_greedy":"1f9db-1f3fc-2642","shortnames":[":man_vampire_medium_light_skin_tone:"],"category":"people"},":man_vampire_tone3:":{"uc_base":"1f9db-1f3fd-2642","uc_output":"1f9db-1f3fd-200d-2642-fe0f","uc_match":"1f9db-1f3fd-2642-fe0f","uc_greedy":"1f9db-1f3fd-2642","shortnames":[":man_vampire_medium_skin_tone:"],"category":"people"},":man_vampire_tone4:":{"uc_base":"1f9db-1f3fe-2642","uc_output":"1f9db-1f3fe-200d-2642-fe0f","uc_match":"1f9db-1f3fe-2642-fe0f","uc_greedy":"1f9db-1f3fe-2642","shortnames":[":man_vampire_medium_dark_skin_tone:"],"category":"people"},":man_vampire_tone5:":{"uc_base":"1f9db-1f3ff-2642","uc_output":"1f9db-1f3ff-200d-2642-fe0f","uc_match":"1f9db-1f3ff-2642-fe0f","uc_greedy":"1f9db-1f3ff-2642","shortnames":[":man_vampire_dark_skin_tone:"],"category":"people"},":man_walking_tone1:":{"uc_base":"1f6b6-1f3fb-2642","uc_output":"1f6b6-1f3fb-200d-2642-fe0f","uc_match":"1f6b6-1f3fb-2642-fe0f","uc_greedy":"1f6b6-1f3fb-2642","shortnames":[":man_walking_light_skin_tone:"],"category":"people"},":man_walking_tone2:":{"uc_base":"1f6b6-1f3fc-2642","uc_output":"1f6b6-1f3fc-200d-2642-fe0f","uc_match":"1f6b6-1f3fc-2642-fe0f","uc_greedy":"1f6b6-1f3fc-2642","shortnames":[":man_walking_medium_light_skin_tone:"],"category":"people"},":man_walking_tone3:":{"uc_base":"1f6b6-1f3fd-2642","uc_output":"1f6b6-1f3fd-200d-2642-fe0f","uc_match":"1f6b6-1f3fd-2642-fe0f","uc_greedy":"1f6b6-1f3fd-2642","shortnames":[":man_walking_medium_skin_tone:"],"category":"people"},":man_walking_tone4:":{"uc_base":"1f6b6-1f3fe-2642","uc_output":"1f6b6-1f3fe-200d-2642-fe0f","uc_match":"1f6b6-1f3fe-2642-fe0f","uc_greedy":"1f6b6-1f3fe-2642","shortnames":[":man_walking_medium_dark_skin_tone:"],"category":"people"},":man_walking_tone5:":{"uc_base":"1f6b6-1f3ff-2642","uc_output":"1f6b6-1f3ff-200d-2642-fe0f","uc_match":"1f6b6-1f3ff-2642-fe0f","uc_greedy":"1f6b6-1f3ff-2642","shortnames":[":man_walking_dark_skin_tone:"],"category":"people"},":man_wearing_turban_tone1:":{"uc_base":"1f473-1f3fb-2642","uc_output":"1f473-1f3fb-200d-2642-fe0f","uc_match":"1f473-1f3fb-2642-fe0f","uc_greedy":"1f473-1f3fb-2642","shortnames":[":man_wearing_turban_light_skin_tone:"],"category":"people"},":man_wearing_turban_tone2:":{"uc_base":"1f473-1f3fc-2642","uc_output":"1f473-1f3fc-200d-2642-fe0f","uc_match":"1f473-1f3fc-2642-fe0f","uc_greedy":"1f473-1f3fc-2642","shortnames":[":man_wearing_turban_medium_light_skin_tone:"],"category":"people"},":man_wearing_turban_tone3:":{"uc_base":"1f473-1f3fd-2642","uc_output":"1f473-1f3fd-200d-2642-fe0f","uc_match":"1f473-1f3fd-2642-fe0f","uc_greedy":"1f473-1f3fd-2642","shortnames":[":man_wearing_turban_medium_skin_tone:"],"category":"people"},":man_wearing_turban_tone4:":{"uc_base":"1f473-1f3fe-2642","uc_output":"1f473-1f3fe-200d-2642-fe0f","uc_match":"1f473-1f3fe-2642-fe0f","uc_greedy":"1f473-1f3fe-2642","shortnames":[":man_wearing_turban_medium_dark_skin_tone:"],"category":"people"},":man_wearing_turban_tone5:":{"uc_base":"1f473-1f3ff-2642","uc_output":"1f473-1f3ff-200d-2642-fe0f","uc_match":"1f473-1f3ff-2642-fe0f","uc_greedy":"1f473-1f3ff-2642","shortnames":[":man_wearing_turban_dark_skin_tone:"],"category":"people"},":mermaid_tone1:":{"uc_base":"1f9dc-1f3fb-2640","uc_output":"1f9dc-1f3fb-200d-2640-fe0f","uc_match":"1f9dc-1f3fb-2640-fe0f","uc_greedy":"1f9dc-1f3fb-2640","shortnames":[":mermaid_light_skin_tone:"],"category":"people"},":mermaid_tone2:":{"uc_base":"1f9dc-1f3fc-2640","uc_output":"1f9dc-1f3fc-200d-2640-fe0f","uc_match":"1f9dc-1f3fc-2640-fe0f","uc_greedy":"1f9dc-1f3fc-2640","shortnames":[":mermaid_medium_light_skin_tone:"],"category":"people"},":mermaid_tone3:":{"uc_base":"1f9dc-1f3fd-2640","uc_output":"1f9dc-1f3fd-200d-2640-fe0f","uc_match":"1f9dc-1f3fd-2640-fe0f","uc_greedy":"1f9dc-1f3fd-2640","shortnames":[":mermaid_medium_skin_tone:"],"category":"people"},":mermaid_tone4:":{"uc_base":"1f9dc-1f3fe-2640","uc_output":"1f9dc-1f3fe-200d-2640-fe0f","uc_match":"1f9dc-1f3fe-2640-fe0f","uc_greedy":"1f9dc-1f3fe-2640","shortnames":[":mermaid_medium_dark_skin_tone:"],"category":"people"},":mermaid_tone5:":{"uc_base":"1f9dc-1f3ff-2640","uc_output":"1f9dc-1f3ff-200d-2640-fe0f","uc_match":"1f9dc-1f3ff-2640-fe0f","uc_greedy":"1f9dc-1f3ff-2640","shortnames":[":mermaid_dark_skin_tone:"],"category":"people"},":merman_tone1:":{"uc_base":"1f9dc-1f3fb-2642","uc_output":"1f9dc-1f3fb-200d-2642-fe0f","uc_match":"1f9dc-1f3fb-2642-fe0f","uc_greedy":"1f9dc-1f3fb-2642","shortnames":[":merman_light_skin_tone:"],"category":"people"},":merman_tone2:":{"uc_base":"1f9dc-1f3fc-2642","uc_output":"1f9dc-1f3fc-200d-2642-fe0f","uc_match":"1f9dc-1f3fc-2642-fe0f","uc_greedy":"1f9dc-1f3fc-2642","shortnames":[":merman_medium_light_skin_tone:"],"category":"people"},":merman_tone3:":{"uc_base":"1f9dc-1f3fd-2642","uc_output":"1f9dc-1f3fd-200d-2642-fe0f","uc_match":"1f9dc-1f3fd-2642-fe0f","uc_greedy":"1f9dc-1f3fd-2642","shortnames":[":merman_medium_skin_tone:"],"category":"people"},":merman_tone4:":{"uc_base":"1f9dc-1f3fe-2642","uc_output":"1f9dc-1f3fe-200d-2642-fe0f","uc_match":"1f9dc-1f3fe-2642-fe0f","uc_greedy":"1f9dc-1f3fe-2642","shortnames":[":merman_medium_dark_skin_tone:"],"category":"people"},":merman_tone5:":{"uc_base":"1f9dc-1f3ff-2642","uc_output":"1f9dc-1f3ff-200d-2642-fe0f","uc_match":"1f9dc-1f3ff-2642-fe0f","uc_greedy":"1f9dc-1f3ff-2642","shortnames":[":merman_dark_skin_tone:"],"category":"people"},":woman_biking_tone1:":{"uc_base":"1f6b4-1f3fb-2640","uc_output":"1f6b4-1f3fb-200d-2640-fe0f","uc_match":"1f6b4-1f3fb-2640-fe0f","uc_greedy":"1f6b4-1f3fb-2640","shortnames":[":woman_biking_light_skin_tone:"],"category":"activity"},":woman_biking_tone2:":{"uc_base":"1f6b4-1f3fc-2640","uc_output":"1f6b4-1f3fc-200d-2640-fe0f","uc_match":"1f6b4-1f3fc-2640-fe0f","uc_greedy":"1f6b4-1f3fc-2640","shortnames":[":woman_biking_medium_light_skin_tone:"],"category":"activity"},":woman_biking_tone3:":{"uc_base":"1f6b4-1f3fd-2640","uc_output":"1f6b4-1f3fd-200d-2640-fe0f","uc_match":"1f6b4-1f3fd-2640-fe0f","uc_greedy":"1f6b4-1f3fd-2640","shortnames":[":woman_biking_medium_skin_tone:"],"category":"activity"},":woman_biking_tone4:":{"uc_base":"1f6b4-1f3fe-2640","uc_output":"1f6b4-1f3fe-200d-2640-fe0f","uc_match":"1f6b4-1f3fe-2640-fe0f","uc_greedy":"1f6b4-1f3fe-2640","shortnames":[":woman_biking_medium_dark_skin_tone:"],"category":"activity"},":woman_biking_tone5:":{"uc_base":"1f6b4-1f3ff-2640","uc_output":"1f6b4-1f3ff-200d-2640-fe0f","uc_match":"1f6b4-1f3ff-2640-fe0f","uc_greedy":"1f6b4-1f3ff-2640","shortnames":[":woman_biking_dark_skin_tone:"],"category":"activity"},":woman_bowing_tone1:":{"uc_base":"1f647-1f3fb-2640","uc_output":"1f647-1f3fb-200d-2640-fe0f","uc_match":"1f647-1f3fb-2640-fe0f","uc_greedy":"1f647-1f3fb-2640","shortnames":[":woman_bowing_light_skin_tone:"],"category":"people"},":woman_bowing_tone2:":{"uc_base":"1f647-1f3fc-2640","uc_output":"1f647-1f3fc-200d-2640-fe0f","uc_match":"1f647-1f3fc-2640-fe0f","uc_greedy":"1f647-1f3fc-2640","shortnames":[":woman_bowing_medium_light_skin_tone:"],"category":"people"},":woman_bowing_tone3:":{"uc_base":"1f647-1f3fd-2640","uc_output":"1f647-1f3fd-200d-2640-fe0f","uc_match":"1f647-1f3fd-2640-fe0f","uc_greedy":"1f647-1f3fd-2640","shortnames":[":woman_bowing_medium_skin_tone:"],"category":"people"},":woman_bowing_tone4:":{"uc_base":"1f647-1f3fe-2640","uc_output":"1f647-1f3fe-200d-2640-fe0f","uc_match":"1f647-1f3fe-2640-fe0f","uc_greedy":"1f647-1f3fe-2640","shortnames":[":woman_bowing_medium_dark_skin_tone:"],"category":"people"},":woman_bowing_tone5:":{"uc_base":"1f647-1f3ff-2640","uc_output":"1f647-1f3ff-200d-2640-fe0f","uc_match":"1f647-1f3ff-2640-fe0f","uc_greedy":"1f647-1f3ff-2640","shortnames":[":woman_bowing_dark_skin_tone:"],"category":"people"},":woman_cartwheeling_tone1:":{"uc_base":"1f938-1f3fb-2640","uc_output":"1f938-1f3fb-200d-2640-fe0f","uc_match":"1f938-1f3fb-2640-fe0f","uc_greedy":"1f938-1f3fb-2640","shortnames":[":woman_cartwheeling_light_skin_tone:"],"category":"activity"},":woman_cartwheeling_tone2:":{"uc_base":"1f938-1f3fc-2640","uc_output":"1f938-1f3fc-200d-2640-fe0f","uc_match":"1f938-1f3fc-2640-fe0f","uc_greedy":"1f938-1f3fc-2640","shortnames":[":woman_cartwheeling_medium_light_skin_tone:"],"category":"activity"},":woman_cartwheeling_tone3:":{"uc_base":"1f938-1f3fd-2640","uc_output":"1f938-1f3fd-200d-2640-fe0f","uc_match":"1f938-1f3fd-2640-fe0f","uc_greedy":"1f938-1f3fd-2640","shortnames":[":woman_cartwheeling_medium_skin_tone:"],"category":"activity"},":woman_cartwheeling_tone4:":{"uc_base":"1f938-1f3fe-2640","uc_output":"1f938-1f3fe-200d-2640-fe0f","uc_match":"1f938-1f3fe-2640-fe0f","uc_greedy":"1f938-1f3fe-2640","shortnames":[":woman_cartwheeling_medium_dark_skin_tone:"],"category":"activity"},":woman_cartwheeling_tone5:":{"uc_base":"1f938-1f3ff-2640","uc_output":"1f938-1f3ff-200d-2640-fe0f","uc_match":"1f938-1f3ff-2640-fe0f","uc_greedy":"1f938-1f3ff-2640","shortnames":[":woman_cartwheeling_dark_skin_tone:"],"category":"activity"},":woman_climbing_tone1:":{"uc_base":"1f9d7-1f3fb-2640","uc_output":"1f9d7-1f3fb-200d-2640-fe0f","uc_match":"1f9d7-1f3fb-2640-fe0f","uc_greedy":"1f9d7-1f3fb-2640","shortnames":[":woman_climbing_light_skin_tone:"],"category":"activity"},":woman_climbing_tone2:":{"uc_base":"1f9d7-1f3fc-2640","uc_output":"1f9d7-1f3fc-200d-2640-fe0f","uc_match":"1f9d7-1f3fc-2640-fe0f","uc_greedy":"1f9d7-1f3fc-2640","shortnames":[":woman_climbing_medium_light_skin_tone:"],"category":"activity"},":woman_climbing_tone3:":{"uc_base":"1f9d7-1f3fd-2640","uc_output":"1f9d7-1f3fd-200d-2640-fe0f","uc_match":"1f9d7-1f3fd-2640-fe0f","uc_greedy":"1f9d7-1f3fd-2640","shortnames":[":woman_climbing_medium_skin_tone:"],"category":"activity"},":woman_climbing_tone4:":{"uc_base":"1f9d7-1f3fe-2640","uc_output":"1f9d7-1f3fe-200d-2640-fe0f","uc_match":"1f9d7-1f3fe-2640-fe0f","uc_greedy":"1f9d7-1f3fe-2640","shortnames":[":woman_climbing_medium_dark_skin_tone:"],"category":"activity"},":woman_climbing_tone5:":{"uc_base":"1f9d7-1f3ff-2640","uc_output":"1f9d7-1f3ff-200d-2640-fe0f","uc_match":"1f9d7-1f3ff-2640-fe0f","uc_greedy":"1f9d7-1f3ff-2640","shortnames":[":woman_climbing_dark_skin_tone:"],"category":"activity"},":woman_construction_worker_tone1:":{"uc_base":"1f477-1f3fb-2640","uc_output":"1f477-1f3fb-200d-2640-fe0f","uc_match":"1f477-1f3fb-2640-fe0f","uc_greedy":"1f477-1f3fb-2640","shortnames":[":woman_construction_worker_light_skin_tone:"],"category":"people"},":woman_construction_worker_tone2:":{"uc_base":"1f477-1f3fc-2640","uc_output":"1f477-1f3fc-200d-2640-fe0f","uc_match":"1f477-1f3fc-2640-fe0f","uc_greedy":"1f477-1f3fc-2640","shortnames":[":woman_construction_worker_medium_light_skin_tone:"],"category":"people"},":woman_construction_worker_tone3:":{"uc_base":"1f477-1f3fd-2640","uc_output":"1f477-1f3fd-200d-2640-fe0f","uc_match":"1f477-1f3fd-2640-fe0f","uc_greedy":"1f477-1f3fd-2640","shortnames":[":woman_construction_worker_medium_skin_tone:"],"category":"people"},":woman_construction_worker_tone4:":{"uc_base":"1f477-1f3fe-2640","uc_output":"1f477-1f3fe-200d-2640-fe0f","uc_match":"1f477-1f3fe-2640-fe0f","uc_greedy":"1f477-1f3fe-2640","shortnames":[":woman_construction_worker_medium_dark_skin_tone:"],"category":"people"},":woman_construction_worker_tone5:":{"uc_base":"1f477-1f3ff-2640","uc_output":"1f477-1f3ff-200d-2640-fe0f","uc_match":"1f477-1f3ff-2640-fe0f","uc_greedy":"1f477-1f3ff-2640","shortnames":[":woman_construction_worker_dark_skin_tone:"],"category":"people"},":woman_detective_tone1:":{"uc_base":"1f575-1f3fb-2640","uc_output":"1f575-1f3fb-200d-2640-fe0f","uc_match":"1f575-fe0f-1f3fb-2640-fe0f","uc_greedy":"1f575-1f3fb-2640","shortnames":[":woman_detective_light_skin_tone:"],"category":"people"},":woman_detective_tone2:":{"uc_base":"1f575-1f3fc-2640","uc_output":"1f575-1f3fc-200d-2640-fe0f","uc_match":"1f575-fe0f-1f3fc-2640-fe0f","uc_greedy":"1f575-1f3fc-2640","shortnames":[":woman_detective_medium_light_skin_tone:"],"category":"people"},":woman_detective_tone3:":{"uc_base":"1f575-1f3fd-2640","uc_output":"1f575-1f3fd-200d-2640-fe0f","uc_match":"1f575-fe0f-1f3fd-2640-fe0f","uc_greedy":"1f575-1f3fd-2640","shortnames":[":woman_detective_medium_skin_tone:"],"category":"people"},":woman_detective_tone4:":{"uc_base":"1f575-1f3fe-2640","uc_output":"1f575-1f3fe-200d-2640-fe0f","uc_match":"1f575-fe0f-1f3fe-2640-fe0f","uc_greedy":"1f575-1f3fe-2640","shortnames":[":woman_detective_medium_dark_skin_tone:"],"category":"people"},":woman_detective_tone5:":{"uc_base":"1f575-1f3ff-2640","uc_output":"1f575-1f3ff-200d-2640-fe0f","uc_match":"1f575-fe0f-1f3ff-2640-fe0f","uc_greedy":"1f575-1f3ff-2640","shortnames":[":woman_detective_dark_skin_tone:"],"category":"people"},":woman_elf_tone1:":{"uc_base":"1f9dd-1f3fb-2640","uc_output":"1f9dd-1f3fb-200d-2640-fe0f","uc_match":"1f9dd-1f3fb-2640-fe0f","uc_greedy":"1f9dd-1f3fb-2640","shortnames":[":woman_elf_light_skin_tone:"],"category":"people"},":woman_elf_tone2:":{"uc_base":"1f9dd-1f3fc-2640","uc_output":"1f9dd-1f3fc-200d-2640-fe0f","uc_match":"1f9dd-1f3fc-2640-fe0f","uc_greedy":"1f9dd-1f3fc-2640","shortnames":[":woman_elf_medium_light_skin_tone:"],"category":"people"},":woman_elf_tone3:":{"uc_base":"1f9dd-1f3fd-2640","uc_output":"1f9dd-1f3fd-200d-2640-fe0f","uc_match":"1f9dd-1f3fd-2640-fe0f","uc_greedy":"1f9dd-1f3fd-2640","shortnames":[":woman_elf_medium_skin_tone:"],"category":"people"},":woman_elf_tone4:":{"uc_base":"1f9dd-1f3fe-2640","uc_output":"1f9dd-1f3fe-200d-2640-fe0f","uc_match":"1f9dd-1f3fe-2640-fe0f","uc_greedy":"1f9dd-1f3fe-2640","shortnames":[":woman_elf_medium_dark_skin_tone:"],"category":"people"},":woman_elf_tone5:":{"uc_base":"1f9dd-1f3ff-2640","uc_output":"1f9dd-1f3ff-200d-2640-fe0f","uc_match":"1f9dd-1f3ff-2640-fe0f","uc_greedy":"1f9dd-1f3ff-2640","shortnames":[":woman_elf_dark_skin_tone:"],"category":"people"},":woman_facepalming_tone1:":{"uc_base":"1f926-1f3fb-2640","uc_output":"1f926-1f3fb-200d-2640-fe0f","uc_match":"1f926-1f3fb-2640-fe0f","uc_greedy":"1f926-1f3fb-2640","shortnames":[":woman_facepalming_light_skin_tone:"],"category":"people"},":woman_facepalming_tone2:":{"uc_base":"1f926-1f3fc-2640","uc_output":"1f926-1f3fc-200d-2640-fe0f","uc_match":"1f926-1f3fc-2640-fe0f","uc_greedy":"1f926-1f3fc-2640","shortnames":[":woman_facepalming_medium_light_skin_tone:"],"category":"people"},":woman_facepalming_tone3:":{"uc_base":"1f926-1f3fd-2640","uc_output":"1f926-1f3fd-200d-2640-fe0f","uc_match":"1f926-1f3fd-2640-fe0f","uc_greedy":"1f926-1f3fd-2640","shortnames":[":woman_facepalming_medium_skin_tone:"],"category":"people"},":woman_facepalming_tone4:":{"uc_base":"1f926-1f3fe-2640","uc_output":"1f926-1f3fe-200d-2640-fe0f","uc_match":"1f926-1f3fe-2640-fe0f","uc_greedy":"1f926-1f3fe-2640","shortnames":[":woman_facepalming_medium_dark_skin_tone:"],"category":"people"},":woman_facepalming_tone5:":{"uc_base":"1f926-1f3ff-2640","uc_output":"1f926-1f3ff-200d-2640-fe0f","uc_match":"1f926-1f3ff-2640-fe0f","uc_greedy":"1f926-1f3ff-2640","shortnames":[":woman_facepalming_dark_skin_tone:"],"category":"people"},":woman_fairy_tone1:":{"uc_base":"1f9da-1f3fb-2640","uc_output":"1f9da-1f3fb-200d-2640-fe0f","uc_match":"1f9da-1f3fb-2640-fe0f","uc_greedy":"1f9da-1f3fb-2640","shortnames":[":woman_fairy_light_skin_tone:"],"category":"people"},":woman_fairy_tone2:":{"uc_base":"1f9da-1f3fc-2640","uc_output":"1f9da-1f3fc-200d-2640-fe0f","uc_match":"1f9da-1f3fc-2640-fe0f","uc_greedy":"1f9da-1f3fc-2640","shortnames":[":woman_fairy_medium_light_skin_tone:"],"category":"people"},":woman_fairy_tone3:":{"uc_base":"1f9da-1f3fd-2640","uc_output":"1f9da-1f3fd-200d-2640-fe0f","uc_match":"1f9da-1f3fd-2640-fe0f","uc_greedy":"1f9da-1f3fd-2640","shortnames":[":woman_fairy_medium_skin_tone:"],"category":"people"},":woman_fairy_tone4:":{"uc_base":"1f9da-1f3fe-2640","uc_output":"1f9da-1f3fe-200d-2640-fe0f","uc_match":"1f9da-1f3fe-2640-fe0f","uc_greedy":"1f9da-1f3fe-2640","shortnames":[":woman_fairy_medium_dark_skin_tone:"],"category":"people"},":woman_fairy_tone5:":{"uc_base":"1f9da-1f3ff-2640","uc_output":"1f9da-1f3ff-200d-2640-fe0f","uc_match":"1f9da-1f3ff-2640-fe0f","uc_greedy":"1f9da-1f3ff-2640","shortnames":[":woman_fairy_dark_skin_tone:"],"category":"people"},":woman_frowning_tone1:":{"uc_base":"1f64d-1f3fb-2640","uc_output":"1f64d-1f3fb-200d-2640-fe0f","uc_match":"1f64d-1f3fb-2640-fe0f","uc_greedy":"1f64d-1f3fb-2640","shortnames":[":woman_frowning_light_skin_tone:"],"category":"people"},":woman_frowning_tone2:":{"uc_base":"1f64d-1f3fc-2640","uc_output":"1f64d-1f3fc-200d-2640-fe0f","uc_match":"1f64d-1f3fc-2640-fe0f","uc_greedy":"1f64d-1f3fc-2640","shortnames":[":woman_frowning_medium_light_skin_tone:"],"category":"people"},":woman_frowning_tone3:":{"uc_base":"1f64d-1f3fd-2640","uc_output":"1f64d-1f3fd-200d-2640-fe0f","uc_match":"1f64d-1f3fd-2640-fe0f","uc_greedy":"1f64d-1f3fd-2640","shortnames":[":woman_frowning_medium_skin_tone:"],"category":"people"},":woman_frowning_tone4:":{"uc_base":"1f64d-1f3fe-2640","uc_output":"1f64d-1f3fe-200d-2640-fe0f","uc_match":"1f64d-1f3fe-2640-fe0f","uc_greedy":"1f64d-1f3fe-2640","shortnames":[":woman_frowning_medium_dark_skin_tone:"],"category":"people"},":woman_frowning_tone5:":{"uc_base":"1f64d-1f3ff-2640","uc_output":"1f64d-1f3ff-200d-2640-fe0f","uc_match":"1f64d-1f3ff-2640-fe0f","uc_greedy":"1f64d-1f3ff-2640","shortnames":[":woman_frowning_dark_skin_tone:"],"category":"people"},":woman_gesturing_no_tone1:":{"uc_base":"1f645-1f3fb-2640","uc_output":"1f645-1f3fb-200d-2640-fe0f","uc_match":"1f645-1f3fb-2640-fe0f","uc_greedy":"1f645-1f3fb-2640","shortnames":[":woman_gesturing_no_light_skin_tone:"],"category":"people"},":woman_gesturing_no_tone2:":{"uc_base":"1f645-1f3fc-2640","uc_output":"1f645-1f3fc-200d-2640-fe0f","uc_match":"1f645-1f3fc-2640-fe0f","uc_greedy":"1f645-1f3fc-2640","shortnames":[":woman_gesturing_no_medium_light_skin_tone:"],"category":"people"},":woman_gesturing_no_tone3:":{"uc_base":"1f645-1f3fd-2640","uc_output":"1f645-1f3fd-200d-2640-fe0f","uc_match":"1f645-1f3fd-2640-fe0f","uc_greedy":"1f645-1f3fd-2640","shortnames":[":woman_gesturing_no_medium_skin_tone:"],"category":"people"},":woman_gesturing_no_tone4:":{"uc_base":"1f645-1f3fe-2640","uc_output":"1f645-1f3fe-200d-2640-fe0f","uc_match":"1f645-1f3fe-2640-fe0f","uc_greedy":"1f645-1f3fe-2640","shortnames":[":woman_gesturing_no_medium_dark_skin_tone:"],"category":"people"},":woman_gesturing_no_tone5:":{"uc_base":"1f645-1f3ff-2640","uc_output":"1f645-1f3ff-200d-2640-fe0f","uc_match":"1f645-1f3ff-2640-fe0f","uc_greedy":"1f645-1f3ff-2640","shortnames":[":woman_gesturing_no_dark_skin_tone:"],"category":"people"},":woman_gesturing_ok_tone1:":{"uc_base":"1f646-1f3fb-2640","uc_output":"1f646-1f3fb-200d-2640-fe0f","uc_match":"1f646-1f3fb-2640-fe0f","uc_greedy":"1f646-1f3fb-2640","shortnames":[":woman_gesturing_ok_light_skin_tone:"],"category":"people"},":woman_gesturing_ok_tone2:":{"uc_base":"1f646-1f3fc-2640","uc_output":"1f646-1f3fc-200d-2640-fe0f","uc_match":"1f646-1f3fc-2640-fe0f","uc_greedy":"1f646-1f3fc-2640","shortnames":[":woman_gesturing_ok_medium_light_skin_tone:"],"category":"people"},":woman_gesturing_ok_tone3:":{"uc_base":"1f646-1f3fd-2640","uc_output":"1f646-1f3fd-200d-2640-fe0f","uc_match":"1f646-1f3fd-2640-fe0f","uc_greedy":"1f646-1f3fd-2640","shortnames":[":woman_gesturing_ok_medium_skin_tone:"],"category":"people"},":woman_gesturing_ok_tone4:":{"uc_base":"1f646-1f3fe-2640","uc_output":"1f646-1f3fe-200d-2640-fe0f","uc_match":"1f646-1f3fe-2640-fe0f","uc_greedy":"1f646-1f3fe-2640","shortnames":[":woman_gesturing_ok_medium_dark_skin_tone:"],"category":"people"},":woman_gesturing_ok_tone5:":{"uc_base":"1f646-1f3ff-2640","uc_output":"1f646-1f3ff-200d-2640-fe0f","uc_match":"1f646-1f3ff-2640-fe0f","uc_greedy":"1f646-1f3ff-2640","shortnames":[":woman_gesturing_ok_dark_skin_tone:"],"category":"people"},":woman_getting_face_massage_tone1:":{"uc_base":"1f486-1f3fb-2640","uc_output":"1f486-1f3fb-200d-2640-fe0f","uc_match":"1f486-1f3fb-2640-fe0f","uc_greedy":"1f486-1f3fb-2640","shortnames":[":woman_getting_face_massage_light_skin_tone:"],"category":"people"},":woman_getting_face_massage_tone2:":{"uc_base":"1f486-1f3fc-2640","uc_output":"1f486-1f3fc-200d-2640-fe0f","uc_match":"1f486-1f3fc-2640-fe0f","uc_greedy":"1f486-1f3fc-2640","shortnames":[":woman_getting_face_massage_medium_light_skin_tone:"],"category":"people"},":woman_getting_face_massage_tone3:":{"uc_base":"1f486-1f3fd-2640","uc_output":"1f486-1f3fd-200d-2640-fe0f","uc_match":"1f486-1f3fd-2640-fe0f","uc_greedy":"1f486-1f3fd-2640","shortnames":[":woman_getting_face_massage_medium_skin_tone:"],"category":"people"},":woman_getting_face_massage_tone4:":{"uc_base":"1f486-1f3fe-2640","uc_output":"1f486-1f3fe-200d-2640-fe0f","uc_match":"1f486-1f3fe-2640-fe0f","uc_greedy":"1f486-1f3fe-2640","shortnames":[":woman_getting_face_massage_medium_dark_skin_tone:"],"category":"people"},":woman_getting_face_massage_tone5:":{"uc_base":"1f486-1f3ff-2640","uc_output":"1f486-1f3ff-200d-2640-fe0f","uc_match":"1f486-1f3ff-2640-fe0f","uc_greedy":"1f486-1f3ff-2640","shortnames":[":woman_getting_face_massage_dark_skin_tone:"],"category":"people"},":woman_getting_haircut_tone1:":{"uc_base":"1f487-1f3fb-2640","uc_output":"1f487-1f3fb-200d-2640-fe0f","uc_match":"1f487-1f3fb-2640-fe0f","uc_greedy":"1f487-1f3fb-2640","shortnames":[":woman_getting_haircut_light_skin_tone:"],"category":"people"},":woman_getting_haircut_tone2:":{"uc_base":"1f487-1f3fc-2640","uc_output":"1f487-1f3fc-200d-2640-fe0f","uc_match":"1f487-1f3fc-2640-fe0f","uc_greedy":"1f487-1f3fc-2640","shortnames":[":woman_getting_haircut_medium_light_skin_tone:"],"category":"people"},":woman_getting_haircut_tone3:":{"uc_base":"1f487-1f3fd-2640","uc_output":"1f487-1f3fd-200d-2640-fe0f","uc_match":"1f487-1f3fd-2640-fe0f","uc_greedy":"1f487-1f3fd-2640","shortnames":[":woman_getting_haircut_medium_skin_tone:"],"category":"people"},":woman_getting_haircut_tone4:":{"uc_base":"1f487-1f3fe-2640","uc_output":"1f487-1f3fe-200d-2640-fe0f","uc_match":"1f487-1f3fe-2640-fe0f","uc_greedy":"1f487-1f3fe-2640","shortnames":[":woman_getting_haircut_medium_dark_skin_tone:"],"category":"people"},":woman_getting_haircut_tone5:":{"uc_base":"1f487-1f3ff-2640","uc_output":"1f487-1f3ff-200d-2640-fe0f","uc_match":"1f487-1f3ff-2640-fe0f","uc_greedy":"1f487-1f3ff-2640","shortnames":[":woman_getting_haircut_dark_skin_tone:"],"category":"people"},":woman_golfing_tone1:":{"uc_base":"1f3cc-1f3fb-2640","uc_output":"1f3cc-1f3fb-200d-2640-fe0f","uc_match":"1f3cc-fe0f-1f3fb-2640-fe0f","uc_greedy":"1f3cc-1f3fb-2640","shortnames":[":woman_golfing_light_skin_tone:"],"category":"activity"},":woman_golfing_tone2:":{"uc_base":"1f3cc-1f3fc-2640","uc_output":"1f3cc-1f3fc-200d-2640-fe0f","uc_match":"1f3cc-fe0f-1f3fc-2640-fe0f","uc_greedy":"1f3cc-1f3fc-2640","shortnames":[":woman_golfing_medium_light_skin_tone:"],"category":"activity"},":woman_golfing_tone3:":{"uc_base":"1f3cc-1f3fd-2640","uc_output":"1f3cc-1f3fd-200d-2640-fe0f","uc_match":"1f3cc-fe0f-1f3fd-2640-fe0f","uc_greedy":"1f3cc-1f3fd-2640","shortnames":[":woman_golfing_medium_skin_tone:"],"category":"activity"},":woman_golfing_tone4:":{"uc_base":"1f3cc-1f3fe-2640","uc_output":"1f3cc-1f3fe-200d-2640-fe0f","uc_match":"1f3cc-fe0f-1f3fe-2640-fe0f","uc_greedy":"1f3cc-1f3fe-2640","shortnames":[":woman_golfing_medium_dark_skin_tone:"],"category":"activity"},":woman_golfing_tone5:":{"uc_base":"1f3cc-1f3ff-2640","uc_output":"1f3cc-1f3ff-200d-2640-fe0f","uc_match":"1f3cc-fe0f-1f3ff-2640-fe0f","uc_greedy":"1f3cc-1f3ff-2640","shortnames":[":woman_golfing_dark_skin_tone:"],"category":"activity"},":woman_guard_tone1:":{"uc_base":"1f482-1f3fb-2640","uc_output":"1f482-1f3fb-200d-2640-fe0f","uc_match":"1f482-1f3fb-2640-fe0f","uc_greedy":"1f482-1f3fb-2640","shortnames":[":woman_guard_light_skin_tone:"],"category":"people"},":woman_guard_tone2:":{"uc_base":"1f482-1f3fc-2640","uc_output":"1f482-1f3fc-200d-2640-fe0f","uc_match":"1f482-1f3fc-2640-fe0f","uc_greedy":"1f482-1f3fc-2640","shortnames":[":woman_guard_medium_light_skin_tone:"],"category":"people"},":woman_guard_tone3:":{"uc_base":"1f482-1f3fd-2640","uc_output":"1f482-1f3fd-200d-2640-fe0f","uc_match":"1f482-1f3fd-2640-fe0f","uc_greedy":"1f482-1f3fd-2640","shortnames":[":woman_guard_medium_skin_tone:"],"category":"people"},":woman_guard_tone4:":{"uc_base":"1f482-1f3fe-2640","uc_output":"1f482-1f3fe-200d-2640-fe0f","uc_match":"1f482-1f3fe-2640-fe0f","uc_greedy":"1f482-1f3fe-2640","shortnames":[":woman_guard_medium_dark_skin_tone:"],"category":"people"},":woman_guard_tone5:":{"uc_base":"1f482-1f3ff-2640","uc_output":"1f482-1f3ff-200d-2640-fe0f","uc_match":"1f482-1f3ff-2640-fe0f","uc_greedy":"1f482-1f3ff-2640","shortnames":[":woman_guard_dark_skin_tone:"],"category":"people"},":woman_health_worker_tone1:":{"uc_base":"1f469-1f3fb-2695","uc_output":"1f469-1f3fb-200d-2695-fe0f","uc_match":"1f469-1f3fb-2695-fe0f","uc_greedy":"1f469-1f3fb-2695","shortnames":[":woman_health_worker_light_skin_tone:"],"category":"people"},":woman_health_worker_tone2:":{"uc_base":"1f469-1f3fc-2695","uc_output":"1f469-1f3fc-200d-2695-fe0f","uc_match":"1f469-1f3fc-2695-fe0f","uc_greedy":"1f469-1f3fc-2695","shortnames":[":woman_health_worker_medium_light_skin_tone:"],"category":"people"},":woman_health_worker_tone3:":{"uc_base":"1f469-1f3fd-2695","uc_output":"1f469-1f3fd-200d-2695-fe0f","uc_match":"1f469-1f3fd-2695-fe0f","uc_greedy":"1f469-1f3fd-2695","shortnames":[":woman_health_worker_medium_skin_tone:"],"category":"people"},":woman_health_worker_tone4:":{"uc_base":"1f469-1f3fe-2695","uc_output":"1f469-1f3fe-200d-2695-fe0f","uc_match":"1f469-1f3fe-2695-fe0f","uc_greedy":"1f469-1f3fe-2695","shortnames":[":woman_health_worker_medium_dark_skin_tone:"],"category":"people"},":woman_health_worker_tone5:":{"uc_base":"1f469-1f3ff-2695","uc_output":"1f469-1f3ff-200d-2695-fe0f","uc_match":"1f469-1f3ff-2695-fe0f","uc_greedy":"1f469-1f3ff-2695","shortnames":[":woman_health_worker_dark_skin_tone:"],"category":"people"},":woman_in_lotus_position_tone1:":{"uc_base":"1f9d8-1f3fb-2640","uc_output":"1f9d8-1f3fb-200d-2640-fe0f","uc_match":"1f9d8-1f3fb-2640-fe0f","uc_greedy":"1f9d8-1f3fb-2640","shortnames":[":woman_in_lotus_position_light_skin_tone:"],"category":"activity"},":woman_in_lotus_position_tone2:":{"uc_base":"1f9d8-1f3fc-2640","uc_output":"1f9d8-1f3fc-200d-2640-fe0f","uc_match":"1f9d8-1f3fc-2640-fe0f","uc_greedy":"1f9d8-1f3fc-2640","shortnames":[":woman_in_lotus_position_medium_light_skin_tone:"],"category":"activity"},":woman_in_lotus_position_tone3:":{"uc_base":"1f9d8-1f3fd-2640","uc_output":"1f9d8-1f3fd-200d-2640-fe0f","uc_match":"1f9d8-1f3fd-2640-fe0f","uc_greedy":"1f9d8-1f3fd-2640","shortnames":[":woman_in_lotus_position_medium_skin_tone:"],"category":"activity"},":woman_in_lotus_position_tone4:":{"uc_base":"1f9d8-1f3fe-2640","uc_output":"1f9d8-1f3fe-200d-2640-fe0f","uc_match":"1f9d8-1f3fe-2640-fe0f","uc_greedy":"1f9d8-1f3fe-2640","shortnames":[":woman_in_lotus_position_medium_dark_skin_tone:"],"category":"activity"},":woman_in_lotus_position_tone5:":{"uc_base":"1f9d8-1f3ff-2640","uc_output":"1f9d8-1f3ff-200d-2640-fe0f","uc_match":"1f9d8-1f3ff-2640-fe0f","uc_greedy":"1f9d8-1f3ff-2640","shortnames":[":woman_in_lotus_position_dark_skin_tone:"],"category":"activity"},":woman_in_steamy_room_tone1:":{"uc_base":"1f9d6-1f3fb-2640","uc_output":"1f9d6-1f3fb-200d-2640-fe0f","uc_match":"1f9d6-1f3fb-2640-fe0f","uc_greedy":"1f9d6-1f3fb-2640","shortnames":[":woman_in_steamy_room_light_skin_tone:"],"category":"activity"},":woman_in_steamy_room_tone2:":{"uc_base":"1f9d6-1f3fc-2640","uc_output":"1f9d6-1f3fc-200d-2640-fe0f","uc_match":"1f9d6-1f3fc-2640-fe0f","uc_greedy":"1f9d6-1f3fc-2640","shortnames":[":woman_in_steamy_room_medium_light_skin_tone:"],"category":"activity"},":woman_in_steamy_room_tone3:":{"uc_base":"1f9d6-1f3fd-2640","uc_output":"1f9d6-1f3fd-200d-2640-fe0f","uc_match":"1f9d6-1f3fd-2640-fe0f","uc_greedy":"1f9d6-1f3fd-2640","shortnames":[":woman_in_steamy_room_medium_skin_tone:"],"category":"activity"},":woman_in_steamy_room_tone4:":{"uc_base":"1f9d6-1f3fe-2640","uc_output":"1f9d6-1f3fe-200d-2640-fe0f","uc_match":"1f9d6-1f3fe-2640-fe0f","uc_greedy":"1f9d6-1f3fe-2640","shortnames":[":woman_in_steamy_room_medium_dark_skin_tone:"],"category":"activity"},":woman_in_steamy_room_tone5:":{"uc_base":"1f9d6-1f3ff-2640","uc_output":"1f9d6-1f3ff-200d-2640-fe0f","uc_match":"1f9d6-1f3ff-2640-fe0f","uc_greedy":"1f9d6-1f3ff-2640","shortnames":[":woman_in_steamy_room_dark_skin_tone:"],"category":"activity"},":woman_judge_tone1:":{"uc_base":"1f469-1f3fb-2696","uc_output":"1f469-1f3fb-200d-2696-fe0f","uc_match":"1f469-1f3fb-2696-fe0f","uc_greedy":"1f469-1f3fb-2696","shortnames":[":woman_judge_light_skin_tone:"],"category":"people"},":woman_judge_tone2:":{"uc_base":"1f469-1f3fc-2696","uc_output":"1f469-1f3fc-200d-2696-fe0f","uc_match":"1f469-1f3fc-2696-fe0f","uc_greedy":"1f469-1f3fc-2696","shortnames":[":woman_judge_medium_light_skin_tone:"],"category":"people"},":woman_judge_tone3:":{"uc_base":"1f469-1f3fd-2696","uc_output":"1f469-1f3fd-200d-2696-fe0f","uc_match":"1f469-1f3fd-2696-fe0f","uc_greedy":"1f469-1f3fd-2696","shortnames":[":woman_judge_medium_skin_tone:"],"category":"people"},":woman_judge_tone4:":{"uc_base":"1f469-1f3fe-2696","uc_output":"1f469-1f3fe-200d-2696-fe0f","uc_match":"1f469-1f3fe-2696-fe0f","uc_greedy":"1f469-1f3fe-2696","shortnames":[":woman_judge_medium_dark_skin_tone:"],"category":"people"},":woman_judge_tone5:":{"uc_base":"1f469-1f3ff-2696","uc_output":"1f469-1f3ff-200d-2696-fe0f","uc_match":"1f469-1f3ff-2696-fe0f","uc_greedy":"1f469-1f3ff-2696","shortnames":[":woman_judge_dark_skin_tone:"],"category":"people"},":woman_juggling_tone1:":{"uc_base":"1f939-1f3fb-2640","uc_output":"1f939-1f3fb-200d-2640-fe0f","uc_match":"1f939-1f3fb-2640-fe0f","uc_greedy":"1f939-1f3fb-2640","shortnames":[":woman_juggling_light_skin_tone:"],"category":"activity"},":woman_juggling_tone2:":{"uc_base":"1f939-1f3fc-2640","uc_output":"1f939-1f3fc-200d-2640-fe0f","uc_match":"1f939-1f3fc-2640-fe0f","uc_greedy":"1f939-1f3fc-2640","shortnames":[":woman_juggling_medium_light_skin_tone:"],"category":"activity"},":woman_juggling_tone3:":{"uc_base":"1f939-1f3fd-2640","uc_output":"1f939-1f3fd-200d-2640-fe0f","uc_match":"1f939-1f3fd-2640-fe0f","uc_greedy":"1f939-1f3fd-2640","shortnames":[":woman_juggling_medium_skin_tone:"],"category":"activity"},":woman_juggling_tone4:":{"uc_base":"1f939-1f3fe-2640","uc_output":"1f939-1f3fe-200d-2640-fe0f","uc_match":"1f939-1f3fe-2640-fe0f","uc_greedy":"1f939-1f3fe-2640","shortnames":[":woman_juggling_medium_dark_skin_tone:"],"category":"activity"},":woman_juggling_tone5:":{"uc_base":"1f939-1f3ff-2640","uc_output":"1f939-1f3ff-200d-2640-fe0f","uc_match":"1f939-1f3ff-2640-fe0f","uc_greedy":"1f939-1f3ff-2640","shortnames":[":woman_juggling_dark_skin_tone:"],"category":"activity"},":woman_lifting_weights_tone1:":{"uc_base":"1f3cb-1f3fb-2640","uc_output":"1f3cb-1f3fb-200d-2640-fe0f","uc_match":"1f3cb-fe0f-1f3fb-2640-fe0f","uc_greedy":"1f3cb-1f3fb-2640","shortnames":[":woman_lifting_weights_light_skin_tone:"],"category":"activity"},":woman_lifting_weights_tone2:":{"uc_base":"1f3cb-1f3fc-2640","uc_output":"1f3cb-1f3fc-200d-2640-fe0f","uc_match":"1f3cb-fe0f-1f3fc-2640-fe0f","uc_greedy":"1f3cb-1f3fc-2640","shortnames":[":woman_lifting_weights_medium_light_skin_tone:"],"category":"activity"},":woman_lifting_weights_tone3:":{"uc_base":"1f3cb-1f3fd-2640","uc_output":"1f3cb-1f3fd-200d-2640-fe0f","uc_match":"1f3cb-fe0f-1f3fd-2640-fe0f","uc_greedy":"1f3cb-1f3fd-2640","shortnames":[":woman_lifting_weights_medium_skin_tone:"],"category":"activity"},":woman_lifting_weights_tone4:":{"uc_base":"1f3cb-1f3fe-2640","uc_output":"1f3cb-1f3fe-200d-2640-fe0f","uc_match":"1f3cb-fe0f-1f3fe-2640-fe0f","uc_greedy":"1f3cb-1f3fe-2640","shortnames":[":woman_lifting_weights_medium_dark_skin_tone:"],"category":"activity"},":woman_lifting_weights_tone5:":{"uc_base":"1f3cb-1f3ff-2640","uc_output":"1f3cb-1f3ff-200d-2640-fe0f","uc_match":"1f3cb-fe0f-1f3ff-2640-fe0f","uc_greedy":"1f3cb-1f3ff-2640","shortnames":[":woman_lifting_weights_dark_skin_tone:"],"category":"activity"},":woman_mage_tone1:":{"uc_base":"1f9d9-1f3fb-2640","uc_output":"1f9d9-1f3fb-200d-2640-fe0f","uc_match":"1f9d9-1f3fb-2640-fe0f","uc_greedy":"1f9d9-1f3fb-2640","shortnames":[":woman_mage_light_skin_tone:"],"category":"people"},":woman_mage_tone2:":{"uc_base":"1f9d9-1f3fc-2640","uc_output":"1f9d9-1f3fc-200d-2640-fe0f","uc_match":"1f9d9-1f3fc-2640-fe0f","uc_greedy":"1f9d9-1f3fc-2640","shortnames":[":woman_mage_medium_light_skin_tone:"],"category":"people"},":woman_mage_tone3:":{"uc_base":"1f9d9-1f3fd-2640","uc_output":"1f9d9-1f3fd-200d-2640-fe0f","uc_match":"1f9d9-1f3fd-2640-fe0f","uc_greedy":"1f9d9-1f3fd-2640","shortnames":[":woman_mage_medium_skin_tone:"],"category":"people"},":woman_mage_tone4:":{"uc_base":"1f9d9-1f3fe-2640","uc_output":"1f9d9-1f3fe-200d-2640-fe0f","uc_match":"1f9d9-1f3fe-2640-fe0f","uc_greedy":"1f9d9-1f3fe-2640","shortnames":[":woman_mage_medium_dark_skin_tone:"],"category":"people"},":woman_mage_tone5:":{"uc_base":"1f9d9-1f3ff-2640","uc_output":"1f9d9-1f3ff-200d-2640-fe0f","uc_match":"1f9d9-1f3ff-2640-fe0f","uc_greedy":"1f9d9-1f3ff-2640","shortnames":[":woman_mage_dark_skin_tone:"],"category":"people"},":woman_mountain_biking_tone1:":{"uc_base":"1f6b5-1f3fb-2640","uc_output":"1f6b5-1f3fb-200d-2640-fe0f","uc_match":"1f6b5-1f3fb-2640-fe0f","uc_greedy":"1f6b5-1f3fb-2640","shortnames":[":woman_mountain_biking_light_skin_tone:"],"category":"activity"},":woman_mountain_biking_tone2:":{"uc_base":"1f6b5-1f3fc-2640","uc_output":"1f6b5-1f3fc-200d-2640-fe0f","uc_match":"1f6b5-1f3fc-2640-fe0f","uc_greedy":"1f6b5-1f3fc-2640","shortnames":[":woman_mountain_biking_medium_light_skin_tone:"],"category":"activity"},":woman_mountain_biking_tone3:":{"uc_base":"1f6b5-1f3fd-2640","uc_output":"1f6b5-1f3fd-200d-2640-fe0f","uc_match":"1f6b5-1f3fd-2640-fe0f","uc_greedy":"1f6b5-1f3fd-2640","shortnames":[":woman_mountain_biking_medium_skin_tone:"],"category":"activity"},":woman_mountain_biking_tone4:":{"uc_base":"1f6b5-1f3fe-2640","uc_output":"1f6b5-1f3fe-200d-2640-fe0f","uc_match":"1f6b5-1f3fe-2640-fe0f","uc_greedy":"1f6b5-1f3fe-2640","shortnames":[":woman_mountain_biking_medium_dark_skin_tone:"],"category":"activity"},":woman_mountain_biking_tone5:":{"uc_base":"1f6b5-1f3ff-2640","uc_output":"1f6b5-1f3ff-200d-2640-fe0f","uc_match":"1f6b5-1f3ff-2640-fe0f","uc_greedy":"1f6b5-1f3ff-2640","shortnames":[":woman_mountain_biking_dark_skin_tone:"],"category":"activity"},":woman_pilot_tone1:":{"uc_base":"1f469-1f3fb-2708","uc_output":"1f469-1f3fb-200d-2708-fe0f","uc_match":"1f469-1f3fb-2708-fe0f","uc_greedy":"1f469-1f3fb-2708","shortnames":[":woman_pilot_light_skin_tone:"],"category":"people"},":woman_pilot_tone2:":{"uc_base":"1f469-1f3fc-2708","uc_output":"1f469-1f3fc-200d-2708-fe0f","uc_match":"1f469-1f3fc-2708-fe0f","uc_greedy":"1f469-1f3fc-2708","shortnames":[":woman_pilot_medium_light_skin_tone:"],"category":"people"},":woman_pilot_tone3:":{"uc_base":"1f469-1f3fd-2708","uc_output":"1f469-1f3fd-200d-2708-fe0f","uc_match":"1f469-1f3fd-2708-fe0f","uc_greedy":"1f469-1f3fd-2708","shortnames":[":woman_pilot_medium_skin_tone:"],"category":"people"},":woman_pilot_tone4:":{"uc_base":"1f469-1f3fe-2708","uc_output":"1f469-1f3fe-200d-2708-fe0f","uc_match":"1f469-1f3fe-2708-fe0f","uc_greedy":"1f469-1f3fe-2708","shortnames":[":woman_pilot_medium_dark_skin_tone:"],"category":"people"},":woman_pilot_tone5:":{"uc_base":"1f469-1f3ff-2708","uc_output":"1f469-1f3ff-200d-2708-fe0f","uc_match":"1f469-1f3ff-2708-fe0f","uc_greedy":"1f469-1f3ff-2708","shortnames":[":woman_pilot_dark_skin_tone:"],"category":"people"},":woman_playing_handball_tone1:":{"uc_base":"1f93e-1f3fb-2640","uc_output":"1f93e-1f3fb-200d-2640-fe0f","uc_match":"1f93e-1f3fb-2640-fe0f","uc_greedy":"1f93e-1f3fb-2640","shortnames":[":woman_playing_handball_light_skin_tone:"],"category":"activity"},":woman_playing_handball_tone2:":{"uc_base":"1f93e-1f3fc-2640","uc_output":"1f93e-1f3fc-200d-2640-fe0f","uc_match":"1f93e-1f3fc-2640-fe0f","uc_greedy":"1f93e-1f3fc-2640","shortnames":[":woman_playing_handball_medium_light_skin_tone:"],"category":"activity"},":woman_playing_handball_tone3:":{"uc_base":"1f93e-1f3fd-2640","uc_output":"1f93e-1f3fd-200d-2640-fe0f","uc_match":"1f93e-1f3fd-2640-fe0f","uc_greedy":"1f93e-1f3fd-2640","shortnames":[":woman_playing_handball_medium_skin_tone:"],"category":"activity"},":woman_playing_handball_tone4:":{"uc_base":"1f93e-1f3fe-2640","uc_output":"1f93e-1f3fe-200d-2640-fe0f","uc_match":"1f93e-1f3fe-2640-fe0f","uc_greedy":"1f93e-1f3fe-2640","shortnames":[":woman_playing_handball_medium_dark_skin_tone:"],"category":"activity"},":woman_playing_handball_tone5:":{"uc_base":"1f93e-1f3ff-2640","uc_output":"1f93e-1f3ff-200d-2640-fe0f","uc_match":"1f93e-1f3ff-2640-fe0f","uc_greedy":"1f93e-1f3ff-2640","shortnames":[":woman_playing_handball_dark_skin_tone:"],"category":"activity"},":woman_playing_water_polo_tone1:":{"uc_base":"1f93d-1f3fb-2640","uc_output":"1f93d-1f3fb-200d-2640-fe0f","uc_match":"1f93d-1f3fb-2640-fe0f","uc_greedy":"1f93d-1f3fb-2640","shortnames":[":woman_playing_water_polo_light_skin_tone:"],"category":"activity"},":woman_playing_water_polo_tone2:":{"uc_base":"1f93d-1f3fc-2640","uc_output":"1f93d-1f3fc-200d-2640-fe0f","uc_match":"1f93d-1f3fc-2640-fe0f","uc_greedy":"1f93d-1f3fc-2640","shortnames":[":woman_playing_water_polo_medium_light_skin_tone:"],"category":"activity"},":woman_playing_water_polo_tone3:":{"uc_base":"1f93d-1f3fd-2640","uc_output":"1f93d-1f3fd-200d-2640-fe0f","uc_match":"1f93d-1f3fd-2640-fe0f","uc_greedy":"1f93d-1f3fd-2640","shortnames":[":woman_playing_water_polo_medium_skin_tone:"],"category":"activity"},":woman_playing_water_polo_tone4:":{"uc_base":"1f93d-1f3fe-2640","uc_output":"1f93d-1f3fe-200d-2640-fe0f","uc_match":"1f93d-1f3fe-2640-fe0f","uc_greedy":"1f93d-1f3fe-2640","shortnames":[":woman_playing_water_polo_medium_dark_skin_tone:"],"category":"activity"},":woman_playing_water_polo_tone5:":{"uc_base":"1f93d-1f3ff-2640","uc_output":"1f93d-1f3ff-200d-2640-fe0f","uc_match":"1f93d-1f3ff-2640-fe0f","uc_greedy":"1f93d-1f3ff-2640","shortnames":[":woman_playing_water_polo_dark_skin_tone:"],"category":"activity"},":woman_police_officer_tone1:":{"uc_base":"1f46e-1f3fb-2640","uc_output":"1f46e-1f3fb-200d-2640-fe0f","uc_match":"1f46e-1f3fb-2640-fe0f","uc_greedy":"1f46e-1f3fb-2640","shortnames":[":woman_police_officer_light_skin_tone:"],"category":"people"},":woman_police_officer_tone2:":{"uc_base":"1f46e-1f3fc-2640","uc_output":"1f46e-1f3fc-200d-2640-fe0f","uc_match":"1f46e-1f3fc-2640-fe0f","uc_greedy":"1f46e-1f3fc-2640","shortnames":[":woman_police_officer_medium_light_skin_tone:"],"category":"people"},":woman_police_officer_tone3:":{"uc_base":"1f46e-1f3fd-2640","uc_output":"1f46e-1f3fd-200d-2640-fe0f","uc_match":"1f46e-1f3fd-2640-fe0f","uc_greedy":"1f46e-1f3fd-2640","shortnames":[":woman_police_officer_medium_skin_tone:"],"category":"people"},":woman_police_officer_tone4:":{"uc_base":"1f46e-1f3fe-2640","uc_output":"1f46e-1f3fe-200d-2640-fe0f","uc_match":"1f46e-1f3fe-2640-fe0f","uc_greedy":"1f46e-1f3fe-2640","shortnames":[":woman_police_officer_medium_dark_skin_tone:"],"category":"people"},":woman_police_officer_tone5:":{"uc_base":"1f46e-1f3ff-2640","uc_output":"1f46e-1f3ff-200d-2640-fe0f","uc_match":"1f46e-1f3ff-2640-fe0f","uc_greedy":"1f46e-1f3ff-2640","shortnames":[":woman_police_officer_dark_skin_tone:"],"category":"people"},":woman_pouting_tone1:":{"uc_base":"1f64e-1f3fb-2640","uc_output":"1f64e-1f3fb-200d-2640-fe0f","uc_match":"1f64e-1f3fb-2640-fe0f","uc_greedy":"1f64e-1f3fb-2640","shortnames":[":woman_pouting_light_skin_tone:"],"category":"people"},":woman_pouting_tone2:":{"uc_base":"1f64e-1f3fc-2640","uc_output":"1f64e-1f3fc-200d-2640-fe0f","uc_match":"1f64e-1f3fc-2640-fe0f","uc_greedy":"1f64e-1f3fc-2640","shortnames":[":woman_pouting_medium_light_skin_tone:"],"category":"people"},":woman_pouting_tone3:":{"uc_base":"1f64e-1f3fd-2640","uc_output":"1f64e-1f3fd-200d-2640-fe0f","uc_match":"1f64e-1f3fd-2640-fe0f","uc_greedy":"1f64e-1f3fd-2640","shortnames":[":woman_pouting_medium_skin_tone:"],"category":"people"},":woman_pouting_tone4:":{"uc_base":"1f64e-1f3fe-2640","uc_output":"1f64e-1f3fe-200d-2640-fe0f","uc_match":"1f64e-1f3fe-2640-fe0f","uc_greedy":"1f64e-1f3fe-2640","shortnames":[":woman_pouting_medium_dark_skin_tone:"],"category":"people"},":woman_pouting_tone5:":{"uc_base":"1f64e-1f3ff-2640","uc_output":"1f64e-1f3ff-200d-2640-fe0f","uc_match":"1f64e-1f3ff-2640-fe0f","uc_greedy":"1f64e-1f3ff-2640","shortnames":[":woman_pouting_dark_skin_tone:"],"category":"people"},":woman_raising_hand_tone1:":{"uc_base":"1f64b-1f3fb-2640","uc_output":"1f64b-1f3fb-200d-2640-fe0f","uc_match":"1f64b-1f3fb-2640-fe0f","uc_greedy":"1f64b-1f3fb-2640","shortnames":[":woman_raising_hand_light_skin_tone:"],"category":"people"},":woman_raising_hand_tone2:":{"uc_base":"1f64b-1f3fc-2640","uc_output":"1f64b-1f3fc-200d-2640-fe0f","uc_match":"1f64b-1f3fc-2640-fe0f","uc_greedy":"1f64b-1f3fc-2640","shortnames":[":woman_raising_hand_medium_light_skin_tone:"],"category":"people"},":woman_raising_hand_tone3:":{"uc_base":"1f64b-1f3fd-2640","uc_output":"1f64b-1f3fd-200d-2640-fe0f","uc_match":"1f64b-1f3fd-2640-fe0f","uc_greedy":"1f64b-1f3fd-2640","shortnames":[":woman_raising_hand_medium_skin_tone:"],"category":"people"},":woman_raising_hand_tone4:":{"uc_base":"1f64b-1f3fe-2640","uc_output":"1f64b-1f3fe-200d-2640-fe0f","uc_match":"1f64b-1f3fe-2640-fe0f","uc_greedy":"1f64b-1f3fe-2640","shortnames":[":woman_raising_hand_medium_dark_skin_tone:"],"category":"people"},":woman_raising_hand_tone5:":{"uc_base":"1f64b-1f3ff-2640","uc_output":"1f64b-1f3ff-200d-2640-fe0f","uc_match":"1f64b-1f3ff-2640-fe0f","uc_greedy":"1f64b-1f3ff-2640","shortnames":[":woman_raising_hand_dark_skin_tone:"],"category":"people"},":woman_rowing_boat_tone1:":{"uc_base":"1f6a3-1f3fb-2640","uc_output":"1f6a3-1f3fb-200d-2640-fe0f","uc_match":"1f6a3-1f3fb-2640-fe0f","uc_greedy":"1f6a3-1f3fb-2640","shortnames":[":woman_rowing_boat_light_skin_tone:"],"category":"activity"},":woman_rowing_boat_tone2:":{"uc_base":"1f6a3-1f3fc-2640","uc_output":"1f6a3-1f3fc-200d-2640-fe0f","uc_match":"1f6a3-1f3fc-2640-fe0f","uc_greedy":"1f6a3-1f3fc-2640","shortnames":[":woman_rowing_boat_medium_light_skin_tone:"],"category":"activity"},":woman_rowing_boat_tone3:":{"uc_base":"1f6a3-1f3fd-2640","uc_output":"1f6a3-1f3fd-200d-2640-fe0f","uc_match":"1f6a3-1f3fd-2640-fe0f","uc_greedy":"1f6a3-1f3fd-2640","shortnames":[":woman_rowing_boat_medium_skin_tone:"],"category":"activity"},":woman_rowing_boat_tone4:":{"uc_base":"1f6a3-1f3fe-2640","uc_output":"1f6a3-1f3fe-200d-2640-fe0f","uc_match":"1f6a3-1f3fe-2640-fe0f","uc_greedy":"1f6a3-1f3fe-2640","shortnames":[":woman_rowing_boat_medium_dark_skin_tone:"],"category":"activity"},":woman_rowing_boat_tone5:":{"uc_base":"1f6a3-1f3ff-2640","uc_output":"1f6a3-1f3ff-200d-2640-fe0f","uc_match":"1f6a3-1f3ff-2640-fe0f","uc_greedy":"1f6a3-1f3ff-2640","shortnames":[":woman_rowing_boat_dark_skin_tone:"],"category":"activity"},":woman_running_tone1:":{"uc_base":"1f3c3-1f3fb-2640","uc_output":"1f3c3-1f3fb-200d-2640-fe0f","uc_match":"1f3c3-1f3fb-2640-fe0f","uc_greedy":"1f3c3-1f3fb-2640","shortnames":[":woman_running_light_skin_tone:"],"category":"people"},":woman_running_tone2:":{"uc_base":"1f3c3-1f3fc-2640","uc_output":"1f3c3-1f3fc-200d-2640-fe0f","uc_match":"1f3c3-1f3fc-2640-fe0f","uc_greedy":"1f3c3-1f3fc-2640","shortnames":[":woman_running_medium_light_skin_tone:"],"category":"people"},":woman_running_tone3:":{"uc_base":"1f3c3-1f3fd-2640","uc_output":"1f3c3-1f3fd-200d-2640-fe0f","uc_match":"1f3c3-1f3fd-2640-fe0f","uc_greedy":"1f3c3-1f3fd-2640","shortnames":[":woman_running_medium_skin_tone:"],"category":"people"},":woman_running_tone4:":{"uc_base":"1f3c3-1f3fe-2640","uc_output":"1f3c3-1f3fe-200d-2640-fe0f","uc_match":"1f3c3-1f3fe-2640-fe0f","uc_greedy":"1f3c3-1f3fe-2640","shortnames":[":woman_running_medium_dark_skin_tone:"],"category":"people"},":woman_running_tone5:":{"uc_base":"1f3c3-1f3ff-2640","uc_output":"1f3c3-1f3ff-200d-2640-fe0f","uc_match":"1f3c3-1f3ff-2640-fe0f","uc_greedy":"1f3c3-1f3ff-2640","shortnames":[":woman_running_dark_skin_tone:"],"category":"people"},":woman_shrugging_tone1:":{"uc_base":"1f937-1f3fb-2640","uc_output":"1f937-1f3fb-200d-2640-fe0f","uc_match":"1f937-1f3fb-2640-fe0f","uc_greedy":"1f937-1f3fb-2640","shortnames":[":woman_shrugging_light_skin_tone:"],"category":"people"},":woman_shrugging_tone2:":{"uc_base":"1f937-1f3fc-2640","uc_output":"1f937-1f3fc-200d-2640-fe0f","uc_match":"1f937-1f3fc-2640-fe0f","uc_greedy":"1f937-1f3fc-2640","shortnames":[":woman_shrugging_medium_light_skin_tone:"],"category":"people"},":woman_shrugging_tone3:":{"uc_base":"1f937-1f3fd-2640","uc_output":"1f937-1f3fd-200d-2640-fe0f","uc_match":"1f937-1f3fd-2640-fe0f","uc_greedy":"1f937-1f3fd-2640","shortnames":[":woman_shrugging_medium_skin_tone:"],"category":"people"},":woman_shrugging_tone4:":{"uc_base":"1f937-1f3fe-2640","uc_output":"1f937-1f3fe-200d-2640-fe0f","uc_match":"1f937-1f3fe-2640-fe0f","uc_greedy":"1f937-1f3fe-2640","shortnames":[":woman_shrugging_medium_dark_skin_tone:"],"category":"people"},":woman_shrugging_tone5:":{"uc_base":"1f937-1f3ff-2640","uc_output":"1f937-1f3ff-200d-2640-fe0f","uc_match":"1f937-1f3ff-2640-fe0f","uc_greedy":"1f937-1f3ff-2640","shortnames":[":woman_shrugging_dark_skin_tone:"],"category":"people"},":woman_surfing_tone1:":{"uc_base":"1f3c4-1f3fb-2640","uc_output":"1f3c4-1f3fb-200d-2640-fe0f","uc_match":"1f3c4-1f3fb-2640-fe0f","uc_greedy":"1f3c4-1f3fb-2640","shortnames":[":woman_surfing_light_skin_tone:"],"category":"activity"},":woman_surfing_tone2:":{"uc_base":"1f3c4-1f3fc-2640","uc_output":"1f3c4-1f3fc-200d-2640-fe0f","uc_match":"1f3c4-1f3fc-2640-fe0f","uc_greedy":"1f3c4-1f3fc-2640","shortnames":[":woman_surfing_medium_light_skin_tone:"],"category":"activity"},":woman_surfing_tone3:":{"uc_base":"1f3c4-1f3fd-2640","uc_output":"1f3c4-1f3fd-200d-2640-fe0f","uc_match":"1f3c4-1f3fd-2640-fe0f","uc_greedy":"1f3c4-1f3fd-2640","shortnames":[":woman_surfing_medium_skin_tone:"],"category":"activity"},":woman_surfing_tone4:":{"uc_base":"1f3c4-1f3fe-2640","uc_output":"1f3c4-1f3fe-200d-2640-fe0f","uc_match":"1f3c4-1f3fe-2640-fe0f","uc_greedy":"1f3c4-1f3fe-2640","shortnames":[":woman_surfing_medium_dark_skin_tone:"],"category":"activity"},":woman_surfing_tone5:":{"uc_base":"1f3c4-1f3ff-2640","uc_output":"1f3c4-1f3ff-200d-2640-fe0f","uc_match":"1f3c4-1f3ff-2640-fe0f","uc_greedy":"1f3c4-1f3ff-2640","shortnames":[":woman_surfing_dark_skin_tone:"],"category":"activity"},":woman_swimming_tone1:":{"uc_base":"1f3ca-1f3fb-2640","uc_output":"1f3ca-1f3fb-200d-2640-fe0f","uc_match":"1f3ca-1f3fb-2640-fe0f","uc_greedy":"1f3ca-1f3fb-2640","shortnames":[":woman_swimming_light_skin_tone:"],"category":"activity"},":woman_swimming_tone2:":{"uc_base":"1f3ca-1f3fc-2640","uc_output":"1f3ca-1f3fc-200d-2640-fe0f","uc_match":"1f3ca-1f3fc-2640-fe0f","uc_greedy":"1f3ca-1f3fc-2640","shortnames":[":woman_swimming_medium_light_skin_tone:"],"category":"activity"},":woman_swimming_tone3:":{"uc_base":"1f3ca-1f3fd-2640","uc_output":"1f3ca-1f3fd-200d-2640-fe0f","uc_match":"1f3ca-1f3fd-2640-fe0f","uc_greedy":"1f3ca-1f3fd-2640","shortnames":[":woman_swimming_medium_skin_tone:"],"category":"activity"},":woman_swimming_tone4:":{"uc_base":"1f3ca-1f3fe-2640","uc_output":"1f3ca-1f3fe-200d-2640-fe0f","uc_match":"1f3ca-1f3fe-2640-fe0f","uc_greedy":"1f3ca-1f3fe-2640","shortnames":[":woman_swimming_medium_dark_skin_tone:"],"category":"activity"},":woman_swimming_tone5:":{"uc_base":"1f3ca-1f3ff-2640","uc_output":"1f3ca-1f3ff-200d-2640-fe0f","uc_match":"1f3ca-1f3ff-2640-fe0f","uc_greedy":"1f3ca-1f3ff-2640","shortnames":[":woman_swimming_dark_skin_tone:"],"category":"activity"},":woman_tipping_hand_tone1:":{"uc_base":"1f481-1f3fb-2640","uc_output":"1f481-1f3fb-200d-2640-fe0f","uc_match":"1f481-1f3fb-2640-fe0f","uc_greedy":"1f481-1f3fb-2640","shortnames":[":woman_tipping_hand_light_skin_tone:"],"category":"people"},":woman_tipping_hand_tone2:":{"uc_base":"1f481-1f3fc-2640","uc_output":"1f481-1f3fc-200d-2640-fe0f","uc_match":"1f481-1f3fc-2640-fe0f","uc_greedy":"1f481-1f3fc-2640","shortnames":[":woman_tipping_hand_medium_light_skin_tone:"],"category":"people"},":woman_tipping_hand_tone3:":{"uc_base":"1f481-1f3fd-2640","uc_output":"1f481-1f3fd-200d-2640-fe0f","uc_match":"1f481-1f3fd-2640-fe0f","uc_greedy":"1f481-1f3fd-2640","shortnames":[":woman_tipping_hand_medium_skin_tone:"],"category":"people"},":woman_tipping_hand_tone4:":{"uc_base":"1f481-1f3fe-2640","uc_output":"1f481-1f3fe-200d-2640-fe0f","uc_match":"1f481-1f3fe-2640-fe0f","uc_greedy":"1f481-1f3fe-2640","shortnames":[":woman_tipping_hand_medium_dark_skin_tone:"],"category":"people"},":woman_tipping_hand_tone5:":{"uc_base":"1f481-1f3ff-2640","uc_output":"1f481-1f3ff-200d-2640-fe0f","uc_match":"1f481-1f3ff-2640-fe0f","uc_greedy":"1f481-1f3ff-2640","shortnames":[":woman_tipping_hand_dark_skin_tone:"],"category":"people"},":woman_vampire_tone1:":{"uc_base":"1f9db-1f3fb-2640","uc_output":"1f9db-1f3fb-200d-2640-fe0f","uc_match":"1f9db-1f3fb-2640-fe0f","uc_greedy":"1f9db-1f3fb-2640","shortnames":[":woman_vampire_light_skin_tone:"],"category":"people"},":woman_vampire_tone2:":{"uc_base":"1f9db-1f3fc-2640","uc_output":"1f9db-1f3fc-200d-2640-fe0f","uc_match":"1f9db-1f3fc-2640-fe0f","uc_greedy":"1f9db-1f3fc-2640","shortnames":[":woman_vampire_medium_light_skin_tone:"],"category":"people"},":woman_vampire_tone3:":{"uc_base":"1f9db-1f3fd-2640","uc_output":"1f9db-1f3fd-200d-2640-fe0f","uc_match":"1f9db-1f3fd-2640-fe0f","uc_greedy":"1f9db-1f3fd-2640","shortnames":[":woman_vampire_medium_skin_tone:"],"category":"people"},":woman_vampire_tone4:":{"uc_base":"1f9db-1f3fe-2640","uc_output":"1f9db-1f3fe-200d-2640-fe0f","uc_match":"1f9db-1f3fe-2640-fe0f","uc_greedy":"1f9db-1f3fe-2640","shortnames":[":woman_vampire_medium_dark_skin_tone:"],"category":"people"},":woman_vampire_tone5:":{"uc_base":"1f9db-1f3ff-2640","uc_output":"1f9db-1f3ff-200d-2640-fe0f","uc_match":"1f9db-1f3ff-2640-fe0f","uc_greedy":"1f9db-1f3ff-2640","shortnames":[":woman_vampire_dark_skin_tone:"],"category":"people"},":woman_walking_tone1:":{"uc_base":"1f6b6-1f3fb-2640","uc_output":"1f6b6-1f3fb-200d-2640-fe0f","uc_match":"1f6b6-1f3fb-2640-fe0f","uc_greedy":"1f6b6-1f3fb-2640","shortnames":[":woman_walking_light_skin_tone:"],"category":"people"},":woman_walking_tone2:":{"uc_base":"1f6b6-1f3fc-2640","uc_output":"1f6b6-1f3fc-200d-2640-fe0f","uc_match":"1f6b6-1f3fc-2640-fe0f","uc_greedy":"1f6b6-1f3fc-2640","shortnames":[":woman_walking_medium_light_skin_tone:"],"category":"people"},":woman_walking_tone3:":{"uc_base":"1f6b6-1f3fd-2640","uc_output":"1f6b6-1f3fd-200d-2640-fe0f","uc_match":"1f6b6-1f3fd-2640-fe0f","uc_greedy":"1f6b6-1f3fd-2640","shortnames":[":woman_walking_medium_skin_tone:"],"category":"people"},":woman_walking_tone4:":{"uc_base":"1f6b6-1f3fe-2640","uc_output":"1f6b6-1f3fe-200d-2640-fe0f","uc_match":"1f6b6-1f3fe-2640-fe0f","uc_greedy":"1f6b6-1f3fe-2640","shortnames":[":woman_walking_medium_dark_skin_tone:"],"category":"people"},":woman_walking_tone5:":{"uc_base":"1f6b6-1f3ff-2640","uc_output":"1f6b6-1f3ff-200d-2640-fe0f","uc_match":"1f6b6-1f3ff-2640-fe0f","uc_greedy":"1f6b6-1f3ff-2640","shortnames":[":woman_walking_dark_skin_tone:"],"category":"people"},":woman_wearing_turban_tone1:":{"uc_base":"1f473-1f3fb-2640","uc_output":"1f473-1f3fb-200d-2640-fe0f","uc_match":"1f473-1f3fb-2640-fe0f","uc_greedy":"1f473-1f3fb-2640","shortnames":[":woman_wearing_turban_light_skin_tone:"],"category":"people"},":woman_wearing_turban_tone2:":{"uc_base":"1f473-1f3fc-2640","uc_output":"1f473-1f3fc-200d-2640-fe0f","uc_match":"1f473-1f3fc-2640-fe0f","uc_greedy":"1f473-1f3fc-2640","shortnames":[":woman_wearing_turban_medium_light_skin_tone:"],"category":"people"},":woman_wearing_turban_tone3:":{"uc_base":"1f473-1f3fd-2640","uc_output":"1f473-1f3fd-200d-2640-fe0f","uc_match":"1f473-1f3fd-2640-fe0f","uc_greedy":"1f473-1f3fd-2640","shortnames":[":woman_wearing_turban_medium_skin_tone:"],"category":"people"},":woman_wearing_turban_tone4:":{"uc_base":"1f473-1f3fe-2640","uc_output":"1f473-1f3fe-200d-2640-fe0f","uc_match":"1f473-1f3fe-2640-fe0f","uc_greedy":"1f473-1f3fe-2640","shortnames":[":woman_wearing_turban_medium_dark_skin_tone:"],"category":"people"},":woman_wearing_turban_tone5:":{"uc_base":"1f473-1f3ff-2640","uc_output":"1f473-1f3ff-200d-2640-fe0f","uc_match":"1f473-1f3ff-2640-fe0f","uc_greedy":"1f473-1f3ff-2640","shortnames":[":woman_wearing_turban_dark_skin_tone:"],"category":"people"},":man_bouncing_ball_tone1:":{"uc_base":"26f9-1f3fb-2642","uc_output":"26f9-1f3fb-200d-2642-fe0f","uc_match":"26f9-fe0f-1f3fb-2642-fe0f","uc_greedy":"26f9-1f3fb-2642","shortnames":[":man_bouncing_ball_light_skin_tone:"],"category":"activity"},":man_bouncing_ball_tone2:":{"uc_base":"26f9-1f3fc-2642","uc_output":"26f9-1f3fc-200d-2642-fe0f","uc_match":"26f9-fe0f-1f3fc-2642-fe0f","uc_greedy":"26f9-1f3fc-2642","shortnames":[":man_bouncing_ball_medium_light_skin_tone:"],"category":"activity"},":man_bouncing_ball_tone3:":{"uc_base":"26f9-1f3fd-2642","uc_output":"26f9-1f3fd-200d-2642-fe0f","uc_match":"26f9-fe0f-1f3fd-2642-fe0f","uc_greedy":"26f9-1f3fd-2642","shortnames":[":man_bouncing_ball_medium_skin_tone:"],"category":"activity"},":man_bouncing_ball_tone4:":{"uc_base":"26f9-1f3fe-2642","uc_output":"26f9-1f3fe-200d-2642-fe0f","uc_match":"26f9-fe0f-1f3fe-2642-fe0f","uc_greedy":"26f9-1f3fe-2642","shortnames":[":man_bouncing_ball_medium_dark_skin_tone:"],"category":"activity"},":man_bouncing_ball_tone5:":{"uc_base":"26f9-1f3ff-2642","uc_output":"26f9-1f3ff-200d-2642-fe0f","uc_match":"26f9-fe0f-1f3ff-2642-fe0f","uc_greedy":"26f9-1f3ff-2642","shortnames":[":man_bouncing_ball_dark_skin_tone:"],"category":"activity"},":man_detective:":{"uc_base":"1f575-2642","uc_output":"1f575-fe0f-200d-2642-fe0f","uc_match":"1f575-fe0f-2642-fe0f","uc_greedy":"1f575-2642","shortnames":[],"category":"people"},":man_golfing:":{"uc_base":"1f3cc-2642","uc_output":"1f3cc-fe0f-200d-2642-fe0f","uc_match":"1f3cc-fe0f-2642-fe0f","uc_greedy":"1f3cc-2642","shortnames":[],"category":"activity"},":man_lifting_weights:":{"uc_base":"1f3cb-2642","uc_output":"1f3cb-fe0f-200d-2642-fe0f","uc_match":"1f3cb-fe0f-2642-fe0f","uc_greedy":"1f3cb-2642","shortnames":[],"category":"activity"},":woman_bouncing_ball_tone1:":{"uc_base":"26f9-1f3fb-2640","uc_output":"26f9-1f3fb-200d-2640-fe0f","uc_match":"26f9-fe0f-1f3fb-2640-fe0f","uc_greedy":"26f9-1f3fb-2640","shortnames":[":woman_bouncing_ball_light_skin_tone:"],"category":"activity"},":woman_bouncing_ball_tone2:":{"uc_base":"26f9-1f3fc-2640","uc_output":"26f9-1f3fc-200d-2640-fe0f","uc_match":"26f9-fe0f-1f3fc-2640-fe0f","uc_greedy":"26f9-1f3fc-2640","shortnames":[":woman_bouncing_ball_medium_light_skin_tone:"],"category":"activity"},":woman_bouncing_ball_tone3:":{"uc_base":"26f9-1f3fd-2640","uc_output":"26f9-1f3fd-200d-2640-fe0f","uc_match":"26f9-fe0f-1f3fd-2640-fe0f","uc_greedy":"26f9-1f3fd-2640","shortnames":[":woman_bouncing_ball_medium_skin_tone:"],"category":"activity"},":woman_bouncing_ball_tone4:":{"uc_base":"26f9-1f3fe-2640","uc_output":"26f9-1f3fe-200d-2640-fe0f","uc_match":"26f9-fe0f-1f3fe-2640-fe0f","uc_greedy":"26f9-1f3fe-2640","shortnames":[":woman_bouncing_ball_medium_dark_skin_tone:"],"category":"activity"},":woman_bouncing_ball_tone5:":{"uc_base":"26f9-1f3ff-2640","uc_output":"26f9-1f3ff-200d-2640-fe0f","uc_match":"26f9-fe0f-1f3ff-2640-fe0f","uc_greedy":"26f9-1f3ff-2640","shortnames":[":woman_bouncing_ball_dark_skin_tone:"],"category":"activity"},":woman_detective:":{"uc_base":"1f575-2640","uc_output":"1f575-fe0f-200d-2640-fe0f","uc_match":"1f575-fe0f-2640-fe0f","uc_greedy":"1f575-2640","shortnames":[],"category":"people"},":woman_golfing:":{"uc_base":"1f3cc-2640","uc_output":"1f3cc-fe0f-200d-2640-fe0f","uc_match":"1f3cc-fe0f-2640-fe0f","uc_greedy":"1f3cc-2640","shortnames":[],"category":"activity"},":woman_lifting_weights:":{"uc_base":"1f3cb-2640","uc_output":"1f3cb-fe0f-200d-2640-fe0f","uc_match":"1f3cb-fe0f-2640-fe0f","uc_greedy":"1f3cb-2640","shortnames":[],"category":"activity"},":man_bouncing_ball:":{"uc_base":"26f9-2642","uc_output":"26f9-fe0f-200d-2642-fe0f","uc_match":"26f9-fe0f-2642-fe0f","uc_greedy":"26f9-2642","shortnames":[],"category":"activity"},":woman_bouncing_ball:":{"uc_base":"26f9-2640","uc_output":"26f9-fe0f-200d-2640-fe0f","uc_match":"26f9-fe0f-2640-fe0f","uc_greedy":"26f9-2640","shortnames":[],"category":"activity"},":man_artist_tone1:":{"uc_base":"1f468-1f3fb-1f3a8","uc_output":"1f468-1f3fb-200d-1f3a8","uc_match":"1f468-1f3fb-1f3a8","uc_greedy":"1f468-1f3fb-1f3a8","shortnames":[":man_artist_light_skin_tone:"],"category":"people"},":man_artist_tone2:":{"uc_base":"1f468-1f3fc-1f3a8","uc_output":"1f468-1f3fc-200d-1f3a8","uc_match":"1f468-1f3fc-1f3a8","uc_greedy":"1f468-1f3fc-1f3a8","shortnames":[":man_artist_medium_light_skin_tone:"],"category":"people"},":man_artist_tone3:":{"uc_base":"1f468-1f3fd-1f3a8","uc_output":"1f468-1f3fd-200d-1f3a8","uc_match":"1f468-1f3fd-1f3a8","uc_greedy":"1f468-1f3fd-1f3a8","shortnames":[":man_artist_medium_skin_tone:"],"category":"people"},":man_artist_tone4:":{"uc_base":"1f468-1f3fe-1f3a8","uc_output":"1f468-1f3fe-200d-1f3a8","uc_match":"1f468-1f3fe-1f3a8","uc_greedy":"1f468-1f3fe-1f3a8","shortnames":[":man_artist_medium_dark_skin_tone:"],"category":"people"},":man_artist_tone5:":{"uc_base":"1f468-1f3ff-1f3a8","uc_output":"1f468-1f3ff-200d-1f3a8","uc_match":"1f468-1f3ff-1f3a8","uc_greedy":"1f468-1f3ff-1f3a8","shortnames":[":man_artist_dark_skin_tone:"],"category":"people"},":man_astronaut_tone1:":{"uc_base":"1f468-1f3fb-1f680","uc_output":"1f468-1f3fb-200d-1f680","uc_match":"1f468-1f3fb-1f680","uc_greedy":"1f468-1f3fb-1f680","shortnames":[":man_astronaut_light_skin_tone:"],"category":"people"},":man_astronaut_tone2:":{"uc_base":"1f468-1f3fc-1f680","uc_output":"1f468-1f3fc-200d-1f680","uc_match":"1f468-1f3fc-1f680","uc_greedy":"1f468-1f3fc-1f680","shortnames":[":man_astronaut_medium_light_skin_tone:"],"category":"people"},":man_astronaut_tone3:":{"uc_base":"1f468-1f3fd-1f680","uc_output":"1f468-1f3fd-200d-1f680","uc_match":"1f468-1f3fd-1f680","uc_greedy":"1f468-1f3fd-1f680","shortnames":[":man_astronaut_medium_skin_tone:"],"category":"people"},":man_astronaut_tone4:":{"uc_base":"1f468-1f3fe-1f680","uc_output":"1f468-1f3fe-200d-1f680","uc_match":"1f468-1f3fe-1f680","uc_greedy":"1f468-1f3fe-1f680","shortnames":[":man_astronaut_medium_dark_skin_tone:"],"category":"people"},":man_astronaut_tone5:":{"uc_base":"1f468-1f3ff-1f680","uc_output":"1f468-1f3ff-200d-1f680","uc_match":"1f468-1f3ff-1f680","uc_greedy":"1f468-1f3ff-1f680","shortnames":[":man_astronaut_dark_skin_tone:"],"category":"people"},":man_cook_tone1:":{"uc_base":"1f468-1f3fb-1f373","uc_output":"1f468-1f3fb-200d-1f373","uc_match":"1f468-1f3fb-1f373","uc_greedy":"1f468-1f3fb-1f373","shortnames":[":man_cook_light_skin_tone:"],"category":"people"},":man_cook_tone2:":{"uc_base":"1f468-1f3fc-1f373","uc_output":"1f468-1f3fc-200d-1f373","uc_match":"1f468-1f3fc-1f373","uc_greedy":"1f468-1f3fc-1f373","shortnames":[":man_cook_medium_light_skin_tone:"],"category":"people"},":man_cook_tone3:":{"uc_base":"1f468-1f3fd-1f373","uc_output":"1f468-1f3fd-200d-1f373","uc_match":"1f468-1f3fd-1f373","uc_greedy":"1f468-1f3fd-1f373","shortnames":[":man_cook_medium_skin_tone:"],"category":"people"},":man_cook_tone4:":{"uc_base":"1f468-1f3fe-1f373","uc_output":"1f468-1f3fe-200d-1f373","uc_match":"1f468-1f3fe-1f373","uc_greedy":"1f468-1f3fe-1f373","shortnames":[":man_cook_medium_dark_skin_tone:"],"category":"people"},":man_cook_tone5:":{"uc_base":"1f468-1f3ff-1f373","uc_output":"1f468-1f3ff-200d-1f373","uc_match":"1f468-1f3ff-1f373","uc_greedy":"1f468-1f3ff-1f373","shortnames":[":man_cook_dark_skin_tone:"],"category":"people"},":man_factory_worker_tone1:":{"uc_base":"1f468-1f3fb-1f3ed","uc_output":"1f468-1f3fb-200d-1f3ed","uc_match":"1f468-1f3fb-1f3ed","uc_greedy":"1f468-1f3fb-1f3ed","shortnames":[":man_factory_worker_light_skin_tone:"],"category":"people"},":man_factory_worker_tone2:":{"uc_base":"1f468-1f3fc-1f3ed","uc_output":"1f468-1f3fc-200d-1f3ed","uc_match":"1f468-1f3fc-1f3ed","uc_greedy":"1f468-1f3fc-1f3ed","shortnames":[":man_factory_worker_medium_light_skin_tone:"],"category":"people"},":man_factory_worker_tone3:":{"uc_base":"1f468-1f3fd-1f3ed","uc_output":"1f468-1f3fd-200d-1f3ed","uc_match":"1f468-1f3fd-1f3ed","uc_greedy":"1f468-1f3fd-1f3ed","shortnames":[":man_factory_worker_medium_skin_tone:"],"category":"people"},":man_factory_worker_tone4:":{"uc_base":"1f468-1f3fe-1f3ed","uc_output":"1f468-1f3fe-200d-1f3ed","uc_match":"1f468-1f3fe-1f3ed","uc_greedy":"1f468-1f3fe-1f3ed","shortnames":[":man_factory_worker_medium_dark_skin_tone:"],"category":"people"},":man_factory_worker_tone5:":{"uc_base":"1f468-1f3ff-1f3ed","uc_output":"1f468-1f3ff-200d-1f3ed","uc_match":"1f468-1f3ff-1f3ed","uc_greedy":"1f468-1f3ff-1f3ed","shortnames":[":man_factory_worker_dark_skin_tone:"],"category":"people"},":man_farmer_tone1:":{"uc_base":"1f468-1f3fb-1f33e","uc_output":"1f468-1f3fb-200d-1f33e","uc_match":"1f468-1f3fb-1f33e","uc_greedy":"1f468-1f3fb-1f33e","shortnames":[":man_farmer_light_skin_tone:"],"category":"people"},":man_farmer_tone2:":{"uc_base":"1f468-1f3fc-1f33e","uc_output":"1f468-1f3fc-200d-1f33e","uc_match":"1f468-1f3fc-1f33e","uc_greedy":"1f468-1f3fc-1f33e","shortnames":[":man_farmer_medium_light_skin_tone:"],"category":"people"},":man_farmer_tone3:":{"uc_base":"1f468-1f3fd-1f33e","uc_output":"1f468-1f3fd-200d-1f33e","uc_match":"1f468-1f3fd-1f33e","uc_greedy":"1f468-1f3fd-1f33e","shortnames":[":man_farmer_medium_skin_tone:"],"category":"people"},":man_farmer_tone4:":{"uc_base":"1f468-1f3fe-1f33e","uc_output":"1f468-1f3fe-200d-1f33e","uc_match":"1f468-1f3fe-1f33e","uc_greedy":"1f468-1f3fe-1f33e","shortnames":[":man_farmer_medium_dark_skin_tone:"],"category":"people"},":man_farmer_tone5:":{"uc_base":"1f468-1f3ff-1f33e","uc_output":"1f468-1f3ff-200d-1f33e","uc_match":"1f468-1f3ff-1f33e","uc_greedy":"1f468-1f3ff-1f33e","shortnames":[":man_farmer_dark_skin_tone:"],"category":"people"},":man_firefighter_tone1:":{"uc_base":"1f468-1f3fb-1f692","uc_output":"1f468-1f3fb-200d-1f692","uc_match":"1f468-1f3fb-1f692","uc_greedy":"1f468-1f3fb-1f692","shortnames":[":man_firefighter_light_skin_tone:"],"category":"people"},":man_firefighter_tone2:":{"uc_base":"1f468-1f3fc-1f692","uc_output":"1f468-1f3fc-200d-1f692","uc_match":"1f468-1f3fc-1f692","uc_greedy":"1f468-1f3fc-1f692","shortnames":[":man_firefighter_medium_light_skin_tone:"],"category":"people"},":man_firefighter_tone3:":{"uc_base":"1f468-1f3fd-1f692","uc_output":"1f468-1f3fd-200d-1f692","uc_match":"1f468-1f3fd-1f692","uc_greedy":"1f468-1f3fd-1f692","shortnames":[":man_firefighter_medium_skin_tone:"],"category":"people"},":man_firefighter_tone4:":{"uc_base":"1f468-1f3fe-1f692","uc_output":"1f468-1f3fe-200d-1f692","uc_match":"1f468-1f3fe-1f692","uc_greedy":"1f468-1f3fe-1f692","shortnames":[":man_firefighter_medium_dark_skin_tone:"],"category":"people"},":man_firefighter_tone5:":{"uc_base":"1f468-1f3ff-1f692","uc_output":"1f468-1f3ff-200d-1f692","uc_match":"1f468-1f3ff-1f692","uc_greedy":"1f468-1f3ff-1f692","shortnames":[":man_firefighter_dark_skin_tone:"],"category":"people"},":man_mechanic_tone1:":{"uc_base":"1f468-1f3fb-1f527","uc_output":"1f468-1f3fb-200d-1f527","uc_match":"1f468-1f3fb-1f527","uc_greedy":"1f468-1f3fb-1f527","shortnames":[":man_mechanic_light_skin_tone:"],"category":"people"},":man_mechanic_tone2:":{"uc_base":"1f468-1f3fc-1f527","uc_output":"1f468-1f3fc-200d-1f527","uc_match":"1f468-1f3fc-1f527","uc_greedy":"1f468-1f3fc-1f527","shortnames":[":man_mechanic_medium_light_skin_tone:"],"category":"people"},":man_mechanic_tone3:":{"uc_base":"1f468-1f3fd-1f527","uc_output":"1f468-1f3fd-200d-1f527","uc_match":"1f468-1f3fd-1f527","uc_greedy":"1f468-1f3fd-1f527","shortnames":[":man_mechanic_medium_skin_tone:"],"category":"people"},":man_mechanic_tone4:":{"uc_base":"1f468-1f3fe-1f527","uc_output":"1f468-1f3fe-200d-1f527","uc_match":"1f468-1f3fe-1f527","uc_greedy":"1f468-1f3fe-1f527","shortnames":[":man_mechanic_medium_dark_skin_tone:"],"category":"people"},":man_mechanic_tone5:":{"uc_base":"1f468-1f3ff-1f527","uc_output":"1f468-1f3ff-200d-1f527","uc_match":"1f468-1f3ff-1f527","uc_greedy":"1f468-1f3ff-1f527","shortnames":[":man_mechanic_dark_skin_tone:"],"category":"people"},":man_office_worker_tone1:":{"uc_base":"1f468-1f3fb-1f4bc","uc_output":"1f468-1f3fb-200d-1f4bc","uc_match":"1f468-1f3fb-1f4bc","uc_greedy":"1f468-1f3fb-1f4bc","shortnames":[":man_office_worker_light_skin_tone:"],"category":"people"},":man_office_worker_tone2:":{"uc_base":"1f468-1f3fc-1f4bc","uc_output":"1f468-1f3fc-200d-1f4bc","uc_match":"1f468-1f3fc-1f4bc","uc_greedy":"1f468-1f3fc-1f4bc","shortnames":[":man_office_worker_medium_light_skin_tone:"],"category":"people"},":man_office_worker_tone3:":{"uc_base":"1f468-1f3fd-1f4bc","uc_output":"1f468-1f3fd-200d-1f4bc","uc_match":"1f468-1f3fd-1f4bc","uc_greedy":"1f468-1f3fd-1f4bc","shortnames":[":man_office_worker_medium_skin_tone:"],"category":"people"},":man_office_worker_tone4:":{"uc_base":"1f468-1f3fe-1f4bc","uc_output":"1f468-1f3fe-200d-1f4bc","uc_match":"1f468-1f3fe-1f4bc","uc_greedy":"1f468-1f3fe-1f4bc","shortnames":[":man_office_worker_medium_dark_skin_tone:"],"category":"people"},":man_office_worker_tone5:":{"uc_base":"1f468-1f3ff-1f4bc","uc_output":"1f468-1f3ff-200d-1f4bc","uc_match":"1f468-1f3ff-1f4bc","uc_greedy":"1f468-1f3ff-1f4bc","shortnames":[":man_office_worker_dark_skin_tone:"],"category":"people"},":man_scientist_tone1:":{"uc_base":"1f468-1f3fb-1f52c","uc_output":"1f468-1f3fb-200d-1f52c","uc_match":"1f468-1f3fb-1f52c","uc_greedy":"1f468-1f3fb-1f52c","shortnames":[":man_scientist_light_skin_tone:"],"category":"people"},":man_scientist_tone2:":{"uc_base":"1f468-1f3fc-1f52c","uc_output":"1f468-1f3fc-200d-1f52c","uc_match":"1f468-1f3fc-1f52c","uc_greedy":"1f468-1f3fc-1f52c","shortnames":[":man_scientist_medium_light_skin_tone:"],"category":"people"},":man_scientist_tone3:":{"uc_base":"1f468-1f3fd-1f52c","uc_output":"1f468-1f3fd-200d-1f52c","uc_match":"1f468-1f3fd-1f52c","uc_greedy":"1f468-1f3fd-1f52c","shortnames":[":man_scientist_medium_skin_tone:"],"category":"people"},":man_scientist_tone4:":{"uc_base":"1f468-1f3fe-1f52c","uc_output":"1f468-1f3fe-200d-1f52c","uc_match":"1f468-1f3fe-1f52c","uc_greedy":"1f468-1f3fe-1f52c","shortnames":[":man_scientist_medium_dark_skin_tone:"],"category":"people"},":man_scientist_tone5:":{"uc_base":"1f468-1f3ff-1f52c","uc_output":"1f468-1f3ff-200d-1f52c","uc_match":"1f468-1f3ff-1f52c","uc_greedy":"1f468-1f3ff-1f52c","shortnames":[":man_scientist_dark_skin_tone:"],"category":"people"},":man_singer_tone1:":{"uc_base":"1f468-1f3fb-1f3a4","uc_output":"1f468-1f3fb-200d-1f3a4","uc_match":"1f468-1f3fb-1f3a4","uc_greedy":"1f468-1f3fb-1f3a4","shortnames":[":man_singer_light_skin_tone:"],"category":"people"},":man_singer_tone2:":{"uc_base":"1f468-1f3fc-1f3a4","uc_output":"1f468-1f3fc-200d-1f3a4","uc_match":"1f468-1f3fc-1f3a4","uc_greedy":"1f468-1f3fc-1f3a4","shortnames":[":man_singer_medium_light_skin_tone:"],"category":"people"},":man_singer_tone3:":{"uc_base":"1f468-1f3fd-1f3a4","uc_output":"1f468-1f3fd-200d-1f3a4","uc_match":"1f468-1f3fd-1f3a4","uc_greedy":"1f468-1f3fd-1f3a4","shortnames":[":man_singer_medium_skin_tone:"],"category":"people"},":man_singer_tone4:":{"uc_base":"1f468-1f3fe-1f3a4","uc_output":"1f468-1f3fe-200d-1f3a4","uc_match":"1f468-1f3fe-1f3a4","uc_greedy":"1f468-1f3fe-1f3a4","shortnames":[":man_singer_medium_dark_skin_tone:"],"category":"people"},":man_singer_tone5:":{"uc_base":"1f468-1f3ff-1f3a4","uc_output":"1f468-1f3ff-200d-1f3a4","uc_match":"1f468-1f3ff-1f3a4","uc_greedy":"1f468-1f3ff-1f3a4","shortnames":[":man_singer_dark_skin_tone:"],"category":"people"},":man_student_tone1:":{"uc_base":"1f468-1f3fb-1f393","uc_output":"1f468-1f3fb-200d-1f393","uc_match":"1f468-1f3fb-1f393","uc_greedy":"1f468-1f3fb-1f393","shortnames":[":man_student_light_skin_tone:"],"category":"people"},":man_student_tone2:":{"uc_base":"1f468-1f3fc-1f393","uc_output":"1f468-1f3fc-200d-1f393","uc_match":"1f468-1f3fc-1f393","uc_greedy":"1f468-1f3fc-1f393","shortnames":[":man_student_medium_light_skin_tone:"],"category":"people"},":man_student_tone3:":{"uc_base":"1f468-1f3fd-1f393","uc_output":"1f468-1f3fd-200d-1f393","uc_match":"1f468-1f3fd-1f393","uc_greedy":"1f468-1f3fd-1f393","shortnames":[":man_student_medium_skin_tone:"],"category":"people"},":man_student_tone4:":{"uc_base":"1f468-1f3fe-1f393","uc_output":"1f468-1f3fe-200d-1f393","uc_match":"1f468-1f3fe-1f393","uc_greedy":"1f468-1f3fe-1f393","shortnames":[":man_student_medium_dark_skin_tone:"],"category":"people"},":man_student_tone5:":{"uc_base":"1f468-1f3ff-1f393","uc_output":"1f468-1f3ff-200d-1f393","uc_match":"1f468-1f3ff-1f393","uc_greedy":"1f468-1f3ff-1f393","shortnames":[":man_student_dark_skin_tone:"],"category":"people"},":man_teacher_tone1:":{"uc_base":"1f468-1f3fb-1f3eb","uc_output":"1f468-1f3fb-200d-1f3eb","uc_match":"1f468-1f3fb-1f3eb","uc_greedy":"1f468-1f3fb-1f3eb","shortnames":[":man_teacher_light_skin_tone:"],"category":"people"},":man_teacher_tone2:":{"uc_base":"1f468-1f3fc-1f3eb","uc_output":"1f468-1f3fc-200d-1f3eb","uc_match":"1f468-1f3fc-1f3eb","uc_greedy":"1f468-1f3fc-1f3eb","shortnames":[":man_teacher_medium_light_skin_tone:"],"category":"people"},":man_teacher_tone3:":{"uc_base":"1f468-1f3fd-1f3eb","uc_output":"1f468-1f3fd-200d-1f3eb","uc_match":"1f468-1f3fd-1f3eb","uc_greedy":"1f468-1f3fd-1f3eb","shortnames":[":man_teacher_medium_skin_tone:"],"category":"people"},":man_teacher_tone4:":{"uc_base":"1f468-1f3fe-1f3eb","uc_output":"1f468-1f3fe-200d-1f3eb","uc_match":"1f468-1f3fe-1f3eb","uc_greedy":"1f468-1f3fe-1f3eb","shortnames":[":man_teacher_medium_dark_skin_tone:"],"category":"people"},":man_teacher_tone5:":{"uc_base":"1f468-1f3ff-1f3eb","uc_output":"1f468-1f3ff-200d-1f3eb","uc_match":"1f468-1f3ff-1f3eb","uc_greedy":"1f468-1f3ff-1f3eb","shortnames":[":man_teacher_dark_skin_tone:"],"category":"people"},":man_technologist_tone1:":{"uc_base":"1f468-1f3fb-1f4bb","uc_output":"1f468-1f3fb-200d-1f4bb","uc_match":"1f468-1f3fb-1f4bb","uc_greedy":"1f468-1f3fb-1f4bb","shortnames":[":man_technologist_light_skin_tone:"],"category":"people"},":man_technologist_tone2:":{"uc_base":"1f468-1f3fc-1f4bb","uc_output":"1f468-1f3fc-200d-1f4bb","uc_match":"1f468-1f3fc-1f4bb","uc_greedy":"1f468-1f3fc-1f4bb","shortnames":[":man_technologist_medium_light_skin_tone:"],"category":"people"},":man_technologist_tone3:":{"uc_base":"1f468-1f3fd-1f4bb","uc_output":"1f468-1f3fd-200d-1f4bb","uc_match":"1f468-1f3fd-1f4bb","uc_greedy":"1f468-1f3fd-1f4bb","shortnames":[":man_technologist_medium_skin_tone:"],"category":"people"},":man_technologist_tone4:":{"uc_base":"1f468-1f3fe-1f4bb","uc_output":"1f468-1f3fe-200d-1f4bb","uc_match":"1f468-1f3fe-1f4bb","uc_greedy":"1f468-1f3fe-1f4bb","shortnames":[":man_technologist_medium_dark_skin_tone:"],"category":"people"},":man_technologist_tone5:":{"uc_base":"1f468-1f3ff-1f4bb","uc_output":"1f468-1f3ff-200d-1f4bb","uc_match":"1f468-1f3ff-1f4bb","uc_greedy":"1f468-1f3ff-1f4bb","shortnames":[":man_technologist_dark_skin_tone:"],"category":"people"},":woman_artist_tone1:":{"uc_base":"1f469-1f3fb-1f3a8","uc_output":"1f469-1f3fb-200d-1f3a8","uc_match":"1f469-1f3fb-1f3a8","uc_greedy":"1f469-1f3fb-1f3a8","shortnames":[":woman_artist_light_skin_tone:"],"category":"people"},":woman_artist_tone2:":{"uc_base":"1f469-1f3fc-1f3a8","uc_output":"1f469-1f3fc-200d-1f3a8","uc_match":"1f469-1f3fc-1f3a8","uc_greedy":"1f469-1f3fc-1f3a8","shortnames":[":woman_artist_medium_light_skin_tone:"],"category":"people"},":woman_artist_tone3:":{"uc_base":"1f469-1f3fd-1f3a8","uc_output":"1f469-1f3fd-200d-1f3a8","uc_match":"1f469-1f3fd-1f3a8","uc_greedy":"1f469-1f3fd-1f3a8","shortnames":[":woman_artist_medium_skin_tone:"],"category":"people"},":woman_artist_tone4:":{"uc_base":"1f469-1f3fe-1f3a8","uc_output":"1f469-1f3fe-200d-1f3a8","uc_match":"1f469-1f3fe-1f3a8","uc_greedy":"1f469-1f3fe-1f3a8","shortnames":[":woman_artist_medium_dark_skin_tone:"],"category":"people"},":woman_artist_tone5:":{"uc_base":"1f469-1f3ff-1f3a8","uc_output":"1f469-1f3ff-200d-1f3a8","uc_match":"1f469-1f3ff-1f3a8","uc_greedy":"1f469-1f3ff-1f3a8","shortnames":[":woman_artist_dark_skin_tone:"],"category":"people"},":woman_astronaut_tone1:":{"uc_base":"1f469-1f3fb-1f680","uc_output":"1f469-1f3fb-200d-1f680","uc_match":"1f469-1f3fb-1f680","uc_greedy":"1f469-1f3fb-1f680","shortnames":[":woman_astronaut_light_skin_tone:"],"category":"people"},":woman_astronaut_tone2:":{"uc_base":"1f469-1f3fc-1f680","uc_output":"1f469-1f3fc-200d-1f680","uc_match":"1f469-1f3fc-1f680","uc_greedy":"1f469-1f3fc-1f680","shortnames":[":woman_astronaut_medium_light_skin_tone:"],"category":"people"},":woman_astronaut_tone3:":{"uc_base":"1f469-1f3fd-1f680","uc_output":"1f469-1f3fd-200d-1f680","uc_match":"1f469-1f3fd-1f680","uc_greedy":"1f469-1f3fd-1f680","shortnames":[":woman_astronaut_medium_skin_tone:"],"category":"people"},":woman_astronaut_tone4:":{"uc_base":"1f469-1f3fe-1f680","uc_output":"1f469-1f3fe-200d-1f680","uc_match":"1f469-1f3fe-1f680","uc_greedy":"1f469-1f3fe-1f680","shortnames":[":woman_astronaut_medium_dark_skin_tone:"],"category":"people"},":woman_astronaut_tone5:":{"uc_base":"1f469-1f3ff-1f680","uc_output":"1f469-1f3ff-200d-1f680","uc_match":"1f469-1f3ff-1f680","uc_greedy":"1f469-1f3ff-1f680","shortnames":[":woman_astronaut_dark_skin_tone:"],"category":"people"},":woman_cook_tone1:":{"uc_base":"1f469-1f3fb-1f373","uc_output":"1f469-1f3fb-200d-1f373","uc_match":"1f469-1f3fb-1f373","uc_greedy":"1f469-1f3fb-1f373","shortnames":[":woman_cook_light_skin_tone:"],"category":"people"},":woman_cook_tone2:":{"uc_base":"1f469-1f3fc-1f373","uc_output":"1f469-1f3fc-200d-1f373","uc_match":"1f469-1f3fc-1f373","uc_greedy":"1f469-1f3fc-1f373","shortnames":[":woman_cook_medium_light_skin_tone:"],"category":"people"},":woman_cook_tone3:":{"uc_base":"1f469-1f3fd-1f373","uc_output":"1f469-1f3fd-200d-1f373","uc_match":"1f469-1f3fd-1f373","uc_greedy":"1f469-1f3fd-1f373","shortnames":[":woman_cook_medium_skin_tone:"],"category":"people"},":woman_cook_tone4:":{"uc_base":"1f469-1f3fe-1f373","uc_output":"1f469-1f3fe-200d-1f373","uc_match":"1f469-1f3fe-1f373","uc_greedy":"1f469-1f3fe-1f373","shortnames":[":woman_cook_medium_dark_skin_tone:"],"category":"people"},":woman_cook_tone5:":{"uc_base":"1f469-1f3ff-1f373","uc_output":"1f469-1f3ff-200d-1f373","uc_match":"1f469-1f3ff-1f373","uc_greedy":"1f469-1f3ff-1f373","shortnames":[":woman_cook_dark_skin_tone:"],"category":"people"},":woman_factory_worker_tone1:":{"uc_base":"1f469-1f3fb-1f3ed","uc_output":"1f469-1f3fb-200d-1f3ed","uc_match":"1f469-1f3fb-1f3ed","uc_greedy":"1f469-1f3fb-1f3ed","shortnames":[":woman_factory_worker_light_skin_tone:"],"category":"people"},":woman_factory_worker_tone2:":{"uc_base":"1f469-1f3fc-1f3ed","uc_output":"1f469-1f3fc-200d-1f3ed","uc_match":"1f469-1f3fc-1f3ed","uc_greedy":"1f469-1f3fc-1f3ed","shortnames":[":woman_factory_worker_medium_light_skin_tone:"],"category":"people"},":woman_factory_worker_tone3:":{"uc_base":"1f469-1f3fd-1f3ed","uc_output":"1f469-1f3fd-200d-1f3ed","uc_match":"1f469-1f3fd-1f3ed","uc_greedy":"1f469-1f3fd-1f3ed","shortnames":[":woman_factory_worker_medium_skin_tone:"],"category":"people"},":woman_factory_worker_tone4:":{"uc_base":"1f469-1f3fe-1f3ed","uc_output":"1f469-1f3fe-200d-1f3ed","uc_match":"1f469-1f3fe-1f3ed","uc_greedy":"1f469-1f3fe-1f3ed","shortnames":[":woman_factory_worker_medium_dark_skin_tone:"],"category":"people"},":woman_factory_worker_tone5:":{"uc_base":"1f469-1f3ff-1f3ed","uc_output":"1f469-1f3ff-200d-1f3ed","uc_match":"1f469-1f3ff-1f3ed","uc_greedy":"1f469-1f3ff-1f3ed","shortnames":[":woman_factory_worker_dark_skin_tone:"],"category":"people"},":woman_farmer_tone1:":{"uc_base":"1f469-1f3fb-1f33e","uc_output":"1f469-1f3fb-200d-1f33e","uc_match":"1f469-1f3fb-1f33e","uc_greedy":"1f469-1f3fb-1f33e","shortnames":[":woman_farmer_light_skin_tone:"],"category":"people"},":woman_farmer_tone2:":{"uc_base":"1f469-1f3fc-1f33e","uc_output":"1f469-1f3fc-200d-1f33e","uc_match":"1f469-1f3fc-1f33e","uc_greedy":"1f469-1f3fc-1f33e","shortnames":[":woman_farmer_medium_light_skin_tone:"],"category":"people"},":woman_farmer_tone3:":{"uc_base":"1f469-1f3fd-1f33e","uc_output":"1f469-1f3fd-200d-1f33e","uc_match":"1f469-1f3fd-1f33e","uc_greedy":"1f469-1f3fd-1f33e","shortnames":[":woman_farmer_medium_skin_tone:"],"category":"people"},":woman_farmer_tone4:":{"uc_base":"1f469-1f3fe-1f33e","uc_output":"1f469-1f3fe-200d-1f33e","uc_match":"1f469-1f3fe-1f33e","uc_greedy":"1f469-1f3fe-1f33e","shortnames":[":woman_farmer_medium_dark_skin_tone:"],"category":"people"},":woman_farmer_tone5:":{"uc_base":"1f469-1f3ff-1f33e","uc_output":"1f469-1f3ff-200d-1f33e","uc_match":"1f469-1f3ff-1f33e","uc_greedy":"1f469-1f3ff-1f33e","shortnames":[":woman_farmer_dark_skin_tone:"],"category":"people"},":woman_firefighter_tone1:":{"uc_base":"1f469-1f3fb-1f692","uc_output":"1f469-1f3fb-200d-1f692","uc_match":"1f469-1f3fb-1f692","uc_greedy":"1f469-1f3fb-1f692","shortnames":[":woman_firefighter_light_skin_tone:"],"category":"people"},":woman_firefighter_tone2:":{"uc_base":"1f469-1f3fc-1f692","uc_output":"1f469-1f3fc-200d-1f692","uc_match":"1f469-1f3fc-1f692","uc_greedy":"1f469-1f3fc-1f692","shortnames":[":woman_firefighter_medium_light_skin_tone:"],"category":"people"},":woman_firefighter_tone3:":{"uc_base":"1f469-1f3fd-1f692","uc_output":"1f469-1f3fd-200d-1f692","uc_match":"1f469-1f3fd-1f692","uc_greedy":"1f469-1f3fd-1f692","shortnames":[":woman_firefighter_medium_skin_tone:"],"category":"people"},":woman_firefighter_tone4:":{"uc_base":"1f469-1f3fe-1f692","uc_output":"1f469-1f3fe-200d-1f692","uc_match":"1f469-1f3fe-1f692","uc_greedy":"1f469-1f3fe-1f692","shortnames":[":woman_firefighter_medium_dark_skin_tone:"],"category":"people"},":woman_firefighter_tone5:":{"uc_base":"1f469-1f3ff-1f692","uc_output":"1f469-1f3ff-200d-1f692","uc_match":"1f469-1f3ff-1f692","uc_greedy":"1f469-1f3ff-1f692","shortnames":[":woman_firefighter_dark_skin_tone:"],"category":"people"},":woman_mechanic_tone1:":{"uc_base":"1f469-1f3fb-1f527","uc_output":"1f469-1f3fb-200d-1f527","uc_match":"1f469-1f3fb-1f527","uc_greedy":"1f469-1f3fb-1f527","shortnames":[":woman_mechanic_light_skin_tone:"],"category":"people"},":woman_mechanic_tone2:":{"uc_base":"1f469-1f3fc-1f527","uc_output":"1f469-1f3fc-200d-1f527","uc_match":"1f469-1f3fc-1f527","uc_greedy":"1f469-1f3fc-1f527","shortnames":[":woman_mechanic_medium_light_skin_tone:"],"category":"people"},":woman_mechanic_tone3:":{"uc_base":"1f469-1f3fd-1f527","uc_output":"1f469-1f3fd-200d-1f527","uc_match":"1f469-1f3fd-1f527","uc_greedy":"1f469-1f3fd-1f527","shortnames":[":woman_mechanic_medium_skin_tone:"],"category":"people"},":woman_mechanic_tone4:":{"uc_base":"1f469-1f3fe-1f527","uc_output":"1f469-1f3fe-200d-1f527","uc_match":"1f469-1f3fe-1f527","uc_greedy":"1f469-1f3fe-1f527","shortnames":[":woman_mechanic_medium_dark_skin_tone:"],"category":"people"},":woman_mechanic_tone5:":{"uc_base":"1f469-1f3ff-1f527","uc_output":"1f469-1f3ff-200d-1f527","uc_match":"1f469-1f3ff-1f527","uc_greedy":"1f469-1f3ff-1f527","shortnames":[":woman_mechanic_dark_skin_tone:"],"category":"people"},":woman_office_worker_tone1:":{"uc_base":"1f469-1f3fb-1f4bc","uc_output":"1f469-1f3fb-200d-1f4bc","uc_match":"1f469-1f3fb-1f4bc","uc_greedy":"1f469-1f3fb-1f4bc","shortnames":[":woman_office_worker_light_skin_tone:"],"category":"people"},":woman_office_worker_tone2:":{"uc_base":"1f469-1f3fc-1f4bc","uc_output":"1f469-1f3fc-200d-1f4bc","uc_match":"1f469-1f3fc-1f4bc","uc_greedy":"1f469-1f3fc-1f4bc","shortnames":[":woman_office_worker_medium_light_skin_tone:"],"category":"people"},":woman_office_worker_tone3:":{"uc_base":"1f469-1f3fd-1f4bc","uc_output":"1f469-1f3fd-200d-1f4bc","uc_match":"1f469-1f3fd-1f4bc","uc_greedy":"1f469-1f3fd-1f4bc","shortnames":[":woman_office_worker_medium_skin_tone:"],"category":"people"},":woman_office_worker_tone4:":{"uc_base":"1f469-1f3fe-1f4bc","uc_output":"1f469-1f3fe-200d-1f4bc","uc_match":"1f469-1f3fe-1f4bc","uc_greedy":"1f469-1f3fe-1f4bc","shortnames":[":woman_office_worker_medium_dark_skin_tone:"],"category":"people"},":woman_office_worker_tone5:":{"uc_base":"1f469-1f3ff-1f4bc","uc_output":"1f469-1f3ff-200d-1f4bc","uc_match":"1f469-1f3ff-1f4bc","uc_greedy":"1f469-1f3ff-1f4bc","shortnames":[":woman_office_worker_dark_skin_tone:"],"category":"people"},":woman_scientist_tone1:":{"uc_base":"1f469-1f3fb-1f52c","uc_output":"1f469-1f3fb-200d-1f52c","uc_match":"1f469-1f3fb-1f52c","uc_greedy":"1f469-1f3fb-1f52c","shortnames":[":woman_scientist_light_skin_tone:"],"category":"people"},":woman_scientist_tone2:":{"uc_base":"1f469-1f3fc-1f52c","uc_output":"1f469-1f3fc-200d-1f52c","uc_match":"1f469-1f3fc-1f52c","uc_greedy":"1f469-1f3fc-1f52c","shortnames":[":woman_scientist_medium_light_skin_tone:"],"category":"people"},":woman_scientist_tone3:":{"uc_base":"1f469-1f3fd-1f52c","uc_output":"1f469-1f3fd-200d-1f52c","uc_match":"1f469-1f3fd-1f52c","uc_greedy":"1f469-1f3fd-1f52c","shortnames":[":woman_scientist_medium_skin_tone:"],"category":"people"},":woman_scientist_tone4:":{"uc_base":"1f469-1f3fe-1f52c","uc_output":"1f469-1f3fe-200d-1f52c","uc_match":"1f469-1f3fe-1f52c","uc_greedy":"1f469-1f3fe-1f52c","shortnames":[":woman_scientist_medium_dark_skin_tone:"],"category":"people"},":woman_scientist_tone5:":{"uc_base":"1f469-1f3ff-1f52c","uc_output":"1f469-1f3ff-200d-1f52c","uc_match":"1f469-1f3ff-1f52c","uc_greedy":"1f469-1f3ff-1f52c","shortnames":[":woman_scientist_dark_skin_tone:"],"category":"people"},":woman_singer_tone1:":{"uc_base":"1f469-1f3fb-1f3a4","uc_output":"1f469-1f3fb-200d-1f3a4","uc_match":"1f469-1f3fb-1f3a4","uc_greedy":"1f469-1f3fb-1f3a4","shortnames":[":woman_singer_light_skin_tone:"],"category":"people"},":woman_singer_tone2:":{"uc_base":"1f469-1f3fc-1f3a4","uc_output":"1f469-1f3fc-200d-1f3a4","uc_match":"1f469-1f3fc-1f3a4","uc_greedy":"1f469-1f3fc-1f3a4","shortnames":[":woman_singer_medium_light_skin_tone:"],"category":"people"},":woman_singer_tone3:":{"uc_base":"1f469-1f3fd-1f3a4","uc_output":"1f469-1f3fd-200d-1f3a4","uc_match":"1f469-1f3fd-1f3a4","uc_greedy":"1f469-1f3fd-1f3a4","shortnames":[":woman_singer_medium_skin_tone:"],"category":"people"},":woman_singer_tone4:":{"uc_base":"1f469-1f3fe-1f3a4","uc_output":"1f469-1f3fe-200d-1f3a4","uc_match":"1f469-1f3fe-1f3a4","uc_greedy":"1f469-1f3fe-1f3a4","shortnames":[":woman_singer_medium_dark_skin_tone:"],"category":"people"},":woman_singer_tone5:":{"uc_base":"1f469-1f3ff-1f3a4","uc_output":"1f469-1f3ff-200d-1f3a4","uc_match":"1f469-1f3ff-1f3a4","uc_greedy":"1f469-1f3ff-1f3a4","shortnames":[":woman_singer_dark_skin_tone:"],"category":"people"},":woman_student_tone1:":{"uc_base":"1f469-1f3fb-1f393","uc_output":"1f469-1f3fb-200d-1f393","uc_match":"1f469-1f3fb-1f393","uc_greedy":"1f469-1f3fb-1f393","shortnames":[":woman_student_light_skin_tone:"],"category":"people"},":woman_student_tone2:":{"uc_base":"1f469-1f3fc-1f393","uc_output":"1f469-1f3fc-200d-1f393","uc_match":"1f469-1f3fc-1f393","uc_greedy":"1f469-1f3fc-1f393","shortnames":[":woman_student_medium_light_skin_tone:"],"category":"people"},":woman_student_tone3:":{"uc_base":"1f469-1f3fd-1f393","uc_output":"1f469-1f3fd-200d-1f393","uc_match":"1f469-1f3fd-1f393","uc_greedy":"1f469-1f3fd-1f393","shortnames":[":woman_student_medium_skin_tone:"],"category":"people"},":woman_student_tone4:":{"uc_base":"1f469-1f3fe-1f393","uc_output":"1f469-1f3fe-200d-1f393","uc_match":"1f469-1f3fe-1f393","uc_greedy":"1f469-1f3fe-1f393","shortnames":[":woman_student_medium_dark_skin_tone:"],"category":"people"},":woman_student_tone5:":{"uc_base":"1f469-1f3ff-1f393","uc_output":"1f469-1f3ff-200d-1f393","uc_match":"1f469-1f3ff-1f393","uc_greedy":"1f469-1f3ff-1f393","shortnames":[":woman_student_dark_skin_tone:"],"category":"people"},":woman_teacher_tone1:":{"uc_base":"1f469-1f3fb-1f3eb","uc_output":"1f469-1f3fb-200d-1f3eb","uc_match":"1f469-1f3fb-1f3eb","uc_greedy":"1f469-1f3fb-1f3eb","shortnames":[":woman_teacher_light_skin_tone:"],"category":"people"},":woman_teacher_tone2:":{"uc_base":"1f469-1f3fc-1f3eb","uc_output":"1f469-1f3fc-200d-1f3eb","uc_match":"1f469-1f3fc-1f3eb","uc_greedy":"1f469-1f3fc-1f3eb","shortnames":[":woman_teacher_medium_light_skin_tone:"],"category":"people"},":woman_teacher_tone3:":{"uc_base":"1f469-1f3fd-1f3eb","uc_output":"1f469-1f3fd-200d-1f3eb","uc_match":"1f469-1f3fd-1f3eb","uc_greedy":"1f469-1f3fd-1f3eb","shortnames":[":woman_teacher_medium_skin_tone:"],"category":"people"},":woman_teacher_tone4:":{"uc_base":"1f469-1f3fe-1f3eb","uc_output":"1f469-1f3fe-200d-1f3eb","uc_match":"1f469-1f3fe-1f3eb","uc_greedy":"1f469-1f3fe-1f3eb","shortnames":[":woman_teacher_medium_dark_skin_tone:"],"category":"people"},":woman_teacher_tone5:":{"uc_base":"1f469-1f3ff-1f3eb","uc_output":"1f469-1f3ff-200d-1f3eb","uc_match":"1f469-1f3ff-1f3eb","uc_greedy":"1f469-1f3ff-1f3eb","shortnames":[":woman_teacher_dark_skin_tone:"],"category":"people"},":woman_technologist_tone1:":{"uc_base":"1f469-1f3fb-1f4bb","uc_output":"1f469-1f3fb-200d-1f4bb","uc_match":"1f469-1f3fb-1f4bb","uc_greedy":"1f469-1f3fb-1f4bb","shortnames":[":woman_technologist_light_skin_tone:"],"category":"people"},":woman_technologist_tone2:":{"uc_base":"1f469-1f3fc-1f4bb","uc_output":"1f469-1f3fc-200d-1f4bb","uc_match":"1f469-1f3fc-1f4bb","uc_greedy":"1f469-1f3fc-1f4bb","shortnames":[":woman_technologist_medium_light_skin_tone:"],"category":"people"},":woman_technologist_tone3:":{"uc_base":"1f469-1f3fd-1f4bb","uc_output":"1f469-1f3fd-200d-1f4bb","uc_match":"1f469-1f3fd-1f4bb","uc_greedy":"1f469-1f3fd-1f4bb","shortnames":[":woman_technologist_medium_skin_tone:"],"category":"people"},":woman_technologist_tone4:":{"uc_base":"1f469-1f3fe-1f4bb","uc_output":"1f469-1f3fe-200d-1f4bb","uc_match":"1f469-1f3fe-1f4bb","uc_greedy":"1f469-1f3fe-1f4bb","shortnames":[":woman_technologist_medium_dark_skin_tone:"],"category":"people"},":woman_technologist_tone5:":{"uc_base":"1f469-1f3ff-1f4bb","uc_output":"1f469-1f3ff-200d-1f4bb","uc_match":"1f469-1f3ff-1f4bb","uc_greedy":"1f469-1f3ff-1f4bb","shortnames":[":woman_technologist_dark_skin_tone:"],"category":"people"},":rainbow_flag:":{"uc_base":"1f3f3-1f308","uc_output":"1f3f3-fe0f-200d-1f308","uc_match":"1f3f3-fe0f-1f308","uc_greedy":"1f3f3-1f308","shortnames":[":gay_pride_flag:"],"category":"flags"},":blond-haired_man:":{"uc_base":"1f471-2642","uc_output":"1f471-200d-2642-fe0f","uc_match":"1f471-2642-fe0f","uc_greedy":"1f471-2642","shortnames":[],"category":"people"},":blond-haired_woman:":{"uc_base":"1f471-2640","uc_output":"1f471-200d-2640-fe0f","uc_match":"1f471-2640-fe0f","uc_greedy":"1f471-2640","shortnames":[],"category":"people"},":man_biking:":{"uc_base":"1f6b4-2642","uc_output":"1f6b4-200d-2642-fe0f","uc_match":"1f6b4-2642-fe0f","uc_greedy":"1f6b4-2642","shortnames":[],"category":"activity"},":man_bowing:":{"uc_base":"1f647-2642","uc_output":"1f647-200d-2642-fe0f","uc_match":"1f647-2642-fe0f","uc_greedy":"1f647-2642","shortnames":[],"category":"people"},":man_cartwheeling:":{"uc_base":"1f938-2642","uc_output":"1f938-200d-2642-fe0f","uc_match":"1f938-2642-fe0f","uc_greedy":"1f938-2642","shortnames":[],"category":"activity"},":man_climbing:":{"uc_base":"1f9d7-2642","uc_output":"1f9d7-200d-2642-fe0f","uc_match":"1f9d7-2642-fe0f","uc_greedy":"1f9d7-2642","shortnames":[],"category":"activity"},":man_construction_worker:":{"uc_base":"1f477-2642","uc_output":"1f477-200d-2642-fe0f","uc_match":"1f477-2642-fe0f","uc_greedy":"1f477-2642","shortnames":[],"category":"people"},":man_elf:":{"uc_base":"1f9dd-2642","uc_output":"1f9dd-200d-2642-fe0f","uc_match":"1f9dd-2642-fe0f","uc_greedy":"1f9dd-2642","shortnames":[],"category":"people"},":man_facepalming:":{"uc_base":"1f926-2642","uc_output":"1f926-200d-2642-fe0f","uc_match":"1f926-2642-fe0f","uc_greedy":"1f926-2642","shortnames":[],"category":"people"},":man_fairy:":{"uc_base":"1f9da-2642","uc_output":"1f9da-200d-2642-fe0f","uc_match":"1f9da-2642-fe0f","uc_greedy":"1f9da-2642","shortnames":[],"category":"people"},":man_frowning:":{"uc_base":"1f64d-2642","uc_output":"1f64d-200d-2642-fe0f","uc_match":"1f64d-2642-fe0f","uc_greedy":"1f64d-2642","shortnames":[],"category":"people"},":man_genie:":{"uc_base":"1f9de-2642","uc_output":"1f9de-200d-2642-fe0f","uc_match":"1f9de-2642-fe0f","uc_greedy":"1f9de-2642","shortnames":[],"category":"people"},":man_gesturing_no:":{"uc_base":"1f645-2642","uc_output":"1f645-200d-2642-fe0f","uc_match":"1f645-2642-fe0f","uc_greedy":"1f645-2642","shortnames":[],"category":"people"},":man_gesturing_ok:":{"uc_base":"1f646-2642","uc_output":"1f646-200d-2642-fe0f","uc_match":"1f646-2642-fe0f","uc_greedy":"1f646-2642","shortnames":[],"category":"people"},":man_getting_face_massage:":{"uc_base":"1f486-2642","uc_output":"1f486-200d-2642-fe0f","uc_match":"1f486-2642-fe0f","uc_greedy":"1f486-2642","shortnames":[],"category":"people"},":man_getting_haircut:":{"uc_base":"1f487-2642","uc_output":"1f487-200d-2642-fe0f","uc_match":"1f487-2642-fe0f","uc_greedy":"1f487-2642","shortnames":[],"category":"people"},":man_guard:":{"uc_base":"1f482-2642","uc_output":"1f482-200d-2642-fe0f","uc_match":"1f482-2642-fe0f","uc_greedy":"1f482-2642","shortnames":[],"category":"people"},":man_health_worker:":{"uc_base":"1f468-2695","uc_output":"1f468-200d-2695-fe0f","uc_match":"1f468-2695-fe0f","uc_greedy":"1f468-2695","shortnames":[],"category":"people"},":man_in_lotus_position:":{"uc_base":"1f9d8-2642","uc_output":"1f9d8-200d-2642-fe0f","uc_match":"1f9d8-2642-fe0f","uc_greedy":"1f9d8-2642","shortnames":[],"category":"activity"},":man_in_steamy_room:":{"uc_base":"1f9d6-2642","uc_output":"1f9d6-200d-2642-fe0f","uc_match":"1f9d6-2642-fe0f","uc_greedy":"1f9d6-2642","shortnames":[],"category":"activity"},":man_judge:":{"uc_base":"1f468-2696","uc_output":"1f468-200d-2696-fe0f","uc_match":"1f468-2696-fe0f","uc_greedy":"1f468-2696","shortnames":[],"category":"people"},":man_juggling:":{"uc_base":"1f939-2642","uc_output":"1f939-200d-2642-fe0f","uc_match":"1f939-2642-fe0f","uc_greedy":"1f939-2642","shortnames":[],"category":"activity"},":man_mage:":{"uc_base":"1f9d9-2642","uc_output":"1f9d9-200d-2642-fe0f","uc_match":"1f9d9-2642-fe0f","uc_greedy":"1f9d9-2642","shortnames":[],"category":"people"},":man_mountain_biking:":{"uc_base":"1f6b5-2642","uc_output":"1f6b5-200d-2642-fe0f","uc_match":"1f6b5-2642-fe0f","uc_greedy":"1f6b5-2642","shortnames":[],"category":"activity"},":man_pilot:":{"uc_base":"1f468-2708","uc_output":"1f468-200d-2708-fe0f","uc_match":"1f468-2708-fe0f","uc_greedy":"1f468-2708","shortnames":[],"category":"people"},":man_playing_handball:":{"uc_base":"1f93e-2642","uc_output":"1f93e-200d-2642-fe0f","uc_match":"1f93e-2642-fe0f","uc_greedy":"1f93e-2642","shortnames":[],"category":"activity"},":man_playing_water_polo:":{"uc_base":"1f93d-2642","uc_output":"1f93d-200d-2642-fe0f","uc_match":"1f93d-2642-fe0f","uc_greedy":"1f93d-2642","shortnames":[],"category":"activity"},":man_police_officer:":{"uc_base":"1f46e-2642","uc_output":"1f46e-200d-2642-fe0f","uc_match":"1f46e-2642-fe0f","uc_greedy":"1f46e-2642","shortnames":[],"category":"people"},":man_pouting:":{"uc_base":"1f64e-2642","uc_output":"1f64e-200d-2642-fe0f","uc_match":"1f64e-2642-fe0f","uc_greedy":"1f64e-2642","shortnames":[],"category":"people"},":man_raising_hand:":{"uc_base":"1f64b-2642","uc_output":"1f64b-200d-2642-fe0f","uc_match":"1f64b-2642-fe0f","uc_greedy":"1f64b-2642","shortnames":[],"category":"people"},":man_rowing_boat:":{"uc_base":"1f6a3-2642","uc_output":"1f6a3-200d-2642-fe0f","uc_match":"1f6a3-2642-fe0f","uc_greedy":"1f6a3-2642","shortnames":[],"category":"activity"},":man_running:":{"uc_base":"1f3c3-2642","uc_output":"1f3c3-200d-2642-fe0f","uc_match":"1f3c3-2642-fe0f","uc_greedy":"1f3c3-2642","shortnames":[],"category":"people"},":man_shrugging:":{"uc_base":"1f937-2642","uc_output":"1f937-200d-2642-fe0f","uc_match":"1f937-2642-fe0f","uc_greedy":"1f937-2642","shortnames":[],"category":"people"},":man_surfing:":{"uc_base":"1f3c4-2642","uc_output":"1f3c4-200d-2642-fe0f","uc_match":"1f3c4-2642-fe0f","uc_greedy":"1f3c4-2642","shortnames":[],"category":"activity"},":man_swimming:":{"uc_base":"1f3ca-2642","uc_output":"1f3ca-200d-2642-fe0f","uc_match":"1f3ca-2642-fe0f","uc_greedy":"1f3ca-2642","shortnames":[],"category":"activity"},":man_tipping_hand:":{"uc_base":"1f481-2642","uc_output":"1f481-200d-2642-fe0f","uc_match":"1f481-2642-fe0f","uc_greedy":"1f481-2642","shortnames":[],"category":"people"},":man_vampire:":{"uc_base":"1f9db-2642","uc_output":"1f9db-200d-2642-fe0f","uc_match":"1f9db-2642-fe0f","uc_greedy":"1f9db-2642","shortnames":[],"category":"people"},":man_walking:":{"uc_base":"1f6b6-2642","uc_output":"1f6b6-200d-2642-fe0f","uc_match":"1f6b6-2642-fe0f","uc_greedy":"1f6b6-2642","shortnames":[],"category":"people"},":man_wearing_turban:":{"uc_base":"1f473-2642","uc_output":"1f473-200d-2642-fe0f","uc_match":"1f473-2642-fe0f","uc_greedy":"1f473-2642","shortnames":[],"category":"people"},":man_zombie:":{"uc_base":"1f9df-2642","uc_output":"1f9df-200d-2642-fe0f","uc_match":"1f9df-2642-fe0f","uc_greedy":"1f9df-2642","shortnames":[],"category":"people"},":men_with_bunny_ears_partying:":{"uc_base":"1f46f-2642","uc_output":"1f46f-200d-2642-fe0f","uc_match":"1f46f-2642-fe0f","uc_greedy":"1f46f-2642","shortnames":[],"category":"people"},":men_wrestling:":{"uc_base":"1f93c-2642","uc_output":"1f93c-200d-2642-fe0f","uc_match":"1f93c-2642-fe0f","uc_greedy":"1f93c-2642","shortnames":[],"category":"activity"},":mermaid:":{"uc_base":"1f9dc-2640","uc_output":"1f9dc-200d-2640-fe0f","uc_match":"1f9dc-2640-fe0f","uc_greedy":"1f9dc-2640","shortnames":[],"category":"people"},":merman:":{"uc_base":"1f9dc-2642","uc_output":"1f9dc-200d-2642-fe0f","uc_match":"1f9dc-2642-fe0f","uc_greedy":"1f9dc-2642","shortnames":[],"category":"people"},":woman_biking:":{"uc_base":"1f6b4-2640","uc_output":"1f6b4-200d-2640-fe0f","uc_match":"1f6b4-2640-fe0f","uc_greedy":"1f6b4-2640","shortnames":[],"category":"activity"},":woman_bowing:":{"uc_base":"1f647-2640","uc_output":"1f647-200d-2640-fe0f","uc_match":"1f647-2640-fe0f","uc_greedy":"1f647-2640","shortnames":[],"category":"people"},":woman_cartwheeling:":{"uc_base":"1f938-2640","uc_output":"1f938-200d-2640-fe0f","uc_match":"1f938-2640-fe0f","uc_greedy":"1f938-2640","shortnames":[],"category":"activity"},":woman_climbing:":{"uc_base":"1f9d7-2640","uc_output":"1f9d7-200d-2640-fe0f","uc_match":"1f9d7-2640-fe0f","uc_greedy":"1f9d7-2640","shortnames":[],"category":"activity"},":woman_construction_worker:":{"uc_base":"1f477-2640","uc_output":"1f477-200d-2640-fe0f","uc_match":"1f477-2640-fe0f","uc_greedy":"1f477-2640","shortnames":[],"category":"people"},":woman_elf:":{"uc_base":"1f9dd-2640","uc_output":"1f9dd-200d-2640-fe0f","uc_match":"1f9dd-2640-fe0f","uc_greedy":"1f9dd-2640","shortnames":[],"category":"people"},":woman_facepalming:":{"uc_base":"1f926-2640","uc_output":"1f926-200d-2640-fe0f","uc_match":"1f926-2640-fe0f","uc_greedy":"1f926-2640","shortnames":[],"category":"people"},":woman_fairy:":{"uc_base":"1f9da-2640","uc_output":"1f9da-200d-2640-fe0f","uc_match":"1f9da-2640-fe0f","uc_greedy":"1f9da-2640","shortnames":[],"category":"people"},":woman_frowning:":{"uc_base":"1f64d-2640","uc_output":"1f64d-200d-2640-fe0f","uc_match":"1f64d-2640-fe0f","uc_greedy":"1f64d-2640","shortnames":[],"category":"people"},":woman_genie:":{"uc_base":"1f9de-2640","uc_output":"1f9de-200d-2640-fe0f","uc_match":"1f9de-2640-fe0f","uc_greedy":"1f9de-2640","shortnames":[],"category":"people"},":woman_gesturing_no:":{"uc_base":"1f645-2640","uc_output":"1f645-200d-2640-fe0f","uc_match":"1f645-2640-fe0f","uc_greedy":"1f645-2640","shortnames":[],"category":"people"},":woman_gesturing_ok:":{"uc_base":"1f646-2640","uc_output":"1f646-200d-2640-fe0f","uc_match":"1f646-2640-fe0f","uc_greedy":"1f646-2640","shortnames":[],"category":"people"},":woman_getting_face_massage:":{"uc_base":"1f486-2640","uc_output":"1f486-200d-2640-fe0f","uc_match":"1f486-2640-fe0f","uc_greedy":"1f486-2640","shortnames":[],"category":"people"},":woman_getting_haircut:":{"uc_base":"1f487-2640","uc_output":"1f487-200d-2640-fe0f","uc_match":"1f487-2640-fe0f","uc_greedy":"1f487-2640","shortnames":[],"category":"people"},":woman_guard:":{"uc_base":"1f482-2640","uc_output":"1f482-200d-2640-fe0f","uc_match":"1f482-2640-fe0f","uc_greedy":"1f482-2640","shortnames":[],"category":"people"},":woman_health_worker:":{"uc_base":"1f469-2695","uc_output":"1f469-200d-2695-fe0f","uc_match":"1f469-2695-fe0f","uc_greedy":"1f469-2695","shortnames":[],"category":"people"},":woman_in_lotus_position:":{"uc_base":"1f9d8-2640","uc_output":"1f9d8-200d-2640-fe0f","uc_match":"1f9d8-2640-fe0f","uc_greedy":"1f9d8-2640","shortnames":[],"category":"activity"},":woman_in_steamy_room:":{"uc_base":"1f9d6-2640","uc_output":"1f9d6-200d-2640-fe0f","uc_match":"1f9d6-2640-fe0f","uc_greedy":"1f9d6-2640","shortnames":[],"category":"activity"},":woman_judge:":{"uc_base":"1f469-2696","uc_output":"1f469-200d-2696-fe0f","uc_match":"1f469-2696-fe0f","uc_greedy":"1f469-2696","shortnames":[],"category":"people"},":woman_juggling:":{"uc_base":"1f939-2640","uc_output":"1f939-200d-2640-fe0f","uc_match":"1f939-2640-fe0f","uc_greedy":"1f939-2640","shortnames":[],"category":"activity"},":woman_mage:":{"uc_base":"1f9d9-2640","uc_output":"1f9d9-200d-2640-fe0f","uc_match":"1f9d9-2640-fe0f","uc_greedy":"1f9d9-2640","shortnames":[],"category":"people"},":woman_mountain_biking:":{"uc_base":"1f6b5-2640","uc_output":"1f6b5-200d-2640-fe0f","uc_match":"1f6b5-2640-fe0f","uc_greedy":"1f6b5-2640","shortnames":[],"category":"activity"},":woman_pilot:":{"uc_base":"1f469-2708","uc_output":"1f469-200d-2708-fe0f","uc_match":"1f469-2708-fe0f","uc_greedy":"1f469-2708","shortnames":[],"category":"people"},":woman_playing_handball:":{"uc_base":"1f93e-2640","uc_output":"1f93e-200d-2640-fe0f","uc_match":"1f93e-2640-fe0f","uc_greedy":"1f93e-2640","shortnames":[],"category":"activity"},":woman_playing_water_polo:":{"uc_base":"1f93d-2640","uc_output":"1f93d-200d-2640-fe0f","uc_match":"1f93d-2640-fe0f","uc_greedy":"1f93d-2640","shortnames":[],"category":"activity"},":woman_police_officer:":{"uc_base":"1f46e-2640","uc_output":"1f46e-200d-2640-fe0f","uc_match":"1f46e-2640-fe0f","uc_greedy":"1f46e-2640","shortnames":[],"category":"people"},":woman_pouting:":{"uc_base":"1f64e-2640","uc_output":"1f64e-200d-2640-fe0f","uc_match":"1f64e-2640-fe0f","uc_greedy":"1f64e-2640","shortnames":[],"category":"people"},":woman_raising_hand:":{"uc_base":"1f64b-2640","uc_output":"1f64b-200d-2640-fe0f","uc_match":"1f64b-2640-fe0f","uc_greedy":"1f64b-2640","shortnames":[],"category":"people"},":woman_rowing_boat:":{"uc_base":"1f6a3-2640","uc_output":"1f6a3-200d-2640-fe0f","uc_match":"1f6a3-2640-fe0f","uc_greedy":"1f6a3-2640","shortnames":[],"category":"activity"},":woman_running:":{"uc_base":"1f3c3-2640","uc_output":"1f3c3-200d-2640-fe0f","uc_match":"1f3c3-2640-fe0f","uc_greedy":"1f3c3-2640","shortnames":[],"category":"people"},":woman_shrugging:":{"uc_base":"1f937-2640","uc_output":"1f937-200d-2640-fe0f","uc_match":"1f937-2640-fe0f","uc_greedy":"1f937-2640","shortnames":[],"category":"people"},":woman_surfing:":{"uc_base":"1f3c4-2640","uc_output":"1f3c4-200d-2640-fe0f","uc_match":"1f3c4-2640-fe0f","uc_greedy":"1f3c4-2640","shortnames":[],"category":"activity"},":woman_swimming:":{"uc_base":"1f3ca-2640","uc_output":"1f3ca-200d-2640-fe0f","uc_match":"1f3ca-2640-fe0f","uc_greedy":"1f3ca-2640","shortnames":[],"category":"activity"},":woman_tipping_hand:":{"uc_base":"1f481-2640","uc_output":"1f481-200d-2640-fe0f","uc_match":"1f481-2640-fe0f","uc_greedy":"1f481-2640","shortnames":[],"category":"people"},":woman_vampire:":{"uc_base":"1f9db-2640","uc_output":"1f9db-200d-2640-fe0f","uc_match":"1f9db-2640-fe0f","uc_greedy":"1f9db-2640","shortnames":[],"category":"people"},":woman_walking:":{"uc_base":"1f6b6-2640","uc_output":"1f6b6-200d-2640-fe0f","uc_match":"1f6b6-2640-fe0f","uc_greedy":"1f6b6-2640","shortnames":[],"category":"people"},":woman_wearing_turban:":{"uc_base":"1f473-2640","uc_output":"1f473-200d-2640-fe0f","uc_match":"1f473-2640-fe0f","uc_greedy":"1f473-2640","shortnames":[],"category":"people"},":woman_zombie:":{"uc_base":"1f9df-2640","uc_output":"1f9df-200d-2640-fe0f","uc_match":"1f9df-2640-fe0f","uc_greedy":"1f9df-2640","shortnames":[],"category":"people"},":women_with_bunny_ears_partying:":{"uc_base":"1f46f-2640","uc_output":"1f46f-200d-2640-fe0f","uc_match":"1f46f-2640-fe0f","uc_greedy":"1f46f-2640","shortnames":[],"category":"people"},":women_wrestling:":{"uc_base":"1f93c-2640","uc_output":"1f93c-200d-2640-fe0f","uc_match":"1f93c-2640-fe0f","uc_greedy":"1f93c-2640","shortnames":[],"category":"activity"},":family_man_boy:":{"uc_base":"1f468-1f466","uc_output":"1f468-200d-1f466","uc_match":"1f468-1f466","uc_greedy":"1f468-1f466","shortnames":[],"category":"people"},":family_man_girl:":{"uc_base":"1f468-1f467","uc_output":"1f468-200d-1f467","uc_match":"1f468-1f467","uc_greedy":"1f468-1f467","shortnames":[],"category":"people"},":family_woman_boy:":{"uc_base":"1f469-1f466","uc_output":"1f469-200d-1f466","uc_match":"1f469-1f466","uc_greedy":"1f469-1f466","shortnames":[],"category":"people"},":family_woman_girl:":{"uc_base":"1f469-1f467","uc_output":"1f469-200d-1f467","uc_match":"1f469-1f467","uc_greedy":"1f469-1f467","shortnames":[],"category":"people"},":man_artist:":{"uc_base":"1f468-1f3a8","uc_output":"1f468-200d-1f3a8","uc_match":"1f468-1f3a8","uc_greedy":"1f468-1f3a8","shortnames":[],"category":"people"},":man_astronaut:":{"uc_base":"1f468-1f680","uc_output":"1f468-200d-1f680","uc_match":"1f468-1f680","uc_greedy":"1f468-1f680","shortnames":[],"category":"people"},":man_cook:":{"uc_base":"1f468-1f373","uc_output":"1f468-200d-1f373","uc_match":"1f468-1f373","uc_greedy":"1f468-1f373","shortnames":[],"category":"people"},":man_factory_worker:":{"uc_base":"1f468-1f3ed","uc_output":"1f468-200d-1f3ed","uc_match":"1f468-1f3ed","uc_greedy":"1f468-1f3ed","shortnames":[],"category":"people"},":man_farmer:":{"uc_base":"1f468-1f33e","uc_output":"1f468-200d-1f33e","uc_match":"1f468-1f33e","uc_greedy":"1f468-1f33e","shortnames":[],"category":"people"},":man_firefighter:":{"uc_base":"1f468-1f692","uc_output":"1f468-200d-1f692","uc_match":"1f468-1f692","uc_greedy":"1f468-1f692","shortnames":[],"category":"people"},":man_mechanic:":{"uc_base":"1f468-1f527","uc_output":"1f468-200d-1f527","uc_match":"1f468-1f527","uc_greedy":"1f468-1f527","shortnames":[],"category":"people"},":man_office_worker:":{"uc_base":"1f468-1f4bc","uc_output":"1f468-200d-1f4bc","uc_match":"1f468-1f4bc","uc_greedy":"1f468-1f4bc","shortnames":[],"category":"people"},":man_scientist:":{"uc_base":"1f468-1f52c","uc_output":"1f468-200d-1f52c","uc_match":"1f468-1f52c","uc_greedy":"1f468-1f52c","shortnames":[],"category":"people"},":man_singer:":{"uc_base":"1f468-1f3a4","uc_output":"1f468-200d-1f3a4","uc_match":"1f468-1f3a4","uc_greedy":"1f468-1f3a4","shortnames":[],"category":"people"},":man_student:":{"uc_base":"1f468-1f393","uc_output":"1f468-200d-1f393","uc_match":"1f468-1f393","uc_greedy":"1f468-1f393","shortnames":[],"category":"people"},":man_teacher:":{"uc_base":"1f468-1f3eb","uc_output":"1f468-200d-1f3eb","uc_match":"1f468-1f3eb","uc_greedy":"1f468-1f3eb","shortnames":[],"category":"people"},":man_technologist:":{"uc_base":"1f468-1f4bb","uc_output":"1f468-200d-1f4bb","uc_match":"1f468-1f4bb","uc_greedy":"1f468-1f4bb","shortnames":[],"category":"people"},":woman_artist:":{"uc_base":"1f469-1f3a8","uc_output":"1f469-200d-1f3a8","uc_match":"1f469-1f3a8","uc_greedy":"1f469-1f3a8","shortnames":[],"category":"people"},":woman_astronaut:":{"uc_base":"1f469-1f680","uc_output":"1f469-200d-1f680","uc_match":"1f469-1f680","uc_greedy":"1f469-1f680","shortnames":[],"category":"people"},":woman_cook:":{"uc_base":"1f469-1f373","uc_output":"1f469-200d-1f373","uc_match":"1f469-1f373","uc_greedy":"1f469-1f373","shortnames":[],"category":"people"},":woman_factory_worker:":{"uc_base":"1f469-1f3ed","uc_output":"1f469-200d-1f3ed","uc_match":"1f469-1f3ed","uc_greedy":"1f469-1f3ed","shortnames":[],"category":"people"},":woman_farmer:":{"uc_base":"1f469-1f33e","uc_output":"1f469-200d-1f33e","uc_match":"1f469-1f33e","uc_greedy":"1f469-1f33e","shortnames":[],"category":"people"},":woman_firefighter:":{"uc_base":"1f469-1f692","uc_output":"1f469-200d-1f692","uc_match":"1f469-1f692","uc_greedy":"1f469-1f692","shortnames":[],"category":"people"},":woman_mechanic:":{"uc_base":"1f469-1f527","uc_output":"1f469-200d-1f527","uc_match":"1f469-1f527","uc_greedy":"1f469-1f527","shortnames":[],"category":"people"},":woman_office_worker:":{"uc_base":"1f469-1f4bc","uc_output":"1f469-200d-1f4bc","uc_match":"1f469-1f4bc","uc_greedy":"1f469-1f4bc","shortnames":[],"category":"people"},":woman_scientist:":{"uc_base":"1f469-1f52c","uc_output":"1f469-200d-1f52c","uc_match":"1f469-1f52c","uc_greedy":"1f469-1f52c","shortnames":[],"category":"people"},":woman_singer:":{"uc_base":"1f469-1f3a4","uc_output":"1f469-200d-1f3a4","uc_match":"1f469-1f3a4","uc_greedy":"1f469-1f3a4","shortnames":[],"category":"people"},":woman_student:":{"uc_base":"1f469-1f393","uc_output":"1f469-200d-1f393","uc_match":"1f469-1f393","uc_greedy":"1f469-1f393","shortnames":[],"category":"people"},":woman_teacher:":{"uc_base":"1f469-1f3eb","uc_output":"1f469-200d-1f3eb","uc_match":"1f469-1f3eb","uc_greedy":"1f469-1f3eb","shortnames":[],"category":"people"},":woman_technologist:":{"uc_base":"1f469-1f4bb","uc_output":"1f469-200d-1f4bb","uc_match":"1f469-1f4bb","uc_greedy":"1f469-1f4bb","shortnames":[],"category":"people"},":asterisk:":{"uc_base":"002a-20e3","uc_output":"002a-fe0f-20e3","uc_match":"002a-20e3","uc_greedy":"002a-20e3","shortnames":[":keycap_asterisk:"],"category":"symbols"},":eight:":{"uc_base":"0038-20e3","uc_output":"0038-fe0f-20e3","uc_match":"0038-20e3","uc_greedy":"0038-20e3","shortnames":[],"category":"symbols"},":five:":{"uc_base":"0035-20e3","uc_output":"0035-fe0f-20e3","uc_match":"0035-20e3","uc_greedy":"0035-20e3","shortnames":[],"category":"symbols"},":four:":{"uc_base":"0034-20e3","uc_output":"0034-fe0f-20e3","uc_match":"0034-20e3","uc_greedy":"0034-20e3","shortnames":[],"category":"symbols"},":hash:":{"uc_base":"0023-20e3","uc_output":"0023-fe0f-20e3","uc_match":"0023-20e3","uc_greedy":"0023-20e3","shortnames":[],"category":"symbols"},":nine:":{"uc_base":"0039-20e3","uc_output":"0039-fe0f-20e3","uc_match":"0039-20e3","uc_greedy":"0039-20e3","shortnames":[],"category":"symbols"},":one:":{"uc_base":"0031-20e3","uc_output":"0031-fe0f-20e3","uc_match":"0031-20e3","uc_greedy":"0031-20e3","shortnames":[],"category":"symbols"},":seven:":{"uc_base":"0037-20e3","uc_output":"0037-fe0f-20e3","uc_match":"0037-20e3","uc_greedy":"0037-20e3","shortnames":[],"category":"symbols"},":six:":{"uc_base":"0036-20e3","uc_output":"0036-fe0f-20e3","uc_match":"0036-20e3","uc_greedy":"0036-20e3","shortnames":[],"category":"symbols"},":three:":{"uc_base":"0033-20e3","uc_output":"0033-fe0f-20e3","uc_match":"0033-20e3","uc_greedy":"0033-20e3","shortnames":[],"category":"symbols"},":two:":{"uc_base":"0032-20e3","uc_output":"0032-fe0f-20e3","uc_match":"0032-20e3","uc_greedy":"0032-20e3","shortnames":[],"category":"symbols"},":zero:":{"uc_base":"0030-20e3","uc_output":"0030-fe0f-20e3","uc_match":"0030-20e3","uc_greedy":"0030-20e3","shortnames":[],"category":"symbols"},":adult_tone1:":{"uc_base":"1f9d1-1f3fb","uc_output":"1f9d1-1f3fb","uc_match":"1f9d1-1f3fb","uc_greedy":"1f9d1-1f3fb","shortnames":[":adult_light_skin_tone:"],"category":"people"},":adult_tone2:":{"uc_base":"1f9d1-1f3fc","uc_output":"1f9d1-1f3fc","uc_match":"1f9d1-1f3fc","uc_greedy":"1f9d1-1f3fc","shortnames":[":adult_medium_light_skin_tone:"],"category":"people"},":adult_tone3:":{"uc_base":"1f9d1-1f3fd","uc_output":"1f9d1-1f3fd","uc_match":"1f9d1-1f3fd","uc_greedy":"1f9d1-1f3fd","shortnames":[":adult_medium_skin_tone:"],"category":"people"},":adult_tone4:":{"uc_base":"1f9d1-1f3fe","uc_output":"1f9d1-1f3fe","uc_match":"1f9d1-1f3fe","uc_greedy":"1f9d1-1f3fe","shortnames":[":adult_medium_dark_skin_tone:"],"category":"people"},":adult_tone5:":{"uc_base":"1f9d1-1f3ff","uc_output":"1f9d1-1f3ff","uc_match":"1f9d1-1f3ff","uc_greedy":"1f9d1-1f3ff","shortnames":[":adult_dark_skin_tone:"],"category":"people"},":angel_tone1:":{"uc_base":"1f47c-1f3fb","uc_output":"1f47c-1f3fb","uc_match":"1f47c-1f3fb","uc_greedy":"1f47c-1f3fb","shortnames":[],"category":"people"},":angel_tone2:":{"uc_base":"1f47c-1f3fc","uc_output":"1f47c-1f3fc","uc_match":"1f47c-1f3fc","uc_greedy":"1f47c-1f3fc","shortnames":[],"category":"people"},":angel_tone3:":{"uc_base":"1f47c-1f3fd","uc_output":"1f47c-1f3fd","uc_match":"1f47c-1f3fd","uc_greedy":"1f47c-1f3fd","shortnames":[],"category":"people"},":angel_tone4:":{"uc_base":"1f47c-1f3fe","uc_output":"1f47c-1f3fe","uc_match":"1f47c-1f3fe","uc_greedy":"1f47c-1f3fe","shortnames":[],"category":"people"},":angel_tone5:":{"uc_base":"1f47c-1f3ff","uc_output":"1f47c-1f3ff","uc_match":"1f47c-1f3ff","uc_greedy":"1f47c-1f3ff","shortnames":[],"category":"people"},":baby_tone1:":{"uc_base":"1f476-1f3fb","uc_output":"1f476-1f3fb","uc_match":"1f476-1f3fb","uc_greedy":"1f476-1f3fb","shortnames":[],"category":"people"},":baby_tone2:":{"uc_base":"1f476-1f3fc","uc_output":"1f476-1f3fc","uc_match":"1f476-1f3fc","uc_greedy":"1f476-1f3fc","shortnames":[],"category":"people"},":baby_tone3:":{"uc_base":"1f476-1f3fd","uc_output":"1f476-1f3fd","uc_match":"1f476-1f3fd","uc_greedy":"1f476-1f3fd","shortnames":[],"category":"people"},":baby_tone4:":{"uc_base":"1f476-1f3fe","uc_output":"1f476-1f3fe","uc_match":"1f476-1f3fe","uc_greedy":"1f476-1f3fe","shortnames":[],"category":"people"},":baby_tone5:":{"uc_base":"1f476-1f3ff","uc_output":"1f476-1f3ff","uc_match":"1f476-1f3ff","uc_greedy":"1f476-1f3ff","shortnames":[],"category":"people"},":bath_tone1:":{"uc_base":"1f6c0-1f3fb","uc_output":"1f6c0-1f3fb","uc_match":"1f6c0-1f3fb","uc_greedy":"1f6c0-1f3fb","shortnames":[],"category":"objects"},":bath_tone2:":{"uc_base":"1f6c0-1f3fc","uc_output":"1f6c0-1f3fc","uc_match":"1f6c0-1f3fc","uc_greedy":"1f6c0-1f3fc","shortnames":[],"category":"objects"},":bath_tone3:":{"uc_base":"1f6c0-1f3fd","uc_output":"1f6c0-1f3fd","uc_match":"1f6c0-1f3fd","uc_greedy":"1f6c0-1f3fd","shortnames":[],"category":"objects"},":bath_tone4:":{"uc_base":"1f6c0-1f3fe","uc_output":"1f6c0-1f3fe","uc_match":"1f6c0-1f3fe","uc_greedy":"1f6c0-1f3fe","shortnames":[],"category":"objects"},":bath_tone5:":{"uc_base":"1f6c0-1f3ff","uc_output":"1f6c0-1f3ff","uc_match":"1f6c0-1f3ff","uc_greedy":"1f6c0-1f3ff","shortnames":[],"category":"objects"},":bearded_person_tone1:":{"uc_base":"1f9d4-1f3fb","uc_output":"1f9d4-1f3fb","uc_match":"1f9d4-1f3fb","uc_greedy":"1f9d4-1f3fb","shortnames":[":bearded_person_light_skin_tone:"],"category":"people"},":bearded_person_tone2:":{"uc_base":"1f9d4-1f3fc","uc_output":"1f9d4-1f3fc","uc_match":"1f9d4-1f3fc","uc_greedy":"1f9d4-1f3fc","shortnames":[":bearded_person_medium_light_skin_tone:"],"category":"people"},":bearded_person_tone3:":{"uc_base":"1f9d4-1f3fd","uc_output":"1f9d4-1f3fd","uc_match":"1f9d4-1f3fd","uc_greedy":"1f9d4-1f3fd","shortnames":[":bearded_person_medium_skin_tone:"],"category":"people"},":bearded_person_tone4:":{"uc_base":"1f9d4-1f3fe","uc_output":"1f9d4-1f3fe","uc_match":"1f9d4-1f3fe","uc_greedy":"1f9d4-1f3fe","shortnames":[":bearded_person_medium_dark_skin_tone:"],"category":"people"},":bearded_person_tone5:":{"uc_base":"1f9d4-1f3ff","uc_output":"1f9d4-1f3ff","uc_match":"1f9d4-1f3ff","uc_greedy":"1f9d4-1f3ff","shortnames":[":bearded_person_dark_skin_tone:"],"category":"people"},":blond_haired_person_tone1:":{"uc_base":"1f471-1f3fb","uc_output":"1f471-1f3fb","uc_match":"1f471-1f3fb","uc_greedy":"1f471-1f3fb","shortnames":[":person_with_blond_hair_tone1:"],"category":"people"},":blond_haired_person_tone2:":{"uc_base":"1f471-1f3fc","uc_output":"1f471-1f3fc","uc_match":"1f471-1f3fc","uc_greedy":"1f471-1f3fc","shortnames":[":person_with_blond_hair_tone2:"],"category":"people"},":blond_haired_person_tone3:":{"uc_base":"1f471-1f3fd","uc_output":"1f471-1f3fd","uc_match":"1f471-1f3fd","uc_greedy":"1f471-1f3fd","shortnames":[":person_with_blond_hair_tone3:"],"category":"people"},":blond_haired_person_tone4:":{"uc_base":"1f471-1f3fe","uc_output":"1f471-1f3fe","uc_match":"1f471-1f3fe","uc_greedy":"1f471-1f3fe","shortnames":[":person_with_blond_hair_tone4:"],"category":"people"},":blond_haired_person_tone5:":{"uc_base":"1f471-1f3ff","uc_output":"1f471-1f3ff","uc_match":"1f471-1f3ff","uc_greedy":"1f471-1f3ff","shortnames":[":person_with_blond_hair_tone5:"],"category":"people"},":boy_tone1:":{"uc_base":"1f466-1f3fb","uc_output":"1f466-1f3fb","uc_match":"1f466-1f3fb","uc_greedy":"1f466-1f3fb","shortnames":[],"category":"people"},":boy_tone2:":{"uc_base":"1f466-1f3fc","uc_output":"1f466-1f3fc","uc_match":"1f466-1f3fc","uc_greedy":"1f466-1f3fc","shortnames":[],"category":"people"},":boy_tone3:":{"uc_base":"1f466-1f3fd","uc_output":"1f466-1f3fd","uc_match":"1f466-1f3fd","uc_greedy":"1f466-1f3fd","shortnames":[],"category":"people"},":boy_tone4:":{"uc_base":"1f466-1f3fe","uc_output":"1f466-1f3fe","uc_match":"1f466-1f3fe","uc_greedy":"1f466-1f3fe","shortnames":[],"category":"people"},":boy_tone5:":{"uc_base":"1f466-1f3ff","uc_output":"1f466-1f3ff","uc_match":"1f466-1f3ff","uc_greedy":"1f466-1f3ff","shortnames":[],"category":"people"},":breast_feeding_tone1:":{"uc_base":"1f931-1f3fb","uc_output":"1f931-1f3fb","uc_match":"1f931-1f3fb","uc_greedy":"1f931-1f3fb","shortnames":[":breast_feeding_light_skin_tone:"],"category":"activity"},":breast_feeding_tone2:":{"uc_base":"1f931-1f3fc","uc_output":"1f931-1f3fc","uc_match":"1f931-1f3fc","uc_greedy":"1f931-1f3fc","shortnames":[":breast_feeding_medium_light_skin_tone:"],"category":"activity"},":breast_feeding_tone3:":{"uc_base":"1f931-1f3fd","uc_output":"1f931-1f3fd","uc_match":"1f931-1f3fd","uc_greedy":"1f931-1f3fd","shortnames":[":breast_feeding_medium_skin_tone:"],"category":"activity"},":breast_feeding_tone4:":{"uc_base":"1f931-1f3fe","uc_output":"1f931-1f3fe","uc_match":"1f931-1f3fe","uc_greedy":"1f931-1f3fe","shortnames":[":breast_feeding_medium_dark_skin_tone:"],"category":"activity"},":breast_feeding_tone5:":{"uc_base":"1f931-1f3ff","uc_output":"1f931-1f3ff","uc_match":"1f931-1f3ff","uc_greedy":"1f931-1f3ff","shortnames":[":breast_feeding_dark_skin_tone:"],"category":"activity"},":bride_with_veil_tone1:":{"uc_base":"1f470-1f3fb","uc_output":"1f470-1f3fb","uc_match":"1f470-1f3fb","uc_greedy":"1f470-1f3fb","shortnames":[],"category":"people"},":bride_with_veil_tone2:":{"uc_base":"1f470-1f3fc","uc_output":"1f470-1f3fc","uc_match":"1f470-1f3fc","uc_greedy":"1f470-1f3fc","shortnames":[],"category":"people"},":bride_with_veil_tone3:":{"uc_base":"1f470-1f3fd","uc_output":"1f470-1f3fd","uc_match":"1f470-1f3fd","uc_greedy":"1f470-1f3fd","shortnames":[],"category":"people"},":bride_with_veil_tone4:":{"uc_base":"1f470-1f3fe","uc_output":"1f470-1f3fe","uc_match":"1f470-1f3fe","uc_greedy":"1f470-1f3fe","shortnames":[],"category":"people"},":bride_with_veil_tone5:":{"uc_base":"1f470-1f3ff","uc_output":"1f470-1f3ff","uc_match":"1f470-1f3ff","uc_greedy":"1f470-1f3ff","shortnames":[],"category":"people"},":call_me_tone1:":{"uc_base":"1f919-1f3fb","uc_output":"1f919-1f3fb","uc_match":"1f919-1f3fb","uc_greedy":"1f919-1f3fb","shortnames":[":call_me_hand_tone1:"],"category":"people"},":call_me_tone2:":{"uc_base":"1f919-1f3fc","uc_output":"1f919-1f3fc","uc_match":"1f919-1f3fc","uc_greedy":"1f919-1f3fc","shortnames":[":call_me_hand_tone2:"],"category":"people"},":call_me_tone3:":{"uc_base":"1f919-1f3fd","uc_output":"1f919-1f3fd","uc_match":"1f919-1f3fd","uc_greedy":"1f919-1f3fd","shortnames":[":call_me_hand_tone3:"],"category":"people"},":call_me_tone4:":{"uc_base":"1f919-1f3fe","uc_output":"1f919-1f3fe","uc_match":"1f919-1f3fe","uc_greedy":"1f919-1f3fe","shortnames":[":call_me_hand_tone4:"],"category":"people"},":call_me_tone5:":{"uc_base":"1f919-1f3ff","uc_output":"1f919-1f3ff","uc_match":"1f919-1f3ff","uc_greedy":"1f919-1f3ff","shortnames":[":call_me_hand_tone5:"],"category":"people"},":child_tone1:":{"uc_base":"1f9d2-1f3fb","uc_output":"1f9d2-1f3fb","uc_match":"1f9d2-1f3fb","uc_greedy":"1f9d2-1f3fb","shortnames":[":child_light_skin_tone:"],"category":"people"},":child_tone2:":{"uc_base":"1f9d2-1f3fc","uc_output":"1f9d2-1f3fc","uc_match":"1f9d2-1f3fc","uc_greedy":"1f9d2-1f3fc","shortnames":[":child_medium_light_skin_tone:"],"category":"people"},":child_tone3:":{"uc_base":"1f9d2-1f3fd","uc_output":"1f9d2-1f3fd","uc_match":"1f9d2-1f3fd","uc_greedy":"1f9d2-1f3fd","shortnames":[":child_medium_skin_tone:"],"category":"people"},":child_tone4:":{"uc_base":"1f9d2-1f3fe","uc_output":"1f9d2-1f3fe","uc_match":"1f9d2-1f3fe","uc_greedy":"1f9d2-1f3fe","shortnames":[":child_medium_dark_skin_tone:"],"category":"people"},":child_tone5:":{"uc_base":"1f9d2-1f3ff","uc_output":"1f9d2-1f3ff","uc_match":"1f9d2-1f3ff","uc_greedy":"1f9d2-1f3ff","shortnames":[":child_dark_skin_tone:"],"category":"people"},":clap_tone1:":{"uc_base":"1f44f-1f3fb","uc_output":"1f44f-1f3fb","uc_match":"1f44f-1f3fb","uc_greedy":"1f44f-1f3fb","shortnames":[],"category":"people"},":clap_tone2:":{"uc_base":"1f44f-1f3fc","uc_output":"1f44f-1f3fc","uc_match":"1f44f-1f3fc","uc_greedy":"1f44f-1f3fc","shortnames":[],"category":"people"},":clap_tone3:":{"uc_base":"1f44f-1f3fd","uc_output":"1f44f-1f3fd","uc_match":"1f44f-1f3fd","uc_greedy":"1f44f-1f3fd","shortnames":[],"category":"people"},":clap_tone4:":{"uc_base":"1f44f-1f3fe","uc_output":"1f44f-1f3fe","uc_match":"1f44f-1f3fe","uc_greedy":"1f44f-1f3fe","shortnames":[],"category":"people"},":clap_tone5:":{"uc_base":"1f44f-1f3ff","uc_output":"1f44f-1f3ff","uc_match":"1f44f-1f3ff","uc_greedy":"1f44f-1f3ff","shortnames":[],"category":"people"},":construction_worker_tone1:":{"uc_base":"1f477-1f3fb","uc_output":"1f477-1f3fb","uc_match":"1f477-1f3fb","uc_greedy":"1f477-1f3fb","shortnames":[],"category":"people"},":construction_worker_tone2:":{"uc_base":"1f477-1f3fc","uc_output":"1f477-1f3fc","uc_match":"1f477-1f3fc","uc_greedy":"1f477-1f3fc","shortnames":[],"category":"people"},":construction_worker_tone3:":{"uc_base":"1f477-1f3fd","uc_output":"1f477-1f3fd","uc_match":"1f477-1f3fd","uc_greedy":"1f477-1f3fd","shortnames":[],"category":"people"},":construction_worker_tone4:":{"uc_base":"1f477-1f3fe","uc_output":"1f477-1f3fe","uc_match":"1f477-1f3fe","uc_greedy":"1f477-1f3fe","shortnames":[],"category":"people"},":construction_worker_tone5:":{"uc_base":"1f477-1f3ff","uc_output":"1f477-1f3ff","uc_match":"1f477-1f3ff","uc_greedy":"1f477-1f3ff","shortnames":[],"category":"people"},":dancer_tone1:":{"uc_base":"1f483-1f3fb","uc_output":"1f483-1f3fb","uc_match":"1f483-1f3fb","uc_greedy":"1f483-1f3fb","shortnames":[],"category":"people"},":dancer_tone2:":{"uc_base":"1f483-1f3fc","uc_output":"1f483-1f3fc","uc_match":"1f483-1f3fc","uc_greedy":"1f483-1f3fc","shortnames":[],"category":"people"},":dancer_tone3:":{"uc_base":"1f483-1f3fd","uc_output":"1f483-1f3fd","uc_match":"1f483-1f3fd","uc_greedy":"1f483-1f3fd","shortnames":[],"category":"people"},":dancer_tone4:":{"uc_base":"1f483-1f3fe","uc_output":"1f483-1f3fe","uc_match":"1f483-1f3fe","uc_greedy":"1f483-1f3fe","shortnames":[],"category":"people"},":dancer_tone5:":{"uc_base":"1f483-1f3ff","uc_output":"1f483-1f3ff","uc_match":"1f483-1f3ff","uc_greedy":"1f483-1f3ff","shortnames":[],"category":"people"},":detective_tone1:":{"uc_base":"1f575-1f3fb","uc_output":"1f575-1f3fb","uc_match":"1f575-fe0f-1f3fb","uc_greedy":"1f575-fe0f-1f3fb","shortnames":[":spy_tone1:",":sleuth_or_spy_tone1:"],"category":"people"},":detective_tone2:":{"uc_base":"1f575-1f3fc","uc_output":"1f575-1f3fc","uc_match":"1f575-fe0f-1f3fc","uc_greedy":"1f575-fe0f-1f3fc","shortnames":[":spy_tone2:",":sleuth_or_spy_tone2:"],"category":"people"},":detective_tone3:":{"uc_base":"1f575-1f3fd","uc_output":"1f575-1f3fd","uc_match":"1f575-fe0f-1f3fd","uc_greedy":"1f575-fe0f-1f3fd","shortnames":[":spy_tone3:",":sleuth_or_spy_tone3:"],"category":"people"},":detective_tone4:":{"uc_base":"1f575-1f3fe","uc_output":"1f575-1f3fe","uc_match":"1f575-fe0f-1f3fe","uc_greedy":"1f575-fe0f-1f3fe","shortnames":[":spy_tone4:",":sleuth_or_spy_tone4:"],"category":"people"},":detective_tone5:":{"uc_base":"1f575-1f3ff","uc_output":"1f575-1f3ff","uc_match":"1f575-fe0f-1f3ff","uc_greedy":"1f575-fe0f-1f3ff","shortnames":[":spy_tone5:",":sleuth_or_spy_tone5:"],"category":"people"},":ear_tone1:":{"uc_base":"1f442-1f3fb","uc_output":"1f442-1f3fb","uc_match":"1f442-1f3fb","uc_greedy":"1f442-1f3fb","shortnames":[],"category":"people"},":ear_tone2:":{"uc_base":"1f442-1f3fc","uc_output":"1f442-1f3fc","uc_match":"1f442-1f3fc","uc_greedy":"1f442-1f3fc","shortnames":[],"category":"people"},":ear_tone3:":{"uc_base":"1f442-1f3fd","uc_output":"1f442-1f3fd","uc_match":"1f442-1f3fd","uc_greedy":"1f442-1f3fd","shortnames":[],"category":"people"},":ear_tone4:":{"uc_base":"1f442-1f3fe","uc_output":"1f442-1f3fe","uc_match":"1f442-1f3fe","uc_greedy":"1f442-1f3fe","shortnames":[],"category":"people"},":ear_tone5:":{"uc_base":"1f442-1f3ff","uc_output":"1f442-1f3ff","uc_match":"1f442-1f3ff","uc_greedy":"1f442-1f3ff","shortnames":[],"category":"people"},":elf_tone1:":{"uc_base":"1f9dd-1f3fb","uc_output":"1f9dd-1f3fb","uc_match":"1f9dd-1f3fb","uc_greedy":"1f9dd-1f3fb","shortnames":[":elf_light_skin_tone:"],"category":"people"},":elf_tone2:":{"uc_base":"1f9dd-1f3fc","uc_output":"1f9dd-1f3fc","uc_match":"1f9dd-1f3fc","uc_greedy":"1f9dd-1f3fc","shortnames":[":elf_medium_light_skin_tone:"],"category":"people"},":elf_tone3:":{"uc_base":"1f9dd-1f3fd","uc_output":"1f9dd-1f3fd","uc_match":"1f9dd-1f3fd","uc_greedy":"1f9dd-1f3fd","shortnames":[":elf_medium_skin_tone:"],"category":"people"},":elf_tone4:":{"uc_base":"1f9dd-1f3fe","uc_output":"1f9dd-1f3fe","uc_match":"1f9dd-1f3fe","uc_greedy":"1f9dd-1f3fe","shortnames":[":elf_medium_dark_skin_tone:"],"category":"people"},":elf_tone5:":{"uc_base":"1f9dd-1f3ff","uc_output":"1f9dd-1f3ff","uc_match":"1f9dd-1f3ff","uc_greedy":"1f9dd-1f3ff","shortnames":[":elf_dark_skin_tone:"],"category":"people"},":fairy_tone1:":{"uc_base":"1f9da-1f3fb","uc_output":"1f9da-1f3fb","uc_match":"1f9da-1f3fb","uc_greedy":"1f9da-1f3fb","shortnames":[":fairy_light_skin_tone:"],"category":"people"},":fairy_tone2:":{"uc_base":"1f9da-1f3fc","uc_output":"1f9da-1f3fc","uc_match":"1f9da-1f3fc","uc_greedy":"1f9da-1f3fc","shortnames":[":fairy_medium_light_skin_tone:"],"category":"people"},":fairy_tone3:":{"uc_base":"1f9da-1f3fd","uc_output":"1f9da-1f3fd","uc_match":"1f9da-1f3fd","uc_greedy":"1f9da-1f3fd","shortnames":[":fairy_medium_skin_tone:"],"category":"people"},":fairy_tone4:":{"uc_base":"1f9da-1f3fe","uc_output":"1f9da-1f3fe","uc_match":"1f9da-1f3fe","uc_greedy":"1f9da-1f3fe","shortnames":[":fairy_medium_dark_skin_tone:"],"category":"people"},":fairy_tone5:":{"uc_base":"1f9da-1f3ff","uc_output":"1f9da-1f3ff","uc_match":"1f9da-1f3ff","uc_greedy":"1f9da-1f3ff","shortnames":[":fairy_dark_skin_tone:"],"category":"people"},":fingers_crossed_tone1:":{"uc_base":"1f91e-1f3fb","uc_output":"1f91e-1f3fb","uc_match":"1f91e-1f3fb","uc_greedy":"1f91e-1f3fb","shortnames":[":hand_with_index_and_middle_fingers_crossed_tone1:"],"category":"people"},":fingers_crossed_tone2:":{"uc_base":"1f91e-1f3fc","uc_output":"1f91e-1f3fc","uc_match":"1f91e-1f3fc","uc_greedy":"1f91e-1f3fc","shortnames":[":hand_with_index_and_middle_fingers_crossed_tone2:"],"category":"people"},":fingers_crossed_tone3:":{"uc_base":"1f91e-1f3fd","uc_output":"1f91e-1f3fd","uc_match":"1f91e-1f3fd","uc_greedy":"1f91e-1f3fd","shortnames":[":hand_with_index_and_middle_fingers_crossed_tone3:"],"category":"people"},":fingers_crossed_tone4:":{"uc_base":"1f91e-1f3fe","uc_output":"1f91e-1f3fe","uc_match":"1f91e-1f3fe","uc_greedy":"1f91e-1f3fe","shortnames":[":hand_with_index_and_middle_fingers_crossed_tone4:"],"category":"people"},":fingers_crossed_tone5:":{"uc_base":"1f91e-1f3ff","uc_output":"1f91e-1f3ff","uc_match":"1f91e-1f3ff","uc_greedy":"1f91e-1f3ff","shortnames":[":hand_with_index_and_middle_fingers_crossed_tone5:"],"category":"people"},":flag_ac:":{"uc_base":"1f1e6-1f1e8","uc_output":"1f1e6-1f1e8","uc_match":"1f1e6-1f1e8","uc_greedy":"1f1e6-1f1e8","shortnames":[":ac:"],"category":"flags"},":flag_ad:":{"uc_base":"1f1e6-1f1e9","uc_output":"1f1e6-1f1e9","uc_match":"1f1e6-1f1e9","uc_greedy":"1f1e6-1f1e9","shortnames":[":ad:"],"category":"flags"},":flag_ae:":{"uc_base":"1f1e6-1f1ea","uc_output":"1f1e6-1f1ea","uc_match":"1f1e6-1f1ea","uc_greedy":"1f1e6-1f1ea","shortnames":[":ae:"],"category":"flags"},":flag_af:":{"uc_base":"1f1e6-1f1eb","uc_output":"1f1e6-1f1eb","uc_match":"1f1e6-1f1eb","uc_greedy":"1f1e6-1f1eb","shortnames":[":af:"],"category":"flags"},":flag_ag:":{"uc_base":"1f1e6-1f1ec","uc_output":"1f1e6-1f1ec","uc_match":"1f1e6-1f1ec","uc_greedy":"1f1e6-1f1ec","shortnames":[":ag:"],"category":"flags"},":flag_ai:":{"uc_base":"1f1e6-1f1ee","uc_output":"1f1e6-1f1ee","uc_match":"1f1e6-1f1ee","uc_greedy":"1f1e6-1f1ee","shortnames":[":ai:"],"category":"flags"},":flag_al:":{"uc_base":"1f1e6-1f1f1","uc_output":"1f1e6-1f1f1","uc_match":"1f1e6-1f1f1","uc_greedy":"1f1e6-1f1f1","shortnames":[":al:"],"category":"flags"},":flag_am:":{"uc_base":"1f1e6-1f1f2","uc_output":"1f1e6-1f1f2","uc_match":"1f1e6-1f1f2","uc_greedy":"1f1e6-1f1f2","shortnames":[":am:"],"category":"flags"},":flag_ao:":{"uc_base":"1f1e6-1f1f4","uc_output":"1f1e6-1f1f4","uc_match":"1f1e6-1f1f4","uc_greedy":"1f1e6-1f1f4","shortnames":[":ao:"],"category":"flags"},":flag_aq:":{"uc_base":"1f1e6-1f1f6","uc_output":"1f1e6-1f1f6","uc_match":"1f1e6-1f1f6","uc_greedy":"1f1e6-1f1f6","shortnames":[":aq:"],"category":"flags"},":flag_ar:":{"uc_base":"1f1e6-1f1f7","uc_output":"1f1e6-1f1f7","uc_match":"1f1e6-1f1f7","uc_greedy":"1f1e6-1f1f7","shortnames":[":ar:"],"category":"flags"},":flag_as:":{"uc_base":"1f1e6-1f1f8","uc_output":"1f1e6-1f1f8","uc_match":"1f1e6-1f1f8","uc_greedy":"1f1e6-1f1f8","shortnames":[":as:"],"category":"flags"},":flag_at:":{"uc_base":"1f1e6-1f1f9","uc_output":"1f1e6-1f1f9","uc_match":"1f1e6-1f1f9","uc_greedy":"1f1e6-1f1f9","shortnames":[":at:"],"category":"flags"},":flag_au:":{"uc_base":"1f1e6-1f1fa","uc_output":"1f1e6-1f1fa","uc_match":"1f1e6-1f1fa","uc_greedy":"1f1e6-1f1fa","shortnames":[":au:"],"category":"flags"},":flag_aw:":{"uc_base":"1f1e6-1f1fc","uc_output":"1f1e6-1f1fc","uc_match":"1f1e6-1f1fc","uc_greedy":"1f1e6-1f1fc","shortnames":[":aw:"],"category":"flags"},":flag_ax:":{"uc_base":"1f1e6-1f1fd","uc_output":"1f1e6-1f1fd","uc_match":"1f1e6-1f1fd","uc_greedy":"1f1e6-1f1fd","shortnames":[":ax:"],"category":"flags"},":flag_az:":{"uc_base":"1f1e6-1f1ff","uc_output":"1f1e6-1f1ff","uc_match":"1f1e6-1f1ff","uc_greedy":"1f1e6-1f1ff","shortnames":[":az:"],"category":"flags"},":flag_ba:":{"uc_base":"1f1e7-1f1e6","uc_output":"1f1e7-1f1e6","uc_match":"1f1e7-1f1e6","uc_greedy":"1f1e7-1f1e6","shortnames":[":ba:"],"category":"flags"},":flag_bb:":{"uc_base":"1f1e7-1f1e7","uc_output":"1f1e7-1f1e7","uc_match":"1f1e7-1f1e7","uc_greedy":"1f1e7-1f1e7","shortnames":[":bb:"],"category":"flags"},":flag_bd:":{"uc_base":"1f1e7-1f1e9","uc_output":"1f1e7-1f1e9","uc_match":"1f1e7-1f1e9","uc_greedy":"1f1e7-1f1e9","shortnames":[":bd:"],"category":"flags"},":flag_be:":{"uc_base":"1f1e7-1f1ea","uc_output":"1f1e7-1f1ea","uc_match":"1f1e7-1f1ea","uc_greedy":"1f1e7-1f1ea","shortnames":[":be:"],"category":"flags"},":flag_bf:":{"uc_base":"1f1e7-1f1eb","uc_output":"1f1e7-1f1eb","uc_match":"1f1e7-1f1eb","uc_greedy":"1f1e7-1f1eb","shortnames":[":bf:"],"category":"flags"},":flag_bg:":{"uc_base":"1f1e7-1f1ec","uc_output":"1f1e7-1f1ec","uc_match":"1f1e7-1f1ec","uc_greedy":"1f1e7-1f1ec","shortnames":[":bg:"],"category":"flags"},":flag_bh:":{"uc_base":"1f1e7-1f1ed","uc_output":"1f1e7-1f1ed","uc_match":"1f1e7-1f1ed","uc_greedy":"1f1e7-1f1ed","shortnames":[":bh:"],"category":"flags"},":flag_bi:":{"uc_base":"1f1e7-1f1ee","uc_output":"1f1e7-1f1ee","uc_match":"1f1e7-1f1ee","uc_greedy":"1f1e7-1f1ee","shortnames":[":bi:"],"category":"flags"},":flag_bj:":{"uc_base":"1f1e7-1f1ef","uc_output":"1f1e7-1f1ef","uc_match":"1f1e7-1f1ef","uc_greedy":"1f1e7-1f1ef","shortnames":[":bj:"],"category":"flags"},":flag_bl:":{"uc_base":"1f1e7-1f1f1","uc_output":"1f1e7-1f1f1","uc_match":"1f1e7-1f1f1","uc_greedy":"1f1e7-1f1f1","shortnames":[":bl:"],"category":"flags"},":flag_bm:":{"uc_base":"1f1e7-1f1f2","uc_output":"1f1e7-1f1f2","uc_match":"1f1e7-1f1f2","uc_greedy":"1f1e7-1f1f2","shortnames":[":bm:"],"category":"flags"},":flag_bn:":{"uc_base":"1f1e7-1f1f3","uc_output":"1f1e7-1f1f3","uc_match":"1f1e7-1f1f3","uc_greedy":"1f1e7-1f1f3","shortnames":[":bn:"],"category":"flags"},":flag_bo:":{"uc_base":"1f1e7-1f1f4","uc_output":"1f1e7-1f1f4","uc_match":"1f1e7-1f1f4","uc_greedy":"1f1e7-1f1f4","shortnames":[":bo:"],"category":"flags"},":flag_bq:":{"uc_base":"1f1e7-1f1f6","uc_output":"1f1e7-1f1f6","uc_match":"1f1e7-1f1f6","uc_greedy":"1f1e7-1f1f6","shortnames":[":bq:"],"category":"flags"},":flag_br:":{"uc_base":"1f1e7-1f1f7","uc_output":"1f1e7-1f1f7","uc_match":"1f1e7-1f1f7","uc_greedy":"1f1e7-1f1f7","shortnames":[":br:"],"category":"flags"},":flag_bs:":{"uc_base":"1f1e7-1f1f8","uc_output":"1f1e7-1f1f8","uc_match":"1f1e7-1f1f8","uc_greedy":"1f1e7-1f1f8","shortnames":[":bs:"],"category":"flags"},":flag_bt:":{"uc_base":"1f1e7-1f1f9","uc_output":"1f1e7-1f1f9","uc_match":"1f1e7-1f1f9","uc_greedy":"1f1e7-1f1f9","shortnames":[":bt:"],"category":"flags"},":flag_bv:":{"uc_base":"1f1e7-1f1fb","uc_output":"1f1e7-1f1fb","uc_match":"1f1e7-1f1fb","uc_greedy":"1f1e7-1f1fb","shortnames":[":bv:"],"category":"flags"},":flag_bw:":{"uc_base":"1f1e7-1f1fc","uc_output":"1f1e7-1f1fc","uc_match":"1f1e7-1f1fc","uc_greedy":"1f1e7-1f1fc","shortnames":[":bw:"],"category":"flags"},":flag_by:":{"uc_base":"1f1e7-1f1fe","uc_output":"1f1e7-1f1fe","uc_match":"1f1e7-1f1fe","uc_greedy":"1f1e7-1f1fe","shortnames":[":by:"],"category":"flags"},":flag_bz:":{"uc_base":"1f1e7-1f1ff","uc_output":"1f1e7-1f1ff","uc_match":"1f1e7-1f1ff","uc_greedy":"1f1e7-1f1ff","shortnames":[":bz:"],"category":"flags"},":flag_ca:":{"uc_base":"1f1e8-1f1e6","uc_output":"1f1e8-1f1e6","uc_match":"1f1e8-1f1e6","uc_greedy":"1f1e8-1f1e6","shortnames":[":ca:"],"category":"flags"},":flag_cc:":{"uc_base":"1f1e8-1f1e8","uc_output":"1f1e8-1f1e8","uc_match":"1f1e8-1f1e8","uc_greedy":"1f1e8-1f1e8","shortnames":[":cc:"],"category":"flags"},":flag_cd:":{"uc_base":"1f1e8-1f1e9","uc_output":"1f1e8-1f1e9","uc_match":"1f1e8-1f1e9","uc_greedy":"1f1e8-1f1e9","shortnames":[":congo:"],"category":"flags"},":flag_cf:":{"uc_base":"1f1e8-1f1eb","uc_output":"1f1e8-1f1eb","uc_match":"1f1e8-1f1eb","uc_greedy":"1f1e8-1f1eb","shortnames":[":cf:"],"category":"flags"},":flag_cg:":{"uc_base":"1f1e8-1f1ec","uc_output":"1f1e8-1f1ec","uc_match":"1f1e8-1f1ec","uc_greedy":"1f1e8-1f1ec","shortnames":[":cg:"],"category":"flags"},":flag_ch:":{"uc_base":"1f1e8-1f1ed","uc_output":"1f1e8-1f1ed","uc_match":"1f1e8-1f1ed","uc_greedy":"1f1e8-1f1ed","shortnames":[":ch:"],"category":"flags"},":flag_ci:":{"uc_base":"1f1e8-1f1ee","uc_output":"1f1e8-1f1ee","uc_match":"1f1e8-1f1ee","uc_greedy":"1f1e8-1f1ee","shortnames":[":ci:"],"category":"flags"},":flag_ck:":{"uc_base":"1f1e8-1f1f0","uc_output":"1f1e8-1f1f0","uc_match":"1f1e8-1f1f0","uc_greedy":"1f1e8-1f1f0","shortnames":[":ck:"],"category":"flags"},":flag_cl:":{"uc_base":"1f1e8-1f1f1","uc_output":"1f1e8-1f1f1","uc_match":"1f1e8-1f1f1","uc_greedy":"1f1e8-1f1f1","shortnames":[":chile:"],"category":"flags"},":flag_cm:":{"uc_base":"1f1e8-1f1f2","uc_output":"1f1e8-1f1f2","uc_match":"1f1e8-1f1f2","uc_greedy":"1f1e8-1f1f2","shortnames":[":cm:"],"category":"flags"},":flag_cn:":{"uc_base":"1f1e8-1f1f3","uc_output":"1f1e8-1f1f3","uc_match":"1f1e8-1f1f3","uc_greedy":"1f1e8-1f1f3","shortnames":[":cn:"],"category":"flags"},":flag_co:":{"uc_base":"1f1e8-1f1f4","uc_output":"1f1e8-1f1f4","uc_match":"1f1e8-1f1f4","uc_greedy":"1f1e8-1f1f4","shortnames":[":co:"],"category":"flags"},":flag_cp:":{"uc_base":"1f1e8-1f1f5","uc_output":"1f1e8-1f1f5","uc_match":"1f1e8-1f1f5","uc_greedy":"1f1e8-1f1f5","shortnames":[":cp:"],"category":"flags"},":flag_cr:":{"uc_base":"1f1e8-1f1f7","uc_output":"1f1e8-1f1f7","uc_match":"1f1e8-1f1f7","uc_greedy":"1f1e8-1f1f7","shortnames":[":cr:"],"category":"flags"},":flag_cu:":{"uc_base":"1f1e8-1f1fa","uc_output":"1f1e8-1f1fa","uc_match":"1f1e8-1f1fa","uc_greedy":"1f1e8-1f1fa","shortnames":[":cu:"],"category":"flags"},":flag_cv:":{"uc_base":"1f1e8-1f1fb","uc_output":"1f1e8-1f1fb","uc_match":"1f1e8-1f1fb","uc_greedy":"1f1e8-1f1fb","shortnames":[":cv:"],"category":"flags"},":flag_cw:":{"uc_base":"1f1e8-1f1fc","uc_output":"1f1e8-1f1fc","uc_match":"1f1e8-1f1fc","uc_greedy":"1f1e8-1f1fc","shortnames":[":cw:"],"category":"flags"},":flag_cx:":{"uc_base":"1f1e8-1f1fd","uc_output":"1f1e8-1f1fd","uc_match":"1f1e8-1f1fd","uc_greedy":"1f1e8-1f1fd","shortnames":[":cx:"],"category":"flags"},":flag_cy:":{"uc_base":"1f1e8-1f1fe","uc_output":"1f1e8-1f1fe","uc_match":"1f1e8-1f1fe","uc_greedy":"1f1e8-1f1fe","shortnames":[":cy:"],"category":"flags"},":flag_cz:":{"uc_base":"1f1e8-1f1ff","uc_output":"1f1e8-1f1ff","uc_match":"1f1e8-1f1ff","uc_greedy":"1f1e8-1f1ff","shortnames":[":cz:"],"category":"flags"},":flag_de:":{"uc_base":"1f1e9-1f1ea","uc_output":"1f1e9-1f1ea","uc_match":"1f1e9-1f1ea","uc_greedy":"1f1e9-1f1ea","shortnames":[":de:"],"category":"flags"},":flag_dg:":{"uc_base":"1f1e9-1f1ec","uc_output":"1f1e9-1f1ec","uc_match":"1f1e9-1f1ec","uc_greedy":"1f1e9-1f1ec","shortnames":[":dg:"],"category":"flags"},":flag_dj:":{"uc_base":"1f1e9-1f1ef","uc_output":"1f1e9-1f1ef","uc_match":"1f1e9-1f1ef","uc_greedy":"1f1e9-1f1ef","shortnames":[":dj:"],"category":"flags"},":flag_dk:":{"uc_base":"1f1e9-1f1f0","uc_output":"1f1e9-1f1f0","uc_match":"1f1e9-1f1f0","uc_greedy":"1f1e9-1f1f0","shortnames":[":dk:"],"category":"flags"},":flag_dm:":{"uc_base":"1f1e9-1f1f2","uc_output":"1f1e9-1f1f2","uc_match":"1f1e9-1f1f2","uc_greedy":"1f1e9-1f1f2","shortnames":[":dm:"],"category":"flags"},":flag_do:":{"uc_base":"1f1e9-1f1f4","uc_output":"1f1e9-1f1f4","uc_match":"1f1e9-1f1f4","uc_greedy":"1f1e9-1f1f4","shortnames":[":do:"],"category":"flags"},":flag_dz:":{"uc_base":"1f1e9-1f1ff","uc_output":"1f1e9-1f1ff","uc_match":"1f1e9-1f1ff","uc_greedy":"1f1e9-1f1ff","shortnames":[":dz:"],"category":"flags"},":flag_ea:":{"uc_base":"1f1ea-1f1e6","uc_output":"1f1ea-1f1e6","uc_match":"1f1ea-1f1e6","uc_greedy":"1f1ea-1f1e6","shortnames":[":ea:"],"category":"flags"},":flag_ec:":{"uc_base":"1f1ea-1f1e8","uc_output":"1f1ea-1f1e8","uc_match":"1f1ea-1f1e8","uc_greedy":"1f1ea-1f1e8","shortnames":[":ec:"],"category":"flags"},":flag_ee:":{"uc_base":"1f1ea-1f1ea","uc_output":"1f1ea-1f1ea","uc_match":"1f1ea-1f1ea","uc_greedy":"1f1ea-1f1ea","shortnames":[":ee:"],"category":"flags"},":flag_eg:":{"uc_base":"1f1ea-1f1ec","uc_output":"1f1ea-1f1ec","uc_match":"1f1ea-1f1ec","uc_greedy":"1f1ea-1f1ec","shortnames":[":eg:"],"category":"flags"},":flag_eh:":{"uc_base":"1f1ea-1f1ed","uc_output":"1f1ea-1f1ed","uc_match":"1f1ea-1f1ed","uc_greedy":"1f1ea-1f1ed","shortnames":[":eh:"],"category":"flags"},":flag_er:":{"uc_base":"1f1ea-1f1f7","uc_output":"1f1ea-1f1f7","uc_match":"1f1ea-1f1f7","uc_greedy":"1f1ea-1f1f7","shortnames":[":er:"],"category":"flags"},":flag_es:":{"uc_base":"1f1ea-1f1f8","uc_output":"1f1ea-1f1f8","uc_match":"1f1ea-1f1f8","uc_greedy":"1f1ea-1f1f8","shortnames":[":es:"],"category":"flags"},":flag_et:":{"uc_base":"1f1ea-1f1f9","uc_output":"1f1ea-1f1f9","uc_match":"1f1ea-1f1f9","uc_greedy":"1f1ea-1f1f9","shortnames":[":et:"],"category":"flags"},":flag_eu:":{"uc_base":"1f1ea-1f1fa","uc_output":"1f1ea-1f1fa","uc_match":"1f1ea-1f1fa","uc_greedy":"1f1ea-1f1fa","shortnames":[":eu:"],"category":"flags"},":flag_fi:":{"uc_base":"1f1eb-1f1ee","uc_output":"1f1eb-1f1ee","uc_match":"1f1eb-1f1ee","uc_greedy":"1f1eb-1f1ee","shortnames":[":fi:"],"category":"flags"},":flag_fj:":{"uc_base":"1f1eb-1f1ef","uc_output":"1f1eb-1f1ef","uc_match":"1f1eb-1f1ef","uc_greedy":"1f1eb-1f1ef","shortnames":[":fj:"],"category":"flags"},":flag_fk:":{"uc_base":"1f1eb-1f1f0","uc_output":"1f1eb-1f1f0","uc_match":"1f1eb-1f1f0","uc_greedy":"1f1eb-1f1f0","shortnames":[":fk:"],"category":"flags"},":flag_fm:":{"uc_base":"1f1eb-1f1f2","uc_output":"1f1eb-1f1f2","uc_match":"1f1eb-1f1f2","uc_greedy":"1f1eb-1f1f2","shortnames":[":fm:"],"category":"flags"},":flag_fo:":{"uc_base":"1f1eb-1f1f4","uc_output":"1f1eb-1f1f4","uc_match":"1f1eb-1f1f4","uc_greedy":"1f1eb-1f1f4","shortnames":[":fo:"],"category":"flags"},":flag_fr:":{"uc_base":"1f1eb-1f1f7","uc_output":"1f1eb-1f1f7","uc_match":"1f1eb-1f1f7","uc_greedy":"1f1eb-1f1f7","shortnames":[":fr:"],"category":"flags"},":flag_ga:":{"uc_base":"1f1ec-1f1e6","uc_output":"1f1ec-1f1e6","uc_match":"1f1ec-1f1e6","uc_greedy":"1f1ec-1f1e6","shortnames":[":ga:"],"category":"flags"},":flag_gb:":{"uc_base":"1f1ec-1f1e7","uc_output":"1f1ec-1f1e7","uc_match":"1f1ec-1f1e7","uc_greedy":"1f1ec-1f1e7","shortnames":[":gb:"],"category":"flags"},":flag_gd:":{"uc_base":"1f1ec-1f1e9","uc_output":"1f1ec-1f1e9","uc_match":"1f1ec-1f1e9","uc_greedy":"1f1ec-1f1e9","shortnames":[":gd:"],"category":"flags"},":flag_ge:":{"uc_base":"1f1ec-1f1ea","uc_output":"1f1ec-1f1ea","uc_match":"1f1ec-1f1ea","uc_greedy":"1f1ec-1f1ea","shortnames":[":ge:"],"category":"flags"},":flag_gf:":{"uc_base":"1f1ec-1f1eb","uc_output":"1f1ec-1f1eb","uc_match":"1f1ec-1f1eb","uc_greedy":"1f1ec-1f1eb","shortnames":[":gf:"],"category":"flags"},":flag_gg:":{"uc_base":"1f1ec-1f1ec","uc_output":"1f1ec-1f1ec","uc_match":"1f1ec-1f1ec","uc_greedy":"1f1ec-1f1ec","shortnames":[":gg:"],"category":"flags"},":flag_gh:":{"uc_base":"1f1ec-1f1ed","uc_output":"1f1ec-1f1ed","uc_match":"1f1ec-1f1ed","uc_greedy":"1f1ec-1f1ed","shortnames":[":gh:"],"category":"flags"},":flag_gi:":{"uc_base":"1f1ec-1f1ee","uc_output":"1f1ec-1f1ee","uc_match":"1f1ec-1f1ee","uc_greedy":"1f1ec-1f1ee","shortnames":[":gi:"],"category":"flags"},":flag_gl:":{"uc_base":"1f1ec-1f1f1","uc_output":"1f1ec-1f1f1","uc_match":"1f1ec-1f1f1","uc_greedy":"1f1ec-1f1f1","shortnames":[":gl:"],"category":"flags"},":flag_gm:":{"uc_base":"1f1ec-1f1f2","uc_output":"1f1ec-1f1f2","uc_match":"1f1ec-1f1f2","uc_greedy":"1f1ec-1f1f2","shortnames":[":gm:"],"category":"flags"},":flag_gn:":{"uc_base":"1f1ec-1f1f3","uc_output":"1f1ec-1f1f3","uc_match":"1f1ec-1f1f3","uc_greedy":"1f1ec-1f1f3","shortnames":[":gn:"],"category":"flags"},":flag_gp:":{"uc_base":"1f1ec-1f1f5","uc_output":"1f1ec-1f1f5","uc_match":"1f1ec-1f1f5","uc_greedy":"1f1ec-1f1f5","shortnames":[":gp:"],"category":"flags"},":flag_gq:":{"uc_base":"1f1ec-1f1f6","uc_output":"1f1ec-1f1f6","uc_match":"1f1ec-1f1f6","uc_greedy":"1f1ec-1f1f6","shortnames":[":gq:"],"category":"flags"},":flag_gr:":{"uc_base":"1f1ec-1f1f7","uc_output":"1f1ec-1f1f7","uc_match":"1f1ec-1f1f7","uc_greedy":"1f1ec-1f1f7","shortnames":[":gr:"],"category":"flags"},":flag_gs:":{"uc_base":"1f1ec-1f1f8","uc_output":"1f1ec-1f1f8","uc_match":"1f1ec-1f1f8","uc_greedy":"1f1ec-1f1f8","shortnames":[":gs:"],"category":"flags"},":flag_gt:":{"uc_base":"1f1ec-1f1f9","uc_output":"1f1ec-1f1f9","uc_match":"1f1ec-1f1f9","uc_greedy":"1f1ec-1f1f9","shortnames":[":gt:"],"category":"flags"},":flag_gu:":{"uc_base":"1f1ec-1f1fa","uc_output":"1f1ec-1f1fa","uc_match":"1f1ec-1f1fa","uc_greedy":"1f1ec-1f1fa","shortnames":[":gu:"],"category":"flags"},":flag_gw:":{"uc_base":"1f1ec-1f1fc","uc_output":"1f1ec-1f1fc","uc_match":"1f1ec-1f1fc","uc_greedy":"1f1ec-1f1fc","shortnames":[":gw:"],"category":"flags"},":flag_gy:":{"uc_base":"1f1ec-1f1fe","uc_output":"1f1ec-1f1fe","uc_match":"1f1ec-1f1fe","uc_greedy":"1f1ec-1f1fe","shortnames":[":gy:"],"category":"flags"},":flag_hk:":{"uc_base":"1f1ed-1f1f0","uc_output":"1f1ed-1f1f0","uc_match":"1f1ed-1f1f0","uc_greedy":"1f1ed-1f1f0","shortnames":[":hk:"],"category":"flags"},":flag_hm:":{"uc_base":"1f1ed-1f1f2","uc_output":"1f1ed-1f1f2","uc_match":"1f1ed-1f1f2","uc_greedy":"1f1ed-1f1f2","shortnames":[":hm:"],"category":"flags"},":flag_hn:":{"uc_base":"1f1ed-1f1f3","uc_output":"1f1ed-1f1f3","uc_match":"1f1ed-1f1f3","uc_greedy":"1f1ed-1f1f3","shortnames":[":hn:"],"category":"flags"},":flag_hr:":{"uc_base":"1f1ed-1f1f7","uc_output":"1f1ed-1f1f7","uc_match":"1f1ed-1f1f7","uc_greedy":"1f1ed-1f1f7","shortnames":[":hr:"],"category":"flags"},":flag_ht:":{"uc_base":"1f1ed-1f1f9","uc_output":"1f1ed-1f1f9","uc_match":"1f1ed-1f1f9","uc_greedy":"1f1ed-1f1f9","shortnames":[":ht:"],"category":"flags"},":flag_hu:":{"uc_base":"1f1ed-1f1fa","uc_output":"1f1ed-1f1fa","uc_match":"1f1ed-1f1fa","uc_greedy":"1f1ed-1f1fa","shortnames":[":hu:"],"category":"flags"},":flag_ic:":{"uc_base":"1f1ee-1f1e8","uc_output":"1f1ee-1f1e8","uc_match":"1f1ee-1f1e8","uc_greedy":"1f1ee-1f1e8","shortnames":[":ic:"],"category":"flags"},":flag_id:":{"uc_base":"1f1ee-1f1e9","uc_output":"1f1ee-1f1e9","uc_match":"1f1ee-1f1e9","uc_greedy":"1f1ee-1f1e9","shortnames":[":indonesia:"],"category":"flags"},":flag_ie:":{"uc_base":"1f1ee-1f1ea","uc_output":"1f1ee-1f1ea","uc_match":"1f1ee-1f1ea","uc_greedy":"1f1ee-1f1ea","shortnames":[":ie:"],"category":"flags"},":flag_il:":{"uc_base":"1f1ee-1f1f1","uc_output":"1f1ee-1f1f1","uc_match":"1f1ee-1f1f1","uc_greedy":"1f1ee-1f1f1","shortnames":[":il:"],"category":"flags"},":flag_im:":{"uc_base":"1f1ee-1f1f2","uc_output":"1f1ee-1f1f2","uc_match":"1f1ee-1f1f2","uc_greedy":"1f1ee-1f1f2","shortnames":[":im:"],"category":"flags"},":flag_in:":{"uc_base":"1f1ee-1f1f3","uc_output":"1f1ee-1f1f3","uc_match":"1f1ee-1f1f3","uc_greedy":"1f1ee-1f1f3","shortnames":[":in:"],"category":"flags"},":flag_io:":{"uc_base":"1f1ee-1f1f4","uc_output":"1f1ee-1f1f4","uc_match":"1f1ee-1f1f4","uc_greedy":"1f1ee-1f1f4","shortnames":[":io:"],"category":"flags"},":flag_iq:":{"uc_base":"1f1ee-1f1f6","uc_output":"1f1ee-1f1f6","uc_match":"1f1ee-1f1f6","uc_greedy":"1f1ee-1f1f6","shortnames":[":iq:"],"category":"flags"},":flag_ir:":{"uc_base":"1f1ee-1f1f7","uc_output":"1f1ee-1f1f7","uc_match":"1f1ee-1f1f7","uc_greedy":"1f1ee-1f1f7","shortnames":[":ir:"],"category":"flags"},":flag_is:":{"uc_base":"1f1ee-1f1f8","uc_output":"1f1ee-1f1f8","uc_match":"1f1ee-1f1f8","uc_greedy":"1f1ee-1f1f8","shortnames":[":is:"],"category":"flags"},":flag_it:":{"uc_base":"1f1ee-1f1f9","uc_output":"1f1ee-1f1f9","uc_match":"1f1ee-1f1f9","uc_greedy":"1f1ee-1f1f9","shortnames":[":it:"],"category":"flags"},":flag_je:":{"uc_base":"1f1ef-1f1ea","uc_output":"1f1ef-1f1ea","uc_match":"1f1ef-1f1ea","uc_greedy":"1f1ef-1f1ea","shortnames":[":je:"],"category":"flags"},":flag_jm:":{"uc_base":"1f1ef-1f1f2","uc_output":"1f1ef-1f1f2","uc_match":"1f1ef-1f1f2","uc_greedy":"1f1ef-1f1f2","shortnames":[":jm:"],"category":"flags"},":flag_jo:":{"uc_base":"1f1ef-1f1f4","uc_output":"1f1ef-1f1f4","uc_match":"1f1ef-1f1f4","uc_greedy":"1f1ef-1f1f4","shortnames":[":jo:"],"category":"flags"},":flag_jp:":{"uc_base":"1f1ef-1f1f5","uc_output":"1f1ef-1f1f5","uc_match":"1f1ef-1f1f5","uc_greedy":"1f1ef-1f1f5","shortnames":[":jp:"],"category":"flags"},":flag_ke:":{"uc_base":"1f1f0-1f1ea","uc_output":"1f1f0-1f1ea","uc_match":"1f1f0-1f1ea","uc_greedy":"1f1f0-1f1ea","shortnames":[":ke:"],"category":"flags"},":flag_kg:":{"uc_base":"1f1f0-1f1ec","uc_output":"1f1f0-1f1ec","uc_match":"1f1f0-1f1ec","uc_greedy":"1f1f0-1f1ec","shortnames":[":kg:"],"category":"flags"},":flag_kh:":{"uc_base":"1f1f0-1f1ed","uc_output":"1f1f0-1f1ed","uc_match":"1f1f0-1f1ed","uc_greedy":"1f1f0-1f1ed","shortnames":[":kh:"],"category":"flags"},":flag_ki:":{"uc_base":"1f1f0-1f1ee","uc_output":"1f1f0-1f1ee","uc_match":"1f1f0-1f1ee","uc_greedy":"1f1f0-1f1ee","shortnames":[":ki:"],"category":"flags"},":flag_km:":{"uc_base":"1f1f0-1f1f2","uc_output":"1f1f0-1f1f2","uc_match":"1f1f0-1f1f2","uc_greedy":"1f1f0-1f1f2","shortnames":[":km:"],"category":"flags"},":flag_kn:":{"uc_base":"1f1f0-1f1f3","uc_output":"1f1f0-1f1f3","uc_match":"1f1f0-1f1f3","uc_greedy":"1f1f0-1f1f3","shortnames":[":kn:"],"category":"flags"},":flag_kp:":{"uc_base":"1f1f0-1f1f5","uc_output":"1f1f0-1f1f5","uc_match":"1f1f0-1f1f5","uc_greedy":"1f1f0-1f1f5","shortnames":[":kp:"],"category":"flags"},":flag_kr:":{"uc_base":"1f1f0-1f1f7","uc_output":"1f1f0-1f1f7","uc_match":"1f1f0-1f1f7","uc_greedy":"1f1f0-1f1f7","shortnames":[":kr:"],"category":"flags"},":flag_kw:":{"uc_base":"1f1f0-1f1fc","uc_output":"1f1f0-1f1fc","uc_match":"1f1f0-1f1fc","uc_greedy":"1f1f0-1f1fc","shortnames":[":kw:"],"category":"flags"},":flag_ky:":{"uc_base":"1f1f0-1f1fe","uc_output":"1f1f0-1f1fe","uc_match":"1f1f0-1f1fe","uc_greedy":"1f1f0-1f1fe","shortnames":[":ky:"],"category":"flags"},":flag_kz:":{"uc_base":"1f1f0-1f1ff","uc_output":"1f1f0-1f1ff","uc_match":"1f1f0-1f1ff","uc_greedy":"1f1f0-1f1ff","shortnames":[":kz:"],"category":"flags"},":flag_la:":{"uc_base":"1f1f1-1f1e6","uc_output":"1f1f1-1f1e6","uc_match":"1f1f1-1f1e6","uc_greedy":"1f1f1-1f1e6","shortnames":[":la:"],"category":"flags"},":flag_lb:":{"uc_base":"1f1f1-1f1e7","uc_output":"1f1f1-1f1e7","uc_match":"1f1f1-1f1e7","uc_greedy":"1f1f1-1f1e7","shortnames":[":lb:"],"category":"flags"},":flag_lc:":{"uc_base":"1f1f1-1f1e8","uc_output":"1f1f1-1f1e8","uc_match":"1f1f1-1f1e8","uc_greedy":"1f1f1-1f1e8","shortnames":[":lc:"],"category":"flags"},":flag_li:":{"uc_base":"1f1f1-1f1ee","uc_output":"1f1f1-1f1ee","uc_match":"1f1f1-1f1ee","uc_greedy":"1f1f1-1f1ee","shortnames":[":li:"],"category":"flags"},":flag_lk:":{"uc_base":"1f1f1-1f1f0","uc_output":"1f1f1-1f1f0","uc_match":"1f1f1-1f1f0","uc_greedy":"1f1f1-1f1f0","shortnames":[":lk:"],"category":"flags"},":flag_lr:":{"uc_base":"1f1f1-1f1f7","uc_output":"1f1f1-1f1f7","uc_match":"1f1f1-1f1f7","uc_greedy":"1f1f1-1f1f7","shortnames":[":lr:"],"category":"flags"},":flag_ls:":{"uc_base":"1f1f1-1f1f8","uc_output":"1f1f1-1f1f8","uc_match":"1f1f1-1f1f8","uc_greedy":"1f1f1-1f1f8","shortnames":[":ls:"],"category":"flags"},":flag_lt:":{"uc_base":"1f1f1-1f1f9","uc_output":"1f1f1-1f1f9","uc_match":"1f1f1-1f1f9","uc_greedy":"1f1f1-1f1f9","shortnames":[":lt:"],"category":"flags"},":flag_lu:":{"uc_base":"1f1f1-1f1fa","uc_output":"1f1f1-1f1fa","uc_match":"1f1f1-1f1fa","uc_greedy":"1f1f1-1f1fa","shortnames":[":lu:"],"category":"flags"},":flag_lv:":{"uc_base":"1f1f1-1f1fb","uc_output":"1f1f1-1f1fb","uc_match":"1f1f1-1f1fb","uc_greedy":"1f1f1-1f1fb","shortnames":[":lv:"],"category":"flags"},":flag_ly:":{"uc_base":"1f1f1-1f1fe","uc_output":"1f1f1-1f1fe","uc_match":"1f1f1-1f1fe","uc_greedy":"1f1f1-1f1fe","shortnames":[":ly:"],"category":"flags"},":flag_ma:":{"uc_base":"1f1f2-1f1e6","uc_output":"1f1f2-1f1e6","uc_match":"1f1f2-1f1e6","uc_greedy":"1f1f2-1f1e6","shortnames":[":ma:"],"category":"flags"},":flag_mc:":{"uc_base":"1f1f2-1f1e8","uc_output":"1f1f2-1f1e8","uc_match":"1f1f2-1f1e8","uc_greedy":"1f1f2-1f1e8","shortnames":[":mc:"],"category":"flags"},":flag_md:":{"uc_base":"1f1f2-1f1e9","uc_output":"1f1f2-1f1e9","uc_match":"1f1f2-1f1e9","uc_greedy":"1f1f2-1f1e9","shortnames":[":md:"],"category":"flags"},":flag_me:":{"uc_base":"1f1f2-1f1ea","uc_output":"1f1f2-1f1ea","uc_match":"1f1f2-1f1ea","uc_greedy":"1f1f2-1f1ea","shortnames":[":me:"],"category":"flags"},":flag_mf:":{"uc_base":"1f1f2-1f1eb","uc_output":"1f1f2-1f1eb","uc_match":"1f1f2-1f1eb","uc_greedy":"1f1f2-1f1eb","shortnames":[":mf:"],"category":"flags"},":flag_mg:":{"uc_base":"1f1f2-1f1ec","uc_output":"1f1f2-1f1ec","uc_match":"1f1f2-1f1ec","uc_greedy":"1f1f2-1f1ec","shortnames":[":mg:"],"category":"flags"},":flag_mh:":{"uc_base":"1f1f2-1f1ed","uc_output":"1f1f2-1f1ed","uc_match":"1f1f2-1f1ed","uc_greedy":"1f1f2-1f1ed","shortnames":[":mh:"],"category":"flags"},":flag_mk:":{"uc_base":"1f1f2-1f1f0","uc_output":"1f1f2-1f1f0","uc_match":"1f1f2-1f1f0","uc_greedy":"1f1f2-1f1f0","shortnames":[":mk:"],"category":"flags"},":flag_ml:":{"uc_base":"1f1f2-1f1f1","uc_output":"1f1f2-1f1f1","uc_match":"1f1f2-1f1f1","uc_greedy":"1f1f2-1f1f1","shortnames":[":ml:"],"category":"flags"},":flag_mm:":{"uc_base":"1f1f2-1f1f2","uc_output":"1f1f2-1f1f2","uc_match":"1f1f2-1f1f2","uc_greedy":"1f1f2-1f1f2","shortnames":[":mm:"],"category":"flags"},":flag_mn:":{"uc_base":"1f1f2-1f1f3","uc_output":"1f1f2-1f1f3","uc_match":"1f1f2-1f1f3","uc_greedy":"1f1f2-1f1f3","shortnames":[":mn:"],"category":"flags"},":flag_mo:":{"uc_base":"1f1f2-1f1f4","uc_output":"1f1f2-1f1f4","uc_match":"1f1f2-1f1f4","uc_greedy":"1f1f2-1f1f4","shortnames":[":mo:"],"category":"flags"},":flag_mp:":{"uc_base":"1f1f2-1f1f5","uc_output":"1f1f2-1f1f5","uc_match":"1f1f2-1f1f5","uc_greedy":"1f1f2-1f1f5","shortnames":[":mp:"],"category":"flags"},":flag_mq:":{"uc_base":"1f1f2-1f1f6","uc_output":"1f1f2-1f1f6","uc_match":"1f1f2-1f1f6","uc_greedy":"1f1f2-1f1f6","shortnames":[":mq:"],"category":"flags"},":flag_mr:":{"uc_base":"1f1f2-1f1f7","uc_output":"1f1f2-1f1f7","uc_match":"1f1f2-1f1f7","uc_greedy":"1f1f2-1f1f7","shortnames":[":mr:"],"category":"flags"},":flag_ms:":{"uc_base":"1f1f2-1f1f8","uc_output":"1f1f2-1f1f8","uc_match":"1f1f2-1f1f8","uc_greedy":"1f1f2-1f1f8","shortnames":[":ms:"],"category":"flags"},":flag_mt:":{"uc_base":"1f1f2-1f1f9","uc_output":"1f1f2-1f1f9","uc_match":"1f1f2-1f1f9","uc_greedy":"1f1f2-1f1f9","shortnames":[":mt:"],"category":"flags"},":flag_mu:":{"uc_base":"1f1f2-1f1fa","uc_output":"1f1f2-1f1fa","uc_match":"1f1f2-1f1fa","uc_greedy":"1f1f2-1f1fa","shortnames":[":mu:"],"category":"flags"},":flag_mv:":{"uc_base":"1f1f2-1f1fb","uc_output":"1f1f2-1f1fb","uc_match":"1f1f2-1f1fb","uc_greedy":"1f1f2-1f1fb","shortnames":[":mv:"],"category":"flags"},":flag_mw:":{"uc_base":"1f1f2-1f1fc","uc_output":"1f1f2-1f1fc","uc_match":"1f1f2-1f1fc","uc_greedy":"1f1f2-1f1fc","shortnames":[":mw:"],"category":"flags"},":flag_mx:":{"uc_base":"1f1f2-1f1fd","uc_output":"1f1f2-1f1fd","uc_match":"1f1f2-1f1fd","uc_greedy":"1f1f2-1f1fd","shortnames":[":mx:"],"category":"flags"},":flag_my:":{"uc_base":"1f1f2-1f1fe","uc_output":"1f1f2-1f1fe","uc_match":"1f1f2-1f1fe","uc_greedy":"1f1f2-1f1fe","shortnames":[":my:"],"category":"flags"},":flag_mz:":{"uc_base":"1f1f2-1f1ff","uc_output":"1f1f2-1f1ff","uc_match":"1f1f2-1f1ff","uc_greedy":"1f1f2-1f1ff","shortnames":[":mz:"],"category":"flags"},":flag_na:":{"uc_base":"1f1f3-1f1e6","uc_output":"1f1f3-1f1e6","uc_match":"1f1f3-1f1e6","uc_greedy":"1f1f3-1f1e6","shortnames":[":na:"],"category":"flags"},":flag_nc:":{"uc_base":"1f1f3-1f1e8","uc_output":"1f1f3-1f1e8","uc_match":"1f1f3-1f1e8","uc_greedy":"1f1f3-1f1e8","shortnames":[":nc:"],"category":"flags"},":flag_ne:":{"uc_base":"1f1f3-1f1ea","uc_output":"1f1f3-1f1ea","uc_match":"1f1f3-1f1ea","uc_greedy":"1f1f3-1f1ea","shortnames":[":ne:"],"category":"flags"},":flag_nf:":{"uc_base":"1f1f3-1f1eb","uc_output":"1f1f3-1f1eb","uc_match":"1f1f3-1f1eb","uc_greedy":"1f1f3-1f1eb","shortnames":[":nf:"],"category":"flags"},":flag_ng:":{"uc_base":"1f1f3-1f1ec","uc_output":"1f1f3-1f1ec","uc_match":"1f1f3-1f1ec","uc_greedy":"1f1f3-1f1ec","shortnames":[":nigeria:"],"category":"flags"},":flag_ni:":{"uc_base":"1f1f3-1f1ee","uc_output":"1f1f3-1f1ee","uc_match":"1f1f3-1f1ee","uc_greedy":"1f1f3-1f1ee","shortnames":[":ni:"],"category":"flags"},":flag_nl:":{"uc_base":"1f1f3-1f1f1","uc_output":"1f1f3-1f1f1","uc_match":"1f1f3-1f1f1","uc_greedy":"1f1f3-1f1f1","shortnames":[":nl:"],"category":"flags"},":flag_no:":{"uc_base":"1f1f3-1f1f4","uc_output":"1f1f3-1f1f4","uc_match":"1f1f3-1f1f4","uc_greedy":"1f1f3-1f1f4","shortnames":[":no:"],"category":"flags"},":flag_np:":{"uc_base":"1f1f3-1f1f5","uc_output":"1f1f3-1f1f5","uc_match":"1f1f3-1f1f5","uc_greedy":"1f1f3-1f1f5","shortnames":[":np:"],"category":"flags"},":flag_nr:":{"uc_base":"1f1f3-1f1f7","uc_output":"1f1f3-1f1f7","uc_match":"1f1f3-1f1f7","uc_greedy":"1f1f3-1f1f7","shortnames":[":nr:"],"category":"flags"},":flag_nu:":{"uc_base":"1f1f3-1f1fa","uc_output":"1f1f3-1f1fa","uc_match":"1f1f3-1f1fa","uc_greedy":"1f1f3-1f1fa","shortnames":[":nu:"],"category":"flags"},":flag_nz:":{"uc_base":"1f1f3-1f1ff","uc_output":"1f1f3-1f1ff","uc_match":"1f1f3-1f1ff","uc_greedy":"1f1f3-1f1ff","shortnames":[":nz:"],"category":"flags"},":flag_om:":{"uc_base":"1f1f4-1f1f2","uc_output":"1f1f4-1f1f2","uc_match":"1f1f4-1f1f2","uc_greedy":"1f1f4-1f1f2","shortnames":[":om:"],"category":"flags"},":flag_pa:":{"uc_base":"1f1f5-1f1e6","uc_output":"1f1f5-1f1e6","uc_match":"1f1f5-1f1e6","uc_greedy":"1f1f5-1f1e6","shortnames":[":pa:"],"category":"flags"},":flag_pe:":{"uc_base":"1f1f5-1f1ea","uc_output":"1f1f5-1f1ea","uc_match":"1f1f5-1f1ea","uc_greedy":"1f1f5-1f1ea","shortnames":[":pe:"],"category":"flags"},":flag_pf:":{"uc_base":"1f1f5-1f1eb","uc_output":"1f1f5-1f1eb","uc_match":"1f1f5-1f1eb","uc_greedy":"1f1f5-1f1eb","shortnames":[":pf:"],"category":"flags"},":flag_pg:":{"uc_base":"1f1f5-1f1ec","uc_output":"1f1f5-1f1ec","uc_match":"1f1f5-1f1ec","uc_greedy":"1f1f5-1f1ec","shortnames":[":pg:"],"category":"flags"},":flag_ph:":{"uc_base":"1f1f5-1f1ed","uc_output":"1f1f5-1f1ed","uc_match":"1f1f5-1f1ed","uc_greedy":"1f1f5-1f1ed","shortnames":[":ph:"],"category":"flags"},":flag_pk:":{"uc_base":"1f1f5-1f1f0","uc_output":"1f1f5-1f1f0","uc_match":"1f1f5-1f1f0","uc_greedy":"1f1f5-1f1f0","shortnames":[":pk:"],"category":"flags"},":flag_pl:":{"uc_base":"1f1f5-1f1f1","uc_output":"1f1f5-1f1f1","uc_match":"1f1f5-1f1f1","uc_greedy":"1f1f5-1f1f1","shortnames":[":pl:"],"category":"flags"},":flag_pm:":{"uc_base":"1f1f5-1f1f2","uc_output":"1f1f5-1f1f2","uc_match":"1f1f5-1f1f2","uc_greedy":"1f1f5-1f1f2","shortnames":[":pm:"],"category":"flags"},":flag_pn:":{"uc_base":"1f1f5-1f1f3","uc_output":"1f1f5-1f1f3","uc_match":"1f1f5-1f1f3","uc_greedy":"1f1f5-1f1f3","shortnames":[":pn:"],"category":"flags"},":flag_pr:":{"uc_base":"1f1f5-1f1f7","uc_output":"1f1f5-1f1f7","uc_match":"1f1f5-1f1f7","uc_greedy":"1f1f5-1f1f7","shortnames":[":pr:"],"category":"flags"},":flag_ps:":{"uc_base":"1f1f5-1f1f8","uc_output":"1f1f5-1f1f8","uc_match":"1f1f5-1f1f8","uc_greedy":"1f1f5-1f1f8","shortnames":[":ps:"],"category":"flags"},":flag_pt:":{"uc_base":"1f1f5-1f1f9","uc_output":"1f1f5-1f1f9","uc_match":"1f1f5-1f1f9","uc_greedy":"1f1f5-1f1f9","shortnames":[":pt:"],"category":"flags"},":flag_pw:":{"uc_base":"1f1f5-1f1fc","uc_output":"1f1f5-1f1fc","uc_match":"1f1f5-1f1fc","uc_greedy":"1f1f5-1f1fc","shortnames":[":pw:"],"category":"flags"},":flag_py:":{"uc_base":"1f1f5-1f1fe","uc_output":"1f1f5-1f1fe","uc_match":"1f1f5-1f1fe","uc_greedy":"1f1f5-1f1fe","shortnames":[":py:"],"category":"flags"},":flag_qa:":{"uc_base":"1f1f6-1f1e6","uc_output":"1f1f6-1f1e6","uc_match":"1f1f6-1f1e6","uc_greedy":"1f1f6-1f1e6","shortnames":[":qa:"],"category":"flags"},":flag_re:":{"uc_base":"1f1f7-1f1ea","uc_output":"1f1f7-1f1ea","uc_match":"1f1f7-1f1ea","uc_greedy":"1f1f7-1f1ea","shortnames":[":re:"],"category":"flags"},":flag_ro:":{"uc_base":"1f1f7-1f1f4","uc_output":"1f1f7-1f1f4","uc_match":"1f1f7-1f1f4","uc_greedy":"1f1f7-1f1f4","shortnames":[":ro:"],"category":"flags"},":flag_rs:":{"uc_base":"1f1f7-1f1f8","uc_output":"1f1f7-1f1f8","uc_match":"1f1f7-1f1f8","uc_greedy":"1f1f7-1f1f8","shortnames":[":rs:"],"category":"flags"},":flag_ru:":{"uc_base":"1f1f7-1f1fa","uc_output":"1f1f7-1f1fa","uc_match":"1f1f7-1f1fa","uc_greedy":"1f1f7-1f1fa","shortnames":[":ru:"],"category":"flags"},":flag_rw:":{"uc_base":"1f1f7-1f1fc","uc_output":"1f1f7-1f1fc","uc_match":"1f1f7-1f1fc","uc_greedy":"1f1f7-1f1fc","shortnames":[":rw:"],"category":"flags"},":flag_sa:":{"uc_base":"1f1f8-1f1e6","uc_output":"1f1f8-1f1e6","uc_match":"1f1f8-1f1e6","uc_greedy":"1f1f8-1f1e6","shortnames":[":saudiarabia:",":saudi:"],"category":"flags"},":flag_sb:":{"uc_base":"1f1f8-1f1e7","uc_output":"1f1f8-1f1e7","uc_match":"1f1f8-1f1e7","uc_greedy":"1f1f8-1f1e7","shortnames":[":sb:"],"category":"flags"},":flag_sc:":{"uc_base":"1f1f8-1f1e8","uc_output":"1f1f8-1f1e8","uc_match":"1f1f8-1f1e8","uc_greedy":"1f1f8-1f1e8","shortnames":[":sc:"],"category":"flags"},":flag_sd:":{"uc_base":"1f1f8-1f1e9","uc_output":"1f1f8-1f1e9","uc_match":"1f1f8-1f1e9","uc_greedy":"1f1f8-1f1e9","shortnames":[":sd:"],"category":"flags"},":flag_se:":{"uc_base":"1f1f8-1f1ea","uc_output":"1f1f8-1f1ea","uc_match":"1f1f8-1f1ea","uc_greedy":"1f1f8-1f1ea","shortnames":[":se:"],"category":"flags"},":flag_sg:":{"uc_base":"1f1f8-1f1ec","uc_output":"1f1f8-1f1ec","uc_match":"1f1f8-1f1ec","uc_greedy":"1f1f8-1f1ec","shortnames":[":sg:"],"category":"flags"},":flag_sh:":{"uc_base":"1f1f8-1f1ed","uc_output":"1f1f8-1f1ed","uc_match":"1f1f8-1f1ed","uc_greedy":"1f1f8-1f1ed","shortnames":[":sh:"],"category":"flags"},":flag_si:":{"uc_base":"1f1f8-1f1ee","uc_output":"1f1f8-1f1ee","uc_match":"1f1f8-1f1ee","uc_greedy":"1f1f8-1f1ee","shortnames":[":si:"],"category":"flags"},":flag_sj:":{"uc_base":"1f1f8-1f1ef","uc_output":"1f1f8-1f1ef","uc_match":"1f1f8-1f1ef","uc_greedy":"1f1f8-1f1ef","shortnames":[":sj:"],"category":"flags"},":flag_sk:":{"uc_base":"1f1f8-1f1f0","uc_output":"1f1f8-1f1f0","uc_match":"1f1f8-1f1f0","uc_greedy":"1f1f8-1f1f0","shortnames":[":sk:"],"category":"flags"},":flag_sl:":{"uc_base":"1f1f8-1f1f1","uc_output":"1f1f8-1f1f1","uc_match":"1f1f8-1f1f1","uc_greedy":"1f1f8-1f1f1","shortnames":[":sl:"],"category":"flags"},":flag_sm:":{"uc_base":"1f1f8-1f1f2","uc_output":"1f1f8-1f1f2","uc_match":"1f1f8-1f1f2","uc_greedy":"1f1f8-1f1f2","shortnames":[":sm:"],"category":"flags"},":flag_sn:":{"uc_base":"1f1f8-1f1f3","uc_output":"1f1f8-1f1f3","uc_match":"1f1f8-1f1f3","uc_greedy":"1f1f8-1f1f3","shortnames":[":sn:"],"category":"flags"},":flag_so:":{"uc_base":"1f1f8-1f1f4","uc_output":"1f1f8-1f1f4","uc_match":"1f1f8-1f1f4","uc_greedy":"1f1f8-1f1f4","shortnames":[":so:"],"category":"flags"},":flag_sr:":{"uc_base":"1f1f8-1f1f7","uc_output":"1f1f8-1f1f7","uc_match":"1f1f8-1f1f7","uc_greedy":"1f1f8-1f1f7","shortnames":[":sr:"],"category":"flags"},":flag_ss:":{"uc_base":"1f1f8-1f1f8","uc_output":"1f1f8-1f1f8","uc_match":"1f1f8-1f1f8","uc_greedy":"1f1f8-1f1f8","shortnames":[":ss:"],"category":"flags"},":flag_st:":{"uc_base":"1f1f8-1f1f9","uc_output":"1f1f8-1f1f9","uc_match":"1f1f8-1f1f9","uc_greedy":"1f1f8-1f1f9","shortnames":[":st:"],"category":"flags"},":flag_sv:":{"uc_base":"1f1f8-1f1fb","uc_output":"1f1f8-1f1fb","uc_match":"1f1f8-1f1fb","uc_greedy":"1f1f8-1f1fb","shortnames":[":sv:"],"category":"flags"},":flag_sx:":{"uc_base":"1f1f8-1f1fd","uc_output":"1f1f8-1f1fd","uc_match":"1f1f8-1f1fd","uc_greedy":"1f1f8-1f1fd","shortnames":[":sx:"],"category":"flags"},":flag_sy:":{"uc_base":"1f1f8-1f1fe","uc_output":"1f1f8-1f1fe","uc_match":"1f1f8-1f1fe","uc_greedy":"1f1f8-1f1fe","shortnames":[":sy:"],"category":"flags"},":flag_sz:":{"uc_base":"1f1f8-1f1ff","uc_output":"1f1f8-1f1ff","uc_match":"1f1f8-1f1ff","uc_greedy":"1f1f8-1f1ff","shortnames":[":sz:"],"category":"flags"},":flag_ta:":{"uc_base":"1f1f9-1f1e6","uc_output":"1f1f9-1f1e6","uc_match":"1f1f9-1f1e6","uc_greedy":"1f1f9-1f1e6","shortnames":[":ta:"],"category":"flags"},":flag_tc:":{"uc_base":"1f1f9-1f1e8","uc_output":"1f1f9-1f1e8","uc_match":"1f1f9-1f1e8","uc_greedy":"1f1f9-1f1e8","shortnames":[":tc:"],"category":"flags"},":flag_td:":{"uc_base":"1f1f9-1f1e9","uc_output":"1f1f9-1f1e9","uc_match":"1f1f9-1f1e9","uc_greedy":"1f1f9-1f1e9","shortnames":[":td:"],"category":"flags"},":flag_tf:":{"uc_base":"1f1f9-1f1eb","uc_output":"1f1f9-1f1eb","uc_match":"1f1f9-1f1eb","uc_greedy":"1f1f9-1f1eb","shortnames":[":tf:"],"category":"flags"},":flag_tg:":{"uc_base":"1f1f9-1f1ec","uc_output":"1f1f9-1f1ec","uc_match":"1f1f9-1f1ec","uc_greedy":"1f1f9-1f1ec","shortnames":[":tg:"],"category":"flags"},":flag_th:":{"uc_base":"1f1f9-1f1ed","uc_output":"1f1f9-1f1ed","uc_match":"1f1f9-1f1ed","uc_greedy":"1f1f9-1f1ed","shortnames":[":th:"],"category":"flags"},":flag_tj:":{"uc_base":"1f1f9-1f1ef","uc_output":"1f1f9-1f1ef","uc_match":"1f1f9-1f1ef","uc_greedy":"1f1f9-1f1ef","shortnames":[":tj:"],"category":"flags"},":flag_tk:":{"uc_base":"1f1f9-1f1f0","uc_output":"1f1f9-1f1f0","uc_match":"1f1f9-1f1f0","uc_greedy":"1f1f9-1f1f0","shortnames":[":tk:"],"category":"flags"},":flag_tl:":{"uc_base":"1f1f9-1f1f1","uc_output":"1f1f9-1f1f1","uc_match":"1f1f9-1f1f1","uc_greedy":"1f1f9-1f1f1","shortnames":[":tl:"],"category":"flags"},":flag_tm:":{"uc_base":"1f1f9-1f1f2","uc_output":"1f1f9-1f1f2","uc_match":"1f1f9-1f1f2","uc_greedy":"1f1f9-1f1f2","shortnames":[":turkmenistan:"],"category":"flags"},":flag_tn:":{"uc_base":"1f1f9-1f1f3","uc_output":"1f1f9-1f1f3","uc_match":"1f1f9-1f1f3","uc_greedy":"1f1f9-1f1f3","shortnames":[":tn:"],"category":"flags"},":flag_to:":{"uc_base":"1f1f9-1f1f4","uc_output":"1f1f9-1f1f4","uc_match":"1f1f9-1f1f4","uc_greedy":"1f1f9-1f1f4","shortnames":[":to:"],"category":"flags"},":flag_tr:":{"uc_base":"1f1f9-1f1f7","uc_output":"1f1f9-1f1f7","uc_match":"1f1f9-1f1f7","uc_greedy":"1f1f9-1f1f7","shortnames":[":tr:"],"category":"flags"},":flag_tt:":{"uc_base":"1f1f9-1f1f9","uc_output":"1f1f9-1f1f9","uc_match":"1f1f9-1f1f9","uc_greedy":"1f1f9-1f1f9","shortnames":[":tt:"],"category":"flags"},":flag_tv:":{"uc_base":"1f1f9-1f1fb","uc_output":"1f1f9-1f1fb","uc_match":"1f1f9-1f1fb","uc_greedy":"1f1f9-1f1fb","shortnames":[":tuvalu:"],"category":"flags"},":flag_tw:":{"uc_base":"1f1f9-1f1fc","uc_output":"1f1f9-1f1fc","uc_match":"1f1f9-1f1fc","uc_greedy":"1f1f9-1f1fc","shortnames":[":tw:"],"category":"flags"},":flag_tz:":{"uc_base":"1f1f9-1f1ff","uc_output":"1f1f9-1f1ff","uc_match":"1f1f9-1f1ff","uc_greedy":"1f1f9-1f1ff","shortnames":[":tz:"],"category":"flags"},":flag_ua:":{"uc_base":"1f1fa-1f1e6","uc_output":"1f1fa-1f1e6","uc_match":"1f1fa-1f1e6","uc_greedy":"1f1fa-1f1e6","shortnames":[":ua:"],"category":"flags"},":flag_ug:":{"uc_base":"1f1fa-1f1ec","uc_output":"1f1fa-1f1ec","uc_match":"1f1fa-1f1ec","uc_greedy":"1f1fa-1f1ec","shortnames":[":ug:"],"category":"flags"},":flag_um:":{"uc_base":"1f1fa-1f1f2","uc_output":"1f1fa-1f1f2","uc_match":"1f1fa-1f1f2","uc_greedy":"1f1fa-1f1f2","shortnames":[":um:"],"category":"flags"},":flag_us:":{"uc_base":"1f1fa-1f1f8","uc_output":"1f1fa-1f1f8","uc_match":"1f1fa-1f1f8","uc_greedy":"1f1fa-1f1f8","shortnames":[":us:"],"category":"flags"},":flag_uy:":{"uc_base":"1f1fa-1f1fe","uc_output":"1f1fa-1f1fe","uc_match":"1f1fa-1f1fe","uc_greedy":"1f1fa-1f1fe","shortnames":[":uy:"],"category":"flags"},":flag_uz:":{"uc_base":"1f1fa-1f1ff","uc_output":"1f1fa-1f1ff","uc_match":"1f1fa-1f1ff","uc_greedy":"1f1fa-1f1ff","shortnames":[":uz:"],"category":"flags"},":flag_va:":{"uc_base":"1f1fb-1f1e6","uc_output":"1f1fb-1f1e6","uc_match":"1f1fb-1f1e6","uc_greedy":"1f1fb-1f1e6","shortnames":[":va:"],"category":"flags"},":flag_vc:":{"uc_base":"1f1fb-1f1e8","uc_output":"1f1fb-1f1e8","uc_match":"1f1fb-1f1e8","uc_greedy":"1f1fb-1f1e8","shortnames":[":vc:"],"category":"flags"},":flag_ve:":{"uc_base":"1f1fb-1f1ea","uc_output":"1f1fb-1f1ea","uc_match":"1f1fb-1f1ea","uc_greedy":"1f1fb-1f1ea","shortnames":[":ve:"],"category":"flags"},":flag_vg:":{"uc_base":"1f1fb-1f1ec","uc_output":"1f1fb-1f1ec","uc_match":"1f1fb-1f1ec","uc_greedy":"1f1fb-1f1ec","shortnames":[":vg:"],"category":"flags"},":flag_vi:":{"uc_base":"1f1fb-1f1ee","uc_output":"1f1fb-1f1ee","uc_match":"1f1fb-1f1ee","uc_greedy":"1f1fb-1f1ee","shortnames":[":vi:"],"category":"flags"},":flag_vn:":{"uc_base":"1f1fb-1f1f3","uc_output":"1f1fb-1f1f3","uc_match":"1f1fb-1f1f3","uc_greedy":"1f1fb-1f1f3","shortnames":[":vn:"],"category":"flags"},":flag_vu:":{"uc_base":"1f1fb-1f1fa","uc_output":"1f1fb-1f1fa","uc_match":"1f1fb-1f1fa","uc_greedy":"1f1fb-1f1fa","shortnames":[":vu:"],"category":"flags"},":flag_wf:":{"uc_base":"1f1fc-1f1eb","uc_output":"1f1fc-1f1eb","uc_match":"1f1fc-1f1eb","uc_greedy":"1f1fc-1f1eb","shortnames":[":wf:"],"category":"flags"},":flag_ws:":{"uc_base":"1f1fc-1f1f8","uc_output":"1f1fc-1f1f8","uc_match":"1f1fc-1f1f8","uc_greedy":"1f1fc-1f1f8","shortnames":[":ws:"],"category":"flags"},":flag_xk:":{"uc_base":"1f1fd-1f1f0","uc_output":"1f1fd-1f1f0","uc_match":"1f1fd-1f1f0","uc_greedy":"1f1fd-1f1f0","shortnames":[":xk:"],"category":"flags"},":flag_ye:":{"uc_base":"1f1fe-1f1ea","uc_output":"1f1fe-1f1ea","uc_match":"1f1fe-1f1ea","uc_greedy":"1f1fe-1f1ea","shortnames":[":ye:"],"category":"flags"},":flag_yt:":{"uc_base":"1f1fe-1f1f9","uc_output":"1f1fe-1f1f9","uc_match":"1f1fe-1f1f9","uc_greedy":"1f1fe-1f1f9","shortnames":[":yt:"],"category":"flags"},":flag_za:":{"uc_base":"1f1ff-1f1e6","uc_output":"1f1ff-1f1e6","uc_match":"1f1ff-1f1e6","uc_greedy":"1f1ff-1f1e6","shortnames":[":za:"],"category":"flags"},":flag_zm:":{"uc_base":"1f1ff-1f1f2","uc_output":"1f1ff-1f1f2","uc_match":"1f1ff-1f1f2","uc_greedy":"1f1ff-1f1f2","shortnames":[":zm:"],"category":"flags"},":flag_zw:":{"uc_base":"1f1ff-1f1fc","uc_output":"1f1ff-1f1fc","uc_match":"1f1ff-1f1fc","uc_greedy":"1f1ff-1f1fc","shortnames":[":zw:"],"category":"flags"},":girl_tone1:":{"uc_base":"1f467-1f3fb","uc_output":"1f467-1f3fb","uc_match":"1f467-1f3fb","uc_greedy":"1f467-1f3fb","shortnames":[],"category":"people"},":girl_tone2:":{"uc_base":"1f467-1f3fc","uc_output":"1f467-1f3fc","uc_match":"1f467-1f3fc","uc_greedy":"1f467-1f3fc","shortnames":[],"category":"people"},":girl_tone3:":{"uc_base":"1f467-1f3fd","uc_output":"1f467-1f3fd","uc_match":"1f467-1f3fd","uc_greedy":"1f467-1f3fd","shortnames":[],"category":"people"},":girl_tone4:":{"uc_base":"1f467-1f3fe","uc_output":"1f467-1f3fe","uc_match":"1f467-1f3fe","uc_greedy":"1f467-1f3fe","shortnames":[],"category":"people"},":girl_tone5:":{"uc_base":"1f467-1f3ff","uc_output":"1f467-1f3ff","uc_match":"1f467-1f3ff","uc_greedy":"1f467-1f3ff","shortnames":[],"category":"people"},":guard_tone1:":{"uc_base":"1f482-1f3fb","uc_output":"1f482-1f3fb","uc_match":"1f482-1f3fb","uc_greedy":"1f482-1f3fb","shortnames":[":guardsman_tone1:"],"category":"people"},":guard_tone2:":{"uc_base":"1f482-1f3fc","uc_output":"1f482-1f3fc","uc_match":"1f482-1f3fc","uc_greedy":"1f482-1f3fc","shortnames":[":guardsman_tone2:"],"category":"people"},":guard_tone3:":{"uc_base":"1f482-1f3fd","uc_output":"1f482-1f3fd","uc_match":"1f482-1f3fd","uc_greedy":"1f482-1f3fd","shortnames":[":guardsman_tone3:"],"category":"people"},":guard_tone4:":{"uc_base":"1f482-1f3fe","uc_output":"1f482-1f3fe","uc_match":"1f482-1f3fe","uc_greedy":"1f482-1f3fe","shortnames":[":guardsman_tone4:"],"category":"people"},":guard_tone5:":{"uc_base":"1f482-1f3ff","uc_output":"1f482-1f3ff","uc_match":"1f482-1f3ff","uc_greedy":"1f482-1f3ff","shortnames":[":guardsman_tone5:"],"category":"people"},":hand_splayed_tone1:":{"uc_base":"1f590-1f3fb","uc_output":"1f590-1f3fb","uc_match":"1f590-fe0f-1f3fb","uc_greedy":"1f590-fe0f-1f3fb","shortnames":[":raised_hand_with_fingers_splayed_tone1:"],"category":"people"},":hand_splayed_tone2:":{"uc_base":"1f590-1f3fc","uc_output":"1f590-1f3fc","uc_match":"1f590-fe0f-1f3fc","uc_greedy":"1f590-fe0f-1f3fc","shortnames":[":raised_hand_with_fingers_splayed_tone2:"],"category":"people"},":hand_splayed_tone3:":{"uc_base":"1f590-1f3fd","uc_output":"1f590-1f3fd","uc_match":"1f590-fe0f-1f3fd","uc_greedy":"1f590-fe0f-1f3fd","shortnames":[":raised_hand_with_fingers_splayed_tone3:"],"category":"people"},":hand_splayed_tone4:":{"uc_base":"1f590-1f3fe","uc_output":"1f590-1f3fe","uc_match":"1f590-fe0f-1f3fe","uc_greedy":"1f590-fe0f-1f3fe","shortnames":[":raised_hand_with_fingers_splayed_tone4:"],"category":"people"},":hand_splayed_tone5:":{"uc_base":"1f590-1f3ff","uc_output":"1f590-1f3ff","uc_match":"1f590-fe0f-1f3ff","uc_greedy":"1f590-fe0f-1f3ff","shortnames":[":raised_hand_with_fingers_splayed_tone5:"],"category":"people"},":horse_racing_tone1:":{"uc_base":"1f3c7-1f3fb","uc_output":"1f3c7-1f3fb","uc_match":"1f3c7-1f3fb","uc_greedy":"1f3c7-1f3fb","shortnames":[],"category":"activity"},":horse_racing_tone2:":{"uc_base":"1f3c7-1f3fc","uc_output":"1f3c7-1f3fc","uc_match":"1f3c7-1f3fc","uc_greedy":"1f3c7-1f3fc","shortnames":[],"category":"activity"},":horse_racing_tone3:":{"uc_base":"1f3c7-1f3fd","uc_output":"1f3c7-1f3fd","uc_match":"1f3c7-1f3fd","uc_greedy":"1f3c7-1f3fd","shortnames":[],"category":"activity"},":horse_racing_tone4:":{"uc_base":"1f3c7-1f3fe","uc_output":"1f3c7-1f3fe","uc_match":"1f3c7-1f3fe","uc_greedy":"1f3c7-1f3fe","shortnames":[],"category":"activity"},":horse_racing_tone5:":{"uc_base":"1f3c7-1f3ff","uc_output":"1f3c7-1f3ff","uc_match":"1f3c7-1f3ff","uc_greedy":"1f3c7-1f3ff","shortnames":[],"category":"activity"},":left_facing_fist_tone1:":{"uc_base":"1f91b-1f3fb","uc_output":"1f91b-1f3fb","uc_match":"1f91b-1f3fb","uc_greedy":"1f91b-1f3fb","shortnames":[":left_fist_tone1:"],"category":"people"},":left_facing_fist_tone2:":{"uc_base":"1f91b-1f3fc","uc_output":"1f91b-1f3fc","uc_match":"1f91b-1f3fc","uc_greedy":"1f91b-1f3fc","shortnames":[":left_fist_tone2:"],"category":"people"},":left_facing_fist_tone3:":{"uc_base":"1f91b-1f3fd","uc_output":"1f91b-1f3fd","uc_match":"1f91b-1f3fd","uc_greedy":"1f91b-1f3fd","shortnames":[":left_fist_tone3:"],"category":"people"},":left_facing_fist_tone4:":{"uc_base":"1f91b-1f3fe","uc_output":"1f91b-1f3fe","uc_match":"1f91b-1f3fe","uc_greedy":"1f91b-1f3fe","shortnames":[":left_fist_tone4:"],"category":"people"},":left_facing_fist_tone5:":{"uc_base":"1f91b-1f3ff","uc_output":"1f91b-1f3ff","uc_match":"1f91b-1f3ff","uc_greedy":"1f91b-1f3ff","shortnames":[":left_fist_tone5:"],"category":"people"},":love_you_gesture_tone1:":{"uc_base":"1f91f-1f3fb","uc_output":"1f91f-1f3fb","uc_match":"1f91f-1f3fb","uc_greedy":"1f91f-1f3fb","shortnames":[":love_you_gesture_light_skin_tone:"],"category":"people"},":love_you_gesture_tone2:":{"uc_base":"1f91f-1f3fc","uc_output":"1f91f-1f3fc","uc_match":"1f91f-1f3fc","uc_greedy":"1f91f-1f3fc","shortnames":[":love_you_gesture_medium_light_skin_tone:"],"category":"people"},":love_you_gesture_tone3:":{"uc_base":"1f91f-1f3fd","uc_output":"1f91f-1f3fd","uc_match":"1f91f-1f3fd","uc_greedy":"1f91f-1f3fd","shortnames":[":love_you_gesture_medium_skin_tone:"],"category":"people"},":love_you_gesture_tone4:":{"uc_base":"1f91f-1f3fe","uc_output":"1f91f-1f3fe","uc_match":"1f91f-1f3fe","uc_greedy":"1f91f-1f3fe","shortnames":[":love_you_gesture_medium_dark_skin_tone:"],"category":"people"},":love_you_gesture_tone5:":{"uc_base":"1f91f-1f3ff","uc_output":"1f91f-1f3ff","uc_match":"1f91f-1f3ff","uc_greedy":"1f91f-1f3ff","shortnames":[":love_you_gesture_dark_skin_tone:"],"category":"people"},":mage_tone1:":{"uc_base":"1f9d9-1f3fb","uc_output":"1f9d9-1f3fb","uc_match":"1f9d9-1f3fb","uc_greedy":"1f9d9-1f3fb","shortnames":[":mage_light_skin_tone:"],"category":"people"},":mage_tone2:":{"uc_base":"1f9d9-1f3fc","uc_output":"1f9d9-1f3fc","uc_match":"1f9d9-1f3fc","uc_greedy":"1f9d9-1f3fc","shortnames":[":mage_medium_light_skin_tone:"],"category":"people"},":mage_tone3:":{"uc_base":"1f9d9-1f3fd","uc_output":"1f9d9-1f3fd","uc_match":"1f9d9-1f3fd","uc_greedy":"1f9d9-1f3fd","shortnames":[":mage_medium_skin_tone:"],"category":"people"},":mage_tone4:":{"uc_base":"1f9d9-1f3fe","uc_output":"1f9d9-1f3fe","uc_match":"1f9d9-1f3fe","uc_greedy":"1f9d9-1f3fe","shortnames":[":mage_medium_dark_skin_tone:"],"category":"people"},":mage_tone5:":{"uc_base":"1f9d9-1f3ff","uc_output":"1f9d9-1f3ff","uc_match":"1f9d9-1f3ff","uc_greedy":"1f9d9-1f3ff","shortnames":[":mage_dark_skin_tone:"],"category":"people"},":man_dancing_tone1:":{"uc_base":"1f57a-1f3fb","uc_output":"1f57a-1f3fb","uc_match":"1f57a-1f3fb","uc_greedy":"1f57a-1f3fb","shortnames":[":male_dancer_tone1:"],"category":"people"},":man_dancing_tone2:":{"uc_base":"1f57a-1f3fc","uc_output":"1f57a-1f3fc","uc_match":"1f57a-1f3fc","uc_greedy":"1f57a-1f3fc","shortnames":[":male_dancer_tone2:"],"category":"people"},":man_dancing_tone3:":{"uc_base":"1f57a-1f3fd","uc_output":"1f57a-1f3fd","uc_match":"1f57a-1f3fd","uc_greedy":"1f57a-1f3fd","shortnames":[":male_dancer_tone3:"],"category":"people"},":man_dancing_tone4:":{"uc_base":"1f57a-1f3fe","uc_output":"1f57a-1f3fe","uc_match":"1f57a-1f3fe","uc_greedy":"1f57a-1f3fe","shortnames":[":male_dancer_tone4:"],"category":"people"},":man_dancing_tone5:":{"uc_base":"1f57a-1f3ff","uc_output":"1f57a-1f3ff","uc_match":"1f57a-1f3ff","uc_greedy":"1f57a-1f3ff","shortnames":[":male_dancer_tone5:"],"category":"people"},":man_in_business_suit_levitating_tone1:":{"uc_base":"1f574-1f3fb","uc_output":"1f574-1f3fb","uc_match":"1f574-fe0f-1f3fb","uc_greedy":"1f574-fe0f-1f3fb","shortnames":[":man_in_business_suit_levitating_light_skin_tone:"],"category":"people"},":man_in_business_suit_levitating_tone2:":{"uc_base":"1f574-1f3fc","uc_output":"1f574-1f3fc","uc_match":"1f574-fe0f-1f3fc","uc_greedy":"1f574-fe0f-1f3fc","shortnames":[":man_in_business_suit_levitating_medium_light_skin_tone:"],"category":"people"},":man_in_business_suit_levitating_tone3:":{"uc_base":"1f574-1f3fd","uc_output":"1f574-1f3fd","uc_match":"1f574-fe0f-1f3fd","uc_greedy":"1f574-fe0f-1f3fd","shortnames":[":man_in_business_suit_levitating_medium_skin_tone:"],"category":"people"},":man_in_business_suit_levitating_tone4:":{"uc_base":"1f574-1f3fe","uc_output":"1f574-1f3fe","uc_match":"1f574-fe0f-1f3fe","uc_greedy":"1f574-fe0f-1f3fe","shortnames":[":man_in_business_suit_levitating_medium_dark_skin_tone:"],"category":"people"},":man_in_business_suit_levitating_tone5:":{"uc_base":"1f574-1f3ff","uc_output":"1f574-1f3ff","uc_match":"1f574-fe0f-1f3ff","uc_greedy":"1f574-fe0f-1f3ff","shortnames":[":man_in_business_suit_levitating_dark_skin_tone:"],"category":"people"},":man_in_tuxedo_tone1:":{"uc_base":"1f935-1f3fb","uc_output":"1f935-1f3fb","uc_match":"1f935-1f3fb","uc_greedy":"1f935-1f3fb","shortnames":[":tuxedo_tone1:"],"category":"people"},":man_in_tuxedo_tone2:":{"uc_base":"1f935-1f3fc","uc_output":"1f935-1f3fc","uc_match":"1f935-1f3fc","uc_greedy":"1f935-1f3fc","shortnames":[":tuxedo_tone2:"],"category":"people"},":man_in_tuxedo_tone3:":{"uc_base":"1f935-1f3fd","uc_output":"1f935-1f3fd","uc_match":"1f935-1f3fd","uc_greedy":"1f935-1f3fd","shortnames":[":tuxedo_tone3:"],"category":"people"},":man_in_tuxedo_tone4:":{"uc_base":"1f935-1f3fe","uc_output":"1f935-1f3fe","uc_match":"1f935-1f3fe","uc_greedy":"1f935-1f3fe","shortnames":[":tuxedo_tone4:"],"category":"people"},":man_in_tuxedo_tone5:":{"uc_base":"1f935-1f3ff","uc_output":"1f935-1f3ff","uc_match":"1f935-1f3ff","uc_greedy":"1f935-1f3ff","shortnames":[":tuxedo_tone5:"],"category":"people"},":man_tone1:":{"uc_base":"1f468-1f3fb","uc_output":"1f468-1f3fb","uc_match":"1f468-1f3fb","uc_greedy":"1f468-1f3fb","shortnames":[],"category":"people"},":man_tone2:":{"uc_base":"1f468-1f3fc","uc_output":"1f468-1f3fc","uc_match":"1f468-1f3fc","uc_greedy":"1f468-1f3fc","shortnames":[],"category":"people"},":man_tone3:":{"uc_base":"1f468-1f3fd","uc_output":"1f468-1f3fd","uc_match":"1f468-1f3fd","uc_greedy":"1f468-1f3fd","shortnames":[],"category":"people"},":man_tone4:":{"uc_base":"1f468-1f3fe","uc_output":"1f468-1f3fe","uc_match":"1f468-1f3fe","uc_greedy":"1f468-1f3fe","shortnames":[],"category":"people"},":man_tone5:":{"uc_base":"1f468-1f3ff","uc_output":"1f468-1f3ff","uc_match":"1f468-1f3ff","uc_greedy":"1f468-1f3ff","shortnames":[],"category":"people"},":man_with_chinese_cap_tone1:":{"uc_base":"1f472-1f3fb","uc_output":"1f472-1f3fb","uc_match":"1f472-1f3fb","uc_greedy":"1f472-1f3fb","shortnames":[":man_with_gua_pi_mao_tone1:"],"category":"people"},":man_with_chinese_cap_tone2:":{"uc_base":"1f472-1f3fc","uc_output":"1f472-1f3fc","uc_match":"1f472-1f3fc","uc_greedy":"1f472-1f3fc","shortnames":[":man_with_gua_pi_mao_tone2:"],"category":"people"},":man_with_chinese_cap_tone3:":{"uc_base":"1f472-1f3fd","uc_output":"1f472-1f3fd","uc_match":"1f472-1f3fd","uc_greedy":"1f472-1f3fd","shortnames":[":man_with_gua_pi_mao_tone3:"],"category":"people"},":man_with_chinese_cap_tone4:":{"uc_base":"1f472-1f3fe","uc_output":"1f472-1f3fe","uc_match":"1f472-1f3fe","uc_greedy":"1f472-1f3fe","shortnames":[":man_with_gua_pi_mao_tone4:"],"category":"people"},":man_with_chinese_cap_tone5:":{"uc_base":"1f472-1f3ff","uc_output":"1f472-1f3ff","uc_match":"1f472-1f3ff","uc_greedy":"1f472-1f3ff","shortnames":[":man_with_gua_pi_mao_tone5:"],"category":"people"},":merperson_tone1:":{"uc_base":"1f9dc-1f3fb","uc_output":"1f9dc-1f3fb","uc_match":"1f9dc-1f3fb","uc_greedy":"1f9dc-1f3fb","shortnames":[":merperson_light_skin_tone:"],"category":"people"},":merperson_tone2:":{"uc_base":"1f9dc-1f3fc","uc_output":"1f9dc-1f3fc","uc_match":"1f9dc-1f3fc","uc_greedy":"1f9dc-1f3fc","shortnames":[":merperson_medium_light_skin_tone:"],"category":"people"},":merperson_tone3:":{"uc_base":"1f9dc-1f3fd","uc_output":"1f9dc-1f3fd","uc_match":"1f9dc-1f3fd","uc_greedy":"1f9dc-1f3fd","shortnames":[":merperson_medium_skin_tone:"],"category":"people"},":merperson_tone4:":{"uc_base":"1f9dc-1f3fe","uc_output":"1f9dc-1f3fe","uc_match":"1f9dc-1f3fe","uc_greedy":"1f9dc-1f3fe","shortnames":[":merperson_medium_dark_skin_tone:"],"category":"people"},":merperson_tone5:":{"uc_base":"1f9dc-1f3ff","uc_output":"1f9dc-1f3ff","uc_match":"1f9dc-1f3ff","uc_greedy":"1f9dc-1f3ff","shortnames":[":merperson_dark_skin_tone:"],"category":"people"},":metal_tone1:":{"uc_base":"1f918-1f3fb","uc_output":"1f918-1f3fb","uc_match":"1f918-1f3fb","uc_greedy":"1f918-1f3fb","shortnames":[":sign_of_the_horns_tone1:"],"category":"people"},":metal_tone2:":{"uc_base":"1f918-1f3fc","uc_output":"1f918-1f3fc","uc_match":"1f918-1f3fc","uc_greedy":"1f918-1f3fc","shortnames":[":sign_of_the_horns_tone2:"],"category":"people"},":metal_tone3:":{"uc_base":"1f918-1f3fd","uc_output":"1f918-1f3fd","uc_match":"1f918-1f3fd","uc_greedy":"1f918-1f3fd","shortnames":[":sign_of_the_horns_tone3:"],"category":"people"},":metal_tone4:":{"uc_base":"1f918-1f3fe","uc_output":"1f918-1f3fe","uc_match":"1f918-1f3fe","uc_greedy":"1f918-1f3fe","shortnames":[":sign_of_the_horns_tone4:"],"category":"people"},":metal_tone5:":{"uc_base":"1f918-1f3ff","uc_output":"1f918-1f3ff","uc_match":"1f918-1f3ff","uc_greedy":"1f918-1f3ff","shortnames":[":sign_of_the_horns_tone5:"],"category":"people"},":middle_finger_tone1:":{"uc_base":"1f595-1f3fb","uc_output":"1f595-1f3fb","uc_match":"1f595-1f3fb","uc_greedy":"1f595-1f3fb","shortnames":[":reversed_hand_with_middle_finger_extended_tone1:"],"category":"people"},":middle_finger_tone2:":{"uc_base":"1f595-1f3fc","uc_output":"1f595-1f3fc","uc_match":"1f595-1f3fc","uc_greedy":"1f595-1f3fc","shortnames":[":reversed_hand_with_middle_finger_extended_tone2:"],"category":"people"},":middle_finger_tone3:":{"uc_base":"1f595-1f3fd","uc_output":"1f595-1f3fd","uc_match":"1f595-1f3fd","uc_greedy":"1f595-1f3fd","shortnames":[":reversed_hand_with_middle_finger_extended_tone3:"],"category":"people"},":middle_finger_tone4:":{"uc_base":"1f595-1f3fe","uc_output":"1f595-1f3fe","uc_match":"1f595-1f3fe","uc_greedy":"1f595-1f3fe","shortnames":[":reversed_hand_with_middle_finger_extended_tone4:"],"category":"people"},":middle_finger_tone5:":{"uc_base":"1f595-1f3ff","uc_output":"1f595-1f3ff","uc_match":"1f595-1f3ff","uc_greedy":"1f595-1f3ff","shortnames":[":reversed_hand_with_middle_finger_extended_tone5:"],"category":"people"},":mrs_claus_tone1:":{"uc_base":"1f936-1f3fb","uc_output":"1f936-1f3fb","uc_match":"1f936-1f3fb","uc_greedy":"1f936-1f3fb","shortnames":[":mother_christmas_tone1:"],"category":"people"},":mrs_claus_tone2:":{"uc_base":"1f936-1f3fc","uc_output":"1f936-1f3fc","uc_match":"1f936-1f3fc","uc_greedy":"1f936-1f3fc","shortnames":[":mother_christmas_tone2:"],"category":"people"},":mrs_claus_tone3:":{"uc_base":"1f936-1f3fd","uc_output":"1f936-1f3fd","uc_match":"1f936-1f3fd","uc_greedy":"1f936-1f3fd","shortnames":[":mother_christmas_tone3:"],"category":"people"},":mrs_claus_tone4:":{"uc_base":"1f936-1f3fe","uc_output":"1f936-1f3fe","uc_match":"1f936-1f3fe","uc_greedy":"1f936-1f3fe","shortnames":[":mother_christmas_tone4:"],"category":"people"},":mrs_claus_tone5:":{"uc_base":"1f936-1f3ff","uc_output":"1f936-1f3ff","uc_match":"1f936-1f3ff","uc_greedy":"1f936-1f3ff","shortnames":[":mother_christmas_tone5:"],"category":"people"},":muscle_tone1:":{"uc_base":"1f4aa-1f3fb","uc_output":"1f4aa-1f3fb","uc_match":"1f4aa-1f3fb","uc_greedy":"1f4aa-1f3fb","shortnames":[],"category":"people"},":muscle_tone2:":{"uc_base":"1f4aa-1f3fc","uc_output":"1f4aa-1f3fc","uc_match":"1f4aa-1f3fc","uc_greedy":"1f4aa-1f3fc","shortnames":[],"category":"people"},":muscle_tone3:":{"uc_base":"1f4aa-1f3fd","uc_output":"1f4aa-1f3fd","uc_match":"1f4aa-1f3fd","uc_greedy":"1f4aa-1f3fd","shortnames":[],"category":"people"},":muscle_tone4:":{"uc_base":"1f4aa-1f3fe","uc_output":"1f4aa-1f3fe","uc_match":"1f4aa-1f3fe","uc_greedy":"1f4aa-1f3fe","shortnames":[],"category":"people"},":muscle_tone5:":{"uc_base":"1f4aa-1f3ff","uc_output":"1f4aa-1f3ff","uc_match":"1f4aa-1f3ff","uc_greedy":"1f4aa-1f3ff","shortnames":[],"category":"people"},":nail_care_tone1:":{"uc_base":"1f485-1f3fb","uc_output":"1f485-1f3fb","uc_match":"1f485-1f3fb","uc_greedy":"1f485-1f3fb","shortnames":[],"category":"people"},":nail_care_tone2:":{"uc_base":"1f485-1f3fc","uc_output":"1f485-1f3fc","uc_match":"1f485-1f3fc","uc_greedy":"1f485-1f3fc","shortnames":[],"category":"people"},":nail_care_tone3:":{"uc_base":"1f485-1f3fd","uc_output":"1f485-1f3fd","uc_match":"1f485-1f3fd","uc_greedy":"1f485-1f3fd","shortnames":[],"category":"people"},":nail_care_tone4:":{"uc_base":"1f485-1f3fe","uc_output":"1f485-1f3fe","uc_match":"1f485-1f3fe","uc_greedy":"1f485-1f3fe","shortnames":[],"category":"people"},":nail_care_tone5:":{"uc_base":"1f485-1f3ff","uc_output":"1f485-1f3ff","uc_match":"1f485-1f3ff","uc_greedy":"1f485-1f3ff","shortnames":[],"category":"people"},":nose_tone1:":{"uc_base":"1f443-1f3fb","uc_output":"1f443-1f3fb","uc_match":"1f443-1f3fb","uc_greedy":"1f443-1f3fb","shortnames":[],"category":"people"},":nose_tone2:":{"uc_base":"1f443-1f3fc","uc_output":"1f443-1f3fc","uc_match":"1f443-1f3fc","uc_greedy":"1f443-1f3fc","shortnames":[],"category":"people"},":nose_tone3:":{"uc_base":"1f443-1f3fd","uc_output":"1f443-1f3fd","uc_match":"1f443-1f3fd","uc_greedy":"1f443-1f3fd","shortnames":[],"category":"people"},":nose_tone4:":{"uc_base":"1f443-1f3fe","uc_output":"1f443-1f3fe","uc_match":"1f443-1f3fe","uc_greedy":"1f443-1f3fe","shortnames":[],"category":"people"},":nose_tone5:":{"uc_base":"1f443-1f3ff","uc_output":"1f443-1f3ff","uc_match":"1f443-1f3ff","uc_greedy":"1f443-1f3ff","shortnames":[],"category":"people"},":ok_hand_tone1:":{"uc_base":"1f44c-1f3fb","uc_output":"1f44c-1f3fb","uc_match":"1f44c-1f3fb","uc_greedy":"1f44c-1f3fb","shortnames":[],"category":"people"},":ok_hand_tone2:":{"uc_base":"1f44c-1f3fc","uc_output":"1f44c-1f3fc","uc_match":"1f44c-1f3fc","uc_greedy":"1f44c-1f3fc","shortnames":[],"category":"people"},":ok_hand_tone3:":{"uc_base":"1f44c-1f3fd","uc_output":"1f44c-1f3fd","uc_match":"1f44c-1f3fd","uc_greedy":"1f44c-1f3fd","shortnames":[],"category":"people"},":ok_hand_tone4:":{"uc_base":"1f44c-1f3fe","uc_output":"1f44c-1f3fe","uc_match":"1f44c-1f3fe","uc_greedy":"1f44c-1f3fe","shortnames":[],"category":"people"},":ok_hand_tone5:":{"uc_base":"1f44c-1f3ff","uc_output":"1f44c-1f3ff","uc_match":"1f44c-1f3ff","uc_greedy":"1f44c-1f3ff","shortnames":[],"category":"people"},":older_adult_tone1:":{"uc_base":"1f9d3-1f3fb","uc_output":"1f9d3-1f3fb","uc_match":"1f9d3-1f3fb","uc_greedy":"1f9d3-1f3fb","shortnames":[":older_adult_light_skin_tone:"],"category":"people"},":older_adult_tone2:":{"uc_base":"1f9d3-1f3fc","uc_output":"1f9d3-1f3fc","uc_match":"1f9d3-1f3fc","uc_greedy":"1f9d3-1f3fc","shortnames":[":older_adult_medium_light_skin_tone:"],"category":"people"},":older_adult_tone3:":{"uc_base":"1f9d3-1f3fd","uc_output":"1f9d3-1f3fd","uc_match":"1f9d3-1f3fd","uc_greedy":"1f9d3-1f3fd","shortnames":[":older_adult_medium_skin_tone:"],"category":"people"},":older_adult_tone4:":{"uc_base":"1f9d3-1f3fe","uc_output":"1f9d3-1f3fe","uc_match":"1f9d3-1f3fe","uc_greedy":"1f9d3-1f3fe","shortnames":[":older_adult_medium_dark_skin_tone:"],"category":"people"},":older_adult_tone5:":{"uc_base":"1f9d3-1f3ff","uc_output":"1f9d3-1f3ff","uc_match":"1f9d3-1f3ff","uc_greedy":"1f9d3-1f3ff","shortnames":[":older_adult_dark_skin_tone:"],"category":"people"},":older_man_tone1:":{"uc_base":"1f474-1f3fb","uc_output":"1f474-1f3fb","uc_match":"1f474-1f3fb","uc_greedy":"1f474-1f3fb","shortnames":[],"category":"people"},":older_man_tone2:":{"uc_base":"1f474-1f3fc","uc_output":"1f474-1f3fc","uc_match":"1f474-1f3fc","uc_greedy":"1f474-1f3fc","shortnames":[],"category":"people"},":older_man_tone3:":{"uc_base":"1f474-1f3fd","uc_output":"1f474-1f3fd","uc_match":"1f474-1f3fd","uc_greedy":"1f474-1f3fd","shortnames":[],"category":"people"},":older_man_tone4:":{"uc_base":"1f474-1f3fe","uc_output":"1f474-1f3fe","uc_match":"1f474-1f3fe","uc_greedy":"1f474-1f3fe","shortnames":[],"category":"people"},":older_man_tone5:":{"uc_base":"1f474-1f3ff","uc_output":"1f474-1f3ff","uc_match":"1f474-1f3ff","uc_greedy":"1f474-1f3ff","shortnames":[],"category":"people"},":older_woman_tone1:":{"uc_base":"1f475-1f3fb","uc_output":"1f475-1f3fb","uc_match":"1f475-1f3fb","uc_greedy":"1f475-1f3fb","shortnames":[":grandma_tone1:"],"category":"people"},":older_woman_tone2:":{"uc_base":"1f475-1f3fc","uc_output":"1f475-1f3fc","uc_match":"1f475-1f3fc","uc_greedy":"1f475-1f3fc","shortnames":[":grandma_tone2:"],"category":"people"},":older_woman_tone3:":{"uc_base":"1f475-1f3fd","uc_output":"1f475-1f3fd","uc_match":"1f475-1f3fd","uc_greedy":"1f475-1f3fd","shortnames":[":grandma_tone3:"],"category":"people"},":older_woman_tone4:":{"uc_base":"1f475-1f3fe","uc_output":"1f475-1f3fe","uc_match":"1f475-1f3fe","uc_greedy":"1f475-1f3fe","shortnames":[":grandma_tone4:"],"category":"people"},":older_woman_tone5:":{"uc_base":"1f475-1f3ff","uc_output":"1f475-1f3ff","uc_match":"1f475-1f3ff","uc_greedy":"1f475-1f3ff","shortnames":[":grandma_tone5:"],"category":"people"},":open_hands_tone1:":{"uc_base":"1f450-1f3fb","uc_output":"1f450-1f3fb","uc_match":"1f450-1f3fb","uc_greedy":"1f450-1f3fb","shortnames":[],"category":"people"},":open_hands_tone2:":{"uc_base":"1f450-1f3fc","uc_output":"1f450-1f3fc","uc_match":"1f450-1f3fc","uc_greedy":"1f450-1f3fc","shortnames":[],"category":"people"},":open_hands_tone3:":{"uc_base":"1f450-1f3fd","uc_output":"1f450-1f3fd","uc_match":"1f450-1f3fd","uc_greedy":"1f450-1f3fd","shortnames":[],"category":"people"},":open_hands_tone4:":{"uc_base":"1f450-1f3fe","uc_output":"1f450-1f3fe","uc_match":"1f450-1f3fe","uc_greedy":"1f450-1f3fe","shortnames":[],"category":"people"},":open_hands_tone5:":{"uc_base":"1f450-1f3ff","uc_output":"1f450-1f3ff","uc_match":"1f450-1f3ff","uc_greedy":"1f450-1f3ff","shortnames":[],"category":"people"},":palms_up_together_tone1:":{"uc_base":"1f932-1f3fb","uc_output":"1f932-1f3fb","uc_match":"1f932-1f3fb","uc_greedy":"1f932-1f3fb","shortnames":[":palms_up_together_light_skin_tone:"],"category":"people"},":palms_up_together_tone2:":{"uc_base":"1f932-1f3fc","uc_output":"1f932-1f3fc","uc_match":"1f932-1f3fc","uc_greedy":"1f932-1f3fc","shortnames":[":palms_up_together_medium_light_skin_tone:"],"category":"people"},":palms_up_together_tone3:":{"uc_base":"1f932-1f3fd","uc_output":"1f932-1f3fd","uc_match":"1f932-1f3fd","uc_greedy":"1f932-1f3fd","shortnames":[":palms_up_together_medium_skin_tone:"],"category":"people"},":palms_up_together_tone4:":{"uc_base":"1f932-1f3fe","uc_output":"1f932-1f3fe","uc_match":"1f932-1f3fe","uc_greedy":"1f932-1f3fe","shortnames":[":palms_up_together_medium_dark_skin_tone:"],"category":"people"},":palms_up_together_tone5:":{"uc_base":"1f932-1f3ff","uc_output":"1f932-1f3ff","uc_match":"1f932-1f3ff","uc_greedy":"1f932-1f3ff","shortnames":[":palms_up_together_dark_skin_tone:"],"category":"people"},":person_biking_tone1:":{"uc_base":"1f6b4-1f3fb","uc_output":"1f6b4-1f3fb","uc_match":"1f6b4-1f3fb","uc_greedy":"1f6b4-1f3fb","shortnames":[":bicyclist_tone1:"],"category":"activity"},":person_biking_tone2:":{"uc_base":"1f6b4-1f3fc","uc_output":"1f6b4-1f3fc","uc_match":"1f6b4-1f3fc","uc_greedy":"1f6b4-1f3fc","shortnames":[":bicyclist_tone2:"],"category":"activity"},":person_biking_tone3:":{"uc_base":"1f6b4-1f3fd","uc_output":"1f6b4-1f3fd","uc_match":"1f6b4-1f3fd","uc_greedy":"1f6b4-1f3fd","shortnames":[":bicyclist_tone3:"],"category":"activity"},":person_biking_tone4:":{"uc_base":"1f6b4-1f3fe","uc_output":"1f6b4-1f3fe","uc_match":"1f6b4-1f3fe","uc_greedy":"1f6b4-1f3fe","shortnames":[":bicyclist_tone4:"],"category":"activity"},":person_biking_tone5:":{"uc_base":"1f6b4-1f3ff","uc_output":"1f6b4-1f3ff","uc_match":"1f6b4-1f3ff","uc_greedy":"1f6b4-1f3ff","shortnames":[":bicyclist_tone5:"],"category":"activity"},":person_bowing_tone1:":{"uc_base":"1f647-1f3fb","uc_output":"1f647-1f3fb","uc_match":"1f647-1f3fb","uc_greedy":"1f647-1f3fb","shortnames":[":bow_tone1:"],"category":"people"},":person_bowing_tone2:":{"uc_base":"1f647-1f3fc","uc_output":"1f647-1f3fc","uc_match":"1f647-1f3fc","uc_greedy":"1f647-1f3fc","shortnames":[":bow_tone2:"],"category":"people"},":person_bowing_tone3:":{"uc_base":"1f647-1f3fd","uc_output":"1f647-1f3fd","uc_match":"1f647-1f3fd","uc_greedy":"1f647-1f3fd","shortnames":[":bow_tone3:"],"category":"people"},":person_bowing_tone4:":{"uc_base":"1f647-1f3fe","uc_output":"1f647-1f3fe","uc_match":"1f647-1f3fe","uc_greedy":"1f647-1f3fe","shortnames":[":bow_tone4:"],"category":"people"},":person_bowing_tone5:":{"uc_base":"1f647-1f3ff","uc_output":"1f647-1f3ff","uc_match":"1f647-1f3ff","uc_greedy":"1f647-1f3ff","shortnames":[":bow_tone5:"],"category":"people"},":person_climbing_tone1:":{"uc_base":"1f9d7-1f3fb","uc_output":"1f9d7-1f3fb","uc_match":"1f9d7-1f3fb","uc_greedy":"1f9d7-1f3fb","shortnames":[":person_climbing_light_skin_tone:"],"category":"activity"},":person_climbing_tone2:":{"uc_base":"1f9d7-1f3fc","uc_output":"1f9d7-1f3fc","uc_match":"1f9d7-1f3fc","uc_greedy":"1f9d7-1f3fc","shortnames":[":person_climbing_medium_light_skin_tone:"],"category":"activity"},":person_climbing_tone3:":{"uc_base":"1f9d7-1f3fd","uc_output":"1f9d7-1f3fd","uc_match":"1f9d7-1f3fd","uc_greedy":"1f9d7-1f3fd","shortnames":[":person_climbing_medium_skin_tone:"],"category":"activity"},":person_climbing_tone4:":{"uc_base":"1f9d7-1f3fe","uc_output":"1f9d7-1f3fe","uc_match":"1f9d7-1f3fe","uc_greedy":"1f9d7-1f3fe","shortnames":[":person_climbing_medium_dark_skin_tone:"],"category":"activity"},":person_climbing_tone5:":{"uc_base":"1f9d7-1f3ff","uc_output":"1f9d7-1f3ff","uc_match":"1f9d7-1f3ff","uc_greedy":"1f9d7-1f3ff","shortnames":[":person_climbing_dark_skin_tone:"],"category":"activity"},":person_doing_cartwheel_tone1:":{"uc_base":"1f938-1f3fb","uc_output":"1f938-1f3fb","uc_match":"1f938-1f3fb","uc_greedy":"1f938-1f3fb","shortnames":[":cartwheel_tone1:"],"category":"activity"},":person_doing_cartwheel_tone2:":{"uc_base":"1f938-1f3fc","uc_output":"1f938-1f3fc","uc_match":"1f938-1f3fc","uc_greedy":"1f938-1f3fc","shortnames":[":cartwheel_tone2:"],"category":"activity"},":person_doing_cartwheel_tone3:":{"uc_base":"1f938-1f3fd","uc_output":"1f938-1f3fd","uc_match":"1f938-1f3fd","uc_greedy":"1f938-1f3fd","shortnames":[":cartwheel_tone3:"],"category":"activity"},":person_doing_cartwheel_tone4:":{"uc_base":"1f938-1f3fe","uc_output":"1f938-1f3fe","uc_match":"1f938-1f3fe","uc_greedy":"1f938-1f3fe","shortnames":[":cartwheel_tone4:"],"category":"activity"},":person_doing_cartwheel_tone5:":{"uc_base":"1f938-1f3ff","uc_output":"1f938-1f3ff","uc_match":"1f938-1f3ff","uc_greedy":"1f938-1f3ff","shortnames":[":cartwheel_tone5:"],"category":"activity"},":person_facepalming_tone1:":{"uc_base":"1f926-1f3fb","uc_output":"1f926-1f3fb","uc_match":"1f926-1f3fb","uc_greedy":"1f926-1f3fb","shortnames":[":face_palm_tone1:",":facepalm_tone1:"],"category":"people"},":person_facepalming_tone2:":{"uc_base":"1f926-1f3fc","uc_output":"1f926-1f3fc","uc_match":"1f926-1f3fc","uc_greedy":"1f926-1f3fc","shortnames":[":face_palm_tone2:",":facepalm_tone2:"],"category":"people"},":person_facepalming_tone3:":{"uc_base":"1f926-1f3fd","uc_output":"1f926-1f3fd","uc_match":"1f926-1f3fd","uc_greedy":"1f926-1f3fd","shortnames":[":face_palm_tone3:",":facepalm_tone3:"],"category":"people"},":person_facepalming_tone4:":{"uc_base":"1f926-1f3fe","uc_output":"1f926-1f3fe","uc_match":"1f926-1f3fe","uc_greedy":"1f926-1f3fe","shortnames":[":face_palm_tone4:",":facepalm_tone4:"],"category":"people"},":person_facepalming_tone5:":{"uc_base":"1f926-1f3ff","uc_output":"1f926-1f3ff","uc_match":"1f926-1f3ff","uc_greedy":"1f926-1f3ff","shortnames":[":face_palm_tone5:",":facepalm_tone5:"],"category":"people"},":person_frowning_tone1:":{"uc_base":"1f64d-1f3fb","uc_output":"1f64d-1f3fb","uc_match":"1f64d-1f3fb","uc_greedy":"1f64d-1f3fb","shortnames":[],"category":"people"},":person_frowning_tone2:":{"uc_base":"1f64d-1f3fc","uc_output":"1f64d-1f3fc","uc_match":"1f64d-1f3fc","uc_greedy":"1f64d-1f3fc","shortnames":[],"category":"people"},":person_frowning_tone3:":{"uc_base":"1f64d-1f3fd","uc_output":"1f64d-1f3fd","uc_match":"1f64d-1f3fd","uc_greedy":"1f64d-1f3fd","shortnames":[],"category":"people"},":person_frowning_tone4:":{"uc_base":"1f64d-1f3fe","uc_output":"1f64d-1f3fe","uc_match":"1f64d-1f3fe","uc_greedy":"1f64d-1f3fe","shortnames":[],"category":"people"},":person_frowning_tone5:":{"uc_base":"1f64d-1f3ff","uc_output":"1f64d-1f3ff","uc_match":"1f64d-1f3ff","uc_greedy":"1f64d-1f3ff","shortnames":[],"category":"people"},":person_gesturing_no_tone1:":{"uc_base":"1f645-1f3fb","uc_output":"1f645-1f3fb","uc_match":"1f645-1f3fb","uc_greedy":"1f645-1f3fb","shortnames":[":no_good_tone1:"],"category":"people"},":person_gesturing_no_tone2:":{"uc_base":"1f645-1f3fc","uc_output":"1f645-1f3fc","uc_match":"1f645-1f3fc","uc_greedy":"1f645-1f3fc","shortnames":[":no_good_tone2:"],"category":"people"},":person_gesturing_no_tone3:":{"uc_base":"1f645-1f3fd","uc_output":"1f645-1f3fd","uc_match":"1f645-1f3fd","uc_greedy":"1f645-1f3fd","shortnames":[":no_good_tone3:"],"category":"people"},":person_gesturing_no_tone4:":{"uc_base":"1f645-1f3fe","uc_output":"1f645-1f3fe","uc_match":"1f645-1f3fe","uc_greedy":"1f645-1f3fe","shortnames":[":no_good_tone4:"],"category":"people"},":person_gesturing_no_tone5:":{"uc_base":"1f645-1f3ff","uc_output":"1f645-1f3ff","uc_match":"1f645-1f3ff","uc_greedy":"1f645-1f3ff","shortnames":[":no_good_tone5:"],"category":"people"},":person_gesturing_ok_tone1:":{"uc_base":"1f646-1f3fb","uc_output":"1f646-1f3fb","uc_match":"1f646-1f3fb","uc_greedy":"1f646-1f3fb","shortnames":[":ok_woman_tone1:"],"category":"people"},":person_gesturing_ok_tone2:":{"uc_base":"1f646-1f3fc","uc_output":"1f646-1f3fc","uc_match":"1f646-1f3fc","uc_greedy":"1f646-1f3fc","shortnames":[":ok_woman_tone2:"],"category":"people"},":person_gesturing_ok_tone3:":{"uc_base":"1f646-1f3fd","uc_output":"1f646-1f3fd","uc_match":"1f646-1f3fd","uc_greedy":"1f646-1f3fd","shortnames":[":ok_woman_tone3:"],"category":"people"},":person_gesturing_ok_tone4:":{"uc_base":"1f646-1f3fe","uc_output":"1f646-1f3fe","uc_match":"1f646-1f3fe","uc_greedy":"1f646-1f3fe","shortnames":[":ok_woman_tone4:"],"category":"people"},":person_gesturing_ok_tone5:":{"uc_base":"1f646-1f3ff","uc_output":"1f646-1f3ff","uc_match":"1f646-1f3ff","uc_greedy":"1f646-1f3ff","shortnames":[":ok_woman_tone5:"],"category":"people"},":person_getting_haircut_tone1:":{"uc_base":"1f487-1f3fb","uc_output":"1f487-1f3fb","uc_match":"1f487-1f3fb","uc_greedy":"1f487-1f3fb","shortnames":[":haircut_tone1:"],"category":"people"},":person_getting_haircut_tone2:":{"uc_base":"1f487-1f3fc","uc_output":"1f487-1f3fc","uc_match":"1f487-1f3fc","uc_greedy":"1f487-1f3fc","shortnames":[":haircut_tone2:"],"category":"people"},":person_getting_haircut_tone3:":{"uc_base":"1f487-1f3fd","uc_output":"1f487-1f3fd","uc_match":"1f487-1f3fd","uc_greedy":"1f487-1f3fd","shortnames":[":haircut_tone3:"],"category":"people"},":person_getting_haircut_tone4:":{"uc_base":"1f487-1f3fe","uc_output":"1f487-1f3fe","uc_match":"1f487-1f3fe","uc_greedy":"1f487-1f3fe","shortnames":[":haircut_tone4:"],"category":"people"},":person_getting_haircut_tone5:":{"uc_base":"1f487-1f3ff","uc_output":"1f487-1f3ff","uc_match":"1f487-1f3ff","uc_greedy":"1f487-1f3ff","shortnames":[":haircut_tone5:"],"category":"people"},":person_getting_massage_tone1:":{"uc_base":"1f486-1f3fb","uc_output":"1f486-1f3fb","uc_match":"1f486-1f3fb","uc_greedy":"1f486-1f3fb","shortnames":[":massage_tone1:"],"category":"people"},":person_getting_massage_tone2:":{"uc_base":"1f486-1f3fc","uc_output":"1f486-1f3fc","uc_match":"1f486-1f3fc","uc_greedy":"1f486-1f3fc","shortnames":[":massage_tone2:"],"category":"people"},":person_getting_massage_tone3:":{"uc_base":"1f486-1f3fd","uc_output":"1f486-1f3fd","uc_match":"1f486-1f3fd","uc_greedy":"1f486-1f3fd","shortnames":[":massage_tone3:"],"category":"people"},":person_getting_massage_tone4:":{"uc_base":"1f486-1f3fe","uc_output":"1f486-1f3fe","uc_match":"1f486-1f3fe","uc_greedy":"1f486-1f3fe","shortnames":[":massage_tone4:"],"category":"people"},":person_getting_massage_tone5:":{"uc_base":"1f486-1f3ff","uc_output":"1f486-1f3ff","uc_match":"1f486-1f3ff","uc_greedy":"1f486-1f3ff","shortnames":[":massage_tone5:"],"category":"people"},":person_golfing_tone1:":{"uc_base":"1f3cc-1f3fb","uc_output":"1f3cc-1f3fb","uc_match":"1f3cc-fe0f-1f3fb","uc_greedy":"1f3cc-fe0f-1f3fb","shortnames":[":person_golfing_light_skin_tone:"],"category":"activity"},":person_golfing_tone2:":{"uc_base":"1f3cc-1f3fc","uc_output":"1f3cc-1f3fc","uc_match":"1f3cc-fe0f-1f3fc","uc_greedy":"1f3cc-fe0f-1f3fc","shortnames":[":person_golfing_medium_light_skin_tone:"],"category":"activity"},":person_golfing_tone3:":{"uc_base":"1f3cc-1f3fd","uc_output":"1f3cc-1f3fd","uc_match":"1f3cc-fe0f-1f3fd","uc_greedy":"1f3cc-fe0f-1f3fd","shortnames":[":person_golfing_medium_skin_tone:"],"category":"activity"},":person_golfing_tone4:":{"uc_base":"1f3cc-1f3fe","uc_output":"1f3cc-1f3fe","uc_match":"1f3cc-fe0f-1f3fe","uc_greedy":"1f3cc-fe0f-1f3fe","shortnames":[":person_golfing_medium_dark_skin_tone:"],"category":"activity"},":person_golfing_tone5:":{"uc_base":"1f3cc-1f3ff","uc_output":"1f3cc-1f3ff","uc_match":"1f3cc-fe0f-1f3ff","uc_greedy":"1f3cc-fe0f-1f3ff","shortnames":[":person_golfing_dark_skin_tone:"],"category":"activity"},":person_in_bed_tone1:":{"uc_base":"1f6cc-1f3fb","uc_output":"1f6cc-1f3fb","uc_match":"1f6cc-1f3fb","uc_greedy":"1f6cc-1f3fb","shortnames":[":person_in_bed_light_skin_tone:"],"category":"objects"},":person_in_bed_tone2:":{"uc_base":"1f6cc-1f3fc","uc_output":"1f6cc-1f3fc","uc_match":"1f6cc-1f3fc","uc_greedy":"1f6cc-1f3fc","shortnames":[":person_in_bed_medium_light_skin_tone:"],"category":"objects"},":person_in_bed_tone3:":{"uc_base":"1f6cc-1f3fd","uc_output":"1f6cc-1f3fd","uc_match":"1f6cc-1f3fd","uc_greedy":"1f6cc-1f3fd","shortnames":[":person_in_bed_medium_skin_tone:"],"category":"objects"},":person_in_bed_tone4:":{"uc_base":"1f6cc-1f3fe","uc_output":"1f6cc-1f3fe","uc_match":"1f6cc-1f3fe","uc_greedy":"1f6cc-1f3fe","shortnames":[":person_in_bed_medium_dark_skin_tone:"],"category":"objects"},":person_in_bed_tone5:":{"uc_base":"1f6cc-1f3ff","uc_output":"1f6cc-1f3ff","uc_match":"1f6cc-1f3ff","uc_greedy":"1f6cc-1f3ff","shortnames":[":person_in_bed_dark_skin_tone:"],"category":"objects"},":person_in_lotus_position_tone1:":{"uc_base":"1f9d8-1f3fb","uc_output":"1f9d8-1f3fb","uc_match":"1f9d8-1f3fb","uc_greedy":"1f9d8-1f3fb","shortnames":[":person_in_lotus_position_light_skin_tone:"],"category":"activity"},":person_in_lotus_position_tone2:":{"uc_base":"1f9d8-1f3fc","uc_output":"1f9d8-1f3fc","uc_match":"1f9d8-1f3fc","uc_greedy":"1f9d8-1f3fc","shortnames":[":person_in_lotus_position_medium_light_skin_tone:"],"category":"activity"},":person_in_lotus_position_tone3:":{"uc_base":"1f9d8-1f3fd","uc_output":"1f9d8-1f3fd","uc_match":"1f9d8-1f3fd","uc_greedy":"1f9d8-1f3fd","shortnames":[":person_in_lotus_position_medium_skin_tone:"],"category":"activity"},":person_in_lotus_position_tone4:":{"uc_base":"1f9d8-1f3fe","uc_output":"1f9d8-1f3fe","uc_match":"1f9d8-1f3fe","uc_greedy":"1f9d8-1f3fe","shortnames":[":person_in_lotus_position_medium_dark_skin_tone:"],"category":"activity"},":person_in_lotus_position_tone5:":{"uc_base":"1f9d8-1f3ff","uc_output":"1f9d8-1f3ff","uc_match":"1f9d8-1f3ff","uc_greedy":"1f9d8-1f3ff","shortnames":[":person_in_lotus_position_dark_skin_tone:"],"category":"activity"},":person_in_steamy_room_tone1:":{"uc_base":"1f9d6-1f3fb","uc_output":"1f9d6-1f3fb","uc_match":"1f9d6-1f3fb","uc_greedy":"1f9d6-1f3fb","shortnames":[":person_in_steamy_room_light_skin_tone:"],"category":"activity"},":person_in_steamy_room_tone2:":{"uc_base":"1f9d6-1f3fc","uc_output":"1f9d6-1f3fc","uc_match":"1f9d6-1f3fc","uc_greedy":"1f9d6-1f3fc","shortnames":[":person_in_steamy_room_medium_light_skin_tone:"],"category":"activity"},":person_in_steamy_room_tone3:":{"uc_base":"1f9d6-1f3fd","uc_output":"1f9d6-1f3fd","uc_match":"1f9d6-1f3fd","uc_greedy":"1f9d6-1f3fd","shortnames":[":person_in_steamy_room_medium_skin_tone:"],"category":"activity"},":person_in_steamy_room_tone4:":{"uc_base":"1f9d6-1f3fe","uc_output":"1f9d6-1f3fe","uc_match":"1f9d6-1f3fe","uc_greedy":"1f9d6-1f3fe","shortnames":[":person_in_steamy_room_medium_dark_skin_tone:"],"category":"activity"},":person_in_steamy_room_tone5:":{"uc_base":"1f9d6-1f3ff","uc_output":"1f9d6-1f3ff","uc_match":"1f9d6-1f3ff","uc_greedy":"1f9d6-1f3ff","shortnames":[":person_in_steamy_room_dark_skin_tone:"],"category":"activity"},":person_juggling_tone1:":{"uc_base":"1f939-1f3fb","uc_output":"1f939-1f3fb","uc_match":"1f939-1f3fb","uc_greedy":"1f939-1f3fb","shortnames":[":juggling_tone1:",":juggler_tone1:"],"category":"activity"},":person_juggling_tone2:":{"uc_base":"1f939-1f3fc","uc_output":"1f939-1f3fc","uc_match":"1f939-1f3fc","uc_greedy":"1f939-1f3fc","shortnames":[":juggling_tone2:",":juggler_tone2:"],"category":"activity"},":person_juggling_tone3:":{"uc_base":"1f939-1f3fd","uc_output":"1f939-1f3fd","uc_match":"1f939-1f3fd","uc_greedy":"1f939-1f3fd","shortnames":[":juggling_tone3:",":juggler_tone3:"],"category":"activity"},":person_juggling_tone4:":{"uc_base":"1f939-1f3fe","uc_output":"1f939-1f3fe","uc_match":"1f939-1f3fe","uc_greedy":"1f939-1f3fe","shortnames":[":juggling_tone4:",":juggler_tone4:"],"category":"activity"},":person_juggling_tone5:":{"uc_base":"1f939-1f3ff","uc_output":"1f939-1f3ff","uc_match":"1f939-1f3ff","uc_greedy":"1f939-1f3ff","shortnames":[":juggling_tone5:",":juggler_tone5:"],"category":"activity"},":person_lifting_weights_tone1:":{"uc_base":"1f3cb-1f3fb","uc_output":"1f3cb-1f3fb","uc_match":"1f3cb-fe0f-1f3fb","uc_greedy":"1f3cb-fe0f-1f3fb","shortnames":[":lifter_tone1:",":weight_lifter_tone1:"],"category":"activity"},":person_lifting_weights_tone2:":{"uc_base":"1f3cb-1f3fc","uc_output":"1f3cb-1f3fc","uc_match":"1f3cb-fe0f-1f3fc","uc_greedy":"1f3cb-fe0f-1f3fc","shortnames":[":lifter_tone2:",":weight_lifter_tone2:"],"category":"activity"},":person_lifting_weights_tone3:":{"uc_base":"1f3cb-1f3fd","uc_output":"1f3cb-1f3fd","uc_match":"1f3cb-fe0f-1f3fd","uc_greedy":"1f3cb-fe0f-1f3fd","shortnames":[":lifter_tone3:",":weight_lifter_tone3:"],"category":"activity"},":person_lifting_weights_tone4:":{"uc_base":"1f3cb-1f3fe","uc_output":"1f3cb-1f3fe","uc_match":"1f3cb-fe0f-1f3fe","uc_greedy":"1f3cb-fe0f-1f3fe","shortnames":[":lifter_tone4:",":weight_lifter_tone4:"],"category":"activity"},":person_lifting_weights_tone5:":{"uc_base":"1f3cb-1f3ff","uc_output":"1f3cb-1f3ff","uc_match":"1f3cb-fe0f-1f3ff","uc_greedy":"1f3cb-fe0f-1f3ff","shortnames":[":lifter_tone5:",":weight_lifter_tone5:"],"category":"activity"},":person_mountain_biking_tone1:":{"uc_base":"1f6b5-1f3fb","uc_output":"1f6b5-1f3fb","uc_match":"1f6b5-1f3fb","uc_greedy":"1f6b5-1f3fb","shortnames":[":mountain_bicyclist_tone1:"],"category":"activity"},":person_mountain_biking_tone2:":{"uc_base":"1f6b5-1f3fc","uc_output":"1f6b5-1f3fc","uc_match":"1f6b5-1f3fc","uc_greedy":"1f6b5-1f3fc","shortnames":[":mountain_bicyclist_tone2:"],"category":"activity"},":person_mountain_biking_tone3:":{"uc_base":"1f6b5-1f3fd","uc_output":"1f6b5-1f3fd","uc_match":"1f6b5-1f3fd","uc_greedy":"1f6b5-1f3fd","shortnames":[":mountain_bicyclist_tone3:"],"category":"activity"},":person_mountain_biking_tone4:":{"uc_base":"1f6b5-1f3fe","uc_output":"1f6b5-1f3fe","uc_match":"1f6b5-1f3fe","uc_greedy":"1f6b5-1f3fe","shortnames":[":mountain_bicyclist_tone4:"],"category":"activity"},":person_mountain_biking_tone5:":{"uc_base":"1f6b5-1f3ff","uc_output":"1f6b5-1f3ff","uc_match":"1f6b5-1f3ff","uc_greedy":"1f6b5-1f3ff","shortnames":[":mountain_bicyclist_tone5:"],"category":"activity"},":person_playing_handball_tone1:":{"uc_base":"1f93e-1f3fb","uc_output":"1f93e-1f3fb","uc_match":"1f93e-1f3fb","uc_greedy":"1f93e-1f3fb","shortnames":[":handball_tone1:"],"category":"activity"},":person_playing_handball_tone2:":{"uc_base":"1f93e-1f3fc","uc_output":"1f93e-1f3fc","uc_match":"1f93e-1f3fc","uc_greedy":"1f93e-1f3fc","shortnames":[":handball_tone2:"],"category":"activity"},":person_playing_handball_tone3:":{"uc_base":"1f93e-1f3fd","uc_output":"1f93e-1f3fd","uc_match":"1f93e-1f3fd","uc_greedy":"1f93e-1f3fd","shortnames":[":handball_tone3:"],"category":"activity"},":person_playing_handball_tone4:":{"uc_base":"1f93e-1f3fe","uc_output":"1f93e-1f3fe","uc_match":"1f93e-1f3fe","uc_greedy":"1f93e-1f3fe","shortnames":[":handball_tone4:"],"category":"activity"},":person_playing_handball_tone5:":{"uc_base":"1f93e-1f3ff","uc_output":"1f93e-1f3ff","uc_match":"1f93e-1f3ff","uc_greedy":"1f93e-1f3ff","shortnames":[":handball_tone5:"],"category":"activity"},":person_playing_water_polo_tone1:":{"uc_base":"1f93d-1f3fb","uc_output":"1f93d-1f3fb","uc_match":"1f93d-1f3fb","uc_greedy":"1f93d-1f3fb","shortnames":[":water_polo_tone1:"],"category":"activity"},":person_playing_water_polo_tone2:":{"uc_base":"1f93d-1f3fc","uc_output":"1f93d-1f3fc","uc_match":"1f93d-1f3fc","uc_greedy":"1f93d-1f3fc","shortnames":[":water_polo_tone2:"],"category":"activity"},":person_playing_water_polo_tone3:":{"uc_base":"1f93d-1f3fd","uc_output":"1f93d-1f3fd","uc_match":"1f93d-1f3fd","uc_greedy":"1f93d-1f3fd","shortnames":[":water_polo_tone3:"],"category":"activity"},":person_playing_water_polo_tone4:":{"uc_base":"1f93d-1f3fe","uc_output":"1f93d-1f3fe","uc_match":"1f93d-1f3fe","uc_greedy":"1f93d-1f3fe","shortnames":[":water_polo_tone4:"],"category":"activity"},":person_playing_water_polo_tone5:":{"uc_base":"1f93d-1f3ff","uc_output":"1f93d-1f3ff","uc_match":"1f93d-1f3ff","uc_greedy":"1f93d-1f3ff","shortnames":[":water_polo_tone5:"],"category":"activity"},":person_pouting_tone1:":{"uc_base":"1f64e-1f3fb","uc_output":"1f64e-1f3fb","uc_match":"1f64e-1f3fb","uc_greedy":"1f64e-1f3fb","shortnames":[":person_with_pouting_face_tone1:"],"category":"people"},":person_pouting_tone2:":{"uc_base":"1f64e-1f3fc","uc_output":"1f64e-1f3fc","uc_match":"1f64e-1f3fc","uc_greedy":"1f64e-1f3fc","shortnames":[":person_with_pouting_face_tone2:"],"category":"people"},":person_pouting_tone3:":{"uc_base":"1f64e-1f3fd","uc_output":"1f64e-1f3fd","uc_match":"1f64e-1f3fd","uc_greedy":"1f64e-1f3fd","shortnames":[":person_with_pouting_face_tone3:"],"category":"people"},":person_pouting_tone4:":{"uc_base":"1f64e-1f3fe","uc_output":"1f64e-1f3fe","uc_match":"1f64e-1f3fe","uc_greedy":"1f64e-1f3fe","shortnames":[":person_with_pouting_face_tone4:"],"category":"people"},":person_pouting_tone5:":{"uc_base":"1f64e-1f3ff","uc_output":"1f64e-1f3ff","uc_match":"1f64e-1f3ff","uc_greedy":"1f64e-1f3ff","shortnames":[":person_with_pouting_face_tone5:"],"category":"people"},":person_raising_hand_tone1:":{"uc_base":"1f64b-1f3fb","uc_output":"1f64b-1f3fb","uc_match":"1f64b-1f3fb","uc_greedy":"1f64b-1f3fb","shortnames":[":raising_hand_tone1:"],"category":"people"},":person_raising_hand_tone2:":{"uc_base":"1f64b-1f3fc","uc_output":"1f64b-1f3fc","uc_match":"1f64b-1f3fc","uc_greedy":"1f64b-1f3fc","shortnames":[":raising_hand_tone2:"],"category":"people"},":person_raising_hand_tone3:":{"uc_base":"1f64b-1f3fd","uc_output":"1f64b-1f3fd","uc_match":"1f64b-1f3fd","uc_greedy":"1f64b-1f3fd","shortnames":[":raising_hand_tone3:"],"category":"people"},":person_raising_hand_tone4:":{"uc_base":"1f64b-1f3fe","uc_output":"1f64b-1f3fe","uc_match":"1f64b-1f3fe","uc_greedy":"1f64b-1f3fe","shortnames":[":raising_hand_tone4:"],"category":"people"},":person_raising_hand_tone5:":{"uc_base":"1f64b-1f3ff","uc_output":"1f64b-1f3ff","uc_match":"1f64b-1f3ff","uc_greedy":"1f64b-1f3ff","shortnames":[":raising_hand_tone5:"],"category":"people"},":person_rowing_boat_tone1:":{"uc_base":"1f6a3-1f3fb","uc_output":"1f6a3-1f3fb","uc_match":"1f6a3-1f3fb","uc_greedy":"1f6a3-1f3fb","shortnames":[":rowboat_tone1:"],"category":"activity"},":person_rowing_boat_tone2:":{"uc_base":"1f6a3-1f3fc","uc_output":"1f6a3-1f3fc","uc_match":"1f6a3-1f3fc","uc_greedy":"1f6a3-1f3fc","shortnames":[":rowboat_tone2:"],"category":"activity"},":person_rowing_boat_tone3:":{"uc_base":"1f6a3-1f3fd","uc_output":"1f6a3-1f3fd","uc_match":"1f6a3-1f3fd","uc_greedy":"1f6a3-1f3fd","shortnames":[":rowboat_tone3:"],"category":"activity"},":person_rowing_boat_tone4:":{"uc_base":"1f6a3-1f3fe","uc_output":"1f6a3-1f3fe","uc_match":"1f6a3-1f3fe","uc_greedy":"1f6a3-1f3fe","shortnames":[":rowboat_tone4:"],"category":"activity"},":person_rowing_boat_tone5:":{"uc_base":"1f6a3-1f3ff","uc_output":"1f6a3-1f3ff","uc_match":"1f6a3-1f3ff","uc_greedy":"1f6a3-1f3ff","shortnames":[":rowboat_tone5:"],"category":"activity"},":person_running_tone1:":{"uc_base":"1f3c3-1f3fb","uc_output":"1f3c3-1f3fb","uc_match":"1f3c3-1f3fb","uc_greedy":"1f3c3-1f3fb","shortnames":[":runner_tone1:"],"category":"people"},":person_running_tone2:":{"uc_base":"1f3c3-1f3fc","uc_output":"1f3c3-1f3fc","uc_match":"1f3c3-1f3fc","uc_greedy":"1f3c3-1f3fc","shortnames":[":runner_tone2:"],"category":"people"},":person_running_tone3:":{"uc_base":"1f3c3-1f3fd","uc_output":"1f3c3-1f3fd","uc_match":"1f3c3-1f3fd","uc_greedy":"1f3c3-1f3fd","shortnames":[":runner_tone3:"],"category":"people"},":person_running_tone4:":{"uc_base":"1f3c3-1f3fe","uc_output":"1f3c3-1f3fe","uc_match":"1f3c3-1f3fe","uc_greedy":"1f3c3-1f3fe","shortnames":[":runner_tone4:"],"category":"people"},":person_running_tone5:":{"uc_base":"1f3c3-1f3ff","uc_output":"1f3c3-1f3ff","uc_match":"1f3c3-1f3ff","uc_greedy":"1f3c3-1f3ff","shortnames":[":runner_tone5:"],"category":"people"},":person_shrugging_tone1:":{"uc_base":"1f937-1f3fb","uc_output":"1f937-1f3fb","uc_match":"1f937-1f3fb","uc_greedy":"1f937-1f3fb","shortnames":[":shrug_tone1:"],"category":"people"},":person_shrugging_tone2:":{"uc_base":"1f937-1f3fc","uc_output":"1f937-1f3fc","uc_match":"1f937-1f3fc","uc_greedy":"1f937-1f3fc","shortnames":[":shrug_tone2:"],"category":"people"},":person_shrugging_tone3:":{"uc_base":"1f937-1f3fd","uc_output":"1f937-1f3fd","uc_match":"1f937-1f3fd","uc_greedy":"1f937-1f3fd","shortnames":[":shrug_tone3:"],"category":"people"},":person_shrugging_tone4:":{"uc_base":"1f937-1f3fe","uc_output":"1f937-1f3fe","uc_match":"1f937-1f3fe","uc_greedy":"1f937-1f3fe","shortnames":[":shrug_tone4:"],"category":"people"},":person_shrugging_tone5:":{"uc_base":"1f937-1f3ff","uc_output":"1f937-1f3ff","uc_match":"1f937-1f3ff","uc_greedy":"1f937-1f3ff","shortnames":[":shrug_tone5:"],"category":"people"},":person_surfing_tone1:":{"uc_base":"1f3c4-1f3fb","uc_output":"1f3c4-1f3fb","uc_match":"1f3c4-1f3fb","uc_greedy":"1f3c4-1f3fb","shortnames":[":surfer_tone1:"],"category":"activity"},":person_surfing_tone2:":{"uc_base":"1f3c4-1f3fc","uc_output":"1f3c4-1f3fc","uc_match":"1f3c4-1f3fc","uc_greedy":"1f3c4-1f3fc","shortnames":[":surfer_tone2:"],"category":"activity"},":person_surfing_tone3:":{"uc_base":"1f3c4-1f3fd","uc_output":"1f3c4-1f3fd","uc_match":"1f3c4-1f3fd","uc_greedy":"1f3c4-1f3fd","shortnames":[":surfer_tone3:"],"category":"activity"},":person_surfing_tone4:":{"uc_base":"1f3c4-1f3fe","uc_output":"1f3c4-1f3fe","uc_match":"1f3c4-1f3fe","uc_greedy":"1f3c4-1f3fe","shortnames":[":surfer_tone4:"],"category":"activity"},":person_surfing_tone5:":{"uc_base":"1f3c4-1f3ff","uc_output":"1f3c4-1f3ff","uc_match":"1f3c4-1f3ff","uc_greedy":"1f3c4-1f3ff","shortnames":[":surfer_tone5:"],"category":"activity"},":person_swimming_tone1:":{"uc_base":"1f3ca-1f3fb","uc_output":"1f3ca-1f3fb","uc_match":"1f3ca-1f3fb","uc_greedy":"1f3ca-1f3fb","shortnames":[":swimmer_tone1:"],"category":"activity"},":person_swimming_tone2:":{"uc_base":"1f3ca-1f3fc","uc_output":"1f3ca-1f3fc","uc_match":"1f3ca-1f3fc","uc_greedy":"1f3ca-1f3fc","shortnames":[":swimmer_tone2:"],"category":"activity"},":person_swimming_tone3:":{"uc_base":"1f3ca-1f3fd","uc_output":"1f3ca-1f3fd","uc_match":"1f3ca-1f3fd","uc_greedy":"1f3ca-1f3fd","shortnames":[":swimmer_tone3:"],"category":"activity"},":person_swimming_tone4:":{"uc_base":"1f3ca-1f3fe","uc_output":"1f3ca-1f3fe","uc_match":"1f3ca-1f3fe","uc_greedy":"1f3ca-1f3fe","shortnames":[":swimmer_tone4:"],"category":"activity"},":person_swimming_tone5:":{"uc_base":"1f3ca-1f3ff","uc_output":"1f3ca-1f3ff","uc_match":"1f3ca-1f3ff","uc_greedy":"1f3ca-1f3ff","shortnames":[":swimmer_tone5:"],"category":"activity"},":person_tipping_hand_tone1:":{"uc_base":"1f481-1f3fb","uc_output":"1f481-1f3fb","uc_match":"1f481-1f3fb","uc_greedy":"1f481-1f3fb","shortnames":[":information_desk_person_tone1:"],"category":"people"},":person_tipping_hand_tone2:":{"uc_base":"1f481-1f3fc","uc_output":"1f481-1f3fc","uc_match":"1f481-1f3fc","uc_greedy":"1f481-1f3fc","shortnames":[":information_desk_person_tone2:"],"category":"people"},":person_tipping_hand_tone3:":{"uc_base":"1f481-1f3fd","uc_output":"1f481-1f3fd","uc_match":"1f481-1f3fd","uc_greedy":"1f481-1f3fd","shortnames":[":information_desk_person_tone3:"],"category":"people"},":person_tipping_hand_tone4:":{"uc_base":"1f481-1f3fe","uc_output":"1f481-1f3fe","uc_match":"1f481-1f3fe","uc_greedy":"1f481-1f3fe","shortnames":[":information_desk_person_tone4:"],"category":"people"},":person_tipping_hand_tone5:":{"uc_base":"1f481-1f3ff","uc_output":"1f481-1f3ff","uc_match":"1f481-1f3ff","uc_greedy":"1f481-1f3ff","shortnames":[":information_desk_person_tone5:"],"category":"people"},":person_walking_tone1:":{"uc_base":"1f6b6-1f3fb","uc_output":"1f6b6-1f3fb","uc_match":"1f6b6-1f3fb","uc_greedy":"1f6b6-1f3fb","shortnames":[":walking_tone1:"],"category":"people"},":person_walking_tone2:":{"uc_base":"1f6b6-1f3fc","uc_output":"1f6b6-1f3fc","uc_match":"1f6b6-1f3fc","uc_greedy":"1f6b6-1f3fc","shortnames":[":walking_tone2:"],"category":"people"},":person_walking_tone3:":{"uc_base":"1f6b6-1f3fd","uc_output":"1f6b6-1f3fd","uc_match":"1f6b6-1f3fd","uc_greedy":"1f6b6-1f3fd","shortnames":[":walking_tone3:"],"category":"people"},":person_walking_tone4:":{"uc_base":"1f6b6-1f3fe","uc_output":"1f6b6-1f3fe","uc_match":"1f6b6-1f3fe","uc_greedy":"1f6b6-1f3fe","shortnames":[":walking_tone4:"],"category":"people"},":person_walking_tone5:":{"uc_base":"1f6b6-1f3ff","uc_output":"1f6b6-1f3ff","uc_match":"1f6b6-1f3ff","uc_greedy":"1f6b6-1f3ff","shortnames":[":walking_tone5:"],"category":"people"},":person_wearing_turban_tone1:":{"uc_base":"1f473-1f3fb","uc_output":"1f473-1f3fb","uc_match":"1f473-1f3fb","uc_greedy":"1f473-1f3fb","shortnames":[":man_with_turban_tone1:"],"category":"people"},":person_wearing_turban_tone2:":{"uc_base":"1f473-1f3fc","uc_output":"1f473-1f3fc","uc_match":"1f473-1f3fc","uc_greedy":"1f473-1f3fc","shortnames":[":man_with_turban_tone2:"],"category":"people"},":person_wearing_turban_tone3:":{"uc_base":"1f473-1f3fd","uc_output":"1f473-1f3fd","uc_match":"1f473-1f3fd","uc_greedy":"1f473-1f3fd","shortnames":[":man_with_turban_tone3:"],"category":"people"},":person_wearing_turban_tone4:":{"uc_base":"1f473-1f3fe","uc_output":"1f473-1f3fe","uc_match":"1f473-1f3fe","uc_greedy":"1f473-1f3fe","shortnames":[":man_with_turban_tone4:"],"category":"people"},":person_wearing_turban_tone5:":{"uc_base":"1f473-1f3ff","uc_output":"1f473-1f3ff","uc_match":"1f473-1f3ff","uc_greedy":"1f473-1f3ff","shortnames":[":man_with_turban_tone5:"],"category":"people"},":point_down_tone1:":{"uc_base":"1f447-1f3fb","uc_output":"1f447-1f3fb","uc_match":"1f447-1f3fb","uc_greedy":"1f447-1f3fb","shortnames":[],"category":"people"},":point_down_tone2:":{"uc_base":"1f447-1f3fc","uc_output":"1f447-1f3fc","uc_match":"1f447-1f3fc","uc_greedy":"1f447-1f3fc","shortnames":[],"category":"people"},":point_down_tone3:":{"uc_base":"1f447-1f3fd","uc_output":"1f447-1f3fd","uc_match":"1f447-1f3fd","uc_greedy":"1f447-1f3fd","shortnames":[],"category":"people"},":point_down_tone4:":{"uc_base":"1f447-1f3fe","uc_output":"1f447-1f3fe","uc_match":"1f447-1f3fe","uc_greedy":"1f447-1f3fe","shortnames":[],"category":"people"},":point_down_tone5:":{"uc_base":"1f447-1f3ff","uc_output":"1f447-1f3ff","uc_match":"1f447-1f3ff","uc_greedy":"1f447-1f3ff","shortnames":[],"category":"people"},":point_left_tone1:":{"uc_base":"1f448-1f3fb","uc_output":"1f448-1f3fb","uc_match":"1f448-1f3fb","uc_greedy":"1f448-1f3fb","shortnames":[],"category":"people"},":point_left_tone2:":{"uc_base":"1f448-1f3fc","uc_output":"1f448-1f3fc","uc_match":"1f448-1f3fc","uc_greedy":"1f448-1f3fc","shortnames":[],"category":"people"},":point_left_tone3:":{"uc_base":"1f448-1f3fd","uc_output":"1f448-1f3fd","uc_match":"1f448-1f3fd","uc_greedy":"1f448-1f3fd","shortnames":[],"category":"people"},":point_left_tone4:":{"uc_base":"1f448-1f3fe","uc_output":"1f448-1f3fe","uc_match":"1f448-1f3fe","uc_greedy":"1f448-1f3fe","shortnames":[],"category":"people"},":point_left_tone5:":{"uc_base":"1f448-1f3ff","uc_output":"1f448-1f3ff","uc_match":"1f448-1f3ff","uc_greedy":"1f448-1f3ff","shortnames":[],"category":"people"},":point_right_tone1:":{"uc_base":"1f449-1f3fb","uc_output":"1f449-1f3fb","uc_match":"1f449-1f3fb","uc_greedy":"1f449-1f3fb","shortnames":[],"category":"people"},":point_right_tone2:":{"uc_base":"1f449-1f3fc","uc_output":"1f449-1f3fc","uc_match":"1f449-1f3fc","uc_greedy":"1f449-1f3fc","shortnames":[],"category":"people"},":point_right_tone3:":{"uc_base":"1f449-1f3fd","uc_output":"1f449-1f3fd","uc_match":"1f449-1f3fd","uc_greedy":"1f449-1f3fd","shortnames":[],"category":"people"},":point_right_tone4:":{"uc_base":"1f449-1f3fe","uc_output":"1f449-1f3fe","uc_match":"1f449-1f3fe","uc_greedy":"1f449-1f3fe","shortnames":[],"category":"people"},":point_right_tone5:":{"uc_base":"1f449-1f3ff","uc_output":"1f449-1f3ff","uc_match":"1f449-1f3ff","uc_greedy":"1f449-1f3ff","shortnames":[],"category":"people"},":point_up_2_tone1:":{"uc_base":"1f446-1f3fb","uc_output":"1f446-1f3fb","uc_match":"1f446-1f3fb","uc_greedy":"1f446-1f3fb","shortnames":[],"category":"people"},":point_up_2_tone2:":{"uc_base":"1f446-1f3fc","uc_output":"1f446-1f3fc","uc_match":"1f446-1f3fc","uc_greedy":"1f446-1f3fc","shortnames":[],"category":"people"},":point_up_2_tone3:":{"uc_base":"1f446-1f3fd","uc_output":"1f446-1f3fd","uc_match":"1f446-1f3fd","uc_greedy":"1f446-1f3fd","shortnames":[],"category":"people"},":point_up_2_tone4:":{"uc_base":"1f446-1f3fe","uc_output":"1f446-1f3fe","uc_match":"1f446-1f3fe","uc_greedy":"1f446-1f3fe","shortnames":[],"category":"people"},":point_up_2_tone5:":{"uc_base":"1f446-1f3ff","uc_output":"1f446-1f3ff","uc_match":"1f446-1f3ff","uc_greedy":"1f446-1f3ff","shortnames":[],"category":"people"},":police_officer_tone1:":{"uc_base":"1f46e-1f3fb","uc_output":"1f46e-1f3fb","uc_match":"1f46e-1f3fb","uc_greedy":"1f46e-1f3fb","shortnames":[":cop_tone1:"],"category":"people"},":police_officer_tone2:":{"uc_base":"1f46e-1f3fc","uc_output":"1f46e-1f3fc","uc_match":"1f46e-1f3fc","uc_greedy":"1f46e-1f3fc","shortnames":[":cop_tone2:"],"category":"people"},":police_officer_tone3:":{"uc_base":"1f46e-1f3fd","uc_output":"1f46e-1f3fd","uc_match":"1f46e-1f3fd","uc_greedy":"1f46e-1f3fd","shortnames":[":cop_tone3:"],"category":"people"},":police_officer_tone4:":{"uc_base":"1f46e-1f3fe","uc_output":"1f46e-1f3fe","uc_match":"1f46e-1f3fe","uc_greedy":"1f46e-1f3fe","shortnames":[":cop_tone4:"],"category":"people"},":police_officer_tone5:":{"uc_base":"1f46e-1f3ff","uc_output":"1f46e-1f3ff","uc_match":"1f46e-1f3ff","uc_greedy":"1f46e-1f3ff","shortnames":[":cop_tone5:"],"category":"people"},":pray_tone1:":{"uc_base":"1f64f-1f3fb","uc_output":"1f64f-1f3fb","uc_match":"1f64f-1f3fb","uc_greedy":"1f64f-1f3fb","shortnames":[],"category":"people"},":pray_tone2:":{"uc_base":"1f64f-1f3fc","uc_output":"1f64f-1f3fc","uc_match":"1f64f-1f3fc","uc_greedy":"1f64f-1f3fc","shortnames":[],"category":"people"},":pray_tone3:":{"uc_base":"1f64f-1f3fd","uc_output":"1f64f-1f3fd","uc_match":"1f64f-1f3fd","uc_greedy":"1f64f-1f3fd","shortnames":[],"category":"people"},":pray_tone4:":{"uc_base":"1f64f-1f3fe","uc_output":"1f64f-1f3fe","uc_match":"1f64f-1f3fe","uc_greedy":"1f64f-1f3fe","shortnames":[],"category":"people"},":pray_tone5:":{"uc_base":"1f64f-1f3ff","uc_output":"1f64f-1f3ff","uc_match":"1f64f-1f3ff","uc_greedy":"1f64f-1f3ff","shortnames":[],"category":"people"},":pregnant_woman_tone1:":{"uc_base":"1f930-1f3fb","uc_output":"1f930-1f3fb","uc_match":"1f930-1f3fb","uc_greedy":"1f930-1f3fb","shortnames":[":expecting_woman_tone1:"],"category":"people"},":pregnant_woman_tone2:":{"uc_base":"1f930-1f3fc","uc_output":"1f930-1f3fc","uc_match":"1f930-1f3fc","uc_greedy":"1f930-1f3fc","shortnames":[":expecting_woman_tone2:"],"category":"people"},":pregnant_woman_tone3:":{"uc_base":"1f930-1f3fd","uc_output":"1f930-1f3fd","uc_match":"1f930-1f3fd","uc_greedy":"1f930-1f3fd","shortnames":[":expecting_woman_tone3:"],"category":"people"},":pregnant_woman_tone4:":{"uc_base":"1f930-1f3fe","uc_output":"1f930-1f3fe","uc_match":"1f930-1f3fe","uc_greedy":"1f930-1f3fe","shortnames":[":expecting_woman_tone4:"],"category":"people"},":pregnant_woman_tone5:":{"uc_base":"1f930-1f3ff","uc_output":"1f930-1f3ff","uc_match":"1f930-1f3ff","uc_greedy":"1f930-1f3ff","shortnames":[":expecting_woman_tone5:"],"category":"people"},":prince_tone1:":{"uc_base":"1f934-1f3fb","uc_output":"1f934-1f3fb","uc_match":"1f934-1f3fb","uc_greedy":"1f934-1f3fb","shortnames":[],"category":"people"},":prince_tone2:":{"uc_base":"1f934-1f3fc","uc_output":"1f934-1f3fc","uc_match":"1f934-1f3fc","uc_greedy":"1f934-1f3fc","shortnames":[],"category":"people"},":prince_tone3:":{"uc_base":"1f934-1f3fd","uc_output":"1f934-1f3fd","uc_match":"1f934-1f3fd","uc_greedy":"1f934-1f3fd","shortnames":[],"category":"people"},":prince_tone4:":{"uc_base":"1f934-1f3fe","uc_output":"1f934-1f3fe","uc_match":"1f934-1f3fe","uc_greedy":"1f934-1f3fe","shortnames":[],"category":"people"},":prince_tone5:":{"uc_base":"1f934-1f3ff","uc_output":"1f934-1f3ff","uc_match":"1f934-1f3ff","uc_greedy":"1f934-1f3ff","shortnames":[],"category":"people"},":princess_tone1:":{"uc_base":"1f478-1f3fb","uc_output":"1f478-1f3fb","uc_match":"1f478-1f3fb","uc_greedy":"1f478-1f3fb","shortnames":[],"category":"people"},":princess_tone2:":{"uc_base":"1f478-1f3fc","uc_output":"1f478-1f3fc","uc_match":"1f478-1f3fc","uc_greedy":"1f478-1f3fc","shortnames":[],"category":"people"},":princess_tone3:":{"uc_base":"1f478-1f3fd","uc_output":"1f478-1f3fd","uc_match":"1f478-1f3fd","uc_greedy":"1f478-1f3fd","shortnames":[],"category":"people"},":princess_tone4:":{"uc_base":"1f478-1f3fe","uc_output":"1f478-1f3fe","uc_match":"1f478-1f3fe","uc_greedy":"1f478-1f3fe","shortnames":[],"category":"people"},":princess_tone5:":{"uc_base":"1f478-1f3ff","uc_output":"1f478-1f3ff","uc_match":"1f478-1f3ff","uc_greedy":"1f478-1f3ff","shortnames":[],"category":"people"},":punch_tone1:":{"uc_base":"1f44a-1f3fb","uc_output":"1f44a-1f3fb","uc_match":"1f44a-1f3fb","uc_greedy":"1f44a-1f3fb","shortnames":[],"category":"people"},":punch_tone2:":{"uc_base":"1f44a-1f3fc","uc_output":"1f44a-1f3fc","uc_match":"1f44a-1f3fc","uc_greedy":"1f44a-1f3fc","shortnames":[],"category":"people"},":punch_tone3:":{"uc_base":"1f44a-1f3fd","uc_output":"1f44a-1f3fd","uc_match":"1f44a-1f3fd","uc_greedy":"1f44a-1f3fd","shortnames":[],"category":"people"},":punch_tone4:":{"uc_base":"1f44a-1f3fe","uc_output":"1f44a-1f3fe","uc_match":"1f44a-1f3fe","uc_greedy":"1f44a-1f3fe","shortnames":[],"category":"people"},":punch_tone5:":{"uc_base":"1f44a-1f3ff","uc_output":"1f44a-1f3ff","uc_match":"1f44a-1f3ff","uc_greedy":"1f44a-1f3ff","shortnames":[],"category":"people"},":raised_back_of_hand_tone1:":{"uc_base":"1f91a-1f3fb","uc_output":"1f91a-1f3fb","uc_match":"1f91a-1f3fb","uc_greedy":"1f91a-1f3fb","shortnames":[":back_of_hand_tone1:"],"category":"people"},":raised_back_of_hand_tone2:":{"uc_base":"1f91a-1f3fc","uc_output":"1f91a-1f3fc","uc_match":"1f91a-1f3fc","uc_greedy":"1f91a-1f3fc","shortnames":[":back_of_hand_tone2:"],"category":"people"},":raised_back_of_hand_tone3:":{"uc_base":"1f91a-1f3fd","uc_output":"1f91a-1f3fd","uc_match":"1f91a-1f3fd","uc_greedy":"1f91a-1f3fd","shortnames":[":back_of_hand_tone3:"],"category":"people"},":raised_back_of_hand_tone4:":{"uc_base":"1f91a-1f3fe","uc_output":"1f91a-1f3fe","uc_match":"1f91a-1f3fe","uc_greedy":"1f91a-1f3fe","shortnames":[":back_of_hand_tone4:"],"category":"people"},":raised_back_of_hand_tone5:":{"uc_base":"1f91a-1f3ff","uc_output":"1f91a-1f3ff","uc_match":"1f91a-1f3ff","uc_greedy":"1f91a-1f3ff","shortnames":[":back_of_hand_tone5:"],"category":"people"},":raised_hands_tone1:":{"uc_base":"1f64c-1f3fb","uc_output":"1f64c-1f3fb","uc_match":"1f64c-1f3fb","uc_greedy":"1f64c-1f3fb","shortnames":[],"category":"people"},":raised_hands_tone2:":{"uc_base":"1f64c-1f3fc","uc_output":"1f64c-1f3fc","uc_match":"1f64c-1f3fc","uc_greedy":"1f64c-1f3fc","shortnames":[],"category":"people"},":raised_hands_tone3:":{"uc_base":"1f64c-1f3fd","uc_output":"1f64c-1f3fd","uc_match":"1f64c-1f3fd","uc_greedy":"1f64c-1f3fd","shortnames":[],"category":"people"},":raised_hands_tone4:":{"uc_base":"1f64c-1f3fe","uc_output":"1f64c-1f3fe","uc_match":"1f64c-1f3fe","uc_greedy":"1f64c-1f3fe","shortnames":[],"category":"people"},":raised_hands_tone5:":{"uc_base":"1f64c-1f3ff","uc_output":"1f64c-1f3ff","uc_match":"1f64c-1f3ff","uc_greedy":"1f64c-1f3ff","shortnames":[],"category":"people"},":right_facing_fist_tone1:":{"uc_base":"1f91c-1f3fb","uc_output":"1f91c-1f3fb","uc_match":"1f91c-1f3fb","uc_greedy":"1f91c-1f3fb","shortnames":[":right_fist_tone1:"],"category":"people"},":right_facing_fist_tone2:":{"uc_base":"1f91c-1f3fc","uc_output":"1f91c-1f3fc","uc_match":"1f91c-1f3fc","uc_greedy":"1f91c-1f3fc","shortnames":[":right_fist_tone2:"],"category":"people"},":right_facing_fist_tone3:":{"uc_base":"1f91c-1f3fd","uc_output":"1f91c-1f3fd","uc_match":"1f91c-1f3fd","uc_greedy":"1f91c-1f3fd","shortnames":[":right_fist_tone3:"],"category":"people"},":right_facing_fist_tone4:":{"uc_base":"1f91c-1f3fe","uc_output":"1f91c-1f3fe","uc_match":"1f91c-1f3fe","uc_greedy":"1f91c-1f3fe","shortnames":[":right_fist_tone4:"],"category":"people"},":right_facing_fist_tone5:":{"uc_base":"1f91c-1f3ff","uc_output":"1f91c-1f3ff","uc_match":"1f91c-1f3ff","uc_greedy":"1f91c-1f3ff","shortnames":[":right_fist_tone5:"],"category":"people"},":santa_tone1:":{"uc_base":"1f385-1f3fb","uc_output":"1f385-1f3fb","uc_match":"1f385-1f3fb","uc_greedy":"1f385-1f3fb","shortnames":[],"category":"people"},":santa_tone2:":{"uc_base":"1f385-1f3fc","uc_output":"1f385-1f3fc","uc_match":"1f385-1f3fc","uc_greedy":"1f385-1f3fc","shortnames":[],"category":"people"},":santa_tone3:":{"uc_base":"1f385-1f3fd","uc_output":"1f385-1f3fd","uc_match":"1f385-1f3fd","uc_greedy":"1f385-1f3fd","shortnames":[],"category":"people"},":santa_tone4:":{"uc_base":"1f385-1f3fe","uc_output":"1f385-1f3fe","uc_match":"1f385-1f3fe","uc_greedy":"1f385-1f3fe","shortnames":[],"category":"people"},":santa_tone5:":{"uc_base":"1f385-1f3ff","uc_output":"1f385-1f3ff","uc_match":"1f385-1f3ff","uc_greedy":"1f385-1f3ff","shortnames":[],"category":"people"},":selfie_tone1:":{"uc_base":"1f933-1f3fb","uc_output":"1f933-1f3fb","uc_match":"1f933-1f3fb","uc_greedy":"1f933-1f3fb","shortnames":[],"category":"people"},":selfie_tone2:":{"uc_base":"1f933-1f3fc","uc_output":"1f933-1f3fc","uc_match":"1f933-1f3fc","uc_greedy":"1f933-1f3fc","shortnames":[],"category":"people"},":selfie_tone3:":{"uc_base":"1f933-1f3fd","uc_output":"1f933-1f3fd","uc_match":"1f933-1f3fd","uc_greedy":"1f933-1f3fd","shortnames":[],"category":"people"},":selfie_tone4:":{"uc_base":"1f933-1f3fe","uc_output":"1f933-1f3fe","uc_match":"1f933-1f3fe","uc_greedy":"1f933-1f3fe","shortnames":[],"category":"people"},":selfie_tone5:":{"uc_base":"1f933-1f3ff","uc_output":"1f933-1f3ff","uc_match":"1f933-1f3ff","uc_greedy":"1f933-1f3ff","shortnames":[],"category":"people"},":snowboarder_tone1:":{"uc_base":"1f3c2-1f3fb","uc_output":"1f3c2-1f3fb","uc_match":"1f3c2-1f3fb","uc_greedy":"1f3c2-1f3fb","shortnames":[":snowboarder_light_skin_tone:"],"category":"activity"},":snowboarder_tone2:":{"uc_base":"1f3c2-1f3fc","uc_output":"1f3c2-1f3fc","uc_match":"1f3c2-1f3fc","uc_greedy":"1f3c2-1f3fc","shortnames":[":snowboarder_medium_light_skin_tone:"],"category":"activity"},":snowboarder_tone3:":{"uc_base":"1f3c2-1f3fd","uc_output":"1f3c2-1f3fd","uc_match":"1f3c2-1f3fd","uc_greedy":"1f3c2-1f3fd","shortnames":[":snowboarder_medium_skin_tone:"],"category":"activity"},":snowboarder_tone4:":{"uc_base":"1f3c2-1f3fe","uc_output":"1f3c2-1f3fe","uc_match":"1f3c2-1f3fe","uc_greedy":"1f3c2-1f3fe","shortnames":[":snowboarder_medium_dark_skin_tone:"],"category":"activity"},":snowboarder_tone5:":{"uc_base":"1f3c2-1f3ff","uc_output":"1f3c2-1f3ff","uc_match":"1f3c2-1f3ff","uc_greedy":"1f3c2-1f3ff","shortnames":[":snowboarder_dark_skin_tone:"],"category":"activity"},":thumbsdown_tone1:":{"uc_base":"1f44e-1f3fb","uc_output":"1f44e-1f3fb","uc_match":"1f44e-1f3fb","uc_greedy":"1f44e-1f3fb","shortnames":[":-1_tone1:",":thumbdown_tone1:"],"category":"people"},":thumbsdown_tone2:":{"uc_base":"1f44e-1f3fc","uc_output":"1f44e-1f3fc","uc_match":"1f44e-1f3fc","uc_greedy":"1f44e-1f3fc","shortnames":[":-1_tone2:",":thumbdown_tone2:"],"category":"people"},":thumbsdown_tone3:":{"uc_base":"1f44e-1f3fd","uc_output":"1f44e-1f3fd","uc_match":"1f44e-1f3fd","uc_greedy":"1f44e-1f3fd","shortnames":[":-1_tone3:",":thumbdown_tone3:"],"category":"people"},":thumbsdown_tone4:":{"uc_base":"1f44e-1f3fe","uc_output":"1f44e-1f3fe","uc_match":"1f44e-1f3fe","uc_greedy":"1f44e-1f3fe","shortnames":[":-1_tone4:",":thumbdown_tone4:"],"category":"people"},":thumbsdown_tone5:":{"uc_base":"1f44e-1f3ff","uc_output":"1f44e-1f3ff","uc_match":"1f44e-1f3ff","uc_greedy":"1f44e-1f3ff","shortnames":[":-1_tone5:",":thumbdown_tone5:"],"category":"people"},":thumbsup_tone1:":{"uc_base":"1f44d-1f3fb","uc_output":"1f44d-1f3fb","uc_match":"1f44d-1f3fb","uc_greedy":"1f44d-1f3fb","shortnames":[":+1_tone1:",":thumbup_tone1:"],"category":"people"},":thumbsup_tone2:":{"uc_base":"1f44d-1f3fc","uc_output":"1f44d-1f3fc","uc_match":"1f44d-1f3fc","uc_greedy":"1f44d-1f3fc","shortnames":[":+1_tone2:",":thumbup_tone2:"],"category":"people"},":thumbsup_tone3:":{"uc_base":"1f44d-1f3fd","uc_output":"1f44d-1f3fd","uc_match":"1f44d-1f3fd","uc_greedy":"1f44d-1f3fd","shortnames":[":+1_tone3:",":thumbup_tone3:"],"category":"people"},":thumbsup_tone4:":{"uc_base":"1f44d-1f3fe","uc_output":"1f44d-1f3fe","uc_match":"1f44d-1f3fe","uc_greedy":"1f44d-1f3fe","shortnames":[":+1_tone4:",":thumbup_tone4:"],"category":"people"},":thumbsup_tone5:":{"uc_base":"1f44d-1f3ff","uc_output":"1f44d-1f3ff","uc_match":"1f44d-1f3ff","uc_greedy":"1f44d-1f3ff","shortnames":[":+1_tone5:",":thumbup_tone5:"],"category":"people"},":united_nations:":{"uc_base":"1f1fa-1f1f3","uc_output":"1f1fa-1f1f3","uc_match":"1f1fa-1f1f3","uc_greedy":"1f1fa-1f1f3","shortnames":[],"category":"flags"},":vampire_tone1:":{"uc_base":"1f9db-1f3fb","uc_output":"1f9db-1f3fb","uc_match":"1f9db-1f3fb","uc_greedy":"1f9db-1f3fb","shortnames":[":vampire_light_skin_tone:"],"category":"people"},":vampire_tone2:":{"uc_base":"1f9db-1f3fc","uc_output":"1f9db-1f3fc","uc_match":"1f9db-1f3fc","uc_greedy":"1f9db-1f3fc","shortnames":[":vampire_medium_light_skin_tone:"],"category":"people"},":vampire_tone3:":{"uc_base":"1f9db-1f3fd","uc_output":"1f9db-1f3fd","uc_match":"1f9db-1f3fd","uc_greedy":"1f9db-1f3fd","shortnames":[":vampire_medium_skin_tone:"],"category":"people"},":vampire_tone4:":{"uc_base":"1f9db-1f3fe","uc_output":"1f9db-1f3fe","uc_match":"1f9db-1f3fe","uc_greedy":"1f9db-1f3fe","shortnames":[":vampire_medium_dark_skin_tone:"],"category":"people"},":vampire_tone5:":{"uc_base":"1f9db-1f3ff","uc_output":"1f9db-1f3ff","uc_match":"1f9db-1f3ff","uc_greedy":"1f9db-1f3ff","shortnames":[":vampire_dark_skin_tone:"],"category":"people"},":vulcan_tone1:":{"uc_base":"1f596-1f3fb","uc_output":"1f596-1f3fb","uc_match":"1f596-1f3fb","uc_greedy":"1f596-1f3fb","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers_tone1:"],"category":"people"},":vulcan_tone2:":{"uc_base":"1f596-1f3fc","uc_output":"1f596-1f3fc","uc_match":"1f596-1f3fc","uc_greedy":"1f596-1f3fc","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers_tone2:"],"category":"people"},":vulcan_tone3:":{"uc_base":"1f596-1f3fd","uc_output":"1f596-1f3fd","uc_match":"1f596-1f3fd","uc_greedy":"1f596-1f3fd","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers_tone3:"],"category":"people"},":vulcan_tone4:":{"uc_base":"1f596-1f3fe","uc_output":"1f596-1f3fe","uc_match":"1f596-1f3fe","uc_greedy":"1f596-1f3fe","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers_tone4:"],"category":"people"},":vulcan_tone5:":{"uc_base":"1f596-1f3ff","uc_output":"1f596-1f3ff","uc_match":"1f596-1f3ff","uc_greedy":"1f596-1f3ff","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers_tone5:"],"category":"people"},":wave_tone1:":{"uc_base":"1f44b-1f3fb","uc_output":"1f44b-1f3fb","uc_match":"1f44b-1f3fb","uc_greedy":"1f44b-1f3fb","shortnames":[],"category":"people"},":wave_tone2:":{"uc_base":"1f44b-1f3fc","uc_output":"1f44b-1f3fc","uc_match":"1f44b-1f3fc","uc_greedy":"1f44b-1f3fc","shortnames":[],"category":"people"},":wave_tone3:":{"uc_base":"1f44b-1f3fd","uc_output":"1f44b-1f3fd","uc_match":"1f44b-1f3fd","uc_greedy":"1f44b-1f3fd","shortnames":[],"category":"people"},":wave_tone4:":{"uc_base":"1f44b-1f3fe","uc_output":"1f44b-1f3fe","uc_match":"1f44b-1f3fe","uc_greedy":"1f44b-1f3fe","shortnames":[],"category":"people"},":wave_tone5:":{"uc_base":"1f44b-1f3ff","uc_output":"1f44b-1f3ff","uc_match":"1f44b-1f3ff","uc_greedy":"1f44b-1f3ff","shortnames":[],"category":"people"},":woman_tone1:":{"uc_base":"1f469-1f3fb","uc_output":"1f469-1f3fb","uc_match":"1f469-1f3fb","uc_greedy":"1f469-1f3fb","shortnames":[],"category":"people"},":woman_tone2:":{"uc_base":"1f469-1f3fc","uc_output":"1f469-1f3fc","uc_match":"1f469-1f3fc","uc_greedy":"1f469-1f3fc","shortnames":[],"category":"people"},":woman_tone3:":{"uc_base":"1f469-1f3fd","uc_output":"1f469-1f3fd","uc_match":"1f469-1f3fd","uc_greedy":"1f469-1f3fd","shortnames":[],"category":"people"},":woman_tone4:":{"uc_base":"1f469-1f3fe","uc_output":"1f469-1f3fe","uc_match":"1f469-1f3fe","uc_greedy":"1f469-1f3fe","shortnames":[],"category":"people"},":woman_tone5:":{"uc_base":"1f469-1f3ff","uc_output":"1f469-1f3ff","uc_match":"1f469-1f3ff","uc_greedy":"1f469-1f3ff","shortnames":[],"category":"people"},":woman_with_headscarf_tone1:":{"uc_base":"1f9d5-1f3fb","uc_output":"1f9d5-1f3fb","uc_match":"1f9d5-1f3fb","uc_greedy":"1f9d5-1f3fb","shortnames":[":woman_with_headscarf_light_skin_tone:"],"category":"people"},":woman_with_headscarf_tone2:":{"uc_base":"1f9d5-1f3fc","uc_output":"1f9d5-1f3fc","uc_match":"1f9d5-1f3fc","uc_greedy":"1f9d5-1f3fc","shortnames":[":woman_with_headscarf_medium_light_skin_tone:"],"category":"people"},":woman_with_headscarf_tone3:":{"uc_base":"1f9d5-1f3fd","uc_output":"1f9d5-1f3fd","uc_match":"1f9d5-1f3fd","uc_greedy":"1f9d5-1f3fd","shortnames":[":woman_with_headscarf_medium_skin_tone:"],"category":"people"},":woman_with_headscarf_tone4:":{"uc_base":"1f9d5-1f3fe","uc_output":"1f9d5-1f3fe","uc_match":"1f9d5-1f3fe","uc_greedy":"1f9d5-1f3fe","shortnames":[":woman_with_headscarf_medium_dark_skin_tone:"],"category":"people"},":woman_with_headscarf_tone5:":{"uc_base":"1f9d5-1f3ff","uc_output":"1f9d5-1f3ff","uc_match":"1f9d5-1f3ff","uc_greedy":"1f9d5-1f3ff","shortnames":[":woman_with_headscarf_dark_skin_tone:"],"category":"people"},":a:":{"uc_base":"1f170","uc_output":"1f170-fe0f","uc_match":"1f170-fe0f","uc_greedy":"1f170","shortnames":[],"category":"symbols"},":airplane_small:":{"uc_base":"1f6e9","uc_output":"1f6e9-fe0f","uc_match":"1f6e9-fe0f","uc_greedy":"1f6e9","shortnames":[":small_airplane:"],"category":"travel"},":anger_right:":{"uc_base":"1f5ef","uc_output":"1f5ef-fe0f","uc_match":"1f5ef-fe0f","uc_greedy":"1f5ef","shortnames":[":right_anger_bubble:"],"category":"symbols"},":b:":{"uc_base":"1f171","uc_output":"1f171-fe0f","uc_match":"1f171-fe0f","uc_greedy":"1f171","shortnames":[],"category":"symbols"},":ballot_box:":{"uc_base":"1f5f3","uc_output":"1f5f3-fe0f","uc_match":"1f5f3-fe0f","uc_greedy":"1f5f3","shortnames":[":ballot_box_with_ballot:"],"category":"objects"},":beach:":{"uc_base":"1f3d6","uc_output":"1f3d6-fe0f","uc_match":"1f3d6-fe0f","uc_greedy":"1f3d6","shortnames":[":beach_with_umbrella:"],"category":"travel"},":bed:":{"uc_base":"1f6cf","uc_output":"1f6cf-fe0f","uc_match":"1f6cf-fe0f","uc_greedy":"1f6cf","shortnames":[],"category":"objects"},":bellhop:":{"uc_base":"1f6ce","uc_output":"1f6ce-fe0f","uc_match":"1f6ce-fe0f","uc_greedy":"1f6ce","shortnames":[":bellhop_bell:"],"category":"objects"},":calendar_spiral:":{"uc_base":"1f5d3","uc_output":"1f5d3-fe0f","uc_match":"1f5d3-fe0f","uc_greedy":"1f5d3","shortnames":[":spiral_calendar_pad:"],"category":"objects"},":camping:":{"uc_base":"1f3d5","uc_output":"1f3d5-fe0f","uc_match":"1f3d5-fe0f","uc_greedy":"1f3d5","shortnames":[],"category":"travel"},":candle:":{"uc_base":"1f56f","uc_output":"1f56f-fe0f","uc_match":"1f56f-fe0f","uc_greedy":"1f56f","shortnames":[],"category":"objects"},":card_box:":{"uc_base":"1f5c3","uc_output":"1f5c3-fe0f","uc_match":"1f5c3-fe0f","uc_greedy":"1f5c3","shortnames":[":card_file_box:"],"category":"objects"},":chipmunk:":{"uc_base":"1f43f","uc_output":"1f43f-fe0f","uc_match":"1f43f-fe0f","uc_greedy":"1f43f","shortnames":[],"category":"nature"},":cityscape:":{"uc_base":"1f3d9","uc_output":"1f3d9-fe0f","uc_match":"1f3d9-fe0f","uc_greedy":"1f3d9","shortnames":[],"category":"travel"},":classical_building:":{"uc_base":"1f3db","uc_output":"1f3db-fe0f","uc_match":"1f3db-fe0f","uc_greedy":"1f3db","shortnames":[],"category":"travel"},":clock:":{"uc_base":"1f570","uc_output":"1f570-fe0f","uc_match":"1f570-fe0f","uc_greedy":"1f570","shortnames":[":mantlepiece_clock:"],"category":"objects"},":cloud_lightning:":{"uc_base":"1f329","uc_output":"1f329-fe0f","uc_match":"1f329-fe0f","uc_greedy":"1f329","shortnames":[":cloud_with_lightning:"],"category":"nature"},":cloud_rain:":{"uc_base":"1f327","uc_output":"1f327-fe0f","uc_match":"1f327-fe0f","uc_greedy":"1f327","shortnames":[":cloud_with_rain:"],"category":"nature"},":cloud_snow:":{"uc_base":"1f328","uc_output":"1f328-fe0f","uc_match":"1f328-fe0f","uc_greedy":"1f328","shortnames":[":cloud_with_snow:"],"category":"nature"},":cloud_tornado:":{"uc_base":"1f32a","uc_output":"1f32a-fe0f","uc_match":"1f32a-fe0f","uc_greedy":"1f32a","shortnames":[":cloud_with_tornado:"],"category":"nature"},":compression:":{"uc_base":"1f5dc","uc_output":"1f5dc-fe0f","uc_match":"1f5dc-fe0f","uc_greedy":"1f5dc","shortnames":[],"category":"objects"},":construction_site:":{"uc_base":"1f3d7","uc_output":"1f3d7-fe0f","uc_match":"1f3d7-fe0f","uc_greedy":"1f3d7","shortnames":[":building_construction:"],"category":"travel"},":control_knobs:":{"uc_base":"1f39b","uc_output":"1f39b-fe0f","uc_match":"1f39b-fe0f","uc_greedy":"1f39b","shortnames":[],"category":"objects"},":couch:":{"uc_base":"1f6cb","uc_output":"1f6cb-fe0f","uc_match":"1f6cb-fe0f","uc_greedy":"1f6cb","shortnames":[":couch_and_lamp:"],"category":"objects"},":crayon:":{"uc_base":"1f58d","uc_output":"1f58d-fe0f","uc_match":"1f58d-fe0f","uc_greedy":"1f58d","shortnames":[":lower_left_crayon:"],"category":"objects"},":cruise_ship:":{"uc_base":"1f6f3","uc_output":"1f6f3-fe0f","uc_match":"1f6f3-fe0f","uc_greedy":"1f6f3","shortnames":[":passenger_ship:"],"category":"travel"},":dagger:":{"uc_base":"1f5e1","uc_output":"1f5e1-fe0f","uc_match":"1f5e1-fe0f","uc_greedy":"1f5e1","shortnames":[":dagger_knife:"],"category":"objects"},":dark_sunglasses:":{"uc_base":"1f576","uc_output":"1f576-fe0f","uc_match":"1f576-fe0f","uc_greedy":"1f576","shortnames":[],"category":"people"},":desert:":{"uc_base":"1f3dc","uc_output":"1f3dc-fe0f","uc_match":"1f3dc-fe0f","uc_greedy":"1f3dc","shortnames":[],"category":"travel"},":desktop:":{"uc_base":"1f5a5","uc_output":"1f5a5-fe0f","uc_match":"1f5a5-fe0f","uc_greedy":"1f5a5","shortnames":[":desktop_computer:"],"category":"objects"},":detective:":{"uc_base":"1f575","uc_output":"1f575-fe0f","uc_match":"1f575-fe0f","uc_greedy":"1f575","shortnames":[":spy:",":sleuth_or_spy:"],"category":"people"},":dividers:":{"uc_base":"1f5c2","uc_output":"1f5c2-fe0f","uc_match":"1f5c2-fe0f","uc_greedy":"1f5c2","shortnames":[":card_index_dividers:"],"category":"objects"},":dove:":{"uc_base":"1f54a","uc_output":"1f54a-fe0f","uc_match":"1f54a-fe0f","uc_greedy":"1f54a","shortnames":[":dove_of_peace:"],"category":"nature"},":eye:":{"uc_base":"1f441","uc_output":"1f441-fe0f","uc_match":"1f441-fe0f","uc_greedy":"1f441","shortnames":[],"category":"people"},":file_cabinet:":{"uc_base":"1f5c4","uc_output":"1f5c4-fe0f","uc_match":"1f5c4-fe0f","uc_greedy":"1f5c4","shortnames":[],"category":"objects"},":film_frames:":{"uc_base":"1f39e","uc_output":"1f39e-fe0f","uc_match":"1f39e-fe0f","uc_greedy":"1f39e","shortnames":[],"category":"objects"},":fist_tone1:":{"uc_base":"270a-1f3fb","uc_output":"270a-1f3fb","uc_match":"270a-1f3fb","uc_greedy":"270a-1f3fb","shortnames":[],"category":"people"},":fist_tone2:":{"uc_base":"270a-1f3fc","uc_output":"270a-1f3fc","uc_match":"270a-1f3fc","uc_greedy":"270a-1f3fc","shortnames":[],"category":"people"},":fist_tone3:":{"uc_base":"270a-1f3fd","uc_output":"270a-1f3fd","uc_match":"270a-1f3fd","uc_greedy":"270a-1f3fd","shortnames":[],"category":"people"},":fist_tone4:":{"uc_base":"270a-1f3fe","uc_output":"270a-1f3fe","uc_match":"270a-1f3fe","uc_greedy":"270a-1f3fe","shortnames":[],"category":"people"},":fist_tone5:":{"uc_base":"270a-1f3ff","uc_output":"270a-1f3ff","uc_match":"270a-1f3ff","uc_greedy":"270a-1f3ff","shortnames":[],"category":"people"},":flag_white:":{"uc_base":"1f3f3","uc_output":"1f3f3-fe0f","uc_match":"1f3f3-fe0f","uc_greedy":"1f3f3","shortnames":[":waving_white_flag:"],"category":"flags"},":fog:":{"uc_base":"1f32b","uc_output":"1f32b-fe0f","uc_match":"1f32b-fe0f","uc_greedy":"1f32b","shortnames":[],"category":"nature"},":fork_knife_plate:":{"uc_base":"1f37d","uc_output":"1f37d-fe0f","uc_match":"1f37d-fe0f","uc_greedy":"1f37d","shortnames":[":fork_and_knife_with_plate:"],"category":"food"},":frame_photo:":{"uc_base":"1f5bc","uc_output":"1f5bc-fe0f","uc_match":"1f5bc-fe0f","uc_greedy":"1f5bc","shortnames":[":frame_with_picture:"],"category":"objects"},":hand_splayed:":{"uc_base":"1f590","uc_output":"1f590-fe0f","uc_match":"1f590-fe0f","uc_greedy":"1f590","shortnames":[":raised_hand_with_fingers_splayed:"],"category":"people"},":hole:":{"uc_base":"1f573","uc_output":"1f573-fe0f","uc_match":"1f573-fe0f","uc_greedy":"1f573","shortnames":[],"category":"objects"},":homes:":{"uc_base":"1f3d8","uc_output":"1f3d8-fe0f","uc_match":"1f3d8-fe0f","uc_greedy":"1f3d8","shortnames":[":house_buildings:"],"category":"travel"},":hot_pepper:":{"uc_base":"1f336","uc_output":"1f336-fe0f","uc_match":"1f336-fe0f","uc_greedy":"1f336","shortnames":[],"category":"food"},":house_abandoned:":{"uc_base":"1f3da","uc_output":"1f3da-fe0f","uc_match":"1f3da-fe0f","uc_greedy":"1f3da","shortnames":[":derelict_house_building:"],"category":"travel"},":island:":{"uc_base":"1f3dd","uc_output":"1f3dd-fe0f","uc_match":"1f3dd-fe0f","uc_greedy":"1f3dd","shortnames":[":desert_island:"],"category":"travel"},":joystick:":{"uc_base":"1f579","uc_output":"1f579-fe0f","uc_match":"1f579-fe0f","uc_greedy":"1f579","shortnames":[],"category":"objects"},":key2:":{"uc_base":"1f5dd","uc_output":"1f5dd-fe0f","uc_match":"1f5dd-fe0f","uc_greedy":"1f5dd","shortnames":[":old_key:"],"category":"objects"},":label:":{"uc_base":"1f3f7","uc_output":"1f3f7-fe0f","uc_match":"1f3f7-fe0f","uc_greedy":"1f3f7","shortnames":[],"category":"objects"},":level_slider:":{"uc_base":"1f39a","uc_output":"1f39a-fe0f","uc_match":"1f39a-fe0f","uc_greedy":"1f39a","shortnames":[],"category":"objects"},":man_in_business_suit_levitating:":{"uc_base":"1f574","uc_output":"1f574-fe0f","uc_match":"1f574-fe0f","uc_greedy":"1f574","shortnames":[],"category":"people"},":map:":{"uc_base":"1f5fa","uc_output":"1f5fa-fe0f","uc_match":"1f5fa-fe0f","uc_greedy":"1f5fa","shortnames":[":world_map:"],"category":"travel"},":microphone2:":{"uc_base":"1f399","uc_output":"1f399-fe0f","uc_match":"1f399-fe0f","uc_greedy":"1f399","shortnames":[":studio_microphone:"],"category":"objects"},":military_medal:":{"uc_base":"1f396","uc_output":"1f396-fe0f","uc_match":"1f396-fe0f","uc_greedy":"1f396","shortnames":[],"category":"activity"},":motorboat:":{"uc_base":"1f6e5","uc_output":"1f6e5-fe0f","uc_match":"1f6e5-fe0f","uc_greedy":"1f6e5","shortnames":[],"category":"travel"},":motorcycle:":{"uc_base":"1f3cd","uc_output":"1f3cd-fe0f","uc_match":"1f3cd-fe0f","uc_greedy":"1f3cd","shortnames":[":racing_motorcycle:"],"category":"travel"},":motorway:":{"uc_base":"1f6e3","uc_output":"1f6e3-fe0f","uc_match":"1f6e3-fe0f","uc_greedy":"1f6e3","shortnames":[],"category":"travel"},":mountain_snow:":{"uc_base":"1f3d4","uc_output":"1f3d4-fe0f","uc_match":"1f3d4-fe0f","uc_greedy":"1f3d4","shortnames":[":snow_capped_mountain:"],"category":"travel"},":mouse_three_button:":{"uc_base":"1f5b1","uc_output":"1f5b1-fe0f","uc_match":"1f5b1-fe0f","uc_greedy":"1f5b1","shortnames":[":three_button_mouse:"],"category":"objects"},":newspaper2:":{"uc_base":"1f5de","uc_output":"1f5de-fe0f","uc_match":"1f5de-fe0f","uc_greedy":"1f5de","shortnames":[":rolled_up_newspaper:"],"category":"objects"},":notepad_spiral:":{"uc_base":"1f5d2","uc_output":"1f5d2-fe0f","uc_match":"1f5d2-fe0f","uc_greedy":"1f5d2","shortnames":[":spiral_note_pad:"],"category":"objects"},":o2:":{"uc_base":"1f17e","uc_output":"1f17e-fe0f","uc_match":"1f17e-fe0f","uc_greedy":"1f17e","shortnames":[],"category":"symbols"},":oil:":{"uc_base":"1f6e2","uc_output":"1f6e2-fe0f","uc_match":"1f6e2-fe0f","uc_greedy":"1f6e2","shortnames":[":oil_drum:"],"category":"objects"},":om_symbol:":{"uc_base":"1f549","uc_output":"1f549-fe0f","uc_match":"1f549-fe0f","uc_greedy":"1f549","shortnames":[],"category":"symbols"},":paintbrush:":{"uc_base":"1f58c","uc_output":"1f58c-fe0f","uc_match":"1f58c-fe0f","uc_greedy":"1f58c","shortnames":[":lower_left_paintbrush:"],"category":"objects"},":paperclips:":{"uc_base":"1f587","uc_output":"1f587-fe0f","uc_match":"1f587-fe0f","uc_greedy":"1f587","shortnames":[":linked_paperclips:"],"category":"objects"},":park:":{"uc_base":"1f3de","uc_output":"1f3de-fe0f","uc_match":"1f3de-fe0f","uc_greedy":"1f3de","shortnames":[":national_park:"],"category":"travel"},":parking:":{"uc_base":"1f17f","uc_output":"1f17f-fe0f","uc_match":"1f17f-fe0f","uc_greedy":"1f17f","shortnames":[],"category":"symbols"},":pen_ballpoint:":{"uc_base":"1f58a","uc_output":"1f58a-fe0f","uc_match":"1f58a-fe0f","uc_greedy":"1f58a","shortnames":[":lower_left_ballpoint_pen:"],"category":"objects"},":pen_fountain:":{"uc_base":"1f58b","uc_output":"1f58b-fe0f","uc_match":"1f58b-fe0f","uc_greedy":"1f58b","shortnames":[":lower_left_fountain_pen:"],"category":"objects"},":person_bouncing_ball_tone1:":{"uc_base":"26f9-1f3fb","uc_output":"26f9-1f3fb","uc_match":"26f9-fe0f-1f3fb","uc_greedy":"26f9-fe0f-1f3fb","shortnames":[":basketball_player_tone1:",":person_with_ball_tone1:"],"category":"activity"},":person_bouncing_ball_tone2:":{"uc_base":"26f9-1f3fc","uc_output":"26f9-1f3fc","uc_match":"26f9-fe0f-1f3fc","uc_greedy":"26f9-fe0f-1f3fc","shortnames":[":basketball_player_tone2:",":person_with_ball_tone2:"],"category":"activity"},":person_bouncing_ball_tone3:":{"uc_base":"26f9-1f3fd","uc_output":"26f9-1f3fd","uc_match":"26f9-fe0f-1f3fd","uc_greedy":"26f9-fe0f-1f3fd","shortnames":[":basketball_player_tone3:",":person_with_ball_tone3:"],"category":"activity"},":person_bouncing_ball_tone4:":{"uc_base":"26f9-1f3fe","uc_output":"26f9-1f3fe","uc_match":"26f9-fe0f-1f3fe","uc_greedy":"26f9-fe0f-1f3fe","shortnames":[":basketball_player_tone4:",":person_with_ball_tone4:"],"category":"activity"},":person_bouncing_ball_tone5:":{"uc_base":"26f9-1f3ff","uc_output":"26f9-1f3ff","uc_match":"26f9-fe0f-1f3ff","uc_greedy":"26f9-fe0f-1f3ff","shortnames":[":basketball_player_tone5:",":person_with_ball_tone5:"],"category":"activity"},":person_golfing:":{"uc_base":"1f3cc","uc_output":"1f3cc-fe0f","uc_match":"1f3cc-fe0f","uc_greedy":"1f3cc","shortnames":[":golfer:"],"category":"activity"},":person_lifting_weights:":{"uc_base":"1f3cb","uc_output":"1f3cb-fe0f","uc_match":"1f3cb-fe0f","uc_greedy":"1f3cb","shortnames":[":lifter:",":weight_lifter:"],"category":"activity"},":point_up_tone1:":{"uc_base":"261d-1f3fb","uc_output":"261d-1f3fb","uc_match":"261d-fe0f-1f3fb","uc_greedy":"261d-fe0f-1f3fb","shortnames":[],"category":"people"},":point_up_tone2:":{"uc_base":"261d-1f3fc","uc_output":"261d-1f3fc","uc_match":"261d-fe0f-1f3fc","uc_greedy":"261d-fe0f-1f3fc","shortnames":[],"category":"people"},":point_up_tone3:":{"uc_base":"261d-1f3fd","uc_output":"261d-1f3fd","uc_match":"261d-fe0f-1f3fd","uc_greedy":"261d-fe0f-1f3fd","shortnames":[],"category":"people"},":point_up_tone4:":{"uc_base":"261d-1f3fe","uc_output":"261d-1f3fe","uc_match":"261d-fe0f-1f3fe","uc_greedy":"261d-fe0f-1f3fe","shortnames":[],"category":"people"},":point_up_tone5:":{"uc_base":"261d-1f3ff","uc_output":"261d-1f3ff","uc_match":"261d-fe0f-1f3ff","uc_greedy":"261d-fe0f-1f3ff","shortnames":[],"category":"people"},":printer:":{"uc_base":"1f5a8","uc_output":"1f5a8-fe0f","uc_match":"1f5a8-fe0f","uc_greedy":"1f5a8","shortnames":[],"category":"objects"},":projector:":{"uc_base":"1f4fd","uc_output":"1f4fd-fe0f","uc_match":"1f4fd-fe0f","uc_greedy":"1f4fd","shortnames":[":film_projector:"],"category":"objects"},":race_car:":{"uc_base":"1f3ce","uc_output":"1f3ce-fe0f","uc_match":"1f3ce-fe0f","uc_greedy":"1f3ce","shortnames":[":racing_car:"],"category":"travel"},":railway_track:":{"uc_base":"1f6e4","uc_output":"1f6e4-fe0f","uc_match":"1f6e4-fe0f","uc_greedy":"1f6e4","shortnames":[":railroad_track:"],"category":"travel"},":raised_hand_tone1:":{"uc_base":"270b-1f3fb","uc_output":"270b-1f3fb","uc_match":"270b-1f3fb","uc_greedy":"270b-1f3fb","shortnames":[],"category":"people"},":raised_hand_tone2:":{"uc_base":"270b-1f3fc","uc_output":"270b-1f3fc","uc_match":"270b-1f3fc","uc_greedy":"270b-1f3fc","shortnames":[],"category":"people"},":raised_hand_tone3:":{"uc_base":"270b-1f3fd","uc_output":"270b-1f3fd","uc_match":"270b-1f3fd","uc_greedy":"270b-1f3fd","shortnames":[],"category":"people"},":raised_hand_tone4:":{"uc_base":"270b-1f3fe","uc_output":"270b-1f3fe","uc_match":"270b-1f3fe","uc_greedy":"270b-1f3fe","shortnames":[],"category":"people"},":raised_hand_tone5:":{"uc_base":"270b-1f3ff","uc_output":"270b-1f3ff","uc_match":"270b-1f3ff","uc_greedy":"270b-1f3ff","shortnames":[],"category":"people"},":reminder_ribbon:":{"uc_base":"1f397","uc_output":"1f397-fe0f","uc_match":"1f397-fe0f","uc_greedy":"1f397","shortnames":[],"category":"activity"},":rosette:":{"uc_base":"1f3f5","uc_output":"1f3f5-fe0f","uc_match":"1f3f5-fe0f","uc_greedy":"1f3f5","shortnames":[],"category":"activity"},":sa:":{"uc_base":"1f202","uc_output":"1f202-fe0f","uc_match":"1f202-fe0f","uc_greedy":"1f202","shortnames":[],"category":"symbols"},":satellite_orbital:":{"uc_base":"1f6f0","uc_output":"1f6f0-fe0f","uc_match":"1f6f0-fe0f","uc_greedy":"1f6f0","shortnames":[],"category":"travel"},":shield:":{"uc_base":"1f6e1","uc_output":"1f6e1-fe0f","uc_match":"1f6e1-fe0f","uc_greedy":"1f6e1","shortnames":[],"category":"objects"},":shopping_bags:":{"uc_base":"1f6cd","uc_output":"1f6cd-fe0f","uc_match":"1f6cd-fe0f","uc_greedy":"1f6cd","shortnames":[],"category":"objects"},":speaking_head:":{"uc_base":"1f5e3","uc_output":"1f5e3-fe0f","uc_match":"1f5e3-fe0f","uc_greedy":"1f5e3","shortnames":[":speaking_head_in_silhouette:"],"category":"people"},":speech_left:":{"uc_base":"1f5e8","uc_output":"1f5e8-fe0f","uc_match":"1f5e8-fe0f","uc_greedy":"1f5e8","shortnames":[":left_speech_bubble:"],"category":"symbols"},":spider:":{"uc_base":"1f577","uc_output":"1f577-fe0f","uc_match":"1f577-fe0f","uc_greedy":"1f577","shortnames":[],"category":"nature"},":spider_web:":{"uc_base":"1f578","uc_output":"1f578-fe0f","uc_match":"1f578-fe0f","uc_greedy":"1f578","shortnames":[],"category":"nature"},":stadium:":{"uc_base":"1f3df","uc_output":"1f3df-fe0f","uc_match":"1f3df-fe0f","uc_greedy":"1f3df","shortnames":[],"category":"travel"},":thermometer:":{"uc_base":"1f321","uc_output":"1f321-fe0f","uc_match":"1f321-fe0f","uc_greedy":"1f321","shortnames":[],"category":"objects"},":tickets:":{"uc_base":"1f39f","uc_output":"1f39f-fe0f","uc_match":"1f39f-fe0f","uc_greedy":"1f39f","shortnames":[":admission_tickets:"],"category":"activity"},":tools:":{"uc_base":"1f6e0","uc_output":"1f6e0-fe0f","uc_match":"1f6e0-fe0f","uc_greedy":"1f6e0","shortnames":[":hammer_and_wrench:"],"category":"objects"},":trackball:":{"uc_base":"1f5b2","uc_output":"1f5b2-fe0f","uc_match":"1f5b2-fe0f","uc_greedy":"1f5b2","shortnames":[],"category":"objects"},":u6708:":{"uc_base":"1f237","uc_output":"1f237-fe0f","uc_match":"1f237-fe0f","uc_greedy":"1f237","shortnames":[],"category":"symbols"},":v_tone1:":{"uc_base":"270c-1f3fb","uc_output":"270c-1f3fb","uc_match":"270c-fe0f-1f3fb","uc_greedy":"270c-fe0f-1f3fb","shortnames":[],"category":"people"},":v_tone2:":{"uc_base":"270c-1f3fc","uc_output":"270c-1f3fc","uc_match":"270c-fe0f-1f3fc","uc_greedy":"270c-fe0f-1f3fc","shortnames":[],"category":"people"},":v_tone3:":{"uc_base":"270c-1f3fd","uc_output":"270c-1f3fd","uc_match":"270c-fe0f-1f3fd","uc_greedy":"270c-fe0f-1f3fd","shortnames":[],"category":"people"},":v_tone4:":{"uc_base":"270c-1f3fe","uc_output":"270c-1f3fe","uc_match":"270c-fe0f-1f3fe","uc_greedy":"270c-fe0f-1f3fe","shortnames":[],"category":"people"},":v_tone5:":{"uc_base":"270c-1f3ff","uc_output":"270c-1f3ff","uc_match":"270c-fe0f-1f3ff","uc_greedy":"270c-fe0f-1f3ff","shortnames":[],"category":"people"},":wastebasket:":{"uc_base":"1f5d1","uc_output":"1f5d1-fe0f","uc_match":"1f5d1-fe0f","uc_greedy":"1f5d1","shortnames":[],"category":"objects"},":white_sun_cloud:":{"uc_base":"1f325","uc_output":"1f325-fe0f","uc_match":"1f325-fe0f","uc_greedy":"1f325","shortnames":[":white_sun_behind_cloud:"],"category":"nature"},":white_sun_rain_cloud:":{"uc_base":"1f326","uc_output":"1f326-fe0f","uc_match":"1f326-fe0f","uc_greedy":"1f326","shortnames":[":white_sun_behind_cloud_with_rain:"],"category":"nature"},":white_sun_small_cloud:":{"uc_base":"1f324","uc_output":"1f324-fe0f","uc_match":"1f324-fe0f","uc_greedy":"1f324","shortnames":[":white_sun_with_small_cloud:"],"category":"nature"},":wind_blowing_face:":{"uc_base":"1f32c","uc_output":"1f32c-fe0f","uc_match":"1f32c-fe0f","uc_greedy":"1f32c","shortnames":[],"category":"nature"},":writing_hand_tone1:":{"uc_base":"270d-1f3fb","uc_output":"270d-1f3fb","uc_match":"270d-fe0f-1f3fb","uc_greedy":"270d-fe0f-1f3fb","shortnames":[],"category":"people"},":writing_hand_tone2:":{"uc_base":"270d-1f3fc","uc_output":"270d-1f3fc","uc_match":"270d-fe0f-1f3fc","uc_greedy":"270d-fe0f-1f3fc","shortnames":[],"category":"people"},":writing_hand_tone3:":{"uc_base":"270d-1f3fd","uc_output":"270d-1f3fd","uc_match":"270d-fe0f-1f3fd","uc_greedy":"270d-fe0f-1f3fd","shortnames":[],"category":"people"},":writing_hand_tone4:":{"uc_base":"270d-1f3fe","uc_output":"270d-1f3fe","uc_match":"270d-fe0f-1f3fe","uc_greedy":"270d-fe0f-1f3fe","shortnames":[],"category":"people"},":writing_hand_tone5:":{"uc_base":"270d-1f3ff","uc_output":"270d-1f3ff","uc_match":"270d-fe0f-1f3ff","uc_greedy":"270d-fe0f-1f3ff","shortnames":[],"category":"people"},":airplane:":{"uc_base":"2708","uc_output":"2708-fe0f","uc_match":"2708-fe0f","uc_greedy":"2708","shortnames":[],"category":"travel"},":alembic:":{"uc_base":"2697","uc_output":"2697-fe0f","uc_match":"2697-fe0f","uc_greedy":"2697","shortnames":[],"category":"objects"},":arrow_backward:":{"uc_base":"25c0","uc_output":"25c0-fe0f","uc_match":"25c0-fe0f","uc_greedy":"25c0","shortnames":[],"category":"symbols"},":arrow_down:":{"uc_base":"2b07","uc_output":"2b07-fe0f","uc_match":"2b07-fe0f","uc_greedy":"2b07","shortnames":[],"category":"symbols"},":arrow_forward:":{"uc_base":"25b6","uc_output":"25b6-fe0f","uc_match":"25b6-fe0f","uc_greedy":"25b6","shortnames":[],"category":"symbols"},":arrow_heading_down:":{"uc_base":"2935","uc_output":"2935-fe0f","uc_match":"2935-fe0f","uc_greedy":"2935","shortnames":[],"category":"symbols"},":arrow_heading_up:":{"uc_base":"2934","uc_output":"2934-fe0f","uc_match":"2934-fe0f","uc_greedy":"2934","shortnames":[],"category":"symbols"},":arrow_left:":{"uc_base":"2b05","uc_output":"2b05-fe0f","uc_match":"2b05-fe0f","uc_greedy":"2b05","shortnames":[],"category":"symbols"},":arrow_lower_left:":{"uc_base":"2199","uc_output":"2199-fe0f","uc_match":"2199-fe0f","uc_greedy":"2199","shortnames":[],"category":"symbols"},":arrow_lower_right:":{"uc_base":"2198","uc_output":"2198-fe0f","uc_match":"2198-fe0f","uc_greedy":"2198","shortnames":[],"category":"symbols"},":arrow_right:":{"uc_base":"27a1","uc_output":"27a1-fe0f","uc_match":"27a1-fe0f","uc_greedy":"27a1","shortnames":[],"category":"symbols"},":arrow_right_hook:":{"uc_base":"21aa","uc_output":"21aa-fe0f","uc_match":"21aa-fe0f","uc_greedy":"21aa","shortnames":[],"category":"symbols"},":arrow_up:":{"uc_base":"2b06","uc_output":"2b06-fe0f","uc_match":"2b06-fe0f","uc_greedy":"2b06","shortnames":[],"category":"symbols"},":arrow_up_down:":{"uc_base":"2195","uc_output":"2195-fe0f","uc_match":"2195-fe0f","uc_greedy":"2195","shortnames":[],"category":"symbols"},":arrow_upper_left:":{"uc_base":"2196","uc_output":"2196-fe0f","uc_match":"2196-fe0f","uc_greedy":"2196","shortnames":[],"category":"symbols"},":arrow_upper_right:":{"uc_base":"2197","uc_output":"2197-fe0f","uc_match":"2197-fe0f","uc_greedy":"2197","shortnames":[],"category":"symbols"},":asterisk_symbol:":{"uc_base":"002a","uc_output":"002a-fe0f","uc_match":"002a-fe0f","uc_greedy":"002a","shortnames":[],"category":"symbols"},":atom:":{"uc_base":"269b","uc_output":"269b-fe0f","uc_match":"269b-fe0f","uc_greedy":"269b","shortnames":[":atom_symbol:"],"category":"symbols"},":ballot_box_with_check:":{"uc_base":"2611","uc_output":"2611-fe0f","uc_match":"2611-fe0f","uc_greedy":"2611","shortnames":[],"category":"symbols"},":bangbang:":{"uc_base":"203c","uc_output":"203c-fe0f","uc_match":"203c-fe0f","uc_greedy":"203c","shortnames":[],"category":"symbols"},":beach_umbrella:":{"uc_base":"26f1","uc_output":"26f1-fe0f","uc_match":"26f1-fe0f","uc_greedy":"26f1","shortnames":[":umbrella_on_ground:"],"category":"travel"},":biohazard:":{"uc_base":"2623","uc_output":"2623-fe0f","uc_match":"2623-fe0f","uc_greedy":"2623","shortnames":[":biohazard_sign:"],"category":"symbols"},":black_medium_square:":{"uc_base":"25fc","uc_output":"25fc-fe0f","uc_match":"25fc-fe0f","uc_greedy":"25fc","shortnames":[],"category":"symbols"},":black_nib:":{"uc_base":"2712","uc_output":"2712-fe0f","uc_match":"2712-fe0f","uc_greedy":"2712","shortnames":[],"category":"objects"},":black_small_square:":{"uc_base":"25aa","uc_output":"25aa-fe0f","uc_match":"25aa-fe0f","uc_greedy":"25aa","shortnames":[],"category":"symbols"},":chains:":{"uc_base":"26d3","uc_output":"26d3-fe0f","uc_match":"26d3-fe0f","uc_greedy":"26d3","shortnames":[],"category":"objects"},":cloud:":{"uc_base":"2601","uc_output":"2601-fe0f","uc_match":"2601-fe0f","uc_greedy":"2601","shortnames":[],"category":"nature"},":clubs:":{"uc_base":"2663","uc_output":"2663-fe0f","uc_match":"2663-fe0f","uc_greedy":"2663","shortnames":[],"category":"symbols"},":coffin:":{"uc_base":"26b0","uc_output":"26b0-fe0f","uc_match":"26b0-fe0f","uc_greedy":"26b0","shortnames":[],"category":"objects"},":comet:":{"uc_base":"2604","uc_output":"2604-fe0f","uc_match":"2604-fe0f","uc_greedy":"2604","shortnames":[],"category":"nature"},":congratulations:":{"uc_base":"3297","uc_output":"3297-fe0f","uc_match":"3297-fe0f","uc_greedy":"3297","shortnames":[],"category":"symbols"},":copyright:":{"uc_base":"00a9","uc_output":"00a9-fe0f","uc_match":"00a9-fe0f","uc_greedy":"00a9","shortnames":[],"category":"symbols"},":cross:":{"uc_base":"271d","uc_output":"271d-fe0f","uc_match":"271d-fe0f","uc_greedy":"271d","shortnames":[":latin_cross:"],"category":"symbols"},":crossed_swords:":{"uc_base":"2694","uc_output":"2694-fe0f","uc_match":"2694-fe0f","uc_greedy":"2694","shortnames":[],"category":"objects"},":diamonds:":{"uc_base":"2666","uc_output":"2666-fe0f","uc_match":"2666-fe0f","uc_greedy":"2666","shortnames":[],"category":"symbols"},":digit_eight:":{"uc_base":"0038","uc_output":"0038-fe0f","uc_match":"0038-fe0f","uc_greedy":"0038","shortnames":[],"category":"symbols"},":digit_five:":{"uc_base":"0035","uc_output":"0035-fe0f","uc_match":"0035-fe0f","uc_greedy":"0035","shortnames":[],"category":"symbols"},":digit_four:":{"uc_base":"0034","uc_output":"0034-fe0f","uc_match":"0034-fe0f","uc_greedy":"0034","shortnames":[],"category":"symbols"},":digit_nine:":{"uc_base":"0039","uc_output":"0039-fe0f","uc_match":"0039-fe0f","uc_greedy":"0039","shortnames":[],"category":"symbols"},":digit_one:":{"uc_base":"0031","uc_output":"0031-fe0f","uc_match":"0031-fe0f","uc_greedy":"0031","shortnames":[],"category":"symbols"},":digit_seven:":{"uc_base":"0037","uc_output":"0037-fe0f","uc_match":"0037-fe0f","uc_greedy":"0037","shortnames":[],"category":"symbols"},":digit_six:":{"uc_base":"0036","uc_output":"0036-fe0f","uc_match":"0036-fe0f","uc_greedy":"0036","shortnames":[],"category":"symbols"},":digit_three:":{"uc_base":"0033","uc_output":"0033-fe0f","uc_match":"0033-fe0f","uc_greedy":"0033","shortnames":[],"category":"symbols"},":digit_two:":{"uc_base":"0032","uc_output":"0032-fe0f","uc_match":"0032-fe0f","uc_greedy":"0032","shortnames":[],"category":"symbols"},":digit_zero:":{"uc_base":"0030","uc_output":"0030-fe0f","uc_match":"0030-fe0f","uc_greedy":"0030","shortnames":[],"category":"symbols"},":eight_pointed_black_star:":{"uc_base":"2734","uc_output":"2734-fe0f","uc_match":"2734-fe0f","uc_greedy":"2734","shortnames":[],"category":"symbols"},":eight_spoked_asterisk:":{"uc_base":"2733","uc_output":"2733-fe0f","uc_match":"2733-fe0f","uc_greedy":"2733","shortnames":[],"category":"symbols"},":eject:":{"uc_base":"23cf","uc_output":"23cf-fe0f","uc_match":"23cf-fe0f","uc_greedy":"23cf","shortnames":[":eject_symbol:"],"category":"symbols"},":envelope:":{"uc_base":"2709","uc_output":"2709-fe0f","uc_match":"2709-fe0f","uc_greedy":"2709","shortnames":[],"category":"objects"},":female_sign:":{"uc_base":"2640","uc_output":"2640-fe0f","uc_match":"2640-fe0f","uc_greedy":"2640","shortnames":[],"category":"people"},":ferry:":{"uc_base":"26f4","uc_output":"26f4-fe0f","uc_match":"26f4-fe0f","uc_greedy":"26f4","shortnames":[],"category":"travel"},":fleur-de-lis:":{"uc_base":"269c","uc_output":"269c-fe0f","uc_match":"269c-fe0f","uc_greedy":"269c","shortnames":[],"category":"symbols"},":frowning2:":{"uc_base":"2639","uc_output":"2639-fe0f","uc_match":"2639-fe0f","uc_greedy":"2639","shortnames":[":white_frowning_face:"],"category":"people"},":gear:":{"uc_base":"2699","uc_output":"2699-fe0f","uc_match":"2699-fe0f","uc_greedy":"2699","shortnames":[],"category":"objects"},":hammer_pick:":{"uc_base":"2692","uc_output":"2692-fe0f","uc_match":"2692-fe0f","uc_greedy":"2692","shortnames":[":hammer_and_pick:"],"category":"objects"},":heart:":{"uc_base":"2764","uc_output":"2764-fe0f","uc_match":"2764-fe0f","uc_greedy":"2764","shortnames":[],"category":"symbols"},":heart_exclamation:":{"uc_base":"2763","uc_output":"2763-fe0f","uc_match":"2763-fe0f","uc_greedy":"2763","shortnames":[":heavy_heart_exclamation_mark_ornament:"],"category":"symbols"},":hearts:":{"uc_base":"2665","uc_output":"2665-fe0f","uc_match":"2665-fe0f","uc_greedy":"2665","shortnames":[],"category":"symbols"},":heavy_check_mark:":{"uc_base":"2714","uc_output":"2714-fe0f","uc_match":"2714-fe0f","uc_greedy":"2714","shortnames":[],"category":"symbols"},":heavy_multiplication_x:":{"uc_base":"2716","uc_output":"2716-fe0f","uc_match":"2716-fe0f","uc_greedy":"2716","shortnames":[],"category":"symbols"},":helmet_with_cross:":{"uc_base":"26d1","uc_output":"26d1-fe0f","uc_match":"26d1-fe0f","uc_greedy":"26d1","shortnames":[":helmet_with_white_cross:"],"category":"people"},":hotsprings:":{"uc_base":"2668","uc_output":"2668-fe0f","uc_match":"2668-fe0f","uc_greedy":"2668","shortnames":[],"category":"symbols"},":ice_skate:":{"uc_base":"26f8","uc_output":"26f8-fe0f","uc_match":"26f8-fe0f","uc_greedy":"26f8","shortnames":[],"category":"activity"},":information_source:":{"uc_base":"2139","uc_output":"2139-fe0f","uc_match":"2139-fe0f","uc_greedy":"2139","shortnames":[],"category":"symbols"},":interrobang:":{"uc_base":"2049","uc_output":"2049-fe0f","uc_match":"2049-fe0f","uc_greedy":"2049","shortnames":[],"category":"symbols"},":keyboard:":{"uc_base":"2328","uc_output":"2328-fe0f","uc_match":"2328-fe0f","uc_greedy":"2328","shortnames":[],"category":"objects"},":left_right_arrow:":{"uc_base":"2194","uc_output":"2194-fe0f","uc_match":"2194-fe0f","uc_greedy":"2194","shortnames":[],"category":"symbols"},":leftwards_arrow_with_hook:":{"uc_base":"21a9","uc_output":"21a9-fe0f","uc_match":"21a9-fe0f","uc_greedy":"21a9","shortnames":[],"category":"symbols"},":m:":{"uc_base":"24c2","uc_output":"24c2-fe0f","uc_match":"24c2-fe0f","uc_greedy":"24c2","shortnames":[],"category":"symbols"},":male_sign:":{"uc_base":"2642","uc_output":"2642-fe0f","uc_match":"2642-fe0f","uc_greedy":"2642","shortnames":[],"category":"people"},":medical_symbol:":{"uc_base":"2695","uc_output":"2695-fe0f","uc_match":"2695-fe0f","uc_greedy":"2695","shortnames":[],"category":"people"},":mountain:":{"uc_base":"26f0","uc_output":"26f0-fe0f","uc_match":"26f0-fe0f","uc_greedy":"26f0","shortnames":[],"category":"travel"},":orthodox_cross:":{"uc_base":"2626","uc_output":"2626-fe0f","uc_match":"2626-fe0f","uc_greedy":"2626","shortnames":[],"category":"symbols"},":part_alternation_mark:":{"uc_base":"303d","uc_output":"303d-fe0f","uc_match":"303d-fe0f","uc_greedy":"303d","shortnames":[],"category":"symbols"},":pause_button:":{"uc_base":"23f8","uc_output":"23f8-fe0f","uc_match":"23f8-fe0f","uc_greedy":"23f8","shortnames":[":double_vertical_bar:"],"category":"symbols"},":peace:":{"uc_base":"262e","uc_output":"262e-fe0f","uc_match":"262e-fe0f","uc_greedy":"262e","shortnames":[":peace_symbol:"],"category":"symbols"},":pencil2:":{"uc_base":"270f","uc_output":"270f-fe0f","uc_match":"270f-fe0f","uc_greedy":"270f","shortnames":[],"category":"objects"},":person_bouncing_ball:":{"uc_base":"26f9","uc_output":"26f9-fe0f","uc_match":"26f9-fe0f","uc_greedy":"26f9","shortnames":[":basketball_player:",":person_with_ball:"],"category":"activity"},":pick:":{"uc_base":"26cf","uc_output":"26cf-fe0f","uc_match":"26cf-fe0f","uc_greedy":"26cf","shortnames":[],"category":"objects"},":play_pause:":{"uc_base":"23ef","uc_output":"23ef-fe0f","uc_match":"23ef-fe0f","uc_greedy":"23ef","shortnames":[],"category":"symbols"},":point_up:":{"uc_base":"261d","uc_output":"261d-fe0f","uc_match":"261d-fe0f","uc_greedy":"261d","shortnames":[],"category":"people"},":pound_symbol:":{"uc_base":"0023","uc_output":"0023-fe0f","uc_match":"0023-fe0f","uc_greedy":"0023","shortnames":[],"category":"symbols"},":radioactive:":{"uc_base":"2622","uc_output":"2622-fe0f","uc_match":"2622-fe0f","uc_greedy":"2622","shortnames":[":radioactive_sign:"],"category":"symbols"},":record_button:":{"uc_base":"23fa","uc_output":"23fa-fe0f","uc_match":"23fa-fe0f","uc_greedy":"23fa","shortnames":[],"category":"symbols"},":recycle:":{"uc_base":"267b","uc_output":"267b-fe0f","uc_match":"267b-fe0f","uc_greedy":"267b","shortnames":[],"category":"symbols"},":registered:":{"uc_base":"00ae","uc_output":"00ae-fe0f","uc_match":"00ae-fe0f","uc_greedy":"00ae","shortnames":[],"category":"symbols"},":relaxed:":{"uc_base":"263a","uc_output":"263a-fe0f","uc_match":"263a-fe0f","uc_greedy":"263a","shortnames":[],"category":"people"},":scales:":{"uc_base":"2696","uc_output":"2696-fe0f","uc_match":"2696-fe0f","uc_greedy":"2696","shortnames":[],"category":"objects"},":scissors:":{"uc_base":"2702","uc_output":"2702-fe0f","uc_match":"2702-fe0f","uc_greedy":"2702","shortnames":[],"category":"objects"},":secret:":{"uc_base":"3299","uc_output":"3299-fe0f","uc_match":"3299-fe0f","uc_greedy":"3299","shortnames":[],"category":"symbols"},":shamrock:":{"uc_base":"2618","uc_output":"2618-fe0f","uc_match":"2618-fe0f","uc_greedy":"2618","shortnames":[],"category":"nature"},":shinto_shrine:":{"uc_base":"26e9","uc_output":"26e9-fe0f","uc_match":"26e9-fe0f","uc_greedy":"26e9","shortnames":[],"category":"travel"},":skier:":{"uc_base":"26f7","uc_output":"26f7-fe0f","uc_match":"26f7-fe0f","uc_greedy":"26f7","shortnames":[],"category":"activity"},":skull_crossbones:":{"uc_base":"2620","uc_output":"2620-fe0f","uc_match":"2620-fe0f","uc_greedy":"2620","shortnames":[":skull_and_crossbones:"],"category":"people"},":snowflake:":{"uc_base":"2744","uc_output":"2744-fe0f","uc_match":"2744-fe0f","uc_greedy":"2744","shortnames":[],"category":"nature"},":snowman2:":{"uc_base":"2603","uc_output":"2603-fe0f","uc_match":"2603-fe0f","uc_greedy":"2603","shortnames":[],"category":"nature"},":spades:":{"uc_base":"2660","uc_output":"2660-fe0f","uc_match":"2660-fe0f","uc_greedy":"2660","shortnames":[],"category":"symbols"},":sparkle:":{"uc_base":"2747","uc_output":"2747-fe0f","uc_match":"2747-fe0f","uc_greedy":"2747","shortnames":[],"category":"symbols"},":star_and_crescent:":{"uc_base":"262a","uc_output":"262a-fe0f","uc_match":"262a-fe0f","uc_greedy":"262a","shortnames":[],"category":"symbols"},":star_of_david:":{"uc_base":"2721","uc_output":"2721-fe0f","uc_match":"2721-fe0f","uc_greedy":"2721","shortnames":[],"category":"symbols"},":stop_button:":{"uc_base":"23f9","uc_output":"23f9-fe0f","uc_match":"23f9-fe0f","uc_greedy":"23f9","shortnames":[],"category":"symbols"},":stopwatch:":{"uc_base":"23f1","uc_output":"23f1-fe0f","uc_match":"23f1-fe0f","uc_greedy":"23f1","shortnames":[],"category":"objects"},":sunny:":{"uc_base":"2600","uc_output":"2600-fe0f","uc_match":"2600-fe0f","uc_greedy":"2600","shortnames":[],"category":"nature"},":telephone:":{"uc_base":"260e","uc_output":"260e-fe0f","uc_match":"260e-fe0f","uc_greedy":"260e","shortnames":[],"category":"objects"},":thunder_cloud_rain:":{"uc_base":"26c8","uc_output":"26c8-fe0f","uc_match":"26c8-fe0f","uc_greedy":"26c8","shortnames":[":thunder_cloud_and_rain:"],"category":"nature"},":timer:":{"uc_base":"23f2","uc_output":"23f2-fe0f","uc_match":"23f2-fe0f","uc_greedy":"23f2","shortnames":[":timer_clock:"],"category":"objects"},":tm:":{"uc_base":"2122","uc_output":"2122-fe0f","uc_match":"2122-fe0f","uc_greedy":"2122","shortnames":[],"category":"symbols"},":track_next:":{"uc_base":"23ed","uc_output":"23ed-fe0f","uc_match":"23ed-fe0f","uc_greedy":"23ed","shortnames":[":next_track:"],"category":"symbols"},":track_previous:":{"uc_base":"23ee","uc_output":"23ee-fe0f","uc_match":"23ee-fe0f","uc_greedy":"23ee","shortnames":[":previous_track:"],"category":"symbols"},":umbrella2:":{"uc_base":"2602","uc_output":"2602-fe0f","uc_match":"2602-fe0f","uc_greedy":"2602","shortnames":[],"category":"people"},":urn:":{"uc_base":"26b1","uc_output":"26b1-fe0f","uc_match":"26b1-fe0f","uc_greedy":"26b1","shortnames":[":funeral_urn:"],"category":"objects"},":v:":{"uc_base":"270c","uc_output":"270c-fe0f","uc_match":"270c-fe0f","uc_greedy":"270c","shortnames":[],"category":"people"},":warning:":{"uc_base":"26a0","uc_output":"26a0-fe0f","uc_match":"26a0-fe0f","uc_greedy":"26a0","shortnames":[],"category":"symbols"},":wavy_dash:":{"uc_base":"3030","uc_output":"3030-fe0f","uc_match":"3030-fe0f","uc_greedy":"3030","shortnames":[],"category":"symbols"},":wheel_of_dharma:":{"uc_base":"2638","uc_output":"2638-fe0f","uc_match":"2638-fe0f","uc_greedy":"2638","shortnames":[],"category":"symbols"},":white_medium_square:":{"uc_base":"25fb","uc_output":"25fb-fe0f","uc_match":"25fb-fe0f","uc_greedy":"25fb","shortnames":[],"category":"symbols"},":white_small_square:":{"uc_base":"25ab","uc_output":"25ab-fe0f","uc_match":"25ab-fe0f","uc_greedy":"25ab","shortnames":[],"category":"symbols"},":writing_hand:":{"uc_base":"270d","uc_output":"270d-fe0f","uc_match":"270d-fe0f","uc_greedy":"270d","shortnames":[],"category":"people"},":yin_yang:":{"uc_base":"262f","uc_output":"262f-fe0f","uc_match":"262f-fe0f","uc_greedy":"262f","shortnames":[],"category":"symbols"},":100:":{"uc_base":"1f4af","uc_output":"1f4af","uc_match":"1f4af","uc_greedy":"1f4af","shortnames":[],"category":"symbols"},":1234:":{"uc_base":"1f522","uc_output":"1f522","uc_match":"1f522","uc_greedy":"1f522","shortnames":[],"category":"symbols"},":8ball:":{"uc_base":"1f3b1","uc_output":"1f3b1","uc_match":"1f3b1","uc_greedy":"1f3b1","shortnames":[],"category":"activity"},":ab:":{"uc_base":"1f18e","uc_output":"1f18e","uc_match":"1f18e","uc_greedy":"1f18e","shortnames":[],"category":"symbols"},":abc:":{"uc_base":"1f524","uc_output":"1f524","uc_match":"1f524","uc_greedy":"1f524","shortnames":[],"category":"symbols"},":abcd:":{"uc_base":"1f521","uc_output":"1f521","uc_match":"1f521","uc_greedy":"1f521","shortnames":[],"category":"symbols"},":accept:":{"uc_base":"1f251","uc_output":"1f251","uc_match":"1f251","uc_greedy":"1f251","shortnames":[],"category":"symbols"},":adult:":{"uc_base":"1f9d1","uc_output":"1f9d1","uc_match":"1f9d1","uc_greedy":"1f9d1","shortnames":[],"category":"people"},":aerial_tramway:":{"uc_base":"1f6a1","uc_output":"1f6a1","uc_match":"1f6a1","uc_greedy":"1f6a1","shortnames":[],"category":"travel"},":airplane_arriving:":{"uc_base":"1f6ec","uc_output":"1f6ec","uc_match":"1f6ec","uc_greedy":"1f6ec","shortnames":[],"category":"travel"},":airplane_departure:":{"uc_base":"1f6eb","uc_output":"1f6eb","uc_match":"1f6eb","uc_greedy":"1f6eb","shortnames":[],"category":"travel"},":alien:":{"uc_base":"1f47d","uc_output":"1f47d","uc_match":"1f47d","uc_greedy":"1f47d","shortnames":[],"category":"people"},":ambulance:":{"uc_base":"1f691","uc_output":"1f691","uc_match":"1f691","uc_greedy":"1f691","shortnames":[],"category":"travel"},":amphora:":{"uc_base":"1f3fa","uc_output":"1f3fa","uc_match":"1f3fa","uc_greedy":"1f3fa","shortnames":[],"category":"objects"},":angel:":{"uc_base":"1f47c","uc_output":"1f47c","uc_match":"1f47c","uc_greedy":"1f47c","shortnames":[],"category":"people"},":anger:":{"uc_base":"1f4a2","uc_output":"1f4a2","uc_match":"1f4a2","uc_greedy":"1f4a2","shortnames":[],"category":"symbols"},":angry:":{"uc_base":"1f620","uc_output":"1f620","uc_match":"1f620","uc_greedy":"1f620","shortnames":[],"category":"people"},":anguished:":{"uc_base":"1f627","uc_output":"1f627","uc_match":"1f627","uc_greedy":"1f627","shortnames":[],"category":"people"},":ant:":{"uc_base":"1f41c","uc_output":"1f41c","uc_match":"1f41c","uc_greedy":"1f41c","shortnames":[],"category":"nature"},":apple:":{"uc_base":"1f34e","uc_output":"1f34e","uc_match":"1f34e","uc_greedy":"1f34e","shortnames":[],"category":"food"},":arrow_down_small:":{"uc_base":"1f53d","uc_output":"1f53d","uc_match":"1f53d","uc_greedy":"1f53d","shortnames":[],"category":"symbols"},":arrow_up_small:":{"uc_base":"1f53c","uc_output":"1f53c","uc_match":"1f53c","uc_greedy":"1f53c","shortnames":[],"category":"symbols"},":arrows_clockwise:":{"uc_base":"1f503","uc_output":"1f503","uc_match":"1f503","uc_greedy":"1f503","shortnames":[],"category":"symbols"},":arrows_counterclockwise:":{"uc_base":"1f504","uc_output":"1f504","uc_match":"1f504","uc_greedy":"1f504","shortnames":[],"category":"symbols"},":art:":{"uc_base":"1f3a8","uc_output":"1f3a8","uc_match":"1f3a8","uc_greedy":"1f3a8","shortnames":[],"category":"activity"},":articulated_lorry:":{"uc_base":"1f69b","uc_output":"1f69b","uc_match":"1f69b","uc_greedy":"1f69b","shortnames":[],"category":"travel"},":astonished:":{"uc_base":"1f632","uc_output":"1f632","uc_match":"1f632","uc_greedy":"1f632","shortnames":[],"category":"people"},":athletic_shoe:":{"uc_base":"1f45f","uc_output":"1f45f","uc_match":"1f45f","uc_greedy":"1f45f","shortnames":[],"category":"people"},":atm:":{"uc_base":"1f3e7","uc_output":"1f3e7","uc_match":"1f3e7","uc_greedy":"1f3e7","shortnames":[],"category":"symbols"},":avocado:":{"uc_base":"1f951","uc_output":"1f951","uc_match":"1f951","uc_greedy":"1f951","shortnames":[],"category":"food"},":baby:":{"uc_base":"1f476","uc_output":"1f476","uc_match":"1f476","uc_greedy":"1f476","shortnames":[],"category":"people"},":baby_bottle:":{"uc_base":"1f37c","uc_output":"1f37c","uc_match":"1f37c","uc_greedy":"1f37c","shortnames":[],"category":"food"},":baby_chick:":{"uc_base":"1f424","uc_output":"1f424","uc_match":"1f424","uc_greedy":"1f424","shortnames":[],"category":"nature"},":baby_symbol:":{"uc_base":"1f6bc","uc_output":"1f6bc","uc_match":"1f6bc","uc_greedy":"1f6bc","shortnames":[],"category":"symbols"},":back:":{"uc_base":"1f519","uc_output":"1f519","uc_match":"1f519","uc_greedy":"1f519","shortnames":[],"category":"symbols"},":bacon:":{"uc_base":"1f953","uc_output":"1f953","uc_match":"1f953","uc_greedy":"1f953","shortnames":[],"category":"food"},":badminton:":{"uc_base":"1f3f8","uc_output":"1f3f8","uc_match":"1f3f8","uc_greedy":"1f3f8","shortnames":[],"category":"activity"},":baggage_claim:":{"uc_base":"1f6c4","uc_output":"1f6c4","uc_match":"1f6c4","uc_greedy":"1f6c4","shortnames":[],"category":"symbols"},":balloon:":{"uc_base":"1f388","uc_output":"1f388","uc_match":"1f388","uc_greedy":"1f388","shortnames":[],"category":"objects"},":bamboo:":{"uc_base":"1f38d","uc_output":"1f38d","uc_match":"1f38d","uc_greedy":"1f38d","shortnames":[],"category":"nature"},":banana:":{"uc_base":"1f34c","uc_output":"1f34c","uc_match":"1f34c","uc_greedy":"1f34c","shortnames":[],"category":"food"},":bank:":{"uc_base":"1f3e6","uc_output":"1f3e6","uc_match":"1f3e6","uc_greedy":"1f3e6","shortnames":[],"category":"travel"},":bar_chart:":{"uc_base":"1f4ca","uc_output":"1f4ca","uc_match":"1f4ca","uc_greedy":"1f4ca","shortnames":[],"category":"objects"},":barber:":{"uc_base":"1f488","uc_output":"1f488","uc_match":"1f488","uc_greedy":"1f488","shortnames":[],"category":"objects"},":basketball:":{"uc_base":"1f3c0","uc_output":"1f3c0","uc_match":"1f3c0","uc_greedy":"1f3c0","shortnames":[],"category":"activity"},":bat:":{"uc_base":"1f987","uc_output":"1f987","uc_match":"1f987","uc_greedy":"1f987","shortnames":[],"category":"nature"},":bath:":{"uc_base":"1f6c0","uc_output":"1f6c0","uc_match":"1f6c0","uc_greedy":"1f6c0","shortnames":[],"category":"objects"},":bathtub:":{"uc_base":"1f6c1","uc_output":"1f6c1","uc_match":"1f6c1","uc_greedy":"1f6c1","shortnames":[],"category":"objects"},":battery:":{"uc_base":"1f50b","uc_output":"1f50b","uc_match":"1f50b","uc_greedy":"1f50b","shortnames":[],"category":"objects"},":bear:":{"uc_base":"1f43b","uc_output":"1f43b","uc_match":"1f43b","uc_greedy":"1f43b","shortnames":[],"category":"nature"},":bearded_person:":{"uc_base":"1f9d4","uc_output":"1f9d4","uc_match":"1f9d4","uc_greedy":"1f9d4","shortnames":[],"category":"people"},":bee:":{"uc_base":"1f41d","uc_output":"1f41d","uc_match":"1f41d","uc_greedy":"1f41d","shortnames":[],"category":"nature"},":beer:":{"uc_base":"1f37a","uc_output":"1f37a","uc_match":"1f37a","uc_greedy":"1f37a","shortnames":[],"category":"food"},":beers:":{"uc_base":"1f37b","uc_output":"1f37b","uc_match":"1f37b","uc_greedy":"1f37b","shortnames":[],"category":"food"},":beetle:":{"uc_base":"1f41e","uc_output":"1f41e","uc_match":"1f41e","uc_greedy":"1f41e","shortnames":[],"category":"nature"},":beginner:":{"uc_base":"1f530","uc_output":"1f530","uc_match":"1f530","uc_greedy":"1f530","shortnames":[],"category":"symbols"},":bell:":{"uc_base":"1f514","uc_output":"1f514","uc_match":"1f514","uc_greedy":"1f514","shortnames":[],"category":"symbols"},":bento:":{"uc_base":"1f371","uc_output":"1f371","uc_match":"1f371","uc_greedy":"1f371","shortnames":[],"category":"food"},":bike:":{"uc_base":"1f6b2","uc_output":"1f6b2","uc_match":"1f6b2","uc_greedy":"1f6b2","shortnames":[],"category":"travel"},":bikini:":{"uc_base":"1f459","uc_output":"1f459","uc_match":"1f459","uc_greedy":"1f459","shortnames":[],"category":"people"},":billed_cap:":{"uc_base":"1f9e2","uc_output":"1f9e2","uc_match":"1f9e2","uc_greedy":"1f9e2","shortnames":[],"category":"people"},":bird:":{"uc_base":"1f426","uc_output":"1f426","uc_match":"1f426","uc_greedy":"1f426","shortnames":[],"category":"nature"},":birthday:":{"uc_base":"1f382","uc_output":"1f382","uc_match":"1f382","uc_greedy":"1f382","shortnames":[],"category":"food"},":black_heart:":{"uc_base":"1f5a4","uc_output":"1f5a4","uc_match":"1f5a4","uc_greedy":"1f5a4","shortnames":[],"category":"symbols"},":black_joker:":{"uc_base":"1f0cf","uc_output":"1f0cf","uc_match":"1f0cf","uc_greedy":"1f0cf","shortnames":[],"category":"symbols"},":black_square_button:":{"uc_base":"1f532","uc_output":"1f532","uc_match":"1f532","uc_greedy":"1f532","shortnames":[],"category":"symbols"},":blond_haired_person:":{"uc_base":"1f471","uc_output":"1f471","uc_match":"1f471","uc_greedy":"1f471","shortnames":[":person_with_blond_hair:"],"category":"people"},":blossom:":{"uc_base":"1f33c","uc_output":"1f33c","uc_match":"1f33c","uc_greedy":"1f33c","shortnames":[],"category":"nature"},":blowfish:":{"uc_base":"1f421","uc_output":"1f421","uc_match":"1f421","uc_greedy":"1f421","shortnames":[],"category":"nature"},":blue_book:":{"uc_base":"1f4d8","uc_output":"1f4d8","uc_match":"1f4d8","uc_greedy":"1f4d8","shortnames":[],"category":"objects"},":blue_car:":{"uc_base":"1f699","uc_output":"1f699","uc_match":"1f699","uc_greedy":"1f699","shortnames":[],"category":"travel"},":blue_circle:":{"uc_base":"1f535","uc_output":"1f535","uc_match":"1f535","uc_greedy":"1f535","shortnames":[],"category":"symbols"},":blue_heart:":{"uc_base":"1f499","uc_output":"1f499","uc_match":"1f499","uc_greedy":"1f499","shortnames":[],"category":"symbols"},":blush:":{"uc_base":"1f60a","uc_output":"1f60a","uc_match":"1f60a","uc_greedy":"1f60a","shortnames":[],"category":"people"},":boar:":{"uc_base":"1f417","uc_output":"1f417","uc_match":"1f417","uc_greedy":"1f417","shortnames":[],"category":"nature"},":bomb:":{"uc_base":"1f4a3","uc_output":"1f4a3","uc_match":"1f4a3","uc_greedy":"1f4a3","shortnames":[],"category":"objects"},":book:":{"uc_base":"1f4d6","uc_output":"1f4d6","uc_match":"1f4d6","uc_greedy":"1f4d6","shortnames":[],"category":"objects"},":bookmark:":{"uc_base":"1f516","uc_output":"1f516","uc_match":"1f516","uc_greedy":"1f516","shortnames":[],"category":"objects"},":bookmark_tabs:":{"uc_base":"1f4d1","uc_output":"1f4d1","uc_match":"1f4d1","uc_greedy":"1f4d1","shortnames":[],"category":"objects"},":books:":{"uc_base":"1f4da","uc_output":"1f4da","uc_match":"1f4da","uc_greedy":"1f4da","shortnames":[],"category":"objects"},":boom:":{"uc_base":"1f4a5","uc_output":"1f4a5","uc_match":"1f4a5","uc_greedy":"1f4a5","shortnames":[],"category":"nature"},":boot:":{"uc_base":"1f462","uc_output":"1f462","uc_match":"1f462","uc_greedy":"1f462","shortnames":[],"category":"people"},":bouquet:":{"uc_base":"1f490","uc_output":"1f490","uc_match":"1f490","uc_greedy":"1f490","shortnames":[],"category":"nature"},":bow_and_arrow:":{"uc_base":"1f3f9","uc_output":"1f3f9","uc_match":"1f3f9","uc_greedy":"1f3f9","shortnames":[":archery:"],"category":"activity"},":bowl_with_spoon:":{"uc_base":"1f963","uc_output":"1f963","uc_match":"1f963","uc_greedy":"1f963","shortnames":[],"category":"food"},":bowling:":{"uc_base":"1f3b3","uc_output":"1f3b3","uc_match":"1f3b3","uc_greedy":"1f3b3","shortnames":[],"category":"activity"},":boxing_glove:":{"uc_base":"1f94a","uc_output":"1f94a","uc_match":"1f94a","uc_greedy":"1f94a","shortnames":[":boxing_gloves:"],"category":"activity"},":boy:":{"uc_base":"1f466","uc_output":"1f466","uc_match":"1f466","uc_greedy":"1f466","shortnames":[],"category":"people"},":brain:":{"uc_base":"1f9e0","uc_output":"1f9e0","uc_match":"1f9e0","uc_greedy":"1f9e0","shortnames":[],"category":"people"},":bread:":{"uc_base":"1f35e","uc_output":"1f35e","uc_match":"1f35e","uc_greedy":"1f35e","shortnames":[],"category":"food"},":breast_feeding:":{"uc_base":"1f931","uc_output":"1f931","uc_match":"1f931","uc_greedy":"1f931","shortnames":[],"category":"activity"},":bride_with_veil:":{"uc_base":"1f470","uc_output":"1f470","uc_match":"1f470","uc_greedy":"1f470","shortnames":[],"category":"people"},":bridge_at_night:":{"uc_base":"1f309","uc_output":"1f309","uc_match":"1f309","uc_greedy":"1f309","shortnames":[],"category":"travel"},":briefcase:":{"uc_base":"1f4bc","uc_output":"1f4bc","uc_match":"1f4bc","uc_greedy":"1f4bc","shortnames":[],"category":"people"},":broccoli:":{"uc_base":"1f966","uc_output":"1f966","uc_match":"1f966","uc_greedy":"1f966","shortnames":[],"category":"food"},":broken_heart:":{"uc_base":"1f494","uc_output":"1f494","uc_match":"1f494","uc_greedy":"1f494","shortnames":[],"category":"symbols"},":bug:":{"uc_base":"1f41b","uc_output":"1f41b","uc_match":"1f41b","uc_greedy":"1f41b","shortnames":[],"category":"nature"},":bulb:":{"uc_base":"1f4a1","uc_output":"1f4a1","uc_match":"1f4a1","uc_greedy":"1f4a1","shortnames":[],"category":"objects"},":bullettrain_front:":{"uc_base":"1f685","uc_output":"1f685","uc_match":"1f685","uc_greedy":"1f685","shortnames":[],"category":"travel"},":bullettrain_side:":{"uc_base":"1f684","uc_output":"1f684","uc_match":"1f684","uc_greedy":"1f684","shortnames":[],"category":"travel"},":burrito:":{"uc_base":"1f32f","uc_output":"1f32f","uc_match":"1f32f","uc_greedy":"1f32f","shortnames":[],"category":"food"},":bus:":{"uc_base":"1f68c","uc_output":"1f68c","uc_match":"1f68c","uc_greedy":"1f68c","shortnames":[],"category":"travel"},":busstop:":{"uc_base":"1f68f","uc_output":"1f68f","uc_match":"1f68f","uc_greedy":"1f68f","shortnames":[],"category":"travel"},":bust_in_silhouette:":{"uc_base":"1f464","uc_output":"1f464","uc_match":"1f464","uc_greedy":"1f464","shortnames":[],"category":"people"},":busts_in_silhouette:":{"uc_base":"1f465","uc_output":"1f465","uc_match":"1f465","uc_greedy":"1f465","shortnames":[],"category":"people"},":butterfly:":{"uc_base":"1f98b","uc_output":"1f98b","uc_match":"1f98b","uc_greedy":"1f98b","shortnames":[],"category":"nature"},":cactus:":{"uc_base":"1f335","uc_output":"1f335","uc_match":"1f335","uc_greedy":"1f335","shortnames":[],"category":"nature"},":cake:":{"uc_base":"1f370","uc_output":"1f370","uc_match":"1f370","uc_greedy":"1f370","shortnames":[],"category":"food"},":calendar:":{"uc_base":"1f4c6","uc_output":"1f4c6","uc_match":"1f4c6","uc_greedy":"1f4c6","shortnames":[],"category":"objects"},":call_me:":{"uc_base":"1f919","uc_output":"1f919","uc_match":"1f919","uc_greedy":"1f919","shortnames":[":call_me_hand:"],"category":"people"},":calling:":{"uc_base":"1f4f2","uc_output":"1f4f2","uc_match":"1f4f2","uc_greedy":"1f4f2","shortnames":[],"category":"objects"},":camel:":{"uc_base":"1f42b","uc_output":"1f42b","uc_match":"1f42b","uc_greedy":"1f42b","shortnames":[],"category":"nature"},":camera:":{"uc_base":"1f4f7","uc_output":"1f4f7","uc_match":"1f4f7","uc_greedy":"1f4f7","shortnames":[],"category":"objects"},":camera_with_flash:":{"uc_base":"1f4f8","uc_output":"1f4f8","uc_match":"1f4f8","uc_greedy":"1f4f8","shortnames":[],"category":"objects"},":candy:":{"uc_base":"1f36c","uc_output":"1f36c","uc_match":"1f36c","uc_greedy":"1f36c","shortnames":[],"category":"food"},":canned_food:":{"uc_base":"1f96b","uc_output":"1f96b","uc_match":"1f96b","uc_greedy":"1f96b","shortnames":[],"category":"food"},":canoe:":{"uc_base":"1f6f6","uc_output":"1f6f6","uc_match":"1f6f6","uc_greedy":"1f6f6","shortnames":[":kayak:"],"category":"travel"},":capital_abcd:":{"uc_base":"1f520","uc_output":"1f520","uc_match":"1f520","uc_greedy":"1f520","shortnames":[],"category":"symbols"},":card_index:":{"uc_base":"1f4c7","uc_output":"1f4c7","uc_match":"1f4c7","uc_greedy":"1f4c7","shortnames":[],"category":"objects"},":carousel_horse:":{"uc_base":"1f3a0","uc_output":"1f3a0","uc_match":"1f3a0","uc_greedy":"1f3a0","shortnames":[],"category":"travel"},":carrot:":{"uc_base":"1f955","uc_output":"1f955","uc_match":"1f955","uc_greedy":"1f955","shortnames":[],"category":"food"},":cat2:":{"uc_base":"1f408","uc_output":"1f408","uc_match":"1f408","uc_greedy":"1f408","shortnames":[],"category":"nature"},":cat:":{"uc_base":"1f431","uc_output":"1f431","uc_match":"1f431","uc_greedy":"1f431","shortnames":[],"category":"nature"},":cd:":{"uc_base":"1f4bf","uc_output":"1f4bf","uc_match":"1f4bf","uc_greedy":"1f4bf","shortnames":[],"category":"objects"},":champagne:":{"uc_base":"1f37e","uc_output":"1f37e","uc_match":"1f37e","uc_greedy":"1f37e","shortnames":[":bottle_with_popping_cork:"],"category":"food"},":champagne_glass:":{"uc_base":"1f942","uc_output":"1f942","uc_match":"1f942","uc_greedy":"1f942","shortnames":[":clinking_glass:"],"category":"food"},":chart:":{"uc_base":"1f4b9","uc_output":"1f4b9","uc_match":"1f4b9","uc_greedy":"1f4b9","shortnames":[],"category":"symbols"},":chart_with_downwards_trend:":{"uc_base":"1f4c9","uc_output":"1f4c9","uc_match":"1f4c9","uc_greedy":"1f4c9","shortnames":[],"category":"objects"},":chart_with_upwards_trend:":{"uc_base":"1f4c8","uc_output":"1f4c8","uc_match":"1f4c8","uc_greedy":"1f4c8","shortnames":[],"category":"objects"},":checkered_flag:":{"uc_base":"1f3c1","uc_output":"1f3c1","uc_match":"1f3c1","uc_greedy":"1f3c1","shortnames":[],"category":"flags"},":cheese:":{"uc_base":"1f9c0","uc_output":"1f9c0","uc_match":"1f9c0","uc_greedy":"1f9c0","shortnames":[":cheese_wedge:"],"category":"food"},":cherries:":{"uc_base":"1f352","uc_output":"1f352","uc_match":"1f352","uc_greedy":"1f352","shortnames":[],"category":"food"},":cherry_blossom:":{"uc_base":"1f338","uc_output":"1f338","uc_match":"1f338","uc_greedy":"1f338","shortnames":[],"category":"nature"},":chestnut:":{"uc_base":"1f330","uc_output":"1f330","uc_match":"1f330","uc_greedy":"1f330","shortnames":[],"category":"food"},":chicken:":{"uc_base":"1f414","uc_output":"1f414","uc_match":"1f414","uc_greedy":"1f414","shortnames":[],"category":"nature"},":child:":{"uc_base":"1f9d2","uc_output":"1f9d2","uc_match":"1f9d2","uc_greedy":"1f9d2","shortnames":[],"category":"people"},":children_crossing:":{"uc_base":"1f6b8","uc_output":"1f6b8","uc_match":"1f6b8","uc_greedy":"1f6b8","shortnames":[],"category":"symbols"},":chocolate_bar:":{"uc_base":"1f36b","uc_output":"1f36b","uc_match":"1f36b","uc_greedy":"1f36b","shortnames":[],"category":"food"},":chopsticks:":{"uc_base":"1f962","uc_output":"1f962","uc_match":"1f962","uc_greedy":"1f962","shortnames":[],"category":"food"},":christmas_tree:":{"uc_base":"1f384","uc_output":"1f384","uc_match":"1f384","uc_greedy":"1f384","shortnames":[],"category":"nature"},":cinema:":{"uc_base":"1f3a6","uc_output":"1f3a6","uc_match":"1f3a6","uc_greedy":"1f3a6","shortnames":[],"category":"symbols"},":circus_tent:":{"uc_base":"1f3aa","uc_output":"1f3aa","uc_match":"1f3aa","uc_greedy":"1f3aa","shortnames":[],"category":"activity"},":city_dusk:":{"uc_base":"1f306","uc_output":"1f306","uc_match":"1f306","uc_greedy":"1f306","shortnames":[],"category":"travel"},":city_sunset:":{"uc_base":"1f307","uc_output":"1f307","uc_match":"1f307","uc_greedy":"1f307","shortnames":[":city_sunrise:"],"category":"travel"},":cl:":{"uc_base":"1f191","uc_output":"1f191","uc_match":"1f191","uc_greedy":"1f191","shortnames":[],"category":"symbols"},":clap:":{"uc_base":"1f44f","uc_output":"1f44f","uc_match":"1f44f","uc_greedy":"1f44f","shortnames":[],"category":"people"},":clapper:":{"uc_base":"1f3ac","uc_output":"1f3ac","uc_match":"1f3ac","uc_greedy":"1f3ac","shortnames":[],"category":"activity"},":clipboard:":{"uc_base":"1f4cb","uc_output":"1f4cb","uc_match":"1f4cb","uc_greedy":"1f4cb","shortnames":[],"category":"objects"},":clock1030:":{"uc_base":"1f565","uc_output":"1f565","uc_match":"1f565","uc_greedy":"1f565","shortnames":[],"category":"symbols"},":clock10:":{"uc_base":"1f559","uc_output":"1f559","uc_match":"1f559","uc_greedy":"1f559","shortnames":[],"category":"symbols"},":clock1130:":{"uc_base":"1f566","uc_output":"1f566","uc_match":"1f566","uc_greedy":"1f566","shortnames":[],"category":"symbols"},":clock11:":{"uc_base":"1f55a","uc_output":"1f55a","uc_match":"1f55a","uc_greedy":"1f55a","shortnames":[],"category":"symbols"},":clock1230:":{"uc_base":"1f567","uc_output":"1f567","uc_match":"1f567","uc_greedy":"1f567","shortnames":[],"category":"symbols"},":clock12:":{"uc_base":"1f55b","uc_output":"1f55b","uc_match":"1f55b","uc_greedy":"1f55b","shortnames":[],"category":"symbols"},":clock130:":{"uc_base":"1f55c","uc_output":"1f55c","uc_match":"1f55c","uc_greedy":"1f55c","shortnames":[],"category":"symbols"},":clock1:":{"uc_base":"1f550","uc_output":"1f550","uc_match":"1f550","uc_greedy":"1f550","shortnames":[],"category":"symbols"},":clock230:":{"uc_base":"1f55d","uc_output":"1f55d","uc_match":"1f55d","uc_greedy":"1f55d","shortnames":[],"category":"symbols"},":clock2:":{"uc_base":"1f551","uc_output":"1f551","uc_match":"1f551","uc_greedy":"1f551","shortnames":[],"category":"symbols"},":clock330:":{"uc_base":"1f55e","uc_output":"1f55e","uc_match":"1f55e","uc_greedy":"1f55e","shortnames":[],"category":"symbols"},":clock3:":{"uc_base":"1f552","uc_output":"1f552","uc_match":"1f552","uc_greedy":"1f552","shortnames":[],"category":"symbols"},":clock430:":{"uc_base":"1f55f","uc_output":"1f55f","uc_match":"1f55f","uc_greedy":"1f55f","shortnames":[],"category":"symbols"},":clock4:":{"uc_base":"1f553","uc_output":"1f553","uc_match":"1f553","uc_greedy":"1f553","shortnames":[],"category":"symbols"},":clock530:":{"uc_base":"1f560","uc_output":"1f560","uc_match":"1f560","uc_greedy":"1f560","shortnames":[],"category":"symbols"},":clock5:":{"uc_base":"1f554","uc_output":"1f554","uc_match":"1f554","uc_greedy":"1f554","shortnames":[],"category":"symbols"},":clock630:":{"uc_base":"1f561","uc_output":"1f561","uc_match":"1f561","uc_greedy":"1f561","shortnames":[],"category":"symbols"},":clock6:":{"uc_base":"1f555","uc_output":"1f555","uc_match":"1f555","uc_greedy":"1f555","shortnames":[],"category":"symbols"},":clock730:":{"uc_base":"1f562","uc_output":"1f562","uc_match":"1f562","uc_greedy":"1f562","shortnames":[],"category":"symbols"},":clock7:":{"uc_base":"1f556","uc_output":"1f556","uc_match":"1f556","uc_greedy":"1f556","shortnames":[],"category":"symbols"},":clock830:":{"uc_base":"1f563","uc_output":"1f563","uc_match":"1f563","uc_greedy":"1f563","shortnames":[],"category":"symbols"},":clock8:":{"uc_base":"1f557","uc_output":"1f557","uc_match":"1f557","uc_greedy":"1f557","shortnames":[],"category":"symbols"},":clock930:":{"uc_base":"1f564","uc_output":"1f564","uc_match":"1f564","uc_greedy":"1f564","shortnames":[],"category":"symbols"},":clock9:":{"uc_base":"1f558","uc_output":"1f558","uc_match":"1f558","uc_greedy":"1f558","shortnames":[],"category":"symbols"},":closed_book:":{"uc_base":"1f4d5","uc_output":"1f4d5","uc_match":"1f4d5","uc_greedy":"1f4d5","shortnames":[],"category":"objects"},":closed_lock_with_key:":{"uc_base":"1f510","uc_output":"1f510","uc_match":"1f510","uc_greedy":"1f510","shortnames":[],"category":"objects"},":closed_umbrella:":{"uc_base":"1f302","uc_output":"1f302","uc_match":"1f302","uc_greedy":"1f302","shortnames":[],"category":"people"},":clown:":{"uc_base":"1f921","uc_output":"1f921","uc_match":"1f921","uc_greedy":"1f921","shortnames":[":clown_face:"],"category":"people"},":coat:":{"uc_base":"1f9e5","uc_output":"1f9e5","uc_match":"1f9e5","uc_greedy":"1f9e5","shortnames":[],"category":"people"},":cocktail:":{"uc_base":"1f378","uc_output":"1f378","uc_match":"1f378","uc_greedy":"1f378","shortnames":[],"category":"food"},":coconut:":{"uc_base":"1f965","uc_output":"1f965","uc_match":"1f965","uc_greedy":"1f965","shortnames":[],"category":"food"},":cold_sweat:":{"uc_base":"1f630","uc_output":"1f630","uc_match":"1f630","uc_greedy":"1f630","shortnames":[],"category":"people"},":computer:":{"uc_base":"1f4bb","uc_output":"1f4bb","uc_match":"1f4bb","uc_greedy":"1f4bb","shortnames":[],"category":"objects"},":confetti_ball:":{"uc_base":"1f38a","uc_output":"1f38a","uc_match":"1f38a","uc_greedy":"1f38a","shortnames":[],"category":"objects"},":confounded:":{"uc_base":"1f616","uc_output":"1f616","uc_match":"1f616","uc_greedy":"1f616","shortnames":[],"category":"people"},":confused:":{"uc_base":"1f615","uc_output":"1f615","uc_match":"1f615","uc_greedy":"1f615","shortnames":[],"category":"people"},":construction:":{"uc_base":"1f6a7","uc_output":"1f6a7","uc_match":"1f6a7","uc_greedy":"1f6a7","shortnames":[],"category":"travel"},":construction_worker:":{"uc_base":"1f477","uc_output":"1f477","uc_match":"1f477","uc_greedy":"1f477","shortnames":[],"category":"people"},":convenience_store:":{"uc_base":"1f3ea","uc_output":"1f3ea","uc_match":"1f3ea","uc_greedy":"1f3ea","shortnames":[],"category":"travel"},":cookie:":{"uc_base":"1f36a","uc_output":"1f36a","uc_match":"1f36a","uc_greedy":"1f36a","shortnames":[],"category":"food"},":cooking:":{"uc_base":"1f373","uc_output":"1f373","uc_match":"1f373","uc_greedy":"1f373","shortnames":[],"category":"food"},":cool:":{"uc_base":"1f192","uc_output":"1f192","uc_match":"1f192","uc_greedy":"1f192","shortnames":[],"category":"symbols"},":corn:":{"uc_base":"1f33d","uc_output":"1f33d","uc_match":"1f33d","uc_greedy":"1f33d","shortnames":[],"category":"food"},":couple:":{"uc_base":"1f46b","uc_output":"1f46b","uc_match":"1f46b","uc_greedy":"1f46b","shortnames":[],"category":"people"},":couple_with_heart:":{"uc_base":"1f491","uc_output":"1f491","uc_match":"1f491","uc_greedy":"1f491","shortnames":[],"category":"people"},":couplekiss:":{"uc_base":"1f48f","uc_output":"1f48f","uc_match":"1f48f","uc_greedy":"1f48f","shortnames":[],"category":"people"},":cow2:":{"uc_base":"1f404","uc_output":"1f404","uc_match":"1f404","uc_greedy":"1f404","shortnames":[],"category":"nature"},":cow:":{"uc_base":"1f42e","uc_output":"1f42e","uc_match":"1f42e","uc_greedy":"1f42e","shortnames":[],"category":"nature"},":cowboy:":{"uc_base":"1f920","uc_output":"1f920","uc_match":"1f920","uc_greedy":"1f920","shortnames":[":face_with_cowboy_hat:"],"category":"people"},":crab:":{"uc_base":"1f980","uc_output":"1f980","uc_match":"1f980","uc_greedy":"1f980","shortnames":[],"category":"nature"},":crazy_face:":{"uc_base":"1f92a","uc_output":"1f92a","uc_match":"1f92a","uc_greedy":"1f92a","shortnames":[],"category":"people"},":credit_card:":{"uc_base":"1f4b3","uc_output":"1f4b3","uc_match":"1f4b3","uc_greedy":"1f4b3","shortnames":[],"category":"objects"},":crescent_moon:":{"uc_base":"1f319","uc_output":"1f319","uc_match":"1f319","uc_greedy":"1f319","shortnames":[],"category":"nature"},":cricket:":{"uc_base":"1f997","uc_output":"1f997","uc_match":"1f997","uc_greedy":"1f997","shortnames":[],"category":"nature"},":cricket_game:":{"uc_base":"1f3cf","uc_output":"1f3cf","uc_match":"1f3cf","uc_greedy":"1f3cf","shortnames":[":cricket_bat_ball:"],"category":"activity"},":crocodile:":{"uc_base":"1f40a","uc_output":"1f40a","uc_match":"1f40a","uc_greedy":"1f40a","shortnames":[],"category":"nature"},":croissant:":{"uc_base":"1f950","uc_output":"1f950","uc_match":"1f950","uc_greedy":"1f950","shortnames":[],"category":"food"},":crossed_flags:":{"uc_base":"1f38c","uc_output":"1f38c","uc_match":"1f38c","uc_greedy":"1f38c","shortnames":[],"category":"flags"},":crown:":{"uc_base":"1f451","uc_output":"1f451","uc_match":"1f451","uc_greedy":"1f451","shortnames":[],"category":"people"},":cry:":{"uc_base":"1f622","uc_output":"1f622","uc_match":"1f622","uc_greedy":"1f622","shortnames":[],"category":"people"},":crying_cat_face:":{"uc_base":"1f63f","uc_output":"1f63f","uc_match":"1f63f","uc_greedy":"1f63f","shortnames":[],"category":"people"},":crystal_ball:":{"uc_base":"1f52e","uc_output":"1f52e","uc_match":"1f52e","uc_greedy":"1f52e","shortnames":[],"category":"objects"},":cucumber:":{"uc_base":"1f952","uc_output":"1f952","uc_match":"1f952","uc_greedy":"1f952","shortnames":[],"category":"food"},":cup_with_straw:":{"uc_base":"1f964","uc_output":"1f964","uc_match":"1f964","uc_greedy":"1f964","shortnames":[],"category":"food"},":cupid:":{"uc_base":"1f498","uc_output":"1f498","uc_match":"1f498","uc_greedy":"1f498","shortnames":[],"category":"symbols"},":curling_stone:":{"uc_base":"1f94c","uc_output":"1f94c","uc_match":"1f94c","uc_greedy":"1f94c","shortnames":[],"category":"activity"},":currency_exchange:":{"uc_base":"1f4b1","uc_output":"1f4b1","uc_match":"1f4b1","uc_greedy":"1f4b1","shortnames":[],"category":"symbols"},":curry:":{"uc_base":"1f35b","uc_output":"1f35b","uc_match":"1f35b","uc_greedy":"1f35b","shortnames":[],"category":"food"},":custard:":{"uc_base":"1f36e","uc_output":"1f36e","uc_match":"1f36e","uc_greedy":"1f36e","shortnames":[":pudding:",":flan:"],"category":"food"},":customs:":{"uc_base":"1f6c3","uc_output":"1f6c3","uc_match":"1f6c3","uc_greedy":"1f6c3","shortnames":[],"category":"symbols"},":cut_of_meat:":{"uc_base":"1f969","uc_output":"1f969","uc_match":"1f969","uc_greedy":"1f969","shortnames":[],"category":"food"},":cyclone:":{"uc_base":"1f300","uc_output":"1f300","uc_match":"1f300","uc_greedy":"1f300","shortnames":[],"category":"symbols"},":dancer:":{"uc_base":"1f483","uc_output":"1f483","uc_match":"1f483","uc_greedy":"1f483","shortnames":[],"category":"people"},":dango:":{"uc_base":"1f361","uc_output":"1f361","uc_match":"1f361","uc_greedy":"1f361","shortnames":[],"category":"food"},":dart:":{"uc_base":"1f3af","uc_output":"1f3af","uc_match":"1f3af","uc_greedy":"1f3af","shortnames":[],"category":"activity"},":dash:":{"uc_base":"1f4a8","uc_output":"1f4a8","uc_match":"1f4a8","uc_greedy":"1f4a8","shortnames":[],"category":"nature"},":date:":{"uc_base":"1f4c5","uc_output":"1f4c5","uc_match":"1f4c5","uc_greedy":"1f4c5","shortnames":[],"category":"objects"},":deciduous_tree:":{"uc_base":"1f333","uc_output":"1f333","uc_match":"1f333","uc_greedy":"1f333","shortnames":[],"category":"nature"},":deer:":{"uc_base":"1f98c","uc_output":"1f98c","uc_match":"1f98c","uc_greedy":"1f98c","shortnames":[],"category":"nature"},":department_store:":{"uc_base":"1f3ec","uc_output":"1f3ec","uc_match":"1f3ec","uc_greedy":"1f3ec","shortnames":[],"category":"travel"},":diamond_shape_with_a_dot_inside:":{"uc_base":"1f4a0","uc_output":"1f4a0","uc_match":"1f4a0","uc_greedy":"1f4a0","shortnames":[],"category":"symbols"},":disappointed:":{"uc_base":"1f61e","uc_output":"1f61e","uc_match":"1f61e","uc_greedy":"1f61e","shortnames":[],"category":"people"},":disappointed_relieved:":{"uc_base":"1f625","uc_output":"1f625","uc_match":"1f625","uc_greedy":"1f625","shortnames":[],"category":"people"},":dizzy:":{"uc_base":"1f4ab","uc_output":"1f4ab","uc_match":"1f4ab","uc_greedy":"1f4ab","shortnames":[],"category":"nature"},":dizzy_face:":{"uc_base":"1f635","uc_output":"1f635","uc_match":"1f635","uc_greedy":"1f635","shortnames":[],"category":"people"},":do_not_litter:":{"uc_base":"1f6af","uc_output":"1f6af","uc_match":"1f6af","uc_greedy":"1f6af","shortnames":[],"category":"symbols"},":dog2:":{"uc_base":"1f415","uc_output":"1f415","uc_match":"1f415","uc_greedy":"1f415","shortnames":[],"category":"nature"},":dog:":{"uc_base":"1f436","uc_output":"1f436","uc_match":"1f436","uc_greedy":"1f436","shortnames":[],"category":"nature"},":dollar:":{"uc_base":"1f4b5","uc_output":"1f4b5","uc_match":"1f4b5","uc_greedy":"1f4b5","shortnames":[],"category":"objects"},":dolls:":{"uc_base":"1f38e","uc_output":"1f38e","uc_match":"1f38e","uc_greedy":"1f38e","shortnames":[],"category":"objects"},":dolphin:":{"uc_base":"1f42c","uc_output":"1f42c","uc_match":"1f42c","uc_greedy":"1f42c","shortnames":[],"category":"nature"},":door:":{"uc_base":"1f6aa","uc_output":"1f6aa","uc_match":"1f6aa","uc_greedy":"1f6aa","shortnames":[],"category":"objects"},":doughnut:":{"uc_base":"1f369","uc_output":"1f369","uc_match":"1f369","uc_greedy":"1f369","shortnames":[],"category":"food"},":dragon:":{"uc_base":"1f409","uc_output":"1f409","uc_match":"1f409","uc_greedy":"1f409","shortnames":[],"category":"nature"},":dragon_face:":{"uc_base":"1f432","uc_output":"1f432","uc_match":"1f432","uc_greedy":"1f432","shortnames":[],"category":"nature"},":dress:":{"uc_base":"1f457","uc_output":"1f457","uc_match":"1f457","uc_greedy":"1f457","shortnames":[],"category":"people"},":dromedary_camel:":{"uc_base":"1f42a","uc_output":"1f42a","uc_match":"1f42a","uc_greedy":"1f42a","shortnames":[],"category":"nature"},":drooling_face:":{"uc_base":"1f924","uc_output":"1f924","uc_match":"1f924","uc_greedy":"1f924","shortnames":[":drool:"],"category":"people"},":droplet:":{"uc_base":"1f4a7","uc_output":"1f4a7","uc_match":"1f4a7","uc_greedy":"1f4a7","shortnames":[],"category":"nature"},":drum:":{"uc_base":"1f941","uc_output":"1f941","uc_match":"1f941","uc_greedy":"1f941","shortnames":[":drum_with_drumsticks:"],"category":"activity"},":duck:":{"uc_base":"1f986","uc_output":"1f986","uc_match":"1f986","uc_greedy":"1f986","shortnames":[],"category":"nature"},":dumpling:":{"uc_base":"1f95f","uc_output":"1f95f","uc_match":"1f95f","uc_greedy":"1f95f","shortnames":[],"category":"food"},":dvd:":{"uc_base":"1f4c0","uc_output":"1f4c0","uc_match":"1f4c0","uc_greedy":"1f4c0","shortnames":[],"category":"objects"},":e-mail:":{"uc_base":"1f4e7","uc_output":"1f4e7","uc_match":"1f4e7","uc_greedy":"1f4e7","shortnames":[":email:"],"category":"objects"},":eagle:":{"uc_base":"1f985","uc_output":"1f985","uc_match":"1f985","uc_greedy":"1f985","shortnames":[],"category":"nature"},":ear:":{"uc_base":"1f442","uc_output":"1f442","uc_match":"1f442","uc_greedy":"1f442","shortnames":[],"category":"people"},":ear_of_rice:":{"uc_base":"1f33e","uc_output":"1f33e","uc_match":"1f33e","uc_greedy":"1f33e","shortnames":[],"category":"nature"},":earth_africa:":{"uc_base":"1f30d","uc_output":"1f30d","uc_match":"1f30d","uc_greedy":"1f30d","shortnames":[],"category":"nature"},":earth_americas:":{"uc_base":"1f30e","uc_output":"1f30e","uc_match":"1f30e","uc_greedy":"1f30e","shortnames":[],"category":"nature"},":earth_asia:":{"uc_base":"1f30f","uc_output":"1f30f","uc_match":"1f30f","uc_greedy":"1f30f","shortnames":[],"category":"nature"},":egg:":{"uc_base":"1f95a","uc_output":"1f95a","uc_match":"1f95a","uc_greedy":"1f95a","shortnames":[],"category":"food"},":eggplant:":{"uc_base":"1f346","uc_output":"1f346","uc_match":"1f346","uc_greedy":"1f346","shortnames":[],"category":"food"},":electric_plug:":{"uc_base":"1f50c","uc_output":"1f50c","uc_match":"1f50c","uc_greedy":"1f50c","shortnames":[],"category":"objects"},":elephant:":{"uc_base":"1f418","uc_output":"1f418","uc_match":"1f418","uc_greedy":"1f418","shortnames":[],"category":"nature"},":elf:":{"uc_base":"1f9dd","uc_output":"1f9dd","uc_match":"1f9dd","uc_greedy":"1f9dd","shortnames":[],"category":"people"},":end:":{"uc_base":"1f51a","uc_output":"1f51a","uc_match":"1f51a","uc_greedy":"1f51a","shortnames":[],"category":"symbols"},":envelope_with_arrow:":{"uc_base":"1f4e9","uc_output":"1f4e9","uc_match":"1f4e9","uc_greedy":"1f4e9","shortnames":[],"category":"objects"},":euro:":{"uc_base":"1f4b6","uc_output":"1f4b6","uc_match":"1f4b6","uc_greedy":"1f4b6","shortnames":[],"category":"objects"},":european_castle:":{"uc_base":"1f3f0","uc_output":"1f3f0","uc_match":"1f3f0","uc_greedy":"1f3f0","shortnames":[],"category":"travel"},":european_post_office:":{"uc_base":"1f3e4","uc_output":"1f3e4","uc_match":"1f3e4","uc_greedy":"1f3e4","shortnames":[],"category":"travel"},":evergreen_tree:":{"uc_base":"1f332","uc_output":"1f332","uc_match":"1f332","uc_greedy":"1f332","shortnames":[],"category":"nature"},":exploding_head:":{"uc_base":"1f92f","uc_output":"1f92f","uc_match":"1f92f","uc_greedy":"1f92f","shortnames":[],"category":"people"},":expressionless:":{"uc_base":"1f611","uc_output":"1f611","uc_match":"1f611","uc_greedy":"1f611","shortnames":[],"category":"people"},":eyeglasses:":{"uc_base":"1f453","uc_output":"1f453","uc_match":"1f453","uc_greedy":"1f453","shortnames":[],"category":"people"},":eyes:":{"uc_base":"1f440","uc_output":"1f440","uc_match":"1f440","uc_greedy":"1f440","shortnames":[],"category":"people"},":face_vomiting:":{"uc_base":"1f92e","uc_output":"1f92e","uc_match":"1f92e","uc_greedy":"1f92e","shortnames":[],"category":"people"},":face_with_hand_over_mouth:":{"uc_base":"1f92d","uc_output":"1f92d","uc_match":"1f92d","uc_greedy":"1f92d","shortnames":[],"category":"people"},":face_with_monocle:":{"uc_base":"1f9d0","uc_output":"1f9d0","uc_match":"1f9d0","uc_greedy":"1f9d0","shortnames":[],"category":"people"},":face_with_raised_eyebrow:":{"uc_base":"1f928","uc_output":"1f928","uc_match":"1f928","uc_greedy":"1f928","shortnames":[],"category":"people"},":face_with_symbols_over_mouth:":{"uc_base":"1f92c","uc_output":"1f92c","uc_match":"1f92c","uc_greedy":"1f92c","shortnames":[],"category":"people"},":factory:":{"uc_base":"1f3ed","uc_output":"1f3ed","uc_match":"1f3ed","uc_greedy":"1f3ed","shortnames":[],"category":"travel"},":fairy:":{"uc_base":"1f9da","uc_output":"1f9da","uc_match":"1f9da","uc_greedy":"1f9da","shortnames":[],"category":"people"},":fallen_leaf:":{"uc_base":"1f342","uc_output":"1f342","uc_match":"1f342","uc_greedy":"1f342","shortnames":[],"category":"nature"},":family:":{"uc_base":"1f46a","uc_output":"1f46a","uc_match":"1f46a","uc_greedy":"1f46a","shortnames":[],"category":"people"},":fax:":{"uc_base":"1f4e0","uc_output":"1f4e0","uc_match":"1f4e0","uc_greedy":"1f4e0","shortnames":[],"category":"objects"},":fearful:":{"uc_base":"1f628","uc_output":"1f628","uc_match":"1f628","uc_greedy":"1f628","shortnames":[],"category":"people"},":feet:":{"uc_base":"1f43e","uc_output":"1f43e","uc_match":"1f43e","uc_greedy":"1f43e","shortnames":[":paw_prints:"],"category":"nature"},":ferris_wheel:":{"uc_base":"1f3a1","uc_output":"1f3a1","uc_match":"1f3a1","uc_greedy":"1f3a1","shortnames":[],"category":"travel"},":field_hockey:":{"uc_base":"1f3d1","uc_output":"1f3d1","uc_match":"1f3d1","uc_greedy":"1f3d1","shortnames":[],"category":"activity"},":file_folder:":{"uc_base":"1f4c1","uc_output":"1f4c1","uc_match":"1f4c1","uc_greedy":"1f4c1","shortnames":[],"category":"objects"},":fingers_crossed:":{"uc_base":"1f91e","uc_output":"1f91e","uc_match":"1f91e","uc_greedy":"1f91e","shortnames":[":hand_with_index_and_middle_finger_crossed:"],"category":"people"},":fire:":{"uc_base":"1f525","uc_output":"1f525","uc_match":"1f525","uc_greedy":"1f525","shortnames":[":flame:"],"category":"nature"},":fire_engine:":{"uc_base":"1f692","uc_output":"1f692","uc_match":"1f692","uc_greedy":"1f692","shortnames":[],"category":"travel"},":fireworks:":{"uc_base":"1f386","uc_output":"1f386","uc_match":"1f386","uc_greedy":"1f386","shortnames":[],"category":"travel"},":first_place:":{"uc_base":"1f947","uc_output":"1f947","uc_match":"1f947","uc_greedy":"1f947","shortnames":[":first_place_medal:"],"category":"activity"},":first_quarter_moon:":{"uc_base":"1f313","uc_output":"1f313","uc_match":"1f313","uc_greedy":"1f313","shortnames":[],"category":"nature"},":first_quarter_moon_with_face:":{"uc_base":"1f31b","uc_output":"1f31b","uc_match":"1f31b","uc_greedy":"1f31b","shortnames":[],"category":"nature"},":fish:":{"uc_base":"1f41f","uc_output":"1f41f","uc_match":"1f41f","uc_greedy":"1f41f","shortnames":[],"category":"nature"},":fish_cake:":{"uc_base":"1f365","uc_output":"1f365","uc_match":"1f365","uc_greedy":"1f365","shortnames":[],"category":"food"},":fishing_pole_and_fish:":{"uc_base":"1f3a3","uc_output":"1f3a3","uc_match":"1f3a3","uc_greedy":"1f3a3","shortnames":[],"category":"activity"},":flag_black:":{"uc_base":"1f3f4","uc_output":"1f3f4","uc_match":"1f3f4","uc_greedy":"1f3f4","shortnames":[":waving_black_flag:"],"category":"flags"},":flags:":{"uc_base":"1f38f","uc_output":"1f38f","uc_match":"1f38f","uc_greedy":"1f38f","shortnames":[],"category":"objects"},":flashlight:":{"uc_base":"1f526","uc_output":"1f526","uc_match":"1f526","uc_greedy":"1f526","shortnames":[],"category":"objects"},":floppy_disk:":{"uc_base":"1f4be","uc_output":"1f4be","uc_match":"1f4be","uc_greedy":"1f4be","shortnames":[],"category":"objects"},":flower_playing_cards:":{"uc_base":"1f3b4","uc_output":"1f3b4","uc_match":"1f3b4","uc_greedy":"1f3b4","shortnames":[],"category":"symbols"},":flushed:":{"uc_base":"1f633","uc_output":"1f633","uc_match":"1f633","uc_greedy":"1f633","shortnames":[],"category":"people"},":flying_saucer:":{"uc_base":"1f6f8","uc_output":"1f6f8","uc_match":"1f6f8","uc_greedy":"1f6f8","shortnames":[],"category":"travel"},":foggy:":{"uc_base":"1f301","uc_output":"1f301","uc_match":"1f301","uc_greedy":"1f301","shortnames":[],"category":"travel"},":football:":{"uc_base":"1f3c8","uc_output":"1f3c8","uc_match":"1f3c8","uc_greedy":"1f3c8","shortnames":[],"category":"activity"},":footprints:":{"uc_base":"1f463","uc_output":"1f463","uc_match":"1f463","uc_greedy":"1f463","shortnames":[],"category":"people"},":fork_and_knife:":{"uc_base":"1f374","uc_output":"1f374","uc_match":"1f374","uc_greedy":"1f374","shortnames":[],"category":"food"},":fortune_cookie:":{"uc_base":"1f960","uc_output":"1f960","uc_match":"1f960","uc_greedy":"1f960","shortnames":[],"category":"food"},":four_leaf_clover:":{"uc_base":"1f340","uc_output":"1f340","uc_match":"1f340","uc_greedy":"1f340","shortnames":[],"category":"nature"},":fox:":{"uc_base":"1f98a","uc_output":"1f98a","uc_match":"1f98a","uc_greedy":"1f98a","shortnames":[":fox_face:"],"category":"nature"},":free:":{"uc_base":"1f193","uc_output":"1f193","uc_match":"1f193","uc_greedy":"1f193","shortnames":[],"category":"symbols"},":french_bread:":{"uc_base":"1f956","uc_output":"1f956","uc_match":"1f956","uc_greedy":"1f956","shortnames":[":baguette_bread:"],"category":"food"},":fried_shrimp:":{"uc_base":"1f364","uc_output":"1f364","uc_match":"1f364","uc_greedy":"1f364","shortnames":[],"category":"food"},":fries:":{"uc_base":"1f35f","uc_output":"1f35f","uc_match":"1f35f","uc_greedy":"1f35f","shortnames":[],"category":"food"},":frog:":{"uc_base":"1f438","uc_output":"1f438","uc_match":"1f438","uc_greedy":"1f438","shortnames":[],"category":"nature"},":frowning:":{"uc_base":"1f626","uc_output":"1f626","uc_match":"1f626","uc_greedy":"1f626","shortnames":[],"category":"people"},":full_moon:":{"uc_base":"1f315","uc_output":"1f315","uc_match":"1f315","uc_greedy":"1f315","shortnames":[],"category":"nature"},":full_moon_with_face:":{"uc_base":"1f31d","uc_output":"1f31d","uc_match":"1f31d","uc_greedy":"1f31d","shortnames":[],"category":"nature"},":game_die:":{"uc_base":"1f3b2","uc_output":"1f3b2","uc_match":"1f3b2","uc_greedy":"1f3b2","shortnames":[],"category":"activity"},":gem:":{"uc_base":"1f48e","uc_output":"1f48e","uc_match":"1f48e","uc_greedy":"1f48e","shortnames":[],"category":"objects"},":genie:":{"uc_base":"1f9de","uc_output":"1f9de","uc_match":"1f9de","uc_greedy":"1f9de","shortnames":[],"category":"people"},":ghost:":{"uc_base":"1f47b","uc_output":"1f47b","uc_match":"1f47b","uc_greedy":"1f47b","shortnames":[],"category":"people"},":gift:":{"uc_base":"1f381","uc_output":"1f381","uc_match":"1f381","uc_greedy":"1f381","shortnames":[],"category":"objects"},":gift_heart:":{"uc_base":"1f49d","uc_output":"1f49d","uc_match":"1f49d","uc_greedy":"1f49d","shortnames":[],"category":"symbols"},":giraffe:":{"uc_base":"1f992","uc_output":"1f992","uc_match":"1f992","uc_greedy":"1f992","shortnames":[],"category":"nature"},":girl:":{"uc_base":"1f467","uc_output":"1f467","uc_match":"1f467","uc_greedy":"1f467","shortnames":[],"category":"people"},":globe_with_meridians:":{"uc_base":"1f310","uc_output":"1f310","uc_match":"1f310","uc_greedy":"1f310","shortnames":[],"category":"symbols"},":gloves:":{"uc_base":"1f9e4","uc_output":"1f9e4","uc_match":"1f9e4","uc_greedy":"1f9e4","shortnames":[],"category":"people"},":goal:":{"uc_base":"1f945","uc_output":"1f945","uc_match":"1f945","uc_greedy":"1f945","shortnames":[":goal_net:"],"category":"activity"},":goat:":{"uc_base":"1f410","uc_output":"1f410","uc_match":"1f410","uc_greedy":"1f410","shortnames":[],"category":"nature"},":gorilla:":{"uc_base":"1f98d","uc_output":"1f98d","uc_match":"1f98d","uc_greedy":"1f98d","shortnames":[],"category":"nature"},":grapes:":{"uc_base":"1f347","uc_output":"1f347","uc_match":"1f347","uc_greedy":"1f347","shortnames":[],"category":"food"},":green_apple:":{"uc_base":"1f34f","uc_output":"1f34f","uc_match":"1f34f","uc_greedy":"1f34f","shortnames":[],"category":"food"},":green_book:":{"uc_base":"1f4d7","uc_output":"1f4d7","uc_match":"1f4d7","uc_greedy":"1f4d7","shortnames":[],"category":"objects"},":green_heart:":{"uc_base":"1f49a","uc_output":"1f49a","uc_match":"1f49a","uc_greedy":"1f49a","shortnames":[],"category":"symbols"},":grimacing:":{"uc_base":"1f62c","uc_output":"1f62c","uc_match":"1f62c","uc_greedy":"1f62c","shortnames":[],"category":"people"},":grin:":{"uc_base":"1f601","uc_output":"1f601","uc_match":"1f601","uc_greedy":"1f601","shortnames":[],"category":"people"},":grinning:":{"uc_base":"1f600","uc_output":"1f600","uc_match":"1f600","uc_greedy":"1f600","shortnames":[],"category":"people"},":guard:":{"uc_base":"1f482","uc_output":"1f482","uc_match":"1f482","uc_greedy":"1f482","shortnames":[":guardsman:"],"category":"people"},":guitar:":{"uc_base":"1f3b8","uc_output":"1f3b8","uc_match":"1f3b8","uc_greedy":"1f3b8","shortnames":[],"category":"activity"},":gun:":{"uc_base":"1f52b","uc_output":"1f52b","uc_match":"1f52b","uc_greedy":"1f52b","shortnames":[],"category":"objects"},":hamburger:":{"uc_base":"1f354","uc_output":"1f354","uc_match":"1f354","uc_greedy":"1f354","shortnames":[],"category":"food"},":hammer:":{"uc_base":"1f528","uc_output":"1f528","uc_match":"1f528","uc_greedy":"1f528","shortnames":[],"category":"objects"},":hamster:":{"uc_base":"1f439","uc_output":"1f439","uc_match":"1f439","uc_greedy":"1f439","shortnames":[],"category":"nature"},":handbag:":{"uc_base":"1f45c","uc_output":"1f45c","uc_match":"1f45c","uc_greedy":"1f45c","shortnames":[],"category":"people"},":handshake:":{"uc_base":"1f91d","uc_output":"1f91d","uc_match":"1f91d","uc_greedy":"1f91d","shortnames":[":shaking_hands:"],"category":"people"},":hatched_chick:":{"uc_base":"1f425","uc_output":"1f425","uc_match":"1f425","uc_greedy":"1f425","shortnames":[],"category":"nature"},":hatching_chick:":{"uc_base":"1f423","uc_output":"1f423","uc_match":"1f423","uc_greedy":"1f423","shortnames":[],"category":"nature"},":head_bandage:":{"uc_base":"1f915","uc_output":"1f915","uc_match":"1f915","uc_greedy":"1f915","shortnames":[":face_with_head_bandage:"],"category":"people"},":headphones:":{"uc_base":"1f3a7","uc_output":"1f3a7","uc_match":"1f3a7","uc_greedy":"1f3a7","shortnames":[],"category":"activity"},":hear_no_evil:":{"uc_base":"1f649","uc_output":"1f649","uc_match":"1f649","uc_greedy":"1f649","shortnames":[],"category":"nature"},":heart_decoration:":{"uc_base":"1f49f","uc_output":"1f49f","uc_match":"1f49f","uc_greedy":"1f49f","shortnames":[],"category":"symbols"},":heart_eyes:":{"uc_base":"1f60d","uc_output":"1f60d","uc_match":"1f60d","uc_greedy":"1f60d","shortnames":[],"category":"people"},":heart_eyes_cat:":{"uc_base":"1f63b","uc_output":"1f63b","uc_match":"1f63b","uc_greedy":"1f63b","shortnames":[],"category":"people"},":heartbeat:":{"uc_base":"1f493","uc_output":"1f493","uc_match":"1f493","uc_greedy":"1f493","shortnames":[],"category":"symbols"},":heartpulse:":{"uc_base":"1f497","uc_output":"1f497","uc_match":"1f497","uc_greedy":"1f497","shortnames":[],"category":"symbols"},":heavy_dollar_sign:":{"uc_base":"1f4b2","uc_output":"1f4b2","uc_match":"1f4b2","uc_greedy":"1f4b2","shortnames":[],"category":"symbols"},":hedgehog:":{"uc_base":"1f994","uc_output":"1f994","uc_match":"1f994","uc_greedy":"1f994","shortnames":[],"category":"nature"},":helicopter:":{"uc_base":"1f681","uc_output":"1f681","uc_match":"1f681","uc_greedy":"1f681","shortnames":[],"category":"travel"},":herb:":{"uc_base":"1f33f","uc_output":"1f33f","uc_match":"1f33f","uc_greedy":"1f33f","shortnames":[],"category":"nature"},":hibiscus:":{"uc_base":"1f33a","uc_output":"1f33a","uc_match":"1f33a","uc_greedy":"1f33a","shortnames":[],"category":"nature"},":high_brightness:":{"uc_base":"1f506","uc_output":"1f506","uc_match":"1f506","uc_greedy":"1f506","shortnames":[],"category":"symbols"},":high_heel:":{"uc_base":"1f460","uc_output":"1f460","uc_match":"1f460","uc_greedy":"1f460","shortnames":[],"category":"people"},":hockey:":{"uc_base":"1f3d2","uc_output":"1f3d2","uc_match":"1f3d2","uc_greedy":"1f3d2","shortnames":[],"category":"activity"},":honey_pot:":{"uc_base":"1f36f","uc_output":"1f36f","uc_match":"1f36f","uc_greedy":"1f36f","shortnames":[],"category":"food"},":horse:":{"uc_base":"1f434","uc_output":"1f434","uc_match":"1f434","uc_greedy":"1f434","shortnames":[],"category":"nature"},":horse_racing:":{"uc_base":"1f3c7","uc_output":"1f3c7","uc_match":"1f3c7","uc_greedy":"1f3c7","shortnames":[],"category":"activity"},":hospital:":{"uc_base":"1f3e5","uc_output":"1f3e5","uc_match":"1f3e5","uc_greedy":"1f3e5","shortnames":[],"category":"travel"},":hotdog:":{"uc_base":"1f32d","uc_output":"1f32d","uc_match":"1f32d","uc_greedy":"1f32d","shortnames":[":hot_dog:"],"category":"food"},":hotel:":{"uc_base":"1f3e8","uc_output":"1f3e8","uc_match":"1f3e8","uc_greedy":"1f3e8","shortnames":[],"category":"travel"},":house:":{"uc_base":"1f3e0","uc_output":"1f3e0","uc_match":"1f3e0","uc_greedy":"1f3e0","shortnames":[],"category":"travel"},":house_with_garden:":{"uc_base":"1f3e1","uc_output":"1f3e1","uc_match":"1f3e1","uc_greedy":"1f3e1","shortnames":[],"category":"travel"},":hugging:":{"uc_base":"1f917","uc_output":"1f917","uc_match":"1f917","uc_greedy":"1f917","shortnames":[":hugging_face:"],"category":"people"},":hushed:":{"uc_base":"1f62f","uc_output":"1f62f","uc_match":"1f62f","uc_greedy":"1f62f","shortnames":[],"category":"people"},":ice_cream:":{"uc_base":"1f368","uc_output":"1f368","uc_match":"1f368","uc_greedy":"1f368","shortnames":[],"category":"food"},":icecream:":{"uc_base":"1f366","uc_output":"1f366","uc_match":"1f366","uc_greedy":"1f366","shortnames":[],"category":"food"},":id:":{"uc_base":"1f194","uc_output":"1f194","uc_match":"1f194","uc_greedy":"1f194","shortnames":[],"category":"symbols"},":ideograph_advantage:":{"uc_base":"1f250","uc_output":"1f250","uc_match":"1f250","uc_greedy":"1f250","shortnames":[],"category":"symbols"},":imp:":{"uc_base":"1f47f","uc_output":"1f47f","uc_match":"1f47f","uc_greedy":"1f47f","shortnames":[],"category":"people"},":inbox_tray:":{"uc_base":"1f4e5","uc_output":"1f4e5","uc_match":"1f4e5","uc_greedy":"1f4e5","shortnames":[],"category":"objects"},":incoming_envelope:":{"uc_base":"1f4e8","uc_output":"1f4e8","uc_match":"1f4e8","uc_greedy":"1f4e8","shortnames":[],"category":"objects"},":innocent:":{"uc_base":"1f607","uc_output":"1f607","uc_match":"1f607","uc_greedy":"1f607","shortnames":[],"category":"people"},":iphone:":{"uc_base":"1f4f1","uc_output":"1f4f1","uc_match":"1f4f1","uc_greedy":"1f4f1","shortnames":[],"category":"objects"},":izakaya_lantern:":{"uc_base":"1f3ee","uc_output":"1f3ee","uc_match":"1f3ee","uc_greedy":"1f3ee","shortnames":[],"category":"objects"},":jack_o_lantern:":{"uc_base":"1f383","uc_output":"1f383","uc_match":"1f383","uc_greedy":"1f383","shortnames":[],"category":"people"},":japan:":{"uc_base":"1f5fe","uc_output":"1f5fe","uc_match":"1f5fe","uc_greedy":"1f5fe","shortnames":[],"category":"travel"},":japanese_castle:":{"uc_base":"1f3ef","uc_output":"1f3ef","uc_match":"1f3ef","uc_greedy":"1f3ef","shortnames":[],"category":"travel"},":japanese_goblin:":{"uc_base":"1f47a","uc_output":"1f47a","uc_match":"1f47a","uc_greedy":"1f47a","shortnames":[],"category":"people"},":japanese_ogre:":{"uc_base":"1f479","uc_output":"1f479","uc_match":"1f479","uc_greedy":"1f479","shortnames":[],"category":"people"},":jeans:":{"uc_base":"1f456","uc_output":"1f456","uc_match":"1f456","uc_greedy":"1f456","shortnames":[],"category":"people"},":joy:":{"uc_base":"1f602","uc_output":"1f602","uc_match":"1f602","uc_greedy":"1f602","shortnames":[],"category":"people"},":joy_cat:":{"uc_base":"1f639","uc_output":"1f639","uc_match":"1f639","uc_greedy":"1f639","shortnames":[],"category":"people"},":kaaba:":{"uc_base":"1f54b","uc_output":"1f54b","uc_match":"1f54b","uc_greedy":"1f54b","shortnames":[],"category":"travel"},":key:":{"uc_base":"1f511","uc_output":"1f511","uc_match":"1f511","uc_greedy":"1f511","shortnames":[],"category":"objects"},":keycap_ten:":{"uc_base":"1f51f","uc_output":"1f51f","uc_match":"1f51f","uc_greedy":"1f51f","shortnames":[],"category":"symbols"},":kimono:":{"uc_base":"1f458","uc_output":"1f458","uc_match":"1f458","uc_greedy":"1f458","shortnames":[],"category":"people"},":kiss:":{"uc_base":"1f48b","uc_output":"1f48b","uc_match":"1f48b","uc_greedy":"1f48b","shortnames":[],"category":"people"},":kissing:":{"uc_base":"1f617","uc_output":"1f617","uc_match":"1f617","uc_greedy":"1f617","shortnames":[],"category":"people"},":kissing_cat:":{"uc_base":"1f63d","uc_output":"1f63d","uc_match":"1f63d","uc_greedy":"1f63d","shortnames":[],"category":"people"},":kissing_closed_eyes:":{"uc_base":"1f61a","uc_output":"1f61a","uc_match":"1f61a","uc_greedy":"1f61a","shortnames":[],"category":"people"},":kissing_heart:":{"uc_base":"1f618","uc_output":"1f618","uc_match":"1f618","uc_greedy":"1f618","shortnames":[],"category":"people"},":kissing_smiling_eyes:":{"uc_base":"1f619","uc_output":"1f619","uc_match":"1f619","uc_greedy":"1f619","shortnames":[],"category":"people"},":kiwi:":{"uc_base":"1f95d","uc_output":"1f95d","uc_match":"1f95d","uc_greedy":"1f95d","shortnames":[":kiwifruit:"],"category":"food"},":knife:":{"uc_base":"1f52a","uc_output":"1f52a","uc_match":"1f52a","uc_greedy":"1f52a","shortnames":[],"category":"objects"},":koala:":{"uc_base":"1f428","uc_output":"1f428","uc_match":"1f428","uc_greedy":"1f428","shortnames":[],"category":"nature"},":koko:":{"uc_base":"1f201","uc_output":"1f201","uc_match":"1f201","uc_greedy":"1f201","shortnames":[],"category":"symbols"},":large_blue_diamond:":{"uc_base":"1f537","uc_output":"1f537","uc_match":"1f537","uc_greedy":"1f537","shortnames":[],"category":"symbols"},":large_orange_diamond:":{"uc_base":"1f536","uc_output":"1f536","uc_match":"1f536","uc_greedy":"1f536","shortnames":[],"category":"symbols"},":last_quarter_moon:":{"uc_base":"1f317","uc_output":"1f317","uc_match":"1f317","uc_greedy":"1f317","shortnames":[],"category":"nature"},":last_quarter_moon_with_face:":{"uc_base":"1f31c","uc_output":"1f31c","uc_match":"1f31c","uc_greedy":"1f31c","shortnames":[],"category":"nature"},":laughing:":{"uc_base":"1f606","uc_output":"1f606","uc_match":"1f606","uc_greedy":"1f606","shortnames":[":satisfied:"],"category":"people"},":leaves:":{"uc_base":"1f343","uc_output":"1f343","uc_match":"1f343","uc_greedy":"1f343","shortnames":[],"category":"nature"},":ledger:":{"uc_base":"1f4d2","uc_output":"1f4d2","uc_match":"1f4d2","uc_greedy":"1f4d2","shortnames":[],"category":"objects"},":left_facing_fist:":{"uc_base":"1f91b","uc_output":"1f91b","uc_match":"1f91b","uc_greedy":"1f91b","shortnames":[":left_fist:"],"category":"people"},":left_luggage:":{"uc_base":"1f6c5","uc_output":"1f6c5","uc_match":"1f6c5","uc_greedy":"1f6c5","shortnames":[],"category":"symbols"},":lemon:":{"uc_base":"1f34b","uc_output":"1f34b","uc_match":"1f34b","uc_greedy":"1f34b","shortnames":[],"category":"food"},":leopard:":{"uc_base":"1f406","uc_output":"1f406","uc_match":"1f406","uc_greedy":"1f406","shortnames":[],"category":"nature"},":light_rail:":{"uc_base":"1f688","uc_output":"1f688","uc_match":"1f688","uc_greedy":"1f688","shortnames":[],"category":"travel"},":link:":{"uc_base":"1f517","uc_output":"1f517","uc_match":"1f517","uc_greedy":"1f517","shortnames":[],"category":"objects"},":lion_face:":{"uc_base":"1f981","uc_output":"1f981","uc_match":"1f981","uc_greedy":"1f981","shortnames":[":lion:"],"category":"nature"},":lips:":{"uc_base":"1f444","uc_output":"1f444","uc_match":"1f444","uc_greedy":"1f444","shortnames":[],"category":"people"},":lipstick:":{"uc_base":"1f484","uc_output":"1f484","uc_match":"1f484","uc_greedy":"1f484","shortnames":[],"category":"people"},":lizard:":{"uc_base":"1f98e","uc_output":"1f98e","uc_match":"1f98e","uc_greedy":"1f98e","shortnames":[],"category":"nature"},":lock:":{"uc_base":"1f512","uc_output":"1f512","uc_match":"1f512","uc_greedy":"1f512","shortnames":[],"category":"objects"},":lock_with_ink_pen:":{"uc_base":"1f50f","uc_output":"1f50f","uc_match":"1f50f","uc_greedy":"1f50f","shortnames":[],"category":"objects"},":lollipop:":{"uc_base":"1f36d","uc_output":"1f36d","uc_match":"1f36d","uc_greedy":"1f36d","shortnames":[],"category":"food"},":loud_sound:":{"uc_base":"1f50a","uc_output":"1f50a","uc_match":"1f50a","uc_greedy":"1f50a","shortnames":[],"category":"symbols"},":loudspeaker:":{"uc_base":"1f4e2","uc_output":"1f4e2","uc_match":"1f4e2","uc_greedy":"1f4e2","shortnames":[],"category":"symbols"},":love_hotel:":{"uc_base":"1f3e9","uc_output":"1f3e9","uc_match":"1f3e9","uc_greedy":"1f3e9","shortnames":[],"category":"travel"},":love_letter:":{"uc_base":"1f48c","uc_output":"1f48c","uc_match":"1f48c","uc_greedy":"1f48c","shortnames":[],"category":"objects"},":love_you_gesture:":{"uc_base":"1f91f","uc_output":"1f91f","uc_match":"1f91f","uc_greedy":"1f91f","shortnames":[],"category":"people"},":low_brightness:":{"uc_base":"1f505","uc_output":"1f505","uc_match":"1f505","uc_greedy":"1f505","shortnames":[],"category":"symbols"},":lying_face:":{"uc_base":"1f925","uc_output":"1f925","uc_match":"1f925","uc_greedy":"1f925","shortnames":[":liar:"],"category":"people"},":mag:":{"uc_base":"1f50d","uc_output":"1f50d","uc_match":"1f50d","uc_greedy":"1f50d","shortnames":[],"category":"objects"},":mag_right:":{"uc_base":"1f50e","uc_output":"1f50e","uc_match":"1f50e","uc_greedy":"1f50e","shortnames":[],"category":"objects"},":mage:":{"uc_base":"1f9d9","uc_output":"1f9d9","uc_match":"1f9d9","uc_greedy":"1f9d9","shortnames":[],"category":"people"},":mahjong:":{"uc_base":"1f004","uc_output":"1f004","uc_match":"1f004","uc_greedy":"1f004","shortnames":[],"category":"symbols"},":mailbox:":{"uc_base":"1f4eb","uc_output":"1f4eb","uc_match":"1f4eb","uc_greedy":"1f4eb","shortnames":[],"category":"objects"},":mailbox_closed:":{"uc_base":"1f4ea","uc_output":"1f4ea","uc_match":"1f4ea","uc_greedy":"1f4ea","shortnames":[],"category":"objects"},":mailbox_with_mail:":{"uc_base":"1f4ec","uc_output":"1f4ec","uc_match":"1f4ec","uc_greedy":"1f4ec","shortnames":[],"category":"objects"},":mailbox_with_no_mail:":{"uc_base":"1f4ed","uc_output":"1f4ed","uc_match":"1f4ed","uc_greedy":"1f4ed","shortnames":[],"category":"objects"},":man:":{"uc_base":"1f468","uc_output":"1f468","uc_match":"1f468","uc_greedy":"1f468","shortnames":[],"category":"people"},":man_dancing:":{"uc_base":"1f57a","uc_output":"1f57a","uc_match":"1f57a","uc_greedy":"1f57a","shortnames":[":male_dancer:"],"category":"people"},":man_in_tuxedo:":{"uc_base":"1f935","uc_output":"1f935","uc_match":"1f935","uc_greedy":"1f935","shortnames":[],"category":"people"},":man_with_chinese_cap:":{"uc_base":"1f472","uc_output":"1f472","uc_match":"1f472","uc_greedy":"1f472","shortnames":[":man_with_gua_pi_mao:"],"category":"people"},":mans_shoe:":{"uc_base":"1f45e","uc_output":"1f45e","uc_match":"1f45e","uc_greedy":"1f45e","shortnames":[],"category":"people"},":maple_leaf:":{"uc_base":"1f341","uc_output":"1f341","uc_match":"1f341","uc_greedy":"1f341","shortnames":[],"category":"nature"},":martial_arts_uniform:":{"uc_base":"1f94b","uc_output":"1f94b","uc_match":"1f94b","uc_greedy":"1f94b","shortnames":[":karate_uniform:"],"category":"activity"},":mask:":{"uc_base":"1f637","uc_output":"1f637","uc_match":"1f637","uc_greedy":"1f637","shortnames":[],"category":"people"},":meat_on_bone:":{"uc_base":"1f356","uc_output":"1f356","uc_match":"1f356","uc_greedy":"1f356","shortnames":[],"category":"food"},":medal:":{"uc_base":"1f3c5","uc_output":"1f3c5","uc_match":"1f3c5","uc_greedy":"1f3c5","shortnames":[":sports_medal:"],"category":"activity"},":mega:":{"uc_base":"1f4e3","uc_output":"1f4e3","uc_match":"1f4e3","uc_greedy":"1f4e3","shortnames":[],"category":"symbols"},":melon:":{"uc_base":"1f348","uc_output":"1f348","uc_match":"1f348","uc_greedy":"1f348","shortnames":[],"category":"food"},":menorah:":{"uc_base":"1f54e","uc_output":"1f54e","uc_match":"1f54e","uc_greedy":"1f54e","shortnames":[],"category":"symbols"},":mens:":{"uc_base":"1f6b9","uc_output":"1f6b9","uc_match":"1f6b9","uc_greedy":"1f6b9","shortnames":[],"category":"symbols"},":merperson:":{"uc_base":"1f9dc","uc_output":"1f9dc","uc_match":"1f9dc","uc_greedy":"1f9dc","shortnames":[],"category":"people"},":metal:":{"uc_base":"1f918","uc_output":"1f918","uc_match":"1f918","uc_greedy":"1f918","shortnames":[":sign_of_the_horns:"],"category":"people"},":metro:":{"uc_base":"1f687","uc_output":"1f687","uc_match":"1f687","uc_greedy":"1f687","shortnames":[],"category":"travel"},":microphone:":{"uc_base":"1f3a4","uc_output":"1f3a4","uc_match":"1f3a4","uc_greedy":"1f3a4","shortnames":[],"category":"activity"},":microscope:":{"uc_base":"1f52c","uc_output":"1f52c","uc_match":"1f52c","uc_greedy":"1f52c","shortnames":[],"category":"objects"},":middle_finger:":{"uc_base":"1f595","uc_output":"1f595","uc_match":"1f595","uc_greedy":"1f595","shortnames":[":reversed_hand_with_middle_finger_extended:"],"category":"people"},":milk:":{"uc_base":"1f95b","uc_output":"1f95b","uc_match":"1f95b","uc_greedy":"1f95b","shortnames":[":glass_of_milk:"],"category":"food"},":milky_way:":{"uc_base":"1f30c","uc_output":"1f30c","uc_match":"1f30c","uc_greedy":"1f30c","shortnames":[],"category":"travel"},":minibus:":{"uc_base":"1f690","uc_output":"1f690","uc_match":"1f690","uc_greedy":"1f690","shortnames":[],"category":"travel"},":minidisc:":{"uc_base":"1f4bd","uc_output":"1f4bd","uc_match":"1f4bd","uc_greedy":"1f4bd","shortnames":[],"category":"objects"},":mobile_phone_off:":{"uc_base":"1f4f4","uc_output":"1f4f4","uc_match":"1f4f4","uc_greedy":"1f4f4","shortnames":[],"category":"symbols"},":money_mouth:":{"uc_base":"1f911","uc_output":"1f911","uc_match":"1f911","uc_greedy":"1f911","shortnames":[":money_mouth_face:"],"category":"people"},":money_with_wings:":{"uc_base":"1f4b8","uc_output":"1f4b8","uc_match":"1f4b8","uc_greedy":"1f4b8","shortnames":[],"category":"objects"},":moneybag:":{"uc_base":"1f4b0","uc_output":"1f4b0","uc_match":"1f4b0","uc_greedy":"1f4b0","shortnames":[],"category":"objects"},":monkey:":{"uc_base":"1f412","uc_output":"1f412","uc_match":"1f412","uc_greedy":"1f412","shortnames":[],"category":"nature"},":monkey_face:":{"uc_base":"1f435","uc_output":"1f435","uc_match":"1f435","uc_greedy":"1f435","shortnames":[],"category":"nature"},":monorail:":{"uc_base":"1f69d","uc_output":"1f69d","uc_match":"1f69d","uc_greedy":"1f69d","shortnames":[],"category":"travel"},":mortar_board:":{"uc_base":"1f393","uc_output":"1f393","uc_match":"1f393","uc_greedy":"1f393","shortnames":[],"category":"people"},":mosque:":{"uc_base":"1f54c","uc_output":"1f54c","uc_match":"1f54c","uc_greedy":"1f54c","shortnames":[],"category":"travel"},":motor_scooter:":{"uc_base":"1f6f5","uc_output":"1f6f5","uc_match":"1f6f5","uc_greedy":"1f6f5","shortnames":[":motorbike:"],"category":"travel"},":mount_fuji:":{"uc_base":"1f5fb","uc_output":"1f5fb","uc_match":"1f5fb","uc_greedy":"1f5fb","shortnames":[],"category":"travel"},":mountain_cableway:":{"uc_base":"1f6a0","uc_output":"1f6a0","uc_match":"1f6a0","uc_greedy":"1f6a0","shortnames":[],"category":"travel"},":mountain_railway:":{"uc_base":"1f69e","uc_output":"1f69e","uc_match":"1f69e","uc_greedy":"1f69e","shortnames":[],"category":"travel"},":mouse2:":{"uc_base":"1f401","uc_output":"1f401","uc_match":"1f401","uc_greedy":"1f401","shortnames":[],"category":"nature"},":mouse:":{"uc_base":"1f42d","uc_output":"1f42d","uc_match":"1f42d","uc_greedy":"1f42d","shortnames":[],"category":"nature"},":movie_camera:":{"uc_base":"1f3a5","uc_output":"1f3a5","uc_match":"1f3a5","uc_greedy":"1f3a5","shortnames":[],"category":"objects"},":moyai:":{"uc_base":"1f5ff","uc_output":"1f5ff","uc_match":"1f5ff","uc_greedy":"1f5ff","shortnames":[],"category":"travel"},":mrs_claus:":{"uc_base":"1f936","uc_output":"1f936","uc_match":"1f936","uc_greedy":"1f936","shortnames":[":mother_christmas:"],"category":"people"},":muscle:":{"uc_base":"1f4aa","uc_output":"1f4aa","uc_match":"1f4aa","uc_greedy":"1f4aa","shortnames":[],"category":"people"},":mushroom:":{"uc_base":"1f344","uc_output":"1f344","uc_match":"1f344","uc_greedy":"1f344","shortnames":[],"category":"nature"},":musical_keyboard:":{"uc_base":"1f3b9","uc_output":"1f3b9","uc_match":"1f3b9","uc_greedy":"1f3b9","shortnames":[],"category":"activity"},":musical_note:":{"uc_base":"1f3b5","uc_output":"1f3b5","uc_match":"1f3b5","uc_greedy":"1f3b5","shortnames":[],"category":"symbols"},":musical_score:":{"uc_base":"1f3bc","uc_output":"1f3bc","uc_match":"1f3bc","uc_greedy":"1f3bc","shortnames":[],"category":"activity"},":mute:":{"uc_base":"1f507","uc_output":"1f507","uc_match":"1f507","uc_greedy":"1f507","shortnames":[],"category":"symbols"},":nail_care:":{"uc_base":"1f485","uc_output":"1f485","uc_match":"1f485","uc_greedy":"1f485","shortnames":[],"category":"people"},":name_badge:":{"uc_base":"1f4db","uc_output":"1f4db","uc_match":"1f4db","uc_greedy":"1f4db","shortnames":[],"category":"symbols"},":nauseated_face:":{"uc_base":"1f922","uc_output":"1f922","uc_match":"1f922","uc_greedy":"1f922","shortnames":[":sick:"],"category":"people"},":necktie:":{"uc_base":"1f454","uc_output":"1f454","uc_match":"1f454","uc_greedy":"1f454","shortnames":[],"category":"people"},":nerd:":{"uc_base":"1f913","uc_output":"1f913","uc_match":"1f913","uc_greedy":"1f913","shortnames":[":nerd_face:"],"category":"people"},":neutral_face:":{"uc_base":"1f610","uc_output":"1f610","uc_match":"1f610","uc_greedy":"1f610","shortnames":[],"category":"people"},":new:":{"uc_base":"1f195","uc_output":"1f195","uc_match":"1f195","uc_greedy":"1f195","shortnames":[],"category":"symbols"},":new_moon:":{"uc_base":"1f311","uc_output":"1f311","uc_match":"1f311","uc_greedy":"1f311","shortnames":[],"category":"nature"},":new_moon_with_face:":{"uc_base":"1f31a","uc_output":"1f31a","uc_match":"1f31a","uc_greedy":"1f31a","shortnames":[],"category":"nature"},":newspaper:":{"uc_base":"1f4f0","uc_output":"1f4f0","uc_match":"1f4f0","uc_greedy":"1f4f0","shortnames":[],"category":"objects"},":ng:":{"uc_base":"1f196","uc_output":"1f196","uc_match":"1f196","uc_greedy":"1f196","shortnames":[],"category":"symbols"},":night_with_stars:":{"uc_base":"1f303","uc_output":"1f303","uc_match":"1f303","uc_greedy":"1f303","shortnames":[],"category":"travel"},":no_bell:":{"uc_base":"1f515","uc_output":"1f515","uc_match":"1f515","uc_greedy":"1f515","shortnames":[],"category":"symbols"},":no_bicycles:":{"uc_base":"1f6b3","uc_output":"1f6b3","uc_match":"1f6b3","uc_greedy":"1f6b3","shortnames":[],"category":"symbols"},":no_entry_sign:":{"uc_base":"1f6ab","uc_output":"1f6ab","uc_match":"1f6ab","uc_greedy":"1f6ab","shortnames":[],"category":"symbols"},":no_mobile_phones:":{"uc_base":"1f4f5","uc_output":"1f4f5","uc_match":"1f4f5","uc_greedy":"1f4f5","shortnames":[],"category":"symbols"},":no_mouth:":{"uc_base":"1f636","uc_output":"1f636","uc_match":"1f636","uc_greedy":"1f636","shortnames":[],"category":"people"},":no_pedestrians:":{"uc_base":"1f6b7","uc_output":"1f6b7","uc_match":"1f6b7","uc_greedy":"1f6b7","shortnames":[],"category":"symbols"},":no_smoking:":{"uc_base":"1f6ad","uc_output":"1f6ad","uc_match":"1f6ad","uc_greedy":"1f6ad","shortnames":[],"category":"symbols"},":non-potable_water:":{"uc_base":"1f6b1","uc_output":"1f6b1","uc_match":"1f6b1","uc_greedy":"1f6b1","shortnames":[],"category":"symbols"},":nose:":{"uc_base":"1f443","uc_output":"1f443","uc_match":"1f443","uc_greedy":"1f443","shortnames":[],"category":"people"},":notebook:":{"uc_base":"1f4d3","uc_output":"1f4d3","uc_match":"1f4d3","uc_greedy":"1f4d3","shortnames":[],"category":"objects"},":notebook_with_decorative_cover:":{"uc_base":"1f4d4","uc_output":"1f4d4","uc_match":"1f4d4","uc_greedy":"1f4d4","shortnames":[],"category":"objects"},":notes:":{"uc_base":"1f3b6","uc_output":"1f3b6","uc_match":"1f3b6","uc_greedy":"1f3b6","shortnames":[],"category":"symbols"},":nut_and_bolt:":{"uc_base":"1f529","uc_output":"1f529","uc_match":"1f529","uc_greedy":"1f529","shortnames":[],"category":"objects"},":ocean:":{"uc_base":"1f30a","uc_output":"1f30a","uc_match":"1f30a","uc_greedy":"1f30a","shortnames":[],"category":"nature"},":octagonal_sign:":{"uc_base":"1f6d1","uc_output":"1f6d1","uc_match":"1f6d1","uc_greedy":"1f6d1","shortnames":[":stop_sign:"],"category":"symbols"},":octopus:":{"uc_base":"1f419","uc_output":"1f419","uc_match":"1f419","uc_greedy":"1f419","shortnames":[],"category":"nature"},":oden:":{"uc_base":"1f362","uc_output":"1f362","uc_match":"1f362","uc_greedy":"1f362","shortnames":[],"category":"food"},":office:":{"uc_base":"1f3e2","uc_output":"1f3e2","uc_match":"1f3e2","uc_greedy":"1f3e2","shortnames":[],"category":"travel"},":ok:":{"uc_base":"1f197","uc_output":"1f197","uc_match":"1f197","uc_greedy":"1f197","shortnames":[],"category":"symbols"},":ok_hand:":{"uc_base":"1f44c","uc_output":"1f44c","uc_match":"1f44c","uc_greedy":"1f44c","shortnames":[],"category":"people"},":older_adult:":{"uc_base":"1f9d3","uc_output":"1f9d3","uc_match":"1f9d3","uc_greedy":"1f9d3","shortnames":[],"category":"people"},":older_man:":{"uc_base":"1f474","uc_output":"1f474","uc_match":"1f474","uc_greedy":"1f474","shortnames":[],"category":"people"},":older_woman:":{"uc_base":"1f475","uc_output":"1f475","uc_match":"1f475","uc_greedy":"1f475","shortnames":[":grandma:"],"category":"people"},":on:":{"uc_base":"1f51b","uc_output":"1f51b","uc_match":"1f51b","uc_greedy":"1f51b","shortnames":[],"category":"symbols"},":oncoming_automobile:":{"uc_base":"1f698","uc_output":"1f698","uc_match":"1f698","uc_greedy":"1f698","shortnames":[],"category":"travel"},":oncoming_bus:":{"uc_base":"1f68d","uc_output":"1f68d","uc_match":"1f68d","uc_greedy":"1f68d","shortnames":[],"category":"travel"},":oncoming_police_car:":{"uc_base":"1f694","uc_output":"1f694","uc_match":"1f694","uc_greedy":"1f694","shortnames":[],"category":"travel"},":oncoming_taxi:":{"uc_base":"1f696","uc_output":"1f696","uc_match":"1f696","uc_greedy":"1f696","shortnames":[],"category":"travel"},":open_file_folder:":{"uc_base":"1f4c2","uc_output":"1f4c2","uc_match":"1f4c2","uc_greedy":"1f4c2","shortnames":[],"category":"objects"},":open_hands:":{"uc_base":"1f450","uc_output":"1f450","uc_match":"1f450","uc_greedy":"1f450","shortnames":[],"category":"people"},":open_mouth:":{"uc_base":"1f62e","uc_output":"1f62e","uc_match":"1f62e","uc_greedy":"1f62e","shortnames":[],"category":"people"},":orange_book:":{"uc_base":"1f4d9","uc_output":"1f4d9","uc_match":"1f4d9","uc_greedy":"1f4d9","shortnames":[],"category":"objects"},":orange_heart:":{"uc_base":"1f9e1","uc_output":"1f9e1","uc_match":"1f9e1","uc_greedy":"1f9e1","shortnames":[],"category":"objects"},":outbox_tray:":{"uc_base":"1f4e4","uc_output":"1f4e4","uc_match":"1f4e4","uc_greedy":"1f4e4","shortnames":[],"category":"objects"},":owl:":{"uc_base":"1f989","uc_output":"1f989","uc_match":"1f989","uc_greedy":"1f989","shortnames":[],"category":"nature"},":ox:":{"uc_base":"1f402","uc_output":"1f402","uc_match":"1f402","uc_greedy":"1f402","shortnames":[],"category":"nature"},":package:":{"uc_base":"1f4e6","uc_output":"1f4e6","uc_match":"1f4e6","uc_greedy":"1f4e6","shortnames":[],"category":"objects"},":page_facing_up:":{"uc_base":"1f4c4","uc_output":"1f4c4","uc_match":"1f4c4","uc_greedy":"1f4c4","shortnames":[],"category":"objects"},":page_with_curl:":{"uc_base":"1f4c3","uc_output":"1f4c3","uc_match":"1f4c3","uc_greedy":"1f4c3","shortnames":[],"category":"objects"},":pager:":{"uc_base":"1f4df","uc_output":"1f4df","uc_match":"1f4df","uc_greedy":"1f4df","shortnames":[],"category":"objects"},":palm_tree:":{"uc_base":"1f334","uc_output":"1f334","uc_match":"1f334","uc_greedy":"1f334","shortnames":[],"category":"nature"},":palms_up_together:":{"uc_base":"1f932","uc_output":"1f932","uc_match":"1f932","uc_greedy":"1f932","shortnames":[],"category":"people"},":pancakes:":{"uc_base":"1f95e","uc_output":"1f95e","uc_match":"1f95e","uc_greedy":"1f95e","shortnames":[],"category":"food"},":panda_face:":{"uc_base":"1f43c","uc_output":"1f43c","uc_match":"1f43c","uc_greedy":"1f43c","shortnames":[],"category":"nature"},":paperclip:":{"uc_base":"1f4ce","uc_output":"1f4ce","uc_match":"1f4ce","uc_greedy":"1f4ce","shortnames":[],"category":"objects"},":passport_control:":{"uc_base":"1f6c2","uc_output":"1f6c2","uc_match":"1f6c2","uc_greedy":"1f6c2","shortnames":[],"category":"symbols"},":peach:":{"uc_base":"1f351","uc_output":"1f351","uc_match":"1f351","uc_greedy":"1f351","shortnames":[],"category":"food"},":peanuts:":{"uc_base":"1f95c","uc_output":"1f95c","uc_match":"1f95c","uc_greedy":"1f95c","shortnames":[":shelled_peanut:"],"category":"food"},":pear:":{"uc_base":"1f350","uc_output":"1f350","uc_match":"1f350","uc_greedy":"1f350","shortnames":[],"category":"food"},":pencil:":{"uc_base":"1f4dd","uc_output":"1f4dd","uc_match":"1f4dd","uc_greedy":"1f4dd","shortnames":[":memo:"],"category":"objects"},":penguin:":{"uc_base":"1f427","uc_output":"1f427","uc_match":"1f427","uc_greedy":"1f427","shortnames":[],"category":"nature"},":pensive:":{"uc_base":"1f614","uc_output":"1f614","uc_match":"1f614","uc_greedy":"1f614","shortnames":[],"category":"people"},":people_with_bunny_ears_partying:":{"uc_base":"1f46f","uc_output":"1f46f","uc_match":"1f46f","uc_greedy":"1f46f","shortnames":[":dancers:"],"category":"people"},":people_wrestling:":{"uc_base":"1f93c","uc_output":"1f93c","uc_match":"1f93c","uc_greedy":"1f93c","shortnames":[":wrestlers:",":wrestling:"],"category":"activity"},":performing_arts:":{"uc_base":"1f3ad","uc_output":"1f3ad","uc_match":"1f3ad","uc_greedy":"1f3ad","shortnames":[],"category":"activity"},":persevere:":{"uc_base":"1f623","uc_output":"1f623","uc_match":"1f623","uc_greedy":"1f623","shortnames":[],"category":"people"},":person_biking:":{"uc_base":"1f6b4","uc_output":"1f6b4","uc_match":"1f6b4","uc_greedy":"1f6b4","shortnames":[":bicyclist:"],"category":"activity"},":person_bowing:":{"uc_base":"1f647","uc_output":"1f647","uc_match":"1f647","uc_greedy":"1f647","shortnames":[":bow:"],"category":"people"},":person_climbing:":{"uc_base":"1f9d7","uc_output":"1f9d7","uc_match":"1f9d7","uc_greedy":"1f9d7","shortnames":[],"category":"activity"},":person_doing_cartwheel:":{"uc_base":"1f938","uc_output":"1f938","uc_match":"1f938","uc_greedy":"1f938","shortnames":[":cartwheel:"],"category":"activity"},":person_facepalming:":{"uc_base":"1f926","uc_output":"1f926","uc_match":"1f926","uc_greedy":"1f926","shortnames":[":face_palm:",":facepalm:"],"category":"people"},":person_fencing:":{"uc_base":"1f93a","uc_output":"1f93a","uc_match":"1f93a","uc_greedy":"1f93a","shortnames":[":fencer:",":fencing:"],"category":"activity"},":person_frowning:":{"uc_base":"1f64d","uc_output":"1f64d","uc_match":"1f64d","uc_greedy":"1f64d","shortnames":[],"category":"people"},":person_gesturing_no:":{"uc_base":"1f645","uc_output":"1f645","uc_match":"1f645","uc_greedy":"1f645","shortnames":[":no_good:"],"category":"people"},":person_gesturing_ok:":{"uc_base":"1f646","uc_output":"1f646","uc_match":"1f646","uc_greedy":"1f646","shortnames":[":ok_woman:"],"category":"people"},":person_getting_haircut:":{"uc_base":"1f487","uc_output":"1f487","uc_match":"1f487","uc_greedy":"1f487","shortnames":[":haircut:"],"category":"people"},":person_getting_massage:":{"uc_base":"1f486","uc_output":"1f486","uc_match":"1f486","uc_greedy":"1f486","shortnames":[":massage:"],"category":"people"},":person_in_lotus_position:":{"uc_base":"1f9d8","uc_output":"1f9d8","uc_match":"1f9d8","uc_greedy":"1f9d8","shortnames":[],"category":"activity"},":person_in_steamy_room:":{"uc_base":"1f9d6","uc_output":"1f9d6","uc_match":"1f9d6","uc_greedy":"1f9d6","shortnames":[],"category":"activity"},":person_juggling:":{"uc_base":"1f939","uc_output":"1f939","uc_match":"1f939","uc_greedy":"1f939","shortnames":[":juggling:",":juggler:"],"category":"activity"},":person_mountain_biking:":{"uc_base":"1f6b5","uc_output":"1f6b5","uc_match":"1f6b5","uc_greedy":"1f6b5","shortnames":[":mountain_bicyclist:"],"category":"activity"},":person_playing_handball:":{"uc_base":"1f93e","uc_output":"1f93e","uc_match":"1f93e","uc_greedy":"1f93e","shortnames":[":handball:"],"category":"activity"},":person_playing_water_polo:":{"uc_base":"1f93d","uc_output":"1f93d","uc_match":"1f93d","uc_greedy":"1f93d","shortnames":[":water_polo:"],"category":"activity"},":person_pouting:":{"uc_base":"1f64e","uc_output":"1f64e","uc_match":"1f64e","uc_greedy":"1f64e","shortnames":[":person_with_pouting_face:"],"category":"people"},":person_raising_hand:":{"uc_base":"1f64b","uc_output":"1f64b","uc_match":"1f64b","uc_greedy":"1f64b","shortnames":[":raising_hand:"],"category":"people"},":person_rowing_boat:":{"uc_base":"1f6a3","uc_output":"1f6a3","uc_match":"1f6a3","uc_greedy":"1f6a3","shortnames":[":rowboat:"],"category":"activity"},":person_running:":{"uc_base":"1f3c3","uc_output":"1f3c3","uc_match":"1f3c3","uc_greedy":"1f3c3","shortnames":[":runner:"],"category":"people"},":person_shrugging:":{"uc_base":"1f937","uc_output":"1f937","uc_match":"1f937","uc_greedy":"1f937","shortnames":[":shrug:"],"category":"people"},":person_surfing:":{"uc_base":"1f3c4","uc_output":"1f3c4","uc_match":"1f3c4","uc_greedy":"1f3c4","shortnames":[":surfer:"],"category":"activity"},":person_swimming:":{"uc_base":"1f3ca","uc_output":"1f3ca","uc_match":"1f3ca","uc_greedy":"1f3ca","shortnames":[":swimmer:"],"category":"activity"},":person_tipping_hand:":{"uc_base":"1f481","uc_output":"1f481","uc_match":"1f481","uc_greedy":"1f481","shortnames":[":information_desk_person:"],"category":"people"},":person_walking:":{"uc_base":"1f6b6","uc_output":"1f6b6","uc_match":"1f6b6","uc_greedy":"1f6b6","shortnames":[":walking:"],"category":"people"},":person_wearing_turban:":{"uc_base":"1f473","uc_output":"1f473","uc_match":"1f473","uc_greedy":"1f473","shortnames":[":man_with_turban:"],"category":"people"},":pie:":{"uc_base":"1f967","uc_output":"1f967","uc_match":"1f967","uc_greedy":"1f967","shortnames":[],"category":"food"},":pig2:":{"uc_base":"1f416","uc_output":"1f416","uc_match":"1f416","uc_greedy":"1f416","shortnames":[],"category":"nature"},":pig:":{"uc_base":"1f437","uc_output":"1f437","uc_match":"1f437","uc_greedy":"1f437","shortnames":[],"category":"nature"},":pig_nose:":{"uc_base":"1f43d","uc_output":"1f43d","uc_match":"1f43d","uc_greedy":"1f43d","shortnames":[],"category":"nature"},":pill:":{"uc_base":"1f48a","uc_output":"1f48a","uc_match":"1f48a","uc_greedy":"1f48a","shortnames":[],"category":"objects"},":pineapple:":{"uc_base":"1f34d","uc_output":"1f34d","uc_match":"1f34d","uc_greedy":"1f34d","shortnames":[],"category":"food"},":ping_pong:":{"uc_base":"1f3d3","uc_output":"1f3d3","uc_match":"1f3d3","uc_greedy":"1f3d3","shortnames":[":table_tennis:"],"category":"activity"},":pizza:":{"uc_base":"1f355","uc_output":"1f355","uc_match":"1f355","uc_greedy":"1f355","shortnames":[],"category":"food"},":place_of_worship:":{"uc_base":"1f6d0","uc_output":"1f6d0","uc_match":"1f6d0","uc_greedy":"1f6d0","shortnames":[":worship_symbol:"],"category":"symbols"},":point_down:":{"uc_base":"1f447","uc_output":"1f447","uc_match":"1f447","uc_greedy":"1f447","shortnames":[],"category":"people"},":point_left:":{"uc_base":"1f448","uc_output":"1f448","uc_match":"1f448","uc_greedy":"1f448","shortnames":[],"category":"people"},":point_right:":{"uc_base":"1f449","uc_output":"1f449","uc_match":"1f449","uc_greedy":"1f449","shortnames":[],"category":"people"},":point_up_2:":{"uc_base":"1f446","uc_output":"1f446","uc_match":"1f446","uc_greedy":"1f446","shortnames":[],"category":"people"},":police_car:":{"uc_base":"1f693","uc_output":"1f693","uc_match":"1f693","uc_greedy":"1f693","shortnames":[],"category":"travel"},":police_officer:":{"uc_base":"1f46e","uc_output":"1f46e","uc_match":"1f46e","uc_greedy":"1f46e","shortnames":[":cop:"],"category":"people"},":poodle:":{"uc_base":"1f429","uc_output":"1f429","uc_match":"1f429","uc_greedy":"1f429","shortnames":[],"category":"nature"},":poop:":{"uc_base":"1f4a9","uc_output":"1f4a9","uc_match":"1f4a9","uc_greedy":"1f4a9","shortnames":[":shit:",":hankey:",":poo:"],"category":"people"},":popcorn:":{"uc_base":"1f37f","uc_output":"1f37f","uc_match":"1f37f","uc_greedy":"1f37f","shortnames":[],"category":"food"},":post_office:":{"uc_base":"1f3e3","uc_output":"1f3e3","uc_match":"1f3e3","uc_greedy":"1f3e3","shortnames":[],"category":"travel"},":postal_horn:":{"uc_base":"1f4ef","uc_output":"1f4ef","uc_match":"1f4ef","uc_greedy":"1f4ef","shortnames":[],"category":"objects"},":postbox:":{"uc_base":"1f4ee","uc_output":"1f4ee","uc_match":"1f4ee","uc_greedy":"1f4ee","shortnames":[],"category":"objects"},":potable_water:":{"uc_base":"1f6b0","uc_output":"1f6b0","uc_match":"1f6b0","uc_greedy":"1f6b0","shortnames":[],"category":"objects"},":potato:":{"uc_base":"1f954","uc_output":"1f954","uc_match":"1f954","uc_greedy":"1f954","shortnames":[],"category":"food"},":pouch:":{"uc_base":"1f45d","uc_output":"1f45d","uc_match":"1f45d","uc_greedy":"1f45d","shortnames":[],"category":"people"},":poultry_leg:":{"uc_base":"1f357","uc_output":"1f357","uc_match":"1f357","uc_greedy":"1f357","shortnames":[],"category":"food"},":pound:":{"uc_base":"1f4b7","uc_output":"1f4b7","uc_match":"1f4b7","uc_greedy":"1f4b7","shortnames":[],"category":"objects"},":pouting_cat:":{"uc_base":"1f63e","uc_output":"1f63e","uc_match":"1f63e","uc_greedy":"1f63e","shortnames":[],"category":"people"},":pray:":{"uc_base":"1f64f","uc_output":"1f64f","uc_match":"1f64f","uc_greedy":"1f64f","shortnames":[],"category":"people"},":prayer_beads:":{"uc_base":"1f4ff","uc_output":"1f4ff","uc_match":"1f4ff","uc_greedy":"1f4ff","shortnames":[],"category":"objects"},":pregnant_woman:":{"uc_base":"1f930","uc_output":"1f930","uc_match":"1f930","uc_greedy":"1f930","shortnames":[":expecting_woman:"],"category":"people"},":pretzel:":{"uc_base":"1f968","uc_output":"1f968","uc_match":"1f968","uc_greedy":"1f968","shortnames":[],"category":"food"},":prince:":{"uc_base":"1f934","uc_output":"1f934","uc_match":"1f934","uc_greedy":"1f934","shortnames":[],"category":"people"},":princess:":{"uc_base":"1f478","uc_output":"1f478","uc_match":"1f478","uc_greedy":"1f478","shortnames":[],"category":"people"},":punch:":{"uc_base":"1f44a","uc_output":"1f44a","uc_match":"1f44a","uc_greedy":"1f44a","shortnames":[],"category":"people"},":purple_heart:":{"uc_base":"1f49c","uc_output":"1f49c","uc_match":"1f49c","uc_greedy":"1f49c","shortnames":[],"category":"symbols"},":purse:":{"uc_base":"1f45b","uc_output":"1f45b","uc_match":"1f45b","uc_greedy":"1f45b","shortnames":[],"category":"people"},":pushpin:":{"uc_base":"1f4cc","uc_output":"1f4cc","uc_match":"1f4cc","uc_greedy":"1f4cc","shortnames":[],"category":"objects"},":put_litter_in_its_place:":{"uc_base":"1f6ae","uc_output":"1f6ae","uc_match":"1f6ae","uc_greedy":"1f6ae","shortnames":[],"category":"symbols"},":rabbit2:":{"uc_base":"1f407","uc_output":"1f407","uc_match":"1f407","uc_greedy":"1f407","shortnames":[],"category":"nature"},":rabbit:":{"uc_base":"1f430","uc_output":"1f430","uc_match":"1f430","uc_greedy":"1f430","shortnames":[],"category":"nature"},":racehorse:":{"uc_base":"1f40e","uc_output":"1f40e","uc_match":"1f40e","uc_greedy":"1f40e","shortnames":[],"category":"nature"},":radio:":{"uc_base":"1f4fb","uc_output":"1f4fb","uc_match":"1f4fb","uc_greedy":"1f4fb","shortnames":[],"category":"objects"},":radio_button:":{"uc_base":"1f518","uc_output":"1f518","uc_match":"1f518","uc_greedy":"1f518","shortnames":[],"category":"symbols"},":rage:":{"uc_base":"1f621","uc_output":"1f621","uc_match":"1f621","uc_greedy":"1f621","shortnames":[],"category":"people"},":railway_car:":{"uc_base":"1f683","uc_output":"1f683","uc_match":"1f683","uc_greedy":"1f683","shortnames":[],"category":"travel"},":rainbow:":{"uc_base":"1f308","uc_output":"1f308","uc_match":"1f308","uc_greedy":"1f308","shortnames":[],"category":"nature"},":raised_back_of_hand:":{"uc_base":"1f91a","uc_output":"1f91a","uc_match":"1f91a","uc_greedy":"1f91a","shortnames":[":back_of_hand:"],"category":"people"},":raised_hands:":{"uc_base":"1f64c","uc_output":"1f64c","uc_match":"1f64c","uc_greedy":"1f64c","shortnames":[],"category":"people"},":ram:":{"uc_base":"1f40f","uc_output":"1f40f","uc_match":"1f40f","uc_greedy":"1f40f","shortnames":[],"category":"nature"},":ramen:":{"uc_base":"1f35c","uc_output":"1f35c","uc_match":"1f35c","uc_greedy":"1f35c","shortnames":[],"category":"food"},":rat:":{"uc_base":"1f400","uc_output":"1f400","uc_match":"1f400","uc_greedy":"1f400","shortnames":[],"category":"nature"},":red_car:":{"uc_base":"1f697","uc_output":"1f697","uc_match":"1f697","uc_greedy":"1f697","shortnames":[],"category":"travel"},":red_circle:":{"uc_base":"1f534","uc_output":"1f534","uc_match":"1f534","uc_greedy":"1f534","shortnames":[],"category":"symbols"},":regional_indicator_a:":{"uc_base":"1f1e6","uc_output":"1f1e6","uc_match":"1f1e6","uc_greedy":"1f1e6","shortnames":[],"category":"regional"},":regional_indicator_b:":{"uc_base":"1f1e7","uc_output":"1f1e7","uc_match":"1f1e7","uc_greedy":"1f1e7","shortnames":[],"category":"regional"},":regional_indicator_c:":{"uc_base":"1f1e8","uc_output":"1f1e8","uc_match":"1f1e8","uc_greedy":"1f1e8","shortnames":[],"category":"regional"},":regional_indicator_d:":{"uc_base":"1f1e9","uc_output":"1f1e9","uc_match":"1f1e9","uc_greedy":"1f1e9","shortnames":[],"category":"regional"},":regional_indicator_e:":{"uc_base":"1f1ea","uc_output":"1f1ea","uc_match":"1f1ea","uc_greedy":"1f1ea","shortnames":[],"category":"regional"},":regional_indicator_f:":{"uc_base":"1f1eb","uc_output":"1f1eb","uc_match":"1f1eb","uc_greedy":"1f1eb","shortnames":[],"category":"regional"},":regional_indicator_g:":{"uc_base":"1f1ec","uc_output":"1f1ec","uc_match":"1f1ec","uc_greedy":"1f1ec","shortnames":[],"category":"regional"},":regional_indicator_h:":{"uc_base":"1f1ed","uc_output":"1f1ed","uc_match":"1f1ed","uc_greedy":"1f1ed","shortnames":[],"category":"regional"},":regional_indicator_i:":{"uc_base":"1f1ee","uc_output":"1f1ee","uc_match":"1f1ee","uc_greedy":"1f1ee","shortnames":[],"category":"regional"},":regional_indicator_j:":{"uc_base":"1f1ef","uc_output":"1f1ef","uc_match":"1f1ef","uc_greedy":"1f1ef","shortnames":[],"category":"regional"},":regional_indicator_k:":{"uc_base":"1f1f0","uc_output":"1f1f0","uc_match":"1f1f0","uc_greedy":"1f1f0","shortnames":[],"category":"regional"},":regional_indicator_l:":{"uc_base":"1f1f1","uc_output":"1f1f1","uc_match":"1f1f1","uc_greedy":"1f1f1","shortnames":[],"category":"regional"},":regional_indicator_m:":{"uc_base":"1f1f2","uc_output":"1f1f2","uc_match":"1f1f2","uc_greedy":"1f1f2","shortnames":[],"category":"regional"},":regional_indicator_n:":{"uc_base":"1f1f3","uc_output":"1f1f3","uc_match":"1f1f3","uc_greedy":"1f1f3","shortnames":[],"category":"regional"},":regional_indicator_o:":{"uc_base":"1f1f4","uc_output":"1f1f4","uc_match":"1f1f4","uc_greedy":"1f1f4","shortnames":[],"category":"regional"},":regional_indicator_p:":{"uc_base":"1f1f5","uc_output":"1f1f5","uc_match":"1f1f5","uc_greedy":"1f1f5","shortnames":[],"category":"regional"},":regional_indicator_q:":{"uc_base":"1f1f6","uc_output":"1f1f6","uc_match":"1f1f6","uc_greedy":"1f1f6","shortnames":[],"category":"regional"},":regional_indicator_r:":{"uc_base":"1f1f7","uc_output":"1f1f7","uc_match":"1f1f7","uc_greedy":"1f1f7","shortnames":[],"category":"regional"},":regional_indicator_s:":{"uc_base":"1f1f8","uc_output":"1f1f8","uc_match":"1f1f8","uc_greedy":"1f1f8","shortnames":[],"category":"regional"},":regional_indicator_t:":{"uc_base":"1f1f9","uc_output":"1f1f9","uc_match":"1f1f9","uc_greedy":"1f1f9","shortnames":[],"category":"regional"},":regional_indicator_u:":{"uc_base":"1f1fa","uc_output":"1f1fa","uc_match":"1f1fa","uc_greedy":"1f1fa","shortnames":[],"category":"regional"},":regional_indicator_v:":{"uc_base":"1f1fb","uc_output":"1f1fb","uc_match":"1f1fb","uc_greedy":"1f1fb","shortnames":[],"category":"regional"},":regional_indicator_w:":{"uc_base":"1f1fc","uc_output":"1f1fc","uc_match":"1f1fc","uc_greedy":"1f1fc","shortnames":[],"category":"regional"},":regional_indicator_x:":{"uc_base":"1f1fd","uc_output":"1f1fd","uc_match":"1f1fd","uc_greedy":"1f1fd","shortnames":[],"category":"regional"},":regional_indicator_y:":{"uc_base":"1f1fe","uc_output":"1f1fe","uc_match":"1f1fe","uc_greedy":"1f1fe","shortnames":[],"category":"regional"},":regional_indicator_z:":{"uc_base":"1f1ff","uc_output":"1f1ff","uc_match":"1f1ff","uc_greedy":"1f1ff","shortnames":[],"category":"regional"},":relieved:":{"uc_base":"1f60c","uc_output":"1f60c","uc_match":"1f60c","uc_greedy":"1f60c","shortnames":[],"category":"people"},":repeat:":{"uc_base":"1f501","uc_output":"1f501","uc_match":"1f501","uc_greedy":"1f501","shortnames":[],"category":"symbols"},":repeat_one:":{"uc_base":"1f502","uc_output":"1f502","uc_match":"1f502","uc_greedy":"1f502","shortnames":[],"category":"symbols"},":restroom:":{"uc_base":"1f6bb","uc_output":"1f6bb","uc_match":"1f6bb","uc_greedy":"1f6bb","shortnames":[],"category":"symbols"},":revolving_hearts:":{"uc_base":"1f49e","uc_output":"1f49e","uc_match":"1f49e","uc_greedy":"1f49e","shortnames":[],"category":"symbols"},":rhino:":{"uc_base":"1f98f","uc_output":"1f98f","uc_match":"1f98f","uc_greedy":"1f98f","shortnames":[":rhinoceros:"],"category":"nature"},":ribbon:":{"uc_base":"1f380","uc_output":"1f380","uc_match":"1f380","uc_greedy":"1f380","shortnames":[],"category":"objects"},":rice:":{"uc_base":"1f35a","uc_output":"1f35a","uc_match":"1f35a","uc_greedy":"1f35a","shortnames":[],"category":"food"},":rice_ball:":{"uc_base":"1f359","uc_output":"1f359","uc_match":"1f359","uc_greedy":"1f359","shortnames":[],"category":"food"},":rice_cracker:":{"uc_base":"1f358","uc_output":"1f358","uc_match":"1f358","uc_greedy":"1f358","shortnames":[],"category":"food"},":rice_scene:":{"uc_base":"1f391","uc_output":"1f391","uc_match":"1f391","uc_greedy":"1f391","shortnames":[],"category":"travel"},":right_facing_fist:":{"uc_base":"1f91c","uc_output":"1f91c","uc_match":"1f91c","uc_greedy":"1f91c","shortnames":[":right_fist:"],"category":"people"},":ring:":{"uc_base":"1f48d","uc_output":"1f48d","uc_match":"1f48d","uc_greedy":"1f48d","shortnames":[],"category":"people"},":robot:":{"uc_base":"1f916","uc_output":"1f916","uc_match":"1f916","uc_greedy":"1f916","shortnames":[":robot_face:"],"category":"people"},":rocket:":{"uc_base":"1f680","uc_output":"1f680","uc_match":"1f680","uc_greedy":"1f680","shortnames":[],"category":"travel"},":rofl:":{"uc_base":"1f923","uc_output":"1f923","uc_match":"1f923","uc_greedy":"1f923","shortnames":[":rolling_on_the_floor_laughing:"],"category":"people"},":roller_coaster:":{"uc_base":"1f3a2","uc_output":"1f3a2","uc_match":"1f3a2","uc_greedy":"1f3a2","shortnames":[],"category":"travel"},":rolling_eyes:":{"uc_base":"1f644","uc_output":"1f644","uc_match":"1f644","uc_greedy":"1f644","shortnames":[":face_with_rolling_eyes:"],"category":"people"},":rooster:":{"uc_base":"1f413","uc_output":"1f413","uc_match":"1f413","uc_greedy":"1f413","shortnames":[],"category":"nature"},":rose:":{"uc_base":"1f339","uc_output":"1f339","uc_match":"1f339","uc_greedy":"1f339","shortnames":[],"category":"nature"},":rotating_light:":{"uc_base":"1f6a8","uc_output":"1f6a8","uc_match":"1f6a8","uc_greedy":"1f6a8","shortnames":[],"category":"travel"},":round_pushpin:":{"uc_base":"1f4cd","uc_output":"1f4cd","uc_match":"1f4cd","uc_greedy":"1f4cd","shortnames":[],"category":"objects"},":rugby_football:":{"uc_base":"1f3c9","uc_output":"1f3c9","uc_match":"1f3c9","uc_greedy":"1f3c9","shortnames":[],"category":"activity"},":running_shirt_with_sash:":{"uc_base":"1f3bd","uc_output":"1f3bd","uc_match":"1f3bd","uc_greedy":"1f3bd","shortnames":[],"category":"activity"},":sake:":{"uc_base":"1f376","uc_output":"1f376","uc_match":"1f376","uc_greedy":"1f376","shortnames":[],"category":"food"},":salad:":{"uc_base":"1f957","uc_output":"1f957","uc_match":"1f957","uc_greedy":"1f957","shortnames":[":green_salad:"],"category":"food"},":sandal:":{"uc_base":"1f461","uc_output":"1f461","uc_match":"1f461","uc_greedy":"1f461","shortnames":[],"category":"people"},":sandwich:":{"uc_base":"1f96a","uc_output":"1f96a","uc_match":"1f96a","uc_greedy":"1f96a","shortnames":[],"category":"food"},":santa:":{"uc_base":"1f385","uc_output":"1f385","uc_match":"1f385","uc_greedy":"1f385","shortnames":[],"category":"people"},":satellite:":{"uc_base":"1f4e1","uc_output":"1f4e1","uc_match":"1f4e1","uc_greedy":"1f4e1","shortnames":[],"category":"objects"},":sauropod:":{"uc_base":"1f995","uc_output":"1f995","uc_match":"1f995","uc_greedy":"1f995","shortnames":[],"category":"nature"},":saxophone:":{"uc_base":"1f3b7","uc_output":"1f3b7","uc_match":"1f3b7","uc_greedy":"1f3b7","shortnames":[],"category":"activity"},":scarf:":{"uc_base":"1f9e3","uc_output":"1f9e3","uc_match":"1f9e3","uc_greedy":"1f9e3","shortnames":[],"category":"people"},":school:":{"uc_base":"1f3eb","uc_output":"1f3eb","uc_match":"1f3eb","uc_greedy":"1f3eb","shortnames":[],"category":"travel"},":school_satchel:":{"uc_base":"1f392","uc_output":"1f392","uc_match":"1f392","uc_greedy":"1f392","shortnames":[],"category":"people"},":scooter:":{"uc_base":"1f6f4","uc_output":"1f6f4","uc_match":"1f6f4","uc_greedy":"1f6f4","shortnames":[],"category":"travel"},":scorpion:":{"uc_base":"1f982","uc_output":"1f982","uc_match":"1f982","uc_greedy":"1f982","shortnames":[],"category":"nature"},":scream:":{"uc_base":"1f631","uc_output":"1f631","uc_match":"1f631","uc_greedy":"1f631","shortnames":[],"category":"people"},":scream_cat:":{"uc_base":"1f640","uc_output":"1f640","uc_match":"1f640","uc_greedy":"1f640","shortnames":[],"category":"people"},":scroll:":{"uc_base":"1f4dc","uc_output":"1f4dc","uc_match":"1f4dc","uc_greedy":"1f4dc","shortnames":[],"category":"objects"},":seat:":{"uc_base":"1f4ba","uc_output":"1f4ba","uc_match":"1f4ba","uc_greedy":"1f4ba","shortnames":[],"category":"travel"},":second_place:":{"uc_base":"1f948","uc_output":"1f948","uc_match":"1f948","uc_greedy":"1f948","shortnames":[":second_place_medal:"],"category":"activity"},":see_no_evil:":{"uc_base":"1f648","uc_output":"1f648","uc_match":"1f648","uc_greedy":"1f648","shortnames":[],"category":"nature"},":seedling:":{"uc_base":"1f331","uc_output":"1f331","uc_match":"1f331","uc_greedy":"1f331","shortnames":[],"category":"nature"},":selfie:":{"uc_base":"1f933","uc_output":"1f933","uc_match":"1f933","uc_greedy":"1f933","shortnames":[],"category":"people"},":shallow_pan_of_food:":{"uc_base":"1f958","uc_output":"1f958","uc_match":"1f958","uc_greedy":"1f958","shortnames":[":paella:"],"category":"food"},":shark:":{"uc_base":"1f988","uc_output":"1f988","uc_match":"1f988","uc_greedy":"1f988","shortnames":[],"category":"nature"},":shaved_ice:":{"uc_base":"1f367","uc_output":"1f367","uc_match":"1f367","uc_greedy":"1f367","shortnames":[],"category":"food"},":sheep:":{"uc_base":"1f411","uc_output":"1f411","uc_match":"1f411","uc_greedy":"1f411","shortnames":[],"category":"nature"},":shell:":{"uc_base":"1f41a","uc_output":"1f41a","uc_match":"1f41a","uc_greedy":"1f41a","shortnames":[],"category":"nature"},":ship:":{"uc_base":"1f6a2","uc_output":"1f6a2","uc_match":"1f6a2","uc_greedy":"1f6a2","shortnames":[],"category":"travel"},":shirt:":{"uc_base":"1f455","uc_output":"1f455","uc_match":"1f455","uc_greedy":"1f455","shortnames":[],"category":"people"},":shopping_cart:":{"uc_base":"1f6d2","uc_output":"1f6d2","uc_match":"1f6d2","uc_greedy":"1f6d2","shortnames":[":shopping_trolley:"],"category":"objects"},":shower:":{"uc_base":"1f6bf","uc_output":"1f6bf","uc_match":"1f6bf","uc_greedy":"1f6bf","shortnames":[],"category":"objects"},":shrimp:":{"uc_base":"1f990","uc_output":"1f990","uc_match":"1f990","uc_greedy":"1f990","shortnames":[],"category":"nature"},":shushing_face:":{"uc_base":"1f92b","uc_output":"1f92b","uc_match":"1f92b","uc_greedy":"1f92b","shortnames":[],"category":"people"},":signal_strength:":{"uc_base":"1f4f6","uc_output":"1f4f6","uc_match":"1f4f6","uc_greedy":"1f4f6","shortnames":[],"category":"symbols"},":six_pointed_star:":{"uc_base":"1f52f","uc_output":"1f52f","uc_match":"1f52f","uc_greedy":"1f52f","shortnames":[],"category":"symbols"},":ski:":{"uc_base":"1f3bf","uc_output":"1f3bf","uc_match":"1f3bf","uc_greedy":"1f3bf","shortnames":[],"category":"activity"},":skull:":{"uc_base":"1f480","uc_output":"1f480","uc_match":"1f480","uc_greedy":"1f480","shortnames":[":skeleton:"],"category":"people"},":sled:":{"uc_base":"1f6f7","uc_output":"1f6f7","uc_match":"1f6f7","uc_greedy":"1f6f7","shortnames":[],"category":"activity"},":sleeping:":{"uc_base":"1f634","uc_output":"1f634","uc_match":"1f634","uc_greedy":"1f634","shortnames":[],"category":"people"},":sleeping_accommodation:":{"uc_base":"1f6cc","uc_output":"1f6cc","uc_match":"1f6cc","uc_greedy":"1f6cc","shortnames":[],"category":"objects"},":sleepy:":{"uc_base":"1f62a","uc_output":"1f62a","uc_match":"1f62a","uc_greedy":"1f62a","shortnames":[],"category":"people"},":slight_frown:":{"uc_base":"1f641","uc_output":"1f641","uc_match":"1f641","uc_greedy":"1f641","shortnames":[":slightly_frowning_face:"],"category":"people"},":slight_smile:":{"uc_base":"1f642","uc_output":"1f642","uc_match":"1f642","uc_greedy":"1f642","shortnames":[":slightly_smiling_face:"],"category":"people"},":slot_machine:":{"uc_base":"1f3b0","uc_output":"1f3b0","uc_match":"1f3b0","uc_greedy":"1f3b0","shortnames":[],"category":"activity"},":small_blue_diamond:":{"uc_base":"1f539","uc_output":"1f539","uc_match":"1f539","uc_greedy":"1f539","shortnames":[],"category":"symbols"},":small_orange_diamond:":{"uc_base":"1f538","uc_output":"1f538","uc_match":"1f538","uc_greedy":"1f538","shortnames":[],"category":"symbols"},":small_red_triangle:":{"uc_base":"1f53a","uc_output":"1f53a","uc_match":"1f53a","uc_greedy":"1f53a","shortnames":[],"category":"symbols"},":small_red_triangle_down:":{"uc_base":"1f53b","uc_output":"1f53b","uc_match":"1f53b","uc_greedy":"1f53b","shortnames":[],"category":"symbols"},":smile:":{"uc_base":"1f604","uc_output":"1f604","uc_match":"1f604","uc_greedy":"1f604","shortnames":[],"category":"people"},":smile_cat:":{"uc_base":"1f638","uc_output":"1f638","uc_match":"1f638","uc_greedy":"1f638","shortnames":[],"category":"people"},":smiley:":{"uc_base":"1f603","uc_output":"1f603","uc_match":"1f603","uc_greedy":"1f603","shortnames":[],"category":"people"},":smiley_cat:":{"uc_base":"1f63a","uc_output":"1f63a","uc_match":"1f63a","uc_greedy":"1f63a","shortnames":[],"category":"people"},":smiling_imp:":{"uc_base":"1f608","uc_output":"1f608","uc_match":"1f608","uc_greedy":"1f608","shortnames":[],"category":"people"},":smirk:":{"uc_base":"1f60f","uc_output":"1f60f","uc_match":"1f60f","uc_greedy":"1f60f","shortnames":[],"category":"people"},":smirk_cat:":{"uc_base":"1f63c","uc_output":"1f63c","uc_match":"1f63c","uc_greedy":"1f63c","shortnames":[],"category":"people"},":smoking:":{"uc_base":"1f6ac","uc_output":"1f6ac","uc_match":"1f6ac","uc_greedy":"1f6ac","shortnames":[],"category":"objects"},":snail:":{"uc_base":"1f40c","uc_output":"1f40c","uc_match":"1f40c","uc_greedy":"1f40c","shortnames":[],"category":"nature"},":snake:":{"uc_base":"1f40d","uc_output":"1f40d","uc_match":"1f40d","uc_greedy":"1f40d","shortnames":[],"category":"nature"},":sneezing_face:":{"uc_base":"1f927","uc_output":"1f927","uc_match":"1f927","uc_greedy":"1f927","shortnames":[":sneeze:"],"category":"people"},":snowboarder:":{"uc_base":"1f3c2","uc_output":"1f3c2","uc_match":"1f3c2","uc_greedy":"1f3c2","shortnames":[],"category":"activity"},":sob:":{"uc_base":"1f62d","uc_output":"1f62d","uc_match":"1f62d","uc_greedy":"1f62d","shortnames":[],"category":"people"},":socks:":{"uc_base":"1f9e6","uc_output":"1f9e6","uc_match":"1f9e6","uc_greedy":"1f9e6","shortnames":[],"category":"people"},":soon:":{"uc_base":"1f51c","uc_output":"1f51c","uc_match":"1f51c","uc_greedy":"1f51c","shortnames":[],"category":"symbols"},":sos:":{"uc_base":"1f198","uc_output":"1f198","uc_match":"1f198","uc_greedy":"1f198","shortnames":[],"category":"symbols"},":sound:":{"uc_base":"1f509","uc_output":"1f509","uc_match":"1f509","uc_greedy":"1f509","shortnames":[],"category":"symbols"},":space_invader:":{"uc_base":"1f47e","uc_output":"1f47e","uc_match":"1f47e","uc_greedy":"1f47e","shortnames":[],"category":"people"},":spaghetti:":{"uc_base":"1f35d","uc_output":"1f35d","uc_match":"1f35d","uc_greedy":"1f35d","shortnames":[],"category":"food"},":sparkler:":{"uc_base":"1f387","uc_output":"1f387","uc_match":"1f387","uc_greedy":"1f387","shortnames":[],"category":"travel"},":sparkling_heart:":{"uc_base":"1f496","uc_output":"1f496","uc_match":"1f496","uc_greedy":"1f496","shortnames":[],"category":"symbols"},":speak_no_evil:":{"uc_base":"1f64a","uc_output":"1f64a","uc_match":"1f64a","uc_greedy":"1f64a","shortnames":[],"category":"nature"},":speaker:":{"uc_base":"1f508","uc_output":"1f508","uc_match":"1f508","uc_greedy":"1f508","shortnames":[],"category":"symbols"},":speech_balloon:":{"uc_base":"1f4ac","uc_output":"1f4ac","uc_match":"1f4ac","uc_greedy":"1f4ac","shortnames":[],"category":"symbols"},":speedboat:":{"uc_base":"1f6a4","uc_output":"1f6a4","uc_match":"1f6a4","uc_greedy":"1f6a4","shortnames":[],"category":"travel"},":spoon:":{"uc_base":"1f944","uc_output":"1f944","uc_match":"1f944","uc_greedy":"1f944","shortnames":[],"category":"food"},":squid:":{"uc_base":"1f991","uc_output":"1f991","uc_match":"1f991","uc_greedy":"1f991","shortnames":[],"category":"nature"},":star2:":{"uc_base":"1f31f","uc_output":"1f31f","uc_match":"1f31f","uc_greedy":"1f31f","shortnames":[],"category":"nature"},":star_struck:":{"uc_base":"1f929","uc_output":"1f929","uc_match":"1f929","uc_greedy":"1f929","shortnames":[],"category":"people"},":stars:":{"uc_base":"1f320","uc_output":"1f320","uc_match":"1f320","uc_greedy":"1f320","shortnames":[],"category":"travel"},":station:":{"uc_base":"1f689","uc_output":"1f689","uc_match":"1f689","uc_greedy":"1f689","shortnames":[],"category":"travel"},":statue_of_liberty:":{"uc_base":"1f5fd","uc_output":"1f5fd","uc_match":"1f5fd","uc_greedy":"1f5fd","shortnames":[],"category":"travel"},":steam_locomotive:":{"uc_base":"1f682","uc_output":"1f682","uc_match":"1f682","uc_greedy":"1f682","shortnames":[],"category":"travel"},":stew:":{"uc_base":"1f372","uc_output":"1f372","uc_match":"1f372","uc_greedy":"1f372","shortnames":[],"category":"food"},":straight_ruler:":{"uc_base":"1f4cf","uc_output":"1f4cf","uc_match":"1f4cf","uc_greedy":"1f4cf","shortnames":[],"category":"objects"},":strawberry:":{"uc_base":"1f353","uc_output":"1f353","uc_match":"1f353","uc_greedy":"1f353","shortnames":[],"category":"food"},":stuck_out_tongue:":{"uc_base":"1f61b","uc_output":"1f61b","uc_match":"1f61b","uc_greedy":"1f61b","shortnames":[],"category":"people"},":stuck_out_tongue_closed_eyes:":{"uc_base":"1f61d","uc_output":"1f61d","uc_match":"1f61d","uc_greedy":"1f61d","shortnames":[],"category":"people"},":stuck_out_tongue_winking_eye:":{"uc_base":"1f61c","uc_output":"1f61c","uc_match":"1f61c","uc_greedy":"1f61c","shortnames":[],"category":"people"},":stuffed_flatbread:":{"uc_base":"1f959","uc_output":"1f959","uc_match":"1f959","uc_greedy":"1f959","shortnames":[":stuffed_pita:"],"category":"food"},":sun_with_face:":{"uc_base":"1f31e","uc_output":"1f31e","uc_match":"1f31e","uc_greedy":"1f31e","shortnames":[],"category":"nature"},":sunflower:":{"uc_base":"1f33b","uc_output":"1f33b","uc_match":"1f33b","uc_greedy":"1f33b","shortnames":[],"category":"nature"},":sunglasses:":{"uc_base":"1f60e","uc_output":"1f60e","uc_match":"1f60e","uc_greedy":"1f60e","shortnames":[],"category":"people"},":sunrise:":{"uc_base":"1f305","uc_output":"1f305","uc_match":"1f305","uc_greedy":"1f305","shortnames":[],"category":"travel"},":sunrise_over_mountains:":{"uc_base":"1f304","uc_output":"1f304","uc_match":"1f304","uc_greedy":"1f304","shortnames":[],"category":"travel"},":sushi:":{"uc_base":"1f363","uc_output":"1f363","uc_match":"1f363","uc_greedy":"1f363","shortnames":[],"category":"food"},":suspension_railway:":{"uc_base":"1f69f","uc_output":"1f69f","uc_match":"1f69f","uc_greedy":"1f69f","shortnames":[],"category":"travel"},":sweat:":{"uc_base":"1f613","uc_output":"1f613","uc_match":"1f613","uc_greedy":"1f613","shortnames":[],"category":"people"},":sweat_drops:":{"uc_base":"1f4a6","uc_output":"1f4a6","uc_match":"1f4a6","uc_greedy":"1f4a6","shortnames":[],"category":"nature"},":sweat_smile:":{"uc_base":"1f605","uc_output":"1f605","uc_match":"1f605","uc_greedy":"1f605","shortnames":[],"category":"people"},":sweet_potato:":{"uc_base":"1f360","uc_output":"1f360","uc_match":"1f360","uc_greedy":"1f360","shortnames":[],"category":"food"},":symbols:":{"uc_base":"1f523","uc_output":"1f523","uc_match":"1f523","uc_greedy":"1f523","shortnames":[],"category":"symbols"},":synagogue:":{"uc_base":"1f54d","uc_output":"1f54d","uc_match":"1f54d","uc_greedy":"1f54d","shortnames":[],"category":"travel"},":syringe:":{"uc_base":"1f489","uc_output":"1f489","uc_match":"1f489","uc_greedy":"1f489","shortnames":[],"category":"objects"},":t_rex:":{"uc_base":"1f996","uc_output":"1f996","uc_match":"1f996","uc_greedy":"1f996","shortnames":[],"category":"nature"},":taco:":{"uc_base":"1f32e","uc_output":"1f32e","uc_match":"1f32e","uc_greedy":"1f32e","shortnames":[],"category":"food"},":tada:":{"uc_base":"1f389","uc_output":"1f389","uc_match":"1f389","uc_greedy":"1f389","shortnames":[],"category":"objects"},":takeout_box:":{"uc_base":"1f961","uc_output":"1f961","uc_match":"1f961","uc_greedy":"1f961","shortnames":[],"category":"food"},":tanabata_tree:":{"uc_base":"1f38b","uc_output":"1f38b","uc_match":"1f38b","uc_greedy":"1f38b","shortnames":[],"category":"nature"},":tangerine:":{"uc_base":"1f34a","uc_output":"1f34a","uc_match":"1f34a","uc_greedy":"1f34a","shortnames":[],"category":"food"},":taxi:":{"uc_base":"1f695","uc_output":"1f695","uc_match":"1f695","uc_greedy":"1f695","shortnames":[],"category":"travel"},":tea:":{"uc_base":"1f375","uc_output":"1f375","uc_match":"1f375","uc_greedy":"1f375","shortnames":[],"category":"food"},":telephone_receiver:":{"uc_base":"1f4de","uc_output":"1f4de","uc_match":"1f4de","uc_greedy":"1f4de","shortnames":[],"category":"objects"},":telescope:":{"uc_base":"1f52d","uc_output":"1f52d","uc_match":"1f52d","uc_greedy":"1f52d","shortnames":[],"category":"objects"},":tennis:":{"uc_base":"1f3be","uc_output":"1f3be","uc_match":"1f3be","uc_greedy":"1f3be","shortnames":[],"category":"activity"},":thermometer_face:":{"uc_base":"1f912","uc_output":"1f912","uc_match":"1f912","uc_greedy":"1f912","shortnames":[":face_with_thermometer:"],"category":"people"},":thinking:":{"uc_base":"1f914","uc_output":"1f914","uc_match":"1f914","uc_greedy":"1f914","shortnames":[":thinking_face:"],"category":"people"},":third_place:":{"uc_base":"1f949","uc_output":"1f949","uc_match":"1f949","uc_greedy":"1f949","shortnames":[":third_place_medal:"],"category":"activity"},":thought_balloon:":{"uc_base":"1f4ad","uc_output":"1f4ad","uc_match":"1f4ad","uc_greedy":"1f4ad","shortnames":[],"category":"symbols"},":thumbsdown:":{"uc_base":"1f44e","uc_output":"1f44e","uc_match":"1f44e","uc_greedy":"1f44e","shortnames":[":-1:",":thumbdown:"],"category":"people"},":thumbsup:":{"uc_base":"1f44d","uc_output":"1f44d","uc_match":"1f44d","uc_greedy":"1f44d","shortnames":[":+1:",":thumbup:"],"category":"people"},":ticket:":{"uc_base":"1f3ab","uc_output":"1f3ab","uc_match":"1f3ab","uc_greedy":"1f3ab","shortnames":[],"category":"activity"},":tiger2:":{"uc_base":"1f405","uc_output":"1f405","uc_match":"1f405","uc_greedy":"1f405","shortnames":[],"category":"nature"},":tiger:":{"uc_base":"1f42f","uc_output":"1f42f","uc_match":"1f42f","uc_greedy":"1f42f","shortnames":[],"category":"nature"},":tired_face:":{"uc_base":"1f62b","uc_output":"1f62b","uc_match":"1f62b","uc_greedy":"1f62b","shortnames":[],"category":"people"},":toilet:":{"uc_base":"1f6bd","uc_output":"1f6bd","uc_match":"1f6bd","uc_greedy":"1f6bd","shortnames":[],"category":"objects"},":tokyo_tower:":{"uc_base":"1f5fc","uc_output":"1f5fc","uc_match":"1f5fc","uc_greedy":"1f5fc","shortnames":[],"category":"travel"},":tomato:":{"uc_base":"1f345","uc_output":"1f345","uc_match":"1f345","uc_greedy":"1f345","shortnames":[],"category":"food"},":tone1:":{"uc_base":"1f3fb","uc_output":"1f3fb","uc_match":"1f3fb","uc_greedy":"1f3fb","shortnames":[],"category":"modifier"},":tone2:":{"uc_base":"1f3fc","uc_output":"1f3fc","uc_match":"1f3fc","uc_greedy":"1f3fc","shortnames":[],"category":"modifier"},":tone3:":{"uc_base":"1f3fd","uc_output":"1f3fd","uc_match":"1f3fd","uc_greedy":"1f3fd","shortnames":[],"category":"modifier"},":tone4:":{"uc_base":"1f3fe","uc_output":"1f3fe","uc_match":"1f3fe","uc_greedy":"1f3fe","shortnames":[],"category":"modifier"},":tone5:":{"uc_base":"1f3ff","uc_output":"1f3ff","uc_match":"1f3ff","uc_greedy":"1f3ff","shortnames":[],"category":"modifier"},":tongue:":{"uc_base":"1f445","uc_output":"1f445","uc_match":"1f445","uc_greedy":"1f445","shortnames":[],"category":"people"},":top:":{"uc_base":"1f51d","uc_output":"1f51d","uc_match":"1f51d","uc_greedy":"1f51d","shortnames":[],"category":"symbols"},":tophat:":{"uc_base":"1f3a9","uc_output":"1f3a9","uc_match":"1f3a9","uc_greedy":"1f3a9","shortnames":[],"category":"people"},":tractor:":{"uc_base":"1f69c","uc_output":"1f69c","uc_match":"1f69c","uc_greedy":"1f69c","shortnames":[],"category":"travel"},":traffic_light:":{"uc_base":"1f6a5","uc_output":"1f6a5","uc_match":"1f6a5","uc_greedy":"1f6a5","shortnames":[],"category":"travel"},":train2:":{"uc_base":"1f686","uc_output":"1f686","uc_match":"1f686","uc_greedy":"1f686","shortnames":[],"category":"travel"},":train:":{"uc_base":"1f68b","uc_output":"1f68b","uc_match":"1f68b","uc_greedy":"1f68b","shortnames":[],"category":"travel"},":tram:":{"uc_base":"1f68a","uc_output":"1f68a","uc_match":"1f68a","uc_greedy":"1f68a","shortnames":[],"category":"travel"},":triangular_flag_on_post:":{"uc_base":"1f6a9","uc_output":"1f6a9","uc_match":"1f6a9","uc_greedy":"1f6a9","shortnames":[],"category":"flags"},":triangular_ruler:":{"uc_base":"1f4d0","uc_output":"1f4d0","uc_match":"1f4d0","uc_greedy":"1f4d0","shortnames":[],"category":"objects"},":trident:":{"uc_base":"1f531","uc_output":"1f531","uc_match":"1f531","uc_greedy":"1f531","shortnames":[],"category":"symbols"},":triumph:":{"uc_base":"1f624","uc_output":"1f624","uc_match":"1f624","uc_greedy":"1f624","shortnames":[],"category":"people"},":trolleybus:":{"uc_base":"1f68e","uc_output":"1f68e","uc_match":"1f68e","uc_greedy":"1f68e","shortnames":[],"category":"travel"},":trophy:":{"uc_base":"1f3c6","uc_output":"1f3c6","uc_match":"1f3c6","uc_greedy":"1f3c6","shortnames":[],"category":"activity"},":tropical_drink:":{"uc_base":"1f379","uc_output":"1f379","uc_match":"1f379","uc_greedy":"1f379","shortnames":[],"category":"food"},":tropical_fish:":{"uc_base":"1f420","uc_output":"1f420","uc_match":"1f420","uc_greedy":"1f420","shortnames":[],"category":"nature"},":truck:":{"uc_base":"1f69a","uc_output":"1f69a","uc_match":"1f69a","uc_greedy":"1f69a","shortnames":[],"category":"travel"},":trumpet:":{"uc_base":"1f3ba","uc_output":"1f3ba","uc_match":"1f3ba","uc_greedy":"1f3ba","shortnames":[],"category":"activity"},":tulip:":{"uc_base":"1f337","uc_output":"1f337","uc_match":"1f337","uc_greedy":"1f337","shortnames":[],"category":"nature"},":tumbler_glass:":{"uc_base":"1f943","uc_output":"1f943","uc_match":"1f943","uc_greedy":"1f943","shortnames":[":whisky:"],"category":"food"},":turkey:":{"uc_base":"1f983","uc_output":"1f983","uc_match":"1f983","uc_greedy":"1f983","shortnames":[],"category":"nature"},":turtle:":{"uc_base":"1f422","uc_output":"1f422","uc_match":"1f422","uc_greedy":"1f422","shortnames":[],"category":"nature"},":tv:":{"uc_base":"1f4fa","uc_output":"1f4fa","uc_match":"1f4fa","uc_greedy":"1f4fa","shortnames":[],"category":"objects"},":twisted_rightwards_arrows:":{"uc_base":"1f500","uc_output":"1f500","uc_match":"1f500","uc_greedy":"1f500","shortnames":[],"category":"symbols"},":two_hearts:":{"uc_base":"1f495","uc_output":"1f495","uc_match":"1f495","uc_greedy":"1f495","shortnames":[],"category":"symbols"},":two_men_holding_hands:":{"uc_base":"1f46c","uc_output":"1f46c","uc_match":"1f46c","uc_greedy":"1f46c","shortnames":[],"category":"people"},":two_women_holding_hands:":{"uc_base":"1f46d","uc_output":"1f46d","uc_match":"1f46d","uc_greedy":"1f46d","shortnames":[],"category":"people"},":u5272:":{"uc_base":"1f239","uc_output":"1f239","uc_match":"1f239","uc_greedy":"1f239","shortnames":[],"category":"symbols"},":u5408:":{"uc_base":"1f234","uc_output":"1f234","uc_match":"1f234","uc_greedy":"1f234","shortnames":[],"category":"symbols"},":u55b6:":{"uc_base":"1f23a","uc_output":"1f23a","uc_match":"1f23a","uc_greedy":"1f23a","shortnames":[],"category":"symbols"},":u6307:":{"uc_base":"1f22f","uc_output":"1f22f","uc_match":"1f22f","uc_greedy":"1f22f","shortnames":[],"category":"symbols"},":u6709:":{"uc_base":"1f236","uc_output":"1f236","uc_match":"1f236","uc_greedy":"1f236","shortnames":[],"category":"symbols"},":u6e80:":{"uc_base":"1f235","uc_output":"1f235","uc_match":"1f235","uc_greedy":"1f235","shortnames":[],"category":"symbols"},":u7121:":{"uc_base":"1f21a","uc_output":"1f21a","uc_match":"1f21a","uc_greedy":"1f21a","shortnames":[],"category":"symbols"},":u7533:":{"uc_base":"1f238","uc_output":"1f238","uc_match":"1f238","uc_greedy":"1f238","shortnames":[],"category":"symbols"},":u7981:":{"uc_base":"1f232","uc_output":"1f232","uc_match":"1f232","uc_greedy":"1f232","shortnames":[],"category":"symbols"},":u7a7a:":{"uc_base":"1f233","uc_output":"1f233","uc_match":"1f233","uc_greedy":"1f233","shortnames":[],"category":"symbols"},":unamused:":{"uc_base":"1f612","uc_output":"1f612","uc_match":"1f612","uc_greedy":"1f612","shortnames":[],"category":"people"},":underage:":{"uc_base":"1f51e","uc_output":"1f51e","uc_match":"1f51e","uc_greedy":"1f51e","shortnames":[],"category":"symbols"},":unicorn:":{"uc_base":"1f984","uc_output":"1f984","uc_match":"1f984","uc_greedy":"1f984","shortnames":[":unicorn_face:"],"category":"nature"},":unlock:":{"uc_base":"1f513","uc_output":"1f513","uc_match":"1f513","uc_greedy":"1f513","shortnames":[],"category":"objects"},":up:":{"uc_base":"1f199","uc_output":"1f199","uc_match":"1f199","uc_greedy":"1f199","shortnames":[],"category":"symbols"},":upside_down:":{"uc_base":"1f643","uc_output":"1f643","uc_match":"1f643","uc_greedy":"1f643","shortnames":[":upside_down_face:"],"category":"people"},":vampire:":{"uc_base":"1f9db","uc_output":"1f9db","uc_match":"1f9db","uc_greedy":"1f9db","shortnames":[],"category":"people"},":vertical_traffic_light:":{"uc_base":"1f6a6","uc_output":"1f6a6","uc_match":"1f6a6","uc_greedy":"1f6a6","shortnames":[],"category":"travel"},":vhs:":{"uc_base":"1f4fc","uc_output":"1f4fc","uc_match":"1f4fc","uc_greedy":"1f4fc","shortnames":[],"category":"objects"},":vibration_mode:":{"uc_base":"1f4f3","uc_output":"1f4f3","uc_match":"1f4f3","uc_greedy":"1f4f3","shortnames":[],"category":"symbols"},":video_camera:":{"uc_base":"1f4f9","uc_output":"1f4f9","uc_match":"1f4f9","uc_greedy":"1f4f9","shortnames":[],"category":"objects"},":video_game:":{"uc_base":"1f3ae","uc_output":"1f3ae","uc_match":"1f3ae","uc_greedy":"1f3ae","shortnames":[],"category":"activity"},":violin:":{"uc_base":"1f3bb","uc_output":"1f3bb","uc_match":"1f3bb","uc_greedy":"1f3bb","shortnames":[],"category":"activity"},":volcano:":{"uc_base":"1f30b","uc_output":"1f30b","uc_match":"1f30b","uc_greedy":"1f30b","shortnames":[],"category":"travel"},":volleyball:":{"uc_base":"1f3d0","uc_output":"1f3d0","uc_match":"1f3d0","uc_greedy":"1f3d0","shortnames":[],"category":"activity"},":vs:":{"uc_base":"1f19a","uc_output":"1f19a","uc_match":"1f19a","uc_greedy":"1f19a","shortnames":[],"category":"symbols"},":vulcan:":{"uc_base":"1f596","uc_output":"1f596","uc_match":"1f596","uc_greedy":"1f596","shortnames":[":raised_hand_with_part_between_middle_and_ring_fingers:"],"category":"people"},":waning_crescent_moon:":{"uc_base":"1f318","uc_output":"1f318","uc_match":"1f318","uc_greedy":"1f318","shortnames":[],"category":"nature"},":waning_gibbous_moon:":{"uc_base":"1f316","uc_output":"1f316","uc_match":"1f316","uc_greedy":"1f316","shortnames":[],"category":"nature"},":water_buffalo:":{"uc_base":"1f403","uc_output":"1f403","uc_match":"1f403","uc_greedy":"1f403","shortnames":[],"category":"nature"},":watermelon:":{"uc_base":"1f349","uc_output":"1f349","uc_match":"1f349","uc_greedy":"1f349","shortnames":[],"category":"food"},":wave:":{"uc_base":"1f44b","uc_output":"1f44b","uc_match":"1f44b","uc_greedy":"1f44b","shortnames":[],"category":"people"},":waxing_crescent_moon:":{"uc_base":"1f312","uc_output":"1f312","uc_match":"1f312","uc_greedy":"1f312","shortnames":[],"category":"nature"},":waxing_gibbous_moon:":{"uc_base":"1f314","uc_output":"1f314","uc_match":"1f314","uc_greedy":"1f314","shortnames":[],"category":"nature"},":wc:":{"uc_base":"1f6be","uc_output":"1f6be","uc_match":"1f6be","uc_greedy":"1f6be","shortnames":[],"category":"symbols"},":weary:":{"uc_base":"1f629","uc_output":"1f629","uc_match":"1f629","uc_greedy":"1f629","shortnames":[],"category":"people"},":wedding:":{"uc_base":"1f492","uc_output":"1f492","uc_match":"1f492","uc_greedy":"1f492","shortnames":[],"category":"travel"},":whale2:":{"uc_base":"1f40b","uc_output":"1f40b","uc_match":"1f40b","uc_greedy":"1f40b","shortnames":[],"category":"nature"},":whale:":{"uc_base":"1f433","uc_output":"1f433","uc_match":"1f433","uc_greedy":"1f433","shortnames":[],"category":"nature"},":white_flower:":{"uc_base":"1f4ae","uc_output":"1f4ae","uc_match":"1f4ae","uc_greedy":"1f4ae","shortnames":[],"category":"symbols"},":white_square_button:":{"uc_base":"1f533","uc_output":"1f533","uc_match":"1f533","uc_greedy":"1f533","shortnames":[],"category":"symbols"},":wilted_rose:":{"uc_base":"1f940","uc_output":"1f940","uc_match":"1f940","uc_greedy":"1f940","shortnames":[":wilted_flower:"],"category":"nature"},":wind_chime:":{"uc_base":"1f390","uc_output":"1f390","uc_match":"1f390","uc_greedy":"1f390","shortnames":[],"category":"objects"},":wine_glass:":{"uc_base":"1f377","uc_output":"1f377","uc_match":"1f377","uc_greedy":"1f377","shortnames":[],"category":"food"},":wink:":{"uc_base":"1f609","uc_output":"1f609","uc_match":"1f609","uc_greedy":"1f609","shortnames":[],"category":"people"},":wolf:":{"uc_base":"1f43a","uc_output":"1f43a","uc_match":"1f43a","uc_greedy":"1f43a","shortnames":[],"category":"nature"},":woman:":{"uc_base":"1f469","uc_output":"1f469","uc_match":"1f469","uc_greedy":"1f469","shortnames":[],"category":"people"},":woman_with_headscarf:":{"uc_base":"1f9d5","uc_output":"1f9d5","uc_match":"1f9d5","uc_greedy":"1f9d5","shortnames":[],"category":"people"},":womans_clothes:":{"uc_base":"1f45a","uc_output":"1f45a","uc_match":"1f45a","uc_greedy":"1f45a","shortnames":[],"category":"people"},":womans_hat:":{"uc_base":"1f452","uc_output":"1f452","uc_match":"1f452","uc_greedy":"1f452","shortnames":[],"category":"people"},":womens:":{"uc_base":"1f6ba","uc_output":"1f6ba","uc_match":"1f6ba","uc_greedy":"1f6ba","shortnames":[],"category":"symbols"},":worried:":{"uc_base":"1f61f","uc_output":"1f61f","uc_match":"1f61f","uc_greedy":"1f61f","shortnames":[],"category":"people"},":wrench:":{"uc_base":"1f527","uc_output":"1f527","uc_match":"1f527","uc_greedy":"1f527","shortnames":[],"category":"objects"},":yellow_heart:":{"uc_base":"1f49b","uc_output":"1f49b","uc_match":"1f49b","uc_greedy":"1f49b","shortnames":[],"category":"symbols"},":yen:":{"uc_base":"1f4b4","uc_output":"1f4b4","uc_match":"1f4b4","uc_greedy":"1f4b4","shortnames":[],"category":"objects"},":yum:":{"uc_base":"1f60b","uc_output":"1f60b","uc_match":"1f60b","uc_greedy":"1f60b","shortnames":[],"category":"people"},":zebra:":{"uc_base":"1f993","uc_output":"1f993","uc_match":"1f993","uc_greedy":"1f993","shortnames":[],"category":"nature"},":zipper_mouth:":{"uc_base":"1f910","uc_output":"1f910","uc_match":"1f910","uc_greedy":"1f910","shortnames":[":zipper_mouth_face:"],"category":"people"},":zombie:":{"uc_base":"1f9df","uc_output":"1f9df","uc_match":"1f9df","uc_greedy":"1f9df","shortnames":[],"category":"people"},":zzz:":{"uc_base":"1f4a4","uc_output":"1f4a4","uc_match":"1f4a4","uc_greedy":"1f4a4","shortnames":[],"category":"symbols"},":alarm_clock:":{"uc_base":"23f0","uc_output":"23f0","uc_match":"23f0","uc_greedy":"23f0","shortnames":[],"category":"objects"},":anchor:":{"uc_base":"2693","uc_output":"2693","uc_match":"2693","uc_greedy":"2693","shortnames":[],"category":"travel"},":aquarius:":{"uc_base":"2652","uc_output":"2652","uc_match":"2652","uc_greedy":"2652","shortnames":[],"category":"symbols"},":aries:":{"uc_base":"2648","uc_output":"2648","uc_match":"2648","uc_greedy":"2648","shortnames":[],"category":"symbols"},":arrow_double_down:":{"uc_base":"23ec","uc_output":"23ec","uc_match":"23ec","uc_greedy":"23ec","shortnames":[],"category":"symbols"},":arrow_double_up:":{"uc_base":"23eb","uc_output":"23eb","uc_match":"23eb","uc_greedy":"23eb","shortnames":[],"category":"symbols"},":baseball:":{"uc_base":"26be","uc_output":"26be","uc_match":"26be","uc_greedy":"26be","shortnames":[],"category":"activity"},":black_circle:":{"uc_base":"26ab","uc_output":"26ab","uc_match":"26ab","uc_greedy":"26ab","shortnames":[],"category":"symbols"},":black_large_square:":{"uc_base":"2b1b","uc_output":"2b1b","uc_match":"2b1b","uc_greedy":"2b1b","shortnames":[],"category":"symbols"},":black_medium_small_square:":{"uc_base":"25fe","uc_output":"25fe","uc_match":"25fe","uc_greedy":"25fe","shortnames":[],"category":"symbols"},":cancer:":{"uc_base":"264b","uc_output":"264b","uc_match":"264b","uc_greedy":"264b","shortnames":[],"category":"symbols"},":capricorn:":{"uc_base":"2651","uc_output":"2651","uc_match":"2651","uc_greedy":"2651","shortnames":[],"category":"symbols"},":church:":{"uc_base":"26ea","uc_output":"26ea","uc_match":"26ea","uc_greedy":"26ea","shortnames":[],"category":"travel"},":coffee:":{"uc_base":"2615","uc_output":"2615","uc_match":"2615","uc_greedy":"2615","shortnames":[],"category":"food"},":curly_loop:":{"uc_base":"27b0","uc_output":"27b0","uc_match":"27b0","uc_greedy":"27b0","shortnames":[],"category":"symbols"},":exclamation:":{"uc_base":"2757","uc_output":"2757","uc_match":"2757","uc_greedy":"2757","shortnames":[],"category":"symbols"},":fast_forward:":{"uc_base":"23e9","uc_output":"23e9","uc_match":"23e9","uc_greedy":"23e9","shortnames":[],"category":"symbols"},":fist:":{"uc_base":"270a","uc_output":"270a","uc_match":"270a","uc_greedy":"270a","shortnames":[],"category":"people"},":fountain:":{"uc_base":"26f2","uc_output":"26f2","uc_match":"26f2","uc_greedy":"26f2","shortnames":[],"category":"travel"},":fuelpump:":{"uc_base":"26fd","uc_output":"26fd","uc_match":"26fd","uc_greedy":"26fd","shortnames":[],"category":"travel"},":gemini:":{"uc_base":"264a","uc_output":"264a","uc_match":"264a","uc_greedy":"264a","shortnames":[],"category":"symbols"},":golf:":{"uc_base":"26f3","uc_output":"26f3","uc_match":"26f3","uc_greedy":"26f3","shortnames":[],"category":"activity"},":grey_exclamation:":{"uc_base":"2755","uc_output":"2755","uc_match":"2755","uc_greedy":"2755","shortnames":[],"category":"symbols"},":grey_question:":{"uc_base":"2754","uc_output":"2754","uc_match":"2754","uc_greedy":"2754","shortnames":[],"category":"symbols"},":heavy_division_sign:":{"uc_base":"2797","uc_output":"2797","uc_match":"2797","uc_greedy":"2797","shortnames":[],"category":"symbols"},":heavy_minus_sign:":{"uc_base":"2796","uc_output":"2796","uc_match":"2796","uc_greedy":"2796","shortnames":[],"category":"symbols"},":heavy_plus_sign:":{"uc_base":"2795","uc_output":"2795","uc_match":"2795","uc_greedy":"2795","shortnames":[],"category":"symbols"},":hourglass:":{"uc_base":"231b","uc_output":"231b","uc_match":"231b","uc_greedy":"231b","shortnames":[],"category":"objects"},":hourglass_flowing_sand:":{"uc_base":"23f3","uc_output":"23f3","uc_match":"23f3","uc_greedy":"23f3","shortnames":[],"category":"objects"},":leo:":{"uc_base":"264c","uc_output":"264c","uc_match":"264c","uc_greedy":"264c","shortnames":[],"category":"symbols"},":libra:":{"uc_base":"264e","uc_output":"264e","uc_match":"264e","uc_greedy":"264e","shortnames":[],"category":"symbols"},":loop:":{"uc_base":"27bf","uc_output":"27bf","uc_match":"27bf","uc_greedy":"27bf","shortnames":[],"category":"symbols"},":negative_squared_cross_mark:":{"uc_base":"274e","uc_output":"274e","uc_match":"274e","uc_greedy":"274e","shortnames":[],"category":"symbols"},":no_entry:":{"uc_base":"26d4","uc_output":"26d4","uc_match":"26d4","uc_greedy":"26d4","shortnames":[],"category":"symbols"},":o:":{"uc_base":"2b55","uc_output":"2b55","uc_match":"2b55","uc_greedy":"2b55","shortnames":[],"category":"symbols"},":ophiuchus:":{"uc_base":"26ce","uc_output":"26ce","uc_match":"26ce","uc_greedy":"26ce","shortnames":[],"category":"symbols"},":partly_sunny:":{"uc_base":"26c5","uc_output":"26c5","uc_match":"26c5","uc_greedy":"26c5","shortnames":[],"category":"nature"},":pisces:":{"uc_base":"2653","uc_output":"2653","uc_match":"2653","uc_greedy":"2653","shortnames":[],"category":"symbols"},":question:":{"uc_base":"2753","uc_output":"2753","uc_match":"2753","uc_greedy":"2753","shortnames":[],"category":"symbols"},":raised_hand:":{"uc_base":"270b","uc_output":"270b","uc_match":"270b","uc_greedy":"270b","shortnames":[],"category":"people"},":rewind:":{"uc_base":"23ea","uc_output":"23ea","uc_match":"23ea","uc_greedy":"23ea","shortnames":[],"category":"symbols"},":sagittarius:":{"uc_base":"2650","uc_output":"2650","uc_match":"2650","uc_greedy":"2650","shortnames":[],"category":"symbols"},":sailboat:":{"uc_base":"26f5","uc_output":"26f5","uc_match":"26f5","uc_greedy":"26f5","shortnames":[],"category":"travel"},":scorpius:":{"uc_base":"264f","uc_output":"264f","uc_match":"264f","uc_greedy":"264f","shortnames":[],"category":"symbols"},":snowman:":{"uc_base":"26c4","uc_output":"26c4","uc_match":"26c4","uc_greedy":"26c4","shortnames":[],"category":"nature"},":soccer:":{"uc_base":"26bd","uc_output":"26bd","uc_match":"26bd","uc_greedy":"26bd","shortnames":[],"category":"activity"},":sparkles:":{"uc_base":"2728","uc_output":"2728","uc_match":"2728","uc_greedy":"2728","shortnames":[],"category":"nature"},":star:":{"uc_base":"2b50","uc_output":"2b50","uc_match":"2b50","uc_greedy":"2b50","shortnames":[],"category":"nature"},":taurus:":{"uc_base":"2649","uc_output":"2649","uc_match":"2649","uc_greedy":"2649","shortnames":[],"category":"symbols"},":tent:":{"uc_base":"26fa","uc_output":"26fa","uc_match":"26fa","uc_greedy":"26fa","shortnames":[],"category":"travel"},":umbrella:":{"uc_base":"2614","uc_output":"2614","uc_match":"2614","uc_greedy":"2614","shortnames":[],"category":"nature"},":virgo:":{"uc_base":"264d","uc_output":"264d","uc_match":"264d","uc_greedy":"264d","shortnames":[],"category":"symbols"},":watch:":{"uc_base":"231a","uc_output":"231a","uc_match":"231a","uc_greedy":"231a","shortnames":[],"category":"objects"},":wheelchair:":{"uc_base":"267f","uc_output":"267f","uc_match":"267f","uc_greedy":"267f","shortnames":[],"category":"symbols"},":white_check_mark:":{"uc_base":"2705","uc_output":"2705","uc_match":"2705","uc_greedy":"2705","shortnames":[],"category":"symbols"},":white_circle:":{"uc_base":"26aa","uc_output":"26aa","uc_match":"26aa","uc_greedy":"26aa","shortnames":[],"category":"symbols"},":white_large_square:":{"uc_base":"2b1c","uc_output":"2b1c","uc_match":"2b1c","uc_greedy":"2b1c","shortnames":[],"category":"symbols"},":white_medium_small_square:":{"uc_base":"25fd","uc_output":"25fd","uc_match":"25fd","uc_greedy":"25fd","shortnames":[],"category":"symbols"},":x:":{"uc_base":"274c","uc_output":"274c","uc_match":"274c","uc_greedy":"274c","shortnames":[],"category":"symbols"},":zap:":{"uc_base":"26a1","uc_output":"26a1","uc_match":"26a1","uc_greedy":"26a1","shortnames":[],"category":"nature"}};
  7883. var tmpShortNames = [], emoji;
  7884. for (emoji in ns.emojioneList) {
  7885. if (!ns.emojioneList.hasOwnProperty(emoji) || (emoji === '')) continue;
  7886. tmpShortNames.push(emoji.replace(/[+]/g, "\\$&"));
  7887. for (var i = 0; i < ns.emojioneList[emoji].shortnames.length; i++) {
  7888. tmpShortNames.push(ns.emojioneList[emoji].shortnames[i].replace(/[+]/g, "\\$&"));
  7889. }
  7890. }
  7891. ns.shortnames = tmpShortNames.join('|');
  7892. // javascript escapes here must be ordered from largest length to shortest
  7893. ns.jsEscapeMap = {"\uD83D\uDC69\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D\uD83D\uDC69":"1f469-2764-1f48b-1f469","\uD83D\uDC68\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D\uD83D\uDC68":"1f468-2764-1f48b-1f468","\uD83D\uDC69\u200D\u2764\uFE0F\u200D\uD83D\uDC8B\u200D\uD83D\uDC68":"1f469-2764-1f48b-1f468","\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67\uDB40\uDC7F":"1f3f4-e0067-e0062-e0065-e006e-e0067-e007f","\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74\uDB40\uDC7F":"1f3f4-e0067-e0062-e0073-e0063-e0074-e007f","\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F":"1f3f4-e0067-e0062-e0077-e006c-e0073-e007f","\uD83D\uDC68\u200D\uD83D\uDC68\u200D\uD83D\uDC66\u200D\uD83D\uDC66":"1f468-1f468-1f466-1f466","\uD83D\uDC68\u200D\uD83D\uDC68\u200D\uD83D\uDC67\u200D\uD83D\uDC66":"1f468-1f468-1f467-1f466","\uD83D\uDC68\u200D\uD83D\uDC68\u200D\uD83D\uDC67\u200D\uD83D\uDC67":"1f468-1f468-1f467-1f467","\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66":"1f468-1f469-1f466-1f466","\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC66":"1f468-1f469-1f467-1f466","\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC67":"1f468-1f469-1f467-1f467","\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66":"1f469-1f469-1f466-1f466","\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC66":"1f469-1f469-1f467-1f466","\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC67":"1f469-1f469-1f467-1f467","\uD83D\uDC68\u200D\u2764\u200D\uD83D\uDC8B\u200D\uD83D\uDC68":"1f468-2764-1f48b-1f468","\uD83D\uDC69\u200D\u2764\u200D\uD83D\uDC8B\u200D\uD83D\uDC68":"1f469-2764-1f48b-1f468","\uD83D\uDC69\u200D\u2764\u200D\uD83D\uDC8B\u200D\uD83D\uDC69":"1f469-2764-1f48b-1f469","\uD83D\uDC69\u200D\u2764\uFE0F\u200D\uD83D\uDC69":"1f469-2764-1f469","\uD83D\uDC68\u200D\u2764\uFE0F\u200D\uD83D\uDC68":"1f468-2764-1f468","\uD83D\uDC69\u200D\u2764\uFE0F\u200D\uD83D\uDC68":"1f469-2764-1f468","\uD83D\uDD75\uFE0F\uD83C\uDFFB\u200D\u2640\uFE0F":"1f575-1f3fb-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFB\u200D\u2642\uFE0F":"1f575-1f3fb-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFC\u200D\u2640\uFE0F":"1f575-1f3fc-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFC\u200D\u2642\uFE0F":"1f575-1f3fc-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFD\u200D\u2640\uFE0F":"1f575-1f3fd-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFD\u200D\u2642\uFE0F":"1f575-1f3fd-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFE\u200D\u2640\uFE0F":"1f575-1f3fe-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFE\u200D\u2642\uFE0F":"1f575-1f3fe-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFF\u200D\u2640\uFE0F":"1f575-1f3ff-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFF\u200D\u2642\uFE0F":"1f575-1f3ff-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3cb-1f3fb-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3cb-1f3fb-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3cb-1f3fc-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3cb-1f3fc-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3cb-1f3fd-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3cb-1f3fd-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3cb-1f3fe-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3cb-1f3fe-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3cb-1f3ff-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3cb-1f3ff-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3cc-1f3fb-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3cc-1f3fb-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3cc-1f3fc-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3cc-1f3fc-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3cc-1f3fd-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3cc-1f3fd-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3cc-1f3fe-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3cc-1f3fe-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3cc-1f3ff-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3cc-1f3ff-2642","\u26F9\uFE0F\uD83C\uDFFB\u200D\u2640\uFE0F":"26f9-1f3fb-2640","\u26F9\uFE0F\uD83C\uDFFB\u200D\u2642\uFE0F":"26f9-1f3fb-2642","\u26F9\uFE0F\uD83C\uDFFC\u200D\u2640\uFE0F":"26f9-1f3fc-2640","\u26F9\uFE0F\uD83C\uDFFC\u200D\u2642\uFE0F":"26f9-1f3fc-2642","\u26F9\uFE0F\uD83C\uDFFD\u200D\u2640\uFE0F":"26f9-1f3fd-2640","\u26F9\uFE0F\uD83C\uDFFD\u200D\u2642\uFE0F":"26f9-1f3fd-2642","\u26F9\uFE0F\uD83C\uDFFE\u200D\u2640\uFE0F":"26f9-1f3fe-2640","\u26F9\uFE0F\uD83C\uDFFE\u200D\u2642\uFE0F":"26f9-1f3fe-2642","\u26F9\uFE0F\uD83C\uDFFF\u200D\u2640\uFE0F":"26f9-1f3ff-2640","\u26F9\uFE0F\uD83C\uDFFF\u200D\u2642\uFE0F":"26f9-1f3ff-2642","\uD83D\uDC68\u200D\uD83D\uDC68\u200D\uD83D\uDC66":"1f468-1f468-1f466","\uD83D\uDC68\u200D\uD83D\uDC68\u200D\uD83D\uDC67":"1f468-1f468-1f467","\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC67":"1f468-1f469-1f467","\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC66":"1f469-1f469-1f466","\uD83D\uDC69\u200D\uD83D\uDC69\u200D\uD83D\uDC67":"1f469-1f469-1f467","\uD83D\uDC68\u200D\uD83D\uDC66\u200D\uD83D\uDC66":"1f468-1f466-1f466","\uD83D\uDC68\u200D\uD83D\uDC67\u200D\uD83D\uDC66":"1f468-1f467-1f466","\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66":"1f469-1f466-1f466","\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC66":"1f469-1f467-1f466","\uD83D\uDC69\u200D\uD83D\uDC67\u200D\uD83D\uDC67":"1f469-1f467-1f467","\uD83D\uDC68\u2764\uFE0F\uD83D\uDC8B\uD83D\uDC68":"1f468-2764-1f48b-1f468","\uD83D\uDC68\u200D\uD83D\uDC67\u200D\uD83D\uDC67":"1f468-1f467-1f467","\uD83D\uDC68\u200D\uD83D\uDC69\u200D\uD83D\uDC66":"1f468-1f469-1f466","\uD83D\uDC69\u2764\uFE0F\uD83D\uDC8B\uD83D\uDC68":"1f469-2764-1f48b-1f468","\uD83D\uDC69\u2764\uFE0F\uD83D\uDC8B\uD83D\uDC69":"1f469-2764-1f48b-1f469","\uD83D\uDC68\u200D\u2764\u200D\uD83D\uDC68":"1f468-2764-1f468","\uD83D\uDC69\u200D\u2764\u200D\uD83D\uDC68":"1f469-2764-1f468","\uD83D\uDC69\u200D\u2764\u200D\uD83D\uDC69":"1f469-2764-1f469","\uD83D\uDC68\uD83C\uDFFB\u200D\u2695\uFE0F":"1f468-1f3fb-2695","\uD83D\uDC68\uD83C\uDFFB\u200D\u2696\uFE0F":"1f468-1f3fb-2696","\uD83D\uDC68\uD83C\uDFFB\u200D\u2708\uFE0F":"1f468-1f3fb-2708","\uD83D\uDC68\uD83C\uDFFC\u200D\u2695\uFE0F":"1f468-1f3fc-2695","\uD83D\uDC68\uD83C\uDFFC\u200D\u2696\uFE0F":"1f468-1f3fc-2696","\uD83D\uDC68\uD83C\uDFFC\u200D\u2708\uFE0F":"1f468-1f3fc-2708","\uD83D\uDC68\uD83C\uDFFD\u200D\u2695\uFE0F":"1f468-1f3fd-2695","\uD83D\uDC68\uD83C\uDFFD\u200D\u2696\uFE0F":"1f468-1f3fd-2696","\uD83D\uDC68\uD83C\uDFFD\u200D\u2708\uFE0F":"1f468-1f3fd-2708","\uD83D\uDC68\uD83C\uDFFE\u200D\u2695\uFE0F":"1f468-1f3fe-2695","\uD83D\uDC68\uD83C\uDFFE\u200D\u2696\uFE0F":"1f468-1f3fe-2696","\uD83D\uDC68\uD83C\uDFFE\u200D\u2708\uFE0F":"1f468-1f3fe-2708","\uD83D\uDC68\uD83C\uDFFF\u200D\u2695\uFE0F":"1f468-1f3ff-2695","\uD83D\uDC68\uD83C\uDFFF\u200D\u2696\uFE0F":"1f468-1f3ff-2696","\uD83D\uDC68\uD83C\uDFFF\u200D\u2708\uFE0F":"1f468-1f3ff-2708","\uD83D\uDC69\uD83C\uDFFB\u200D\u2695\uFE0F":"1f469-1f3fb-2695","\uD83D\uDC69\uD83C\uDFFB\u200D\u2696\uFE0F":"1f469-1f3fb-2696","\uD83D\uDC69\uD83C\uDFFB\u200D\u2708\uFE0F":"1f469-1f3fb-2708","\uD83D\uDC69\uD83C\uDFFC\u200D\u2695\uFE0F":"1f469-1f3fc-2695","\uD83D\uDC69\uD83C\uDFFC\u200D\u2696\uFE0F":"1f469-1f3fc-2696","\uD83D\uDC69\uD83C\uDFFC\u200D\u2708\uFE0F":"1f469-1f3fc-2708","\uD83D\uDC69\uD83C\uDFFD\u200D\u2695\uFE0F":"1f469-1f3fd-2695","\uD83D\uDC69\uD83C\uDFFD\u200D\u2696\uFE0F":"1f469-1f3fd-2696","\uD83D\uDC69\uD83C\uDFFD\u200D\u2708\uFE0F":"1f469-1f3fd-2708","\uD83D\uDC69\uD83C\uDFFE\u200D\u2695\uFE0F":"1f469-1f3fe-2695","\uD83D\uDC69\uD83C\uDFFE\u200D\u2696\uFE0F":"1f469-1f3fe-2696","\uD83D\uDC69\uD83C\uDFFE\u200D\u2708\uFE0F":"1f469-1f3fe-2708","\uD83D\uDC69\uD83C\uDFFF\u200D\u2695\uFE0F":"1f469-1f3ff-2695","\uD83D\uDC69\uD83C\uDFFF\u200D\u2696\uFE0F":"1f469-1f3ff-2696","\uD83D\uDC69\uD83C\uDFFF\u200D\u2708\uFE0F":"1f469-1f3ff-2708","\uD83D\uDC6E\uD83C\uDFFB\u200D\u2640\uFE0F":"1f46e-1f3fb-2640","\uD83D\uDC6E\uD83C\uDFFB\u200D\u2642\uFE0F":"1f46e-1f3fb-2642","\uD83D\uDC6E\uD83C\uDFFC\u200D\u2640\uFE0F":"1f46e-1f3fc-2640","\uD83D\uDC6E\uD83C\uDFFC\u200D\u2642\uFE0F":"1f46e-1f3fc-2642","\uD83D\uDC6E\uD83C\uDFFD\u200D\u2640\uFE0F":"1f46e-1f3fd-2640","\uD83D\uDC6E\uD83C\uDFFD\u200D\u2642\uFE0F":"1f46e-1f3fd-2642","\uD83D\uDC6E\uD83C\uDFFE\u200D\u2640\uFE0F":"1f46e-1f3fe-2640","\uD83D\uDC6E\uD83C\uDFFE\u200D\u2642\uFE0F":"1f46e-1f3fe-2642","\uD83D\uDC6E\uD83C\uDFFF\u200D\u2640\uFE0F":"1f46e-1f3ff-2640","\uD83D\uDC6E\uD83C\uDFFF\u200D\u2642\uFE0F":"1f46e-1f3ff-2642","\uD83D\uDC71\uD83C\uDFFB\u200D\u2640\uFE0F":"1f471-1f3fb-2640","\uD83D\uDC71\uD83C\uDFFB\u200D\u2642\uFE0F":"1f471-1f3fb-2642","\uD83D\uDC71\uD83C\uDFFC\u200D\u2640\uFE0F":"1f471-1f3fc-2640","\uD83D\uDC71\uD83C\uDFFC\u200D\u2642\uFE0F":"1f471-1f3fc-2642","\uD83D\uDC71\uD83C\uDFFD\u200D\u2640\uFE0F":"1f471-1f3fd-2640","\uD83D\uDC71\uD83C\uDFFD\u200D\u2642\uFE0F":"1f471-1f3fd-2642","\uD83D\uDC71\uD83C\uDFFE\u200D\u2640\uFE0F":"1f471-1f3fe-2640","\uD83D\uDC71\uD83C\uDFFE\u200D\u2642\uFE0F":"1f471-1f3fe-2642","\uD83D\uDC71\uD83C\uDFFF\u200D\u2640\uFE0F":"1f471-1f3ff-2640","\uD83D\uDC71\uD83C\uDFFF\u200D\u2642\uFE0F":"1f471-1f3ff-2642","\uD83D\uDC73\uD83C\uDFFB\u200D\u2640\uFE0F":"1f473-1f3fb-2640","\uD83D\uDC73\uD83C\uDFFB\u200D\u2642\uFE0F":"1f473-1f3fb-2642","\uD83D\uDC73\uD83C\uDFFC\u200D\u2640\uFE0F":"1f473-1f3fc-2640","\uD83D\uDC73\uD83C\uDFFC\u200D\u2642\uFE0F":"1f473-1f3fc-2642","\uD83D\uDC73\uD83C\uDFFD\u200D\u2640\uFE0F":"1f473-1f3fd-2640","\uD83D\uDC73\uD83C\uDFFD\u200D\u2642\uFE0F":"1f473-1f3fd-2642","\uD83D\uDC73\uD83C\uDFFE\u200D\u2640\uFE0F":"1f473-1f3fe-2640","\uD83D\uDC73\uD83C\uDFFE\u200D\u2642\uFE0F":"1f473-1f3fe-2642","\uD83D\uDC73\uD83C\uDFFF\u200D\u2640\uFE0F":"1f473-1f3ff-2640","\uD83D\uDC73\uD83C\uDFFF\u200D\u2642\uFE0F":"1f473-1f3ff-2642","\uD83D\uDC77\uD83C\uDFFB\u200D\u2640\uFE0F":"1f477-1f3fb-2640","\uD83D\uDC77\uD83C\uDFFB\u200D\u2642\uFE0F":"1f477-1f3fb-2642","\uD83D\uDC77\uD83C\uDFFC\u200D\u2640\uFE0F":"1f477-1f3fc-2640","\uD83D\uDC77\uD83C\uDFFC\u200D\u2642\uFE0F":"1f477-1f3fc-2642","\uD83D\uDC77\uD83C\uDFFD\u200D\u2640\uFE0F":"1f477-1f3fd-2640","\uD83D\uDC77\uD83C\uDFFD\u200D\u2642\uFE0F":"1f477-1f3fd-2642","\uD83D\uDC77\uD83C\uDFFE\u200D\u2640\uFE0F":"1f477-1f3fe-2640","\uD83D\uDC77\uD83C\uDFFE\u200D\u2642\uFE0F":"1f477-1f3fe-2642","\uD83D\uDC77\uD83C\uDFFF\u200D\u2640\uFE0F":"1f477-1f3ff-2640","\uD83D\uDC77\uD83C\uDFFF\u200D\u2642\uFE0F":"1f477-1f3ff-2642","\uD83D\uDC82\uD83C\uDFFB\u200D\u2640\uFE0F":"1f482-1f3fb-2640","\uD83D\uDC82\uD83C\uDFFB\u200D\u2642\uFE0F":"1f482-1f3fb-2642","\uD83D\uDC82\uD83C\uDFFC\u200D\u2640\uFE0F":"1f482-1f3fc-2640","\uD83D\uDC82\uD83C\uDFFC\u200D\u2642\uFE0F":"1f482-1f3fc-2642","\uD83D\uDC82\uD83C\uDFFD\u200D\u2640\uFE0F":"1f482-1f3fd-2640","\uD83D\uDC82\uD83C\uDFFD\u200D\u2642\uFE0F":"1f482-1f3fd-2642","\uD83D\uDC82\uD83C\uDFFE\u200D\u2640\uFE0F":"1f482-1f3fe-2640","\uD83D\uDC82\uD83C\uDFFE\u200D\u2642\uFE0F":"1f482-1f3fe-2642","\uD83D\uDC82\uD83C\uDFFF\u200D\u2640\uFE0F":"1f482-1f3ff-2640","\uD83D\uDC82\uD83C\uDFFF\u200D\u2642\uFE0F":"1f482-1f3ff-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFB\u2640\uFE0F":"1f575-1f3fb-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFB\u2642\uFE0F":"1f575-1f3fb-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFC\u2640\uFE0F":"1f575-1f3fc-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFC\u2642\uFE0F":"1f575-1f3fc-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFD\u2640\uFE0F":"1f575-1f3fd-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFD\u2642\uFE0F":"1f575-1f3fd-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFE\u2640\uFE0F":"1f575-1f3fe-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFE\u2642\uFE0F":"1f575-1f3fe-2642","\uD83D\uDD75\uFE0F\uD83C\uDFFF\u2640\uFE0F":"1f575-1f3ff-2640","\uD83D\uDD75\uFE0F\uD83C\uDFFF\u2642\uFE0F":"1f575-1f3ff-2642","\uD83C\uDFC3\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3c3-1f3fb-2640","\uD83C\uDFC3\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3c3-1f3fb-2642","\uD83C\uDFC3\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3c3-1f3fc-2640","\uD83C\uDFC3\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3c3-1f3fc-2642","\uD83C\uDFC3\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3c3-1f3fd-2640","\uD83C\uDFC3\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3c3-1f3fd-2642","\uD83C\uDFC3\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3c3-1f3fe-2640","\uD83C\uDFC3\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3c3-1f3fe-2642","\uD83C\uDFC3\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3c3-1f3ff-2640","\uD83C\uDFC3\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3c3-1f3ff-2642","\uD83C\uDFC4\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3c4-1f3fb-2640","\uD83C\uDFC4\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3c4-1f3fb-2642","\uD83C\uDFC4\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3c4-1f3fc-2640","\uD83C\uDFC4\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3c4-1f3fc-2642","\uD83C\uDFC4\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3c4-1f3fd-2640","\uD83C\uDFC4\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3c4-1f3fd-2642","\uD83C\uDFC4\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3c4-1f3fe-2640","\uD83C\uDFC4\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3c4-1f3fe-2642","\uD83C\uDFC4\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3c4-1f3ff-2640","\uD83C\uDFC4\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3c4-1f3ff-2642","\uD83C\uDFCA\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3ca-1f3fb-2640","\uD83C\uDFCA\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3ca-1f3fb-2642","\uD83C\uDFCA\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3ca-1f3fc-2640","\uD83C\uDFCA\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3ca-1f3fc-2642","\uD83C\uDFCA\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3ca-1f3fd-2640","\uD83C\uDFCA\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3ca-1f3fd-2642","\uD83C\uDFCA\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3ca-1f3fe-2640","\uD83C\uDFCA\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3ca-1f3fe-2642","\uD83C\uDFCA\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3ca-1f3ff-2640","\uD83C\uDFCA\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3ca-1f3ff-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFB\u2640\uFE0F":"1f3cb-1f3fb-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFB\u2642\uFE0F":"1f3cb-1f3fb-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFC\u2640\uFE0F":"1f3cb-1f3fc-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFC\u2642\uFE0F":"1f3cb-1f3fc-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFD\u2640\uFE0F":"1f3cb-1f3fd-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFD\u2642\uFE0F":"1f3cb-1f3fd-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFE\u2640\uFE0F":"1f3cb-1f3fe-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFE\u2642\uFE0F":"1f3cb-1f3fe-2642","\uD83C\uDFCB\uFE0F\uD83C\uDFFF\u2640\uFE0F":"1f3cb-1f3ff-2640","\uD83C\uDFCB\uFE0F\uD83C\uDFFF\u2642\uFE0F":"1f3cb-1f3ff-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFB\u2640\uFE0F":"1f3cc-1f3fb-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFB\u2642\uFE0F":"1f3cc-1f3fb-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFC\u2640\uFE0F":"1f3cc-1f3fc-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFC\u2642\uFE0F":"1f3cc-1f3fc-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFD\u2640\uFE0F":"1f3cc-1f3fd-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFD\u2642\uFE0F":"1f3cc-1f3fd-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFE\u2640\uFE0F":"1f3cc-1f3fe-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFE\u2642\uFE0F":"1f3cc-1f3fe-2642","\uD83C\uDFCC\uFE0F\uD83C\uDFFF\u2640\uFE0F":"1f3cc-1f3ff-2640","\uD83C\uDFCC\uFE0F\uD83C\uDFFF\u2642\uFE0F":"1f3cc-1f3ff-2642","\uD83D\uDC86\uD83C\uDFFB\u200D\u2640\uFE0F":"1f486-1f3fb-2640","\uD83D\uDC86\uD83C\uDFFB\u200D\u2642\uFE0F":"1f486-1f3fb-2642","\uD83D\uDC86\uD83C\uDFFC\u200D\u2640\uFE0F":"1f486-1f3fc-2640","\uD83D\uDC86\uD83C\uDFFC\u200D\u2642\uFE0F":"1f486-1f3fc-2642","\uD83D\uDC86\uD83C\uDFFD\u200D\u2640\uFE0F":"1f486-1f3fd-2640","\uD83D\uDC86\uD83C\uDFFD\u200D\u2642\uFE0F":"1f486-1f3fd-2642","\uD83D\uDC86\uD83C\uDFFE\u200D\u2640\uFE0F":"1f486-1f3fe-2640","\uD83D\uDC86\uD83C\uDFFE\u200D\u2642\uFE0F":"1f486-1f3fe-2642","\uD83D\uDC86\uD83C\uDFFF\u200D\u2640\uFE0F":"1f486-1f3ff-2640","\uD83D\uDC86\uD83C\uDFFF\u200D\u2642\uFE0F":"1f486-1f3ff-2642","\uD83D\uDC87\uD83C\uDFFB\u200D\u2640\uFE0F":"1f487-1f3fb-2640","\uD83D\uDC87\uD83C\uDFFB\u200D\u2642\uFE0F":"1f487-1f3fb-2642","\uD83D\uDC87\uD83C\uDFFC\u200D\u2640\uFE0F":"1f487-1f3fc-2640","\uD83D\uDC87\uD83C\uDFFC\u200D\u2642\uFE0F":"1f487-1f3fc-2642","\uD83D\uDC87\uD83C\uDFFD\u200D\u2640\uFE0F":"1f487-1f3fd-2640","\uD83D\uDC87\uD83C\uDFFD\u200D\u2642\uFE0F":"1f487-1f3fd-2642","\uD83D\uDC87\uD83C\uDFFE\u200D\u2640\uFE0F":"1f487-1f3fe-2640","\uD83D\uDC87\uD83C\uDFFE\u200D\u2642\uFE0F":"1f487-1f3fe-2642","\uD83D\uDC87\uD83C\uDFFF\u200D\u2640\uFE0F":"1f487-1f3ff-2640","\uD83D\uDC87\uD83C\uDFFF\u200D\u2642\uFE0F":"1f487-1f3ff-2642","\uD83D\uDEA3\uD83C\uDFFB\u200D\u2640\uFE0F":"1f6a3-1f3fb-2640","\uD83D\uDEA3\uD83C\uDFFB\u200D\u2642\uFE0F":"1f6a3-1f3fb-2642","\uD83D\uDEA3\uD83C\uDFFC\u200D\u2640\uFE0F":"1f6a3-1f3fc-2640","\uD83D\uDEA3\uD83C\uDFFC\u200D\u2642\uFE0F":"1f6a3-1f3fc-2642","\uD83D\uDEA3\uD83C\uDFFD\u200D\u2640\uFE0F":"1f6a3-1f3fd-2640","\uD83D\uDEA3\uD83C\uDFFD\u200D\u2642\uFE0F":"1f6a3-1f3fd-2642","\uD83D\uDEA3\uD83C\uDFFE\u200D\u2640\uFE0F":"1f6a3-1f3fe-2640","\uD83D\uDEA3\uD83C\uDFFE\u200D\u2642\uFE0F":"1f6a3-1f3fe-2642","\uD83D\uDEA3\uD83C\uDFFF\u200D\u2640\uFE0F":"1f6a3-1f3ff-2640","\uD83D\uDEA3\uD83C\uDFFF\u200D\u2642\uFE0F":"1f6a3-1f3ff-2642","\uD83D\uDEB4\uD83C\uDFFB\u200D\u2640\uFE0F":"1f6b4-1f3fb-2640","\uD83D\uDEB4\uD83C\uDFFB\u200D\u2642\uFE0F":"1f6b4-1f3fb-2642","\uD83D\uDEB4\uD83C\uDFFC\u200D\u2640\uFE0F":"1f6b4-1f3fc-2640","\uD83D\uDEB4\uD83C\uDFFC\u200D\u2642\uFE0F":"1f6b4-1f3fc-2642","\uD83D\uDEB4\uD83C\uDFFD\u200D\u2640\uFE0F":"1f6b4-1f3fd-2640","\uD83D\uDEB4\uD83C\uDFFD\u200D\u2642\uFE0F":"1f6b4-1f3fd-2642","\uD83D\uDEB4\uD83C\uDFFE\u200D\u2640\uFE0F":"1f6b4-1f3fe-2640","\uD83D\uDEB4\uD83C\uDFFE\u200D\u2642\uFE0F":"1f6b4-1f3fe-2642","\uD83D\uDEB4\uD83C\uDFFF\u200D\u2640\uFE0F":"1f6b4-1f3ff-2640","\uD83D\uDEB4\uD83C\uDFFF\u200D\u2642\uFE0F":"1f6b4-1f3ff-2642","\uD83D\uDEB5\uD83C\uDFFB\u200D\u2640\uFE0F":"1f6b5-1f3fb-2640","\uD83D\uDEB5\uD83C\uDFFB\u200D\u2642\uFE0F":"1f6b5-1f3fb-2642","\uD83D\uDEB5\uD83C\uDFFC\u200D\u2640\uFE0F":"1f6b5-1f3fc-2640","\uD83D\uDEB5\uD83C\uDFFC\u200D\u2642\uFE0F":"1f6b5-1f3fc-2642","\uD83D\uDEB5\uD83C\uDFFD\u200D\u2640\uFE0F":"1f6b5-1f3fd-2640","\uD83D\uDEB5\uD83C\uDFFD\u200D\u2642\uFE0F":"1f6b5-1f3fd-2642","\uD83D\uDEB5\uD83C\uDFFE\u200D\u2640\uFE0F":"1f6b5-1f3fe-2640","\uD83D\uDEB5\uD83C\uDFFE\u200D\u2642\uFE0F":"1f6b5-1f3fe-2642","\uD83D\uDEB5\uD83C\uDFFF\u200D\u2640\uFE0F":"1f6b5-1f3ff-2640","\uD83D\uDEB5\uD83C\uDFFF\u200D\u2642\uFE0F":"1f6b5-1f3ff-2642","\uD83D\uDEB6\uD83C\uDFFB\u200D\u2640\uFE0F":"1f6b6-1f3fb-2640","\uD83D\uDEB6\uD83C\uDFFB\u200D\u2642\uFE0F":"1f6b6-1f3fb-2642","\uD83D\uDEB6\uD83C\uDFFC\u200D\u2640\uFE0F":"1f6b6-1f3fc-2640","\uD83D\uDEB6\uD83C\uDFFC\u200D\u2642\uFE0F":"1f6b6-1f3fc-2642","\uD83D\uDEB6\uD83C\uDFFD\u200D\u2640\uFE0F":"1f6b6-1f3fd-2640","\uD83D\uDEB6\uD83C\uDFFD\u200D\u2642\uFE0F":"1f6b6-1f3fd-2642","\uD83D\uDEB6\uD83C\uDFFE\u200D\u2640\uFE0F":"1f6b6-1f3fe-2640","\uD83D\uDEB6\uD83C\uDFFE\u200D\u2642\uFE0F":"1f6b6-1f3fe-2642","\uD83D\uDEB6\uD83C\uDFFF\u200D\u2640\uFE0F":"1f6b6-1f3ff-2640","\uD83D\uDEB6\uD83C\uDFFF\u200D\u2642\uFE0F":"1f6b6-1f3ff-2642","\uD83E\uDD38\uD83C\uDFFB\u200D\u2640\uFE0F":"1f938-1f3fb-2640","\uD83E\uDD38\uD83C\uDFFB\u200D\u2642\uFE0F":"1f938-1f3fb-2642","\uD83E\uDD38\uD83C\uDFFC\u200D\u2640\uFE0F":"1f938-1f3fc-2640","\uD83E\uDD38\uD83C\uDFFC\u200D\u2642\uFE0F":"1f938-1f3fc-2642","\uD83E\uDD38\uD83C\uDFFD\u200D\u2640\uFE0F":"1f938-1f3fd-2640","\uD83E\uDD38\uD83C\uDFFD\u200D\u2642\uFE0F":"1f938-1f3fd-2642","\uD83E\uDD38\uD83C\uDFFE\u200D\u2640\uFE0F":"1f938-1f3fe-2640","\uD83E\uDD38\uD83C\uDFFE\u200D\u2642\uFE0F":"1f938-1f3fe-2642","\uD83E\uDD38\uD83C\uDFFF\u200D\u2640\uFE0F":"1f938-1f3ff-2640","\uD83E\uDD38\uD83C\uDFFF\u200D\u2642\uFE0F":"1f938-1f3ff-2642","\uD83E\uDD39\uD83C\uDFFB\u200D\u2640\uFE0F":"1f939-1f3fb-2640","\uD83E\uDD39\uD83C\uDFFB\u200D\u2642\uFE0F":"1f939-1f3fb-2642","\uD83E\uDD39\uD83C\uDFFC\u200D\u2640\uFE0F":"1f939-1f3fc-2640","\uD83E\uDD39\uD83C\uDFFC\u200D\u2642\uFE0F":"1f939-1f3fc-2642","\uD83E\uDD39\uD83C\uDFFD\u200D\u2640\uFE0F":"1f939-1f3fd-2640","\uD83E\uDD39\uD83C\uDFFD\u200D\u2642\uFE0F":"1f939-1f3fd-2642","\uD83E\uDD39\uD83C\uDFFE\u200D\u2640\uFE0F":"1f939-1f3fe-2640","\uD83E\uDD39\uD83C\uDFFE\u200D\u2642\uFE0F":"1f939-1f3fe-2642","\uD83E\uDD39\uD83C\uDFFF\u200D\u2640\uFE0F":"1f939-1f3ff-2640","\uD83E\uDD39\uD83C\uDFFF\u200D\u2642\uFE0F":"1f939-1f3ff-2642","\uD83E\uDD3D\uD83C\uDFFB\u200D\u2640\uFE0F":"1f93d-1f3fb-2640","\uD83E\uDD3D\uD83C\uDFFB\u200D\u2642\uFE0F":"1f93d-1f3fb-2642","\uD83E\uDD3D\uD83C\uDFFC\u200D\u2640\uFE0F":"1f93d-1f3fc-2640","\uD83E\uDD3D\uD83C\uDFFC\u200D\u2642\uFE0F":"1f93d-1f3fc-2642","\uD83E\uDD3D\uD83C\uDFFD\u200D\u2640\uFE0F":"1f93d-1f3fd-2640","\uD83E\uDD3D\uD83C\uDFFD\u200D\u2642\uFE0F":"1f93d-1f3fd-2642","\uD83E\uDD3D\uD83C\uDFFE\u200D\u2640\uFE0F":"1f93d-1f3fe-2640","\uD83E\uDD3D\uD83C\uDFFE\u200D\u2642\uFE0F":"1f93d-1f3fe-2642","\uD83E\uDD3D\uD83C\uDFFF\u200D\u2640\uFE0F":"1f93d-1f3ff-2640","\uD83E\uDD3D\uD83C\uDFFF\u200D\u2642\uFE0F":"1f93d-1f3ff-2642","\uD83E\uDD3E\uD83C\uDFFB\u200D\u2640\uFE0F":"1f93e-1f3fb-2640","\uD83E\uDD3E\uD83C\uDFFB\u200D\u2642\uFE0F":"1f93e-1f3fb-2642","\uD83E\uDD3E\uD83C\uDFFC\u200D\u2640\uFE0F":"1f93e-1f3fc-2640","\uD83E\uDD3E\uD83C\uDFFC\u200D\u2642\uFE0F":"1f93e-1f3fc-2642","\uD83E\uDD3E\uD83C\uDFFD\u200D\u2640\uFE0F":"1f93e-1f3fd-2640","\uD83E\uDD3E\uD83C\uDFFD\u200D\u2642\uFE0F":"1f93e-1f3fd-2642","\uD83E\uDD3E\uD83C\uDFFE\u200D\u2640\uFE0F":"1f93e-1f3fe-2640","\uD83E\uDD3E\uD83C\uDFFE\u200D\u2642\uFE0F":"1f93e-1f3fe-2642","\uD83E\uDD3E\uD83C\uDFFF\u200D\u2640\uFE0F":"1f93e-1f3ff-2640","\uD83E\uDD3E\uD83C\uDFFF\u200D\u2642\uFE0F":"1f93e-1f3ff-2642","\uD83D\uDC81\uD83C\uDFFB\u200D\u2640\uFE0F":"1f481-1f3fb-2640","\uD83D\uDC81\uD83C\uDFFB\u200D\u2642\uFE0F":"1f481-1f3fb-2642","\uD83D\uDC81\uD83C\uDFFC\u200D\u2640\uFE0F":"1f481-1f3fc-2640","\uD83D\uDC81\uD83C\uDFFC\u200D\u2642\uFE0F":"1f481-1f3fc-2642","\uD83D\uDC81\uD83C\uDFFD\u200D\u2640\uFE0F":"1f481-1f3fd-2640","\uD83D\uDC81\uD83C\uDFFD\u200D\u2642\uFE0F":"1f481-1f3fd-2642","\uD83D\uDC81\uD83C\uDFFE\u200D\u2640\uFE0F":"1f481-1f3fe-2640","\uD83D\uDC81\uD83C\uDFFE\u200D\u2642\uFE0F":"1f481-1f3fe-2642","\uD83D\uDC81\uD83C\uDFFF\u200D\u2640\uFE0F":"1f481-1f3ff-2640","\uD83D\uDC81\uD83C\uDFFF\u200D\u2642\uFE0F":"1f481-1f3ff-2642","\uD83D\uDE45\uD83C\uDFFB\u200D\u2640\uFE0F":"1f645-1f3fb-2640","\uD83D\uDE45\uD83C\uDFFB\u200D\u2642\uFE0F":"1f645-1f3fb-2642","\uD83D\uDE45\uD83C\uDFFC\u200D\u2640\uFE0F":"1f645-1f3fc-2640","\uD83D\uDE45\uD83C\uDFFC\u200D\u2642\uFE0F":"1f645-1f3fc-2642","\uD83D\uDE45\uD83C\uDFFD\u200D\u2640\uFE0F":"1f645-1f3fd-2640","\uD83D\uDE45\uD83C\uDFFD\u200D\u2642\uFE0F":"1f645-1f3fd-2642","\uD83D\uDE45\uD83C\uDFFE\u200D\u2640\uFE0F":"1f645-1f3fe-2640","\uD83D\uDE45\uD83C\uDFFE\u200D\u2642\uFE0F":"1f645-1f3fe-2642","\uD83D\uDE45\uD83C\uDFFF\u200D\u2640\uFE0F":"1f645-1f3ff-2640","\uD83D\uDE45\uD83C\uDFFF\u200D\u2642\uFE0F":"1f645-1f3ff-2642","\uD83D\uDE46\uD83C\uDFFB\u200D\u2640\uFE0F":"1f646-1f3fb-2640","\uD83D\uDE46\uD83C\uDFFB\u200D\u2642\uFE0F":"1f646-1f3fb-2642","\uD83D\uDE46\uD83C\uDFFC\u200D\u2640\uFE0F":"1f646-1f3fc-2640","\uD83D\uDE46\uD83C\uDFFC\u200D\u2642\uFE0F":"1f646-1f3fc-2642","\uD83D\uDE46\uD83C\uDFFD\u200D\u2640\uFE0F":"1f646-1f3fd-2640","\uD83D\uDE46\uD83C\uDFFD\u200D\u2642\uFE0F":"1f646-1f3fd-2642","\uD83D\uDE46\uD83C\uDFFE\u200D\u2640\uFE0F":"1f646-1f3fe-2640","\uD83D\uDE46\uD83C\uDFFE\u200D\u2642\uFE0F":"1f646-1f3fe-2642","\uD83D\uDE46\uD83C\uDFFF\u200D\u2640\uFE0F":"1f646-1f3ff-2640","\uD83D\uDE46\uD83C\uDFFF\u200D\u2642\uFE0F":"1f646-1f3ff-2642","\uD83D\uDE47\uD83C\uDFFB\u200D\u2640\uFE0F":"1f647-1f3fb-2640","\uD83D\uDE47\uD83C\uDFFB\u200D\u2642\uFE0F":"1f647-1f3fb-2642","\uD83D\uDE47\uD83C\uDFFC\u200D\u2640\uFE0F":"1f647-1f3fc-2640","\uD83D\uDE47\uD83C\uDFFC\u200D\u2642\uFE0F":"1f647-1f3fc-2642","\uD83D\uDE47\uD83C\uDFFD\u200D\u2640\uFE0F":"1f647-1f3fd-2640","\uD83D\uDE47\uD83C\uDFFD\u200D\u2642\uFE0F":"1f647-1f3fd-2642","\uD83D\uDE47\uD83C\uDFFE\u200D\u2640\uFE0F":"1f647-1f3fe-2640","\uD83D\uDE47\uD83C\uDFFE\u200D\u2642\uFE0F":"1f647-1f3fe-2642","\uD83D\uDE47\uD83C\uDFFF\u200D\u2640\uFE0F":"1f647-1f3ff-2640","\uD83D\uDE47\uD83C\uDFFF\u200D\u2642\uFE0F":"1f647-1f3ff-2642","\uD83D\uDE4B\uD83C\uDFFB\u200D\u2640\uFE0F":"1f64b-1f3fb-2640","\uD83D\uDE4B\uD83C\uDFFB\u200D\u2642\uFE0F":"1f64b-1f3fb-2642","\uD83D\uDE4B\uD83C\uDFFC\u200D\u2640\uFE0F":"1f64b-1f3fc-2640","\uD83D\uDE4B\uD83C\uDFFC\u200D\u2642\uFE0F":"1f64b-1f3fc-2642","\uD83D\uDE4B\uD83C\uDFFD\u200D\u2640\uFE0F":"1f64b-1f3fd-2640","\uD83D\uDE4B\uD83C\uDFFD\u200D\u2642\uFE0F":"1f64b-1f3fd-2642","\uD83D\uDE4B\uD83C\uDFFE\u200D\u2640\uFE0F":"1f64b-1f3fe-2640","\uD83D\uDE4B\uD83C\uDFFE\u200D\u2642\uFE0F":"1f64b-1f3fe-2642","\uD83D\uDE4B\uD83C\uDFFF\u200D\u2640\uFE0F":"1f64b-1f3ff-2640","\uD83D\uDE4B\uD83C\uDFFF\u200D\u2642\uFE0F":"1f64b-1f3ff-2642","\uD83D\uDE4D\uD83C\uDFFB\u200D\u2640\uFE0F":"1f64d-1f3fb-2640","\uD83D\uDE4D\uD83C\uDFFB\u200D\u2642\uFE0F":"1f64d-1f3fb-2642","\uD83D\uDE4D\uD83C\uDFFC\u200D\u2640\uFE0F":"1f64d-1f3fc-2640","\uD83D\uDE4D\uD83C\uDFFC\u200D\u2642\uFE0F":"1f64d-1f3fc-2642","\uD83D\uDE4D\uD83C\uDFFD\u200D\u2640\uFE0F":"1f64d-1f3fd-2640","\uD83D\uDE4D\uD83C\uDFFD\u200D\u2642\uFE0F":"1f64d-1f3fd-2642","\uD83D\uDE4D\uD83C\uDFFE\u200D\u2640\uFE0F":"1f64d-1f3fe-2640","\uD83D\uDE4D\uD83C\uDFFE\u200D\u2642\uFE0F":"1f64d-1f3fe-2642","\uD83D\uDE4D\uD83C\uDFFF\u200D\u2640\uFE0F":"1f64d-1f3ff-2640","\uD83D\uDE4D\uD83C\uDFFF\u200D\u2642\uFE0F":"1f64d-1f3ff-2642","\uD83D\uDE4E\uD83C\uDFFB\u200D\u2640\uFE0F":"1f64e-1f3fb-2640","\uD83D\uDE4E\uD83C\uDFFB\u200D\u2642\uFE0F":"1f64e-1f3fb-2642","\uD83D\uDE4E\uD83C\uDFFC\u200D\u2640\uFE0F":"1f64e-1f3fc-2640","\uD83D\uDE4E\uD83C\uDFFC\u200D\u2642\uFE0F":"1f64e-1f3fc-2642","\uD83D\uDE4E\uD83C\uDFFD\u200D\u2640\uFE0F":"1f64e-1f3fd-2640","\uD83D\uDE4E\uD83C\uDFFD\u200D\u2642\uFE0F":"1f64e-1f3fd-2642","\uD83D\uDE4E\uD83C\uDFFE\u200D\u2640\uFE0F":"1f64e-1f3fe-2640","\uD83D\uDE4E\uD83C\uDFFE\u200D\u2642\uFE0F":"1f64e-1f3fe-2642","\uD83D\uDE4E\uD83C\uDFFF\u200D\u2640\uFE0F":"1f64e-1f3ff-2640","\uD83D\uDE4E\uD83C\uDFFF\u200D\u2642\uFE0F":"1f64e-1f3ff-2642","\uD83E\uDD26\uD83C\uDFFB\u200D\u2640\uFE0F":"1f926-1f3fb-2640","\uD83E\uDD26\uD83C\uDFFB\u200D\u2642\uFE0F":"1f926-1f3fb-2642","\uD83E\uDD26\uD83C\uDFFC\u200D\u2640\uFE0F":"1f926-1f3fc-2640","\uD83E\uDD26\uD83C\uDFFC\u200D\u2642\uFE0F":"1f926-1f3fc-2642","\uD83E\uDD26\uD83C\uDFFD\u200D\u2640\uFE0F":"1f926-1f3fd-2640","\uD83E\uDD26\uD83C\uDFFD\u200D\u2642\uFE0F":"1f926-1f3fd-2642","\uD83E\uDD26\uD83C\uDFFE\u200D\u2640\uFE0F":"1f926-1f3fe-2640","\uD83E\uDD26\uD83C\uDFFE\u200D\u2642\uFE0F":"1f926-1f3fe-2642","\uD83E\uDD26\uD83C\uDFFF\u200D\u2640\uFE0F":"1f926-1f3ff-2640","\uD83E\uDD26\uD83C\uDFFF\u200D\u2642\uFE0F":"1f926-1f3ff-2642","\uD83E\uDD37\uD83C\uDFFB\u200D\u2640\uFE0F":"1f937-1f3fb-2640","\uD83E\uDD37\uD83C\uDFFB\u200D\u2642\uFE0F":"1f937-1f3fb-2642","\uD83E\uDD37\uD83C\uDFFC\u200D\u2640\uFE0F":"1f937-1f3fc-2640","\uD83E\uDD37\uD83C\uDFFC\u200D\u2642\uFE0F":"1f937-1f3fc-2642","\uD83E\uDD37\uD83C\uDFFD\u200D\u2640\uFE0F":"1f937-1f3fd-2640","\uD83E\uDD37\uD83C\uDFFD\u200D\u2642\uFE0F":"1f937-1f3fd-2642","\uD83E\uDD37\uD83C\uDFFE\u200D\u2640\uFE0F":"1f937-1f3fe-2640","\uD83E\uDD37\uD83C\uDFFE\u200D\u2642\uFE0F":"1f937-1f3fe-2642","\uD83E\uDD37\uD83C\uDFFF\u200D\u2640\uFE0F":"1f937-1f3ff-2640","\uD83E\uDD37\uD83C\uDFFF\u200D\u2642\uFE0F":"1f937-1f3ff-2642","\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8\uFE0F":"1f441-1f5e8","\uD83D\uDD75\uD83C\uDFFB\u200D\u2640\uFE0F":"1f575-1f3fb-2640","\uD83D\uDD75\uD83C\uDFFB\u200D\u2642\uFE0F":"1f575-1f3fb-2642","\uD83D\uDD75\uD83C\uDFFC\u200D\u2640\uFE0F":"1f575-1f3fc-2640","\uD83D\uDD75\uD83C\uDFFC\u200D\u2642\uFE0F":"1f575-1f3fc-2642","\uD83D\uDD75\uD83C\uDFFD\u200D\u2640\uFE0F":"1f575-1f3fd-2640","\uD83D\uDD75\uD83C\uDFFD\u200D\u2642\uFE0F":"1f575-1f3fd-2642","\uD83D\uDD75\uD83C\uDFFE\u200D\u2640\uFE0F":"1f575-1f3fe-2640","\uD83D\uDD75\uD83C\uDFFE\u200D\u2642\uFE0F":"1f575-1f3fe-2642","\uD83D\uDD75\uD83C\uDFFF\u200D\u2640\uFE0F":"1f575-1f3ff-2640","\uD83D\uDD75\uD83C\uDFFF\u200D\u2642\uFE0F":"1f575-1f3ff-2642","\uD83C\uDFCB\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3cb-1f3fb-2640","\uD83C\uDFCB\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3cb-1f3fb-2642","\uD83C\uDFCB\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3cb-1f3fc-2640","\uD83C\uDFCB\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3cb-1f3fc-2642","\uD83C\uDFCB\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3cb-1f3fd-2640","\uD83C\uDFCB\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3cb-1f3fd-2642","\uD83C\uDFCB\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3cb-1f3fe-2640","\uD83C\uDFCB\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3cb-1f3fe-2642","\uD83C\uDFCB\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3cb-1f3ff-2640","\uD83C\uDFCB\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3cb-1f3ff-2642","\uD83C\uDFCC\uD83C\uDFFB\u200D\u2640\uFE0F":"1f3cc-1f3fb-2640","\uD83C\uDFCC\uD83C\uDFFB\u200D\u2642\uFE0F":"1f3cc-1f3fb-2642","\uD83C\uDFCC\uD83C\uDFFC\u200D\u2640\uFE0F":"1f3cc-1f3fc-2640","\uD83C\uDFCC\uD83C\uDFFC\u200D\u2642\uFE0F":"1f3cc-1f3fc-2642","\uD83C\uDFCC\uD83C\uDFFD\u200D\u2640\uFE0F":"1f3cc-1f3fd-2640","\uD83C\uDFCC\uD83C\uDFFD\u200D\u2642\uFE0F":"1f3cc-1f3fd-2642","\uD83C\uDFCC\uD83C\uDFFE\u200D\u2640\uFE0F":"1f3cc-1f3fe-2640","\uD83C\uDFCC\uD83C\uDFFE\u200D\u2642\uFE0F":"1f3cc-1f3fe-2642","\uD83C\uDFCC\uD83C\uDFFF\u200D\u2640\uFE0F":"1f3cc-1f3ff-2640","\uD83C\uDFCC\uD83C\uDFFF\u200D\u2642\uFE0F":"1f3cc-1f3ff-2642","\uD83E\uDDD9\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9d9-1f3fb-2640","\uD83E\uDDD9\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9d9-1f3fb-2642","\uD83E\uDDD9\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9d9-1f3fc-2640","\uD83E\uDDD9\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9d9-1f3fc-2642","\uD83E\uDDD9\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9d9-1f3fd-2640","\uD83E\uDDD9\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9d9-1f3fd-2642","\uD83E\uDDD9\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9d9-1f3fe-2640","\uD83E\uDDD9\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9d9-1f3fe-2642","\uD83E\uDDD9\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9d9-1f3ff-2640","\uD83E\uDDD9\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9d9-1f3ff-2642","\uD83E\uDDDA\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9da-1f3fb-2640","\uD83E\uDDDA\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9da-1f3fb-2642","\uD83E\uDDDA\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9da-1f3fc-2640","\uD83E\uDDDA\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9da-1f3fc-2642","\uD83E\uDDDA\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9da-1f3fd-2640","\uD83E\uDDDA\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9da-1f3fd-2642","\uD83E\uDDDA\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9da-1f3fe-2640","\uD83E\uDDDA\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9da-1f3fe-2642","\uD83E\uDDDA\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9da-1f3ff-2640","\uD83E\uDDDA\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9da-1f3ff-2642","\uD83E\uDDDB\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9db-1f3fb-2640","\uD83E\uDDDB\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9db-1f3fb-2642","\uD83E\uDDDB\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9db-1f3fc-2640","\uD83E\uDDDB\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9db-1f3fc-2642","\uD83E\uDDDB\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9db-1f3fd-2640","\uD83E\uDDDB\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9db-1f3fd-2642","\uD83E\uDDDB\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9db-1f3fe-2640","\uD83E\uDDDB\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9db-1f3fe-2642","\uD83E\uDDDB\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9db-1f3ff-2640","\uD83E\uDDDB\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9db-1f3ff-2642","\uD83E\uDDDC\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9dc-1f3fb-2640","\uD83E\uDDDC\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9dc-1f3fb-2642","\uD83E\uDDDC\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9dc-1f3fc-2640","\uD83E\uDDDC\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9dc-1f3fc-2642","\uD83E\uDDDC\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9dc-1f3fd-2640","\uD83E\uDDDC\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9dc-1f3fd-2642","\uD83E\uDDDC\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9dc-1f3fe-2640","\uD83E\uDDDC\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9dc-1f3fe-2642","\uD83E\uDDDC\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9dc-1f3ff-2640","\uD83E\uDDDC\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9dc-1f3ff-2642","\uD83E\uDDDD\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9dd-1f3fb-2640","\uD83E\uDDDD\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9dd-1f3fb-2642","\uD83E\uDDDD\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9dd-1f3fc-2640","\uD83E\uDDDD\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9dd-1f3fc-2642","\uD83E\uDDDD\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9dd-1f3fd-2640","\uD83E\uDDDD\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9dd-1f3fd-2642","\uD83E\uDDDD\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9dd-1f3fe-2640","\uD83E\uDDDD\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9dd-1f3fe-2642","\uD83E\uDDDD\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9dd-1f3ff-2640","\uD83E\uDDDD\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9dd-1f3ff-2642","\uD83E\uDDD6\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9d6-1f3fb-2640","\uD83E\uDDD6\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9d6-1f3fb-2642","\uD83E\uDDD6\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9d6-1f3fc-2640","\uD83E\uDDD6\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9d6-1f3fc-2642","\uD83E\uDDD6\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9d6-1f3fd-2640","\uD83E\uDDD6\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9d6-1f3fd-2642","\uD83E\uDDD6\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9d6-1f3fe-2640","\uD83E\uDDD6\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9d6-1f3fe-2642","\uD83E\uDDD6\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9d6-1f3ff-2640","\uD83E\uDDD6\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9d6-1f3ff-2642","\uD83E\uDDD7\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9d7-1f3fb-2640","\uD83E\uDDD7\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9d7-1f3fb-2642","\uD83E\uDDD7\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9d7-1f3fc-2640","\uD83E\uDDD7\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9d7-1f3fc-2642","\uD83E\uDDD7\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9d7-1f3fd-2640","\uD83E\uDDD7\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9d7-1f3fd-2642","\uD83E\uDDD7\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9d7-1f3fe-2640","\uD83E\uDDD7\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9d7-1f3fe-2642","\uD83E\uDDD7\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9d7-1f3ff-2640","\uD83E\uDDD7\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9d7-1f3ff-2642","\uD83E\uDDD8\uD83C\uDFFB\u200D\u2640\uFE0F":"1f9d8-1f3fb-2640","\uD83E\uDDD8\uD83C\uDFFB\u200D\u2642\uFE0F":"1f9d8-1f3fb-2642","\uD83E\uDDD8\uD83C\uDFFC\u200D\u2640\uFE0F":"1f9d8-1f3fc-2640","\uD83E\uDDD8\uD83C\uDFFC\u200D\u2642\uFE0F":"1f9d8-1f3fc-2642","\uD83E\uDDD8\uD83C\uDFFD\u200D\u2640\uFE0F":"1f9d8-1f3fd-2640","\uD83E\uDDD8\uD83C\uDFFD\u200D\u2642\uFE0F":"1f9d8-1f3fd-2642","\uD83E\uDDD8\uD83C\uDFFE\u200D\u2640\uFE0F":"1f9d8-1f3fe-2640","\uD83E\uDDD8\uD83C\uDFFE\u200D\u2642\uFE0F":"1f9d8-1f3fe-2642","\uD83E\uDDD8\uD83C\uDFFF\u200D\u2640\uFE0F":"1f9d8-1f3ff-2640","\uD83E\uDDD8\uD83C\uDFFF\u200D\u2642\uFE0F":"1f9d8-1f3ff-2642","\uD83D\uDD75\uFE0F\u200D\u2640\uFE0F":"1f575-2640","\uD83D\uDD75\uFE0F\u200D\u2642\uFE0F":"1f575-2642","\u26F9\uFE0F\uD83C\uDFFB\u2640\uFE0F":"26f9-1f3fb-2640","\u26F9\uFE0F\uD83C\uDFFB\u2642\uFE0F":"26f9-1f3fb-2642","\u26F9\uFE0F\uD83C\uDFFC\u2640\uFE0F":"26f9-1f3fc-2640","\u26F9\uFE0F\uD83C\uDFFC\u2642\uFE0F":"26f9-1f3fc-2642","\u26F9\uFE0F\uD83C\uDFFD\u2640\uFE0F":"26f9-1f3fd-2640","\u26F9\uFE0F\uD83C\uDFFD\u2642\uFE0F":"26f9-1f3fd-2642","\u26F9\uFE0F\uD83C\uDFFE\u2640\uFE0F":"26f9-1f3fe-2640","\u26F9\uFE0F\uD83C\uDFFE\u2642\uFE0F":"26f9-1f3fe-2642","\u26F9\uFE0F\uD83C\uDFFF\u2640\uFE0F":"26f9-1f3ff-2640","\u26F9\uFE0F\uD83C\uDFFF\u2642\uFE0F":"26f9-1f3ff-2642","\uD83C\uDFCB\uFE0F\u200D\u2640\uFE0F":"1f3cb-2640","\uD83C\uDFCB\uFE0F\u200D\u2642\uFE0F":"1f3cb-2642","\uD83C\uDFCC\uFE0F\u200D\u2640\uFE0F":"1f3cc-2640","\uD83C\uDFCC\uFE0F\u200D\u2642\uFE0F":"1f3cc-2642","\u26F9\uD83C\uDFFB\u200D\u2640\uFE0F":"26f9-1f3fb-2640","\u26F9\uD83C\uDFFB\u200D\u2642\uFE0F":"26f9-1f3fb-2642","\u26F9\uD83C\uDFFC\u200D\u2640\uFE0F":"26f9-1f3fc-2640","\u26F9\uD83C\uDFFC\u200D\u2642\uFE0F":"26f9-1f3fc-2642","\u26F9\uD83C\uDFFD\u200D\u2640\uFE0F":"26f9-1f3fd-2640","\u26F9\uD83C\uDFFD\u200D\u2642\uFE0F":"26f9-1f3fd-2642","\u26F9\uD83C\uDFFE\u200D\u2640\uFE0F":"26f9-1f3fe-2640","\u26F9\uD83C\uDFFE\u200D\u2642\uFE0F":"26f9-1f3fe-2642","\u26F9\uD83C\uDFFF\u200D\u2640\uFE0F":"26f9-1f3ff-2640","\u26F9\uD83C\uDFFF\u200D\u2642\uFE0F":"26f9-1f3ff-2642","\u26F9\uFE0F\u200D\u2640\uFE0F":"26f9-2640","\u26F9\uFE0F\u200D\u2642\uFE0F":"26f9-2642","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC66\uD83D\uDC66":"1f468-1f468-1f466-1f466","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC67\uD83D\uDC66":"1f468-1f468-1f467-1f466","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC67\uD83D\uDC67":"1f468-1f468-1f467-1f467","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC66\uD83D\uDC66":"1f468-1f469-1f466-1f466","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC67\uD83D\uDC66":"1f468-1f469-1f467-1f466","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC67\uD83D\uDC67":"1f468-1f469-1f467-1f467","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC66\uD83D\uDC66":"1f469-1f469-1f466-1f466","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC67\uD83D\uDC66":"1f469-1f469-1f467-1f466","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC67\uD83D\uDC67":"1f469-1f469-1f467-1f467","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDCBB":"1f468-1f3ff-1f4bb","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDCBB":"1f468-1f3fe-1f4bb","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDCBB":"1f468-1f3fd-1f4bb","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDCBB":"1f468-1f3fc-1f4bb","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDCBB":"1f468-1f3fb-1f4bb","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDCBB":"1f469-1f3ff-1f4bb","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDCBB":"1f469-1f3fe-1f4bb","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDCBB":"1f469-1f3fd-1f4bb","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDCBB":"1f469-1f3fc-1f4bb","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDCBB":"1f469-1f3fb-1f4bb","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDFEB":"1f468-1f3ff-1f3eb","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDFEB":"1f468-1f3fe-1f3eb","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDFEB":"1f468-1f3fd-1f3eb","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDFEB":"1f468-1f3fc-1f3eb","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDFEB":"1f468-1f3fb-1f3eb","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDFEB":"1f469-1f3ff-1f3eb","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDFEB":"1f469-1f3fe-1f3eb","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDFEB":"1f469-1f3fd-1f3eb","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDFEB":"1f469-1f3fc-1f3eb","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDFEB":"1f469-1f3fb-1f3eb","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDF93":"1f468-1f3ff-1f393","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDF93":"1f468-1f3fe-1f393","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDF93":"1f468-1f3fd-1f393","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDF93":"1f468-1f3fc-1f393","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDF93":"1f468-1f3fb-1f393","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDF93":"1f469-1f3ff-1f393","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDF93":"1f469-1f3fe-1f393","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDF93":"1f469-1f3fd-1f393","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDF93":"1f469-1f3fc-1f393","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDF93":"1f469-1f3fb-1f393","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDFA4":"1f468-1f3ff-1f3a4","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDFA4":"1f468-1f3fe-1f3a4","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDFA4":"1f468-1f3fd-1f3a4","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDFA4":"1f468-1f3fc-1f3a4","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDFA4":"1f468-1f3fb-1f3a4","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDFA4":"1f469-1f3ff-1f3a4","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDFA4":"1f469-1f3fe-1f3a4","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDFA4":"1f469-1f3fd-1f3a4","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDFA4":"1f469-1f3fc-1f3a4","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDFA4":"1f469-1f3fb-1f3a4","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDD2C":"1f468-1f3ff-1f52c","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDD2C":"1f468-1f3fe-1f52c","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDD2C":"1f468-1f3fd-1f52c","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDD2C":"1f468-1f3fc-1f52c","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDD2C":"1f468-1f3fb-1f52c","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDD2C":"1f469-1f3ff-1f52c","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDD2C":"1f469-1f3fe-1f52c","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDD2C":"1f469-1f3fd-1f52c","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDD2C":"1f469-1f3fc-1f52c","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDD2C":"1f469-1f3fb-1f52c","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDCBC":"1f468-1f3ff-1f4bc","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDCBC":"1f468-1f3fe-1f4bc","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDCBC":"1f468-1f3fd-1f4bc","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDCBC":"1f468-1f3fc-1f4bc","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDCBC":"1f468-1f3fb-1f4bc","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDCBC":"1f469-1f3ff-1f4bc","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDCBC":"1f469-1f3fe-1f4bc","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDCBC":"1f469-1f3fd-1f4bc","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDCBC":"1f469-1f3fc-1f4bc","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDCBC":"1f469-1f3fb-1f4bc","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDD27":"1f468-1f3ff-1f527","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDD27":"1f468-1f3fe-1f527","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDD27":"1f468-1f3fd-1f527","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDD27":"1f468-1f3fc-1f527","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDD27":"1f468-1f3fb-1f527","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDD27":"1f469-1f3ff-1f527","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDD27":"1f469-1f3fe-1f527","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDD27":"1f469-1f3fd-1f527","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDD27":"1f469-1f3fc-1f527","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDD27":"1f469-1f3fb-1f527","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDFED":"1f468-1f3ff-1f3ed","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDFED":"1f468-1f3fe-1f3ed","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDFED":"1f468-1f3fd-1f3ed","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDFED":"1f468-1f3fc-1f3ed","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDFED":"1f468-1f3fb-1f3ed","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDFED":"1f469-1f3ff-1f3ed","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDFED":"1f469-1f3fe-1f3ed","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDFED":"1f469-1f3fd-1f3ed","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDFED":"1f469-1f3fc-1f3ed","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDFED":"1f469-1f3fb-1f3ed","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDF73":"1f468-1f3ff-1f373","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDF73":"1f468-1f3fe-1f373","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDF73":"1f468-1f3fd-1f373","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDF73":"1f468-1f3fc-1f373","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDF73":"1f468-1f3fb-1f373","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDF73":"1f469-1f3ff-1f373","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDF73":"1f469-1f3fe-1f373","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDF73":"1f469-1f3fd-1f373","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDF73":"1f469-1f3fc-1f373","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDF73":"1f469-1f3fb-1f373","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDF3E":"1f468-1f3ff-1f33e","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDF3E":"1f468-1f3fe-1f33e","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDF3E":"1f468-1f3fd-1f33e","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDF3E":"1f468-1f3fc-1f33e","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDF3E":"1f468-1f3fb-1f33e","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDF3E":"1f469-1f3ff-1f33e","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDF3E":"1f469-1f3fe-1f33e","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDF3E":"1f469-1f3fd-1f33e","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDF3E":"1f469-1f3fc-1f33e","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDF3E":"1f469-1f3fb-1f33e","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83C\uDFA8":"1f468-1f3fb-1f3a8","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83C\uDFA8":"1f468-1f3fc-1f3a8","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83C\uDFA8":"1f468-1f3fd-1f3a8","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83C\uDFA8":"1f468-1f3fe-1f3a8","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83C\uDFA8":"1f468-1f3ff-1f3a8","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83C\uDFA8":"1f469-1f3fb-1f3a8","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83C\uDFA8":"1f469-1f3fc-1f3a8","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83C\uDFA8":"1f469-1f3fd-1f3a8","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83C\uDFA8":"1f469-1f3fe-1f3a8","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83C\uDFA8":"1f469-1f3ff-1f3a8","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDE80":"1f468-1f3fb-1f680","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDE80":"1f468-1f3fc-1f680","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDE80":"1f468-1f3fd-1f680","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDE80":"1f468-1f3fe-1f680","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDE80":"1f468-1f3ff-1f680","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDE80":"1f469-1f3fb-1f680","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDE80":"1f469-1f3fc-1f680","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDE80":"1f469-1f3fd-1f680","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDE80":"1f469-1f3fe-1f680","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDE80":"1f469-1f3ff-1f680","\uD83D\uDC68\uD83C\uDFFB\u200D\uD83D\uDE92":"1f468-1f3fb-1f692","\uD83D\uDC68\uD83C\uDFFC\u200D\uD83D\uDE92":"1f468-1f3fc-1f692","\uD83D\uDC68\uD83C\uDFFD\u200D\uD83D\uDE92":"1f468-1f3fd-1f692","\uD83D\uDC68\uD83C\uDFFE\u200D\uD83D\uDE92":"1f468-1f3fe-1f692","\uD83D\uDC68\uD83C\uDFFF\u200D\uD83D\uDE92":"1f468-1f3ff-1f692","\uD83D\uDC69\uD83C\uDFFB\u200D\uD83D\uDE92":"1f469-1f3fb-1f692","\uD83D\uDC69\uD83C\uDFFC\u200D\uD83D\uDE92":"1f469-1f3fc-1f692","\uD83D\uDC69\uD83C\uDFFD\u200D\uD83D\uDE92":"1f469-1f3fd-1f692","\uD83D\uDC69\uD83C\uDFFE\u200D\uD83D\uDE92":"1f469-1f3fe-1f692","\uD83D\uDC69\uD83C\uDFFF\u200D\uD83D\uDE92":"1f469-1f3ff-1f692","\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08":"1f3f3-1f308","\uD83C\uDFCC\uD83C\uDFFB\u200D\u2642":"1f3cc-1f3fb-2642","\uD83C\uDFCC\uD83C\uDFFC\u200D\u2642":"1f3cc-1f3fc-2642","\uD83C\uDFCC\uD83C\uDFFD\u200D\u2642":"1f3cc-1f3fd-2642","\uD83C\uDFCC\uD83C\uDFFE\u200D\u2642":"1f3cc-1f3fe-2642","\uD83C\uDFCC\uD83C\uDFFF\u200D\u2642":"1f3cc-1f3ff-2642","\uD83C\uDFCC\uD83C\uDFFB\u200D\u2640":"1f3cc-1f3fb-2640","\uD83C\uDFCC\uD83C\uDFFC\u200D\u2640":"1f3cc-1f3fc-2640","\uD83C\uDFCC\uD83C\uDFFD\u200D\u2640":"1f3cc-1f3fd-2640","\uD83C\uDFCC\uD83C\uDFFE\u200D\u2640":"1f3cc-1f3fe-2640","\uD83C\uDFCC\uD83C\uDFFF\u200D\u2640":"1f3cc-1f3ff-2640","\uD83E\uDD39\uD83C\uDFFF\u200D\u2642":"1f939-1f3ff-2642","\uD83E\uDD39\uD83C\uDFFE\u200D\u2642":"1f939-1f3fe-2642","\uD83E\uDD39\uD83C\uDFFD\u200D\u2642":"1f939-1f3fd-2642","\uD83E\uDD39\uD83C\uDFFC\u200D\u2642":"1f939-1f3fc-2642","\uD83E\uDD39\uD83C\uDFFB\u200D\u2642":"1f939-1f3fb-2642","\uD83E\uDD39\uD83C\uDFFF\u200D\u2640":"1f939-1f3ff-2640","\uD83E\uDD39\uD83C\uDFFE\u200D\u2640":"1f939-1f3fe-2640","\uD83E\uDD39\uD83C\uDFFD\u200D\u2640":"1f939-1f3fd-2640","\uD83E\uDD39\uD83C\uDFFC\u200D\u2640":"1f939-1f3fc-2640","\uD83E\uDD39\uD83C\uDFFB\u200D\u2640":"1f939-1f3fb-2640","\uD83E\uDD3E\uD83C\uDFFF\u200D\u2642":"1f93e-1f3ff-2642","\uD83E\uDD3E\uD83C\uDFFE\u200D\u2642":"1f93e-1f3fe-2642","\uD83E\uDD3E\uD83C\uDFFD\u200D\u2642":"1f93e-1f3fd-2642","\uD83E\uDD3E\uD83C\uDFFC\u200D\u2642":"1f93e-1f3fc-2642","\uD83E\uDD3E\uD83C\uDFFB\u200D\u2642":"1f93e-1f3fb-2642","\uD83E\uDD3E\uD83C\uDFFF\u200D\u2640":"1f93e-1f3ff-2640","\uD83E\uDD3E\uD83C\uDFFE\u200D\u2640":"1f93e-1f3fe-2640","\uD83E\uDD3E\uD83C\uDFFD\u200D\u2640":"1f93e-1f3fd-2640","\uD83E\uDD3E\uD83C\uDFFC\u200D\u2640":"1f93e-1f3fc-2640","\uD83E\uDD3E\uD83C\uDFFB\u200D\u2640":"1f93e-1f3fb-2640","\uD83E\uDD3D\uD83C\uDFFF\u200D\u2642":"1f93d-1f3ff-2642","\uD83E\uDD3D\uD83C\uDFFE\u200D\u2642":"1f93d-1f3fe-2642","\uD83E\uDD3D\uD83C\uDFFD\u200D\u2642":"1f93d-1f3fd-2642","\uD83E\uDD3D\uD83C\uDFFC\u200D\u2642":"1f93d-1f3fc-2642","\uD83E\uDD3D\uD83C\uDFFB\u200D\u2642":"1f93d-1f3fb-2642","\uD83E\uDD3D\uD83C\uDFFF\u200D\u2640":"1f93d-1f3ff-2640","\uD83E\uDD3D\uD83C\uDFFE\u200D\u2640":"1f93d-1f3fe-2640","\uD83E\uDD3D\uD83C\uDFFD\u200D\u2640":"1f93d-1f3fd-2640","\uD83E\uDD3D\uD83C\uDFFC\u200D\u2640":"1f93d-1f3fc-2640","\uD83E\uDD3D\uD83C\uDFFB\u200D\u2640":"1f93d-1f3fb-2640","\uD83E\uDD38\uD83C\uDFFF\u200D\u2642":"1f938-1f3ff-2642","\uD83E\uDD38\uD83C\uDFFE\u200D\u2642":"1f938-1f3fe-2642","\uD83E\uDD38\uD83C\uDFFD\u200D\u2642":"1f938-1f3fd-2642","\uD83E\uDD38\uD83C\uDFFC\u200D\u2642":"1f938-1f3fc-2642","\uD83E\uDD38\uD83C\uDFFB\u200D\u2642":"1f938-1f3fb-2642","\uD83E\uDD38\uD83C\uDFFF\u200D\u2640":"1f938-1f3ff-2640","\uD83E\uDD38\uD83C\uDFFE\u200D\u2640":"1f938-1f3fe-2640","\uD83E\uDD38\uD83C\uDFFD\u200D\u2640":"1f938-1f3fd-2640","\uD83E\uDD38\uD83C\uDFFC\u200D\u2640":"1f938-1f3fc-2640","\uD83E\uDD38\uD83C\uDFFB\u200D\u2640":"1f938-1f3fb-2640","\uD83D\uDEB6\uD83C\uDFFF\u200D\u2642":"1f6b6-1f3ff-2642","\uD83D\uDEB6\uD83C\uDFFE\u200D\u2642":"1f6b6-1f3fe-2642","\uD83D\uDEB6\uD83C\uDFFD\u200D\u2642":"1f6b6-1f3fd-2642","\uD83D\uDEB6\uD83C\uDFFC\u200D\u2642":"1f6b6-1f3fc-2642","\uD83D\uDEB6\uD83C\uDFFB\u200D\u2642":"1f6b6-1f3fb-2642","\uD83D\uDEB6\uD83C\uDFFF\u200D\u2640":"1f6b6-1f3ff-2640","\uD83D\uDEB6\uD83C\uDFFE\u200D\u2640":"1f6b6-1f3fe-2640","\uD83D\uDEB6\uD83C\uDFFD\u200D\u2640":"1f6b6-1f3fd-2640","\uD83D\uDEB6\uD83C\uDFFC\u200D\u2640":"1f6b6-1f3fc-2640","\uD83D\uDEB6\uD83C\uDFFB\u200D\u2640":"1f6b6-1f3fb-2640","\uD83D\uDEB5\uD83C\uDFFF\u200D\u2642":"1f6b5-1f3ff-2642","\uD83D\uDEB5\uD83C\uDFFE\u200D\u2642":"1f6b5-1f3fe-2642","\uD83D\uDEB5\uD83C\uDFFD\u200D\u2642":"1f6b5-1f3fd-2642","\uD83D\uDEB5\uD83C\uDFFC\u200D\u2642":"1f6b5-1f3fc-2642","\uD83D\uDEB5\uD83C\uDFFB\u200D\u2642":"1f6b5-1f3fb-2642","\uD83D\uDEB5\uD83C\uDFFF\u200D\u2640":"1f6b5-1f3ff-2640","\uD83D\uDEB5\uD83C\uDFFE\u200D\u2640":"1f6b5-1f3fe-2640","\uD83D\uDEB5\uD83C\uDFFD\u200D\u2640":"1f6b5-1f3fd-2640","\uD83D\uDEB5\uD83C\uDFFC\u200D\u2640":"1f6b5-1f3fc-2640","\uD83D\uDEB5\uD83C\uDFFB\u200D\u2640":"1f6b5-1f3fb-2640","\uD83D\uDEB4\uD83C\uDFFF\u200D\u2642":"1f6b4-1f3ff-2642","\uD83D\uDEB4\uD83C\uDFFE\u200D\u2642":"1f6b4-1f3fe-2642","\uD83D\uDEB4\uD83C\uDFFD\u200D\u2642":"1f6b4-1f3fd-2642","\uD83D\uDEB4\uD83C\uDFFC\u200D\u2642":"1f6b4-1f3fc-2642","\uD83D\uDEB4\uD83C\uDFFB\u200D\u2642":"1f6b4-1f3fb-2642","\uD83D\uDEB4\uD83C\uDFFF\u200D\u2640":"1f6b4-1f3ff-2640","\uD83D\uDEB4\uD83C\uDFFE\u200D\u2640":"1f6b4-1f3fe-2640","\uD83D\uDEB4\uD83C\uDFFD\u200D\u2640":"1f6b4-1f3fd-2640","\uD83D\uDEB4\uD83C\uDFFC\u200D\u2640":"1f6b4-1f3fc-2640","\uD83D\uDEB4\uD83C\uDFFB\u200D\u2640":"1f6b4-1f3fb-2640","\uD83D\uDEA3\uD83C\uDFFF\u200D\u2642":"1f6a3-1f3ff-2642","\uD83D\uDEA3\uD83C\uDFFE\u200D\u2642":"1f6a3-1f3fe-2642","\uD83D\uDEA3\uD83C\uDFFD\u200D\u2642":"1f6a3-1f3fd-2642","\uD83D\uDEA3\uD83C\uDFFC\u200D\u2642":"1f6a3-1f3fc-2642","\uD83D\uDEA3\uD83C\uDFFB\u200D\u2642":"1f6a3-1f3fb-2642","\uD83D\uDEA3\uD83C\uDFFF\u200D\u2640":"1f6a3-1f3ff-2640","\uD83D\uDEA3\uD83C\uDFFE\u200D\u2640":"1f6a3-1f3fe-2640","\uD83D\uDEA3\uD83C\uDFFD\u200D\u2640":"1f6a3-1f3fd-2640","\uD83D\uDEA3\uD83C\uDFFC\u200D\u2640":"1f6a3-1f3fc-2640","\uD83D\uDEA3\uD83C\uDFFB\u200D\u2640":"1f6a3-1f3fb-2640","\uD83C\uDFCB\uD83C\uDFFF\u200D\u2642":"1f3cb-1f3ff-2642","\uD83C\uDFCB\uD83C\uDFFE\u200D\u2642":"1f3cb-1f3fe-2642","\uD83C\uDFCB\uD83C\uDFFD\u200D\u2642":"1f3cb-1f3fd-2642","\uD83C\uDFCB\uD83C\uDFFC\u200D\u2642":"1f3cb-1f3fc-2642","\uD83C\uDFCB\uD83C\uDFFB\u200D\u2642":"1f3cb-1f3fb-2642","\uD83C\uDFCB\uD83C\uDFFF\u200D\u2640":"1f3cb-1f3ff-2640","\uD83C\uDFCB\uD83C\uDFFE\u200D\u2640":"1f3cb-1f3fe-2640","\uD83C\uDFCB\uD83C\uDFFD\u200D\u2640":"1f3cb-1f3fd-2640","\uD83C\uDFCB\uD83C\uDFFC\u200D\u2640":"1f3cb-1f3fc-2640","\uD83C\uDFCB\uD83C\uDFFB\u200D\u2640":"1f3cb-1f3fb-2640","\uD83C\uDFCA\uD83C\uDFFF\u200D\u2642":"1f3ca-1f3ff-2642","\uD83C\uDFCA\uD83C\uDFFE\u200D\u2642":"1f3ca-1f3fe-2642","\uD83C\uDFCA\uD83C\uDFFD\u200D\u2642":"1f3ca-1f3fd-2642","\uD83C\uDFCA\uD83C\uDFFC\u200D\u2642":"1f3ca-1f3fc-2642","\uD83C\uDFCA\uD83C\uDFFB\u200D\u2642":"1f3ca-1f3fb-2642","\uD83C\uDFCA\uD83C\uDFFF\u200D\u2640":"1f3ca-1f3ff-2640","\uD83C\uDFCA\uD83C\uDFFE\u200D\u2640":"1f3ca-1f3fe-2640","\uD83C\uDFCA\uD83C\uDFFD\u200D\u2640":"1f3ca-1f3fd-2640","\uD83C\uDFCA\uD83C\uDFFC\u200D\u2640":"1f3ca-1f3fc-2640","\uD83C\uDFCA\uD83C\uDFFB\u200D\u2640":"1f3ca-1f3fb-2640","\uD83C\uDFC4\uD83C\uDFFF\u200D\u2642":"1f3c4-1f3ff-2642","\uD83C\uDFC4\uD83C\uDFFE\u200D\u2642":"1f3c4-1f3fe-2642","\uD83C\uDFC4\uD83C\uDFFD\u200D\u2642":"1f3c4-1f3fd-2642","\uD83C\uDFC4\uD83C\uDFFC\u200D\u2642":"1f3c4-1f3fc-2642","\uD83C\uDFC4\uD83C\uDFFB\u200D\u2642":"1f3c4-1f3fb-2642","\uD83C\uDFC4\uD83C\uDFFF\u200D\u2640":"1f3c4-1f3ff-2640","\uD83C\uDFC4\uD83C\uDFFE\u200D\u2640":"1f3c4-1f3fe-2640","\uD83C\uDFC4\uD83C\uDFFD\u200D\u2640":"1f3c4-1f3fd-2640","\uD83C\uDFC4\uD83C\uDFFC\u200D\u2640":"1f3c4-1f3fc-2640","\uD83C\uDFC4\uD83C\uDFFB\u200D\u2640":"1f3c4-1f3fb-2640","\uD83C\uDFC3\uD83C\uDFFF\u200D\u2642":"1f3c3-1f3ff-2642","\uD83C\uDFC3\uD83C\uDFFE\u200D\u2642":"1f3c3-1f3fe-2642","\uD83C\uDFC3\uD83C\uDFFD\u200D\u2642":"1f3c3-1f3fd-2642","\uD83C\uDFC3\uD83C\uDFFC\u200D\u2642":"1f3c3-1f3fc-2642","\uD83C\uDFC3\uD83C\uDFFB\u200D\u2642":"1f3c3-1f3fb-2642","\uD83C\uDFC3\uD83C\uDFFF\u200D\u2640":"1f3c3-1f3ff-2640","\uD83C\uDFC3\uD83C\uDFFE\u200D\u2640":"1f3c3-1f3fe-2640","\uD83C\uDFC3\uD83C\uDFFD\u200D\u2640":"1f3c3-1f3fd-2640","\uD83C\uDFC3\uD83C\uDFFC\u200D\u2640":"1f3c3-1f3fc-2640","\uD83C\uDFC3\uD83C\uDFFB\u200D\u2640":"1f3c3-1f3fb-2640","\uD83E\uDD37\uD83C\uDFFF\u200D\u2642":"1f937-1f3ff-2642","\uD83E\uDD37\uD83C\uDFFE\u200D\u2642":"1f937-1f3fe-2642","\uD83E\uDD37\uD83C\uDFFD\u200D\u2642":"1f937-1f3fd-2642","\uD83E\uDD37\uD83C\uDFFC\u200D\u2642":"1f937-1f3fc-2642","\uD83E\uDD37\uD83C\uDFFB\u200D\u2642":"1f937-1f3fb-2642","\uD83E\uDD37\uD83C\uDFFF\u200D\u2640":"1f937-1f3ff-2640","\uD83E\uDD37\uD83C\uDFFE\u200D\u2640":"1f937-1f3fe-2640","\uD83E\uDD37\uD83C\uDFFD\u200D\u2640":"1f937-1f3fd-2640","\uD83E\uDD37\uD83C\uDFFC\u200D\u2640":"1f937-1f3fc-2640","\uD83E\uDD37\uD83C\uDFFB\u200D\u2640":"1f937-1f3fb-2640","\uD83E\uDD26\uD83C\uDFFF\u200D\u2642":"1f926-1f3ff-2642","\uD83E\uDD26\uD83C\uDFFE\u200D\u2642":"1f926-1f3fe-2642","\uD83E\uDD26\uD83C\uDFFD\u200D\u2642":"1f926-1f3fd-2642","\uD83E\uDD26\uD83C\uDFFC\u200D\u2642":"1f926-1f3fc-2642","\uD83E\uDD26\uD83C\uDFFB\u200D\u2642":"1f926-1f3fb-2642","\uD83E\uDD26\uD83C\uDFFF\u200D\u2640":"1f926-1f3ff-2640","\uD83E\uDD26\uD83C\uDFFE\u200D\u2640":"1f926-1f3fe-2640","\uD83E\uDD26\uD83C\uDFFD\u200D\u2640":"1f926-1f3fd-2640","\uD83E\uDD26\uD83C\uDFFC\u200D\u2640":"1f926-1f3fc-2640","\uD83E\uDD26\uD83C\uDFFB\u200D\u2640":"1f926-1f3fb-2640","\uD83D\uDE4E\uD83C\uDFFF\u200D\u2642":"1f64e-1f3ff-2642","\uD83D\uDE4E\uD83C\uDFFE\u200D\u2642":"1f64e-1f3fe-2642","\uD83D\uDE4E\uD83C\uDFFD\u200D\u2642":"1f64e-1f3fd-2642","\uD83D\uDE4E\uD83C\uDFFC\u200D\u2642":"1f64e-1f3fc-2642","\uD83D\uDE4E\uD83C\uDFFB\u200D\u2642":"1f64e-1f3fb-2642","\uD83D\uDE4E\uD83C\uDFFF\u200D\u2640":"1f64e-1f3ff-2640","\uD83D\uDE4E\uD83C\uDFFE\u200D\u2640":"1f64e-1f3fe-2640","\uD83D\uDE4E\uD83C\uDFFD\u200D\u2640":"1f64e-1f3fd-2640","\uD83D\uDE4E\uD83C\uDFFC\u200D\u2640":"1f64e-1f3fc-2640","\uD83D\uDE4E\uD83C\uDFFB\u200D\u2640":"1f64e-1f3fb-2640","\uD83D\uDE4D\uD83C\uDFFF\u200D\u2642":"1f64d-1f3ff-2642","\uD83D\uDE4D\uD83C\uDFFE\u200D\u2642":"1f64d-1f3fe-2642","\uD83D\uDE4D\uD83C\uDFFD\u200D\u2642":"1f64d-1f3fd-2642","\uD83D\uDE4D\uD83C\uDFFC\u200D\u2642":"1f64d-1f3fc-2642","\uD83D\uDE4D\uD83C\uDFFB\u200D\u2642":"1f64d-1f3fb-2642","\uD83D\uDE4D\uD83C\uDFFF\u200D\u2640":"1f64d-1f3ff-2640","\uD83D\uDE4D\uD83C\uDFFE\u200D\u2640":"1f64d-1f3fe-2640","\uD83D\uDE4D\uD83C\uDFFD\u200D\u2640":"1f64d-1f3fd-2640","\uD83D\uDE4D\uD83C\uDFFC\u200D\u2640":"1f64d-1f3fc-2640","\uD83D\uDE4D\uD83C\uDFFB\u200D\u2640":"1f64d-1f3fb-2640","\uD83D\uDE4B\uD83C\uDFFF\u200D\u2642":"1f64b-1f3ff-2642","\uD83D\uDE4B\uD83C\uDFFE\u200D\u2642":"1f64b-1f3fe-2642","\uD83D\uDE4B\uD83C\uDFFD\u200D\u2642":"1f64b-1f3fd-2642","\uD83D\uDE4B\uD83C\uDFFC\u200D\u2642":"1f64b-1f3fc-2642","\uD83D\uDE4B\uD83C\uDFFB\u200D\u2642":"1f64b-1f3fb-2642","\uD83D\uDE4B\uD83C\uDFFF\u200D\u2640":"1f64b-1f3ff-2640","\uD83D\uDE4B\uD83C\uDFFE\u200D\u2640":"1f64b-1f3fe-2640","\uD83D\uDE4B\uD83C\uDFFD\u200D\u2640":"1f64b-1f3fd-2640","\uD83D\uDE4B\uD83C\uDFFC\u200D\u2640":"1f64b-1f3fc-2640","\uD83D\uDE4B\uD83C\uDFFB\u200D\u2640":"1f64b-1f3fb-2640","\uD83D\uDE47\uD83C\uDFFF\u200D\u2642":"1f647-1f3ff-2642","\uD83D\uDE47\uD83C\uDFFE\u200D\u2642":"1f647-1f3fe-2642","\uD83D\uDE47\uD83C\uDFFD\u200D\u2642":"1f647-1f3fd-2642","\uD83D\uDE47\uD83C\uDFFC\u200D\u2642":"1f647-1f3fc-2642","\uD83D\uDE47\uD83C\uDFFB\u200D\u2642":"1f647-1f3fb-2642","\uD83D\uDE47\uD83C\uDFFF\u200D\u2640":"1f647-1f3ff-2640","\uD83D\uDE47\uD83C\uDFFE\u200D\u2640":"1f647-1f3fe-2640","\uD83D\uDE47\uD83C\uDFFD\u200D\u2640":"1f647-1f3fd-2640","\uD83D\uDE47\uD83C\uDFFC\u200D\u2640":"1f647-1f3fc-2640","\uD83D\uDE47\uD83C\uDFFB\u200D\u2640":"1f647-1f3fb-2640","\uD83D\uDE46\uD83C\uDFFF\u200D\u2642":"1f646-1f3ff-2642","\uD83D\uDE46\uD83C\uDFFE\u200D\u2642":"1f646-1f3fe-2642","\uD83D\uDE46\uD83C\uDFFD\u200D\u2642":"1f646-1f3fd-2642","\uD83D\uDE46\uD83C\uDFFC\u200D\u2642":"1f646-1f3fc-2642","\uD83D\uDE46\uD83C\uDFFB\u200D\u2642":"1f646-1f3fb-2642","\uD83D\uDE46\uD83C\uDFFF\u200D\u2640":"1f646-1f3ff-2640","\uD83D\uDE46\uD83C\uDFFE\u200D\u2640":"1f646-1f3fe-2640","\uD83D\uDE46\uD83C\uDFFD\u200D\u2640":"1f646-1f3fd-2640","\uD83D\uDE46\uD83C\uDFFC\u200D\u2640":"1f646-1f3fc-2640","\uD83D\uDE46\uD83C\uDFFB\u200D\u2640":"1f646-1f3fb-2640","\uD83D\uDE45\uD83C\uDFFF\u200D\u2642":"1f645-1f3ff-2642","\uD83D\uDE45\uD83C\uDFFE\u200D\u2642":"1f645-1f3fe-2642","\uD83D\uDE45\uD83C\uDFFD\u200D\u2642":"1f645-1f3fd-2642","\uD83D\uDE45\uD83C\uDFFC\u200D\u2642":"1f645-1f3fc-2642","\uD83D\uDE45\uD83C\uDFFB\u200D\u2642":"1f645-1f3fb-2642","\uD83D\uDE45\uD83C\uDFFF\u200D\u2640":"1f645-1f3ff-2640","\uD83D\uDE45\uD83C\uDFFE\u200D\u2640":"1f645-1f3fe-2640","\uD83D\uDE45\uD83C\uDFFD\u200D\u2640":"1f645-1f3fd-2640","\uD83D\uDE45\uD83C\uDFFC\u200D\u2640":"1f645-1f3fc-2640","\uD83D\uDE45\uD83C\uDFFB\u200D\u2640":"1f645-1f3fb-2640","\uD83D\uDC87\uD83C\uDFFF\u200D\u2642":"1f487-1f3ff-2642","\uD83D\uDC87\uD83C\uDFFE\u200D\u2642":"1f487-1f3fe-2642","\uD83D\uDC87\uD83C\uDFFD\u200D\u2642":"1f487-1f3fd-2642","\uD83D\uDC87\uD83C\uDFFC\u200D\u2642":"1f487-1f3fc-2642","\uD83D\uDC87\uD83C\uDFFB\u200D\u2642":"1f487-1f3fb-2642","\uD83D\uDC87\uD83C\uDFFF\u200D\u2640":"1f487-1f3ff-2640","\uD83D\uDC87\uD83C\uDFFE\u200D\u2640":"1f487-1f3fe-2640","\uD83D\uDC87\uD83C\uDFFD\u200D\u2640":"1f487-1f3fd-2640","\uD83D\uDC87\uD83C\uDFFC\u200D\u2640":"1f487-1f3fc-2640","\uD83D\uDC87\uD83C\uDFFB\u200D\u2640":"1f487-1f3fb-2640","\uD83D\uDC86\uD83C\uDFFF\u200D\u2642":"1f486-1f3ff-2642","\uD83D\uDC86\uD83C\uDFFE\u200D\u2642":"1f486-1f3fe-2642","\uD83D\uDC86\uD83C\uDFFD\u200D\u2642":"1f486-1f3fd-2642","\uD83D\uDC86\uD83C\uDFFC\u200D\u2642":"1f486-1f3fc-2642","\uD83D\uDC86\uD83C\uDFFB\u200D\u2642":"1f486-1f3fb-2642","\uD83D\uDC86\uD83C\uDFFF\u200D\u2640":"1f486-1f3ff-2640","\uD83D\uDC86\uD83C\uDFFE\u200D\u2640":"1f486-1f3fe-2640","\uD83D\uDC86\uD83C\uDFFD\u200D\u2640":"1f486-1f3fd-2640","\uD83D\uDC86\uD83C\uDFFC\u200D\u2640":"1f486-1f3fc-2640","\uD83D\uDC86\uD83C\uDFFB\u200D\u2640":"1f486-1f3fb-2640","\uD83D\uDC81\uD83C\uDFFF\u200D\u2642":"1f481-1f3ff-2642","\uD83D\uDC81\uD83C\uDFFE\u200D\u2642":"1f481-1f3fe-2642","\uD83D\uDC81\uD83C\uDFFD\u200D\u2642":"1f481-1f3fd-2642","\uD83D\uDC81\uD83C\uDFFC\u200D\u2642":"1f481-1f3fc-2642","\uD83D\uDC81\uD83C\uDFFB\u200D\u2642":"1f481-1f3fb-2642","\uD83D\uDC81\uD83C\uDFFF\u200D\u2640":"1f481-1f3ff-2640","\uD83D\uDC81\uD83C\uDFFE\u200D\u2640":"1f481-1f3fe-2640","\uD83D\uDC81\uD83C\uDFFD\u200D\u2640":"1f481-1f3fd-2640","\uD83D\uDC81\uD83C\uDFFC\u200D\u2640":"1f481-1f3fc-2640","\uD83D\uDC81\uD83C\uDFFB\u200D\u2640":"1f481-1f3fb-2640","\uD83D\uDC71\uD83C\uDFFF\u200D\u2642":"1f471-1f3ff-2642","\uD83D\uDC71\uD83C\uDFFE\u200D\u2642":"1f471-1f3fe-2642","\uD83D\uDC71\uD83C\uDFFD\u200D\u2642":"1f471-1f3fd-2642","\uD83D\uDC71\uD83C\uDFFC\u200D\u2642":"1f471-1f3fc-2642","\uD83D\uDC71\uD83C\uDFFB\u200D\u2642":"1f471-1f3fb-2642","\uD83D\uDC71\uD83C\uDFFF\u200D\u2640":"1f471-1f3ff-2640","\uD83D\uDC71\uD83C\uDFFE\u200D\u2640":"1f471-1f3fe-2640","\uD83D\uDC71\uD83C\uDFFD\u200D\u2640":"1f471-1f3fd-2640","\uD83D\uDC71\uD83C\uDFFC\u200D\u2640":"1f471-1f3fc-2640","\uD83D\uDC71\uD83C\uDFFB\u200D\u2640":"1f471-1f3fb-2640","\uD83D\uDC73\uD83C\uDFFF\u200D\u2642":"1f473-1f3ff-2642","\uD83D\uDC73\uD83C\uDFFE\u200D\u2642":"1f473-1f3fe-2642","\uD83D\uDC73\uD83C\uDFFD\u200D\u2642":"1f473-1f3fd-2642","\uD83D\uDC73\uD83C\uDFFC\u200D\u2642":"1f473-1f3fc-2642","\uD83D\uDC73\uD83C\uDFFB\u200D\u2642":"1f473-1f3fb-2642","\uD83D\uDC73\uD83C\uDFFF\u200D\u2640":"1f473-1f3ff-2640","\uD83D\uDC73\uD83C\uDFFE\u200D\u2640":"1f473-1f3fe-2640","\uD83D\uDC73\uD83C\uDFFD\u200D\u2640":"1f473-1f3fd-2640","\uD83D\uDC73\uD83C\uDFFC\u200D\u2640":"1f473-1f3fc-2640","\uD83D\uDC73\uD83C\uDFFB\u200D\u2640":"1f473-1f3fb-2640","\uD83D\uDC82\uD83C\uDFFF\u200D\u2642":"1f482-1f3ff-2642","\uD83D\uDC82\uD83C\uDFFE\u200D\u2642":"1f482-1f3fe-2642","\uD83D\uDC82\uD83C\uDFFD\u200D\u2642":"1f482-1f3fd-2642","\uD83D\uDC82\uD83C\uDFFC\u200D\u2642":"1f482-1f3fc-2642","\uD83D\uDC82\uD83C\uDFFB\u200D\u2642":"1f482-1f3fb-2642","\uD83D\uDC82\uD83C\uDFFF\u200D\u2640":"1f482-1f3ff-2640","\uD83D\uDC82\uD83C\uDFFE\u200D\u2640":"1f482-1f3fe-2640","\uD83D\uDC82\uD83C\uDFFD\u200D\u2640":"1f482-1f3fd-2640","\uD83D\uDC82\uD83C\uDFFC\u200D\u2640":"1f482-1f3fc-2640","\uD83D\uDC82\uD83C\uDFFB\u200D\u2640":"1f482-1f3fb-2640","\uD83D\uDD75\uD83C\uDFFF\u200D\u2642":"1f575-1f3ff-2642","\uD83D\uDD75\uD83C\uDFFE\u200D\u2642":"1f575-1f3fe-2642","\uD83D\uDD75\uD83C\uDFFD\u200D\u2642":"1f575-1f3fd-2642","\uD83D\uDD75\uD83C\uDFFC\u200D\u2642":"1f575-1f3fc-2642","\uD83D\uDD75\uD83C\uDFFB\u200D\u2642":"1f575-1f3fb-2642","\uD83D\uDD75\uD83C\uDFFF\u200D\u2640":"1f575-1f3ff-2640","\uD83D\uDD75\uD83C\uDFFE\u200D\u2640":"1f575-1f3fe-2640","\uD83D\uDD75\uD83C\uDFFD\u200D\u2640":"1f575-1f3fd-2640","\uD83D\uDD75\uD83C\uDFFC\u200D\u2640":"1f575-1f3fc-2640","\uD83D\uDD75\uD83C\uDFFB\u200D\u2640":"1f575-1f3fb-2640","\uD83D\uDC77\uD83C\uDFFF\u200D\u2642":"1f477-1f3ff-2642","\uD83D\uDC77\uD83C\uDFFE\u200D\u2642":"1f477-1f3fe-2642","\uD83D\uDC77\uD83C\uDFFD\u200D\u2642":"1f477-1f3fd-2642","\uD83D\uDC77\uD83C\uDFFC\u200D\u2642":"1f477-1f3fc-2642","\uD83D\uDC77\uD83C\uDFFB\u200D\u2642":"1f477-1f3fb-2642","\uD83D\uDC77\uD83C\uDFFF\u200D\u2640":"1f477-1f3ff-2640","\uD83D\uDC77\uD83C\uDFFE\u200D\u2640":"1f477-1f3fe-2640","\uD83D\uDC77\uD83C\uDFFD\u200D\u2640":"1f477-1f3fd-2640","\uD83D\uDC77\uD83C\uDFFC\u200D\u2640":"1f477-1f3fc-2640","\uD83D\uDC77\uD83C\uDFFB\u200D\u2640":"1f477-1f3fb-2640","\uD83D\uDC6E\uD83C\uDFFF\u200D\u2642":"1f46e-1f3ff-2642","\uD83D\uDC6E\uD83C\uDFFE\u200D\u2642":"1f46e-1f3fe-2642","\uD83D\uDC6E\uD83C\uDFFD\u200D\u2642":"1f46e-1f3fd-2642","\uD83D\uDC6E\uD83C\uDFFC\u200D\u2642":"1f46e-1f3fc-2642","\uD83D\uDC6E\uD83C\uDFFB\u200D\u2642":"1f46e-1f3fb-2642","\uD83D\uDC6E\uD83C\uDFFF\u200D\u2640":"1f46e-1f3ff-2640","\uD83D\uDC6E\uD83C\uDFFE\u200D\u2640":"1f46e-1f3fe-2640","\uD83D\uDC6E\uD83C\uDFFD\u200D\u2640":"1f46e-1f3fd-2640","\uD83D\uDC6E\uD83C\uDFFC\u200D\u2640":"1f46e-1f3fc-2640","\uD83D\uDC6E\uD83C\uDFFB\u200D\u2640":"1f46e-1f3fb-2640","\uD83D\uDC68\uD83C\uDFFF\u200D\u2695":"1f468-1f3ff-2695","\uD83D\uDC68\uD83C\uDFFE\u200D\u2695":"1f468-1f3fe-2695","\uD83D\uDC68\uD83C\uDFFD\u200D\u2695":"1f468-1f3fd-2695","\uD83D\uDC68\uD83C\uDFFC\u200D\u2695":"1f468-1f3fc-2695","\uD83D\uDC68\uD83C\uDFFB\u200D\u2695":"1f468-1f3fb-2695","\uD83D\uDC69\uD83C\uDFFF\u200D\u2695":"1f469-1f3ff-2695","\uD83D\uDC69\uD83C\uDFFE\u200D\u2695":"1f469-1f3fe-2695","\uD83D\uDC69\uD83C\uDFFD\u200D\u2695":"1f469-1f3fd-2695","\uD83D\uDC69\uD83C\uDFFC\u200D\u2695":"1f469-1f3fc-2695","\uD83D\uDC69\uD83C\uDFFB\u200D\u2695":"1f469-1f3fb-2695","\uD83D\uDC68\uD83C\uDFFB\u200D\u2696":"1f468-1f3fb-2696","\uD83D\uDC68\uD83C\uDFFC\u200D\u2696":"1f468-1f3fc-2696","\uD83D\uDC68\uD83C\uDFFD\u200D\u2696":"1f468-1f3fd-2696","\uD83D\uDC68\uD83C\uDFFE\u200D\u2696":"1f468-1f3fe-2696","\uD83D\uDC68\uD83C\uDFFF\u200D\u2696":"1f468-1f3ff-2696","\uD83D\uDC69\uD83C\uDFFB\u200D\u2696":"1f469-1f3fb-2696","\uD83D\uDC69\uD83C\uDFFC\u200D\u2696":"1f469-1f3fc-2696","\uD83D\uDC69\uD83C\uDFFD\u200D\u2696":"1f469-1f3fd-2696","\uD83D\uDC69\uD83C\uDFFE\u200D\u2696":"1f469-1f3fe-2696","\uD83D\uDC69\uD83C\uDFFF\u200D\u2696":"1f469-1f3ff-2696","\uD83D\uDC68\uD83C\uDFFB\u200D\u2708":"1f468-1f3fb-2708","\uD83D\uDC68\uD83C\uDFFC\u200D\u2708":"1f468-1f3fc-2708","\uD83D\uDC68\uD83C\uDFFD\u200D\u2708":"1f468-1f3fd-2708","\uD83D\uDC68\uD83C\uDFFE\u200D\u2708":"1f468-1f3fe-2708","\uD83D\uDC68\uD83C\uDFFF\u200D\u2708":"1f468-1f3ff-2708","\uD83D\uDC69\uD83C\uDFFB\u200D\u2708":"1f469-1f3fb-2708","\uD83D\uDC69\uD83C\uDFFC\u200D\u2708":"1f469-1f3fc-2708","\uD83D\uDC69\uD83C\uDFFD\u200D\u2708":"1f469-1f3fd-2708","\uD83D\uDC69\uD83C\uDFFE\u200D\u2708":"1f469-1f3fe-2708","\uD83D\uDC69\uD83C\uDFFF\u200D\u2708":"1f469-1f3ff-2708","\uD83D\uDC68\u2764\uFE0F\uD83D\uDC68":"1f468-2764-1f468","\uD83D\uDC69\u2764\uFE0F\uD83D\uDC68":"1f469-2764-1f468","\uD83D\uDC69\u2764\uFE0F\uD83D\uDC69":"1f469-2764-1f469","\uD83D\uDC68\uD83C\uDFFB\u2695\uFE0F":"1f468-1f3fb-2695","\uD83D\uDC68\uD83C\uDFFB\u2696\uFE0F":"1f468-1f3fb-2696","\uD83D\uDC68\uD83C\uDFFB\u2708\uFE0F":"1f468-1f3fb-2708","\uD83D\uDC68\uD83C\uDFFC\u2695\uFE0F":"1f468-1f3fc-2695","\uD83D\uDC68\uD83C\uDFFC\u2696\uFE0F":"1f468-1f3fc-2696","\uD83D\uDC68\uD83C\uDFFC\u2708\uFE0F":"1f468-1f3fc-2708","\uD83D\uDC68\uD83C\uDFFD\u2695\uFE0F":"1f468-1f3fd-2695","\uD83D\uDC68\uD83C\uDFFD\u2696\uFE0F":"1f468-1f3fd-2696","\uD83D\uDC68\uD83C\uDFFD\u2708\uFE0F":"1f468-1f3fd-2708","\uD83D\uDC68\uD83C\uDFFE\u2695\uFE0F":"1f468-1f3fe-2695","\uD83D\uDC68\uD83C\uDFFE\u2696\uFE0F":"1f468-1f3fe-2696","\uD83D\uDC68\uD83C\uDFFE\u2708\uFE0F":"1f468-1f3fe-2708","\uD83D\uDC68\uD83C\uDFFF\u2695\uFE0F":"1f468-1f3ff-2695","\uD83D\uDC68\uD83C\uDFFF\u2696\uFE0F":"1f468-1f3ff-2696","\uD83D\uDC68\uD83C\uDFFF\u2708\uFE0F":"1f468-1f3ff-2708","\uD83D\uDC69\uD83C\uDFFB\u2695\uFE0F":"1f469-1f3fb-2695","\uD83D\uDC69\uD83C\uDFFB\u2696\uFE0F":"1f469-1f3fb-2696","\uD83D\uDC69\uD83C\uDFFB\u2708\uFE0F":"1f469-1f3fb-2708","\uD83D\uDC69\uD83C\uDFFC\u2695\uFE0F":"1f469-1f3fc-2695","\uD83D\uDC69\uD83C\uDFFC\u2696\uFE0F":"1f469-1f3fc-2696","\uD83D\uDC69\uD83C\uDFFC\u2708\uFE0F":"1f469-1f3fc-2708","\uD83D\uDC69\uD83C\uDFFD\u2695\uFE0F":"1f469-1f3fd-2695","\uD83D\uDC69\uD83C\uDFFD\u2696\uFE0F":"1f469-1f3fd-2696","\uD83D\uDC69\uD83C\uDFFD\u2708\uFE0F":"1f469-1f3fd-2708","\uD83D\uDC69\uD83C\uDFFE\u2695\uFE0F":"1f469-1f3fe-2695","\uD83D\uDC69\uD83C\uDFFE\u2696\uFE0F":"1f469-1f3fe-2696","\uD83D\uDC69\uD83C\uDFFE\u2708\uFE0F":"1f469-1f3fe-2708","\uD83D\uDC69\uD83C\uDFFF\u2695\uFE0F":"1f469-1f3ff-2695","\uD83D\uDC69\uD83C\uDFFF\u2696\uFE0F":"1f469-1f3ff-2696","\uD83D\uDC69\uD83C\uDFFF\u2708\uFE0F":"1f469-1f3ff-2708","\uD83D\uDC6E\uD83C\uDFFB\u2640\uFE0F":"1f46e-1f3fb-2640","\uD83D\uDC6E\uD83C\uDFFB\u2642\uFE0F":"1f46e-1f3fb-2642","\uD83D\uDC6E\uD83C\uDFFC\u2640\uFE0F":"1f46e-1f3fc-2640","\uD83D\uDC6E\uD83C\uDFFC\u2642\uFE0F":"1f46e-1f3fc-2642","\uD83D\uDC6E\uD83C\uDFFD\u2640\uFE0F":"1f46e-1f3fd-2640","\uD83D\uDC6E\uD83C\uDFFD\u2642\uFE0F":"1f46e-1f3fd-2642","\uD83D\uDC6E\uD83C\uDFFE\u2640\uFE0F":"1f46e-1f3fe-2640","\uD83D\uDC6E\uD83C\uDFFE\u2642\uFE0F":"1f46e-1f3fe-2642","\uD83D\uDC6E\uD83C\uDFFF\u2640\uFE0F":"1f46e-1f3ff-2640","\uD83D\uDC6E\uD83C\uDFFF\u2642\uFE0F":"1f46e-1f3ff-2642","\uD83D\uDC71\uD83C\uDFFB\u2640\uFE0F":"1f471-1f3fb-2640","\uD83D\uDC71\uD83C\uDFFB\u2642\uFE0F":"1f471-1f3fb-2642","\uD83D\uDC71\uD83C\uDFFC\u2640\uFE0F":"1f471-1f3fc-2640","\uD83D\uDC71\uD83C\uDFFC\u2642\uFE0F":"1f471-1f3fc-2642","\uD83D\uDC71\uD83C\uDFFD\u2640\uFE0F":"1f471-1f3fd-2640","\uD83D\uDC71\uD83C\uDFFD\u2642\uFE0F":"1f471-1f3fd-2642","\uD83D\uDC71\uD83C\uDFFE\u2640\uFE0F":"1f471-1f3fe-2640","\uD83D\uDC71\uD83C\uDFFE\u2642\uFE0F":"1f471-1f3fe-2642","\uD83D\uDC71\uD83C\uDFFF\u2640\uFE0F":"1f471-1f3ff-2640","\uD83D\uDC71\uD83C\uDFFF\u2642\uFE0F":"1f471-1f3ff-2642","\uD83D\uDC73\uD83C\uDFFB\u2640\uFE0F":"1f473-1f3fb-2640","\uD83D\uDC73\uD83C\uDFFB\u2642\uFE0F":"1f473-1f3fb-2642","\uD83D\uDC73\uD83C\uDFFC\u2640\uFE0F":"1f473-1f3fc-2640","\uD83D\uDC73\uD83C\uDFFC\u2642\uFE0F":"1f473-1f3fc-2642","\uD83D\uDC73\uD83C\uDFFD\u2640\uFE0F":"1f473-1f3fd-2640","\uD83D\uDC73\uD83C\uDFFD\u2642\uFE0F":"1f473-1f3fd-2642","\uD83D\uDC73\uD83C\uDFFE\u2640\uFE0F":"1f473-1f3fe-2640","\uD83D\uDC73\uD83C\uDFFE\u2642\uFE0F":"1f473-1f3fe-2642","\uD83D\uDC73\uD83C\uDFFF\u2640\uFE0F":"1f473-1f3ff-2640","\uD83D\uDC73\uD83C\uDFFF\u2642\uFE0F":"1f473-1f3ff-2642","\uD83D\uDC77\uD83C\uDFFB\u2640\uFE0F":"1f477-1f3fb-2640","\uD83D\uDC77\uD83C\uDFFB\u2642\uFE0F":"1f477-1f3fb-2642","\uD83D\uDC77\uD83C\uDFFC\u2640\uFE0F":"1f477-1f3fc-2640","\uD83D\uDC77\uD83C\uDFFC\u2642\uFE0F":"1f477-1f3fc-2642","\uD83D\uDC77\uD83C\uDFFD\u2640\uFE0F":"1f477-1f3fd-2640","\uD83D\uDC77\uD83C\uDFFD\u2642\uFE0F":"1f477-1f3fd-2642","\uD83D\uDC77\uD83C\uDFFE\u2640\uFE0F":"1f477-1f3fe-2640","\uD83D\uDC77\uD83C\uDFFE\u2642\uFE0F":"1f477-1f3fe-2642","\uD83D\uDC77\uD83C\uDFFF\u2640\uFE0F":"1f477-1f3ff-2640","\uD83D\uDC77\uD83C\uDFFF\u2642\uFE0F":"1f477-1f3ff-2642","\uD83D\uDC82\uD83C\uDFFB\u2640\uFE0F":"1f482-1f3fb-2640","\uD83D\uDC82\uD83C\uDFFB\u2642\uFE0F":"1f482-1f3fb-2642","\uD83D\uDC82\uD83C\uDFFC\u2640\uFE0F":"1f482-1f3fc-2640","\uD83D\uDC82\uD83C\uDFFC\u2642\uFE0F":"1f482-1f3fc-2642","\uD83D\uDC82\uD83C\uDFFD\u2640\uFE0F":"1f482-1f3fd-2640","\uD83D\uDC82\uD83C\uDFFD\u2642\uFE0F":"1f482-1f3fd-2642","\uD83D\uDC82\uD83C\uDFFE\u2640\uFE0F":"1f482-1f3fe-2640","\uD83D\uDC82\uD83C\uDFFE\u2642\uFE0F":"1f482-1f3fe-2642","\uD83D\uDC82\uD83C\uDFFF\u2640\uFE0F":"1f482-1f3ff-2640","\uD83D\uDC82\uD83C\uDFFF\u2642\uFE0F":"1f482-1f3ff-2642","\uD83C\uDFC3\uD83C\uDFFB\u2640\uFE0F":"1f3c3-1f3fb-2640","\uD83C\uDFC3\uD83C\uDFFB\u2642\uFE0F":"1f3c3-1f3fb-2642","\uD83C\uDFC3\uD83C\uDFFC\u2640\uFE0F":"1f3c3-1f3fc-2640","\uD83C\uDFC3\uD83C\uDFFC\u2642\uFE0F":"1f3c3-1f3fc-2642","\uD83C\uDFC3\uD83C\uDFFD\u2640\uFE0F":"1f3c3-1f3fd-2640","\uD83C\uDFC3\uD83C\uDFFD\u2642\uFE0F":"1f3c3-1f3fd-2642","\uD83C\uDFC3\uD83C\uDFFE\u2640\uFE0F":"1f3c3-1f3fe-2640","\uD83C\uDFC3\uD83C\uDFFE\u2642\uFE0F":"1f3c3-1f3fe-2642","\uD83C\uDFC3\uD83C\uDFFF\u2640\uFE0F":"1f3c3-1f3ff-2640","\uD83C\uDFC3\uD83C\uDFFF\u2642\uFE0F":"1f3c3-1f3ff-2642","\uD83C\uDFC4\uD83C\uDFFB\u2640\uFE0F":"1f3c4-1f3fb-2640","\uD83C\uDFC4\uD83C\uDFFB\u2642\uFE0F":"1f3c4-1f3fb-2642","\uD83C\uDFC4\uD83C\uDFFC\u2640\uFE0F":"1f3c4-1f3fc-2640","\uD83C\uDFC4\uD83C\uDFFC\u2642\uFE0F":"1f3c4-1f3fc-2642","\uD83C\uDFC4\uD83C\uDFFD\u2640\uFE0F":"1f3c4-1f3fd-2640","\uD83C\uDFC4\uD83C\uDFFD\u2642\uFE0F":"1f3c4-1f3fd-2642","\uD83C\uDFC4\uD83C\uDFFE\u2640\uFE0F":"1f3c4-1f3fe-2640","\uD83C\uDFC4\uD83C\uDFFE\u2642\uFE0F":"1f3c4-1f3fe-2642","\uD83C\uDFC4\uD83C\uDFFF\u2640\uFE0F":"1f3c4-1f3ff-2640","\uD83C\uDFC4\uD83C\uDFFF\u2642\uFE0F":"1f3c4-1f3ff-2642","\uD83C\uDFCA\uD83C\uDFFB\u2640\uFE0F":"1f3ca-1f3fb-2640","\uD83C\uDFCA\uD83C\uDFFB\u2642\uFE0F":"1f3ca-1f3fb-2642","\uD83C\uDFCA\uD83C\uDFFC\u2640\uFE0F":"1f3ca-1f3fc-2640","\uD83C\uDFCA\uD83C\uDFFC\u2642\uFE0F":"1f3ca-1f3fc-2642","\uD83C\uDFCA\uD83C\uDFFD\u2640\uFE0F":"1f3ca-1f3fd-2640","\uD83C\uDFCA\uD83C\uDFFD\u2642\uFE0F":"1f3ca-1f3fd-2642","\uD83C\uDFCA\uD83C\uDFFE\u2640\uFE0F":"1f3ca-1f3fe-2640","\uD83C\uDFCA\uD83C\uDFFE\u2642\uFE0F":"1f3ca-1f3fe-2642","\uD83C\uDFCA\uD83C\uDFFF\u2640\uFE0F":"1f3ca-1f3ff-2640","\uD83C\uDFCA\uD83C\uDFFF\u2642\uFE0F":"1f3ca-1f3ff-2642","\uD83D\uDC86\uD83C\uDFFB\u2640\uFE0F":"1f486-1f3fb-2640","\uD83D\uDC86\uD83C\uDFFB\u2642\uFE0F":"1f486-1f3fb-2642","\uD83D\uDC86\uD83C\uDFFC\u2640\uFE0F":"1f486-1f3fc-2640","\uD83D\uDC86\uD83C\uDFFC\u2642\uFE0F":"1f486-1f3fc-2642","\uD83D\uDC86\uD83C\uDFFD\u2640\uFE0F":"1f486-1f3fd-2640","\uD83D\uDC86\uD83C\uDFFD\u2642\uFE0F":"1f486-1f3fd-2642","\uD83D\uDC86\uD83C\uDFFE\u2640\uFE0F":"1f486-1f3fe-2640","\uD83D\uDC86\uD83C\uDFFE\u2642\uFE0F":"1f486-1f3fe-2642","\uD83D\uDC86\uD83C\uDFFF\u2640\uFE0F":"1f486-1f3ff-2640","\uD83D\uDC86\uD83C\uDFFF\u2642\uFE0F":"1f486-1f3ff-2642","\uD83D\uDC87\uD83C\uDFFB\u2640\uFE0F":"1f487-1f3fb-2640","\uD83D\uDC87\uD83C\uDFFB\u2642\uFE0F":"1f487-1f3fb-2642","\uD83D\uDC87\uD83C\uDFFC\u2640\uFE0F":"1f487-1f3fc-2640","\uD83D\uDC87\uD83C\uDFFC\u2642\uFE0F":"1f487-1f3fc-2642","\uD83D\uDC87\uD83C\uDFFD\u2640\uFE0F":"1f487-1f3fd-2640","\uD83D\uDC87\uD83C\uDFFD\u2642\uFE0F":"1f487-1f3fd-2642","\uD83D\uDC87\uD83C\uDFFE\u2640\uFE0F":"1f487-1f3fe-2640","\uD83D\uDC87\uD83C\uDFFE\u2642\uFE0F":"1f487-1f3fe-2642","\uD83D\uDC87\uD83C\uDFFF\u2640\uFE0F":"1f487-1f3ff-2640","\uD83D\uDC87\uD83C\uDFFF\u2642\uFE0F":"1f487-1f3ff-2642","\uD83D\uDEA3\uD83C\uDFFB\u2640\uFE0F":"1f6a3-1f3fb-2640","\uD83D\uDEA3\uD83C\uDFFB\u2642\uFE0F":"1f6a3-1f3fb-2642","\uD83D\uDEA3\uD83C\uDFFC\u2640\uFE0F":"1f6a3-1f3fc-2640","\uD83D\uDEA3\uD83C\uDFFC\u2642\uFE0F":"1f6a3-1f3fc-2642","\uD83D\uDEA3\uD83C\uDFFD\u2640\uFE0F":"1f6a3-1f3fd-2640","\uD83D\uDEA3\uD83C\uDFFD\u2642\uFE0F":"1f6a3-1f3fd-2642","\uD83D\uDEA3\uD83C\uDFFE\u2640\uFE0F":"1f6a3-1f3fe-2640","\uD83D\uDEA3\uD83C\uDFFE\u2642\uFE0F":"1f6a3-1f3fe-2642","\uD83D\uDEA3\uD83C\uDFFF\u2640\uFE0F":"1f6a3-1f3ff-2640","\uD83D\uDEA3\uD83C\uDFFF\u2642\uFE0F":"1f6a3-1f3ff-2642","\uD83D\uDEB4\uD83C\uDFFB\u2640\uFE0F":"1f6b4-1f3fb-2640","\uD83D\uDEB4\uD83C\uDFFB\u2642\uFE0F":"1f6b4-1f3fb-2642","\uD83D\uDEB4\uD83C\uDFFC\u2640\uFE0F":"1f6b4-1f3fc-2640","\uD83D\uDEB4\uD83C\uDFFC\u2642\uFE0F":"1f6b4-1f3fc-2642","\uD83D\uDEB4\uD83C\uDFFD\u2640\uFE0F":"1f6b4-1f3fd-2640","\uD83D\uDEB4\uD83C\uDFFD\u2642\uFE0F":"1f6b4-1f3fd-2642","\uD83D\uDEB4\uD83C\uDFFE\u2640\uFE0F":"1f6b4-1f3fe-2640","\uD83D\uDEB4\uD83C\uDFFE\u2642\uFE0F":"1f6b4-1f3fe-2642","\uD83D\uDEB4\uD83C\uDFFF\u2640\uFE0F":"1f6b4-1f3ff-2640","\uD83D\uDEB4\uD83C\uDFFF\u2642\uFE0F":"1f6b4-1f3ff-2642","\uD83D\uDEB5\uD83C\uDFFB\u2640\uFE0F":"1f6b5-1f3fb-2640","\uD83D\uDEB5\uD83C\uDFFB\u2642\uFE0F":"1f6b5-1f3fb-2642","\uD83D\uDEB5\uD83C\uDFFC\u2640\uFE0F":"1f6b5-1f3fc-2640","\uD83D\uDEB5\uD83C\uDFFC\u2642\uFE0F":"1f6b5-1f3fc-2642","\uD83D\uDEB5\uD83C\uDFFD\u2640\uFE0F":"1f6b5-1f3fd-2640","\uD83D\uDEB5\uD83C\uDFFD\u2642\uFE0F":"1f6b5-1f3fd-2642","\uD83D\uDEB5\uD83C\uDFFE\u2640\uFE0F":"1f6b5-1f3fe-2640","\uD83D\uDEB5\uD83C\uDFFE\u2642\uFE0F":"1f6b5-1f3fe-2642","\uD83D\uDEB5\uD83C\uDFFF\u2640\uFE0F":"1f6b5-1f3ff-2640","\uD83D\uDEB5\uD83C\uDFFF\u2642\uFE0F":"1f6b5-1f3ff-2642","\uD83D\uDEB6\uD83C\uDFFB\u2640\uFE0F":"1f6b6-1f3fb-2640","\uD83D\uDEB6\uD83C\uDFFB\u2642\uFE0F":"1f6b6-1f3fb-2642","\uD83D\uDEB6\uD83C\uDFFC\u2640\uFE0F":"1f6b6-1f3fc-2640","\uD83D\uDEB6\uD83C\uDFFC\u2642\uFE0F":"1f6b6-1f3fc-2642","\uD83D\uDEB6\uD83C\uDFFD\u2640\uFE0F":"1f6b6-1f3fd-2640","\uD83D\uDEB6\uD83C\uDFFD\u2642\uFE0F":"1f6b6-1f3fd-2642","\uD83D\uDEB6\uD83C\uDFFE\u2640\uFE0F":"1f6b6-1f3fe-2640","\uD83D\uDEB6\uD83C\uDFFE\u2642\uFE0F":"1f6b6-1f3fe-2642","\uD83D\uDEB6\uD83C\uDFFF\u2640\uFE0F":"1f6b6-1f3ff-2640","\uD83D\uDEB6\uD83C\uDFFF\u2642\uFE0F":"1f6b6-1f3ff-2642","\uD83E\uDD38\uD83C\uDFFB\u2640\uFE0F":"1f938-1f3fb-2640","\uD83E\uDD38\uD83C\uDFFB\u2642\uFE0F":"1f938-1f3fb-2642","\uD83E\uDD38\uD83C\uDFFC\u2640\uFE0F":"1f938-1f3fc-2640","\uD83E\uDD38\uD83C\uDFFC\u2642\uFE0F":"1f938-1f3fc-2642","\uD83E\uDD38\uD83C\uDFFD\u2640\uFE0F":"1f938-1f3fd-2640","\uD83E\uDD38\uD83C\uDFFD\u2642\uFE0F":"1f938-1f3fd-2642","\uD83E\uDD38\uD83C\uDFFE\u2640\uFE0F":"1f938-1f3fe-2640","\uD83E\uDD38\uD83C\uDFFE\u2642\uFE0F":"1f938-1f3fe-2642","\uD83E\uDD38\uD83C\uDFFF\u2640\uFE0F":"1f938-1f3ff-2640","\uD83E\uDD38\uD83C\uDFFF\u2642\uFE0F":"1f938-1f3ff-2642","\uD83E\uDD39\uD83C\uDFFB\u2640\uFE0F":"1f939-1f3fb-2640","\uD83E\uDD39\uD83C\uDFFB\u2642\uFE0F":"1f939-1f3fb-2642","\uD83E\uDD39\uD83C\uDFFC\u2640\uFE0F":"1f939-1f3fc-2640","\uD83E\uDD39\uD83C\uDFFC\u2642\uFE0F":"1f939-1f3fc-2642","\uD83E\uDD39\uD83C\uDFFD\u2640\uFE0F":"1f939-1f3fd-2640","\uD83E\uDD39\uD83C\uDFFD\u2642\uFE0F":"1f939-1f3fd-2642","\uD83E\uDD39\uD83C\uDFFE\u2640\uFE0F":"1f939-1f3fe-2640","\uD83E\uDD39\uD83C\uDFFE\u2642\uFE0F":"1f939-1f3fe-2642","\uD83E\uDD39\uD83C\uDFFF\u2640\uFE0F":"1f939-1f3ff-2640","\uD83E\uDD39\uD83C\uDFFF\u2642\uFE0F":"1f939-1f3ff-2642","\uD83E\uDD3D\uD83C\uDFFB\u2640\uFE0F":"1f93d-1f3fb-2640","\uD83E\uDD3D\uD83C\uDFFB\u2642\uFE0F":"1f93d-1f3fb-2642","\uD83E\uDD3D\uD83C\uDFFC\u2640\uFE0F":"1f93d-1f3fc-2640","\uD83E\uDD3D\uD83C\uDFFC\u2642\uFE0F":"1f93d-1f3fc-2642","\uD83E\uDD3D\uD83C\uDFFD\u2640\uFE0F":"1f93d-1f3fd-2640","\uD83E\uDD3D\uD83C\uDFFD\u2642\uFE0F":"1f93d-1f3fd-2642","\uD83E\uDD3D\uD83C\uDFFE\u2640\uFE0F":"1f93d-1f3fe-2640","\uD83E\uDD3D\uD83C\uDFFE\u2642\uFE0F":"1f93d-1f3fe-2642","\uD83E\uDD3D\uD83C\uDFFF\u2640\uFE0F":"1f93d-1f3ff-2640","\uD83E\uDD3D\uD83C\uDFFF\u2642\uFE0F":"1f93d-1f3ff-2642","\uD83E\uDD3E\uD83C\uDFFB\u2640\uFE0F":"1f93e-1f3fb-2640","\uD83E\uDD3E\uD83C\uDFFB\u2642\uFE0F":"1f93e-1f3fb-2642","\uD83E\uDD3E\uD83C\uDFFC\u2640\uFE0F":"1f93e-1f3fc-2640","\uD83E\uDD3E\uD83C\uDFFC\u2642\uFE0F":"1f93e-1f3fc-2642","\uD83E\uDD3E\uD83C\uDFFD\u2640\uFE0F":"1f93e-1f3fd-2640","\uD83E\uDD3E\uD83C\uDFFD\u2642\uFE0F":"1f93e-1f3fd-2642","\uD83E\uDD3E\uD83C\uDFFE\u2640\uFE0F":"1f93e-1f3fe-2640","\uD83E\uDD3E\uD83C\uDFFE\u2642\uFE0F":"1f93e-1f3fe-2642","\uD83E\uDD3E\uD83C\uDFFF\u2640\uFE0F":"1f93e-1f3ff-2640","\uD83E\uDD3E\uD83C\uDFFF\u2642\uFE0F":"1f93e-1f3ff-2642","\uD83D\uDC81\uD83C\uDFFB\u2640\uFE0F":"1f481-1f3fb-2640","\uD83D\uDC81\uD83C\uDFFB\u2642\uFE0F":"1f481-1f3fb-2642","\uD83D\uDC81\uD83C\uDFFC\u2640\uFE0F":"1f481-1f3fc-2640","\uD83D\uDC81\uD83C\uDFFC\u2642\uFE0F":"1f481-1f3fc-2642","\uD83D\uDC81\uD83C\uDFFD\u2640\uFE0F":"1f481-1f3fd-2640","\uD83D\uDC81\uD83C\uDFFD\u2642\uFE0F":"1f481-1f3fd-2642","\uD83D\uDC81\uD83C\uDFFE\u2640\uFE0F":"1f481-1f3fe-2640","\uD83D\uDC81\uD83C\uDFFE\u2642\uFE0F":"1f481-1f3fe-2642","\uD83D\uDC81\uD83C\uDFFF\u2640\uFE0F":"1f481-1f3ff-2640","\uD83D\uDC81\uD83C\uDFFF\u2642\uFE0F":"1f481-1f3ff-2642","\uD83D\uDE45\uD83C\uDFFB\u2640\uFE0F":"1f645-1f3fb-2640","\uD83D\uDE45\uD83C\uDFFB\u2642\uFE0F":"1f645-1f3fb-2642","\uD83D\uDE45\uD83C\uDFFC\u2640\uFE0F":"1f645-1f3fc-2640","\uD83D\uDE45\uD83C\uDFFC\u2642\uFE0F":"1f645-1f3fc-2642","\uD83D\uDE45\uD83C\uDFFD\u2640\uFE0F":"1f645-1f3fd-2640","\uD83D\uDE45\uD83C\uDFFD\u2642\uFE0F":"1f645-1f3fd-2642","\uD83D\uDE45\uD83C\uDFFE\u2640\uFE0F":"1f645-1f3fe-2640","\uD83D\uDE45\uD83C\uDFFE\u2642\uFE0F":"1f645-1f3fe-2642","\uD83D\uDE45\uD83C\uDFFF\u2640\uFE0F":"1f645-1f3ff-2640","\uD83D\uDE45\uD83C\uDFFF\u2642\uFE0F":"1f645-1f3ff-2642","\uD83D\uDE46\uD83C\uDFFB\u2640\uFE0F":"1f646-1f3fb-2640","\uD83D\uDE46\uD83C\uDFFB\u2642\uFE0F":"1f646-1f3fb-2642","\uD83D\uDE46\uD83C\uDFFC\u2640\uFE0F":"1f646-1f3fc-2640","\uD83D\uDE46\uD83C\uDFFC\u2642\uFE0F":"1f646-1f3fc-2642","\uD83D\uDE46\uD83C\uDFFD\u2640\uFE0F":"1f646-1f3fd-2640","\uD83D\uDE46\uD83C\uDFFD\u2642\uFE0F":"1f646-1f3fd-2642","\uD83D\uDE46\uD83C\uDFFE\u2640\uFE0F":"1f646-1f3fe-2640","\uD83D\uDE46\uD83C\uDFFE\u2642\uFE0F":"1f646-1f3fe-2642","\uD83D\uDE46\uD83C\uDFFF\u2640\uFE0F":"1f646-1f3ff-2640","\uD83D\uDE46\uD83C\uDFFF\u2642\uFE0F":"1f646-1f3ff-2642","\uD83D\uDE47\uD83C\uDFFB\u2640\uFE0F":"1f647-1f3fb-2640","\uD83D\uDE47\uD83C\uDFFB\u2642\uFE0F":"1f647-1f3fb-2642","\uD83D\uDE47\uD83C\uDFFC\u2640\uFE0F":"1f647-1f3fc-2640","\uD83D\uDE47\uD83C\uDFFC\u2642\uFE0F":"1f647-1f3fc-2642","\uD83D\uDE47\uD83C\uDFFD\u2640\uFE0F":"1f647-1f3fd-2640","\uD83D\uDE47\uD83C\uDFFD\u2642\uFE0F":"1f647-1f3fd-2642","\uD83D\uDE47\uD83C\uDFFE\u2640\uFE0F":"1f647-1f3fe-2640","\uD83D\uDE47\uD83C\uDFFE\u2642\uFE0F":"1f647-1f3fe-2642","\uD83D\uDE47\uD83C\uDFFF\u2640\uFE0F":"1f647-1f3ff-2640","\uD83D\uDE47\uD83C\uDFFF\u2642\uFE0F":"1f647-1f3ff-2642","\uD83D\uDE4B\uD83C\uDFFB\u2640\uFE0F":"1f64b-1f3fb-2640","\uD83D\uDE4B\uD83C\uDFFB\u2642\uFE0F":"1f64b-1f3fb-2642","\uD83D\uDE4B\uD83C\uDFFC\u2640\uFE0F":"1f64b-1f3fc-2640","\uD83D\uDE4B\uD83C\uDFFC\u2642\uFE0F":"1f64b-1f3fc-2642","\uD83D\uDE4B\uD83C\uDFFD\u2640\uFE0F":"1f64b-1f3fd-2640","\uD83D\uDE4B\uD83C\uDFFD\u2642\uFE0F":"1f64b-1f3fd-2642","\uD83D\uDE4B\uD83C\uDFFE\u2640\uFE0F":"1f64b-1f3fe-2640","\uD83D\uDE4B\uD83C\uDFFE\u2642\uFE0F":"1f64b-1f3fe-2642","\uD83D\uDE4B\uD83C\uDFFF\u2640\uFE0F":"1f64b-1f3ff-2640","\uD83D\uDE4B\uD83C\uDFFF\u2642\uFE0F":"1f64b-1f3ff-2642","\uD83D\uDE4D\uD83C\uDFFB\u2640\uFE0F":"1f64d-1f3fb-2640","\uD83D\uDE4D\uD83C\uDFFB\u2642\uFE0F":"1f64d-1f3fb-2642","\uD83D\uDE4D\uD83C\uDFFC\u2640\uFE0F":"1f64d-1f3fc-2640","\uD83D\uDE4D\uD83C\uDFFC\u2642\uFE0F":"1f64d-1f3fc-2642","\uD83D\uDE4D\uD83C\uDFFD\u2640\uFE0F":"1f64d-1f3fd-2640","\uD83D\uDE4D\uD83C\uDFFD\u2642\uFE0F":"1f64d-1f3fd-2642","\uD83D\uDE4D\uD83C\uDFFE\u2640\uFE0F":"1f64d-1f3fe-2640","\uD83D\uDE4D\uD83C\uDFFE\u2642\uFE0F":"1f64d-1f3fe-2642","\uD83D\uDE4D\uD83C\uDFFF\u2640\uFE0F":"1f64d-1f3ff-2640","\uD83D\uDE4D\uD83C\uDFFF\u2642\uFE0F":"1f64d-1f3ff-2642","\uD83D\uDE4E\uD83C\uDFFB\u2640\uFE0F":"1f64e-1f3fb-2640","\uD83D\uDE4E\uD83C\uDFFB\u2642\uFE0F":"1f64e-1f3fb-2642","\uD83D\uDE4E\uD83C\uDFFC\u2640\uFE0F":"1f64e-1f3fc-2640","\uD83D\uDE4E\uD83C\uDFFC\u2642\uFE0F":"1f64e-1f3fc-2642","\uD83D\uDE4E\uD83C\uDFFD\u2640\uFE0F":"1f64e-1f3fd-2640","\uD83D\uDE4E\uD83C\uDFFD\u2642\uFE0F":"1f64e-1f3fd-2642","\uD83D\uDE4E\uD83C\uDFFE\u2640\uFE0F":"1f64e-1f3fe-2640","\uD83D\uDE4E\uD83C\uDFFE\u2642\uFE0F":"1f64e-1f3fe-2642","\uD83D\uDE4E\uD83C\uDFFF\u2640\uFE0F":"1f64e-1f3ff-2640","\uD83D\uDE4E\uD83C\uDFFF\u2642\uFE0F":"1f64e-1f3ff-2642","\uD83E\uDD26\uD83C\uDFFB\u2640\uFE0F":"1f926-1f3fb-2640","\uD83E\uDD26\uD83C\uDFFB\u2642\uFE0F":"1f926-1f3fb-2642","\uD83E\uDD26\uD83C\uDFFC\u2640\uFE0F":"1f926-1f3fc-2640","\uD83E\uDD26\uD83C\uDFFC\u2642\uFE0F":"1f926-1f3fc-2642","\uD83E\uDD26\uD83C\uDFFD\u2640\uFE0F":"1f926-1f3fd-2640","\uD83E\uDD26\uD83C\uDFFD\u2642\uFE0F":"1f926-1f3fd-2642","\uD83E\uDD26\uD83C\uDFFE\u2640\uFE0F":"1f926-1f3fe-2640","\uD83E\uDD26\uD83C\uDFFE\u2642\uFE0F":"1f926-1f3fe-2642","\uD83E\uDD26\uD83C\uDFFF\u2640\uFE0F":"1f926-1f3ff-2640","\uD83E\uDD26\uD83C\uDFFF\u2642\uFE0F":"1f926-1f3ff-2642","\uD83E\uDD37\uD83C\uDFFB\u2640\uFE0F":"1f937-1f3fb-2640","\uD83E\uDD37\uD83C\uDFFB\u2642\uFE0F":"1f937-1f3fb-2642","\uD83E\uDD37\uD83C\uDFFC\u2640\uFE0F":"1f937-1f3fc-2640","\uD83E\uDD37\uD83C\uDFFC\u2642\uFE0F":"1f937-1f3fc-2642","\uD83E\uDD37\uD83C\uDFFD\u2640\uFE0F":"1f937-1f3fd-2640","\uD83E\uDD37\uD83C\uDFFD\u2642\uFE0F":"1f937-1f3fd-2642","\uD83E\uDD37\uD83C\uDFFE\u2640\uFE0F":"1f937-1f3fe-2640","\uD83E\uDD37\uD83C\uDFFE\u2642\uFE0F":"1f937-1f3fe-2642","\uD83E\uDD37\uD83C\uDFFF\u2640\uFE0F":"1f937-1f3ff-2640","\uD83E\uDD37\uD83C\uDFFF\u2642\uFE0F":"1f937-1f3ff-2642","\uD83D\uDC41\uFE0F\uD83D\uDDE8\uFE0F":"1f441-1f5e8","\uD83E\uDDD9\uD83C\uDFFB\u200D\u2640":"1f9d9-1f3fb-2640","\uD83E\uDDD9\uD83C\uDFFB\u2640\uFE0F":"1f9d9-1f3fb-2640","\uD83E\uDDD9\uD83C\uDFFB\u200D\u2642":"1f9d9-1f3fb-2642","\uD83E\uDDD9\uD83C\uDFFB\u2642\uFE0F":"1f9d9-1f3fb-2642","\uD83E\uDDD9\uD83C\uDFFC\u200D\u2640":"1f9d9-1f3fc-2640","\uD83E\uDDD9\uD83C\uDFFC\u2640\uFE0F":"1f9d9-1f3fc-2640","\uD83E\uDDD9\uD83C\uDFFC\u200D\u2642":"1f9d9-1f3fc-2642","\uD83E\uDDD9\uD83C\uDFFC\u2642\uFE0F":"1f9d9-1f3fc-2642","\uD83E\uDDD9\uD83C\uDFFD\u200D\u2640":"1f9d9-1f3fd-2640","\uD83E\uDDD9\uD83C\uDFFD\u2640\uFE0F":"1f9d9-1f3fd-2640","\uD83E\uDDD9\uD83C\uDFFD\u200D\u2642":"1f9d9-1f3fd-2642","\uD83E\uDDD9\uD83C\uDFFD\u2642\uFE0F":"1f9d9-1f3fd-2642","\uD83E\uDDD9\uD83C\uDFFE\u200D\u2640":"1f9d9-1f3fe-2640","\uD83E\uDDD9\uD83C\uDFFE\u2640\uFE0F":"1f9d9-1f3fe-2640","\uD83E\uDDD9\uD83C\uDFFE\u200D\u2642":"1f9d9-1f3fe-2642","\uD83E\uDDD9\uD83C\uDFFE\u2642\uFE0F":"1f9d9-1f3fe-2642","\uD83E\uDDD9\uD83C\uDFFF\u200D\u2640":"1f9d9-1f3ff-2640","\uD83E\uDDD9\uD83C\uDFFF\u2640\uFE0F":"1f9d9-1f3ff-2640","\uD83E\uDDD9\uD83C\uDFFF\u200D\u2642":"1f9d9-1f3ff-2642","\uD83E\uDDD9\uD83C\uDFFF\u2642\uFE0F":"1f9d9-1f3ff-2642","\uD83E\uDDDA\uD83C\uDFFB\u200D\u2640":"1f9da-1f3fb-2640","\uD83E\uDDDA\uD83C\uDFFB\u2640\uFE0F":"1f9da-1f3fb-2640","\uD83E\uDDDA\uD83C\uDFFB\u200D\u2642":"1f9da-1f3fb-2642","\uD83E\uDDDA\uD83C\uDFFB\u2642\uFE0F":"1f9da-1f3fb-2642","\uD83E\uDDDA\uD83C\uDFFC\u200D\u2640":"1f9da-1f3fc-2640","\uD83E\uDDDA\uD83C\uDFFC\u2640\uFE0F":"1f9da-1f3fc-2640","\uD83E\uDDDA\uD83C\uDFFC\u200D\u2642":"1f9da-1f3fc-2642","\uD83E\uDDDA\uD83C\uDFFC\u2642\uFE0F":"1f9da-1f3fc-2642","\uD83E\uDDDA\uD83C\uDFFD\u200D\u2640":"1f9da-1f3fd-2640","\uD83E\uDDDA\uD83C\uDFFD\u2640\uFE0F":"1f9da-1f3fd-2640","\uD83E\uDDDA\uD83C\uDFFD\u200D\u2642":"1f9da-1f3fd-2642","\uD83E\uDDDA\uD83C\uDFFD\u2642\uFE0F":"1f9da-1f3fd-2642","\uD83E\uDDDA\uD83C\uDFFE\u200D\u2640":"1f9da-1f3fe-2640","\uD83E\uDDDA\uD83C\uDFFE\u2640\uFE0F":"1f9da-1f3fe-2640","\uD83E\uDDDA\uD83C\uDFFE\u200D\u2642":"1f9da-1f3fe-2642","\uD83E\uDDDA\uD83C\uDFFE\u2642\uFE0F":"1f9da-1f3fe-2642","\uD83E\uDDDA\uD83C\uDFFF\u200D\u2640":"1f9da-1f3ff-2640","\uD83E\uDDDA\uD83C\uDFFF\u2640\uFE0F":"1f9da-1f3ff-2640","\uD83E\uDDDA\uD83C\uDFFF\u200D\u2642":"1f9da-1f3ff-2642","\uD83E\uDDDA\uD83C\uDFFF\u2642\uFE0F":"1f9da-1f3ff-2642","\uD83E\uDDDB\uD83C\uDFFB\u200D\u2640":"1f9db-1f3fb-2640","\uD83E\uDDDB\uD83C\uDFFB\u2640\uFE0F":"1f9db-1f3fb-2640","\uD83E\uDDDB\uD83C\uDFFB\u200D\u2642":"1f9db-1f3fb-2642","\uD83E\uDDDB\uD83C\uDFFB\u2642\uFE0F":"1f9db-1f3fb-2642","\uD83E\uDDDB\uD83C\uDFFC\u200D\u2640":"1f9db-1f3fc-2640","\uD83E\uDDDB\uD83C\uDFFC\u2640\uFE0F":"1f9db-1f3fc-2640","\uD83E\uDDDB\uD83C\uDFFC\u200D\u2642":"1f9db-1f3fc-2642","\uD83E\uDDDB\uD83C\uDFFC\u2642\uFE0F":"1f9db-1f3fc-2642","\uD83E\uDDDB\uD83C\uDFFD\u200D\u2640":"1f9db-1f3fd-2640","\uD83E\uDDDB\uD83C\uDFFD\u2640\uFE0F":"1f9db-1f3fd-2640","\uD83E\uDDDB\uD83C\uDFFD\u200D\u2642":"1f9db-1f3fd-2642","\uD83E\uDDDB\uD83C\uDFFD\u2642\uFE0F":"1f9db-1f3fd-2642","\uD83E\uDDDB\uD83C\uDFFE\u200D\u2640":"1f9db-1f3fe-2640","\uD83E\uDDDB\uD83C\uDFFE\u2640\uFE0F":"1f9db-1f3fe-2640","\uD83E\uDDDB\uD83C\uDFFE\u200D\u2642":"1f9db-1f3fe-2642","\uD83E\uDDDB\uD83C\uDFFE\u2642\uFE0F":"1f9db-1f3fe-2642","\uD83E\uDDDB\uD83C\uDFFF\u200D\u2640":"1f9db-1f3ff-2640","\uD83E\uDDDB\uD83C\uDFFF\u2640\uFE0F":"1f9db-1f3ff-2640","\uD83E\uDDDB\uD83C\uDFFF\u200D\u2642":"1f9db-1f3ff-2642","\uD83E\uDDDB\uD83C\uDFFF\u2642\uFE0F":"1f9db-1f3ff-2642","\uD83E\uDDDC\uD83C\uDFFB\u200D\u2640":"1f9dc-1f3fb-2640","\uD83E\uDDDC\uD83C\uDFFB\u2640\uFE0F":"1f9dc-1f3fb-2640","\uD83E\uDDDC\uD83C\uDFFB\u200D\u2642":"1f9dc-1f3fb-2642","\uD83E\uDDDC\uD83C\uDFFB\u2642\uFE0F":"1f9dc-1f3fb-2642","\uD83E\uDDDC\uD83C\uDFFC\u200D\u2640":"1f9dc-1f3fc-2640","\uD83E\uDDDC\uD83C\uDFFC\u2640\uFE0F":"1f9dc-1f3fc-2640","\uD83E\uDDDC\uD83C\uDFFC\u200D\u2642":"1f9dc-1f3fc-2642","\uD83E\uDDDC\uD83C\uDFFC\u2642\uFE0F":"1f9dc-1f3fc-2642","\uD83E\uDDDC\uD83C\uDFFD\u200D\u2640":"1f9dc-1f3fd-2640","\uD83E\uDDDC\uD83C\uDFFD\u2640\uFE0F":"1f9dc-1f3fd-2640","\uD83E\uDDDC\uD83C\uDFFD\u200D\u2642":"1f9dc-1f3fd-2642","\uD83E\uDDDC\uD83C\uDFFD\u2642\uFE0F":"1f9dc-1f3fd-2642","\uD83E\uDDDC\uD83C\uDFFE\u200D\u2640":"1f9dc-1f3fe-2640","\uD83E\uDDDC\uD83C\uDFFE\u2640\uFE0F":"1f9dc-1f3fe-2640","\uD83E\uDDDC\uD83C\uDFFE\u200D\u2642":"1f9dc-1f3fe-2642","\uD83E\uDDDC\uD83C\uDFFE\u2642\uFE0F":"1f9dc-1f3fe-2642","\uD83E\uDDDC\uD83C\uDFFF\u200D\u2640":"1f9dc-1f3ff-2640","\uD83E\uDDDC\uD83C\uDFFF\u2640\uFE0F":"1f9dc-1f3ff-2640","\uD83E\uDDDC\uD83C\uDFFF\u200D\u2642":"1f9dc-1f3ff-2642","\uD83E\uDDDC\uD83C\uDFFF\u2642\uFE0F":"1f9dc-1f3ff-2642","\uD83E\uDDDD\uD83C\uDFFB\u200D\u2640":"1f9dd-1f3fb-2640","\uD83E\uDDDD\uD83C\uDFFB\u2640\uFE0F":"1f9dd-1f3fb-2640","\uD83E\uDDDD\uD83C\uDFFB\u200D\u2642":"1f9dd-1f3fb-2642","\uD83E\uDDDD\uD83C\uDFFB\u2642\uFE0F":"1f9dd-1f3fb-2642","\uD83E\uDDDD\uD83C\uDFFC\u200D\u2640":"1f9dd-1f3fc-2640","\uD83E\uDDDD\uD83C\uDFFC\u2640\uFE0F":"1f9dd-1f3fc-2640","\uD83E\uDDDD\uD83C\uDFFC\u200D\u2642":"1f9dd-1f3fc-2642","\uD83E\uDDDD\uD83C\uDFFC\u2642\uFE0F":"1f9dd-1f3fc-2642","\uD83E\uDDDD\uD83C\uDFFD\u200D\u2640":"1f9dd-1f3fd-2640","\uD83E\uDDDD\uD83C\uDFFD\u2640\uFE0F":"1f9dd-1f3fd-2640","\uD83E\uDDDD\uD83C\uDFFD\u200D\u2642":"1f9dd-1f3fd-2642","\uD83E\uDDDD\uD83C\uDFFD\u2642\uFE0F":"1f9dd-1f3fd-2642","\uD83E\uDDDD\uD83C\uDFFE\u200D\u2640":"1f9dd-1f3fe-2640","\uD83E\uDDDD\uD83C\uDFFE\u2640\uFE0F":"1f9dd-1f3fe-2640","\uD83E\uDDDD\uD83C\uDFFE\u200D\u2642":"1f9dd-1f3fe-2642","\uD83E\uDDDD\uD83C\uDFFE\u2642\uFE0F":"1f9dd-1f3fe-2642","\uD83E\uDDDD\uD83C\uDFFF\u200D\u2640":"1f9dd-1f3ff-2640","\uD83E\uDDDD\uD83C\uDFFF\u2640\uFE0F":"1f9dd-1f3ff-2640","\uD83E\uDDDD\uD83C\uDFFF\u200D\u2642":"1f9dd-1f3ff-2642","\uD83E\uDDDD\uD83C\uDFFF\u2642\uFE0F":"1f9dd-1f3ff-2642","\uD83E\uDDD6\uD83C\uDFFB\u200D\u2640":"1f9d6-1f3fb-2640","\uD83E\uDDD6\uD83C\uDFFB\u2640\uFE0F":"1f9d6-1f3fb-2640","\uD83E\uDDD6\uD83C\uDFFB\u200D\u2642":"1f9d6-1f3fb-2642","\uD83E\uDDD6\uD83C\uDFFB\u2642\uFE0F":"1f9d6-1f3fb-2642","\uD83E\uDDD6\uD83C\uDFFC\u200D\u2640":"1f9d6-1f3fc-2640","\uD83E\uDDD6\uD83C\uDFFC\u2640\uFE0F":"1f9d6-1f3fc-2640","\uD83E\uDDD6\uD83C\uDFFC\u200D\u2642":"1f9d6-1f3fc-2642","\uD83E\uDDD6\uD83C\uDFFC\u2642\uFE0F":"1f9d6-1f3fc-2642","\uD83E\uDDD6\uD83C\uDFFD\u200D\u2640":"1f9d6-1f3fd-2640","\uD83E\uDDD6\uD83C\uDFFD\u2640\uFE0F":"1f9d6-1f3fd-2640","\uD83E\uDDD6\uD83C\uDFFD\u200D\u2642":"1f9d6-1f3fd-2642","\uD83E\uDDD6\uD83C\uDFFD\u2642\uFE0F":"1f9d6-1f3fd-2642","\uD83E\uDDD6\uD83C\uDFFE\u200D\u2640":"1f9d6-1f3fe-2640","\uD83E\uDDD6\uD83C\uDFFE\u2640\uFE0F":"1f9d6-1f3fe-2640","\uD83E\uDDD6\uD83C\uDFFE\u200D\u2642":"1f9d6-1f3fe-2642","\uD83E\uDDD6\uD83C\uDFFE\u2642\uFE0F":"1f9d6-1f3fe-2642","\uD83E\uDDD6\uD83C\uDFFF\u200D\u2640":"1f9d6-1f3ff-2640","\uD83E\uDDD6\uD83C\uDFFF\u2640\uFE0F":"1f9d6-1f3ff-2640","\uD83E\uDDD6\uD83C\uDFFF\u200D\u2642":"1f9d6-1f3ff-2642","\uD83E\uDDD6\uD83C\uDFFF\u2642\uFE0F":"1f9d6-1f3ff-2642","\uD83E\uDDD7\uD83C\uDFFB\u200D\u2640":"1f9d7-1f3fb-2640","\uD83E\uDDD7\uD83C\uDFFB\u2640\uFE0F":"1f9d7-1f3fb-2640","\uD83E\uDDD7\uD83C\uDFFB\u200D\u2642":"1f9d7-1f3fb-2642","\uD83E\uDDD7\uD83C\uDFFB\u2642\uFE0F":"1f9d7-1f3fb-2642","\uD83E\uDDD7\uD83C\uDFFC\u200D\u2640":"1f9d7-1f3fc-2640","\uD83E\uDDD7\uD83C\uDFFC\u2640\uFE0F":"1f9d7-1f3fc-2640","\uD83E\uDDD7\uD83C\uDFFC\u200D\u2642":"1f9d7-1f3fc-2642","\uD83E\uDDD7\uD83C\uDFFC\u2642\uFE0F":"1f9d7-1f3fc-2642","\uD83E\uDDD7\uD83C\uDFFD\u200D\u2640":"1f9d7-1f3fd-2640","\uD83E\uDDD7\uD83C\uDFFD\u2640\uFE0F":"1f9d7-1f3fd-2640","\uD83E\uDDD7\uD83C\uDFFD\u200D\u2642":"1f9d7-1f3fd-2642","\uD83E\uDDD7\uD83C\uDFFD\u2642\uFE0F":"1f9d7-1f3fd-2642","\uD83E\uDDD7\uD83C\uDFFE\u200D\u2640":"1f9d7-1f3fe-2640","\uD83E\uDDD7\uD83C\uDFFE\u2640\uFE0F":"1f9d7-1f3fe-2640","\uD83E\uDDD7\uD83C\uDFFE\u200D\u2642":"1f9d7-1f3fe-2642","\uD83E\uDDD7\uD83C\uDFFE\u2642\uFE0F":"1f9d7-1f3fe-2642","\uD83E\uDDD7\uD83C\uDFFF\u200D\u2640":"1f9d7-1f3ff-2640","\uD83E\uDDD7\uD83C\uDFFF\u2640\uFE0F":"1f9d7-1f3ff-2640","\uD83E\uDDD7\uD83C\uDFFF\u200D\u2642":"1f9d7-1f3ff-2642","\uD83E\uDDD7\uD83C\uDFFF\u2642\uFE0F":"1f9d7-1f3ff-2642","\uD83E\uDDD8\uD83C\uDFFB\u200D\u2640":"1f9d8-1f3fb-2640","\uD83E\uDDD8\uD83C\uDFFB\u2640\uFE0F":"1f9d8-1f3fb-2640","\uD83E\uDDD8\uD83C\uDFFB\u200D\u2642":"1f9d8-1f3fb-2642","\uD83E\uDDD8\uD83C\uDFFB\u2642\uFE0F":"1f9d8-1f3fb-2642","\uD83E\uDDD8\uD83C\uDFFC\u200D\u2640":"1f9d8-1f3fc-2640","\uD83E\uDDD8\uD83C\uDFFC\u2640\uFE0F":"1f9d8-1f3fc-2640","\uD83E\uDDD8\uD83C\uDFFC\u200D\u2642":"1f9d8-1f3fc-2642","\uD83E\uDDD8\uD83C\uDFFC\u2642\uFE0F":"1f9d8-1f3fc-2642","\uD83E\uDDD8\uD83C\uDFFD\u200D\u2640":"1f9d8-1f3fd-2640","\uD83E\uDDD8\uD83C\uDFFD\u2640\uFE0F":"1f9d8-1f3fd-2640","\uD83E\uDDD8\uD83C\uDFFD\u200D\u2642":"1f9d8-1f3fd-2642","\uD83E\uDDD8\uD83C\uDFFD\u2642\uFE0F":"1f9d8-1f3fd-2642","\uD83E\uDDD8\uD83C\uDFFE\u200D\u2640":"1f9d8-1f3fe-2640","\uD83E\uDDD8\uD83C\uDFFE\u2640\uFE0F":"1f9d8-1f3fe-2640","\uD83E\uDDD8\uD83C\uDFFE\u200D\u2642":"1f9d8-1f3fe-2642","\uD83E\uDDD8\uD83C\uDFFE\u2642\uFE0F":"1f9d8-1f3fe-2642","\uD83E\uDDD8\uD83C\uDFFF\u200D\u2640":"1f9d8-1f3ff-2640","\uD83E\uDDD8\uD83C\uDFFF\u2640\uFE0F":"1f9d8-1f3ff-2640","\uD83E\uDDD8\uD83C\uDFFF\u200D\u2642":"1f9d8-1f3ff-2642","\uD83E\uDDD8\uD83C\uDFFF\u2642\uFE0F":"1f9d8-1f3ff-2642","\u26F9\uD83C\uDFFF\u200D\u2642":"26f9-1f3ff-2642","\u26F9\uD83C\uDFFE\u200D\u2642":"26f9-1f3fe-2642","\u26F9\uD83C\uDFFD\u200D\u2642":"26f9-1f3fd-2642","\u26F9\uD83C\uDFFC\u200D\u2642":"26f9-1f3fc-2642","\u26F9\uD83C\uDFFB\u200D\u2642":"26f9-1f3fb-2642","\u26F9\uD83C\uDFFF\u200D\u2640":"26f9-1f3ff-2640","\u26F9\uD83C\uDFFE\u200D\u2640":"26f9-1f3fe-2640","\u26F9\uD83C\uDFFD\u200D\u2640":"26f9-1f3fd-2640","\u26F9\uD83C\uDFFC\u200D\u2640":"26f9-1f3fc-2640","\u26F9\uD83C\uDFFB\u200D\u2640":"26f9-1f3fb-2640","\uD83D\uDC68\u200D\u2695\uFE0F":"1f468-2695","\uD83D\uDC68\u200D\u2696\uFE0F":"1f468-2696","\uD83D\uDC68\u200D\u2708\uFE0F":"1f468-2708","\uD83D\uDC69\u200D\u2695\uFE0F":"1f469-2695","\uD83D\uDC69\u200D\u2696\uFE0F":"1f469-2696","\uD83D\uDC69\u200D\u2708\uFE0F":"1f469-2708","\uD83D\uDC6E\u200D\u2640\uFE0F":"1f46e-2640","\uD83D\uDC6E\u200D\u2642\uFE0F":"1f46e-2642","\uD83D\uDC71\u200D\u2640\uFE0F":"1f471-2640","\uD83D\uDC71\u200D\u2642\uFE0F":"1f471-2642","\uD83D\uDC73\u200D\u2640\uFE0F":"1f473-2640","\uD83D\uDC73\u200D\u2642\uFE0F":"1f473-2642","\uD83D\uDC77\u200D\u2640\uFE0F":"1f477-2640","\uD83D\uDC77\u200D\u2642\uFE0F":"1f477-2642","\uD83D\uDC82\u200D\u2640\uFE0F":"1f482-2640","\uD83D\uDC82\u200D\u2642\uFE0F":"1f482-2642","\uD83D\uDD75\uFE0F\u2640\uFE0F":"1f575-2640","\uD83D\uDD75\uFE0F\u2642\uFE0F":"1f575-2642","\uD83C\uDFC3\u200D\u2640\uFE0F":"1f3c3-2640","\uD83C\uDFC3\u200D\u2642\uFE0F":"1f3c3-2642","\uD83C\uDFC4\u200D\u2640\uFE0F":"1f3c4-2640","\uD83C\uDFC4\u200D\u2642\uFE0F":"1f3c4-2642","\uD83C\uDFCA\u200D\u2640\uFE0F":"1f3ca-2640","\uD83C\uDFCA\u200D\u2642\uFE0F":"1f3ca-2642","\uD83C\uDFCB\uFE0F\u2640\uFE0F":"1f3cb-2640","\uD83C\uDFCB\uFE0F\u2642\uFE0F":"1f3cb-2642","\uD83C\uDFCC\uFE0F\u2640\uFE0F":"1f3cc-2640","\uD83C\uDFCC\uFE0F\u2642\uFE0F":"1f3cc-2642","\uD83D\uDC6F\u200D\u2640\uFE0F":"1f46f-2640","\uD83D\uDC6F\u200D\u2642\uFE0F":"1f46f-2642","\uD83D\uDC86\u200D\u2640\uFE0F":"1f486-2640","\uD83D\uDC86\u200D\u2642\uFE0F":"1f486-2642","\uD83D\uDC87\u200D\u2640\uFE0F":"1f487-2640","\uD83D\uDC87\u200D\u2642\uFE0F":"1f487-2642","\uD83D\uDEA3\u200D\u2640\uFE0F":"1f6a3-2640","\uD83D\uDEA3\u200D\u2642\uFE0F":"1f6a3-2642","\uD83D\uDEB4\u200D\u2640\uFE0F":"1f6b4-2640","\uD83D\uDEB4\u200D\u2642\uFE0F":"1f6b4-2642","\uD83D\uDEB5\u200D\u2640\uFE0F":"1f6b5-2640","\uD83D\uDEB5\u200D\u2642\uFE0F":"1f6b5-2642","\uD83D\uDEB6\u200D\u2640\uFE0F":"1f6b6-2640","\uD83D\uDEB6\u200D\u2642\uFE0F":"1f6b6-2642","\uD83E\uDD38\u200D\u2640\uFE0F":"1f938-2640","\uD83E\uDD38\u200D\u2642\uFE0F":"1f938-2642","\uD83E\uDD39\u200D\u2640\uFE0F":"1f939-2640","\uD83E\uDD39\u200D\u2642\uFE0F":"1f939-2642","\uD83E\uDD3C\u200D\u2640\uFE0F":"1f93c-2640","\uD83E\uDD3C\u200D\u2642\uFE0F":"1f93c-2642","\uD83E\uDD3D\u200D\u2640\uFE0F":"1f93d-2640","\uD83E\uDD3D\u200D\u2642\uFE0F":"1f93d-2642","\uD83E\uDD3E\u200D\u2640\uFE0F":"1f93e-2640","\uD83E\uDD3E\u200D\u2642\uFE0F":"1f93e-2642","\uD83D\uDC81\u200D\u2640\uFE0F":"1f481-2640","\uD83D\uDC81\u200D\u2642\uFE0F":"1f481-2642","\uD83D\uDE45\u200D\u2640\uFE0F":"1f645-2640","\uD83D\uDE45\u200D\u2642\uFE0F":"1f645-2642","\uD83D\uDE46\u200D\u2640\uFE0F":"1f646-2640","\uD83D\uDE46\u200D\u2642\uFE0F":"1f646-2642","\uD83D\uDE47\u200D\u2640\uFE0F":"1f647-2640","\uD83D\uDE47\u200D\u2642\uFE0F":"1f647-2642","\uD83D\uDE4B\u200D\u2640\uFE0F":"1f64b-2640","\uD83D\uDE4B\u200D\u2642\uFE0F":"1f64b-2642","\uD83D\uDE4D\u200D\u2640\uFE0F":"1f64d-2640","\uD83D\uDE4D\u200D\u2642\uFE0F":"1f64d-2642","\uD83D\uDE4E\u200D\u2640\uFE0F":"1f64e-2640","\uD83D\uDE4E\u200D\u2642\uFE0F":"1f64e-2642","\uD83E\uDD26\u200D\u2640\uFE0F":"1f926-2640","\uD83E\uDD26\u200D\u2642\uFE0F":"1f926-2642","\uD83E\uDD37\u200D\u2640\uFE0F":"1f937-2640","\uD83E\uDD37\u200D\u2642\uFE0F":"1f937-2642","\uD83E\uDDD9\u200D\u2640\uFE0F":"1f9d9-2640","\uD83E\uDDD9\u200D\u2642\uFE0F":"1f9d9-2642","\uD83E\uDDDA\u200D\u2640\uFE0F":"1f9da-2640","\uD83E\uDDDA\u200D\u2642\uFE0F":"1f9da-2642","\uD83E\uDDDB\u200D\u2640\uFE0F":"1f9db-2640","\uD83E\uDDDB\u200D\u2642\uFE0F":"1f9db-2642","\uD83E\uDDDC\u200D\u2640\uFE0F":"1f9dc-2640","\uD83E\uDDDC\u200D\u2642\uFE0F":"1f9dc-2642","\uD83E\uDDDD\u200D\u2640\uFE0F":"1f9dd-2640","\uD83E\uDDDD\u200D\u2642\uFE0F":"1f9dd-2642","\uD83E\uDDDE\u200D\u2640\uFE0F":"1f9de-2640","\uD83E\uDDDE\u200D\u2642\uFE0F":"1f9de-2642","\uD83E\uDDDF\u200D\u2640\uFE0F":"1f9df-2640","\uD83E\uDDDF\u200D\u2642\uFE0F":"1f9df-2642","\uD83E\uDDD6\u200D\u2640\uFE0F":"1f9d6-2640","\uD83E\uDDD6\u200D\u2642\uFE0F":"1f9d6-2642","\uD83E\uDDD7\u200D\u2640\uFE0F":"1f9d7-2640","\uD83E\uDDD7\u200D\u2642\uFE0F":"1f9d7-2642","\uD83E\uDDD8\u200D\u2640\uFE0F":"1f9d8-2640","\uD83E\uDDD8\u200D\u2642\uFE0F":"1f9d8-2642","\u26F9\uFE0F\u2640\uFE0F":"26f9-2640","\u26F9\uFE0F\u2642\uFE0F":"26f9-2642","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC66":"1f468-1f468-1f466","\uD83D\uDC68\uD83D\uDC68\uD83D\uDC67":"1f468-1f468-1f467","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC67":"1f468-1f469-1f467","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC66":"1f469-1f469-1f466","\uD83D\uDC69\uD83D\uDC69\uD83D\uDC67":"1f469-1f469-1f467","\uD83D\uDC68\uD83D\uDC66\uD83D\uDC66":"1f468-1f466-1f466","\uD83D\uDC68\uD83D\uDC67\uD83D\uDC66":"1f468-1f467-1f466","\uD83D\uDC69\uD83D\uDC66\uD83D\uDC66":"1f469-1f466-1f466","\uD83D\uDC69\uD83D\uDC67\uD83D\uDC66":"1f469-1f467-1f466","\uD83D\uDC69\uD83D\uDC67\uD83D\uDC67":"1f469-1f467-1f467","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDFA8":"1f468-1f3fb-1f3a8","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDFA8":"1f468-1f3fc-1f3a8","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDFA8":"1f468-1f3fd-1f3a8","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDFA8":"1f468-1f3fe-1f3a8","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDFA8":"1f468-1f3ff-1f3a8","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDFA8":"1f469-1f3fb-1f3a8","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDFA8":"1f469-1f3fc-1f3a8","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDFA8":"1f469-1f3fd-1f3a8","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDFA8":"1f469-1f3fe-1f3a8","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDFA8":"1f469-1f3ff-1f3a8","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDE80":"1f468-1f3fb-1f680","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDE80":"1f468-1f3fc-1f680","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDE80":"1f468-1f3fd-1f680","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDE80":"1f468-1f3fe-1f680","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDE80":"1f468-1f3ff-1f680","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDE80":"1f469-1f3fb-1f680","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDE80":"1f469-1f3fc-1f680","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDE80":"1f469-1f3fd-1f680","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDE80":"1f469-1f3fe-1f680","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDE80":"1f469-1f3ff-1f680","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDE92":"1f468-1f3fb-1f692","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDE92":"1f468-1f3fc-1f692","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDE92":"1f468-1f3fd-1f692","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDE92":"1f468-1f3fe-1f692","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDE92":"1f468-1f3ff-1f692","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDE92":"1f469-1f3fb-1f692","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDE92":"1f469-1f3fc-1f692","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDE92":"1f469-1f3fd-1f692","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDE92":"1f469-1f3fe-1f692","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDE92":"1f469-1f3ff-1f692","\uD83D\uDC68\uD83D\uDC69\uD83D\uDC66":"1f468-1f469-1f466","\uD83D\uDC68\uD83D\uDC67\uD83D\uDC67":"1f468-1f467-1f467","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDF3E":"1f468-1f3fb-1f33e","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDF73":"1f468-1f3fb-1f373","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDF93":"1f468-1f3fb-1f393","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDFA4":"1f468-1f3fb-1f3a4","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDFEB":"1f468-1f3fb-1f3eb","\uD83D\uDC68\uD83C\uDFFB\uD83C\uDFED":"1f468-1f3fb-1f3ed","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDCBB":"1f468-1f3fb-1f4bb","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDCBC":"1f468-1f3fb-1f4bc","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDD27":"1f468-1f3fb-1f527","\uD83D\uDC68\uD83C\uDFFB\uD83D\uDD2C":"1f468-1f3fb-1f52c","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDF3E":"1f468-1f3fc-1f33e","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDF73":"1f468-1f3fc-1f373","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDF93":"1f468-1f3fc-1f393","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDFA4":"1f468-1f3fc-1f3a4","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDFEB":"1f468-1f3fc-1f3eb","\uD83D\uDC68\uD83C\uDFFC\uD83C\uDFED":"1f468-1f3fc-1f3ed","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDCBB":"1f468-1f3fc-1f4bb","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDCBC":"1f468-1f3fc-1f4bc","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDD27":"1f468-1f3fc-1f527","\uD83D\uDC68\uD83C\uDFFC\uD83D\uDD2C":"1f468-1f3fc-1f52c","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDF3E":"1f468-1f3fd-1f33e","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDF73":"1f468-1f3fd-1f373","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDF93":"1f468-1f3fd-1f393","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDFA4":"1f468-1f3fd-1f3a4","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDFEB":"1f468-1f3fd-1f3eb","\uD83D\uDC68\uD83C\uDFFD\uD83C\uDFED":"1f468-1f3fd-1f3ed","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDCBB":"1f468-1f3fd-1f4bb","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDCBC":"1f468-1f3fd-1f4bc","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDD27":"1f468-1f3fd-1f527","\uD83D\uDC68\uD83C\uDFFD\uD83D\uDD2C":"1f468-1f3fd-1f52c","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDF3E":"1f468-1f3fe-1f33e","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDF73":"1f468-1f3fe-1f373","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDF93":"1f468-1f3fe-1f393","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDFA4":"1f468-1f3fe-1f3a4","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDFEB":"1f468-1f3fe-1f3eb","\uD83D\uDC68\uD83C\uDFFE\uD83C\uDFED":"1f468-1f3fe-1f3ed","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDCBB":"1f468-1f3fe-1f4bb","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDCBC":"1f468-1f3fe-1f4bc","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDD27":"1f468-1f3fe-1f527","\uD83D\uDC68\uD83C\uDFFE\uD83D\uDD2C":"1f468-1f3fe-1f52c","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDF3E":"1f468-1f3ff-1f33e","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDF73":"1f468-1f3ff-1f373","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDF93":"1f468-1f3ff-1f393","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDFA4":"1f468-1f3ff-1f3a4","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDFEB":"1f468-1f3ff-1f3eb","\uD83D\uDC68\uD83C\uDFFF\uD83C\uDFED":"1f468-1f3ff-1f3ed","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDCBB":"1f468-1f3ff-1f4bb","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDCBC":"1f468-1f3ff-1f4bc","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDD27":"1f468-1f3ff-1f527","\uD83D\uDC68\uD83C\uDFFF\uD83D\uDD2C":"1f468-1f3ff-1f52c","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDF3E":"1f469-1f3fb-1f33e","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDF73":"1f469-1f3fb-1f373","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDF93":"1f469-1f3fb-1f393","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDFA4":"1f469-1f3fb-1f3a4","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDFEB":"1f469-1f3fb-1f3eb","\uD83D\uDC69\uD83C\uDFFB\uD83C\uDFED":"1f469-1f3fb-1f3ed","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDCBB":"1f469-1f3fb-1f4bb","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDCBC":"1f469-1f3fb-1f4bc","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDD27":"1f469-1f3fb-1f527","\uD83D\uDC69\uD83C\uDFFB\uD83D\uDD2C":"1f469-1f3fb-1f52c","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDF3E":"1f469-1f3fc-1f33e","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDF73":"1f469-1f3fc-1f373","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDF93":"1f469-1f3fc-1f393","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDFA4":"1f469-1f3fc-1f3a4","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDFEB":"1f469-1f3fc-1f3eb","\uD83D\uDC69\uD83C\uDFFC\uD83C\uDFED":"1f469-1f3fc-1f3ed","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDCBB":"1f469-1f3fc-1f4bb","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDCBC":"1f469-1f3fc-1f4bc","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDD27":"1f469-1f3fc-1f527","\uD83D\uDC69\uD83C\uDFFC\uD83D\uDD2C":"1f469-1f3fc-1f52c","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF3E":"1f469-1f3fd-1f33e","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF73":"1f469-1f3fd-1f373","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDF93":"1f469-1f3fd-1f393","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDFA4":"1f469-1f3fd-1f3a4","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDFEB":"1f469-1f3fd-1f3eb","\uD83D\uDC69\uD83C\uDFFD\uD83C\uDFED":"1f469-1f3fd-1f3ed","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDCBB":"1f469-1f3fd-1f4bb","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDCBC":"1f469-1f3fd-1f4bc","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDD27":"1f469-1f3fd-1f527","\uD83D\uDC69\uD83C\uDFFD\uD83D\uDD2C":"1f469-1f3fd-1f52c","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDF3E":"1f469-1f3fe-1f33e","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDF73":"1f469-1f3fe-1f373","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDF93":"1f469-1f3fe-1f393","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDFA4":"1f469-1f3fe-1f3a4","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDFEB":"1f469-1f3fe-1f3eb","\uD83D\uDC69\uD83C\uDFFE\uD83C\uDFED":"1f469-1f3fe-1f3ed","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDCBB":"1f469-1f3fe-1f4bb","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDCBC":"1f469-1f3fe-1f4bc","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDD27":"1f469-1f3fe-1f527","\uD83D\uDC69\uD83C\uDFFE\uD83D\uDD2C":"1f469-1f3fe-1f52c","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDF3E":"1f469-1f3ff-1f33e","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDF73":"1f469-1f3ff-1f373","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDF93":"1f469-1f3ff-1f393","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDFA4":"1f469-1f3ff-1f3a4","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDFEB":"1f469-1f3ff-1f3eb","\uD83D\uDC69\uD83C\uDFFF\uD83C\uDFED":"1f469-1f3ff-1f3ed","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDCBB":"1f469-1f3ff-1f4bb","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDCBC":"1f469-1f3ff-1f4bc","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDD27":"1f469-1f3ff-1f527","\uD83D\uDC69\uD83C\uDFFF\uD83D\uDD2C":"1f469-1f3ff-1f52c","\uD83D\uDC41\u200D\uD83D\uDDE8":"1f441-1f5e8","\uD83D\uDC68\u200D\uD83D\uDCBB":"1f468-1f4bb","\uD83D\uDC69\u200D\uD83D\uDCBB":"1f469-1f4bb","\uD83D\uDC68\u200D\uD83C\uDFEB":"1f468-1f3eb","\uD83D\uDC69\u200D\uD83C\uDFEB":"1f469-1f3eb","\uD83D\uDC68\u200D\uD83C\uDF93":"1f468-1f393","\uD83D\uDC69\u200D\uD83C\uDF93":"1f469-1f393","\uD83D\uDC68\u200D\uD83C\uDFA4":"1f468-1f3a4","\uD83D\uDC69\u200D\uD83C\uDFA4":"1f469-1f3a4","\uD83D\uDC68\u200D\uD83D\uDD2C":"1f468-1f52c","\uD83D\uDC69\u200D\uD83D\uDD2C":"1f469-1f52c","\uD83D\uDC68\u200D\uD83D\uDCBC":"1f468-1f4bc","\uD83D\uDC69\u200D\uD83D\uDCBC":"1f469-1f4bc","\uD83D\uDC68\u200D\uD83D\uDD27":"1f468-1f527","\uD83D\uDC69\u200D\uD83D\uDD27":"1f469-1f527","\uD83D\uDC68\u200D\uD83C\uDFED":"1f468-1f3ed","\uD83D\uDC69\u200D\uD83C\uDFED":"1f469-1f3ed","\uD83D\uDC68\u200D\uD83C\uDF73":"1f468-1f373","\uD83D\uDC69\u200D\uD83C\uDF73":"1f469-1f373","\uD83D\uDC68\u200D\uD83C\uDF3E":"1f468-1f33e","\uD83D\uDC69\u200D\uD83C\uDF3E":"1f469-1f33e","\uD83D\uDC68\u200D\uD83D\uDC66":"1f468-1f466","\uD83D\uDC68\u200D\uD83D\uDC67":"1f468-1f467","\uD83D\uDC69\u200D\uD83D\uDC66":"1f469-1f466","\uD83D\uDC69\u200D\uD83D\uDC67":"1f469-1f467","\uD83D\uDC68\u200D\uD83C\uDFA8":"1f468-1f3a8","\uD83D\uDC69\u200D\uD83C\uDFA8":"1f469-1f3a8","\uD83D\uDC68\u200D\uD83D\uDE80":"1f468-1f680","\uD83D\uDC69\u200D\uD83D\uDE80":"1f469-1f680","\uD83D\uDC68\u200D\uD83D\uDE92":"1f468-1f692","\uD83D\uDC69\u200D\uD83D\uDE92":"1f469-1f692","\uD83C\uDFCB\uFE0F\uD83C\uDFFB":"1f3cb-1f3fb","\uD83C\uDFCB\uFE0F\uD83C\uDFFC":"1f3cb-1f3fc","\uD83C\uDFCB\uFE0F\uD83C\uDFFD":"1f3cb-1f3fd","\uD83C\uDFCB\uFE0F\uD83C\uDFFE":"1f3cb-1f3fe","\uD83C\uDFCB\uFE0F\uD83C\uDFFF":"1f3cb-1f3ff","\uD83C\uDFCC\uFE0F\uD83C\uDFFB":"1f3cc-1f3fb","\uD83C\uDFCC\uFE0F\uD83C\uDFFC":"1f3cc-1f3fc","\uD83C\uDFCC\uFE0F\uD83C\uDFFD":"1f3cc-1f3fd","\uD83C\uDFCC\uFE0F\uD83C\uDFFE":"1f3cc-1f3fe","\uD83C\uDFCC\uFE0F\uD83C\uDFFF":"1f3cc-1f3ff","\uD83D\uDD74\uFE0F\uD83C\uDFFB":"1f574-1f3fb","\uD83D\uDD74\uFE0F\uD83C\uDFFC":"1f574-1f3fc","\uD83D\uDD74\uFE0F\uD83C\uDFFD":"1f574-1f3fd","\uD83D\uDD74\uFE0F\uD83C\uDFFE":"1f574-1f3fe","\uD83D\uDD74\uFE0F\uD83C\uDFFF":"1f574-1f3ff","\uD83D\uDD75\uFE0F\uD83C\uDFFB":"1f575-1f3fb","\uD83D\uDD75\uFE0F\uD83C\uDFFC":"1f575-1f3fc","\uD83D\uDD75\uFE0F\uD83C\uDFFD":"1f575-1f3fd","\uD83D\uDD75\uFE0F\uD83C\uDFFE":"1f575-1f3fe","\uD83D\uDD75\uFE0F\uD83C\uDFFF":"1f575-1f3ff","\uD83D\uDD90\uFE0F\uD83C\uDFFB":"1f590-1f3fb","\uD83D\uDD90\uFE0F\uD83C\uDFFC":"1f590-1f3fc","\uD83D\uDD90\uFE0F\uD83C\uDFFD":"1f590-1f3fd","\uD83D\uDD90\uFE0F\uD83C\uDFFE":"1f590-1f3fe","\uD83D\uDD90\uFE0F\uD83C\uDFFF":"1f590-1f3ff","\uD83C\uDFF3\u200D\uD83C\uDF08":"1f3f3-1f308","\uD83C\uDFF3\uFE0F\uD83C\uDF08":"1f3f3-1f308","\uD83D\uDC6F\u200D\u2642":"1f46f-2642","\uD83D\uDC6F\u200D\u2640":"1f46f-2640","\uD83E\uDD3C\u200D\u2642":"1f93c-2642","\uD83E\uDD3C\u200D\u2640":"1f93c-2640","\uD83E\uDD39\u200D\u2642":"1f939-2642","\uD83E\uDD39\u200D\u2640":"1f939-2640","\uD83E\uDD3E\u200D\u2642":"1f93e-2642","\uD83E\uDD3E\u200D\u2640":"1f93e-2640","\uD83E\uDD3D\u200D\u2642":"1f93d-2642","\uD83E\uDD3D\u200D\u2640":"1f93d-2640","\uD83E\uDD38\u200D\u2642":"1f938-2642","\uD83E\uDD38\u200D\u2640":"1f938-2640","\uD83D\uDEB6\u200D\u2642":"1f6b6-2642","\uD83D\uDEB6\u200D\u2640":"1f6b6-2640","\uD83D\uDEB5\u200D\u2642":"1f6b5-2642","\uD83D\uDEB5\u200D\u2640":"1f6b5-2640","\uD83D\uDEB4\u200D\u2642":"1f6b4-2642","\uD83D\uDEB4\u200D\u2640":"1f6b4-2640","\uD83D\uDEA3\u200D\u2642":"1f6a3-2642","\uD83D\uDEA3\u200D\u2640":"1f6a3-2640","\uD83C\uDFCA\u200D\u2642":"1f3ca-2642","\uD83C\uDFCA\u200D\u2640":"1f3ca-2640","\uD83C\uDFC4\u200D\u2642":"1f3c4-2642","\uD83C\uDFC4\u200D\u2640":"1f3c4-2640","\uD83C\uDFC3\u200D\u2642":"1f3c3-2642","\uD83C\uDFC3\u200D\u2640":"1f3c3-2640","\uD83E\uDD37\u200D\u2642":"1f937-2642","\uD83E\uDD37\u200D\u2640":"1f937-2640","\uD83E\uDD26\u200D\u2642":"1f926-2642","\uD83E\uDD26\u200D\u2640":"1f926-2640","\uD83D\uDE4E\u200D\u2642":"1f64e-2642","\uD83D\uDE4E\u200D\u2640":"1f64e-2640","\uD83D\uDE4D\u200D\u2642":"1f64d-2642","\uD83D\uDE4D\u200D\u2640":"1f64d-2640","\uD83D\uDE4B\u200D\u2642":"1f64b-2642","\uD83D\uDE4B\u200D\u2640":"1f64b-2640","\uD83D\uDE47\u200D\u2642":"1f647-2642","\uD83D\uDE47\u200D\u2640":"1f647-2640","\uD83D\uDE46\u200D\u2642":"1f646-2642","\uD83D\uDE46\u200D\u2640":"1f646-2640","\uD83D\uDE45\u200D\u2642":"1f645-2642","\uD83D\uDE45\u200D\u2640":"1f645-2640","\uD83D\uDC87\u200D\u2642":"1f487-2642","\uD83D\uDC87\u200D\u2640":"1f487-2640","\uD83D\uDC86\u200D\u2642":"1f486-2642","\uD83D\uDC86\u200D\u2640":"1f486-2640","\uD83D\uDC81\u200D\u2642":"1f481-2642","\uD83D\uDC81\u200D\u2640":"1f481-2640","\uD83D\uDC71\u200D\u2642":"1f471-2642","\uD83D\uDC71\u200D\u2640":"1f471-2640","\uD83D\uDC73\u200D\u2642":"1f473-2642","\uD83D\uDC73\u200D\u2640":"1f473-2640","\uD83D\uDC82\u200D\u2642":"1f482-2642","\uD83D\uDC82\u200D\u2640":"1f482-2640","\uD83D\uDC77\u200D\u2642":"1f477-2642","\uD83D\uDC77\u200D\u2640":"1f477-2640","\uD83D\uDC6E\u200D\u2642":"1f46e-2642","\uD83D\uDC6E\u200D\u2640":"1f46e-2640","\uD83D\uDC68\u200D\u2695":"1f468-2695","\uD83D\uDC69\u200D\u2695":"1f469-2695","\uD83D\uDC68\u200D\u2696":"1f468-2696","\uD83D\uDC69\u200D\u2696":"1f469-2696","\uD83D\uDC68\u200D\u2708":"1f468-2708","\uD83D\uDC69\u200D\u2708":"1f469-2708","\u261D\uFE0F\uD83C\uDFFB":"261d-1f3fb","\u261D\uFE0F\uD83C\uDFFC":"261d-1f3fc","\u261D\uFE0F\uD83C\uDFFD":"261d-1f3fd","\u261D\uFE0F\uD83C\uDFFE":"261d-1f3fe","\u261D\uFE0F\uD83C\uDFFF":"261d-1f3ff","\u26F9\uFE0F\uD83C\uDFFB":"26f9-1f3fb","\u26F9\uFE0F\uD83C\uDFFC":"26f9-1f3fc","\u26F9\uFE0F\uD83C\uDFFD":"26f9-1f3fd","\u26F9\uFE0F\uD83C\uDFFE":"26f9-1f3fe","\u26F9\uFE0F\uD83C\uDFFF":"26f9-1f3ff","\u270C\uFE0F\uD83C\uDFFB":"270c-1f3fb","\u270C\uFE0F\uD83C\uDFFC":"270c-1f3fc","\u270C\uFE0F\uD83C\uDFFD":"270c-1f3fd","\u270C\uFE0F\uD83C\uDFFE":"270c-1f3fe","\u270C\uFE0F\uD83C\uDFFF":"270c-1f3ff","\u270D\uFE0F\uD83C\uDFFB":"270d-1f3fb","\u270D\uFE0F\uD83C\uDFFC":"270d-1f3fc","\u270D\uFE0F\uD83C\uDFFD":"270d-1f3fd","\u270D\uFE0F\uD83C\uDFFE":"270d-1f3fe","\u270D\uFE0F\uD83C\uDFFF":"270d-1f3ff","\uD83D\uDC68\u2695\uFE0F":"1f468-2695","\uD83D\uDC68\u2696\uFE0F":"1f468-2696","\uD83D\uDC68\u2708\uFE0F":"1f468-2708","\uD83D\uDC69\u2695\uFE0F":"1f469-2695","\uD83D\uDC69\u2696\uFE0F":"1f469-2696","\uD83D\uDC69\u2708\uFE0F":"1f469-2708","\uD83D\uDC6E\u2640\uFE0F":"1f46e-2640","\uD83D\uDC6E\u2642\uFE0F":"1f46e-2642","\uD83D\uDC71\u2640\uFE0F":"1f471-2640","\uD83D\uDC71\u2642\uFE0F":"1f471-2642","\uD83D\uDC73\u2640\uFE0F":"1f473-2640","\uD83D\uDC73\u2642\uFE0F":"1f473-2642","\uD83D\uDC77\u2640\uFE0F":"1f477-2640","\uD83D\uDC77\u2642\uFE0F":"1f477-2642","\uD83D\uDC82\u2640\uFE0F":"1f482-2640","\uD83D\uDC82\u2642\uFE0F":"1f482-2642","\uD83D\uDD75\u200D\u2640":"1f575-2640","\uD83D\uDD75\u200D\u2642":"1f575-2642","\uD83C\uDFC3\u2640\uFE0F":"1f3c3-2640","\uD83C\uDFC3\u2642\uFE0F":"1f3c3-2642","\uD83C\uDFC4\u2640\uFE0F":"1f3c4-2640","\uD83C\uDFC4\u2642\uFE0F":"1f3c4-2642","\uD83C\uDFCA\u2640\uFE0F":"1f3ca-2640","\uD83C\uDFCA\u2642\uFE0F":"1f3ca-2642","\uD83C\uDFCB\u200D\u2640":"1f3cb-2640","\uD83C\uDFCB\u200D\u2642":"1f3cb-2642","\uD83C\uDFCC\u200D\u2640":"1f3cc-2640","\uD83C\uDFCC\u200D\u2642":"1f3cc-2642","\uD83D\uDC6F\u2640\uFE0F":"1f46f-2640","\uD83D\uDC6F\u2642\uFE0F":"1f46f-2642","\uD83D\uDC86\u2640\uFE0F":"1f486-2640","\uD83D\uDC86\u2642\uFE0F":"1f486-2642","\uD83D\uDC87\u2640\uFE0F":"1f487-2640","\uD83D\uDC87\u2642\uFE0F":"1f487-2642","\uD83D\uDEA3\u2640\uFE0F":"1f6a3-2640","\uD83D\uDEA3\u2642\uFE0F":"1f6a3-2642","\uD83D\uDEB4\u2640\uFE0F":"1f6b4-2640","\uD83D\uDEB4\u2642\uFE0F":"1f6b4-2642","\uD83D\uDEB5\u2640\uFE0F":"1f6b5-2640","\uD83D\uDEB5\u2642\uFE0F":"1f6b5-2642","\uD83D\uDEB6\u2640\uFE0F":"1f6b6-2640","\uD83D\uDEB6\u2642\uFE0F":"1f6b6-2642","\uD83E\uDD38\u2640\uFE0F":"1f938-2640","\uD83E\uDD38\u2642\uFE0F":"1f938-2642","\uD83E\uDD39\u2640\uFE0F":"1f939-2640","\uD83E\uDD39\u2642\uFE0F":"1f939-2642","\uD83E\uDD3C\u2640\uFE0F":"1f93c-2640","\uD83E\uDD3C\u2642\uFE0F":"1f93c-2642","\uD83E\uDD3D\u2640\uFE0F":"1f93d-2640","\uD83E\uDD3D\u2642\uFE0F":"1f93d-2642","\uD83E\uDD3E\u2640\uFE0F":"1f93e-2640","\uD83E\uDD3E\u2642\uFE0F":"1f93e-2642","\uD83D\uDC81\u2640\uFE0F":"1f481-2640","\uD83D\uDC81\u2642\uFE0F":"1f481-2642","\uD83D\uDE45\u2640\uFE0F":"1f645-2640","\uD83D\uDE45\u2642\uFE0F":"1f645-2642","\uD83D\uDE46\u2640\uFE0F":"1f646-2640","\uD83D\uDE46\u2642\uFE0F":"1f646-2642","\uD83D\uDE47\u2640\uFE0F":"1f647-2640","\uD83D\uDE47\u2642\uFE0F":"1f647-2642","\uD83D\uDE4B\u2640\uFE0F":"1f64b-2640","\uD83D\uDE4B\u2642\uFE0F":"1f64b-2642","\uD83D\uDE4D\u2640\uFE0F":"1f64d-2640","\uD83D\uDE4D\u2642\uFE0F":"1f64d-2642","\uD83D\uDE4E\u2640\uFE0F":"1f64e-2640","\uD83D\uDE4E\u2642\uFE0F":"1f64e-2642","\uD83E\uDD26\u2640\uFE0F":"1f926-2640","\uD83E\uDD26\u2642\uFE0F":"1f926-2642","\uD83E\uDD37\u2640\uFE0F":"1f937-2640","\uD83E\uDD37\u2642\uFE0F":"1f937-2642","\uD83E\uDDD9\u200D\u2640":"1f9d9-2640","\uD83E\uDDD9\u2640\uFE0F":"1f9d9-2640","\uD83E\uDDD9\u200D\u2642":"1f9d9-2642","\uD83E\uDDD9\u2642\uFE0F":"1f9d9-2642","\uD83E\uDDDA\u200D\u2640":"1f9da-2640","\uD83E\uDDDA\u2640\uFE0F":"1f9da-2640","\uD83E\uDDDA\u200D\u2642":"1f9da-2642","\uD83E\uDDDA\u2642\uFE0F":"1f9da-2642","\uD83E\uDDDB\u200D\u2640":"1f9db-2640","\uD83E\uDDDB\u2640\uFE0F":"1f9db-2640","\uD83E\uDDDB\u200D\u2642":"1f9db-2642","\uD83E\uDDDB\u2642\uFE0F":"1f9db-2642","\uD83E\uDDDC\u200D\u2640":"1f9dc-2640","\uD83E\uDDDC\u2640\uFE0F":"1f9dc-2640","\uD83E\uDDDC\u200D\u2642":"1f9dc-2642","\uD83E\uDDDC\u2642\uFE0F":"1f9dc-2642","\uD83E\uDDDD\u200D\u2640":"1f9dd-2640","\uD83E\uDDDD\u2640\uFE0F":"1f9dd-2640","\uD83E\uDDDD\u200D\u2642":"1f9dd-2642","\uD83E\uDDDD\u2642\uFE0F":"1f9dd-2642","\uD83E\uDDDE\u200D\u2640":"1f9de-2640","\uD83E\uDDDE\u2640\uFE0F":"1f9de-2640","\uD83E\uDDDE\u200D\u2642":"1f9de-2642","\uD83E\uDDDE\u2642\uFE0F":"1f9de-2642","\uD83E\uDDDF\u200D\u2640":"1f9df-2640","\uD83E\uDDDF\u2640\uFE0F":"1f9df-2640","\uD83E\uDDDF\u200D\u2642":"1f9df-2642","\uD83E\uDDDF\u2642\uFE0F":"1f9df-2642","\uD83E\uDDD6\u200D\u2640":"1f9d6-2640","\uD83E\uDDD6\u2640\uFE0F":"1f9d6-2640","\uD83E\uDDD6\u200D\u2642":"1f9d6-2642","\uD83E\uDDD6\u2642\uFE0F":"1f9d6-2642","\uD83E\uDDD7\u200D\u2640":"1f9d7-2640","\uD83E\uDDD7\u2640\uFE0F":"1f9d7-2640","\uD83E\uDDD7\u200D\u2642":"1f9d7-2642","\uD83E\uDDD7\u2642\uFE0F":"1f9d7-2642","\uD83E\uDDD8\u200D\u2640":"1f9d8-2640","\uD83E\uDDD8\u2640\uFE0F":"1f9d8-2640","\uD83E\uDDD8\u200D\u2642":"1f9d8-2642","\uD83E\uDDD8\u2642\uFE0F":"1f9d8-2642","#\uFE0F\u20E3":"0023-20e3","0\uFE0F\u20E3":"0030-20e3","1\uFE0F\u20E3":"0031-20e3","2\uFE0F\u20E3":"0032-20e3","3\uFE0F\u20E3":"0033-20e3","4\uFE0F\u20E3":"0034-20e3","5\uFE0F\u20E3":"0035-20e3","6\uFE0F\u20E3":"0036-20e3","7\uFE0F\u20E3":"0037-20e3","8\uFE0F\u20E3":"0038-20e3","9\uFE0F\u20E3":"0039-20e3","*\uFE0F\u20E3":"002a-20e3","\u26F9\u200D\u2640":"26f9-2640","\u26F9\u200D\u2642":"26f9-2642","\uD83C\uDDE8\uD83C\uDDF3":"1f1e8-1f1f3","\uD83C\uDDE9\uD83C\uDDEA":"1f1e9-1f1ea","\uD83C\uDDEA\uD83C\uDDF8":"1f1ea-1f1f8","\uD83C\uDDEB\uD83C\uDDF7":"1f1eb-1f1f7","\uD83C\uDDEC\uD83C\uDDE7":"1f1ec-1f1e7","\uD83C\uDDEE\uD83C\uDDF9":"1f1ee-1f1f9","\uD83C\uDDEF\uD83C\uDDF5":"1f1ef-1f1f5","\uD83C\uDDF0\uD83C\uDDF7":"1f1f0-1f1f7","\uD83C\uDDFA\uD83C\uDDF8":"1f1fa-1f1f8","\uD83C\uDDF7\uD83C\uDDFA":"1f1f7-1f1fa","\uD83E\uDD34\uD83C\uDFFB":"1f934-1f3fb","\uD83E\uDD34\uD83C\uDFFC":"1f934-1f3fc","\uD83E\uDD34\uD83C\uDFFD":"1f934-1f3fd","\uD83E\uDD34\uD83C\uDFFE":"1f934-1f3fe","\uD83E\uDD34\uD83C\uDFFF":"1f934-1f3ff","\uD83E\uDD36\uD83C\uDFFB":"1f936-1f3fb","\uD83E\uDD36\uD83C\uDFFC":"1f936-1f3fc","\uD83E\uDD36\uD83C\uDFFD":"1f936-1f3fd","\uD83E\uDD36\uD83C\uDFFE":"1f936-1f3fe","\uD83E\uDD36\uD83C\uDFFF":"1f936-1f3ff","\uD83E\uDD35\uD83C\uDFFB":"1f935-1f3fb","\uD83E\uDD35\uD83C\uDFFC":"1f935-1f3fc","\uD83E\uDD35\uD83C\uDFFD":"1f935-1f3fd","\uD83E\uDD35\uD83C\uDFFE":"1f935-1f3fe","\uD83E\uDD35\uD83C\uDFFF":"1f935-1f3ff","\uD83E\uDD37\uD83C\uDFFB":"1f937-1f3fb","\uD83E\uDD37\uD83C\uDFFC":"1f937-1f3fc","\uD83E\uDD37\uD83C\uDFFD":"1f937-1f3fd","\uD83E\uDD37\uD83C\uDFFE":"1f937-1f3fe","\uD83E\uDD37\uD83C\uDFFF":"1f937-1f3ff","\uD83E\uDD26\uD83C\uDFFB":"1f926-1f3fb","\uD83E\uDD26\uD83C\uDFFC":"1f926-1f3fc","\uD83E\uDD26\uD83C\uDFFD":"1f926-1f3fd","\uD83E\uDD26\uD83C\uDFFE":"1f926-1f3fe","\uD83E\uDD26\uD83C\uDFFF":"1f926-1f3ff","\uD83E\uDD30\uD83C\uDFFB":"1f930-1f3fb","\uD83E\uDD30\uD83C\uDFFC":"1f930-1f3fc","\uD83E\uDD30\uD83C\uDFFD":"1f930-1f3fd","\uD83E\uDD30\uD83C\uDFFE":"1f930-1f3fe","\uD83E\uDD30\uD83C\uDFFF":"1f930-1f3ff","\uD83D\uDD7A\uD83C\uDFFB":"1f57a-1f3fb","\uD83D\uDD7A\uD83C\uDFFC":"1f57a-1f3fc","\uD83D\uDD7A\uD83C\uDFFD":"1f57a-1f3fd","\uD83D\uDD7A\uD83C\uDFFE":"1f57a-1f3fe","\uD83D\uDD7A\uD83C\uDFFF":"1f57a-1f3ff","\uD83E\uDD33\uD83C\uDFFB":"1f933-1f3fb","\uD83E\uDD33\uD83C\uDFFC":"1f933-1f3fc","\uD83E\uDD33\uD83C\uDFFD":"1f933-1f3fd","\uD83E\uDD33\uD83C\uDFFE":"1f933-1f3fe","\uD83E\uDD33\uD83C\uDFFF":"1f933-1f3ff","\uD83E\uDD1E\uD83C\uDFFB":"1f91e-1f3fb","\uD83E\uDD1E\uD83C\uDFFC":"1f91e-1f3fc","\uD83E\uDD1E\uD83C\uDFFD":"1f91e-1f3fd","\uD83E\uDD1E\uD83C\uDFFE":"1f91e-1f3fe","\uD83E\uDD1E\uD83C\uDFFF":"1f91e-1f3ff","\uD83E\uDD19\uD83C\uDFFB":"1f919-1f3fb","\uD83E\uDD19\uD83C\uDFFC":"1f919-1f3fc","\uD83E\uDD19\uD83C\uDFFD":"1f919-1f3fd","\uD83C\uDDE6\uD83C\uDDEB":"1f1e6-1f1eb","\uD83C\uDDE6\uD83C\uDDF1":"1f1e6-1f1f1","\uD83C\uDDE9\uD83C\uDDFF":"1f1e9-1f1ff","\uD83C\uDDE6\uD83C\uDDE9":"1f1e6-1f1e9","\uD83C\uDDE6\uD83C\uDDF4":"1f1e6-1f1f4","\uD83C\uDDE6\uD83C\uDDEC":"1f1e6-1f1ec","\uD83C\uDDE6\uD83C\uDDF7":"1f1e6-1f1f7","\uD83C\uDDE6\uD83C\uDDF2":"1f1e6-1f1f2","\uD83C\uDDE6\uD83C\uDDFA":"1f1e6-1f1fa","\uD83C\uDDE6\uD83C\uDDF9":"1f1e6-1f1f9","\uD83C\uDDE6\uD83C\uDDFF":"1f1e6-1f1ff","\uD83C\uDDE7\uD83C\uDDF8":"1f1e7-1f1f8","\uD83C\uDDE7\uD83C\uDDED":"1f1e7-1f1ed","\uD83C\uDDE7\uD83C\uDDE9":"1f1e7-1f1e9","\uD83C\uDDE7\uD83C\uDDE7":"1f1e7-1f1e7","\uD83C\uDDE7\uD83C\uDDFE":"1f1e7-1f1fe","\uD83C\uDDE7\uD83C\uDDEA":"1f1e7-1f1ea","\uD83C\uDDE7\uD83C\uDDFF":"1f1e7-1f1ff","\uD83C\uDDE7\uD83C\uDDEF":"1f1e7-1f1ef","\uD83C\uDDE7\uD83C\uDDF9":"1f1e7-1f1f9","\uD83C\uDDE7\uD83C\uDDF4":"1f1e7-1f1f4","\uD83C\uDDE7\uD83C\uDDE6":"1f1e7-1f1e6","\uD83C\uDDE7\uD83C\uDDFC":"1f1e7-1f1fc","\uD83C\uDDE7\uD83C\uDDF7":"1f1e7-1f1f7","\uD83C\uDDE7\uD83C\uDDF3":"1f1e7-1f1f3","\uD83C\uDDE7\uD83C\uDDEC":"1f1e7-1f1ec","\uD83C\uDDE7\uD83C\uDDEB":"1f1e7-1f1eb","\uD83C\uDDE7\uD83C\uDDEE":"1f1e7-1f1ee","\uD83C\uDDF0\uD83C\uDDED":"1f1f0-1f1ed","\uD83C\uDDE8\uD83C\uDDF2":"1f1e8-1f1f2","\uD83C\uDDE8\uD83C\uDDE6":"1f1e8-1f1e6","\uD83C\uDDE8\uD83C\uDDFB":"1f1e8-1f1fb","\uD83E\uDD19\uD83C\uDFFE":"1f919-1f3fe","\uD83C\uDDE8\uD83C\uDDEB":"1f1e8-1f1eb","\uD83C\uDDF9\uD83C\uDDE9":"1f1f9-1f1e9","\uD83C\uDDE8\uD83C\uDDF1":"1f1e8-1f1f1","\uD83C\uDDE8\uD83C\uDDF4":"1f1e8-1f1f4","\uD83C\uDDF0\uD83C\uDDF2":"1f1f0-1f1f2","\uD83C\uDDE8\uD83C\uDDF7":"1f1e8-1f1f7","\uD83C\uDDE8\uD83C\uDDEE":"1f1e8-1f1ee","\uD83C\uDDED\uD83C\uDDF7":"1f1ed-1f1f7","\uD83C\uDDE8\uD83C\uDDFA":"1f1e8-1f1fa","\uD83C\uDDE8\uD83C\uDDFE":"1f1e8-1f1fe","\uD83C\uDDE8\uD83C\uDDFF":"1f1e8-1f1ff","\uD83E\uDD19\uD83C\uDFFF":"1f919-1f3ff","\uD83C\uDDE8\uD83C\uDDE9":"1f1e8-1f1e9","\uD83E\uDD1B\uD83C\uDFFB":"1f91b-1f3fb","\uD83C\uDDE9\uD83C\uDDF0":"1f1e9-1f1f0","\uD83C\uDDE9\uD83C\uDDEF":"1f1e9-1f1ef","\uD83C\uDDE9\uD83C\uDDF2":"1f1e9-1f1f2","\uD83C\uDDE9\uD83C\uDDF4":"1f1e9-1f1f4","\uD83C\uDDF9\uD83C\uDDF1":"1f1f9-1f1f1","\uD83C\uDDEA\uD83C\uDDE8":"1f1ea-1f1e8","\uD83C\uDDEA\uD83C\uDDEC":"1f1ea-1f1ec","\uD83C\uDDF8\uD83C\uDDFB":"1f1f8-1f1fb","\uD83C\uDDEC\uD83C\uDDF6":"1f1ec-1f1f6","\uD83C\uDDEA\uD83C\uDDF7":"1f1ea-1f1f7","\uD83C\uDDEA\uD83C\uDDEA":"1f1ea-1f1ea","\uD83C\uDDEA\uD83C\uDDF9":"1f1ea-1f1f9","\uD83E\uDD1B\uD83C\uDFFC":"1f91b-1f3fc","\uD83C\uDDEB\uD83C\uDDEF":"1f1eb-1f1ef","\uD83C\uDDEB\uD83C\uDDEE":"1f1eb-1f1ee","\uD83C\uDDEC\uD83C\uDDE6":"1f1ec-1f1e6","\uD83C\uDDEC\uD83C\uDDF2":"1f1ec-1f1f2","\uD83C\uDDEC\uD83C\uDDEA":"1f1ec-1f1ea","\uD83C\uDDEC\uD83C\uDDED":"1f1ec-1f1ed","\uD83C\uDDEC\uD83C\uDDF7":"1f1ec-1f1f7","\uD83C\uDDEC\uD83C\uDDE9":"1f1ec-1f1e9","\uD83C\uDDEC\uD83C\uDDF9":"1f1ec-1f1f9","\uD83C\uDDEC\uD83C\uDDF3":"1f1ec-1f1f3","\uD83C\uDDEC\uD83C\uDDFC":"1f1ec-1f1fc","\uD83C\uDDEC\uD83C\uDDFE":"1f1ec-1f1fe","\uD83C\uDDED\uD83C\uDDF9":"1f1ed-1f1f9","\uD83C\uDDED\uD83C\uDDF3":"1f1ed-1f1f3","\uD83C\uDDED\uD83C\uDDFA":"1f1ed-1f1fa","\uD83C\uDDEE\uD83C\uDDF8":"1f1ee-1f1f8","\uD83C\uDDEE\uD83C\uDDF3":"1f1ee-1f1f3","\uD83C\uDDEE\uD83C\uDDE9":"1f1ee-1f1e9","\uD83C\uDDEE\uD83C\uDDF7":"1f1ee-1f1f7","\uD83C\uDDEE\uD83C\uDDF6":"1f1ee-1f1f6","\uD83C\uDDEE\uD83C\uDDEA":"1f1ee-1f1ea","\uD83C\uDDEE\uD83C\uDDF1":"1f1ee-1f1f1","\uD83C\uDDEF\uD83C\uDDF2":"1f1ef-1f1f2","\uD83C\uDDEF\uD83C\uDDF4":"1f1ef-1f1f4","\uD83C\uDDF0\uD83C\uDDFF":"1f1f0-1f1ff","\uD83C\uDDF0\uD83C\uDDEA":"1f1f0-1f1ea","\uD83C\uDDF0\uD83C\uDDEE":"1f1f0-1f1ee","\uD83C\uDDFD\uD83C\uDDF0":"1f1fd-1f1f0","\uD83C\uDDF0\uD83C\uDDFC":"1f1f0-1f1fc","\uD83C\uDDF0\uD83C\uDDEC":"1f1f0-1f1ec","\uD83E\uDD1B\uD83C\uDFFD":"1f91b-1f3fd","\uD83C\uDDF1\uD83C\uDDE6":"1f1f1-1f1e6","\uD83C\uDDF1\uD83C\uDDFB":"1f1f1-1f1fb","\uD83C\uDDF1\uD83C\uDDE7":"1f1f1-1f1e7","\uD83C\uDDF1\uD83C\uDDF8":"1f1f1-1f1f8","\uD83C\uDDF1\uD83C\uDDF7":"1f1f1-1f1f7","\uD83C\uDDF1\uD83C\uDDFE":"1f1f1-1f1fe","\uD83C\uDDF1\uD83C\uDDEE":"1f1f1-1f1ee","\uD83C\uDDF1\uD83C\uDDF9":"1f1f1-1f1f9","\uD83C\uDDF1\uD83C\uDDFA":"1f1f1-1f1fa","\uD83C\uDDF2\uD83C\uDDF0":"1f1f2-1f1f0","\uD83C\uDDF2\uD83C\uDDEC":"1f1f2-1f1ec","\uD83C\uDDF2\uD83C\uDDFC":"1f1f2-1f1fc","\uD83C\uDDF2\uD83C\uDDFE":"1f1f2-1f1fe","\uD83C\uDDF2\uD83C\uDDFB":"1f1f2-1f1fb","\uD83C\uDDF2\uD83C\uDDF1":"1f1f2-1f1f1","\uD83C\uDDF2\uD83C\uDDF9":"1f1f2-1f1f9","\uD83C\uDDF2\uD83C\uDDED":"1f1f2-1f1ed","\uD83C\uDDF2\uD83C\uDDF7":"1f1f2-1f1f7","\uD83C\uDDF2\uD83C\uDDFA":"1f1f2-1f1fa","\uD83C\uDDF2\uD83C\uDDFD":"1f1f2-1f1fd","\uD83C\uDDEB\uD83C\uDDF2":"1f1eb-1f1f2","\uD83C\uDDF2\uD83C\uDDE9":"1f1f2-1f1e9","\uD83C\uDDF2\uD83C\uDDE8":"1f1f2-1f1e8","\uD83C\uDDF2\uD83C\uDDF3":"1f1f2-1f1f3","\uD83C\uDDF2\uD83C\uDDEA":"1f1f2-1f1ea","\uD83C\uDDF2\uD83C\uDDE6":"1f1f2-1f1e6","\uD83C\uDDF2\uD83C\uDDFF":"1f1f2-1f1ff","\uD83C\uDDF2\uD83C\uDDF2":"1f1f2-1f1f2","\uD83C\uDDF3\uD83C\uDDE6":"1f1f3-1f1e6","\uD83C\uDDF3\uD83C\uDDF7":"1f1f3-1f1f7","\uD83C\uDDF3\uD83C\uDDF5":"1f1f3-1f1f5","\uD83C\uDDF3\uD83C\uDDF1":"1f1f3-1f1f1","\uD83C\uDDF3\uD83C\uDDFF":"1f1f3-1f1ff","\uD83C\uDDF3\uD83C\uDDEE":"1f1f3-1f1ee","\uD83C\uDDF3\uD83C\uDDEA":"1f1f3-1f1ea","\uD83C\uDDF3\uD83C\uDDEC":"1f1f3-1f1ec","\uD83C\uDDF0\uD83C\uDDF5":"1f1f0-1f1f5","\uD83C\uDDF3\uD83C\uDDF4":"1f1f3-1f1f4","\uD83C\uDDF4\uD83C\uDDF2":"1f1f4-1f1f2","\uD83C\uDDF5\uD83C\uDDF0":"1f1f5-1f1f0","\uD83C\uDDF5\uD83C\uDDFC":"1f1f5-1f1fc","\uD83C\uDDF5\uD83C\uDDE6":"1f1f5-1f1e6","\uD83C\uDDF5\uD83C\uDDEC":"1f1f5-1f1ec","\uD83E\uDD1B\uD83C\uDFFE":"1f91b-1f3fe","\uD83C\uDDF5\uD83C\uDDFE":"1f1f5-1f1fe","\uD83C\uDDF5\uD83C\uDDEA":"1f1f5-1f1ea","\uD83C\uDDF5\uD83C\uDDED":"1f1f5-1f1ed","\uD83C\uDDF5\uD83C\uDDF1":"1f1f5-1f1f1","\uD83C\uDDF5\uD83C\uDDF9":"1f1f5-1f1f9","\uD83C\uDDF6\uD83C\uDDE6":"1f1f6-1f1e6","\uD83C\uDDF9\uD83C\uDDFC":"1f1f9-1f1fc","\uD83C\uDDE8\uD83C\uDDEC":"1f1e8-1f1ec","\uD83C\uDDF7\uD83C\uDDF4":"1f1f7-1f1f4","\uD83C\uDDF7\uD83C\uDDFC":"1f1f7-1f1fc","\uD83C\uDDF0\uD83C\uDDF3":"1f1f0-1f1f3","\uD83C\uDDF1\uD83C\uDDE8":"1f1f1-1f1e8","\uD83C\uDDFB\uD83C\uDDE8":"1f1fb-1f1e8","\uD83C\uDDFC\uD83C\uDDF8":"1f1fc-1f1f8","\uD83C\uDDF8\uD83C\uDDF2":"1f1f8-1f1f2","\uD83C\uDDF8\uD83C\uDDF9":"1f1f8-1f1f9","\uD83C\uDDF8\uD83C\uDDE6":"1f1f8-1f1e6","\uD83E\uDD1B\uD83C\uDFFF":"1f91b-1f3ff","\uD83C\uDDF8\uD83C\uDDF3":"1f1f8-1f1f3","\uD83C\uDDF7\uD83C\uDDF8":"1f1f7-1f1f8","\uD83C\uDDF8\uD83C\uDDE8":"1f1f8-1f1e8","\uD83C\uDDF8\uD83C\uDDF1":"1f1f8-1f1f1","\uD83C\uDDF8\uD83C\uDDEC":"1f1f8-1f1ec","\uD83C\uDDF8\uD83C\uDDF0":"1f1f8-1f1f0","\uD83C\uDDF8\uD83C\uDDEE":"1f1f8-1f1ee","\uD83C\uDDF8\uD83C\uDDE7":"1f1f8-1f1e7","\uD83C\uDDF8\uD83C\uDDF4":"1f1f8-1f1f4","\uD83C\uDDFF\uD83C\uDDE6":"1f1ff-1f1e6","\uD83C\uDDF1\uD83C\uDDF0":"1f1f1-1f1f0","\uD83C\uDDF8\uD83C\uDDE9":"1f1f8-1f1e9","\uD83C\uDDF8\uD83C\uDDF7":"1f1f8-1f1f7","\uD83C\uDDF8\uD83C\uDDFF":"1f1f8-1f1ff","\uD83C\uDDF8\uD83C\uDDEA":"1f1f8-1f1ea","\uD83C\uDDE8\uD83C\uDDED":"1f1e8-1f1ed","\uD83C\uDDF8\uD83C\uDDFE":"1f1f8-1f1fe","\uD83C\uDDF9\uD83C\uDDEF":"1f1f9-1f1ef","\uD83C\uDDF9\uD83C\uDDFF":"1f1f9-1f1ff","\uD83C\uDDF9\uD83C\uDDED":"1f1f9-1f1ed","\uD83C\uDDF9\uD83C\uDDEC":"1f1f9-1f1ec","\uD83C\uDDF9\uD83C\uDDF4":"1f1f9-1f1f4","\uD83C\uDDF9\uD83C\uDDF9":"1f1f9-1f1f9","\uD83C\uDDF9\uD83C\uDDF3":"1f1f9-1f1f3","\uD83C\uDDF9\uD83C\uDDF7":"1f1f9-1f1f7","\uD83C\uDDF9\uD83C\uDDF2":"1f1f9-1f1f2","\uD83C\uDDF9\uD83C\uDDFB":"1f1f9-1f1fb","\uD83C\uDDFA\uD83C\uDDEC":"1f1fa-1f1ec","\uD83C\uDDFA\uD83C\uDDE6":"1f1fa-1f1e6","\uD83C\uDDE6\uD83C\uDDEA":"1f1e6-1f1ea","\uD83C\uDDFA\uD83C\uDDFE":"1f1fa-1f1fe","\uD83C\uDDFA\uD83C\uDDFF":"1f1fa-1f1ff","\uD83C\uDDFB\uD83C\uDDFA":"1f1fb-1f1fa","\uD83C\uDDFB\uD83C\uDDE6":"1f1fb-1f1e6","\uD83C\uDDFB\uD83C\uDDEA":"1f1fb-1f1ea","\uD83C\uDDFB\uD83C\uDDF3":"1f1fb-1f1f3","\uD83C\uDDEA\uD83C\uDDED":"1f1ea-1f1ed","\uD83E\uDD1C\uD83C\uDFFB":"1f91c-1f3fb","\uD83C\uDDFE\uD83C\uDDEA":"1f1fe-1f1ea","\uD83C\uDDFF\uD83C\uDDF2":"1f1ff-1f1f2","\uD83C\uDDFF\uD83C\uDDFC":"1f1ff-1f1fc","\uD83C\uDDF5\uD83C\uDDF7":"1f1f5-1f1f7","\uD83C\uDDF0\uD83C\uDDFE":"1f1f0-1f1fe","\uD83C\uDDE7\uD83C\uDDF2":"1f1e7-1f1f2","\uD83C\uDDF5\uD83C\uDDEB":"1f1f5-1f1eb","\uD83C\uDDF5\uD83C\uDDF8":"1f1f5-1f1f8","\uD83C\uDDF3\uD83C\uDDE8":"1f1f3-1f1e8","\uD83E\uDD1C\uD83C\uDFFC":"1f91c-1f3fc","\uD83C\uDDF8\uD83C\uDDED":"1f1f8-1f1ed","\uD83C\uDDE6\uD83C\uDDFC":"1f1e6-1f1fc","\uD83C\uDDFB\uD83C\uDDEE":"1f1fb-1f1ee","\uD83C\uDDED\uD83C\uDDF0":"1f1ed-1f1f0","\uD83C\uDDE6\uD83C\uDDE8":"1f1e6-1f1e8","\uD83C\uDDF2\uD83C\uDDF8":"1f1f2-1f1f8","\uD83C\uDDEC\uD83C\uDDFA":"1f1ec-1f1fa","\uD83C\uDDEC\uD83C\uDDF1":"1f1ec-1f1f1","\uD83C\uDDF3\uD83C\uDDFA":"1f1f3-1f1fa","\uD83C\uDDFC\uD83C\uDDEB":"1f1fc-1f1eb","\uD83C\uDDF2\uD83C\uDDF4":"1f1f2-1f1f4","\uD83E\uDD1C\uD83C\uDFFD":"1f91c-1f3fd","\uD83C\uDDEB\uD83C\uDDF4":"1f1eb-1f1f4","\uD83C\uDDEB\uD83C\uDDF0":"1f1eb-1f1f0","\uD83C\uDDEF\uD83C\uDDEA":"1f1ef-1f1ea","\uD83C\uDDE6\uD83C\uDDEE":"1f1e6-1f1ee","\uD83C\uDDEC\uD83C\uDDEE":"1f1ec-1f1ee","\uD83E\uDD1C\uD83C\uDFFE":"1f91c-1f3fe","\uD83E\uDD1C\uD83C\uDFFF":"1f91c-1f3ff","\uD83E\uDD1A\uD83C\uDFFB":"1f91a-1f3fb","\uD83E\uDD1A\uD83C\uDFFC":"1f91a-1f3fc","\uD83E\uDD1A\uD83C\uDFFD":"1f91a-1f3fd","\uD83E\uDD1A\uD83C\uDFFE":"1f91a-1f3fe","\uD83D\uDC76\uD83C\uDFFB":"1f476-1f3fb","\uD83D\uDC76\uD83C\uDFFC":"1f476-1f3fc","\uD83D\uDC76\uD83C\uDFFD":"1f476-1f3fd","\uD83D\uDC76\uD83C\uDFFE":"1f476-1f3fe","\uD83D\uDC76\uD83C\uDFFF":"1f476-1f3ff","\uD83D\uDC66\uD83C\uDFFB":"1f466-1f3fb","\uD83D\uDC66\uD83C\uDFFC":"1f466-1f3fc","\uD83D\uDC66\uD83C\uDFFD":"1f466-1f3fd","\uD83D\uDC66\uD83C\uDFFE":"1f466-1f3fe","\uD83D\uDC66\uD83C\uDFFF":"1f466-1f3ff","\uD83D\uDC67\uD83C\uDFFB":"1f467-1f3fb","\uD83D\uDC67\uD83C\uDFFC":"1f467-1f3fc","\uD83D\uDC67\uD83C\uDFFD":"1f467-1f3fd","\uD83D\uDC67\uD83C\uDFFE":"1f467-1f3fe","\uD83D\uDC67\uD83C\uDFFF":"1f467-1f3ff","\uD83D\uDC68\uD83C\uDFFB":"1f468-1f3fb","\uD83D\uDC68\uD83C\uDFFC":"1f468-1f3fc","\uD83D\uDC68\uD83C\uDFFD":"1f468-1f3fd","\uD83D\uDC68\uD83C\uDFFE":"1f468-1f3fe","\uD83D\uDC68\uD83C\uDFFF":"1f468-1f3ff","\uD83D\uDC69\uD83C\uDFFB":"1f469-1f3fb","\uD83D\uDC69\uD83C\uDFFC":"1f469-1f3fc","\uD83D\uDC69\uD83C\uDFFD":"1f469-1f3fd","\uD83D\uDC69\uD83C\uDFFE":"1f469-1f3fe","\uD83D\uDC69\uD83C\uDFFF":"1f469-1f3ff","\uD83D\uDC70\uD83C\uDFFB":"1f470-1f3fb","\uD83D\uDC70\uD83C\uDFFC":"1f470-1f3fc","\uD83E\uDD1A\uD83C\uDFFF":"1f91a-1f3ff","\uD83D\uDC70\uD83C\uDFFD":"1f470-1f3fd","\uD83D\uDC70\uD83C\uDFFE":"1f470-1f3fe","\uD83D\uDC70\uD83C\uDFFF":"1f470-1f3ff","\uD83D\uDC71\uD83C\uDFFB":"1f471-1f3fb","\uD83D\uDC71\uD83C\uDFFC":"1f471-1f3fc","\uD83D\uDC71\uD83C\uDFFD":"1f471-1f3fd","\uD83D\uDC71\uD83C\uDFFE":"1f471-1f3fe","\uD83D\uDC71\uD83C\uDFFF":"1f471-1f3ff","\uD83D\uDC72\uD83C\uDFFB":"1f472-1f3fb","\uD83D\uDC72\uD83C\uDFFC":"1f472-1f3fc","\uD83D\uDC72\uD83C\uDFFD":"1f472-1f3fd","\uD83D\uDC72\uD83C\uDFFE":"1f472-1f3fe","\uD83D\uDC72\uD83C\uDFFF":"1f472-1f3ff","\uD83D\uDC73\uD83C\uDFFB":"1f473-1f3fb","\uD83D\uDC73\uD83C\uDFFC":"1f473-1f3fc","\uD83D\uDC73\uD83C\uDFFD":"1f473-1f3fd","\uD83D\uDC73\uD83C\uDFFE":"1f473-1f3fe","\uD83D\uDC73\uD83C\uDFFF":"1f473-1f3ff","\uD83D\uDC74\uD83C\uDFFB":"1f474-1f3fb","\uD83D\uDC74\uD83C\uDFFC":"1f474-1f3fc","\uD83D\uDC74\uD83C\uDFFD":"1f474-1f3fd","\uD83D\uDC74\uD83C\uDFFE":"1f474-1f3fe","\uD83D\uDC74\uD83C\uDFFF":"1f474-1f3ff","\uD83D\uDC75\uD83C\uDFFB":"1f475-1f3fb","\uD83D\uDC75\uD83C\uDFFC":"1f475-1f3fc","\uD83D\uDC75\uD83C\uDFFD":"1f475-1f3fd","\uD83D\uDC75\uD83C\uDFFE":"1f475-1f3fe","\uD83D\uDC75\uD83C\uDFFF":"1f475-1f3ff","\uD83D\uDC6E\uD83C\uDFFB":"1f46e-1f3fb","\uD83D\uDC6E\uD83C\uDFFC":"1f46e-1f3fc","\uD83D\uDC6E\uD83C\uDFFD":"1f46e-1f3fd","\uD83D\uDC6E\uD83C\uDFFE":"1f46e-1f3fe","\uD83D\uDC6E\uD83C\uDFFF":"1f46e-1f3ff","\uD83D\uDC77\uD83C\uDFFB":"1f477-1f3fb","\uD83D\uDC77\uD83C\uDFFC":"1f477-1f3fc","\uD83D\uDC77\uD83C\uDFFD":"1f477-1f3fd","\uD83D\uDC77\uD83C\uDFFE":"1f477-1f3fe","\uD83D\uDC77\uD83C\uDFFF":"1f477-1f3ff","\uD83D\uDC78\uD83C\uDFFB":"1f478-1f3fb","\uD83D\uDC78\uD83C\uDFFC":"1f478-1f3fc","\uD83D\uDC78\uD83C\uDFFD":"1f478-1f3fd","\uD83D\uDC78\uD83C\uDFFE":"1f478-1f3fe","\uD83E\uDD38\uD83C\uDFFB":"1f938-1f3fb","\uD83D\uDC78\uD83C\uDFFF":"1f478-1f3ff","\uD83D\uDC82\uD83C\uDFFB":"1f482-1f3fb","\uD83D\uDC82\uD83C\uDFFC":"1f482-1f3fc","\uD83E\uDD38\uD83C\uDFFC":"1f938-1f3fc","\uD83D\uDC82\uD83C\uDFFD":"1f482-1f3fd","\uD83D\uDC82\uD83C\uDFFE":"1f482-1f3fe","\uD83D\uDC82\uD83C\uDFFF":"1f482-1f3ff","\uD83E\uDD38\uD83C\uDFFD":"1f938-1f3fd","\uD83D\uDC7C\uD83C\uDFFB":"1f47c-1f3fb","\uD83D\uDC7C\uD83C\uDFFC":"1f47c-1f3fc","\uD83D\uDC7C\uD83C\uDFFD":"1f47c-1f3fd","\uD83D\uDC7C\uD83C\uDFFE":"1f47c-1f3fe","\uD83D\uDC7C\uD83C\uDFFF":"1f47c-1f3ff","\uD83D\uDE47\uD83C\uDFFB":"1f647-1f3fb","\uD83D\uDE47\uD83C\uDFFC":"1f647-1f3fc","\uD83D\uDE47\uD83C\uDFFD":"1f647-1f3fd","\uD83D\uDE47\uD83C\uDFFE":"1f647-1f3fe","\uD83D\uDE47\uD83C\uDFFF":"1f647-1f3ff","\uD83D\uDC81\uD83C\uDFFB":"1f481-1f3fb","\uD83D\uDC81\uD83C\uDFFC":"1f481-1f3fc","\uD83D\uDC81\uD83C\uDFFD":"1f481-1f3fd","\uD83E\uDD38\uD83C\uDFFE":"1f938-1f3fe","\uD83D\uDC81\uD83C\uDFFE":"1f481-1f3fe","\uD83D\uDC81\uD83C\uDFFF":"1f481-1f3ff","\uD83D\uDE45\uD83C\uDFFB":"1f645-1f3fb","\uD83E\uDD38\uD83C\uDFFF":"1f938-1f3ff","\uD83D\uDE45\uD83C\uDFFC":"1f645-1f3fc","\uD83D\uDE45\uD83C\uDFFD":"1f645-1f3fd","\uD83D\uDE45\uD83C\uDFFE":"1f645-1f3fe","\uD83D\uDE45\uD83C\uDFFF":"1f645-1f3ff","\uD83D\uDE46\uD83C\uDFFB":"1f646-1f3fb","\uD83D\uDE46\uD83C\uDFFC":"1f646-1f3fc","\uD83D\uDE46\uD83C\uDFFD":"1f646-1f3fd","\uD83D\uDE46\uD83C\uDFFE":"1f646-1f3fe","\uD83D\uDE46\uD83C\uDFFF":"1f646-1f3ff","\uD83D\uDE4B\uD83C\uDFFB":"1f64b-1f3fb","\uD83D\uDE4B\uD83C\uDFFC":"1f64b-1f3fc","\uD83D\uDE4B\uD83C\uDFFD":"1f64b-1f3fd","\uD83D\uDE4B\uD83C\uDFFE":"1f64b-1f3fe","\uD83D\uDE4B\uD83C\uDFFF":"1f64b-1f3ff","\uD83D\uDE4E\uD83C\uDFFB":"1f64e-1f3fb","\uD83D\uDE4E\uD83C\uDFFC":"1f64e-1f3fc","\uD83D\uDE4E\uD83C\uDFFD":"1f64e-1f3fd","\uD83D\uDE4E\uD83C\uDFFE":"1f64e-1f3fe","\uD83D\uDE4E\uD83C\uDFFF":"1f64e-1f3ff","\uD83D\uDE4D\uD83C\uDFFB":"1f64d-1f3fb","\uD83D\uDE4D\uD83C\uDFFC":"1f64d-1f3fc","\uD83D\uDE4D\uD83C\uDFFD":"1f64d-1f3fd","\uD83D\uDE4D\uD83C\uDFFE":"1f64d-1f3fe","\uD83D\uDE4D\uD83C\uDFFF":"1f64d-1f3ff","\uD83D\uDC86\uD83C\uDFFB":"1f486-1f3fb","\uD83D\uDC86\uD83C\uDFFC":"1f486-1f3fc","\uD83D\uDC86\uD83C\uDFFD":"1f486-1f3fd","\uD83D\uDC86\uD83C\uDFFE":"1f486-1f3fe","\uD83D\uDC86\uD83C\uDFFF":"1f486-1f3ff","\uD83D\uDC87\uD83C\uDFFB":"1f487-1f3fb","\uD83D\uDC87\uD83C\uDFFC":"1f487-1f3fc","\uD83D\uDC87\uD83C\uDFFD":"1f487-1f3fd","\uD83D\uDC87\uD83C\uDFFE":"1f487-1f3fe","\uD83D\uDC87\uD83C\uDFFF":"1f487-1f3ff","\uD83D\uDE4C\uD83C\uDFFB":"1f64c-1f3fb","\uD83D\uDE4C\uD83C\uDFFC":"1f64c-1f3fc","\uD83D\uDE4C\uD83C\uDFFD":"1f64c-1f3fd","\uD83D\uDE4C\uD83C\uDFFE":"1f64c-1f3fe","\uD83D\uDE4C\uD83C\uDFFF":"1f64c-1f3ff","\uD83D\uDC4F\uD83C\uDFFB":"1f44f-1f3fb","\uD83D\uDC4F\uD83C\uDFFC":"1f44f-1f3fc","\uD83D\uDC4F\uD83C\uDFFD":"1f44f-1f3fd","\uD83E\uDD3D\uD83C\uDFFB":"1f93d-1f3fb","\uD83D\uDC4F\uD83C\uDFFE":"1f44f-1f3fe","\uD83D\uDC4F\uD83C\uDFFF":"1f44f-1f3ff","\uD83E\uDD3D\uD83C\uDFFC":"1f93d-1f3fc","\uD83D\uDC42\uD83C\uDFFB":"1f442-1f3fb","\uD83D\uDC42\uD83C\uDFFC":"1f442-1f3fc","\uD83D\uDC42\uD83C\uDFFD":"1f442-1f3fd","\uD83D\uDC42\uD83C\uDFFE":"1f442-1f3fe","\uD83D\uDC42\uD83C\uDFFF":"1f442-1f3ff","\uD83D\uDC43\uD83C\uDFFB":"1f443-1f3fb","\uD83D\uDC43\uD83C\uDFFC":"1f443-1f3fc","\uD83D\uDC43\uD83C\uDFFD":"1f443-1f3fd","\uD83D\uDC43\uD83C\uDFFE":"1f443-1f3fe","\uD83D\uDC43\uD83C\uDFFF":"1f443-1f3ff","\uD83D\uDC85\uD83C\uDFFB":"1f485-1f3fb","\uD83D\uDC85\uD83C\uDFFC":"1f485-1f3fc","\uD83D\uDC85\uD83C\uDFFD":"1f485-1f3fd","\uD83D\uDC85\uD83C\uDFFE":"1f485-1f3fe","\uD83D\uDC85\uD83C\uDFFF":"1f485-1f3ff","\uD83D\uDC4B\uD83C\uDFFB":"1f44b-1f3fb","\uD83D\uDC4B\uD83C\uDFFC":"1f44b-1f3fc","\uD83D\uDC4B\uD83C\uDFFD":"1f44b-1f3fd","\uD83D\uDC4B\uD83C\uDFFE":"1f44b-1f3fe","\uD83D\uDC4B\uD83C\uDFFF":"1f44b-1f3ff","\uD83D\uDC4D\uD83C\uDFFB":"1f44d-1f3fb","\uD83D\uDC4D\uD83C\uDFFC":"1f44d-1f3fc","\uD83D\uDC4D\uD83C\uDFFD":"1f44d-1f3fd","\uD83D\uDC4D\uD83C\uDFFE":"1f44d-1f3fe","\uD83D\uDC4D\uD83C\uDFFF":"1f44d-1f3ff","\uD83D\uDC4E\uD83C\uDFFB":"1f44e-1f3fb","\uD83D\uDC4E\uD83C\uDFFC":"1f44e-1f3fc","\uD83D\uDC4E\uD83C\uDFFD":"1f44e-1f3fd","\uD83D\uDC4E\uD83C\uDFFE":"1f44e-1f3fe","\uD83D\uDC4E\uD83C\uDFFF":"1f44e-1f3ff","\uD83D\uDC46\uD83C\uDFFB":"1f446-1f3fb","\uD83D\uDC46\uD83C\uDFFC":"1f446-1f3fc","\uD83D\uDC46\uD83C\uDFFD":"1f446-1f3fd","\uD83D\uDC46\uD83C\uDFFE":"1f446-1f3fe","\uD83D\uDC46\uD83C\uDFFF":"1f446-1f3ff","\uD83D\uDC47\uD83C\uDFFB":"1f447-1f3fb","\uD83D\uDC47\uD83C\uDFFC":"1f447-1f3fc","\uD83D\uDC47\uD83C\uDFFD":"1f447-1f3fd","\uD83D\uDC47\uD83C\uDFFE":"1f447-1f3fe","\uD83D\uDC47\uD83C\uDFFF":"1f447-1f3ff","\uD83D\uDC48\uD83C\uDFFB":"1f448-1f3fb","\uD83D\uDC48\uD83C\uDFFC":"1f448-1f3fc","\uD83D\uDC48\uD83C\uDFFD":"1f448-1f3fd","\uD83D\uDC48\uD83C\uDFFE":"1f448-1f3fe","\uD83D\uDC48\uD83C\uDFFF":"1f448-1f3ff","\uD83D\uDC49\uD83C\uDFFB":"1f449-1f3fb","\uD83D\uDC49\uD83C\uDFFC":"1f449-1f3fc","\uD83D\uDC49\uD83C\uDFFD":"1f449-1f3fd","\uD83D\uDC49\uD83C\uDFFE":"1f449-1f3fe","\uD83D\uDC49\uD83C\uDFFF":"1f449-1f3ff","\uD83D\uDC4C\uD83C\uDFFB":"1f44c-1f3fb","\uD83D\uDC4C\uD83C\uDFFC":"1f44c-1f3fc","\uD83E\uDD3D\uD83C\uDFFD":"1f93d-1f3fd","\uD83D\uDC4C\uD83C\uDFFD":"1f44c-1f3fd","\uD83D\uDC4C\uD83C\uDFFE":"1f44c-1f3fe","\uD83E\uDD3D\uD83C\uDFFE":"1f93d-1f3fe","\uD83D\uDC4C\uD83C\uDFFF":"1f44c-1f3ff","\uD83D\uDC4A\uD83C\uDFFB":"1f44a-1f3fb","\uD83D\uDC4A\uD83C\uDFFC":"1f44a-1f3fc","\uD83D\uDC4A\uD83C\uDFFD":"1f44a-1f3fd","\uD83D\uDC4A\uD83C\uDFFE":"1f44a-1f3fe","\uD83D\uDC4A\uD83C\uDFFF":"1f44a-1f3ff","\uD83D\uDCAA\uD83C\uDFFB":"1f4aa-1f3fb","\uD83D\uDCAA\uD83C\uDFFC":"1f4aa-1f3fc","\uD83D\uDCAA\uD83C\uDFFD":"1f4aa-1f3fd","\uD83D\uDCAA\uD83C\uDFFE":"1f4aa-1f3fe","\uD83D\uDCAA\uD83C\uDFFF":"1f4aa-1f3ff","\uD83D\uDC50\uD83C\uDFFB":"1f450-1f3fb","\uD83D\uDC50\uD83C\uDFFC":"1f450-1f3fc","\uD83D\uDC50\uD83C\uDFFD":"1f450-1f3fd","\uD83D\uDC50\uD83C\uDFFE":"1f450-1f3fe","\uD83D\uDC50\uD83C\uDFFF":"1f450-1f3ff","\uD83D\uDE4F\uD83C\uDFFB":"1f64f-1f3fb","\uD83E\uDD3D\uD83C\uDFFF":"1f93d-1f3ff","\uD83D\uDE4F\uD83C\uDFFC":"1f64f-1f3fc","\uD83D\uDE4F\uD83C\uDFFD":"1f64f-1f3fd","\uD83E\uDD3E\uD83C\uDFFB":"1f93e-1f3fb","\uD83D\uDE4F\uD83C\uDFFE":"1f64f-1f3fe","\uD83D\uDE4F\uD83C\uDFFF":"1f64f-1f3ff","\uD83E\uDD3E\uD83C\uDFFC":"1f93e-1f3fc","\uD83C\uDFC3\uD83C\uDFFB":"1f3c3-1f3fb","\uD83C\uDFC3\uD83C\uDFFC":"1f3c3-1f3fc","\uD83C\uDFC3\uD83C\uDFFD":"1f3c3-1f3fd","\uD83C\uDFC3\uD83C\uDFFE":"1f3c3-1f3fe","\uD83E\uDD3E\uD83C\uDFFD":"1f93e-1f3fd","\uD83C\uDFC3\uD83C\uDFFF":"1f3c3-1f3ff","\uD83D\uDEB6\uD83C\uDFFB":"1f6b6-1f3fb","\uD83D\uDEB6\uD83C\uDFFC":"1f6b6-1f3fc","\uD83D\uDEB6\uD83C\uDFFD":"1f6b6-1f3fd","\uD83D\uDEB6\uD83C\uDFFE":"1f6b6-1f3fe","\uD83D\uDEB6\uD83C\uDFFF":"1f6b6-1f3ff","\uD83D\uDC83\uD83C\uDFFB":"1f483-1f3fb","\uD83E\uDD3E\uD83C\uDFFE":"1f93e-1f3fe","\uD83D\uDC83\uD83C\uDFFC":"1f483-1f3fc","\uD83D\uDC83\uD83C\uDFFD":"1f483-1f3fd","\uD83E\uDD3E\uD83C\uDFFF":"1f93e-1f3ff","\uD83D\uDC83\uD83C\uDFFE":"1f483-1f3fe","\uD83D\uDC83\uD83C\uDFFF":"1f483-1f3ff","\uD83E\uDD39\uD83C\uDFFB":"1f939-1f3fb","\uD83D\uDEA3\uD83C\uDFFB":"1f6a3-1f3fb","\uD83D\uDEA3\uD83C\uDFFC":"1f6a3-1f3fc","\uD83D\uDEA3\uD83C\uDFFD":"1f6a3-1f3fd","\uD83D\uDEA3\uD83C\uDFFE":"1f6a3-1f3fe","\uD83D\uDEA3\uD83C\uDFFF":"1f6a3-1f3ff","\uD83C\uDFCA\uD83C\uDFFB":"1f3ca-1f3fb","\uD83C\uDFCA\uD83C\uDFFC":"1f3ca-1f3fc","\uD83E\uDD39\uD83C\uDFFC":"1f939-1f3fc","\uD83C\uDFCA\uD83C\uDFFD":"1f3ca-1f3fd","\uD83C\uDFCA\uD83C\uDFFE":"1f3ca-1f3fe","\uD83C\uDFCA\uD83C\uDFFF":"1f3ca-1f3ff","\uD83E\uDD39\uD83C\uDFFD":"1f939-1f3fd","\uD83C\uDFC4\uD83C\uDFFB":"1f3c4-1f3fb","\uD83C\uDFC4\uD83C\uDFFC":"1f3c4-1f3fc","\uD83C\uDFC4\uD83C\uDFFD":"1f3c4-1f3fd","\uD83C\uDFC4\uD83C\uDFFE":"1f3c4-1f3fe","\uD83C\uDFC4\uD83C\uDFFF":"1f3c4-1f3ff","\uD83D\uDEC0\uD83C\uDFFB":"1f6c0-1f3fb","\uD83D\uDEC0\uD83C\uDFFC":"1f6c0-1f3fc","\uD83E\uDD39\uD83C\uDFFE":"1f939-1f3fe","\uD83D\uDEC0\uD83C\uDFFD":"1f6c0-1f3fd","\uD83D\uDEC0\uD83C\uDFFE":"1f6c0-1f3fe","\uD83D\uDEC0\uD83C\uDFFF":"1f6c0-1f3ff","\uD83E\uDD39\uD83C\uDFFF":"1f939-1f3ff","\uD83D\uDEB4\uD83C\uDFFB":"1f6b4-1f3fb","\uD83D\uDEB4\uD83C\uDFFC":"1f6b4-1f3fc","\uD83D\uDEB4\uD83C\uDFFD":"1f6b4-1f3fd","\uD83D\uDEB4\uD83C\uDFFE":"1f6b4-1f3fe","\uD83D\uDEB4\uD83C\uDFFF":"1f6b4-1f3ff","\uD83D\uDEB5\uD83C\uDFFB":"1f6b5-1f3fb","\uD83D\uDEB5\uD83C\uDFFC":"1f6b5-1f3fc","\uD83D\uDEB5\uD83C\uDFFD":"1f6b5-1f3fd","\uD83D\uDEB5\uD83C\uDFFE":"1f6b5-1f3fe","\uD83D\uDEB5\uD83C\uDFFF":"1f6b5-1f3ff","\uD83C\uDFC7\uD83C\uDFFB":"1f3c7-1f3fb","\uD83C\uDFC7\uD83C\uDFFC":"1f3c7-1f3fc","\uD83C\uDFC7\uD83C\uDFFD":"1f3c7-1f3fd","\uD83C\uDFC7\uD83C\uDFFE":"1f3c7-1f3fe","\uD83C\uDFC7\uD83C\uDFFF":"1f3c7-1f3ff","\uD83D\uDD90\uD83C\uDFFB":"1f590-1f3fb","\uD83D\uDD90\uD83C\uDFFC":"1f590-1f3fc","\uD83D\uDD90\uD83C\uDFFD":"1f590-1f3fd","\uD83D\uDD90\uD83C\uDFFE":"1f590-1f3fe","\uD83D\uDD90\uD83C\uDFFF":"1f590-1f3ff","\uD83D\uDD95\uD83C\uDFFB":"1f595-1f3fb","\uD83D\uDD95\uD83C\uDFFC":"1f595-1f3fc","\uD83D\uDD95\uD83C\uDFFD":"1f595-1f3fd","\uD83D\uDD95\uD83C\uDFFE":"1f595-1f3fe","\uD83D\uDD95\uD83C\uDFFF":"1f595-1f3ff","\uD83D\uDD96\uD83C\uDFFB":"1f596-1f3fb","\uD83D\uDD96\uD83C\uDFFC":"1f596-1f3fc","\uD83D\uDD96\uD83C\uDFFD":"1f596-1f3fd","\uD83D\uDD96\uD83C\uDFFE":"1f596-1f3fe","\uD83D\uDD96\uD83C\uDFFF":"1f596-1f3ff","\uD83C\uDF85\uD83C\uDFFB":"1f385-1f3fb","\uD83C\uDF85\uD83C\uDFFC":"1f385-1f3fc","\uD83C\uDF85\uD83C\uDFFD":"1f385-1f3fd","\uD83C\uDF85\uD83C\uDFFE":"1f385-1f3fe","\uD83C\uDF85\uD83C\uDFFF":"1f385-1f3ff","\uD83E\uDD18\uD83C\uDFFB":"1f918-1f3fb","\uD83E\uDD18\uD83C\uDFFC":"1f918-1f3fc","\uD83E\uDD18\uD83C\uDFFD":"1f918-1f3fd","\uD83E\uDD18\uD83C\uDFFE":"1f918-1f3fe","\uD83E\uDD18\uD83C\uDFFF":"1f918-1f3ff","\uD83C\uDFCB\uD83C\uDFFB":"1f3cb-1f3fb","\uD83C\uDFCB\uD83C\uDFFC":"1f3cb-1f3fc","\uD83C\uDFCB\uD83C\uDFFD":"1f3cb-1f3fd","\uD83C\uDFCB\uD83C\uDFFE":"1f3cb-1f3fe","\uD83C\uDFCB\uD83C\uDFFF":"1f3cb-1f3ff","\uD83C\uDDE6\uD83C\uDDFD":"1f1e6-1f1fd","\uD83C\uDDF9\uD83C\uDDE6":"1f1f9-1f1e6","\uD83C\uDDEE\uD83C\uDDF4":"1f1ee-1f1f4","\uD83C\uDDE7\uD83C\uDDF6":"1f1e7-1f1f6","\uD83C\uDDE8\uD83C\uDDFD":"1f1e8-1f1fd","\uD83C\uDDE8\uD83C\uDDE8":"1f1e8-1f1e8","\uD83C\uDDEC\uD83C\uDDEC":"1f1ec-1f1ec","\uD83C\uDDEE\uD83C\uDDF2":"1f1ee-1f1f2","\uD83C\uDDFE\uD83C\uDDF9":"1f1fe-1f1f9","\uD83C\uDDF3\uD83C\uDDEB":"1f1f3-1f1eb","\uD83C\uDDF5\uD83C\uDDF3":"1f1f5-1f1f3","\uD83C\uDDE7\uD83C\uDDF1":"1f1e7-1f1f1","\uD83C\uDDF5\uD83C\uDDF2":"1f1f5-1f1f2","\uD83C\uDDEC\uD83C\uDDF8":"1f1ec-1f1f8","\uD83C\uDDF9\uD83C\uDDF0":"1f1f9-1f1f0","\uD83C\uDDE7\uD83C\uDDFB":"1f1e7-1f1fb","\uD83C\uDDED\uD83C\uDDF2":"1f1ed-1f1f2","\uD83C\uDDF8\uD83C\uDDEF":"1f1f8-1f1ef","\uD83C\uDDFA\uD83C\uDDF2":"1f1fa-1f1f2","\uD83C\uDDEE\uD83C\uDDE8":"1f1ee-1f1e8","\uD83C\uDDEA\uD83C\uDDE6":"1f1ea-1f1e6","\uD83C\uDDE8\uD83C\uDDF5":"1f1e8-1f1f5","\uD83C\uDDE9\uD83C\uDDEC":"1f1e9-1f1ec","\uD83C\uDDE6\uD83C\uDDF8":"1f1e6-1f1f8","\uD83C\uDDE6\uD83C\uDDF6":"1f1e6-1f1f6","\uD83C\uDDFB\uD83C\uDDEC":"1f1fb-1f1ec","\uD83C\uDDE8\uD83C\uDDF0":"1f1e8-1f1f0","\uD83C\uDDE8\uD83C\uDDFC":"1f1e8-1f1fc","\uD83C\uDDEA\uD83C\uDDFA":"1f1ea-1f1fa","\uD83C\uDDEC\uD83C\uDDEB":"1f1ec-1f1eb","\uD83C\uDDF9\uD83C\uDDEB":"1f1f9-1f1eb","\uD83C\uDDEC\uD83C\uDDF5":"1f1ec-1f1f5","\uD83C\uDDF2\uD83C\uDDF6":"1f1f2-1f1f6","\uD83C\uDDF2\uD83C\uDDF5":"1f1f2-1f1f5","\uD83C\uDDF7\uD83C\uDDEA":"1f1f7-1f1ea","\uD83C\uDDF8\uD83C\uDDFD":"1f1f8-1f1fd","\uD83C\uDDF8\uD83C\uDDF8":"1f1f8-1f1f8","\uD83C\uDDF9\uD83C\uDDE8":"1f1f9-1f1e8","\uD83C\uDDF2\uD83C\uDDEB":"1f1f2-1f1eb","\uD83D\uDD75\uD83C\uDFFB":"1f575-1f3fb","\uD83D\uDD75\uD83C\uDFFC":"1f575-1f3fc","\uD83D\uDD75\uD83C\uDFFD":"1f575-1f3fd","\uD83D\uDD75\uD83C\uDFFE":"1f575-1f3fe","\uD83D\uDD75\uD83C\uDFFF":"1f575-1f3ff","\uD83C\uDFC2\uD83C\uDFFB":"1f3c2-1f3fb","\uD83D\uDC68\uD83D\uDCBB":"1f468-1f4bb","\uD83D\uDC69\uD83D\uDCBB":"1f469-1f4bb","\uD83D\uDC68\uD83C\uDFEB":"1f468-1f3eb","\uD83D\uDC69\uD83C\uDFEB":"1f469-1f3eb","\uD83D\uDC68\uD83C\uDF93":"1f468-1f393","\uD83D\uDC69\uD83C\uDF93":"1f469-1f393","\uD83D\uDC68\uD83C\uDFA4":"1f468-1f3a4","\uD83D\uDC69\uD83C\uDFA4":"1f469-1f3a4","\uD83D\uDC68\uD83D\uDD2C":"1f468-1f52c","\uD83D\uDC69\uD83D\uDD2C":"1f469-1f52c","\uD83D\uDC68\uD83D\uDCBC":"1f468-1f4bc","\uD83D\uDC69\uD83D\uDCBC":"1f469-1f4bc","\uD83D\uDC68\uD83D\uDD27":"1f468-1f527","\uD83D\uDC69\uD83D\uDD27":"1f469-1f527","\uD83D\uDC68\uD83C\uDFED":"1f468-1f3ed","\uD83D\uDC69\uD83C\uDFED":"1f469-1f3ed","\uD83D\uDC68\uD83C\uDF73":"1f468-1f373","\uD83D\uDC69\uD83C\uDF73":"1f469-1f373","\uD83D\uDC68\uD83C\uDF3E":"1f468-1f33e","\uD83D\uDC69\uD83C\uDF3E":"1f469-1f33e","\uD83D\uDD74\uD83C\uDFFB":"1f574-1f3fb","\uD83D\uDD74\uD83C\uDFFC":"1f574-1f3fc","\uD83D\uDD74\uD83C\uDFFD":"1f574-1f3fd","\uD83D\uDD74\uD83C\uDFFE":"1f574-1f3fe","\uD83D\uDD74\uD83C\uDFFF":"1f574-1f3ff","\uD83D\uDECC\uD83C\uDFFB":"1f6cc-1f3fb","\uD83D\uDECC\uD83C\uDFFC":"1f6cc-1f3fc","\uD83D\uDECC\uD83C\uDFFD":"1f6cc-1f3fd","\uD83D\uDECC\uD83C\uDFFE":"1f6cc-1f3fe","\uD83D\uDECC\uD83C\uDFFF":"1f6cc-1f3ff","\uD83D\uDC68\uD83D\uDC66":"1f468-1f466","\uD83D\uDC68\uD83D\uDC67":"1f468-1f467","\uD83D\uDC69\uD83D\uDC66":"1f469-1f466","\uD83D\uDC69\uD83D\uDC67":"1f469-1f467","\uD83D\uDC68\uD83C\uDFA8":"1f468-1f3a8","\uD83D\uDC69\uD83C\uDFA8":"1f469-1f3a8","\uD83D\uDC68\uD83D\uDE80":"1f468-1f680","\uD83D\uDC69\uD83D\uDE80":"1f469-1f680","\uD83D\uDC68\uD83D\uDE92":"1f468-1f692","\uD83D\uDC69\uD83D\uDE92":"1f469-1f692","\uD83C\uDDFA\uD83C\uDDF3":"1f1fa-1f1f3","\uD83C\uDFC2\uD83C\uDFFC":"1f3c2-1f3fc","\uD83C\uDFC2\uD83C\uDFFD":"1f3c2-1f3fd","\uD83C\uDFC2\uD83C\uDFFE":"1f3c2-1f3fe","\uD83C\uDFC2\uD83C\uDFFF":"1f3c2-1f3ff","\uD83C\uDFCC\uD83C\uDFFB":"1f3cc-1f3fb","\uD83C\uDFCC\uD83C\uDFFC":"1f3cc-1f3fc","\uD83C\uDFCC\uD83C\uDFFD":"1f3cc-1f3fd","\uD83C\uDFCC\uD83C\uDFFE":"1f3cc-1f3fe","\uD83C\uDFCC\uD83C\uDFFF":"1f3cc-1f3ff","\uD83E\uDD1F\uD83C\uDFFB":"1f91f-1f3fb","\uD83E\uDD1F\uD83C\uDFFC":"1f91f-1f3fc","\uD83E\uDD1F\uD83C\uDFFD":"1f91f-1f3fd","\uD83E\uDD1F\uD83C\uDFFE":"1f91f-1f3fe","\uD83E\uDD1F\uD83C\uDFFF":"1f91f-1f3ff","\uD83E\uDD31\uD83C\uDFFB":"1f931-1f3fb","\uD83E\uDD31\uD83C\uDFFC":"1f931-1f3fc","\uD83E\uDD31\uD83C\uDFFD":"1f931-1f3fd","\uD83E\uDD31\uD83C\uDFFE":"1f931-1f3fe","\uD83E\uDD31\uD83C\uDFFF":"1f931-1f3ff","\uD83E\uDD32\uD83C\uDFFB":"1f932-1f3fb","\uD83E\uDD32\uD83C\uDFFC":"1f932-1f3fc","\uD83E\uDD32\uD83C\uDFFD":"1f932-1f3fd","\uD83E\uDD32\uD83C\uDFFE":"1f932-1f3fe","\uD83E\uDD32\uD83C\uDFFF":"1f932-1f3ff","\uD83E\uDDD1\uD83C\uDFFB":"1f9d1-1f3fb","\uD83E\uDDD1\uD83C\uDFFC":"1f9d1-1f3fc","\uD83E\uDDD1\uD83C\uDFFD":"1f9d1-1f3fd","\uD83E\uDDD1\uD83C\uDFFE":"1f9d1-1f3fe","\uD83E\uDDD1\uD83C\uDFFF":"1f9d1-1f3ff","\uD83E\uDDD2\uD83C\uDFFB":"1f9d2-1f3fb","\uD83E\uDDD2\uD83C\uDFFC":"1f9d2-1f3fc","\uD83E\uDDD2\uD83C\uDFFD":"1f9d2-1f3fd","\uD83E\uDDD2\uD83C\uDFFE":"1f9d2-1f3fe","\uD83E\uDDD2\uD83C\uDFFF":"1f9d2-1f3ff","\uD83E\uDDD3\uD83C\uDFFB":"1f9d3-1f3fb","\uD83E\uDDD3\uD83C\uDFFC":"1f9d3-1f3fc","\uD83E\uDDD3\uD83C\uDFFD":"1f9d3-1f3fd","\uD83E\uDDD3\uD83C\uDFFE":"1f9d3-1f3fe","\uD83E\uDDD3\uD83C\uDFFF":"1f9d3-1f3ff","\uD83E\uDDD4\uD83C\uDFFB":"1f9d4-1f3fb","\uD83E\uDDD4\uD83C\uDFFC":"1f9d4-1f3fc","\uD83E\uDDD4\uD83C\uDFFD":"1f9d4-1f3fd","\uD83E\uDDD4\uD83C\uDFFE":"1f9d4-1f3fe","\uD83E\uDDD4\uD83C\uDFFF":"1f9d4-1f3ff","\uD83E\uDDD5\uD83C\uDFFB":"1f9d5-1f3fb","\uD83E\uDDD5\uD83C\uDFFC":"1f9d5-1f3fc","\uD83E\uDDD5\uD83C\uDFFD":"1f9d5-1f3fd","\uD83E\uDDD5\uD83C\uDFFE":"1f9d5-1f3fe","\uD83E\uDDD5\uD83C\uDFFF":"1f9d5-1f3ff","\uD83E\uDDD6\uD83C\uDFFB":"1f9d6-1f3fb","\uD83E\uDDD6\uD83C\uDFFC":"1f9d6-1f3fc","\uD83E\uDDD6\uD83C\uDFFD":"1f9d6-1f3fd","\uD83E\uDDD6\uD83C\uDFFE":"1f9d6-1f3fe","\uD83E\uDDD6\uD83C\uDFFF":"1f9d6-1f3ff","\uD83E\uDDD7\uD83C\uDFFB":"1f9d7-1f3fb","\uD83E\uDDD7\uD83C\uDFFC":"1f9d7-1f3fc","\uD83E\uDDD7\uD83C\uDFFD":"1f9d7-1f3fd","\uD83E\uDDD7\uD83C\uDFFE":"1f9d7-1f3fe","\uD83E\uDDD7\uD83C\uDFFF":"1f9d7-1f3ff","\uD83E\uDDD8\uD83C\uDFFB":"1f9d8-1f3fb","\uD83E\uDDD8\uD83C\uDFFC":"1f9d8-1f3fc","\uD83E\uDDD8\uD83C\uDFFD":"1f9d8-1f3fd","\uD83E\uDDD8\uD83C\uDFFE":"1f9d8-1f3fe","\uD83E\uDDD8\uD83C\uDFFF":"1f9d8-1f3ff","\uD83E\uDDD9\uD83C\uDFFB":"1f9d9-1f3fb","\uD83E\uDDD9\uD83C\uDFFC":"1f9d9-1f3fc","\uD83E\uDDD9\uD83C\uDFFD":"1f9d9-1f3fd","\uD83E\uDDD9\uD83C\uDFFE":"1f9d9-1f3fe","\uD83E\uDDD9\uD83C\uDFFF":"1f9d9-1f3ff","\uD83E\uDDDA\uD83C\uDFFB":"1f9da-1f3fb","\uD83E\uDDDA\uD83C\uDFFC":"1f9da-1f3fc","\uD83E\uDDDA\uD83C\uDFFD":"1f9da-1f3fd","\uD83E\uDDDA\uD83C\uDFFE":"1f9da-1f3fe","\uD83E\uDDDA\uD83C\uDFFF":"1f9da-1f3ff","\uD83E\uDDDB\uD83C\uDFFB":"1f9db-1f3fb","\uD83E\uDDDB\uD83C\uDFFC":"1f9db-1f3fc","\uD83E\uDDDB\uD83C\uDFFD":"1f9db-1f3fd","\uD83E\uDDDB\uD83C\uDFFE":"1f9db-1f3fe","\uD83E\uDDDB\uD83C\uDFFF":"1f9db-1f3ff","\uD83E\uDDDC\uD83C\uDFFB":"1f9dc-1f3fb","\uD83E\uDDDC\uD83C\uDFFC":"1f9dc-1f3fc","\uD83E\uDDDC\uD83C\uDFFD":"1f9dc-1f3fd","\uD83E\uDDDC\uD83C\uDFFE":"1f9dc-1f3fe","\uD83E\uDDDC\uD83C\uDFFF":"1f9dc-1f3ff","\uD83E\uDDDD\uD83C\uDFFB":"1f9dd-1f3fb","\uD83E\uDDDD\uD83C\uDFFC":"1f9dd-1f3fc","\uD83E\uDDDD\uD83C\uDFFD":"1f9dd-1f3fd","\uD83E\uDDDD\uD83C\uDFFE":"1f9dd-1f3fe","\uD83E\uDDDD\uD83C\uDFFF":"1f9dd-1f3ff","\uD83C\uDD7F\uFE0F":"1f17f","\uD83C\uDE02\uFE0F":"1f202","\uD83C\uDE37\uFE0F":"1f237","\uD83C\uDF9E\uFE0F":"1f39e","\uD83C\uDF9F\uFE0F":"1f39f","\uD83C\uDFCB\uFE0F":"1f3cb","\uD83C\uDFCC\uFE0F":"1f3cc","\uD83C\uDFCD\uFE0F":"1f3cd","\uD83C\uDFCE\uFE0F":"1f3ce","\uD83C\uDF96\uFE0F":"1f396","\uD83C\uDF97\uFE0F":"1f397","\uD83C\uDF36\uFE0F":"1f336","\uD83C\uDF27\uFE0F":"1f327","\uD83C\uDF28\uFE0F":"1f328","\uD83C\uDF29\uFE0F":"1f329","\uD83C\uDF2A\uFE0F":"1f32a","\uD83C\uDF2B\uFE0F":"1f32b","\uD83C\uDF2C\uFE0F":"1f32c","\uD83D\uDC3F\uFE0F":"1f43f","\uD83D\uDD77\uFE0F":"1f577","\uD83D\uDD78\uFE0F":"1f578","\uD83C\uDF21\uFE0F":"1f321","\uD83C\uDF99\uFE0F":"1f399","\uD83C\uDF9A\uFE0F":"1f39a","\uD83C\uDF9B\uFE0F":"1f39b","\uD83C\uDFF3\uFE0F":"1f3f3","\uD83C\uDFF5\uFE0F":"1f3f5","\uD83C\uDFF7\uFE0F":"1f3f7","\uD83D\uDCFD\uFE0F":"1f4fd","\uD83D\uDD49\uFE0F":"1f549","\uD83D\uDD4A\uFE0F":"1f54a","\uD83D\uDD6F\uFE0F":"1f56f","\uD83D\uDD70\uFE0F":"1f570","\uD83D\uDD73\uFE0F":"1f573","\uD83D\uDD76\uFE0F":"1f576","\uD83D\uDD79\uFE0F":"1f579","\uD83D\uDD87\uFE0F":"1f587","\uD83D\uDD8A\uFE0F":"1f58a","\uD83D\uDD8B\uFE0F":"1f58b","\uD83D\uDD8C\uFE0F":"1f58c","\uD83D\uDD8D\uFE0F":"1f58d","\uD83D\uDDA5\uFE0F":"1f5a5","\uD83D\uDDA8\uFE0F":"1f5a8","\uD83D\uDDB2\uFE0F":"1f5b2","\uD83D\uDDBC\uFE0F":"1f5bc","\uD83D\uDDC2\uFE0F":"1f5c2","\uD83D\uDDC3\uFE0F":"1f5c3","\uD83D\uDDC4\uFE0F":"1f5c4","\uD83D\uDDD1\uFE0F":"1f5d1","\uD83D\uDDD2\uFE0F":"1f5d2","\uD83D\uDDD3\uFE0F":"1f5d3","\uD83D\uDDDC\uFE0F":"1f5dc","\uD83D\uDDDD\uFE0F":"1f5dd","\uD83D\uDDDE\uFE0F":"1f5de","\uD83D\uDDE1\uFE0F":"1f5e1","\uD83D\uDDE3\uFE0F":"1f5e3","\uD83D\uDDE8\uFE0F":"1f5e8","\uD83D\uDDEF\uFE0F":"1f5ef","\uD83D\uDDF3\uFE0F":"1f5f3","\uD83D\uDDFA\uFE0F":"1f5fa","\uD83D\uDEE0\uFE0F":"1f6e0","\uD83D\uDEE1\uFE0F":"1f6e1","\uD83D\uDEE2\uFE0F":"1f6e2","\uD83D\uDEF0\uFE0F":"1f6f0","\uD83C\uDF7D\uFE0F":"1f37d","\uD83D\uDC41\uFE0F":"1f441","\uD83D\uDD74\uFE0F":"1f574","\uD83D\uDD75\uFE0F":"1f575","\uD83D\uDD90\uFE0F":"1f590","\uD83C\uDFD4\uFE0F":"1f3d4","\uD83C\uDFD5\uFE0F":"1f3d5","\uD83C\uDFD6\uFE0F":"1f3d6","\uD83C\uDFD7\uFE0F":"1f3d7","\uD83C\uDFD8\uFE0F":"1f3d8","\uD83C\uDFD9\uFE0F":"1f3d9","\uD83C\uDFDA\uFE0F":"1f3da","\uD83C\uDFDB\uFE0F":"1f3db","\uD83C\uDFDC\uFE0F":"1f3dc","\uD83C\uDFDD\uFE0F":"1f3dd","\uD83C\uDFDE\uFE0F":"1f3de","\uD83C\uDFDF\uFE0F":"1f3df","\uD83D\uDECB\uFE0F":"1f6cb","\uD83D\uDECD\uFE0F":"1f6cd","\uD83D\uDECE\uFE0F":"1f6ce","\uD83D\uDECF\uFE0F":"1f6cf","\uD83D\uDEE3\uFE0F":"1f6e3","\uD83D\uDEE4\uFE0F":"1f6e4","\uD83D\uDEE5\uFE0F":"1f6e5","\uD83D\uDEE9\uFE0F":"1f6e9","\uD83D\uDEF3\uFE0F":"1f6f3","\u261D\uD83C\uDFFB":"261d-1f3fb","\u261D\uD83C\uDFFC":"261d-1f3fc","\u261D\uD83C\uDFFD":"261d-1f3fd","\u261D\uD83C\uDFFE":"261d-1f3fe","\u261D\uD83C\uDFFF":"261d-1f3ff","\u270C\uD83C\uDFFB":"270c-1f3fb","\u270C\uD83C\uDFFC":"270c-1f3fc","\u270C\uD83C\uDFFD":"270c-1f3fd","\u270C\uD83C\uDFFE":"270c-1f3fe","\u270C\uD83C\uDFFF":"270c-1f3ff","\u270A\uD83C\uDFFB":"270a-1f3fb","\u270A\uD83C\uDFFC":"270a-1f3fc","\u270A\uD83C\uDFFD":"270a-1f3fd","\u270A\uD83C\uDFFE":"270a-1f3fe","\u270A\uD83C\uDFFF":"270a-1f3ff","\u270B\uD83C\uDFFB":"270b-1f3fb","\u270B\uD83C\uDFFC":"270b-1f3fc","\u270B\uD83C\uDFFD":"270b-1f3fd","\u270B\uD83C\uDFFE":"270b-1f3fe","\u270B\uD83C\uDFFF":"270b-1f3ff","\u270D\uD83C\uDFFB":"270d-1f3fb","\u270D\uD83C\uDFFC":"270d-1f3fc","\u270D\uD83C\uDFFD":"270d-1f3fd","\u270D\uD83C\uDFFE":"270d-1f3fe","\u270D\uD83C\uDFFF":"270d-1f3ff","\uD83C\uDF24\uFE0F":"1f324","\uD83C\uDF25\uFE0F":"1f325","\uD83C\uDF26\uFE0F":"1f326","\uD83D\uDDB1\uFE0F":"1f5b1","\u26F9\uD83C\uDFFB":"26f9-1f3fb","\u26F9\uD83C\uDFFC":"26f9-1f3fc","\u26F9\uD83C\uDFFD":"26f9-1f3fd","\u26F9\uD83C\uDFFE":"26f9-1f3fe","\u26F9\uD83C\uDFFF":"26f9-1f3ff","\uD83C\uDD70\uFE0F":"1f170","\uD83C\uDD71\uFE0F":"1f171","\uD83C\uDD7E\uFE0F":"1f17e","#\u20E3":"0023-20e3","0\u20E3":"0030-20e3","1\u20E3":"0031-20e3","2\u20E3":"0032-20e3","3\u20E3":"0033-20e3","4\u20E3":"0034-20e3","5\u20E3":"0035-20e3","6\u20E3":"0036-20e3","7\u20E3":"0037-20e3","8\u20E3":"0038-20e3","9\u20E3":"0039-20e3","\u00A9\uFE0F":"00a9","\u00AE\uFE0F":"00ae","\u203C\uFE0F":"203c","\u2049\uFE0F":"2049","\u2122\uFE0F":"2122","\u2139\uFE0F":"2139","\u2194\uFE0F":"2194","\u2195\uFE0F":"2195","\u2196\uFE0F":"2196","\u2197\uFE0F":"2197","\u2198\uFE0F":"2198","\u2199\uFE0F":"2199","\u21A9\uFE0F":"21a9","\u21AA\uFE0F":"21aa","\u24C2\uFE0F":"24c2","\u25AA\uFE0F":"25aa","\u25AB\uFE0F":"25ab","\u25B6\uFE0F":"25b6","\u25C0\uFE0F":"25c0","\u25FB\uFE0F":"25fb","\u25FC\uFE0F":"25fc","\u2600\uFE0F":"2600","\u2601\uFE0F":"2601","\u260E\uFE0F":"260e","\u2611\uFE0F":"2611","\u261D\uFE0F":"261d","\u263A\uFE0F":"263a","\u2660\uFE0F":"2660","\u2663\uFE0F":"2663","\u2665\uFE0F":"2665","\u2666\uFE0F":"2666","\u2668\uFE0F":"2668","\u267B\uFE0F":"267b","\u26A0\uFE0F":"26a0","\u2702\uFE0F":"2702","\u2708\uFE0F":"2708","\u2709\uFE0F":"2709","\u270C\uFE0F":"270c","\u270F\uFE0F":"270f","\u2712\uFE0F":"2712","\u2714\uFE0F":"2714","\u2716\uFE0F":"2716","\u2733\uFE0F":"2733","\u2734\uFE0F":"2734","\u2744\uFE0F":"2744","\u2747\uFE0F":"2747","\u2764\uFE0F":"2764","\u27A1\uFE0F":"27a1","\u2934\uFE0F":"2934","\u2935\uFE0F":"2935","\u2B05\uFE0F":"2b05","\u2B06\uFE0F":"2b06","\u2B07\uFE0F":"2b07","\u3030\uFE0F":"3030","\u303D\uFE0F":"303d","\u3297\uFE0F":"3297","\u3299\uFE0F":"3299","\u271D\uFE0F":"271d","\u2328\uFE0F":"2328","\u270D\uFE0F":"270d","*\u20E3":"002a-20e3","\u23CF\uFE0F":"23cf","\u23ED\uFE0F":"23ed","\u23EE\uFE0F":"23ee","\u23EF\uFE0F":"23ef","\u23F1\uFE0F":"23f1","\u23F2\uFE0F":"23f2","\u23F8\uFE0F":"23f8","\u23F9\uFE0F":"23f9","\u23FA\uFE0F":"23fa","\u2602\uFE0F":"2602","\u2603\uFE0F":"2603","\u2604\uFE0F":"2604","\u2618\uFE0F":"2618","\u2620\uFE0F":"2620","\u2622\uFE0F":"2622","\u2623\uFE0F":"2623","\u2626\uFE0F":"2626","\u262A\uFE0F":"262a","\u262E\uFE0F":"262e","\u262F\uFE0F":"262f","\u2638\uFE0F":"2638","\u2639\uFE0F":"2639","\u2692\uFE0F":"2692","\u2694\uFE0F":"2694","\u2696\uFE0F":"2696","\u2697\uFE0F":"2697","\u2699\uFE0F":"2699","\u269B\uFE0F":"269b","\u269C\uFE0F":"269c","\u26B0\uFE0F":"26b0","\u26B1\uFE0F":"26b1","\u26C8\uFE0F":"26c8","\u26CF\uFE0F":"26cf","\u26D1\uFE0F":"26d1","\u26D3\uFE0F":"26d3","\u26E9\uFE0F":"26e9","\u26F0\uFE0F":"26f0","\u26F1\uFE0F":"26f1","\u26F4\uFE0F":"26f4","\u26F7\uFE0F":"26f7","\u26F8\uFE0F":"26f8","\u26F9\uFE0F":"26f9","\u2721\uFE0F":"2721","\u2763\uFE0F":"2763","#\uFE0F":"0023","*\uFE0F":"002a","0\uFE0F":"0030","1\uFE0F":"0031","2\uFE0F":"0032","3\uFE0F":"0033","4\uFE0F":"0034","5\uFE0F":"0035","6\uFE0F":"0036","7\uFE0F":"0037","8\uFE0F":"0038","9\uFE0F":"0039","\u2640\uFE0F":"2640","\u2642\uFE0F":"2642","\u2695\uFE0F":"2695","\uD83E\uDD49":"1f949","\uD83E\uDD48":"1f948","\uD83E\uDD47":"1f947","\uD83E\uDD3A":"1f93a","\uD83E\uDD45":"1f945","\uD83E\uDD3E":"1f93e","\uD83C\uDDFF":"1f1ff","\uD83E\uDD3D":"1f93d","\uD83E\uDD4B":"1f94b","\uD83E\uDD4A":"1f94a","\uD83E\uDD3C":"1f93c","\uD83E\uDD39":"1f939","\uD83E\uDD38":"1f938","\uD83D\uDEF6":"1f6f6","\uD83D\uDEF5":"1f6f5","\uD83D\uDEF4":"1f6f4","\uD83D\uDED2":"1f6d2","\uD83C\uDC04":"1f004","\uD83C\uDCCF":"1f0cf","\uD83D\uDED1":"1f6d1","\uD83C\uDD8E":"1f18e","\uD83C\uDD91":"1f191","\uD83C\uDDFE":"1f1fe","\uD83C\uDD92":"1f192","\uD83C\uDD93":"1f193","\uD83C\uDD94":"1f194","\uD83C\uDD95":"1f195","\uD83C\uDD96":"1f196","\uD83C\uDD97":"1f197","\uD83C\uDD98":"1f198","\uD83E\uDD44":"1f944","\uD83C\uDD99":"1f199","\uD83C\uDD9A":"1f19a","\uD83E\uDD42":"1f942","\uD83E\uDD43":"1f943","\uD83C\uDE01":"1f201","\uD83C\uDE1A":"1f21a","\uD83C\uDE2F":"1f22f","\uD83E\uDD59":"1f959","\uD83C\uDE32":"1f232","\uD83C\uDE33":"1f233","\uD83C\uDE34":"1f234","\uD83C\uDE35":"1f235","\uD83C\uDE36":"1f236","\uD83E\uDD58":"1f958","\uD83C\uDE38":"1f238","\uD83C\uDE39":"1f239","\uD83E\uDD57":"1f957","\uD83C\uDE3A":"1f23a","\uD83C\uDE50":"1f250","\uD83C\uDE51":"1f251","\uD83C\uDF00":"1f300","\uD83E\uDD56":"1f956","\uD83C\uDF01":"1f301","\uD83C\uDF02":"1f302","\uD83C\uDF03":"1f303","\uD83C\uDF04":"1f304","\uD83C\uDF05":"1f305","\uD83C\uDF06":"1f306","\uD83E\uDD55":"1f955","\uD83C\uDF07":"1f307","\uD83C\uDF08":"1f308","\uD83E\uDD54":"1f954","\uD83C\uDF09":"1f309","\uD83C\uDF0A":"1f30a","\uD83C\uDF0B":"1f30b","\uD83C\uDF0C":"1f30c","\uD83C\uDF0F":"1f30f","\uD83C\uDF11":"1f311","\uD83E\uDD53":"1f953","\uD83C\uDF13":"1f313","\uD83C\uDF14":"1f314","\uD83C\uDF15":"1f315","\uD83C\uDF19":"1f319","\uD83C\uDF1B":"1f31b","\uD83C\uDF1F":"1f31f","\uD83E\uDD52":"1f952","\uD83C\uDF20":"1f320","\uD83C\uDF30":"1f330","\uD83E\uDD51":"1f951","\uD83C\uDF31":"1f331","\uD83C\uDF34":"1f334","\uD83C\uDF35":"1f335","\uD83C\uDF37":"1f337","\uD83C\uDF38":"1f338","\uD83C\uDF39":"1f339","\uD83C\uDF3A":"1f33a","\uD83C\uDF3B":"1f33b","\uD83C\uDF3C":"1f33c","\uD83C\uDF3D":"1f33d","\uD83E\uDD50":"1f950","\uD83C\uDF3E":"1f33e","\uD83C\uDF3F":"1f33f","\uD83C\uDF40":"1f340","\uD83C\uDF41":"1f341","\uD83C\uDF42":"1f342","\uD83C\uDF43":"1f343","\uD83C\uDF44":"1f344","\uD83C\uDF45":"1f345","\uD83C\uDF46":"1f346","\uD83C\uDF47":"1f347","\uD83C\uDF48":"1f348","\uD83C\uDF49":"1f349","\uD83C\uDF4A":"1f34a","\uD83E\uDD40":"1f940","\uD83C\uDF4C":"1f34c","\uD83C\uDF4D":"1f34d","\uD83C\uDF4E":"1f34e","\uD83C\uDF4F":"1f34f","\uD83C\uDF51":"1f351","\uD83C\uDF52":"1f352","\uD83C\uDF53":"1f353","\uD83E\uDD8F":"1f98f","\uD83C\uDF54":"1f354","\uD83C\uDF55":"1f355","\uD83C\uDF56":"1f356","\uD83E\uDD8E":"1f98e","\uD83C\uDF57":"1f357","\uD83C\uDF58":"1f358","\uD83C\uDF59":"1f359","\uD83E\uDD8D":"1f98d","\uD83C\uDF5A":"1f35a","\uD83C\uDF5B":"1f35b","\uD83E\uDD8C":"1f98c","\uD83C\uDF5C":"1f35c","\uD83C\uDF5D":"1f35d","\uD83C\uDF5E":"1f35e","\uD83C\uDF5F":"1f35f","\uD83E\uDD8B":"1f98b","\uD83C\uDF60":"1f360","\uD83C\uDF61":"1f361","\uD83E\uDD8A":"1f98a","\uD83C\uDF62":"1f362","\uD83C\uDF63":"1f363","\uD83E\uDD89":"1f989","\uD83C\uDF64":"1f364","\uD83C\uDF65":"1f365","\uD83E\uDD88":"1f988","\uD83C\uDF66":"1f366","\uD83E\uDD87":"1f987","\uD83C\uDF67":"1f367","\uD83C\uDDFD":"1f1fd","\uD83C\uDF68":"1f368","\uD83E\uDD86":"1f986","\uD83C\uDF69":"1f369","\uD83E\uDD85":"1f985","\uD83C\uDF6A":"1f36a","\uD83D\uDDA4":"1f5a4","\uD83C\uDF6B":"1f36b","\uD83C\uDF6C":"1f36c","\uD83C\uDF6D":"1f36d","\uD83C\uDF6E":"1f36e","\uD83C\uDF6F":"1f36f","\uD83E\uDD1E":"1f91e","\uD83C\uDF70":"1f370","\uD83C\uDF71":"1f371","\uD83C\uDF72":"1f372","\uD83E\uDD1D":"1f91d","\uD83C\uDF73":"1f373","\uD83C\uDF74":"1f374","\uD83C\uDF75":"1f375","\uD83C\uDF76":"1f376","\uD83C\uDF77":"1f377","\uD83C\uDF78":"1f378","\uD83C\uDF79":"1f379","\uD83C\uDF7A":"1f37a","\uD83C\uDF7B":"1f37b","\uD83C\uDF80":"1f380","\uD83C\uDF81":"1f381","\uD83C\uDF82":"1f382","\uD83C\uDF83":"1f383","\uD83E\uDD1B":"1f91b","\uD83E\uDD1C":"1f91c","\uD83C\uDF84":"1f384","\uD83C\uDF85":"1f385","\uD83C\uDF86":"1f386","\uD83E\uDD1A":"1f91a","\uD83C\uDF87":"1f387","\uD83C\uDF88":"1f388","\uD83C\uDF89":"1f389","\uD83C\uDF8A":"1f38a","\uD83C\uDF8B":"1f38b","\uD83C\uDF8C":"1f38c","\uD83E\uDD19":"1f919","\uD83C\uDF8D":"1f38d","\uD83D\uDD7A":"1f57a","\uD83C\uDF8E":"1f38e","\uD83E\uDD33":"1f933","\uD83C\uDF8F":"1f38f","\uD83E\uDD30":"1f930","\uD83C\uDF90":"1f390","\uD83E\uDD26":"1f926","\uD83E\uDD37":"1f937","\uD83C\uDF91":"1f391","\uD83C\uDF92":"1f392","\uD83C\uDF93":"1f393","\uD83C\uDFA0":"1f3a0","\uD83C\uDFA1":"1f3a1","\uD83C\uDFA2":"1f3a2","\uD83C\uDFA3":"1f3a3","\uD83C\uDFA4":"1f3a4","\uD83C\uDFA5":"1f3a5","\uD83C\uDFA6":"1f3a6","\uD83C\uDFA7":"1f3a7","\uD83E\uDD36":"1f936","\uD83C\uDFA8":"1f3a8","\uD83E\uDD35":"1f935","\uD83C\uDFA9":"1f3a9","\uD83C\uDFAA":"1f3aa","\uD83E\uDD34":"1f934","\uD83C\uDFAB":"1f3ab","\uD83C\uDFAC":"1f3ac","\uD83C\uDFAD":"1f3ad","\uD83E\uDD27":"1f927","\uD83C\uDFAE":"1f3ae","\uD83C\uDFAF":"1f3af","\uD83C\uDFB0":"1f3b0","\uD83C\uDFB1":"1f3b1","\uD83C\uDFB2":"1f3b2","\uD83C\uDFB3":"1f3b3","\uD83C\uDFB4":"1f3b4","\uD83E\uDD25":"1f925","\uD83C\uDFB5":"1f3b5","\uD83C\uDFB6":"1f3b6","\uD83C\uDFB7":"1f3b7","\uD83E\uDD24":"1f924","\uD83C\uDFB8":"1f3b8","\uD83C\uDFB9":"1f3b9","\uD83C\uDFBA":"1f3ba","\uD83E\uDD23":"1f923","\uD83C\uDFBB":"1f3bb","\uD83C\uDFBC":"1f3bc","\uD83C\uDFBD":"1f3bd","\uD83E\uDD22":"1f922","\uD83C\uDFBE":"1f3be","\uD83C\uDFBF":"1f3bf","\uD83C\uDFC0":"1f3c0","\uD83C\uDFC1":"1f3c1","\uD83E\uDD21":"1f921","\uD83C\uDFC2":"1f3c2","\uD83C\uDFC3":"1f3c3","\uD83C\uDFC4":"1f3c4","\uD83C\uDFC6":"1f3c6","\uD83C\uDFC8":"1f3c8","\uD83C\uDFCA":"1f3ca","\uD83C\uDFE0":"1f3e0","\uD83C\uDFE1":"1f3e1","\uD83C\uDFE2":"1f3e2","\uD83C\uDFE3":"1f3e3","\uD83C\uDFE5":"1f3e5","\uD83C\uDFE6":"1f3e6","\uD83C\uDFE7":"1f3e7","\uD83C\uDFE8":"1f3e8","\uD83C\uDFE9":"1f3e9","\uD83C\uDFEA":"1f3ea","\uD83C\uDFEB":"1f3eb","\uD83C\uDFEC":"1f3ec","\uD83E\uDD20":"1f920","\uD83C\uDFED":"1f3ed","\uD83C\uDFEE":"1f3ee","\uD83C\uDFEF":"1f3ef","\uD83C\uDFF0":"1f3f0","\uD83D\uDC0C":"1f40c","\uD83D\uDC0D":"1f40d","\uD83D\uDC0E":"1f40e","\uD83D\uDC11":"1f411","\uD83D\uDC12":"1f412","\uD83D\uDC14":"1f414","\uD83D\uDC17":"1f417","\uD83D\uDC18":"1f418","\uD83D\uDC19":"1f419","\uD83D\uDC1A":"1f41a","\uD83D\uDC1B":"1f41b","\uD83D\uDC1C":"1f41c","\uD83D\uDC1D":"1f41d","\uD83D\uDC1E":"1f41e","\uD83D\uDC1F":"1f41f","\uD83D\uDC20":"1f420","\uD83D\uDC21":"1f421","\uD83D\uDC22":"1f422","\uD83D\uDC23":"1f423","\uD83D\uDC24":"1f424","\uD83D\uDC25":"1f425","\uD83D\uDC26":"1f426","\uD83D\uDC27":"1f427","\uD83D\uDC28":"1f428","\uD83D\uDC29":"1f429","\uD83D\uDC2B":"1f42b","\uD83D\uDC2C":"1f42c","\uD83D\uDC2D":"1f42d","\uD83D\uDC2E":"1f42e","\uD83D\uDC2F":"1f42f","\uD83D\uDC30":"1f430","\uD83D\uDC31":"1f431","\uD83D\uDC32":"1f432","\uD83D\uDC33":"1f433","\uD83D\uDC34":"1f434","\uD83D\uDC35":"1f435","\uD83D\uDC36":"1f436","\uD83D\uDC37":"1f437","\uD83D\uDC38":"1f438","\uD83D\uDC39":"1f439","\uD83D\uDC3A":"1f43a","\uD83D\uDC3B":"1f43b","\uD83D\uDC3C":"1f43c","\uD83D\uDC3D":"1f43d","\uD83D\uDC3E":"1f43e","\uD83D\uDC40":"1f440","\uD83D\uDC42":"1f442","\uD83D\uDC43":"1f443","\uD83D\uDC44":"1f444","\uD83D\uDC45":"1f445","\uD83D\uDC46":"1f446","\uD83D\uDC47":"1f447","\uD83D\uDC48":"1f448","\uD83D\uDC49":"1f449","\uD83D\uDC4A":"1f44a","\uD83D\uDC4B":"1f44b","\uD83D\uDC4C":"1f44c","\uD83D\uDC4D":"1f44d","\uD83D\uDC4E":"1f44e","\uD83D\uDC4F":"1f44f","\uD83D\uDC50":"1f450","\uD83D\uDC51":"1f451","\uD83D\uDC52":"1f452","\uD83D\uDC53":"1f453","\uD83D\uDC54":"1f454","\uD83D\uDC55":"1f455","\uD83D\uDC56":"1f456","\uD83D\uDC57":"1f457","\uD83D\uDC58":"1f458","\uD83D\uDC59":"1f459","\uD83D\uDC5A":"1f45a","\uD83D\uDC5B":"1f45b","\uD83D\uDC5C":"1f45c","\uD83D\uDC5D":"1f45d","\uD83D\uDC5E":"1f45e","\uD83D\uDC5F":"1f45f","\uD83D\uDC60":"1f460","\uD83D\uDC61":"1f461","\uD83D\uDC62":"1f462","\uD83D\uDC63":"1f463","\uD83D\uDC64":"1f464","\uD83D\uDC66":"1f466","\uD83D\uDC67":"1f467","\uD83D\uDC68":"1f468","\uD83D\uDC69":"1f469","\uD83D\uDC6A":"1f46a","\uD83D\uDC6B":"1f46b","\uD83D\uDC6E":"1f46e","\uD83D\uDC6F":"1f46f","\uD83D\uDC70":"1f470","\uD83D\uDC71":"1f471","\uD83D\uDC72":"1f472","\uD83D\uDC73":"1f473","\uD83D\uDC74":"1f474","\uD83D\uDC75":"1f475","\uD83D\uDC76":"1f476","\uD83D\uDC77":"1f477","\uD83D\uDC78":"1f478","\uD83D\uDC79":"1f479","\uD83D\uDC7A":"1f47a","\uD83D\uDC7B":"1f47b","\uD83D\uDC7C":"1f47c","\uD83D\uDC7D":"1f47d","\uD83D\uDC7E":"1f47e","\uD83D\uDC7F":"1f47f","\uD83D\uDC80":"1f480","\uD83D\uDCC7":"1f4c7","\uD83D\uDC81":"1f481","\uD83D\uDC82":"1f482","\uD83D\uDC83":"1f483","\uD83D\uDC84":"1f484","\uD83D\uDC85":"1f485","\uD83D\uDCD2":"1f4d2","\uD83D\uDC86":"1f486","\uD83D\uDCD3":"1f4d3","\uD83D\uDC87":"1f487","\uD83D\uDCD4":"1f4d4","\uD83D\uDC88":"1f488","\uD83D\uDCD5":"1f4d5","\uD83D\uDC89":"1f489","\uD83D\uDCD6":"1f4d6","\uD83D\uDC8A":"1f48a","\uD83D\uDCD7":"1f4d7","\uD83D\uDC8B":"1f48b","\uD83D\uDCD8":"1f4d8","\uD83D\uDC8C":"1f48c","\uD83D\uDCD9":"1f4d9","\uD83D\uDC8D":"1f48d","\uD83D\uDCDA":"1f4da","\uD83D\uDC8E":"1f48e","\uD83D\uDCDB":"1f4db","\uD83D\uDC8F":"1f48f","\uD83D\uDCDC":"1f4dc","\uD83D\uDC90":"1f490","\uD83D\uDCDD":"1f4dd","\uD83D\uDC91":"1f491","\uD83D\uDCDE":"1f4de","\uD83D\uDC92":"1f492","\uD83D\uDCDF":"1f4df","\uD83D\uDCE0":"1f4e0","\uD83D\uDC93":"1f493","\uD83D\uDCE1":"1f4e1","\uD83D\uDCE2":"1f4e2","\uD83D\uDC94":"1f494","\uD83D\uDCE3":"1f4e3","\uD83D\uDCE4":"1f4e4","\uD83D\uDC95":"1f495","\uD83D\uDCE5":"1f4e5","\uD83D\uDCE6":"1f4e6","\uD83D\uDC96":"1f496","\uD83D\uDCE7":"1f4e7","\uD83D\uDCE8":"1f4e8","\uD83D\uDC97":"1f497","\uD83D\uDCE9":"1f4e9","\uD83D\uDCEA":"1f4ea","\uD83D\uDC98":"1f498","\uD83D\uDCEB":"1f4eb","\uD83D\uDCEE":"1f4ee","\uD83D\uDC99":"1f499","\uD83D\uDCF0":"1f4f0","\uD83D\uDCF1":"1f4f1","\uD83D\uDC9A":"1f49a","\uD83D\uDCF2":"1f4f2","\uD83D\uDCF3":"1f4f3","\uD83D\uDC9B":"1f49b","\uD83D\uDCF4":"1f4f4","\uD83D\uDCF6":"1f4f6","\uD83D\uDC9C":"1f49c","\uD83D\uDCF7":"1f4f7","\uD83D\uDCF9":"1f4f9","\uD83D\uDC9D":"1f49d","\uD83D\uDCFA":"1f4fa","\uD83D\uDCFB":"1f4fb","\uD83D\uDC9E":"1f49e","\uD83D\uDCFC":"1f4fc","\uD83D\uDD03":"1f503","\uD83D\uDC9F":"1f49f","\uD83D\uDD0A":"1f50a","\uD83D\uDD0B":"1f50b","\uD83D\uDCA0":"1f4a0","\uD83D\uDD0C":"1f50c","\uD83D\uDD0D":"1f50d","\uD83D\uDCA1":"1f4a1","\uD83D\uDD0E":"1f50e","\uD83D\uDD0F":"1f50f","\uD83D\uDCA2":"1f4a2","\uD83D\uDD10":"1f510","\uD83D\uDD11":"1f511","\uD83D\uDCA3":"1f4a3","\uD83D\uDD12":"1f512","\uD83D\uDD13":"1f513","\uD83D\uDCA4":"1f4a4","\uD83D\uDD14":"1f514","\uD83D\uDD16":"1f516","\uD83D\uDCA5":"1f4a5","\uD83D\uDD17":"1f517","\uD83D\uDD18":"1f518","\uD83D\uDCA6":"1f4a6","\uD83D\uDD19":"1f519","\uD83D\uDD1A":"1f51a","\uD83D\uDCA7":"1f4a7","\uD83D\uDD1B":"1f51b","\uD83D\uDD1C":"1f51c","\uD83D\uDCA8":"1f4a8","\uD83D\uDD1D":"1f51d","\uD83D\uDD1E":"1f51e","\uD83D\uDCA9":"1f4a9","\uD83D\uDD1F":"1f51f","\uD83D\uDCAA":"1f4aa","\uD83D\uDD20":"1f520","\uD83D\uDD21":"1f521","\uD83D\uDCAB":"1f4ab","\uD83D\uDD22":"1f522","\uD83D\uDD23":"1f523","\uD83D\uDCAC":"1f4ac","\uD83D\uDD24":"1f524","\uD83D\uDD25":"1f525","\uD83D\uDCAE":"1f4ae","\uD83D\uDD26":"1f526","\uD83D\uDD27":"1f527","\uD83D\uDCAF":"1f4af","\uD83D\uDD28":"1f528","\uD83D\uDD29":"1f529","\uD83D\uDCB0":"1f4b0","\uD83D\uDD2A":"1f52a","\uD83D\uDD2B":"1f52b","\uD83D\uDCB1":"1f4b1","\uD83D\uDD2E":"1f52e","\uD83D\uDCB2":"1f4b2","\uD83D\uDD2F":"1f52f","\uD83D\uDCB3":"1f4b3","\uD83D\uDD30":"1f530","\uD83D\uDD31":"1f531","\uD83D\uDCB4":"1f4b4","\uD83D\uDD32":"1f532","\uD83D\uDD33":"1f533","\uD83D\uDCB5":"1f4b5","\uD83D\uDD34":"1f534","\uD83D\uDD35":"1f535","\uD83D\uDCB8":"1f4b8","\uD83D\uDD36":"1f536","\uD83D\uDD37":"1f537","\uD83D\uDCB9":"1f4b9","\uD83D\uDD38":"1f538","\uD83D\uDD39":"1f539","\uD83D\uDCBA":"1f4ba","\uD83D\uDD3A":"1f53a","\uD83D\uDD3B":"1f53b","\uD83D\uDCBB":"1f4bb","\uD83D\uDD3C":"1f53c","\uD83D\uDCBC":"1f4bc","\uD83D\uDD3D":"1f53d","\uD83D\uDD50":"1f550","\uD83D\uDCBD":"1f4bd","\uD83D\uDD51":"1f551","\uD83D\uDCBE":"1f4be","\uD83D\uDD52":"1f552","\uD83D\uDCBF":"1f4bf","\uD83D\uDD53":"1f553","\uD83D\uDCC0":"1f4c0","\uD83D\uDD54":"1f554","\uD83D\uDD55":"1f555","\uD83D\uDCC1":"1f4c1","\uD83D\uDD56":"1f556","\uD83D\uDD57":"1f557","\uD83D\uDCC2":"1f4c2","\uD83D\uDD58":"1f558","\uD83D\uDD59":"1f559","\uD83D\uDCC3":"1f4c3","\uD83D\uDD5A":"1f55a","\uD83D\uDD5B":"1f55b","\uD83D\uDCC4":"1f4c4","\uD83D\uDDFB":"1f5fb","\uD83D\uDDFC":"1f5fc","\uD83D\uDCC5":"1f4c5","\uD83D\uDDFD":"1f5fd","\uD83D\uDDFE":"1f5fe","\uD83D\uDCC6":"1f4c6","\uD83D\uDDFF":"1f5ff","\uD83D\uDE01":"1f601","\uD83D\uDE02":"1f602","\uD83D\uDE03":"1f603","\uD83D\uDCC8":"1f4c8","\uD83D\uDE04":"1f604","\uD83D\uDE05":"1f605","\uD83D\uDCC9":"1f4c9","\uD83D\uDE06":"1f606","\uD83D\uDE09":"1f609","\uD83D\uDCCA":"1f4ca","\uD83D\uDE0A":"1f60a","\uD83D\uDE0B":"1f60b","\uD83D\uDCCB":"1f4cb","\uD83D\uDE0C":"1f60c","\uD83D\uDE0D":"1f60d","\uD83D\uDCCC":"1f4cc","\uD83D\uDE0F":"1f60f","\uD83D\uDE12":"1f612","\uD83D\uDCCD":"1f4cd","\uD83D\uDE13":"1f613","\uD83D\uDE14":"1f614","\uD83D\uDCCE":"1f4ce","\uD83D\uDE16":"1f616","\uD83D\uDE18":"1f618","\uD83D\uDCCF":"1f4cf","\uD83D\uDE1A":"1f61a","\uD83D\uDE1C":"1f61c","\uD83D\uDCD0":"1f4d0","\uD83D\uDE1D":"1f61d","\uD83D\uDE1E":"1f61e","\uD83D\uDCD1":"1f4d1","\uD83D\uDE20":"1f620","\uD83D\uDE21":"1f621","\uD83D\uDE22":"1f622","\uD83D\uDE23":"1f623","\uD83D\uDE24":"1f624","\uD83D\uDE25":"1f625","\uD83D\uDE28":"1f628","\uD83D\uDE29":"1f629","\uD83D\uDE2A":"1f62a","\uD83D\uDE2B":"1f62b","\uD83D\uDE2D":"1f62d","\uD83D\uDE30":"1f630","\uD83D\uDE31":"1f631","\uD83D\uDE32":"1f632","\uD83D\uDE33":"1f633","\uD83D\uDE35":"1f635","\uD83D\uDE37":"1f637","\uD83D\uDE38":"1f638","\uD83D\uDE39":"1f639","\uD83D\uDE3A":"1f63a","\uD83D\uDE3B":"1f63b","\uD83D\uDE3C":"1f63c","\uD83D\uDE3D":"1f63d","\uD83D\uDE3E":"1f63e","\uD83D\uDE3F":"1f63f","\uD83D\uDE40":"1f640","\uD83D\uDE45":"1f645","\uD83D\uDE46":"1f646","\uD83D\uDE47":"1f647","\uD83D\uDE48":"1f648","\uD83D\uDE49":"1f649","\uD83D\uDE4A":"1f64a","\uD83D\uDE4B":"1f64b","\uD83D\uDE4C":"1f64c","\uD83D\uDE4D":"1f64d","\uD83D\uDE4E":"1f64e","\uD83D\uDE4F":"1f64f","\uD83D\uDE80":"1f680","\uD83D\uDE83":"1f683","\uD83D\uDE84":"1f684","\uD83D\uDE85":"1f685","\uD83D\uDE87":"1f687","\uD83D\uDE89":"1f689","\uD83D\uDE8C":"1f68c","\uD83D\uDE8F":"1f68f","\uD83D\uDE91":"1f691","\uD83D\uDE92":"1f692","\uD83D\uDE93":"1f693","\uD83D\uDE95":"1f695","\uD83D\uDE97":"1f697","\uD83D\uDE99":"1f699","\uD83D\uDE9A":"1f69a","\uD83D\uDEA2":"1f6a2","\uD83D\uDEA4":"1f6a4","\uD83D\uDEA5":"1f6a5","\uD83D\uDEA7":"1f6a7","\uD83D\uDEA8":"1f6a8","\uD83D\uDEA9":"1f6a9","\uD83D\uDEAA":"1f6aa","\uD83D\uDEAB":"1f6ab","\uD83D\uDEAC":"1f6ac","\uD83D\uDEAD":"1f6ad","\uD83D\uDEB2":"1f6b2","\uD83D\uDEB6":"1f6b6","\uD83D\uDEB9":"1f6b9","\uD83D\uDEBA":"1f6ba","\uD83D\uDEBB":"1f6bb","\uD83D\uDEBC":"1f6bc","\uD83D\uDEBD":"1f6bd","\uD83D\uDEBE":"1f6be","\uD83D\uDEC0":"1f6c0","\uD83E\uDD18":"1f918","\uD83D\uDE00":"1f600","\uD83D\uDE07":"1f607","\uD83D\uDE08":"1f608","\uD83D\uDE0E":"1f60e","\uD83D\uDE10":"1f610","\uD83D\uDE11":"1f611","\uD83D\uDE15":"1f615","\uD83D\uDE17":"1f617","\uD83D\uDE19":"1f619","\uD83D\uDE1B":"1f61b","\uD83D\uDE1F":"1f61f","\uD83D\uDE26":"1f626","\uD83D\uDE27":"1f627","\uD83D\uDE2C":"1f62c","\uD83D\uDE2E":"1f62e","\uD83D\uDE2F":"1f62f","\uD83D\uDE34":"1f634","\uD83D\uDE36":"1f636","\uD83D\uDE81":"1f681","\uD83D\uDE82":"1f682","\uD83D\uDE86":"1f686","\uD83D\uDE88":"1f688","\uD83D\uDE8A":"1f68a","\uD83D\uDE8D":"1f68d","\uD83D\uDE8E":"1f68e","\uD83D\uDE90":"1f690","\uD83D\uDE94":"1f694","\uD83D\uDE96":"1f696","\uD83D\uDE98":"1f698","\uD83D\uDE9B":"1f69b","\uD83D\uDE9C":"1f69c","\uD83D\uDE9D":"1f69d","\uD83D\uDE9E":"1f69e","\uD83D\uDE9F":"1f69f","\uD83D\uDEA0":"1f6a0","\uD83D\uDEA1":"1f6a1","\uD83D\uDEA3":"1f6a3","\uD83D\uDEA6":"1f6a6","\uD83D\uDEAE":"1f6ae","\uD83D\uDEAF":"1f6af","\uD83D\uDEB0":"1f6b0","\uD83D\uDEB1":"1f6b1","\uD83D\uDEB3":"1f6b3","\uD83D\uDEB4":"1f6b4","\uD83D\uDEB5":"1f6b5","\uD83D\uDEB7":"1f6b7","\uD83D\uDEB8":"1f6b8","\uD83D\uDEBF":"1f6bf","\uD83D\uDEC1":"1f6c1","\uD83D\uDEC2":"1f6c2","\uD83D\uDEC3":"1f6c3","\uD83D\uDEC4":"1f6c4","\uD83D\uDEC5":"1f6c5","\uD83C\uDF0D":"1f30d","\uD83C\uDF0E":"1f30e","\uD83C\uDF10":"1f310","\uD83C\uDF12":"1f312","\uD83C\uDF16":"1f316","\uD83C\uDF17":"1f317","\uD83C\uDF18":"1f318","\uD83C\uDF1A":"1f31a","\uD83C\uDF1C":"1f31c","\uD83C\uDF1D":"1f31d","\uD83C\uDF1E":"1f31e","\uD83C\uDF32":"1f332","\uD83C\uDF33":"1f333","\uD83C\uDF4B":"1f34b","\uD83C\uDF50":"1f350","\uD83C\uDF7C":"1f37c","\uD83C\uDFC7":"1f3c7","\uD83C\uDFC9":"1f3c9","\uD83C\uDFE4":"1f3e4","\uD83D\uDC00":"1f400","\uD83D\uDC01":"1f401","\uD83D\uDC02":"1f402","\uD83D\uDC03":"1f403","\uD83D\uDC04":"1f404","\uD83D\uDC05":"1f405","\uD83D\uDC06":"1f406","\uD83D\uDC07":"1f407","\uD83D\uDC08":"1f408","\uD83D\uDC09":"1f409","\uD83D\uDC0A":"1f40a","\uD83D\uDC0B":"1f40b","\uD83D\uDC0F":"1f40f","\uD83D\uDC10":"1f410","\uD83D\uDC13":"1f413","\uD83D\uDC15":"1f415","\uD83D\uDC16":"1f416","\uD83D\uDC2A":"1f42a","\uD83D\uDC65":"1f465","\uD83D\uDC6C":"1f46c","\uD83D\uDC6D":"1f46d","\uD83D\uDCAD":"1f4ad","\uD83D\uDCB6":"1f4b6","\uD83D\uDCB7":"1f4b7","\uD83D\uDCEC":"1f4ec","\uD83D\uDCED":"1f4ed","\uD83D\uDCEF":"1f4ef","\uD83D\uDCF5":"1f4f5","\uD83D\uDD00":"1f500","\uD83D\uDD01":"1f501","\uD83D\uDD02":"1f502","\uD83D\uDD04":"1f504","\uD83D\uDD05":"1f505","\uD83D\uDD06":"1f506","\uD83D\uDD07":"1f507","\uD83D\uDD09":"1f509","\uD83D\uDD15":"1f515","\uD83D\uDD2C":"1f52c","\uD83D\uDD2D":"1f52d","\uD83D\uDD5C":"1f55c","\uD83D\uDD5D":"1f55d","\uD83D\uDD5E":"1f55e","\uD83D\uDD5F":"1f55f","\uD83D\uDD60":"1f560","\uD83D\uDD61":"1f561","\uD83D\uDD62":"1f562","\uD83D\uDD63":"1f563","\uD83D\uDD64":"1f564","\uD83D\uDD65":"1f565","\uD83D\uDD66":"1f566","\uD83D\uDD67":"1f567","\uD83D\uDD08":"1f508","\uD83D\uDE8B":"1f68b","\uD83C\uDFC5":"1f3c5","\uD83C\uDFF4":"1f3f4","\uD83D\uDCF8":"1f4f8","\uD83D\uDECC":"1f6cc","\uD83D\uDD95":"1f595","\uD83D\uDD96":"1f596","\uD83D\uDE41":"1f641","\uD83D\uDE42":"1f642","\uD83D\uDEEB":"1f6eb","\uD83D\uDEEC":"1f6ec","\uD83C\uDFFB":"1f3fb","\uD83C\uDFFC":"1f3fc","\uD83C\uDFFD":"1f3fd","\uD83C\uDFFE":"1f3fe","\uD83C\uDFFF":"1f3ff","\uD83D\uDE43":"1f643","\uD83E\uDD11":"1f911","\uD83E\uDD13":"1f913","\uD83E\uDD17":"1f917","\uD83D\uDE44":"1f644","\uD83E\uDD14":"1f914","\uD83E\uDD10":"1f910","\uD83E\uDD12":"1f912","\uD83E\uDD15":"1f915","\uD83E\uDD16":"1f916","\uD83E\uDD81":"1f981","\uD83E\uDD84":"1f984","\uD83E\uDD82":"1f982","\uD83E\uDD80":"1f980","\uD83E\uDD83":"1f983","\uD83E\uDDC0":"1f9c0","\uD83C\uDF2D":"1f32d","\uD83C\uDF2E":"1f32e","\uD83C\uDF2F":"1f32f","\uD83C\uDF7F":"1f37f","\uD83C\uDF7E":"1f37e","\uD83C\uDFF9":"1f3f9","\uD83C\uDFFA":"1f3fa","\uD83D\uDED0":"1f6d0","\uD83D\uDD4B":"1f54b","\uD83D\uDD4C":"1f54c","\uD83D\uDD4D":"1f54d","\uD83D\uDD4E":"1f54e","\uD83D\uDCFF":"1f4ff","\uD83C\uDFCF":"1f3cf","\uD83C\uDFD0":"1f3d0","\uD83C\uDFD1":"1f3d1","\uD83C\uDFD2":"1f3d2","\uD83C\uDFD3":"1f3d3","\uD83C\uDFF8":"1f3f8","\uD83E\uDD41":"1f941","\uD83E\uDD90":"1f990","\uD83E\uDD91":"1f991","\uD83E\uDD5A":"1f95a","\uD83E\uDD5B":"1f95b","\uD83E\uDD5C":"1f95c","\uD83E\uDD5D":"1f95d","\uD83E\uDD5E":"1f95e","\uD83C\uDDFC":"1f1fc","\uD83C\uDDFB":"1f1fb","\uD83C\uDDFA":"1f1fa","\uD83C\uDDF9":"1f1f9","\uD83C\uDDF8":"1f1f8","\uD83C\uDDF7":"1f1f7","\uD83C\uDDF6":"1f1f6","\uD83C\uDDF5":"1f1f5","\uD83C\uDDF4":"1f1f4","\uD83C\uDDF3":"1f1f3","\uD83C\uDDF2":"1f1f2","\uD83C\uDDF1":"1f1f1","\uD83C\uDDF0":"1f1f0","\uD83C\uDDEF":"1f1ef","\uD83C\uDDEE":"1f1ee","\uD83C\uDDED":"1f1ed","\uD83C\uDDEC":"1f1ec","\uD83C\uDDEB":"1f1eb","\uD83C\uDDEA":"1f1ea","\uD83C\uDDE9":"1f1e9","\uD83C\uDDE8":"1f1e8","\uD83C\uDDE7":"1f1e7","\uD83C\uDDE6":"1f1e6","\uD83D\uDEF7":"1f6f7","\uD83D\uDEF8":"1f6f8","\uD83E\uDD1F":"1f91f","\uD83E\uDD28":"1f928","\uD83E\uDD29":"1f929","\uD83E\uDD2A":"1f92a","\uD83E\uDD2B":"1f92b","\uD83E\uDD2C":"1f92c","\uD83E\uDD2D":"1f92d","\uD83E\uDD2E":"1f92e","\uD83E\uDD2F":"1f92f","\uD83E\uDD31":"1f931","\uD83E\uDD32":"1f932","\uD83E\uDD4C":"1f94c","\uD83E\uDD5F":"1f95f","\uD83E\uDD60":"1f960","\uD83E\uDD61":"1f961","\uD83E\uDD62":"1f962","\uD83E\uDD63":"1f963","\uD83E\uDD64":"1f964","\uD83E\uDD65":"1f965","\uD83E\uDD66":"1f966","\uD83E\uDD67":"1f967","\uD83E\uDD68":"1f968","\uD83E\uDD69":"1f969","\uD83E\uDD6A":"1f96a","\uD83E\uDD6B":"1f96b","\uD83E\uDD92":"1f992","\uD83E\uDD93":"1f993","\uD83E\uDD94":"1f994","\uD83E\uDD95":"1f995","\uD83E\uDD96":"1f996","\uD83E\uDD97":"1f997","\uD83E\uDDD0":"1f9d0","\uD83E\uDDD1":"1f9d1","\uD83E\uDDD2":"1f9d2","\uD83E\uDDD3":"1f9d3","\uD83E\uDDD4":"1f9d4","\uD83E\uDDD5":"1f9d5","\uD83E\uDDD6":"1f9d6","\uD83E\uDDD7":"1f9d7","\uD83E\uDDD8":"1f9d8","\uD83E\uDDD9":"1f9d9","\uD83E\uDDDA":"1f9da","\uD83E\uDDDB":"1f9db","\uD83E\uDDDC":"1f9dc","\uD83E\uDDDD":"1f9dd","\uD83E\uDDDE":"1f9de","\uD83E\uDDDF":"1f9df","\uD83E\uDDE0":"1f9e0","\uD83E\uDDE1":"1f9e1","\uD83E\uDDE2":"1f9e2","\uD83E\uDDE3":"1f9e3","\uD83E\uDDE4":"1f9e4","\uD83E\uDDE5":"1f9e5","\uD83E\uDDE6":"1f9e6","\u231A":"231a","\u231B":"231b","\u23E9":"23e9","\u23EA":"23ea","\u23EB":"23eb","\u23EC":"23ec","\u23F0":"23f0","\u23F3":"23f3","\u25FD":"25fd","\u25FE":"25fe","\u2614":"2614","\u2615":"2615","\u2648":"2648","\u2649":"2649","\u264A":"264a","\u264B":"264b","\u264C":"264c","\u264D":"264d","\u264E":"264e","\u264F":"264f","\u2650":"2650","\u2651":"2651","\u2652":"2652","\u2653":"2653","\u267F":"267f","\u2693":"2693","\u26A1":"26a1","\u26AA":"26aa","\u26AB":"26ab","\u26BD":"26bd","\u26BE":"26be","\u26C4":"26c4","\u26C5":"26c5","\u26CE":"26ce","\u26D4":"26d4","\u26EA":"26ea","\u26F2":"26f2","\u26F3":"26f3","\u26F5":"26f5","\u26FA":"26fa","\u26FD":"26fd","\u2705":"2705","\u270A":"270a","\u270B":"270b","\u2728":"2728","\u274C":"274c","\u274E":"274e","\u2753":"2753","\u2754":"2754","\u2755":"2755","\u2757":"2757","\u2795":"2795","\u2796":"2796","\u2797":"2797","\u27B0":"27b0","\u2B1B":"2b1b","\u2B1C":"2b1c","\u2B50":"2b50","\u2B55":"2b55","\u27BF":"27bf"};
  7894. ns.jsEscapeMapGreedy = {"\uD83D\uDC69\u2764\uD83D\uDC8B\uD83D\uDC69":"1f469-2764-1f48b-1f469","\uD83D\uDC68\u2764\uD83D\uDC8B\uD83D\uDC68":"1f468-2764-1f48b-1f468","\uD83D\uDC69\u2764\uD83D\uDC8B\uD83D\uDC68":"1f469-2764-1f48b-1f468","\uD83D\uDC69\u2764\uD83D\uDC69":"1f469-2764-1f469","\uD83D\uDC68\u2764\uD83D\uDC68":"1f468-2764-1f468","\uD83C\uDFCC\uD83C\uDFFB\u2642":"1f3cc-1f3fb-2642","\uD83C\uDFCC\uD83C\uDFFC\u2642":"1f3cc-1f3fc-2642","\uD83C\uDFCC\uD83C\uDFFD\u2642":"1f3cc-1f3fd-2642","\uD83C\uDFCC\uD83C\uDFFE\u2642":"1f3cc-1f3fe-2642","\uD83C\uDFCC\uD83C\uDFFF\u2642":"1f3cc-1f3ff-2642","\uD83C\uDFCC\uD83C\uDFFB\u2640":"1f3cc-1f3fb-2640","\uD83C\uDFCC\uD83C\uDFFC\u2640":"1f3cc-1f3fc-2640","\uD83C\uDFCC\uD83C\uDFFD\u2640":"1f3cc-1f3fd-2640","\uD83C\uDFCC\uD83C\uDFFE\u2640":"1f3cc-1f3fe-2640","\uD83C\uDFCC\uD83C\uDFFF\u2640":"1f3cc-1f3ff-2640","\uD83D\uDC68\uD83C\uDFFB\u2696":"1f468-1f3fb-2696","\uD83D\uDC68\uD83C\uDFFC\u2696":"1f468-1f3fc-2696","\uD83D\uDC68\uD83C\uDFFD\u2696":"1f468-1f3fd-2696","\uD83D\uDC68\uD83C\uDFFE\u2696":"1f468-1f3fe-2696","\uD83D\uDC68\uD83C\uDFFF\u2696":"1f468-1f3ff-2696","\uD83D\uDC69\uD83C\uDFFB\u2696":"1f469-1f3fb-2696","\uD83D\uDC69\uD83C\uDFFC\u2696":"1f469-1f3fc-2696","\uD83D\uDC69\uD83C\uDFFD\u2696":"1f469-1f3fd-2696","\uD83D\uDC69\uD83C\uDFFE\u2696":"1f469-1f3fe-2696","\uD83D\uDC69\uD83C\uDFFF\u2696":"1f469-1f3ff-2696","\uD83D\uDC68\uD83C\uDFFB\u2708":"1f468-1f3fb-2708","\uD83D\uDC68\uD83C\uDFFC\u2708":"1f468-1f3fc-2708","\uD83D\uDC68\uD83C\uDFFD\u2708":"1f468-1f3fd-2708","\uD83D\uDC68\uD83C\uDFFE\u2708":"1f468-1f3fe-2708","\uD83D\uDC68\uD83C\uDFFF\u2708":"1f468-1f3ff-2708","\uD83D\uDC69\uD83C\uDFFB\u2708":"1f469-1f3fb-2708","\uD83D\uDC69\uD83C\uDFFC\u2708":"1f469-1f3fc-2708","\uD83D\uDC69\uD83C\uDFFD\u2708":"1f469-1f3fd-2708","\uD83D\uDC69\uD83C\uDFFE\u2708":"1f469-1f3fe-2708","\uD83D\uDC69\uD83C\uDFFF\u2708":"1f469-1f3ff-2708","\uD83D\uDC69\u2764\uD83D\uDC68":"1f469-2764-1f468","\uD83D\uDC68\uD83C\uDFFB\u2695":"1f468-1f3fb-2695","\uD83D\uDC68\uD83C\uDFFC\u2695":"1f468-1f3fc-2695","\uD83D\uDC68\uD83C\uDFFD\u2695":"1f468-1f3fd-2695","\uD83D\uDC68\uD83C\uDFFE\u2695":"1f468-1f3fe-2695","\uD83D\uDC68\uD83C\uDFFF\u2695":"1f468-1f3ff-2695","\uD83D\uDC69\uD83C\uDFFB\u2695":"1f469-1f3fb-2695","\uD83D\uDC69\uD83C\uDFFC\u2695":"1f469-1f3fc-2695","\uD83D\uDC69\uD83C\uDFFD\u2695":"1f469-1f3fd-2695","\uD83D\uDC69\uD83C\uDFFE\u2695":"1f469-1f3fe-2695","\uD83D\uDC69\uD83C\uDFFF\u2695":"1f469-1f3ff-2695","\uD83D\uDC6E\uD83C\uDFFB\u2640":"1f46e-1f3fb-2640","\uD83D\uDC6E\uD83C\uDFFB\u2642":"1f46e-1f3fb-2642","\uD83D\uDC6E\uD83C\uDFFC\u2640":"1f46e-1f3fc-2640","\uD83D\uDC6E\uD83C\uDFFC\u2642":"1f46e-1f3fc-2642","\uD83D\uDC6E\uD83C\uDFFD\u2640":"1f46e-1f3fd-2640","\uD83D\uDC6E\uD83C\uDFFD\u2642":"1f46e-1f3fd-2642","\uD83D\uDC6E\uD83C\uDFFE\u2640":"1f46e-1f3fe-2640","\uD83D\uDC6E\uD83C\uDFFE\u2642":"1f46e-1f3fe-2642","\uD83D\uDC6E\uD83C\uDFFF\u2640":"1f46e-1f3ff-2640","\uD83D\uDC6E\uD83C\uDFFF\u2642":"1f46e-1f3ff-2642","\uD83D\uDC71\uD83C\uDFFB\u2640":"1f471-1f3fb-2640","\uD83D\uDC71\uD83C\uDFFB\u2642":"1f471-1f3fb-2642","\uD83D\uDC71\uD83C\uDFFC\u2640":"1f471-1f3fc-2640","\uD83D\uDC71\uD83C\uDFFC\u2642":"1f471-1f3fc-2642","\uD83D\uDC71\uD83C\uDFFD\u2640":"1f471-1f3fd-2640","\uD83D\uDC71\uD83C\uDFFD\u2642":"1f471-1f3fd-2642","\uD83D\uDC71\uD83C\uDFFE\u2640":"1f471-1f3fe-2640","\uD83D\uDC71\uD83C\uDFFE\u2642":"1f471-1f3fe-2642","\uD83D\uDC71\uD83C\uDFFF\u2640":"1f471-1f3ff-2640","\uD83D\uDC71\uD83C\uDFFF\u2642":"1f471-1f3ff-2642","\uD83D\uDC73\uD83C\uDFFB\u2640":"1f473-1f3fb-2640","\uD83D\uDC73\uD83C\uDFFB\u2642":"1f473-1f3fb-2642","\uD83D\uDC73\uD83C\uDFFC\u2640":"1f473-1f3fc-2640","\uD83D\uDC73\uD83C\uDFFC\u2642":"1f473-1f3fc-2642","\uD83D\uDC73\uD83C\uDFFD\u2640":"1f473-1f3fd-2640","\uD83D\uDC73\uD83C\uDFFD\u2642":"1f473-1f3fd-2642","\uD83D\uDC73\uD83C\uDFFE\u2640":"1f473-1f3fe-2640","\uD83D\uDC73\uD83C\uDFFE\u2642":"1f473-1f3fe-2642","\uD83D\uDC73\uD83C\uDFFF\u2640":"1f473-1f3ff-2640","\uD83D\uDC73\uD83C\uDFFF\u2642":"1f473-1f3ff-2642","\uD83D\uDC77\uD83C\uDFFB\u2640":"1f477-1f3fb-2640","\uD83D\uDC77\uD83C\uDFFB\u2642":"1f477-1f3fb-2642","\uD83D\uDC77\uD83C\uDFFC\u2640":"1f477-1f3fc-2640","\uD83D\uDC77\uD83C\uDFFC\u2642":"1f477-1f3fc-2642","\uD83D\uDC77\uD83C\uDFFD\u2640":"1f477-1f3fd-2640","\uD83D\uDC77\uD83C\uDFFD\u2642":"1f477-1f3fd-2642","\uD83D\uDC77\uD83C\uDFFE\u2640":"1f477-1f3fe-2640","\uD83D\uDC77\uD83C\uDFFE\u2642":"1f477-1f3fe-2642","\uD83D\uDC77\uD83C\uDFFF\u2640":"1f477-1f3ff-2640","\uD83D\uDC77\uD83C\uDFFF\u2642":"1f477-1f3ff-2642","\uD83D\uDC82\uD83C\uDFFB\u2640":"1f482-1f3fb-2640","\uD83D\uDC82\uD83C\uDFFB\u2642":"1f482-1f3fb-2642","\uD83D\uDC82\uD83C\uDFFC\u2640":"1f482-1f3fc-2640","\uD83D\uDC82\uD83C\uDFFC\u2642":"1f482-1f3fc-2642","\uD83D\uDC82\uD83C\uDFFD\u2640":"1f482-1f3fd-2640","\uD83D\uDC82\uD83C\uDFFD\u2642":"1f482-1f3fd-2642","\uD83D\uDC82\uD83C\uDFFE\u2640":"1f482-1f3fe-2640","\uD83D\uDC82\uD83C\uDFFE\u2642":"1f482-1f3fe-2642","\uD83D\uDC82\uD83C\uDFFF\u2640":"1f482-1f3ff-2640","\uD83D\uDC82\uD83C\uDFFF\u2642":"1f482-1f3ff-2642","\uD83D\uDD75\uD83C\uDFFB\u2640":"1f575-1f3fb-2640","\uD83D\uDD75\uD83C\uDFFB\u2642":"1f575-1f3fb-2642","\uD83D\uDD75\uD83C\uDFFC\u2640":"1f575-1f3fc-2640","\uD83D\uDD75\uD83C\uDFFC\u2642":"1f575-1f3fc-2642","\uD83D\uDD75\uD83C\uDFFD\u2640":"1f575-1f3fd-2640","\uD83D\uDD75\uD83C\uDFFD\u2642":"1f575-1f3fd-2642","\uD83D\uDD75\uD83C\uDFFE\u2640":"1f575-1f3fe-2640","\uD83D\uDD75\uD83C\uDFFE\u2642":"1f575-1f3fe-2642","\uD83D\uDD75\uD83C\uDFFF\u2640":"1f575-1f3ff-2640","\uD83D\uDD75\uD83C\uDFFF\u2642":"1f575-1f3ff-2642","\uD83C\uDFC3\uD83C\uDFFB\u2640":"1f3c3-1f3fb-2640","\uD83C\uDFC3\uD83C\uDFFB\u2642":"1f3c3-1f3fb-2642","\uD83C\uDFC3\uD83C\uDFFC\u2640":"1f3c3-1f3fc-2640","\uD83C\uDFC3\uD83C\uDFFC\u2642":"1f3c3-1f3fc-2642","\uD83C\uDFC3\uD83C\uDFFD\u2640":"1f3c3-1f3fd-2640","\uD83C\uDFC3\uD83C\uDFFD\u2642":"1f3c3-1f3fd-2642","\uD83C\uDFC3\uD83C\uDFFE\u2640":"1f3c3-1f3fe-2640","\uD83C\uDFC3\uD83C\uDFFE\u2642":"1f3c3-1f3fe-2642","\uD83C\uDFC3\uD83C\uDFFF\u2640":"1f3c3-1f3ff-2640","\uD83C\uDFC3\uD83C\uDFFF\u2642":"1f3c3-1f3ff-2642","\uD83C\uDFC4\uD83C\uDFFB\u2640":"1f3c4-1f3fb-2640","\uD83C\uDFC4\uD83C\uDFFB\u2642":"1f3c4-1f3fb-2642","\uD83C\uDFC4\uD83C\uDFFC\u2640":"1f3c4-1f3fc-2640","\uD83C\uDFC4\uD83C\uDFFC\u2642":"1f3c4-1f3fc-2642","\uD83C\uDFC4\uD83C\uDFFD\u2640":"1f3c4-1f3fd-2640","\uD83C\uDFC4\uD83C\uDFFD\u2642":"1f3c4-1f3fd-2642","\uD83C\uDFC4\uD83C\uDFFE\u2640":"1f3c4-1f3fe-2640","\uD83C\uDFC4\uD83C\uDFFE\u2642":"1f3c4-1f3fe-2642","\uD83C\uDFC4\uD83C\uDFFF\u2640":"1f3c4-1f3ff-2640","\uD83C\uDFC4\uD83C\uDFFF\u2642":"1f3c4-1f3ff-2642","\uD83C\uDFCA\uD83C\uDFFB\u2640":"1f3ca-1f3fb-2640","\uD83C\uDFCA\uD83C\uDFFB\u2642":"1f3ca-1f3fb-2642","\uD83C\uDFCA\uD83C\uDFFC\u2640":"1f3ca-1f3fc-2640","\uD83C\uDFCA\uD83C\uDFFC\u2642":"1f3ca-1f3fc-2642","\uD83C\uDFCA\uD83C\uDFFD\u2640":"1f3ca-1f3fd-2640","\uD83C\uDFCA\uD83C\uDFFD\u2642":"1f3ca-1f3fd-2642","\uD83C\uDFCA\uD83C\uDFFE\u2640":"1f3ca-1f3fe-2640","\uD83C\uDFCA\uD83C\uDFFE\u2642":"1f3ca-1f3fe-2642","\uD83C\uDFCA\uD83C\uDFFF\u2640":"1f3ca-1f3ff-2640","\uD83C\uDFCA\uD83C\uDFFF\u2642":"1f3ca-1f3ff-2642","\uD83C\uDFCB\uD83C\uDFFB\u2640":"1f3cb-1f3fb-2640","\uD83C\uDFCB\uD83C\uDFFB\u2642":"1f3cb-1f3fb-2642","\uD83C\uDFCB\uD83C\uDFFC\u2640":"1f3cb-1f3fc-2640","\uD83C\uDFCB\uD83C\uDFFC\u2642":"1f3cb-1f3fc-2642","\uD83C\uDFCB\uD83C\uDFFD\u2640":"1f3cb-1f3fd-2640","\uD83C\uDFCB\uD83C\uDFFD\u2642":"1f3cb-1f3fd-2642","\uD83C\uDFCB\uD83C\uDFFE\u2640":"1f3cb-1f3fe-2640","\uD83C\uDFCB\uD83C\uDFFE\u2642":"1f3cb-1f3fe-2642","\uD83C\uDFCB\uD83C\uDFFF\u2640":"1f3cb-1f3ff-2640","\uD83C\uDFCB\uD83C\uDFFF\u2642":"1f3cb-1f3ff-2642","\uD83D\uDC86\uD83C\uDFFB\u2640":"1f486-1f3fb-2640","\uD83D\uDC86\uD83C\uDFFB\u2642":"1f486-1f3fb-2642","\uD83D\uDC86\uD83C\uDFFC\u2640":"1f486-1f3fc-2640","\uD83D\uDC86\uD83C\uDFFC\u2642":"1f486-1f3fc-2642","\uD83D\uDC86\uD83C\uDFFD\u2640":"1f486-1f3fd-2640","\uD83D\uDC86\uD83C\uDFFD\u2642":"1f486-1f3fd-2642","\uD83D\uDC86\uD83C\uDFFE\u2640":"1f486-1f3fe-2640","\uD83D\uDC86\uD83C\uDFFE\u2642":"1f486-1f3fe-2642","\uD83D\uDC86\uD83C\uDFFF\u2640":"1f486-1f3ff-2640","\uD83D\uDC86\uD83C\uDFFF\u2642":"1f486-1f3ff-2642","\uD83D\uDC87\uD83C\uDFFB\u2640":"1f487-1f3fb-2640","\uD83D\uDC87\uD83C\uDFFB\u2642":"1f487-1f3fb-2642","\uD83D\uDC87\uD83C\uDFFC\u2640":"1f487-1f3fc-2640","\uD83D\uDC87\uD83C\uDFFC\u2642":"1f487-1f3fc-2642","\uD83D\uDC87\uD83C\uDFFD\u2640":"1f487-1f3fd-2640","\uD83D\uDC87\uD83C\uDFFD\u2642":"1f487-1f3fd-2642","\uD83D\uDC87\uD83C\uDFFE\u2640":"1f487-1f3fe-2640","\uD83D\uDC87\uD83C\uDFFE\u2642":"1f487-1f3fe-2642","\uD83D\uDC87\uD83C\uDFFF\u2640":"1f487-1f3ff-2640","\uD83D\uDC87\uD83C\uDFFF\u2642":"1f487-1f3ff-2642","\uD83D\uDEA3\uD83C\uDFFB\u2640":"1f6a3-1f3fb-2640","\uD83D\uDEA3\uD83C\uDFFB\u2642":"1f6a3-1f3fb-2642","\uD83D\uDEA3\uD83C\uDFFC\u2640":"1f6a3-1f3fc-2640","\uD83D\uDEA3\uD83C\uDFFC\u2642":"1f6a3-1f3fc-2642","\uD83D\uDEA3\uD83C\uDFFD\u2640":"1f6a3-1f3fd-2640","\uD83D\uDEA3\uD83C\uDFFD\u2642":"1f6a3-1f3fd-2642","\uD83D\uDEA3\uD83C\uDFFE\u2640":"1f6a3-1f3fe-2640","\uD83D\uDEA3\uD83C\uDFFE\u2642":"1f6a3-1f3fe-2642","\uD83D\uDEA3\uD83C\uDFFF\u2640":"1f6a3-1f3ff-2640","\uD83D\uDEA3\uD83C\uDFFF\u2642":"1f6a3-1f3ff-2642","\uD83D\uDEB4\uD83C\uDFFB\u2640":"1f6b4-1f3fb-2640","\uD83D\uDEB4\uD83C\uDFFB\u2642":"1f6b4-1f3fb-2642","\uD83D\uDEB4\uD83C\uDFFC\u2640":"1f6b4-1f3fc-2640","\uD83D\uDEB4\uD83C\uDFFC\u2642":"1f6b4-1f3fc-2642","\uD83D\uDEB4\uD83C\uDFFD\u2640":"1f6b4-1f3fd-2640","\uD83D\uDEB4\uD83C\uDFFD\u2642":"1f6b4-1f3fd-2642","\uD83D\uDEB4\uD83C\uDFFE\u2640":"1f6b4-1f3fe-2640","\uD83D\uDEB4\uD83C\uDFFE\u2642":"1f6b4-1f3fe-2642","\uD83D\uDEB4\uD83C\uDFFF\u2640":"1f6b4-1f3ff-2640","\uD83D\uDEB4\uD83C\uDFFF\u2642":"1f6b4-1f3ff-2642","\uD83D\uDEB5\uD83C\uDFFB\u2640":"1f6b5-1f3fb-2640","\uD83D\uDEB5\uD83C\uDFFB\u2642":"1f6b5-1f3fb-2642","\uD83D\uDEB5\uD83C\uDFFC\u2640":"1f6b5-1f3fc-2640","\uD83D\uDEB5\uD83C\uDFFC\u2642":"1f6b5-1f3fc-2642","\uD83D\uDEB5\uD83C\uDFFD\u2640":"1f6b5-1f3fd-2640","\uD83D\uDEB5\uD83C\uDFFD\u2642":"1f6b5-1f3fd-2642","\uD83D\uDEB5\uD83C\uDFFE\u2640":"1f6b5-1f3fe-2640","\uD83D\uDEB5\uD83C\uDFFE\u2642":"1f6b5-1f3fe-2642","\uD83D\uDEB5\uD83C\uDFFF\u2640":"1f6b5-1f3ff-2640","\uD83D\uDEB5\uD83C\uDFFF\u2642":"1f6b5-1f3ff-2642","\uD83D\uDEB6\uD83C\uDFFB\u2640":"1f6b6-1f3fb-2640","\uD83D\uDEB6\uD83C\uDFFB\u2642":"1f6b6-1f3fb-2642","\uD83D\uDEB6\uD83C\uDFFC\u2640":"1f6b6-1f3fc-2640","\uD83D\uDEB6\uD83C\uDFFC\u2642":"1f6b6-1f3fc-2642","\uD83D\uDEB6\uD83C\uDFFD\u2640":"1f6b6-1f3fd-2640","\uD83D\uDEB6\uD83C\uDFFD\u2642":"1f6b6-1f3fd-2642","\uD83D\uDEB6\uD83C\uDFFE\u2640":"1f6b6-1f3fe-2640","\uD83D\uDEB6\uD83C\uDFFE\u2642":"1f6b6-1f3fe-2642","\uD83D\uDEB6\uD83C\uDFFF\u2640":"1f6b6-1f3ff-2640","\uD83D\uDEB6\uD83C\uDFFF\u2642":"1f6b6-1f3ff-2642","\uD83E\uDD38\uD83C\uDFFB\u2640":"1f938-1f3fb-2640","\uD83E\uDD38\uD83C\uDFFB\u2642":"1f938-1f3fb-2642","\uD83E\uDD38\uD83C\uDFFC\u2640":"1f938-1f3fc-2640","\uD83E\uDD38\uD83C\uDFFC\u2642":"1f938-1f3fc-2642","\uD83E\uDD38\uD83C\uDFFD\u2640":"1f938-1f3fd-2640","\uD83E\uDD38\uD83C\uDFFD\u2642":"1f938-1f3fd-2642","\uD83E\uDD38\uD83C\uDFFE\u2640":"1f938-1f3fe-2640","\uD83E\uDD38\uD83C\uDFFE\u2642":"1f938-1f3fe-2642","\uD83E\uDD38\uD83C\uDFFF\u2640":"1f938-1f3ff-2640","\uD83E\uDD38\uD83C\uDFFF\u2642":"1f938-1f3ff-2642","\uD83E\uDD39\uD83C\uDFFB\u2640":"1f939-1f3fb-2640","\uD83E\uDD39\uD83C\uDFFB\u2642":"1f939-1f3fb-2642","\uD83E\uDD39\uD83C\uDFFC\u2640":"1f939-1f3fc-2640","\uD83E\uDD39\uD83C\uDFFC\u2642":"1f939-1f3fc-2642","\uD83E\uDD39\uD83C\uDFFD\u2640":"1f939-1f3fd-2640","\uD83E\uDD39\uD83C\uDFFD\u2642":"1f939-1f3fd-2642","\uD83E\uDD39\uD83C\uDFFE\u2640":"1f939-1f3fe-2640","\uD83E\uDD39\uD83C\uDFFE\u2642":"1f939-1f3fe-2642","\uD83E\uDD39\uD83C\uDFFF\u2640":"1f939-1f3ff-2640","\uD83E\uDD39\uD83C\uDFFF\u2642":"1f939-1f3ff-2642","\uD83E\uDD3D\uD83C\uDFFB\u2640":"1f93d-1f3fb-2640","\uD83E\uDD3D\uD83C\uDFFB\u2642":"1f93d-1f3fb-2642","\uD83E\uDD3D\uD83C\uDFFC\u2640":"1f93d-1f3fc-2640","\uD83E\uDD3D\uD83C\uDFFC\u2642":"1f93d-1f3fc-2642","\uD83E\uDD3D\uD83C\uDFFD\u2640":"1f93d-1f3fd-2640","\uD83E\uDD3D\uD83C\uDFFD\u2642":"1f93d-1f3fd-2642","\uD83E\uDD3D\uD83C\uDFFE\u2640":"1f93d-1f3fe-2640","\uD83E\uDD3D\uD83C\uDFFE\u2642":"1f93d-1f3fe-2642","\uD83E\uDD3D\uD83C\uDFFF\u2640":"1f93d-1f3ff-2640","\uD83E\uDD3D\uD83C\uDFFF\u2642":"1f93d-1f3ff-2642","\uD83E\uDD3E\uD83C\uDFFB\u2640":"1f93e-1f3fb-2640","\uD83E\uDD3E\uD83C\uDFFB\u2642":"1f93e-1f3fb-2642","\uD83E\uDD3E\uD83C\uDFFC\u2640":"1f93e-1f3fc-2640","\uD83E\uDD3E\uD83C\uDFFC\u2642":"1f93e-1f3fc-2642","\uD83E\uDD3E\uD83C\uDFFD\u2640":"1f93e-1f3fd-2640","\uD83E\uDD3E\uD83C\uDFFD\u2642":"1f93e-1f3fd-2642","\uD83E\uDD3E\uD83C\uDFFE\u2640":"1f93e-1f3fe-2640","\uD83E\uDD3E\uD83C\uDFFE\u2642":"1f93e-1f3fe-2642","\uD83E\uDD3E\uD83C\uDFFF\u2640":"1f93e-1f3ff-2640","\uD83E\uDD3E\uD83C\uDFFF\u2642":"1f93e-1f3ff-2642","\uD83D\uDC81\uD83C\uDFFB\u2640":"1f481-1f3fb-2640","\uD83D\uDC81\uD83C\uDFFB\u2642":"1f481-1f3fb-2642","\uD83D\uDC81\uD83C\uDFFC\u2640":"1f481-1f3fc-2640","\uD83D\uDC81\uD83C\uDFFC\u2642":"1f481-1f3fc-2642","\uD83D\uDC81\uD83C\uDFFD\u2640":"1f481-1f3fd-2640","\uD83D\uDC81\uD83C\uDFFD\u2642":"1f481-1f3fd-2642","\uD83D\uDC81\uD83C\uDFFE\u2640":"1f481-1f3fe-2640","\uD83D\uDC81\uD83C\uDFFE\u2642":"1f481-1f3fe-2642","\uD83D\uDC81\uD83C\uDFFF\u2640":"1f481-1f3ff-2640","\uD83D\uDC81\uD83C\uDFFF\u2642":"1f481-1f3ff-2642","\uD83D\uDE45\uD83C\uDFFB\u2640":"1f645-1f3fb-2640","\uD83D\uDE45\uD83C\uDFFB\u2642":"1f645-1f3fb-2642","\uD83D\uDE45\uD83C\uDFFC\u2640":"1f645-1f3fc-2640","\uD83D\uDE45\uD83C\uDFFC\u2642":"1f645-1f3fc-2642","\uD83D\uDE45\uD83C\uDFFD\u2640":"1f645-1f3fd-2640","\uD83D\uDE45\uD83C\uDFFD\u2642":"1f645-1f3fd-2642","\uD83D\uDE45\uD83C\uDFFE\u2640":"1f645-1f3fe-2640","\uD83D\uDE45\uD83C\uDFFE\u2642":"1f645-1f3fe-2642","\uD83D\uDE45\uD83C\uDFFF\u2640":"1f645-1f3ff-2640","\uD83D\uDE45\uD83C\uDFFF\u2642":"1f645-1f3ff-2642","\uD83D\uDE46\uD83C\uDFFB\u2640":"1f646-1f3fb-2640","\uD83D\uDE46\uD83C\uDFFB\u2642":"1f646-1f3fb-2642","\uD83D\uDE46\uD83C\uDFFC\u2640":"1f646-1f3fc-2640","\uD83D\uDE46\uD83C\uDFFC\u2642":"1f646-1f3fc-2642","\uD83D\uDE46\uD83C\uDFFD\u2640":"1f646-1f3fd-2640","\uD83D\uDE46\uD83C\uDFFD\u2642":"1f646-1f3fd-2642","\uD83D\uDE46\uD83C\uDFFE\u2640":"1f646-1f3fe-2640","\uD83D\uDE46\uD83C\uDFFE\u2642":"1f646-1f3fe-2642","\uD83D\uDE46\uD83C\uDFFF\u2640":"1f646-1f3ff-2640","\uD83D\uDE46\uD83C\uDFFF\u2642":"1f646-1f3ff-2642","\uD83D\uDE47\uD83C\uDFFB\u2640":"1f647-1f3fb-2640","\uD83D\uDE47\uD83C\uDFFB\u2642":"1f647-1f3fb-2642","\uD83D\uDE47\uD83C\uDFFC\u2640":"1f647-1f3fc-2640","\uD83D\uDE47\uD83C\uDFFC\u2642":"1f647-1f3fc-2642","\uD83D\uDE47\uD83C\uDFFD\u2640":"1f647-1f3fd-2640","\uD83D\uDE47\uD83C\uDFFD\u2642":"1f647-1f3fd-2642","\uD83D\uDE47\uD83C\uDFFE\u2640":"1f647-1f3fe-2640","\uD83D\uDE47\uD83C\uDFFE\u2642":"1f647-1f3fe-2642","\uD83D\uDE47\uD83C\uDFFF\u2640":"1f647-1f3ff-2640","\uD83D\uDE47\uD83C\uDFFF\u2642":"1f647-1f3ff-2642","\uD83D\uDE4B\uD83C\uDFFB\u2640":"1f64b-1f3fb-2640","\uD83D\uDE4B\uD83C\uDFFB\u2642":"1f64b-1f3fb-2642","\uD83D\uDE4B\uD83C\uDFFC\u2640":"1f64b-1f3fc-2640","\uD83D\uDE4B\uD83C\uDFFC\u2642":"1f64b-1f3fc-2642","\uD83D\uDE4B\uD83C\uDFFD\u2640":"1f64b-1f3fd-2640","\uD83D\uDE4B\uD83C\uDFFD\u2642":"1f64b-1f3fd-2642","\uD83D\uDE4B\uD83C\uDFFE\u2640":"1f64b-1f3fe-2640","\uD83D\uDE4B\uD83C\uDFFE\u2642":"1f64b-1f3fe-2642","\uD83D\uDE4B\uD83C\uDFFF\u2640":"1f64b-1f3ff-2640","\uD83D\uDE4B\uD83C\uDFFF\u2642":"1f64b-1f3ff-2642","\uD83D\uDE4D\uD83C\uDFFB\u2640":"1f64d-1f3fb-2640","\uD83D\uDE4D\uD83C\uDFFB\u2642":"1f64d-1f3fb-2642","\uD83D\uDE4D\uD83C\uDFFC\u2640":"1f64d-1f3fc-2640","\uD83D\uDE4D\uD83C\uDFFC\u2642":"1f64d-1f3fc-2642","\uD83D\uDE4D\uD83C\uDFFD\u2640":"1f64d-1f3fd-2640","\uD83D\uDE4D\uD83C\uDFFD\u2642":"1f64d-1f3fd-2642","\uD83D\uDE4D\uD83C\uDFFE\u2640":"1f64d-1f3fe-2640","\uD83D\uDE4D\uD83C\uDFFE\u2642":"1f64d-1f3fe-2642","\uD83D\uDE4D\uD83C\uDFFF\u2640":"1f64d-1f3ff-2640","\uD83D\uDE4D\uD83C\uDFFF\u2642":"1f64d-1f3ff-2642","\uD83D\uDE4E\uD83C\uDFFB\u2640":"1f64e-1f3fb-2640","\uD83D\uDE4E\uD83C\uDFFB\u2642":"1f64e-1f3fb-2642","\uD83D\uDE4E\uD83C\uDFFC\u2640":"1f64e-1f3fc-2640","\uD83D\uDE4E\uD83C\uDFFC\u2642":"1f64e-1f3fc-2642","\uD83D\uDE4E\uD83C\uDFFD\u2640":"1f64e-1f3fd-2640","\uD83D\uDE4E\uD83C\uDFFD\u2642":"1f64e-1f3fd-2642","\uD83D\uDE4E\uD83C\uDFFE\u2640":"1f64e-1f3fe-2640","\uD83D\uDE4E\uD83C\uDFFE\u2642":"1f64e-1f3fe-2642","\uD83D\uDE4E\uD83C\uDFFF\u2640":"1f64e-1f3ff-2640","\uD83D\uDE4E\uD83C\uDFFF\u2642":"1f64e-1f3ff-2642","\uD83E\uDD26\uD83C\uDFFB\u2640":"1f926-1f3fb-2640","\uD83E\uDD26\uD83C\uDFFB\u2642":"1f926-1f3fb-2642","\uD83E\uDD26\uD83C\uDFFC\u2640":"1f926-1f3fc-2640","\uD83E\uDD26\uD83C\uDFFC\u2642":"1f926-1f3fc-2642","\uD83E\uDD26\uD83C\uDFFD\u2640":"1f926-1f3fd-2640","\uD83E\uDD26\uD83C\uDFFD\u2642":"1f926-1f3fd-2642","\uD83E\uDD26\uD83C\uDFFE\u2640":"1f926-1f3fe-2640","\uD83E\uDD26\uD83C\uDFFE\u2642":"1f926-1f3fe-2642","\uD83E\uDD26\uD83C\uDFFF\u2640":"1f926-1f3ff-2640","\uD83E\uDD26\uD83C\uDFFF\u2642":"1f926-1f3ff-2642","\uD83E\uDD37\uD83C\uDFFB\u2640":"1f937-1f3fb-2640","\uD83E\uDD37\uD83C\uDFFB\u2642":"1f937-1f3fb-2642","\uD83E\uDD37\uD83C\uDFFC\u2640":"1f937-1f3fc-2640","\uD83E\uDD37\uD83C\uDFFC\u2642":"1f937-1f3fc-2642","\uD83E\uDD37\uD83C\uDFFD\u2640":"1f937-1f3fd-2640","\uD83E\uDD37\uD83C\uDFFD\u2642":"1f937-1f3fd-2642","\uD83E\uDD37\uD83C\uDFFE\u2640":"1f937-1f3fe-2640","\uD83E\uDD37\uD83C\uDFFE\u2642":"1f937-1f3fe-2642","\uD83E\uDD37\uD83C\uDFFF\u2640":"1f937-1f3ff-2640","\uD83E\uDD37\uD83C\uDFFF\u2642":"1f937-1f3ff-2642","\uD83E\uDDD9\uD83C\uDFFB\u2640":"1f9d9-1f3fb-2640","\uD83E\uDDD9\uD83C\uDFFB\u2642":"1f9d9-1f3fb-2642","\uD83E\uDDD9\uD83C\uDFFC\u2640":"1f9d9-1f3fc-2640","\uD83E\uDDD9\uD83C\uDFFC\u2642":"1f9d9-1f3fc-2642","\uD83E\uDDD9\uD83C\uDFFD\u2640":"1f9d9-1f3fd-2640","\uD83E\uDDD9\uD83C\uDFFD\u2642":"1f9d9-1f3fd-2642","\uD83E\uDDD9\uD83C\uDFFE\u2640":"1f9d9-1f3fe-2640","\uD83E\uDDD9\uD83C\uDFFE\u2642":"1f9d9-1f3fe-2642","\uD83E\uDDD9\uD83C\uDFFF\u2640":"1f9d9-1f3ff-2640","\uD83E\uDDD9\uD83C\uDFFF\u2642":"1f9d9-1f3ff-2642","\uD83E\uDDDA\uD83C\uDFFB\u2640":"1f9da-1f3fb-2640","\uD83E\uDDDA\uD83C\uDFFB\u2642":"1f9da-1f3fb-2642","\uD83E\uDDDA\uD83C\uDFFC\u2640":"1f9da-1f3fc-2640","\uD83E\uDDDA\uD83C\uDFFC\u2642":"1f9da-1f3fc-2642","\uD83E\uDDDA\uD83C\uDFFD\u2640":"1f9da-1f3fd-2640","\uD83E\uDDDA\uD83C\uDFFD\u2642":"1f9da-1f3fd-2642","\uD83E\uDDDA\uD83C\uDFFE\u2640":"1f9da-1f3fe-2640","\uD83E\uDDDA\uD83C\uDFFE\u2642":"1f9da-1f3fe-2642","\uD83E\uDDDA\uD83C\uDFFF\u2640":"1f9da-1f3ff-2640","\uD83E\uDDDA\uD83C\uDFFF\u2642":"1f9da-1f3ff-2642","\uD83E\uDDDB\uD83C\uDFFB\u2640":"1f9db-1f3fb-2640","\uD83E\uDDDB\uD83C\uDFFB\u2642":"1f9db-1f3fb-2642","\uD83E\uDDDB\uD83C\uDFFC\u2640":"1f9db-1f3fc-2640","\uD83E\uDDDB\uD83C\uDFFC\u2642":"1f9db-1f3fc-2642","\uD83E\uDDDB\uD83C\uDFFD\u2640":"1f9db-1f3fd-2640","\uD83E\uDDDB\uD83C\uDFFD\u2642":"1f9db-1f3fd-2642","\uD83E\uDDDB\uD83C\uDFFE\u2640":"1f9db-1f3fe-2640","\uD83E\uDDDB\uD83C\uDFFE\u2642":"1f9db-1f3fe-2642","\uD83E\uDDDB\uD83C\uDFFF\u2640":"1f9db-1f3ff-2640","\uD83E\uDDDB\uD83C\uDFFF\u2642":"1f9db-1f3ff-2642","\uD83E\uDDDC\uD83C\uDFFB\u2640":"1f9dc-1f3fb-2640","\uD83E\uDDDC\uD83C\uDFFB\u2642":"1f9dc-1f3fb-2642","\uD83E\uDDDC\uD83C\uDFFC\u2640":"1f9dc-1f3fc-2640","\uD83E\uDDDC\uD83C\uDFFC\u2642":"1f9dc-1f3fc-2642","\uD83E\uDDDC\uD83C\uDFFD\u2640":"1f9dc-1f3fd-2640","\uD83E\uDDDC\uD83C\uDFFD\u2642":"1f9dc-1f3fd-2642","\uD83E\uDDDC\uD83C\uDFFE\u2640":"1f9dc-1f3fe-2640","\uD83E\uDDDC\uD83C\uDFFE\u2642":"1f9dc-1f3fe-2642","\uD83E\uDDDC\uD83C\uDFFF\u2640":"1f9dc-1f3ff-2640","\uD83E\uDDDC\uD83C\uDFFF\u2642":"1f9dc-1f3ff-2642","\uD83E\uDDDD\uD83C\uDFFB\u2640":"1f9dd-1f3fb-2640","\uD83E\uDDDD\uD83C\uDFFB\u2642":"1f9dd-1f3fb-2642","\uD83E\uDDDD\uD83C\uDFFC\u2640":"1f9dd-1f3fc-2640","\uD83E\uDDDD\uD83C\uDFFC\u2642":"1f9dd-1f3fc-2642","\uD83E\uDDDD\uD83C\uDFFD\u2640":"1f9dd-1f3fd-2640","\uD83E\uDDDD\uD83C\uDFFD\u2642":"1f9dd-1f3fd-2642","\uD83E\uDDDD\uD83C\uDFFE\u2640":"1f9dd-1f3fe-2640","\uD83E\uDDDD\uD83C\uDFFE\u2642":"1f9dd-1f3fe-2642","\uD83E\uDDDD\uD83C\uDFFF\u2640":"1f9dd-1f3ff-2640","\uD83E\uDDDD\uD83C\uDFFF\u2642":"1f9dd-1f3ff-2642","\uD83E\uDDD6\uD83C\uDFFB\u2640":"1f9d6-1f3fb-2640","\uD83E\uDDD6\uD83C\uDFFB\u2642":"1f9d6-1f3fb-2642","\uD83E\uDDD6\uD83C\uDFFC\u2640":"1f9d6-1f3fc-2640","\uD83E\uDDD6\uD83C\uDFFC\u2642":"1f9d6-1f3fc-2642","\uD83E\uDDD6\uD83C\uDFFD\u2640":"1f9d6-1f3fd-2640","\uD83E\uDDD6\uD83C\uDFFD\u2642":"1f9d6-1f3fd-2642","\uD83E\uDDD6\uD83C\uDFFE\u2640":"1f9d6-1f3fe-2640","\uD83E\uDDD6\uD83C\uDFFE\u2642":"1f9d6-1f3fe-2642","\uD83E\uDDD6\uD83C\uDFFF\u2640":"1f9d6-1f3ff-2640","\uD83E\uDDD6\uD83C\uDFFF\u2642":"1f9d6-1f3ff-2642","\uD83E\uDDD7\uD83C\uDFFB\u2640":"1f9d7-1f3fb-2640","\uD83E\uDDD7\uD83C\uDFFB\u2642":"1f9d7-1f3fb-2642","\uD83E\uDDD7\uD83C\uDFFC\u2640":"1f9d7-1f3fc-2640","\uD83E\uDDD7\uD83C\uDFFC\u2642":"1f9d7-1f3fc-2642","\uD83E\uDDD7\uD83C\uDFFD\u2640":"1f9d7-1f3fd-2640","\uD83E\uDDD7\uD83C\uDFFD\u2642":"1f9d7-1f3fd-2642","\uD83E\uDDD7\uD83C\uDFFE\u2640":"1f9d7-1f3fe-2640","\uD83E\uDDD7\uD83C\uDFFE\u2642":"1f9d7-1f3fe-2642","\uD83E\uDDD7\uD83C\uDFFF\u2640":"1f9d7-1f3ff-2640","\uD83E\uDDD7\uD83C\uDFFF\u2642":"1f9d7-1f3ff-2642","\uD83E\uDDD8\uD83C\uDFFB\u2640":"1f9d8-1f3fb-2640","\uD83E\uDDD8\uD83C\uDFFB\u2642":"1f9d8-1f3fb-2642","\uD83E\uDDD8\uD83C\uDFFC\u2640":"1f9d8-1f3fc-2640","\uD83E\uDDD8\uD83C\uDFFC\u2642":"1f9d8-1f3fc-2642","\uD83E\uDDD8\uD83C\uDFFD\u2640":"1f9d8-1f3fd-2640","\uD83E\uDDD8\uD83C\uDFFD\u2642":"1f9d8-1f3fd-2642","\uD83E\uDDD8\uD83C\uDFFE\u2640":"1f9d8-1f3fe-2640","\uD83E\uDDD8\uD83C\uDFFE\u2642":"1f9d8-1f3fe-2642","\uD83E\uDDD8\uD83C\uDFFF\u2640":"1f9d8-1f3ff-2640","\uD83E\uDDD8\uD83C\uDFFF\u2642":"1f9d8-1f3ff-2642","\u26F9\uD83C\uDFFB\u2640":"26f9-1f3fb-2640","\u26F9\uD83C\uDFFB\u2642":"26f9-1f3fb-2642","\u26F9\uD83C\uDFFC\u2640":"26f9-1f3fc-2640","\u26F9\uD83C\uDFFC\u2642":"26f9-1f3fc-2642","\u26F9\uD83C\uDFFD\u2640":"26f9-1f3fd-2640","\u26F9\uD83C\uDFFD\u2642":"26f9-1f3fd-2642","\u26F9\uD83C\uDFFE\u2640":"26f9-1f3fe-2640","\u26F9\uD83C\uDFFE\u2642":"26f9-1f3fe-2642","\u26F9\uD83C\uDFFF\u2640":"26f9-1f3ff-2640","\u26F9\uD83C\uDFFF\u2642":"26f9-1f3ff-2642","\uD83C\uDFF3\uD83C\uDF08":"1f3f3-1f308","\uD83D\uDC41\uD83D\uDDE8":"1f441-1f5e8","\uD83D\uDC6F\u2642":"1f46f-2642","\uD83D\uDC6F\u2640":"1f46f-2640","\uD83C\uDFCC\u2642":"1f3cc-2642","\uD83C\uDFCC\u2640":"1f3cc-2640","\uD83E\uDD3C\u2642":"1f93c-2642","\uD83E\uDD3C\u2640":"1f93c-2640","\uD83E\uDD39\u2642":"1f939-2642","\uD83E\uDD39\u2640":"1f939-2640","\uD83E\uDD3E\u2642":"1f93e-2642","\uD83E\uDD3E\u2640":"1f93e-2640","\uD83E\uDD3D\u2642":"1f93d-2642","\uD83E\uDD3D\u2640":"1f93d-2640","\uD83E\uDD38\u2642":"1f938-2642","\uD83E\uDD38\u2640":"1f938-2640","\uD83D\uDEB6\u2642":"1f6b6-2642","\uD83D\uDEB6\u2640":"1f6b6-2640","\uD83D\uDEB5\u2642":"1f6b5-2642","\uD83D\uDEB5\u2640":"1f6b5-2640","\uD83D\uDEB4\u2642":"1f6b4-2642","\uD83D\uDEB4\u2640":"1f6b4-2640","\uD83D\uDEA3\u2642":"1f6a3-2642","\uD83D\uDEA3\u2640":"1f6a3-2640","\uD83C\uDFCB\u2642":"1f3cb-2642","\uD83C\uDFCB\u2640":"1f3cb-2640","\uD83C\uDFCA\u2642":"1f3ca-2642","\uD83C\uDFCA\u2640":"1f3ca-2640","\uD83C\uDFC4\u2642":"1f3c4-2642","\uD83C\uDFC4\u2640":"1f3c4-2640","\uD83C\uDFC3\u2642":"1f3c3-2642","\uD83C\uDFC3\u2640":"1f3c3-2640","\uD83E\uDD37\u2642":"1f937-2642","\uD83E\uDD37\u2640":"1f937-2640","\uD83E\uDD26\u2642":"1f926-2642","\uD83E\uDD26\u2640":"1f926-2640","\uD83D\uDE4E\u2642":"1f64e-2642","\uD83D\uDE4E\u2640":"1f64e-2640","\uD83D\uDE4D\u2642":"1f64d-2642","\uD83D\uDE4D\u2640":"1f64d-2640","\uD83D\uDE4B\u2642":"1f64b-2642","\uD83D\uDE4B\u2640":"1f64b-2640","\uD83D\uDE47\u2642":"1f647-2642","\uD83D\uDE47\u2640":"1f647-2640","\uD83D\uDE46\u2642":"1f646-2642","\uD83D\uDE46\u2640":"1f646-2640","\uD83D\uDE45\u2642":"1f645-2642","\uD83D\uDE45\u2640":"1f645-2640","\uD83D\uDC87\u2642":"1f487-2642","\uD83D\uDC87\u2640":"1f487-2640","\uD83D\uDC86\u2642":"1f486-2642","\uD83D\uDC86\u2640":"1f486-2640","\uD83D\uDC81\u2642":"1f481-2642","\uD83D\uDC81\u2640":"1f481-2640","\uD83D\uDC71\u2642":"1f471-2642","\uD83D\uDC71\u2640":"1f471-2640","\uD83D\uDC73\u2642":"1f473-2642","\uD83D\uDC73\u2640":"1f473-2640","\uD83D\uDC82\u2642":"1f482-2642","\uD83D\uDC82\u2640":"1f482-2640","\uD83D\uDD75\u2642":"1f575-2642","\uD83D\uDD75\u2640":"1f575-2640","\uD83D\uDC77\u2642":"1f477-2642","\uD83D\uDC77\u2640":"1f477-2640","\uD83D\uDC6E\u2642":"1f46e-2642","\uD83D\uDC6E\u2640":"1f46e-2640","\uD83D\uDC68\u2695":"1f468-2695","\uD83D\uDC69\u2695":"1f469-2695","\uD83D\uDC68\u2696":"1f468-2696","\uD83D\uDC69\u2696":"1f469-2696","\uD83D\uDC68\u2708":"1f468-2708","\uD83D\uDC69\u2708":"1f469-2708","\uD83E\uDDD9\u2640":"1f9d9-2640","\uD83E\uDDD9\u2642":"1f9d9-2642","\uD83E\uDDDA\u2640":"1f9da-2640","\uD83E\uDDDA\u2642":"1f9da-2642","\uD83E\uDDDB\u2640":"1f9db-2640","\uD83E\uDDDB\u2642":"1f9db-2642","\uD83E\uDDDC\u2640":"1f9dc-2640","\uD83E\uDDDC\u2642":"1f9dc-2642","\uD83E\uDDDD\u2640":"1f9dd-2640","\uD83E\uDDDD\u2642":"1f9dd-2642","\uD83E\uDDDE\u2640":"1f9de-2640","\uD83E\uDDDE\u2642":"1f9de-2642","\uD83E\uDDDF\u2640":"1f9df-2640","\uD83E\uDDDF\u2642":"1f9df-2642","\uD83E\uDDD6\u2640":"1f9d6-2640","\uD83E\uDDD6\u2642":"1f9d6-2642","\uD83E\uDDD7\u2640":"1f9d7-2640","\uD83E\uDDD7\u2642":"1f9d7-2642","\uD83E\uDDD8\u2640":"1f9d8-2640","\uD83E\uDDD8\u2642":"1f9d8-2642","\u26F9\u2642":"26f9-2642","\u26F9\u2640":"26f9-2640","\uD83C\uDD70":"1f170","\uD83C\uDD71":"1f171","\uD83C\uDD7E":"1f17e","\uD83C\uDD7F":"1f17f","\uD83C\uDE02":"1f202","\uD83C\uDE37":"1f237","\uD83C\uDF9E":"1f39e","\uD83C\uDF9F":"1f39f","\uD83C\uDFCB":"1f3cb","\uD83C\uDFCC":"1f3cc","\uD83C\uDFCD":"1f3cd","\uD83C\uDFCE":"1f3ce","\uD83C\uDF96":"1f396","\uD83C\uDF97":"1f397","\uD83C\uDF36":"1f336","\uD83C\uDF27":"1f327","\uD83C\uDF28":"1f328","\uD83C\uDF29":"1f329","\uD83C\uDF2A":"1f32a","\uD83C\uDF2B":"1f32b","\uD83C\uDF2C":"1f32c","\uD83D\uDC3F":"1f43f","\uD83D\uDD77":"1f577","\uD83D\uDD78":"1f578","\uD83C\uDF21":"1f321","\uD83C\uDF99":"1f399","\uD83C\uDF9A":"1f39a","\uD83C\uDF9B":"1f39b","\uD83C\uDFF3":"1f3f3","\uD83C\uDFF5":"1f3f5","\uD83C\uDFF7":"1f3f7","\uD83D\uDCFD":"1f4fd","\uD83D\uDD49":"1f549","\uD83D\uDD4A":"1f54a","\uD83D\uDD6F":"1f56f","\uD83D\uDD70":"1f570","\uD83D\uDD73":"1f573","\uD83D\uDD76":"1f576","\uD83D\uDD79":"1f579","\uD83D\uDD87":"1f587","\uD83D\uDD8A":"1f58a","\uD83D\uDD8B":"1f58b","\uD83D\uDD8C":"1f58c","\uD83D\uDD8D":"1f58d","\uD83D\uDDA5":"1f5a5","\uD83D\uDDA8":"1f5a8","\uD83D\uDDB2":"1f5b2","\uD83D\uDDBC":"1f5bc","\uD83D\uDDC2":"1f5c2","\uD83D\uDDC3":"1f5c3","\uD83D\uDDC4":"1f5c4","\uD83D\uDDD1":"1f5d1","\uD83D\uDDD2":"1f5d2","\uD83D\uDDD3":"1f5d3","\uD83D\uDDDC":"1f5dc","\uD83D\uDDDD":"1f5dd","\uD83D\uDDDE":"1f5de","\uD83D\uDDE1":"1f5e1","\uD83D\uDDE3":"1f5e3","\uD83D\uDDE8":"1f5e8","\uD83D\uDDEF":"1f5ef","\uD83D\uDDF3":"1f5f3","\uD83D\uDDFA":"1f5fa","\uD83D\uDEE0":"1f6e0","\uD83D\uDEE1":"1f6e1","\uD83D\uDEE2":"1f6e2","\uD83D\uDEF0":"1f6f0","\uD83C\uDF7D":"1f37d","\uD83D\uDC41":"1f441","\uD83D\uDD74":"1f574","\uD83D\uDD75":"1f575","\uD83D\uDD90":"1f590","\uD83C\uDFD4":"1f3d4","\uD83C\uDFD5":"1f3d5","\uD83C\uDFD6":"1f3d6","\uD83C\uDFD7":"1f3d7","\uD83C\uDFD8":"1f3d8","\uD83C\uDFD9":"1f3d9","\uD83C\uDFDA":"1f3da","\uD83C\uDFDB":"1f3db","\uD83C\uDFDC":"1f3dc","\uD83C\uDFDD":"1f3dd","\uD83C\uDFDE":"1f3de","\uD83C\uDFDF":"1f3df","\uD83D\uDECB":"1f6cb","\uD83D\uDECD":"1f6cd","\uD83D\uDECE":"1f6ce","\uD83D\uDECF":"1f6cf","\uD83D\uDEE3":"1f6e3","\uD83D\uDEE4":"1f6e4","\uD83D\uDEE5":"1f6e5","\uD83D\uDEE9":"1f6e9","\uD83D\uDEF3":"1f6f3","\uD83C\uDF24":"1f324","\uD83C\uDF25":"1f325","\uD83C\uDF26":"1f326","\uD83D\uDDB1":"1f5b1","\u00A9":"00a9","\u00AE":"00ae","\u203C":"203c","\u2049":"2049","\u2122":"2122","\u2139":"2139","\u2194":"2194","\u2195":"2195","\u2196":"2196","\u2197":"2197","\u2198":"2198","\u2199":"2199","\u21A9":"21a9","\u21AA":"21aa","\u24C2":"24c2","\u25AA":"25aa","\u25AB":"25ab","\u25B6":"25b6","\u25C0":"25c0","\u25FB":"25fb","\u25FC":"25fc","\u2600":"2600","\u2601":"2601","\u260E":"260e","\u2611":"2611","\u261D":"261d","\u263A":"263a","*":"002a","\u2660":"2660","\u2663":"2663","\u2665":"2665","\u2666":"2666","\u2668":"2668","\u267B":"267b","\u26A0":"26a0","\u2702":"2702","\u2708":"2708","\u2709":"2709","\u270C":"270c","\u270F":"270f","\u2712":"2712","\u2714":"2714","\u2716":"2716","\u2733":"2733","\u2734":"2734","\u2744":"2744","\u2747":"2747","\u2764":"2764","\u27A1":"27a1","\u2934":"2934","\u2935":"2935","\u2B05":"2b05","\u2B06":"2b06","\u2B07":"2b07","\u3030":"3030","\u303D":"303d","\u3297":"3297","\u3299":"3299","#":"0023","\u271D":"271d","\u2328":"2328","\u270D":"270d","\u23CF":"23cf","\u23ED":"23ed","\u23EE":"23ee","\u23EF":"23ef","\u23F1":"23f1","\u23F2":"23f2","\u23F8":"23f8","\u23F9":"23f9","\u23FA":"23fa","\u2602":"2602","\u2603":"2603","\u2604":"2604","\u2618":"2618","\u2620":"2620","\u2622":"2622","\u2623":"2623","\u2626":"2626","\u262A":"262a","\u262E":"262e","\u262F":"262f","\u2638":"2638","\u2639":"2639","\u2692":"2692","\u2694":"2694","\u2696":"2696","\u2697":"2697","\u2699":"2699","\u269B":"269b","\u269C":"269c","\u26B0":"26b0","\u26B1":"26b1","\u26C8":"26c8","\u26CF":"26cf","\u26D1":"26d1","\u26D3":"26d3","\u26E9":"26e9","\u26F0":"26f0","\u26F1":"26f1","\u26F4":"26f4","\u26F7":"26f7","\u26F8":"26f8","\u26F9":"26f9","\u2721":"2721","\u2763":"2763","9":"0039","8":"0038","7":"0037","6":"0036","5":"0035","4":"0034","3":"0033","2":"0032","1":"0031","0":"0030","\u2640":"2640","\u2642":"2642","\u2695":"2695"};
  7895. ns.asciiList = {
  7896. '*\\0/*':'1f646',
  7897. '*\\O/*':'1f646',
  7898. '-___-':'1f611',
  7899. ':\'-)':'1f602',
  7900. '\':-)':'1f605',
  7901. '\':-D':'1f605',
  7902. '>:-)':'1f606',
  7903. '\':-(':'1f613',
  7904. '>:-(':'1f620',
  7905. ':\'-(':'1f622',
  7906. 'O:-)':'1f607',
  7907. '0:-3':'1f607',
  7908. '0:-)':'1f607',
  7909. '0;^)':'1f607',
  7910. 'O;-)':'1f607',
  7911. '0;-)':'1f607',
  7912. 'O:-3':'1f607',
  7913. '-__-':'1f611',
  7914. ':-Þ':'1f61b',
  7915. '</3':'1f494',
  7916. ':\')':'1f602',
  7917. ':-D':'1f603',
  7918. '\':)':'1f605',
  7919. '\'=)':'1f605',
  7920. '\':D':'1f605',
  7921. '\'=D':'1f605',
  7922. '>:)':'1f606',
  7923. '>;)':'1f606',
  7924. '>=)':'1f606',
  7925. ';-)':'1f609',
  7926. '*-)':'1f609',
  7927. ';-]':'1f609',
  7928. ';^)':'1f609',
  7929. '\':(':'1f613',
  7930. '\'=(':'1f613',
  7931. ':-*':'1f618',
  7932. ':^*':'1f618',
  7933. '>:P':'1f61c',
  7934. 'X-P':'1f61c',
  7935. '>:[':'1f61e',
  7936. ':-(':'1f61e',
  7937. ':-[':'1f61e',
  7938. '>:(':'1f620',
  7939. ':\'(':'1f622',
  7940. ';-(':'1f622',
  7941. '>.<':'1f623',
  7942. '#-)':'1f635',
  7943. '%-)':'1f635',
  7944. 'X-)':'1f635',
  7945. '\\0/':'1f646',
  7946. '\\O/':'1f646',
  7947. '0:3':'1f607',
  7948. '0:)':'1f607',
  7949. 'O:)':'1f607',
  7950. 'O=)':'1f607',
  7951. 'O:3':'1f607',
  7952. 'B-)':'1f60e',
  7953. '8-)':'1f60e',
  7954. 'B-D':'1f60e',
  7955. '8-D':'1f60e',
  7956. '-_-':'1f611',
  7957. '>:\\':'1f615',
  7958. '>:/':'1f615',
  7959. ':-/':'1f615',
  7960. ':-.':'1f615',
  7961. ':-P':'1f61b',
  7962. ':Þ':'1f61b',
  7963. ':-b':'1f61b',
  7964. ':-O':'1f62e',
  7965. 'O_O':'1f62e',
  7966. '>:O':'1f62e',
  7967. ':-X':'1f636',
  7968. ':-#':'1f636',
  7969. ':-)':'1f642',
  7970. '(y)':'1f44d',
  7971. '<3':'2764',
  7972. ':D':'1f603',
  7973. '=D':'1f603',
  7974. ';)':'1f609',
  7975. '*)':'1f609',
  7976. ';]':'1f609',
  7977. ';D':'1f609',
  7978. ':*':'1f618',
  7979. '=*':'1f618',
  7980. ':(':'1f61e',
  7981. ':[':'1f61e',
  7982. '=(':'1f61e',
  7983. ':@':'1f620',
  7984. ';(':'1f622',
  7985. 'D:':'1f628',
  7986. ':$':'1f633',
  7987. '=$':'1f633',
  7988. '#)':'1f635',
  7989. '%)':'1f635',
  7990. 'X)':'1f635',
  7991. 'B)':'1f60e',
  7992. '8)':'1f60e',
  7993. ':/':'1f615',
  7994. ':\\':'1f615',
  7995. '=/':'1f615',
  7996. '=\\':'1f615',
  7997. ':L':'1f615',
  7998. '=L':'1f615',
  7999. ':P':'1f61b',
  8000. '=P':'1f61b',
  8001. ':b':'1f61b',
  8002. ':O':'1f62e',
  8003. ':X':'1f636',
  8004. ':#':'1f636',
  8005. '=X':'1f636',
  8006. '=#':'1f636',
  8007. ':)':'1f642',
  8008. '=]':'1f642',
  8009. '=)':'1f642',
  8010. ':]':'1f642'
  8011. };
  8012. ns.asciiRegexp = '(\\*\\\\0\\/\\*|\\*\\\\O\\/\\*|\\-___\\-|\\:\'\\-\\)|\'\\:\\-\\)|\'\\:\\-D|\\>\\:\\-\\)|>\\:\\-\\)|\'\\:\\-\\(|\\>\\:\\-\\(|>\\:\\-\\(|\\:\'\\-\\(|O\\:\\-\\)|0\\:\\-3|0\\:\\-\\)|0;\\^\\)|O;\\-\\)|0;\\-\\)|O\\:\\-3|\\-__\\-|\\:\\-Þ|\\:\\-Þ|\\<\\/3|<\\/3|\\:\'\\)|\\:\\-D|\'\\:\\)|\'\\=\\)|\'\\:D|\'\\=D|\\>\\:\\)|>\\:\\)|\\>;\\)|>;\\)|\\>\\=\\)|>\\=\\)|;\\-\\)|\\*\\-\\)|;\\-\\]|;\\^\\)|\'\\:\\(|\'\\=\\(|\\:\\-\\*|\\:\\^\\*|\\>\\:P|>\\:P|X\\-P|\\>\\:\\[|>\\:\\[|\\:\\-\\(|\\:\\-\\[|\\>\\:\\(|>\\:\\(|\\:\'\\(|;\\-\\(|\\>\\.\\<|>\\.<|#\\-\\)|%\\-\\)|X\\-\\)|\\\\0\\/|\\\\O\\/|0\\:3|0\\:\\)|O\\:\\)|O\\=\\)|O\\:3|B\\-\\)|8\\-\\)|B\\-D|8\\-D|\\-_\\-|\\>\\:\\\\|>\\:\\\\|\\>\\:\\/|>\\:\\/|\\:\\-\\/|\\:\\-\\.|\\:\\-P|\\:Þ|\\:Þ|\\:\\-b|\\:\\-O|O_O|\\>\\:O|>\\:O|\\:\\-X|\\:\\-#|\\:\\-\\)|\\(y\\)|\\<3|<3|\\:D|\\=D|;\\)|\\*\\)|;\\]|;D|\\:\\*|\\=\\*|\\:\\(|\\:\\[|\\=\\(|\\:@|;\\(|D\\:|\\:\\$|\\=\\$|#\\)|%\\)|X\\)|B\\)|8\\)|\\:\\/|\\:\\\\|\\=\\/|\\=\\\\|\\:L|\\=L|\\:P|\\=P|\\:b|\\:O|\\:X|\\:#|\\=X|\\=#|\\:\\)|\\=\\]|\\=\\)|\\:\\])';
  8013. ns.emojiVersion = '3.1'; // you can [optionally] modify this to load alternate emoji versions. see readme for backwards compatibility and version options
  8014. ns.emojiSize = '32';
  8015. ns.greedyMatch = false; // set to true for greedy unicode matching
  8016. ns.imagePathPNG = 'https://cdn.jsdelivr.net/emojione/assets/' + ns.emojiVersion + '/png/';
  8017. ns.defaultPathPNG = ns.imagePathPNG;
  8018. ns.imageTitleTag = true; // set to false to remove title attribute from img tag
  8019. ns.sprites = false; // if this is true then sprite markup will be used
  8020. ns.spriteSize = '32';
  8021. ns.unicodeAlt = true; // use the unicode char as the alt attribute (makes copy and pasting the resulting text better)
  8022. ns.ascii = false; // change to true to convert ascii smileys
  8023. ns.riskyMatchAscii = false; // set true to match ascii without leading/trailing space char
  8024. ns.regShortNames = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+ns.shortnames+")", "gi");
  8025. ns.regAscii = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|((\\s|^)"+ns.asciiRegexp+"(?=\\s|$|[!,.?]))", "gi");
  8026. ns.regAsciiRisky = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|(()"+ns.asciiRegexp+"())", "gi");
  8027. ns.regUnicode = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|(?:\uD83C\uDFF3)\uFE0F?\u200D?(?:\uD83C\uDF08)|(?:\uD83D\uDC41)\uFE0F?\u200D?(?:\uD83D\uDDE8)\uFE0F?|[#-9]\uFE0F?\u20E3|(?:(?:\uD83C\uDFF4)(?:\uDB40[\uDC60-\uDCFF]){1,6})|(?:\uD83C[\uDDE0-\uDDFF]){2}|(?:(?:\uD83D[\uDC68\uDC69]))\uFE0F?(?:\uD83C[\uDFFA-\uDFFF])?\u200D?(?:[\u2695\u2696\u2708]|\uD83C[\uDF3E-\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92])|(?:\uD83D[\uDC68\uDC69]|\uD83E[\uDDD0-\uDDDF])(?:\uD83C[\uDFFA-\uDFFF])?\u200D?[\u2640\u2642\u2695\u2696\u2708]?\uFE0F?|(?:(?:\u2764|\uD83D[\uDC66-\uDC69\uDC8B])[\u200D\uFE0F]{0,2}){1,3}(?:\u2764|\uD83D[\uDC66-\uDC69\uDC8B])|(?:(?:\u2764|\uD83D[\uDC66-\uDC69\uDC8B])\uFE0F?){2,4}|(?:\uD83D[\uDC68\uDC69\uDC6E\uDC71-\uDC87\uDD75\uDE45-\uDE4E]|\uD83E[\uDD26\uDD37]|\uD83C[\uDFC3-\uDFCC]|\uD83E[\uDD38-\uDD3E]|\uD83D[\uDEA3-\uDEB6]|\u26f9|\uD83D\uDC6F)\uFE0F?(?:\uD83C[\uDFFB-\uDFFF])?\u200D?[\u2640\u2642]?\uFE0F?|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85-\uDFCC]|\uD83D[\uDC42-\uDCAA\uDD74-\uDD96\uDE45-\uDE4F\uDEA3-\uDECC]|\uD83E[\uDD18-\uDD3E])\uFE0F?(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u2194-\u2199\u21a9-\u21aa]\uFE0F?|[\u0023\u002a]|[\u3030\u303d]\uFE0F?|(?:\ud83c[\udd70-\udd71]|\ud83c\udd8e|\ud83c[\udd91-\udd9a])\uFE0F?|\u24c2\uFE0F?|[\u3297\u3299]\uFE0F?|(?:\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51])\uFE0F?|[\u203c\u2049]\uFE0F?|[\u25aa-\u25ab\u25b6\u25c0\u25fb-\u25fe]\uFE0F?|[\u00a9\u00ae]\uFE0F?|[\u2122\u2139]\uFE0F?|\ud83c\udc04\uFE0F?|[\u2b05-\u2b07\u2b1b-\u2b1c\u2b50\u2b55]\uFE0F?|[\u231a-\u231b\u2328\u23cf\u23e9-\u23f3\u23f8-\u23fa]\uFE0F?|\ud83c\udccf|[\u2934\u2935]\uFE0F?)|[\u2700-\u27bf]\uFE0F?|[\ud800-\udbff][\udc00-\udfff]\uFE0F?|[\u2600-\u26FF]\uFE0F?|[\u0030-\u0039]\uFE0F", "g");
  8028. ns.toImage = function(str) {
  8029. str = ns.unicodeToImage(str);
  8030. str = ns.shortnameToImage(str);
  8031. return str;
  8032. };
  8033. // Uses toShort to transform all unicode into a standard shortname
  8034. // then transforms the shortname into unicode
  8035. // This is done for standardization when converting several unicode types
  8036. ns.unifyUnicode = function(str) {
  8037. str = ns.toShort(str);
  8038. str = ns.shortnameToUnicode(str);
  8039. return str;
  8040. };
  8041. // Replace shortnames (:wink:) with Ascii equivalents ( ;^) )
  8042. // Useful for systems that dont support unicode nor images
  8043. ns.shortnameToAscii = function(str) {
  8044. var unicode,
  8045. // something to keep in mind here is that array flip will destroy
  8046. // half of the ascii text "emojis" because the unicode numbers are duplicated
  8047. // this is ok for what it's being used for
  8048. unicodeToAscii = ns.objectFlip(ns.asciiList);
  8049. str = str.replace(ns.regShortNames, function(shortname) {
  8050. if( (typeof shortname === 'undefined') || (shortname === '') || (!(shortname in ns.emojioneList)) ) {
  8051. // if the shortname doesnt exist just return the entire match
  8052. return shortname;
  8053. }
  8054. else {
  8055. unicode = ns.emojioneList[shortname].uc_output;
  8056. if(typeof unicodeToAscii[unicode] !== 'undefined') {
  8057. return unicodeToAscii[unicode];
  8058. } else {
  8059. return shortname;
  8060. }
  8061. }
  8062. });
  8063. return str;
  8064. };
  8065. // will output unicode from shortname
  8066. // useful for sending emojis back to mobile devices
  8067. ns.shortnameToUnicode = function(str) {
  8068. // replace regular shortnames first
  8069. var unicode,fname;
  8070. str = str.replace(ns.regShortNames, function(shortname) {
  8071. if( (typeof shortname === 'undefined') || (shortname === '') || (!(shortname in ns.emojioneList)) ) {
  8072. // if the shortname doesnt exist just return the entire matchhju
  8073. return shortname;
  8074. }
  8075. unicode = ns.emojioneList[shortname].uc_output.toUpperCase();
  8076. fname = ns.emojioneList[shortname].uc_base;
  8077. return ns.convert(unicode);
  8078. });
  8079. // if ascii smileys are turned on, then we'll replace them!
  8080. if (ns.ascii) {
  8081. var asciiRX = ns.riskyMatchAscii ? ns.regAsciiRisky : ns.regAscii;
  8082. str = str.replace(asciiRX, function(entire, m1, m2, m3) {
  8083. if( (typeof m3 === 'undefined') || (m3 === '') || (!(ns.unescapeHTML(m3) in ns.asciiList)) ) {
  8084. // if the ascii doesnt exist just return the entire match
  8085. return entire;
  8086. }
  8087. m3 = ns.unescapeHTML(m3);
  8088. unicode = ns.asciiList[m3].toUpperCase();
  8089. return m2+ns.convert(unicode);
  8090. });
  8091. }
  8092. return str;
  8093. };
  8094. ns.shortnameToImage = function(str) {
  8095. // replace regular shortnames first
  8096. var replaceWith,shortname,unicode,fname,alt,category,title,size,ePath;
  8097. var mappedUnicode = ns.mapUnicodeToShort();
  8098. str = str.replace(ns.regShortNames, function(shortname) {
  8099. if( (typeof shortname === 'undefined') || (shortname === '') || (ns.shortnames.indexOf(shortname) === -1) ) {
  8100. // if the shortname doesnt exist just return the entire match
  8101. return shortname;
  8102. }
  8103. else {
  8104. // map shortname to parent
  8105. if (!ns.emojioneList[shortname]) {
  8106. for ( var emoji in ns.emojioneList ) {
  8107. if (!ns.emojioneList.hasOwnProperty(emoji) || (emoji === '')) continue;
  8108. if (ns.emojioneList[emoji].shortnames.indexOf(shortname) === -1) continue;
  8109. shortname = emoji;
  8110. break;
  8111. }
  8112. }
  8113. unicode = ns.emojioneList[shortname].uc_output;
  8114. fname = ns.emojioneList[shortname].uc_base;
  8115. category = (fname.includes("-1f3f")) ? 'diversity' : ns.emojioneList[shortname].category;
  8116. title = ns.imageTitleTag ? 'title="' + shortname + '"' : '';
  8117. size = (ns.spriteSize == '32' || ns.spriteSize == '64') ? ns.spriteSize : '32';
  8118. //if the image path has not changed, we'll assume the default cdn path, otherwise we'll assume the provided path
  8119. ePath = (ns.imagePathPNG != ns.defaultPathPNG) ? ns.imagePathPNG : ns.defaultPathPNG + ns.emojiSize + '/';
  8120. // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname
  8121. alt = (ns.unicodeAlt) ? ns.convert(unicode.toUpperCase()) : shortname;
  8122. if(ns.sprites) {
  8123. replaceWith = '<span class="emojione emojione-' + size + '-' + category + ' _' + fname + '" ' + title + '>' + alt + '</span>';
  8124. }
  8125. else {
  8126. replaceWith = '<img class="emojione" alt="' + alt + '" ' + title + ' src="' + ePath + fname + '.png"/>';
  8127. }
  8128. return replaceWith;
  8129. }
  8130. });
  8131. // if ascii smileys are turned on, then we'll replace them!
  8132. if (ns.ascii) {
  8133. var asciiRX = ns.riskyMatchAscii ? ns.regAsciiRisky : ns.regAscii;
  8134. str = str.replace(asciiRX, function(entire, m1, m2, m3) {
  8135. if( (typeof m3 === 'undefined') || (m3 === '') || (!(ns.unescapeHTML(m3) in ns.asciiList)) ) {
  8136. // if the ascii doesnt exist just return the entire match
  8137. return entire;
  8138. }
  8139. m3 = ns.unescapeHTML(m3);
  8140. unicode = ns.asciiList[m3];
  8141. shortname = mappedUnicode[unicode];
  8142. category = (unicode.includes("-1f3f")) ? 'diversity' : ns.emojioneList[shortname].category;
  8143. title = ns.imageTitleTag ? 'title="' + ns.escapeHTML(m3) + '"' : '';
  8144. size = (ns.spriteSize == '32' || ns.spriteSize == '64') ? ns.spriteSize : '32';
  8145. //if the image path has not changed, we'll assume the default cdn path, otherwise we'll assume the provided path
  8146. ePath = (ns.imagePathPNG != ns.defaultPathPNG) ? ns.imagePathPNG : ns.defaultPathPNG + ns.emojiSize + '/';
  8147. // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname
  8148. alt = (ns.unicodeAlt) ? ns.convert(unicode.toUpperCase()) : ns.escapeHTML(m3);
  8149. if(ns.sprites) {
  8150. replaceWith = m2+'<span class="emojione emojione-' + size + '-' + category + ' _' + unicode +'" ' + title + '>' + alt + '</span>';
  8151. }
  8152. else {
  8153. replaceWith = m2+'<img class="emojione" alt="'+alt+'" ' + title + ' src="' + ePath + unicode + '.png"/>';
  8154. }
  8155. return replaceWith;
  8156. });
  8157. }
  8158. return str;
  8159. };
  8160. ns.unicodeToImage = function(str) {
  8161. var replaceWith,unicode,short,fname,alt,category,title,size,ePath;
  8162. var mappedUnicode = ns.mapUnicodeToShort();
  8163. var eList = ns.emojioneList;
  8164. str = str.replace(ns.regUnicode, function(unicodeChar) {
  8165. if( (typeof unicodeChar === 'undefined') || (unicodeChar === '') )
  8166. {
  8167. return unicodeChar;
  8168. }
  8169. else if ( unicodeChar in ns.jsEscapeMap )
  8170. {
  8171. fname = ns.jsEscapeMap[unicodeChar];
  8172. }
  8173. else if ( ns.greedyMatch && unicodeChar in ns.jsEscapeMapGreedy )
  8174. {
  8175. fname = ns.jsEscapeMapGreedy[unicodeChar];
  8176. }
  8177. else
  8178. {
  8179. return unicodeChar;
  8180. }
  8181. // then map to shortname and locate the filename
  8182. short = mappedUnicode[fname];
  8183. // then pull the unicode output from emojioneList
  8184. fname = eList[short].uc_base;
  8185. unicode = eList[short].uc_output;
  8186. category = (fname.includes("-1f3f")) ? 'diversity' : eList[short].category;
  8187. size = (ns.spriteSize == '32' || ns.spriteSize == '64') ? ns.spriteSize : '32';
  8188. //if the image path has not changed, we'll assume the default cdn path, otherwise we'll assume the provided path
  8189. ePath = (ns.imagePathPNG != ns.defaultPathPNG) ? ns.imagePathPNG : ns.defaultPathPNG + ns.emojiSize + '/';
  8190. // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname
  8191. alt = (ns.unicodeAlt) ? ns.convert(unicode.toUpperCase()) : short;
  8192. title = ns.imageTitleTag ? 'title="' + short + '"' : '';
  8193. if(ns.sprites) {
  8194. replaceWith = '<span class="emojione emojione-' + size + '-' + category + ' _' + fname + '" ' + title + '>' + alt + '</span>';
  8195. }
  8196. else {
  8197. replaceWith = '<img class="emojione" alt="' + alt + '" ' + title + ' src="' + ePath + fname + '.png"/>';
  8198. }
  8199. return replaceWith;
  8200. });
  8201. // if ascii smileys are turned on, then we'll replace them!
  8202. if (ns.ascii) {
  8203. var asciiRX = ns.riskyMatchAscii ? ns.regAsciiRisky : ns.regAscii;
  8204. str = str.replace(asciiRX, function(entire, m1, m2, m3) {
  8205. if( (typeof m3 === 'undefined') || (m3 === '') || (!(ns.unescapeHTML(m3) in ns.asciiList)) ) {
  8206. // if the ascii doesnt exist just return the entire match
  8207. return entire;
  8208. }
  8209. m3 = ns.unescapeHTML(m3);
  8210. unicode = ns.asciiList[m3];
  8211. shortname = mappedUnicode[unicode];
  8212. category = (unicode.includes("-1f3f")) ? 'diversity' : ns.emojioneList[shortname].category;
  8213. title = ns.imageTitleTag ? 'title="' + ns.escapeHTML(m3) + '"' : '';
  8214. size = (ns.spriteSize == '32' || ns.spriteSize == '64') ? ns.spriteSize : '32';
  8215. //if the image path has not changed, we'll assume the default cdn path, otherwise we'll assume the provided path
  8216. ePath = (ns.imagePathPNG != ns.defaultPathPNG) ? ns.imagePathPNG : ns.defaultPathPNG + ns.emojiSize + '/';
  8217. // depending on the settings, we'll either add the native unicode as the alt tag, otherwise the shortname
  8218. alt = (ns.unicodeAlt) ? ns.convert(unicode.toUpperCase()) : ns.escapeHTML(m3);
  8219. if(ns.sprites) {
  8220. replaceWith = m2+'<span class="emojione emojione-' + size + '-' + category + ' _' + unicode +'" ' + title + '>' + alt + '</span>';
  8221. }
  8222. else {
  8223. replaceWith = m2+'<img class="emojione" alt="'+alt+'" ' + title + ' src="' + ePath + unicode + '.png"/>';
  8224. }
  8225. return replaceWith;
  8226. });
  8227. }
  8228. return str;
  8229. };
  8230. // this is really just unicodeToShortname() but I opted for the shorthand name to match toImage()
  8231. ns.toShort = function(str) {
  8232. var find = ns.unicodeCharRegex();
  8233. return ns.replaceAll(str, find);
  8234. };
  8235. // for converting unicode code points and code pairs to their respective characters
  8236. ns.convert = function(unicode) {
  8237. if(unicode.indexOf("-") > -1) {
  8238. var parts = [];
  8239. var s = unicode.split('-');
  8240. for(var i = 0; i < s.length; i++) {
  8241. var part = parseInt(s[i], 16);
  8242. if (part >= 0x10000 && part <= 0x10FFFF) {
  8243. var hi = Math.floor((part - 0x10000) / 0x400) + 0xD800;
  8244. var lo = ((part - 0x10000) % 0x400) + 0xDC00;
  8245. part = (String.fromCharCode(hi) + String.fromCharCode(lo));
  8246. }
  8247. else {
  8248. part = String.fromCharCode(part);
  8249. }
  8250. parts.push(part);
  8251. }
  8252. return parts.join('');
  8253. }
  8254. else {
  8255. var s = parseInt(unicode, 16);
  8256. if (s >= 0x10000 && s <= 0x10FFFF) {
  8257. var hi = Math.floor((s - 0x10000) / 0x400) + 0xD800;
  8258. var lo = ((s - 0x10000) % 0x400) + 0xDC00;
  8259. return (String.fromCharCode(hi) + String.fromCharCode(lo));
  8260. }
  8261. else {
  8262. return String.fromCharCode(s);
  8263. }
  8264. }
  8265. };
  8266. ns.escapeHTML = function (string) {
  8267. var escaped = {
  8268. '&' : '&amp;',
  8269. '<' : '&lt;',
  8270. '>' : '&gt;',
  8271. '"' : '&quot;',
  8272. '\'': '&#039;'
  8273. };
  8274. return string.replace(/[&<>"']/g, function (match) {
  8275. return escaped[match];
  8276. });
  8277. };
  8278. ns.unescapeHTML = function (string) {
  8279. var unescaped = {
  8280. '&amp;' : '&',
  8281. '&#38;' : '&',
  8282. '&#x26;' : '&',
  8283. '&lt;' : '<',
  8284. '&#60;' : '<',
  8285. '&#x3C;' : '<',
  8286. '&gt;' : '>',
  8287. '&#62;' : '>',
  8288. '&#x3E;' : '>',
  8289. '&quot;' : '"',
  8290. '&#34;' : '"',
  8291. '&#x22;' : '"',
  8292. '&apos;' : '\'',
  8293. '&#39;' : '\'',
  8294. '&#x27;' : '\''
  8295. };
  8296. return string.replace(/&(?:amp|#38|#x26|lt|#60|#x3C|gt|#62|#x3E|apos|#39|#x27|quot|#34|#x22);/ig, function (match) {
  8297. return unescaped[match];
  8298. });
  8299. };
  8300. ns.shortnameConversionMap = function() {
  8301. var map = [], emoji;
  8302. for (emoji in ns.emojioneList) {
  8303. if (!ns.emojioneList.hasOwnProperty(emoji) || (emoji === '')) continue;
  8304. map[ns.convert(ns.emojioneList[emoji].uc_output)] = emoji;
  8305. }
  8306. return map;
  8307. };
  8308. ns.unicodeCharRegex = function() {
  8309. var map = [];
  8310. for (emoji in ns.emojioneList) {
  8311. if (!ns.emojioneList.hasOwnProperty(emoji) || (emoji === '')) continue;
  8312. map.push(ns.convert(ns.emojioneList[emoji].uc_output));
  8313. }
  8314. return map.join('|');
  8315. };
  8316. ns.mapEmojioneList = function (addToMapStorage) {
  8317. for (var shortname in ns.emojioneList) {
  8318. if (!ns.emojioneList.hasOwnProperty(shortname)) { continue; }
  8319. var unicode = ns.emojioneList[shortname].uc_base;
  8320. addToMapStorage(unicode, shortname);
  8321. }
  8322. };
  8323. ns.mapUnicodeToShort = function() {
  8324. if (!ns.memMapShortToUnicode) {
  8325. ns.memMapShortToUnicode = {};
  8326. ns.mapEmojioneList(function (unicode, shortname) {
  8327. ns.memMapShortToUnicode[unicode] = shortname;
  8328. });
  8329. }
  8330. return ns.memMapShortToUnicode;
  8331. };
  8332. ns.memorizeReplacement = function() {
  8333. if (!ns.unicodeReplacementRegEx || !ns.memMapShortToUnicodeCharacters) {
  8334. var unicodeList = [];
  8335. ns.memMapShortToUnicodeCharacters = {};
  8336. ns.mapEmojioneList(function (unicode, shortname) {
  8337. var emojiCharacter = ns.convert(unicode);
  8338. ns.memMapShortToUnicodeCharacters[emojiCharacter] = shortname;
  8339. unicodeList.push(emojiCharacter);
  8340. });
  8341. ns.unicodeReplacementRegEx = unicodeList.join('|');
  8342. }
  8343. };
  8344. ns.mapUnicodeCharactersToShort = function() {
  8345. ns.memorizeReplacement();
  8346. return ns.memMapShortToUnicodeCharacters;
  8347. };
  8348. //reverse an object
  8349. ns.objectFlip = function (obj) {
  8350. var key, tmp_obj = {};
  8351. for (key in obj) {
  8352. if (obj.hasOwnProperty(key)) {
  8353. tmp_obj[obj[key]] = key;
  8354. }
  8355. }
  8356. return tmp_obj;
  8357. };
  8358. ns.escapeRegExp = function(string) {
  8359. return string.replace(/[-[\]{}()*+?.,;:&\\^$#\s]/g, "\\$&");
  8360. };
  8361. ns.replaceAll = function(string, find) {
  8362. var escapedFind = ns.escapeRegExp(find); //sorted largest output to smallest output
  8363. var search = new RegExp("<object[^>]*>.*?<\/object>|<span[^>]*>.*?<\/span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|("+escapedFind+")", "gi");
  8364. // callback prevents replacing anything inside of these common html tags as well as between an <object></object> tag
  8365. var replace = function(entire, m1) {
  8366. return ((typeof m1 === 'undefined') || (m1 === '')) ? entire : ns.shortnameConversionMap()[m1];
  8367. };
  8368. return string.replace(search,replace);
  8369. };
  8370. }(this.emojione = this.emojione || {}));
  8371. if(typeof module === "object") module.exports = this.emojione;
  8372. define("emojione", (function (global) {
  8373. return function () {
  8374. var ret, fn;
  8375. return ret || global.emojione;
  8376. };
  8377. }(this)));
  8378. (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  8379. /**
  8380. * 默认配置
  8381. *
  8382. * @author 老雷<leizongmin@gmail.com>
  8383. */
  8384. var FilterCSS = require('cssfilter').FilterCSS;
  8385. var getDefaultCSSWhiteList = require('cssfilter').getDefaultWhiteList;
  8386. var _ = require('./util');
  8387. // 默认白名单
  8388. function getDefaultWhiteList () {
  8389. return {
  8390. a: ['target', 'href', 'title'],
  8391. abbr: ['title'],
  8392. address: [],
  8393. area: ['shape', 'coords', 'href', 'alt'],
  8394. article: [],
  8395. aside: [],
  8396. audio: ['autoplay', 'controls', 'loop', 'preload', 'src'],
  8397. b: [],
  8398. bdi: ['dir'],
  8399. bdo: ['dir'],
  8400. big: [],
  8401. blockquote: ['cite'],
  8402. br: [],
  8403. caption: [],
  8404. center: [],
  8405. cite: [],
  8406. code: [],
  8407. col: ['align', 'valign', 'span', 'width'],
  8408. colgroup: ['align', 'valign', 'span', 'width'],
  8409. dd: [],
  8410. del: ['datetime'],
  8411. details: ['open'],
  8412. div: [],
  8413. dl: [],
  8414. dt: [],
  8415. em: [],
  8416. font: ['color', 'size', 'face'],
  8417. footer: [],
  8418. h1: [],
  8419. h2: [],
  8420. h3: [],
  8421. h4: [],
  8422. h5: [],
  8423. h6: [],
  8424. header: [],
  8425. hr: [],
  8426. i: [],
  8427. img: ['src', 'alt', 'title', 'width', 'height'],
  8428. ins: ['datetime'],
  8429. li: [],
  8430. mark: [],
  8431. nav: [],
  8432. ol: [],
  8433. p: [],
  8434. pre: [],
  8435. s: [],
  8436. section:[],
  8437. small: [],
  8438. span: [],
  8439. sub: [],
  8440. sup: [],
  8441. strong: [],
  8442. table: ['width', 'border', 'align', 'valign'],
  8443. tbody: ['align', 'valign'],
  8444. td: ['width', 'rowspan', 'colspan', 'align', 'valign'],
  8445. tfoot: ['align', 'valign'],
  8446. th: ['width', 'rowspan', 'colspan', 'align', 'valign'],
  8447. thead: ['align', 'valign'],
  8448. tr: ['rowspan', 'align', 'valign'],
  8449. tt: [],
  8450. u: [],
  8451. ul: [],
  8452. video: ['autoplay', 'controls', 'loop', 'preload', 'src', 'height', 'width']
  8453. };
  8454. }
  8455. // 默认CSS Filter
  8456. var defaultCSSFilter = new FilterCSS();
  8457. /**
  8458. * 匹配到标签时的处理方法
  8459. *
  8460. * @param {String} tag
  8461. * @param {String} html
  8462. * @param {Object} options
  8463. * @return {String}
  8464. */
  8465. function onTag (tag, html, options) {
  8466. // do nothing
  8467. }
  8468. /**
  8469. * 匹配到不在白名单上的标签时的处理方法
  8470. *
  8471. * @param {String} tag
  8472. * @param {String} html
  8473. * @param {Object} options
  8474. * @return {String}
  8475. */
  8476. function onIgnoreTag (tag, html, options) {
  8477. // do nothing
  8478. }
  8479. /**
  8480. * 匹配到标签属性时的处理方法
  8481. *
  8482. * @param {String} tag
  8483. * @param {String} name
  8484. * @param {String} value
  8485. * @return {String}
  8486. */
  8487. function onTagAttr (tag, name, value) {
  8488. // do nothing
  8489. }
  8490. /**
  8491. * 匹配到不在白名单上的标签属性时的处理方法
  8492. *
  8493. * @param {String} tag
  8494. * @param {String} name
  8495. * @param {String} value
  8496. * @return {String}
  8497. */
  8498. function onIgnoreTagAttr (tag, name, value) {
  8499. // do nothing
  8500. }
  8501. /**
  8502. * HTML转义
  8503. *
  8504. * @param {String} html
  8505. */
  8506. function escapeHtml (html) {
  8507. return html.replace(REGEXP_LT, '&lt;').replace(REGEXP_GT, '&gt;');
  8508. }
  8509. /**
  8510. * 安全的标签属性值
  8511. *
  8512. * @param {String} tag
  8513. * @param {String} name
  8514. * @param {String} value
  8515. * @param {Object} cssFilter
  8516. * @return {String}
  8517. */
  8518. function safeAttrValue (tag, name, value, cssFilter) {
  8519. // 转换为友好的属性值,再做判断
  8520. value = friendlyAttrValue(value);
  8521. if (name === 'href' || name === 'src') {
  8522. // 过滤 href 和 src 属性
  8523. // 仅允许 http:// | https:// | mailto: | / | # 开头的地址
  8524. value = _.trim(value);
  8525. if (value === '#') return '#';
  8526. if (!(value.substr(0, 7) === 'http://' ||
  8527. value.substr(0, 8) === 'https://' ||
  8528. value.substr(0, 7) === 'mailto:' ||
  8529. value[0] === '#' ||
  8530. value[0] === '/')) {
  8531. return '';
  8532. }
  8533. } else if (name === 'background') {
  8534. // 过滤 background 属性 (这个xss漏洞较老了,可能已经不适用)
  8535. // javascript:
  8536. REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0;
  8537. if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) {
  8538. return '';
  8539. }
  8540. } else if (name === 'style') {
  8541. // /*注释*/
  8542. /*REGEXP_DEFAULT_ON_TAG_ATTR_3.lastIndex = 0;
  8543. if (REGEXP_DEFAULT_ON_TAG_ATTR_3.test(value)) {
  8544. return '';
  8545. }*/
  8546. // expression()
  8547. REGEXP_DEFAULT_ON_TAG_ATTR_7.lastIndex = 0;
  8548. if (REGEXP_DEFAULT_ON_TAG_ATTR_7.test(value)) {
  8549. return '';
  8550. }
  8551. // url()
  8552. REGEXP_DEFAULT_ON_TAG_ATTR_8.lastIndex = 0;
  8553. if (REGEXP_DEFAULT_ON_TAG_ATTR_8.test(value)) {
  8554. REGEXP_DEFAULT_ON_TAG_ATTR_4.lastIndex = 0;
  8555. if (REGEXP_DEFAULT_ON_TAG_ATTR_4.test(value)) {
  8556. return '';
  8557. }
  8558. }
  8559. if (cssFilter !== false) {
  8560. cssFilter = cssFilter || defaultCSSFilter;
  8561. value = cssFilter.process(value);
  8562. }
  8563. }
  8564. // 输出时需要转义<>"
  8565. value = escapeAttrValue(value);
  8566. return value;
  8567. }
  8568. // 正则表达式
  8569. var REGEXP_LT = /</g;
  8570. var REGEXP_GT = />/g;
  8571. var REGEXP_QUOTE = /"/g;
  8572. var REGEXP_QUOTE_2 = /&quot;/g;
  8573. var REGEXP_ATTR_VALUE_1 = /&#([a-zA-Z0-9]*);?/img;
  8574. var REGEXP_ATTR_VALUE_COLON = /&colon;?/img;
  8575. var REGEXP_ATTR_VALUE_NEWLINE = /&newline;?/img;
  8576. var REGEXP_DEFAULT_ON_TAG_ATTR_3 = /\/\*|\*\//mg;
  8577. var REGEXP_DEFAULT_ON_TAG_ATTR_4 = /((j\s*a\s*v\s*a|v\s*b|l\s*i\s*v\s*e)\s*s\s*c\s*r\s*i\s*p\s*t\s*|m\s*o\s*c\s*h\s*a)\:/ig;
  8578. var REGEXP_DEFAULT_ON_TAG_ATTR_5 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:/ig;
  8579. var REGEXP_DEFAULT_ON_TAG_ATTR_6 = /^[\s"'`]*(d\s*a\s*t\s*a\s*)\:\s*image\//ig;
  8580. var REGEXP_DEFAULT_ON_TAG_ATTR_7 = /e\s*x\s*p\s*r\s*e\s*s\s*s\s*i\s*o\s*n\s*\(.*/ig;
  8581. var REGEXP_DEFAULT_ON_TAG_ATTR_8 = /u\s*r\s*l\s*\(.*/ig;
  8582. /**
  8583. * 对双引号进行转义
  8584. *
  8585. * @param {String} str
  8586. * @return {String} str
  8587. */
  8588. function escapeQuote (str) {
  8589. return str.replace(REGEXP_QUOTE, '&quot;');
  8590. }
  8591. /**
  8592. * 对双引号进行转义
  8593. *
  8594. * @param {String} str
  8595. * @return {String} str
  8596. */
  8597. function unescapeQuote (str) {
  8598. return str.replace(REGEXP_QUOTE_2, '"');
  8599. }
  8600. /**
  8601. * 对html实体编码进行转义
  8602. *
  8603. * @param {String} str
  8604. * @return {String}
  8605. */
  8606. function escapeHtmlEntities (str) {
  8607. return str.replace(REGEXP_ATTR_VALUE_1, function replaceUnicode (str, code) {
  8608. return (code[0] === 'x' || code[0] === 'X')
  8609. ? String.fromCharCode(parseInt(code.substr(1), 16))
  8610. : String.fromCharCode(parseInt(code, 10));
  8611. });
  8612. }
  8613. /**
  8614. * 对html5新增的危险实体编码进行转义
  8615. *
  8616. * @param {String} str
  8617. * @return {String}
  8618. */
  8619. function escapeDangerHtml5Entities (str) {
  8620. return str.replace(REGEXP_ATTR_VALUE_COLON, ':')
  8621. .replace(REGEXP_ATTR_VALUE_NEWLINE, ' ');
  8622. }
  8623. /**
  8624. * 清除不可见字符
  8625. *
  8626. * @param {String} str
  8627. * @return {String}
  8628. */
  8629. function clearNonPrintableCharacter (str) {
  8630. var str2 = '';
  8631. for (var i = 0, len = str.length; i < len; i++) {
  8632. str2 += str.charCodeAt(i) < 32 ? ' ' : str.charAt(i);
  8633. }
  8634. return _.trim(str2);
  8635. }
  8636. /**
  8637. * 将标签的属性值转换成一般字符,便于分析
  8638. *
  8639. * @param {String} str
  8640. * @return {String}
  8641. */
  8642. function friendlyAttrValue (str) {
  8643. str = unescapeQuote(str); // 双引号
  8644. str = escapeHtmlEntities(str); // 转换HTML实体编码
  8645. str = escapeDangerHtml5Entities(str); // 转换危险的HTML5新增实体编码
  8646. str = clearNonPrintableCharacter(str); // 清除不可见字符
  8647. return str;
  8648. }
  8649. /**
  8650. * 转义用于输出的标签属性值
  8651. *
  8652. * @param {String} str
  8653. * @return {String}
  8654. */
  8655. function escapeAttrValue (str) {
  8656. str = escapeQuote(str);
  8657. str = escapeHtml(str);
  8658. return str;
  8659. }
  8660. /**
  8661. * 去掉不在白名单中的标签onIgnoreTag处理方法
  8662. */
  8663. function onIgnoreTagStripAll () {
  8664. return '';
  8665. }
  8666. /**
  8667. * 删除标签体
  8668. *
  8669. * @param {array} tags 要删除的标签列表
  8670. * @param {function} next 对不在列表中的标签的处理函数,可选
  8671. */
  8672. function StripTagBody (tags, next) {
  8673. if (typeof(next) !== 'function') {
  8674. next = function () {};
  8675. }
  8676. var isRemoveAllTag = !Array.isArray(tags);
  8677. function isRemoveTag (tag) {
  8678. if (isRemoveAllTag) return true;
  8679. return (_.indexOf(tags, tag) !== -1);
  8680. }
  8681. var removeList = []; // 要删除的位置范围列表
  8682. var posStart = false; // 当前标签开始位置
  8683. return {
  8684. onIgnoreTag: function (tag, html, options) {
  8685. if (isRemoveTag(tag)) {
  8686. if (options.isClosing) {
  8687. var ret = '[/removed]';
  8688. var end = options.position + ret.length;
  8689. removeList.push([posStart !== false ? posStart : options.position, end]);
  8690. posStart = false;
  8691. return ret;
  8692. } else {
  8693. if (!posStart) {
  8694. posStart = options.position;
  8695. }
  8696. return '[removed]';
  8697. }
  8698. } else {
  8699. return next(tag, html, options);
  8700. }
  8701. },
  8702. remove: function (html) {
  8703. var rethtml = '';
  8704. var lastPos = 0;
  8705. _.forEach(removeList, function (pos) {
  8706. rethtml += html.slice(lastPos, pos[0]);
  8707. lastPos = pos[1];
  8708. });
  8709. rethtml += html.slice(lastPos);
  8710. return rethtml;
  8711. }
  8712. };
  8713. }
  8714. /**
  8715. * 去除备注标签
  8716. *
  8717. * @param {String} html
  8718. * @return {String}
  8719. */
  8720. function stripCommentTag (html) {
  8721. return html.replace(STRIP_COMMENT_TAG_REGEXP, '');
  8722. }
  8723. var STRIP_COMMENT_TAG_REGEXP = /<!--[\s\S]*?-->/g;
  8724. /**
  8725. * 去除不可见字符
  8726. *
  8727. * @param {String} html
  8728. * @return {String}
  8729. */
  8730. function stripBlankChar (html) {
  8731. var chars = html.split('');
  8732. chars = chars.filter(function (char) {
  8733. var c = char.charCodeAt(0);
  8734. if (c === 127) return false;
  8735. if (c <= 31) {
  8736. if (c === 10 || c === 13) return true;
  8737. return false;
  8738. }
  8739. return true;
  8740. });
  8741. return chars.join('');
  8742. }
  8743. exports.whiteList = getDefaultWhiteList();
  8744. exports.getDefaultWhiteList = getDefaultWhiteList;
  8745. exports.onTag = onTag;
  8746. exports.onIgnoreTag = onIgnoreTag;
  8747. exports.onTagAttr = onTagAttr;
  8748. exports.onIgnoreTagAttr = onIgnoreTagAttr;
  8749. exports.safeAttrValue = safeAttrValue;
  8750. exports.escapeHtml = escapeHtml;
  8751. exports.escapeQuote = escapeQuote;
  8752. exports.unescapeQuote = unescapeQuote;
  8753. exports.escapeHtmlEntities = escapeHtmlEntities;
  8754. exports.escapeDangerHtml5Entities = escapeDangerHtml5Entities;
  8755. exports.clearNonPrintableCharacter = clearNonPrintableCharacter;
  8756. exports.friendlyAttrValue = friendlyAttrValue;
  8757. exports.escapeAttrValue = escapeAttrValue;
  8758. exports.onIgnoreTagStripAll = onIgnoreTagStripAll;
  8759. exports.StripTagBody = StripTagBody;
  8760. exports.stripCommentTag = stripCommentTag;
  8761. exports.stripBlankChar = stripBlankChar;
  8762. exports.cssFilter = defaultCSSFilter;
  8763. exports.getDefaultCSSWhiteList = getDefaultCSSWhiteList;
  8764. },{"./util":4,"cssfilter":8}],2:[function(require,module,exports){
  8765. /**
  8766. * 模块入口
  8767. *
  8768. * @author 老雷<leizongmin@gmail.com>
  8769. */
  8770. var DEFAULT = require('./default');
  8771. var parser = require('./parser');
  8772. var FilterXSS = require('./xss');
  8773. /**
  8774. * XSS过滤
  8775. *
  8776. * @param {String} html 要过滤的HTML代码
  8777. * @param {Object} options 选项:whiteList, onTag, onTagAttr, onIgnoreTag, onIgnoreTagAttr, safeAttrValue, escapeHtml
  8778. * @return {String}
  8779. */
  8780. function filterXSS (html, options) {
  8781. var xss = new FilterXSS(options);
  8782. return xss.process(html);
  8783. }
  8784. // 输出
  8785. exports = module.exports = filterXSS;
  8786. exports.FilterXSS = FilterXSS;
  8787. for (var i in DEFAULT) exports[i] = DEFAULT[i];
  8788. for (var i in parser) exports[i] = parser[i];
  8789. // 在浏览器端使用
  8790. if (typeof window !== 'undefined') {
  8791. window.filterXSS = module.exports;
  8792. }
  8793. },{"./default":1,"./parser":3,"./xss":5}],3:[function(require,module,exports){
  8794. /**
  8795. * 简单 HTML Parser
  8796. *
  8797. * @author 老雷<leizongmin@gmail.com>
  8798. */
  8799. var _ = require('./util');
  8800. /**
  8801. * 获取标签的名称
  8802. *
  8803. * @param {String} html 如:'<a hef="#">'
  8804. * @return {String}
  8805. */
  8806. function getTagName (html) {
  8807. var i = html.indexOf(' ');
  8808. if (i === -1) {
  8809. var tagName = html.slice(1, -1);
  8810. } else {
  8811. var tagName = html.slice(1, i + 1);
  8812. }
  8813. tagName = _.trim(tagName).toLowerCase();
  8814. if (tagName.slice(0, 1) === '/') tagName = tagName.slice(1);
  8815. if (tagName.slice(-1) === '/') tagName = tagName.slice(0, -1);
  8816. return tagName;
  8817. }
  8818. /**
  8819. * 是否为闭合标签
  8820. *
  8821. * @param {String} html 如:'<a hef="#">'
  8822. * @return {Boolean}
  8823. */
  8824. function isClosing (html) {
  8825. return (html.slice(0, 2) === '</');
  8826. }
  8827. /**
  8828. * 分析HTML代码,调用相应的函数处理,返回处理后的HTML
  8829. *
  8830. * @param {String} html
  8831. * @param {Function} onTag 处理标签的函数
  8832. * 参数格式: function (sourcePosition, position, tag, html, isClosing)
  8833. * @param {Function} escapeHtml 对HTML进行转义的函数
  8834. * @return {String}
  8835. */
  8836. function parseTag (html, onTag, escapeHtml) {
  8837. 'user strict';
  8838. var rethtml = ''; // 待返回的HTML
  8839. var lastPos = 0; // 上一个标签结束位置
  8840. var tagStart = false; // 当前标签开始位置
  8841. var quoteStart = false; // 引号开始位置
  8842. var currentPos = 0; // 当前位置
  8843. var len = html.length; // HTML长度
  8844. var currentHtml = ''; // 当前标签的HTML代码
  8845. var currentTagName = ''; // 当前标签的名称
  8846. // 逐个分析字符
  8847. for (currentPos = 0; currentPos < len; currentPos++) {
  8848. var c = html.charAt(currentPos);
  8849. if (tagStart === false) {
  8850. if (c === '<') {
  8851. tagStart = currentPos;
  8852. continue;
  8853. }
  8854. } else {
  8855. if (quoteStart === false) {
  8856. if (c === '<') {
  8857. rethtml += escapeHtml(html.slice(lastPos, currentPos));
  8858. tagStart = currentPos;
  8859. lastPos = currentPos;
  8860. continue;
  8861. }
  8862. if (c === '>') {
  8863. rethtml += escapeHtml(html.slice(lastPos, tagStart));
  8864. currentHtml = html.slice(tagStart, currentPos + 1);
  8865. currentTagName = getTagName(currentHtml);
  8866. rethtml += onTag(tagStart,
  8867. rethtml.length,
  8868. currentTagName,
  8869. currentHtml,
  8870. isClosing(currentHtml));
  8871. lastPos = currentPos + 1;
  8872. tagStart = false;
  8873. continue;
  8874. }
  8875. // HTML标签内的引号仅当前一个字符是等于号时才有效
  8876. if ((c === '"' || c === "'") && html.charAt(currentPos - 1) === '=') {
  8877. quoteStart = c;
  8878. continue;
  8879. }
  8880. } else {
  8881. if (c === quoteStart) {
  8882. quoteStart = false;
  8883. continue;
  8884. }
  8885. }
  8886. }
  8887. }
  8888. if (lastPos < html.length) {
  8889. rethtml += escapeHtml(html.substr(lastPos));
  8890. }
  8891. return rethtml;
  8892. }
  8893. // 不符合属性名称规则的正则表达式
  8894. var REGEXP_ATTR_NAME = /[^a-zA-Z0-9_:\.\-]/img;
  8895. /**
  8896. * 分析标签HTML代码,调用相应的函数处理,返回HTML
  8897. *
  8898. * @param {String} html 如标签'<a href="#" target="_blank">' 则为 'href="#" target="_blank"'
  8899. * @param {Function} onAttr 处理属性值的函数
  8900. * 函数格式: function (name, value)
  8901. * @return {String}
  8902. */
  8903. function parseAttr (html, onAttr) {
  8904. 'user strict';
  8905. var lastPos = 0; // 当前位置
  8906. var retAttrs = []; // 待返回的属性列表
  8907. var tmpName = false; // 临时属性名称
  8908. var len = html.length; // HTML代码长度
  8909. function addAttr (name, value) {
  8910. name = _.trim(name);
  8911. name = name.replace(REGEXP_ATTR_NAME, '').toLowerCase();
  8912. if (name.length < 1) return;
  8913. var ret = onAttr(name, value || '');
  8914. if (ret) retAttrs.push(ret);
  8915. };
  8916. // 逐个分析字符
  8917. for (var i = 0; i < len; i++) {
  8918. var c = html.charAt(i);
  8919. var v, j;
  8920. if (tmpName === false && c === '=') {
  8921. tmpName = html.slice(lastPos, i);
  8922. lastPos = i + 1;
  8923. continue;
  8924. }
  8925. if (tmpName !== false) {
  8926. // HTML标签内的引号仅当前一个字符是等于号时才有效
  8927. if (i === lastPos && (c === '"' || c === "'") && html.charAt(i - 1) === '=') {
  8928. j = html.indexOf(c, i + 1);
  8929. if (j === -1) {
  8930. break;
  8931. } else {
  8932. v = _.trim(html.slice(lastPos + 1, j));
  8933. addAttr(tmpName, v);
  8934. tmpName = false;
  8935. i = j;
  8936. lastPos = i + 1;
  8937. continue;
  8938. }
  8939. }
  8940. }
  8941. if (c === ' ') {
  8942. if (tmpName === false) {
  8943. j = findNextEqual(html, i);
  8944. if (j === -1) {
  8945. v = _.trim(html.slice(lastPos, i));
  8946. addAttr(v);
  8947. tmpName = false;
  8948. lastPos = i + 1;
  8949. continue;
  8950. } else {
  8951. i = j - 1;
  8952. continue;
  8953. }
  8954. } else {
  8955. j = findBeforeEqual(html, i - 1);
  8956. if (j === -1) {
  8957. v = _.trim(html.slice(lastPos, i));
  8958. v = stripQuoteWrap(v);
  8959. addAttr(tmpName, v);
  8960. tmpName = false;
  8961. lastPos = i + 1;
  8962. continue;
  8963. } else {
  8964. continue;
  8965. }
  8966. }
  8967. }
  8968. }
  8969. if (lastPos < html.length) {
  8970. if (tmpName === false) {
  8971. addAttr(html.slice(lastPos));
  8972. } else {
  8973. addAttr(tmpName, stripQuoteWrap(_.trim(html.slice(lastPos))));
  8974. }
  8975. }
  8976. return _.trim(retAttrs.join(' '));
  8977. }
  8978. function findNextEqual (str, i) {
  8979. for (; i < str.length; i++) {
  8980. var c = str[i];
  8981. if (c === ' ') continue;
  8982. if (c === '=') return i;
  8983. return -1;
  8984. }
  8985. }
  8986. function findBeforeEqual (str, i) {
  8987. for (; i > 0; i--) {
  8988. var c = str[i];
  8989. if (c === ' ') continue;
  8990. if (c === '=') return i;
  8991. return -1;
  8992. }
  8993. }
  8994. function isQuoteWrapString (text) {
  8995. if ((text[0] === '"' && text[text.length - 1] === '"') ||
  8996. (text[0] === '\'' && text[text.length - 1] === '\'')) {
  8997. return true;
  8998. } else {
  8999. return false;
  9000. }
  9001. };
  9002. function stripQuoteWrap (text) {
  9003. if (isQuoteWrapString(text)) {
  9004. return text.substr(1, text.length - 2);
  9005. } else {
  9006. return text;
  9007. }
  9008. };
  9009. exports.parseTag = parseTag;
  9010. exports.parseAttr = parseAttr;
  9011. },{"./util":4}],4:[function(require,module,exports){
  9012. module.exports = {
  9013. indexOf: function (arr, item) {
  9014. var i, j;
  9015. if (Array.prototype.indexOf) {
  9016. return arr.indexOf(item);
  9017. }
  9018. for (i = 0, j = arr.length; i < j; i++) {
  9019. if (arr[i] === item) {
  9020. return i;
  9021. }
  9022. }
  9023. return -1;
  9024. },
  9025. forEach: function (arr, fn, scope) {
  9026. var i, j;
  9027. if (Array.prototype.forEach) {
  9028. return arr.forEach(fn, scope);
  9029. }
  9030. for (i = 0, j = arr.length; i < j; i++) {
  9031. fn.call(scope, arr[i], i, arr);
  9032. }
  9033. },
  9034. trim: function (str) {
  9035. if (String.prototype.trim) {
  9036. return str.trim();
  9037. }
  9038. return str.replace(/(^\s*)|(\s*$)/g, '');
  9039. }
  9040. };
  9041. },{}],5:[function(require,module,exports){
  9042. /**
  9043. * 过滤XSS
  9044. *
  9045. * @author 老雷<leizongmin@gmail.com>
  9046. */
  9047. var FilterCSS = require('cssfilter').FilterCSS;
  9048. var DEFAULT = require('./default');
  9049. var parser = require('./parser');
  9050. var parseTag = parser.parseTag;
  9051. var parseAttr = parser.parseAttr;
  9052. var _ = require('./util');
  9053. /**
  9054. * 返回值是否为空
  9055. *
  9056. * @param {Object} obj
  9057. * @return {Boolean}
  9058. */
  9059. function isNull (obj) {
  9060. return (obj === undefined || obj === null);
  9061. }
  9062. /**
  9063. * 取标签内的属性列表字符串
  9064. *
  9065. * @param {String} html
  9066. * @return {Object}
  9067. * - {String} html
  9068. * - {Boolean} closing
  9069. */
  9070. function getAttrs (html) {
  9071. var i = html.indexOf(' ');
  9072. if (i === -1) {
  9073. return {
  9074. html: '',
  9075. closing: (html[html.length - 2] === '/')
  9076. };
  9077. }
  9078. html = _.trim(html.slice(i + 1, -1));
  9079. var isClosing = (html[html.length - 1] === '/');
  9080. if (isClosing) html = _.trim(html.slice(0, -1));
  9081. return {
  9082. html: html,
  9083. closing: isClosing
  9084. };
  9085. }
  9086. /**
  9087. * 浅拷贝对象
  9088. *
  9089. * @param {Object} obj
  9090. * @return {Object}
  9091. */
  9092. function shallowCopyObject (obj) {
  9093. var ret = {};
  9094. for (var i in obj) {
  9095. ret[i] = obj[i];
  9096. }
  9097. return ret;
  9098. }
  9099. /**
  9100. * XSS过滤对象
  9101. *
  9102. * @param {Object} options
  9103. * 选项:whiteList, onTag, onTagAttr, onIgnoreTag,
  9104. * onIgnoreTagAttr, safeAttrValue, escapeHtml
  9105. * stripIgnoreTagBody, allowCommentTag, stripBlankChar
  9106. * css{whiteList, onAttr, onIgnoreAttr} css=false表示禁用cssfilter
  9107. */
  9108. function FilterXSS (options) {
  9109. options = shallowCopyObject(options || {});
  9110. if (options.stripIgnoreTag) {
  9111. if (options.onIgnoreTag) {
  9112. console.error('Notes: cannot use these two options "stripIgnoreTag" and "onIgnoreTag" at the same time');
  9113. }
  9114. options.onIgnoreTag = DEFAULT.onIgnoreTagStripAll;
  9115. }
  9116. options.whiteList = options.whiteList || DEFAULT.whiteList;
  9117. options.onTag = options.onTag || DEFAULT.onTag;
  9118. options.onTagAttr = options.onTagAttr || DEFAULT.onTagAttr;
  9119. options.onIgnoreTag = options.onIgnoreTag || DEFAULT.onIgnoreTag;
  9120. options.onIgnoreTagAttr = options.onIgnoreTagAttr || DEFAULT.onIgnoreTagAttr;
  9121. options.safeAttrValue = options.safeAttrValue || DEFAULT.safeAttrValue;
  9122. options.escapeHtml = options.escapeHtml || DEFAULT.escapeHtml;
  9123. this.options = options;
  9124. if (options.css === false) {
  9125. this.cssFilter = false;
  9126. } else {
  9127. options.css = options.css || {};
  9128. this.cssFilter = new FilterCSS(options.css);
  9129. }
  9130. }
  9131. /**
  9132. * 开始处理
  9133. *
  9134. * @param {String} html
  9135. * @return {String}
  9136. */
  9137. FilterXSS.prototype.process = function (html) {
  9138. // 兼容各种奇葩输入
  9139. html = html || '';
  9140. html = html.toString();
  9141. if (!html) return '';
  9142. var me = this;
  9143. var options = me.options;
  9144. var whiteList = options.whiteList;
  9145. var onTag = options.onTag;
  9146. var onIgnoreTag = options.onIgnoreTag;
  9147. var onTagAttr = options.onTagAttr;
  9148. var onIgnoreTagAttr = options.onIgnoreTagAttr;
  9149. var safeAttrValue = options.safeAttrValue;
  9150. var escapeHtml = options.escapeHtml;
  9151. var cssFilter = me.cssFilter;
  9152. // 是否清除不可见字符
  9153. if (options.stripBlankChar) {
  9154. html = DEFAULT.stripBlankChar(html);
  9155. }
  9156. // 是否禁止备注标签
  9157. if (!options.allowCommentTag) {
  9158. html = DEFAULT.stripCommentTag(html);
  9159. }
  9160. // 如果开启了stripIgnoreTagBody
  9161. var stripIgnoreTagBody = false;
  9162. if (options.stripIgnoreTagBody) {
  9163. var stripIgnoreTagBody = DEFAULT.StripTagBody(options.stripIgnoreTagBody, onIgnoreTag);
  9164. onIgnoreTag = stripIgnoreTagBody.onIgnoreTag;
  9165. }
  9166. var retHtml = parseTag(html, function (sourcePosition, position, tag, html, isClosing) {
  9167. var info = {
  9168. sourcePosition: sourcePosition,
  9169. position: position,
  9170. isClosing: isClosing,
  9171. isWhite: (tag in whiteList)
  9172. };
  9173. // 调用onTag处理
  9174. var ret = onTag(tag, html, info);
  9175. if (!isNull(ret)) return ret;
  9176. // 默认标签处理方法
  9177. if (info.isWhite) {
  9178. // 白名单标签,解析标签属性
  9179. // 如果是闭合标签,则不需要解析属性
  9180. if (info.isClosing) {
  9181. return '</' + tag + '>';
  9182. }
  9183. var attrs = getAttrs(html);
  9184. var whiteAttrList = whiteList[tag];
  9185. var attrsHtml = parseAttr(attrs.html, function (name, value) {
  9186. // 调用onTagAttr处理
  9187. var isWhiteAttr = (_.indexOf(whiteAttrList, name) !== -1);
  9188. var ret = onTagAttr(tag, name, value, isWhiteAttr);
  9189. if (!isNull(ret)) return ret;
  9190. // 默认的属性处理方法
  9191. if (isWhiteAttr) {
  9192. // 白名单属性,调用safeAttrValue过滤属性值
  9193. value = safeAttrValue(tag, name, value, cssFilter);
  9194. if (value) {
  9195. return name + '="' + value + '"';
  9196. } else {
  9197. return name;
  9198. }
  9199. } else {
  9200. // 非白名单属性,调用onIgnoreTagAttr处理
  9201. var ret = onIgnoreTagAttr(tag, name, value, isWhiteAttr);
  9202. if (!isNull(ret)) return ret;
  9203. return;
  9204. }
  9205. });
  9206. // 构造新的标签代码
  9207. var html = '<' + tag;
  9208. if (attrsHtml) html += ' ' + attrsHtml;
  9209. if (attrs.closing) html += ' /';
  9210. html += '>';
  9211. return html;
  9212. } else {
  9213. // 非白名单标签,调用onIgnoreTag处理
  9214. var ret = onIgnoreTag(tag, html, info);
  9215. if (!isNull(ret)) return ret;
  9216. return escapeHtml(html);
  9217. }
  9218. }, escapeHtml);
  9219. // 如果开启了stripIgnoreTagBody,需要对结果再进行处理
  9220. if (stripIgnoreTagBody) {
  9221. retHtml = stripIgnoreTagBody.remove(retHtml);
  9222. }
  9223. return retHtml;
  9224. };
  9225. module.exports = FilterXSS;
  9226. },{"./default":1,"./parser":3,"./util":4,"cssfilter":8}],6:[function(require,module,exports){
  9227. /**
  9228. * cssfilter
  9229. *
  9230. * @author 老雷<leizongmin@gmail.com>
  9231. */
  9232. var DEFAULT = require('./default');
  9233. var parseStyle = require('./parser');
  9234. var _ = require('./util');
  9235. /**
  9236. * 返回值是否为空
  9237. *
  9238. * @param {Object} obj
  9239. * @return {Boolean}
  9240. */
  9241. function isNull (obj) {
  9242. return (obj === undefined || obj === null);
  9243. }
  9244. /**
  9245. * 浅拷贝对象
  9246. *
  9247. * @param {Object} obj
  9248. * @return {Object}
  9249. */
  9250. function shallowCopyObject (obj) {
  9251. var ret = {};
  9252. for (var i in obj) {
  9253. ret[i] = obj[i];
  9254. }
  9255. return ret;
  9256. }
  9257. /**
  9258. * 创建CSS过滤器
  9259. *
  9260. * @param {Object} options
  9261. * - {Object} whiteList
  9262. * - {Object} onAttr
  9263. * - {Object} onIgnoreAttr
  9264. */
  9265. function FilterCSS (options) {
  9266. options = shallowCopyObject(options || {});
  9267. options.whiteList = options.whiteList || DEFAULT.whiteList;
  9268. options.onAttr = options.onAttr || DEFAULT.onAttr;
  9269. options.onIgnoreAttr = options.onIgnoreAttr || DEFAULT.onIgnoreAttr;
  9270. this.options = options;
  9271. }
  9272. FilterCSS.prototype.process = function (css) {
  9273. // 兼容各种奇葩输入
  9274. css = css || '';
  9275. css = css.toString();
  9276. if (!css) return '';
  9277. var me = this;
  9278. var options = me.options;
  9279. var whiteList = options.whiteList;
  9280. var onAttr = options.onAttr;
  9281. var onIgnoreAttr = options.onIgnoreAttr;
  9282. var retCSS = parseStyle(css, function (sourcePosition, position, name, value, source) {
  9283. var check = whiteList[name];
  9284. var isWhite = false;
  9285. if (check === true) isWhite = check;
  9286. else if (typeof check === 'function') isWhite = check(value);
  9287. else if (check instanceof RegExp) isWhite = check.test(value);
  9288. if (isWhite !== true) isWhite = false;
  9289. var opts = {
  9290. position: position,
  9291. sourcePosition: sourcePosition,
  9292. source: source,
  9293. isWhite: isWhite
  9294. };
  9295. if (isWhite) {
  9296. var ret = onAttr(name, value, opts);
  9297. if (isNull(ret)) {
  9298. return name + ':' + value;
  9299. } else {
  9300. return ret;
  9301. }
  9302. } else {
  9303. var ret = onIgnoreAttr(name, value, opts);
  9304. if (!isNull(ret)) {
  9305. return ret;
  9306. }
  9307. }
  9308. });
  9309. return retCSS;
  9310. };
  9311. module.exports = FilterCSS;
  9312. },{"./default":7,"./parser":9,"./util":10}],7:[function(require,module,exports){
  9313. /**
  9314. * cssfilter
  9315. *
  9316. * @author 老雷<leizongmin@gmail.com>
  9317. */
  9318. function getDefaultWhiteList () {
  9319. // 白名单值说明:
  9320. // true: 允许该属性
  9321. // Function: function (val) { } 返回true表示允许该属性,其他值均表示不允许
  9322. // RegExp: regexp.test(val) 返回true表示允许该属性,其他值均表示不允许
  9323. // 除上面列出的值外均表示不允许
  9324. var whiteList = {};
  9325. whiteList['align-content'] = false; // default: auto
  9326. whiteList['align-items'] = false; // default: auto
  9327. whiteList['align-self'] = false; // default: auto
  9328. whiteList['alignment-adjust'] = false; // default: auto
  9329. whiteList['alignment-baseline'] = false; // default: baseline
  9330. whiteList['all'] = false; // default: depending on individual properties
  9331. whiteList['anchor-point'] = false; // default: none
  9332. whiteList['animation'] = false; // default: depending on individual properties
  9333. whiteList['animation-delay'] = false; // default: 0
  9334. whiteList['animation-direction'] = false; // default: normal
  9335. whiteList['animation-duration'] = false; // default: 0
  9336. whiteList['animation-fill-mode'] = false; // default: none
  9337. whiteList['animation-iteration-count'] = false; // default: 1
  9338. whiteList['animation-name'] = false; // default: none
  9339. whiteList['animation-play-state'] = false; // default: running
  9340. whiteList['animation-timing-function'] = false; // default: ease
  9341. whiteList['azimuth'] = false; // default: center
  9342. whiteList['backface-visibility'] = false; // default: visible
  9343. whiteList['background'] = true; // default: depending on individual properties
  9344. whiteList['background-attachment'] = true; // default: scroll
  9345. whiteList['background-clip'] = true; // default: border-box
  9346. whiteList['background-color'] = true; // default: transparent
  9347. whiteList['background-image'] = true; // default: none
  9348. whiteList['background-origin'] = true; // default: padding-box
  9349. whiteList['background-position'] = true; // default: 0% 0%
  9350. whiteList['background-repeat'] = true; // default: repeat
  9351. whiteList['background-size'] = true; // default: auto
  9352. whiteList['baseline-shift'] = false; // default: baseline
  9353. whiteList['binding'] = false; // default: none
  9354. whiteList['bleed'] = false; // default: 6pt
  9355. whiteList['bookmark-label'] = false; // default: content()
  9356. whiteList['bookmark-level'] = false; // default: none
  9357. whiteList['bookmark-state'] = false; // default: open
  9358. whiteList['border'] = true; // default: depending on individual properties
  9359. whiteList['border-bottom'] = true; // default: depending on individual properties
  9360. whiteList['border-bottom-color'] = true; // default: current color
  9361. whiteList['border-bottom-left-radius'] = true; // default: 0
  9362. whiteList['border-bottom-right-radius'] = true; // default: 0
  9363. whiteList['border-bottom-style'] = true; // default: none
  9364. whiteList['border-bottom-width'] = true; // default: medium
  9365. whiteList['border-collapse'] = true; // default: separate
  9366. whiteList['border-color'] = true; // default: depending on individual properties
  9367. whiteList['border-image'] = true; // default: none
  9368. whiteList['border-image-outset'] = true; // default: 0
  9369. whiteList['border-image-repeat'] = true; // default: stretch
  9370. whiteList['border-image-slice'] = true; // default: 100%
  9371. whiteList['border-image-source'] = true; // default: none
  9372. whiteList['border-image-width'] = true; // default: 1
  9373. whiteList['border-left'] = true; // default: depending on individual properties
  9374. whiteList['border-left-color'] = true; // default: current color
  9375. whiteList['border-left-style'] = true; // default: none
  9376. whiteList['border-left-width'] = true; // default: medium
  9377. whiteList['border-radius'] = true; // default: 0
  9378. whiteList['border-right'] = true; // default: depending on individual properties
  9379. whiteList['border-right-color'] = true; // default: current color
  9380. whiteList['border-right-style'] = true; // default: none
  9381. whiteList['border-right-width'] = true; // default: medium
  9382. whiteList['border-spacing'] = true; // default: 0
  9383. whiteList['border-style'] = true; // default: depending on individual properties
  9384. whiteList['border-top'] = true; // default: depending on individual properties
  9385. whiteList['border-top-color'] = true; // default: current color
  9386. whiteList['border-top-left-radius'] = true; // default: 0
  9387. whiteList['border-top-right-radius'] = true; // default: 0
  9388. whiteList['border-top-style'] = true; // default: none
  9389. whiteList['border-top-width'] = true; // default: medium
  9390. whiteList['border-width'] = true; // default: depending on individual properties
  9391. whiteList['bottom'] = false; // default: auto
  9392. whiteList['box-decoration-break'] = true; // default: slice
  9393. whiteList['box-shadow'] = true; // default: none
  9394. whiteList['box-sizing'] = true; // default: content-box
  9395. whiteList['box-snap'] = true; // default: none
  9396. whiteList['box-suppress'] = true; // default: show
  9397. whiteList['break-after'] = true; // default: auto
  9398. whiteList['break-before'] = true; // default: auto
  9399. whiteList['break-inside'] = true; // default: auto
  9400. whiteList['caption-side'] = false; // default: top
  9401. whiteList['chains'] = false; // default: none
  9402. whiteList['clear'] = true; // default: none
  9403. whiteList['clip'] = false; // default: auto
  9404. whiteList['clip-path'] = false; // default: none
  9405. whiteList['clip-rule'] = false; // default: nonzero
  9406. whiteList['color'] = true; // default: implementation dependent
  9407. whiteList['color-interpolation-filters'] = true; // default: auto
  9408. whiteList['column-count'] = false; // default: auto
  9409. whiteList['column-fill'] = false; // default: balance
  9410. whiteList['column-gap'] = false; // default: normal
  9411. whiteList['column-rule'] = false; // default: depending on individual properties
  9412. whiteList['column-rule-color'] = false; // default: current color
  9413. whiteList['column-rule-style'] = false; // default: medium
  9414. whiteList['column-rule-width'] = false; // default: medium
  9415. whiteList['column-span'] = false; // default: none
  9416. whiteList['column-width'] = false; // default: auto
  9417. whiteList['columns'] = false; // default: depending on individual properties
  9418. whiteList['contain'] = false; // default: none
  9419. whiteList['content'] = false; // default: normal
  9420. whiteList['counter-increment'] = false; // default: none
  9421. whiteList['counter-reset'] = false; // default: none
  9422. whiteList['counter-set'] = false; // default: none
  9423. whiteList['crop'] = false; // default: auto
  9424. whiteList['cue'] = false; // default: depending on individual properties
  9425. whiteList['cue-after'] = false; // default: none
  9426. whiteList['cue-before'] = false; // default: none
  9427. whiteList['cursor'] = false; // default: auto
  9428. whiteList['direction'] = false; // default: ltr
  9429. whiteList['display'] = true; // default: depending on individual properties
  9430. whiteList['display-inside'] = true; // default: auto
  9431. whiteList['display-list'] = true; // default: none
  9432. whiteList['display-outside'] = true; // default: inline-level
  9433. whiteList['dominant-baseline'] = false; // default: auto
  9434. whiteList['elevation'] = false; // default: level
  9435. whiteList['empty-cells'] = false; // default: show
  9436. whiteList['filter'] = false; // default: none
  9437. whiteList['flex'] = false; // default: depending on individual properties
  9438. whiteList['flex-basis'] = false; // default: auto
  9439. whiteList['flex-direction'] = false; // default: row
  9440. whiteList['flex-flow'] = false; // default: depending on individual properties
  9441. whiteList['flex-grow'] = false; // default: 0
  9442. whiteList['flex-shrink'] = false; // default: 1
  9443. whiteList['flex-wrap'] = false; // default: nowrap
  9444. whiteList['float'] = false; // default: none
  9445. whiteList['float-offset'] = false; // default: 0 0
  9446. whiteList['flood-color'] = false; // default: black
  9447. whiteList['flood-opacity'] = false; // default: 1
  9448. whiteList['flow-from'] = false; // default: none
  9449. whiteList['flow-into'] = false; // default: none
  9450. whiteList['font'] = true; // default: depending on individual properties
  9451. whiteList['font-family'] = true; // default: implementation dependent
  9452. whiteList['font-feature-settings'] = true; // default: normal
  9453. whiteList['font-kerning'] = true; // default: auto
  9454. whiteList['font-language-override'] = true; // default: normal
  9455. whiteList['font-size'] = true; // default: medium
  9456. whiteList['font-size-adjust'] = true; // default: none
  9457. whiteList['font-stretch'] = true; // default: normal
  9458. whiteList['font-style'] = true; // default: normal
  9459. whiteList['font-synthesis'] = true; // default: weight style
  9460. whiteList['font-variant'] = true; // default: normal
  9461. whiteList['font-variant-alternates'] = true; // default: normal
  9462. whiteList['font-variant-caps'] = true; // default: normal
  9463. whiteList['font-variant-east-asian'] = true; // default: normal
  9464. whiteList['font-variant-ligatures'] = true; // default: normal
  9465. whiteList['font-variant-numeric'] = true; // default: normal
  9466. whiteList['font-variant-position'] = true; // default: normal
  9467. whiteList['font-weight'] = true; // default: normal
  9468. whiteList['grid'] = false; // default: depending on individual properties
  9469. whiteList['grid-area'] = false; // default: depending on individual properties
  9470. whiteList['grid-auto-columns'] = false; // default: auto
  9471. whiteList['grid-auto-flow'] = false; // default: none
  9472. whiteList['grid-auto-rows'] = false; // default: auto
  9473. whiteList['grid-column'] = false; // default: depending on individual properties
  9474. whiteList['grid-column-end'] = false; // default: auto
  9475. whiteList['grid-column-start'] = false; // default: auto
  9476. whiteList['grid-row'] = false; // default: depending on individual properties
  9477. whiteList['grid-row-end'] = false; // default: auto
  9478. whiteList['grid-row-start'] = false; // default: auto
  9479. whiteList['grid-template'] = false; // default: depending on individual properties
  9480. whiteList['grid-template-areas'] = false; // default: none
  9481. whiteList['grid-template-columns'] = false; // default: none
  9482. whiteList['grid-template-rows'] = false; // default: none
  9483. whiteList['hanging-punctuation'] = false; // default: none
  9484. whiteList['height'] = true; // default: auto
  9485. whiteList['hyphens'] = false; // default: manual
  9486. whiteList['icon'] = false; // default: auto
  9487. whiteList['image-orientation'] = false; // default: auto
  9488. whiteList['image-resolution'] = false; // default: normal
  9489. whiteList['ime-mode'] = false; // default: auto
  9490. whiteList['initial-letters'] = false; // default: normal
  9491. whiteList['inline-box-align'] = false; // default: last
  9492. whiteList['justify-content'] = false; // default: auto
  9493. whiteList['justify-items'] = false; // default: auto
  9494. whiteList['justify-self'] = false; // default: auto
  9495. whiteList['left'] = false; // default: auto
  9496. whiteList['letter-spacing'] = true; // default: normal
  9497. whiteList['lighting-color'] = true; // default: white
  9498. whiteList['line-box-contain'] = false; // default: block inline replaced
  9499. whiteList['line-break'] = false; // default: auto
  9500. whiteList['line-grid'] = false; // default: match-parent
  9501. whiteList['line-height'] = false; // default: normal
  9502. whiteList['line-snap'] = false; // default: none
  9503. whiteList['line-stacking'] = false; // default: depending on individual properties
  9504. whiteList['line-stacking-ruby'] = false; // default: exclude-ruby
  9505. whiteList['line-stacking-shift'] = false; // default: consider-shifts
  9506. whiteList['line-stacking-strategy'] = false; // default: inline-line-height
  9507. whiteList['list-style'] = true; // default: depending on individual properties
  9508. whiteList['list-style-image'] = true; // default: none
  9509. whiteList['list-style-position'] = true; // default: outside
  9510. whiteList['list-style-type'] = true; // default: disc
  9511. whiteList['margin'] = true; // default: depending on individual properties
  9512. whiteList['margin-bottom'] = true; // default: 0
  9513. whiteList['margin-left'] = true; // default: 0
  9514. whiteList['margin-right'] = true; // default: 0
  9515. whiteList['margin-top'] = true; // default: 0
  9516. whiteList['marker-offset'] = false; // default: auto
  9517. whiteList['marker-side'] = false; // default: list-item
  9518. whiteList['marks'] = false; // default: none
  9519. whiteList['mask'] = false; // default: border-box
  9520. whiteList['mask-box'] = false; // default: see individual properties
  9521. whiteList['mask-box-outset'] = false; // default: 0
  9522. whiteList['mask-box-repeat'] = false; // default: stretch
  9523. whiteList['mask-box-slice'] = false; // default: 0 fill
  9524. whiteList['mask-box-source'] = false; // default: none
  9525. whiteList['mask-box-width'] = false; // default: auto
  9526. whiteList['mask-clip'] = false; // default: border-box
  9527. whiteList['mask-image'] = false; // default: none
  9528. whiteList['mask-origin'] = false; // default: border-box
  9529. whiteList['mask-position'] = false; // default: center
  9530. whiteList['mask-repeat'] = false; // default: no-repeat
  9531. whiteList['mask-size'] = false; // default: border-box
  9532. whiteList['mask-source-type'] = false; // default: auto
  9533. whiteList['mask-type'] = false; // default: luminance
  9534. whiteList['max-height'] = true; // default: none
  9535. whiteList['max-lines'] = false; // default: none
  9536. whiteList['max-width'] = true; // default: none
  9537. whiteList['min-height'] = true; // default: 0
  9538. whiteList['min-width'] = true; // default: 0
  9539. whiteList['move-to'] = false; // default: normal
  9540. whiteList['nav-down'] = false; // default: auto
  9541. whiteList['nav-index'] = false; // default: auto
  9542. whiteList['nav-left'] = false; // default: auto
  9543. whiteList['nav-right'] = false; // default: auto
  9544. whiteList['nav-up'] = false; // default: auto
  9545. whiteList['object-fit'] = false; // default: fill
  9546. whiteList['object-position'] = false; // default: 50% 50%
  9547. whiteList['opacity'] = false; // default: 1
  9548. whiteList['order'] = false; // default: 0
  9549. whiteList['orphans'] = false; // default: 2
  9550. whiteList['outline'] = false; // default: depending on individual properties
  9551. whiteList['outline-color'] = false; // default: invert
  9552. whiteList['outline-offset'] = false; // default: 0
  9553. whiteList['outline-style'] = false; // default: none
  9554. whiteList['outline-width'] = false; // default: medium
  9555. whiteList['overflow'] = false; // default: depending on individual properties
  9556. whiteList['overflow-wrap'] = false; // default: normal
  9557. whiteList['overflow-x'] = false; // default: visible
  9558. whiteList['overflow-y'] = false; // default: visible
  9559. whiteList['padding'] = true; // default: depending on individual properties
  9560. whiteList['padding-bottom'] = true; // default: 0
  9561. whiteList['padding-left'] = true; // default: 0
  9562. whiteList['padding-right'] = true; // default: 0
  9563. whiteList['padding-top'] = true; // default: 0
  9564. whiteList['page'] = false; // default: auto
  9565. whiteList['page-break-after'] = false; // default: auto
  9566. whiteList['page-break-before'] = false; // default: auto
  9567. whiteList['page-break-inside'] = false; // default: auto
  9568. whiteList['page-policy'] = false; // default: start
  9569. whiteList['pause'] = false; // default: implementation dependent
  9570. whiteList['pause-after'] = false; // default: implementation dependent
  9571. whiteList['pause-before'] = false; // default: implementation dependent
  9572. whiteList['perspective'] = false; // default: none
  9573. whiteList['perspective-origin'] = false; // default: 50% 50%
  9574. whiteList['pitch'] = false; // default: medium
  9575. whiteList['pitch-range'] = false; // default: 50
  9576. whiteList['play-during'] = false; // default: auto
  9577. whiteList['position'] = false; // default: static
  9578. whiteList['presentation-level'] = false; // default: 0
  9579. whiteList['quotes'] = false; // default: text
  9580. whiteList['region-fragment'] = false; // default: auto
  9581. whiteList['resize'] = false; // default: none
  9582. whiteList['rest'] = false; // default: depending on individual properties
  9583. whiteList['rest-after'] = false; // default: none
  9584. whiteList['rest-before'] = false; // default: none
  9585. whiteList['richness'] = false; // default: 50
  9586. whiteList['right'] = false; // default: auto
  9587. whiteList['rotation'] = false; // default: 0
  9588. whiteList['rotation-point'] = false; // default: 50% 50%
  9589. whiteList['ruby-align'] = false; // default: auto
  9590. whiteList['ruby-merge'] = false; // default: separate
  9591. whiteList['ruby-position'] = false; // default: before
  9592. whiteList['shape-image-threshold'] = false; // default: 0.0
  9593. whiteList['shape-outside'] = false; // default: none
  9594. whiteList['shape-margin'] = false; // default: 0
  9595. whiteList['size'] = false; // default: auto
  9596. whiteList['speak'] = false; // default: auto
  9597. whiteList['speak-as'] = false; // default: normal
  9598. whiteList['speak-header'] = false; // default: once
  9599. whiteList['speak-numeral'] = false; // default: continuous
  9600. whiteList['speak-punctuation'] = false; // default: none
  9601. whiteList['speech-rate'] = false; // default: medium
  9602. whiteList['stress'] = false; // default: 50
  9603. whiteList['string-set'] = false; // default: none
  9604. whiteList['tab-size'] = false; // default: 8
  9605. whiteList['table-layout'] = false; // default: auto
  9606. whiteList['text-align'] = true; // default: start
  9607. whiteList['text-align-last'] = true; // default: auto
  9608. whiteList['text-combine-upright'] = true; // default: none
  9609. whiteList['text-decoration'] = true; // default: none
  9610. whiteList['text-decoration-color'] = true; // default: currentColor
  9611. whiteList['text-decoration-line'] = true; // default: none
  9612. whiteList['text-decoration-skip'] = true; // default: objects
  9613. whiteList['text-decoration-style'] = true; // default: solid
  9614. whiteList['text-emphasis'] = true; // default: depending on individual properties
  9615. whiteList['text-emphasis-color'] = true; // default: currentColor
  9616. whiteList['text-emphasis-position'] = true; // default: over right
  9617. whiteList['text-emphasis-style'] = true; // default: none
  9618. whiteList['text-height'] = true; // default: auto
  9619. whiteList['text-indent'] = true; // default: 0
  9620. whiteList['text-justify'] = true; // default: auto
  9621. whiteList['text-orientation'] = true; // default: mixed
  9622. whiteList['text-overflow'] = true; // default: clip
  9623. whiteList['text-shadow'] = true; // default: none
  9624. whiteList['text-space-collapse'] = true; // default: collapse
  9625. whiteList['text-transform'] = true; // default: none
  9626. whiteList['text-underline-position'] = true; // default: auto
  9627. whiteList['text-wrap'] = true; // default: normal
  9628. whiteList['top'] = false; // default: auto
  9629. whiteList['transform'] = false; // default: none
  9630. whiteList['transform-origin'] = false; // default: 50% 50% 0
  9631. whiteList['transform-style'] = false; // default: flat
  9632. whiteList['transition'] = false; // default: depending on individual properties
  9633. whiteList['transition-delay'] = false; // default: 0s
  9634. whiteList['transition-duration'] = false; // default: 0s
  9635. whiteList['transition-property'] = false; // default: all
  9636. whiteList['transition-timing-function'] = false; // default: ease
  9637. whiteList['unicode-bidi'] = false; // default: normal
  9638. whiteList['vertical-align'] = false; // default: baseline
  9639. whiteList['visibility'] = false; // default: visible
  9640. whiteList['voice-balance'] = false; // default: center
  9641. whiteList['voice-duration'] = false; // default: auto
  9642. whiteList['voice-family'] = false; // default: implementation dependent
  9643. whiteList['voice-pitch'] = false; // default: medium
  9644. whiteList['voice-range'] = false; // default: medium
  9645. whiteList['voice-rate'] = false; // default: normal
  9646. whiteList['voice-stress'] = false; // default: normal
  9647. whiteList['voice-volume'] = false; // default: medium
  9648. whiteList['volume'] = false; // default: medium
  9649. whiteList['white-space'] = false; // default: normal
  9650. whiteList['widows'] = false; // default: 2
  9651. whiteList['width'] = true; // default: auto
  9652. whiteList['will-change'] = false; // default: auto
  9653. whiteList['word-break'] = true; // default: normal
  9654. whiteList['word-spacing'] = true; // default: normal
  9655. whiteList['word-wrap'] = true; // default: normal
  9656. whiteList['wrap-flow'] = false; // default: auto
  9657. whiteList['wrap-through'] = false; // default: wrap
  9658. whiteList['writing-mode'] = false; // default: horizontal-tb
  9659. whiteList['z-index'] = false; // default: auto
  9660. return whiteList;
  9661. }
  9662. /**
  9663. * 匹配到白名单上的一个属性时
  9664. *
  9665. * @param {String} name
  9666. * @param {String} value
  9667. * @param {Object} options
  9668. * @return {String}
  9669. */
  9670. function onAttr (name, value, options) {
  9671. // do nothing
  9672. }
  9673. /**
  9674. * 匹配到不在白名单上的一个属性时
  9675. *
  9676. * @param {String} name
  9677. * @param {String} value
  9678. * @param {Object} options
  9679. * @return {String}
  9680. */
  9681. function onIgnoreAttr (name, value, options) {
  9682. // do nothing
  9683. }
  9684. exports.whiteList = getDefaultWhiteList();
  9685. exports.getDefaultWhiteList = getDefaultWhiteList;
  9686. exports.onAttr = onAttr;
  9687. exports.onIgnoreAttr = onIgnoreAttr;
  9688. },{}],8:[function(require,module,exports){
  9689. /**
  9690. * cssfilter
  9691. *
  9692. * @author 老雷<leizongmin@gmail.com>
  9693. */
  9694. var DEFAULT = require('./default');
  9695. var FilterCSS = require('./css');
  9696. /**
  9697. * XSS过滤
  9698. *
  9699. * @param {String} css 要过滤的CSS代码
  9700. * @param {Object} options 选项:whiteList, onAttr, onIgnoreAttr
  9701. * @return {String}
  9702. */
  9703. function filterCSS (html, options) {
  9704. var xss = new FilterCSS(options);
  9705. return xss.process(html);
  9706. }
  9707. // 输出
  9708. exports = module.exports = filterCSS;
  9709. exports.FilterCSS = FilterCSS;
  9710. for (var i in DEFAULT) exports[i] = DEFAULT[i];
  9711. // 在浏览器端使用
  9712. if (typeof window !== 'undefined') {
  9713. window.filterCSS = module.exports;
  9714. }
  9715. },{"./css":6,"./default":7}],9:[function(require,module,exports){
  9716. /**
  9717. * cssfilter
  9718. *
  9719. * @author 老雷<leizongmin@gmail.com>
  9720. */
  9721. var _ = require('./util');
  9722. /**
  9723. * 解析style
  9724. *
  9725. * @param {String} css
  9726. * @param {Function} onAttr 处理属性的函数
  9727. * 参数格式: function (sourcePosition, position, name, value, source)
  9728. * @return {String}
  9729. */
  9730. function parseStyle (css, onAttr) {
  9731. css = _.trimRight(css);
  9732. if (css[css.length - 1] !== ';') css += ';';
  9733. var cssLength = css.length;
  9734. var isParenthesisOpen = false;
  9735. var lastPos = 0;
  9736. var i = 0;
  9737. var retCSS = '';
  9738. function addNewAttr () {
  9739. // 如果没有正常的闭合圆括号,则直接忽略当前属性
  9740. if (!isParenthesisOpen) {
  9741. var source = _.trim(css.slice(lastPos, i));
  9742. var j = source.indexOf(':');
  9743. if (j !== -1) {
  9744. var name = _.trim(source.slice(0, j));
  9745. var value = _.trim(source.slice(j + 1));
  9746. // 必须有属性名称
  9747. if (name) {
  9748. var ret = onAttr(lastPos, retCSS.length, name, value, source);
  9749. if (ret) retCSS += ret + '; ';
  9750. }
  9751. }
  9752. }
  9753. lastPos = i + 1;
  9754. }
  9755. for (; i < cssLength; i++) {
  9756. var c = css[i];
  9757. if (c === '/' && css[i + 1] === '*') {
  9758. // 备注开始
  9759. var j = css.indexOf('*/', i + 2);
  9760. // 如果没有正常的备注结束,则后面的部分全部跳过
  9761. if (j === -1) break;
  9762. // 直接将当前位置调到备注结尾,并且初始化状态
  9763. i = j + 1;
  9764. lastPos = i + 1;
  9765. isParenthesisOpen = false;
  9766. } else if (c === '(') {
  9767. isParenthesisOpen = true;
  9768. } else if (c === ')') {
  9769. isParenthesisOpen = false;
  9770. } else if (c === ';') {
  9771. if (isParenthesisOpen) {
  9772. // 在圆括号里面,忽略
  9773. } else {
  9774. addNewAttr();
  9775. }
  9776. } else if (c === '\n') {
  9777. addNewAttr();
  9778. }
  9779. }
  9780. return _.trim(retCSS);
  9781. }
  9782. module.exports = parseStyle;
  9783. },{"./util":10}],10:[function(require,module,exports){
  9784. module.exports = {
  9785. indexOf: function (arr, item) {
  9786. var i, j;
  9787. if (Array.prototype.indexOf) {
  9788. return arr.indexOf(item);
  9789. }
  9790. for (i = 0, j = arr.length; i < j; i++) {
  9791. if (arr[i] === item) {
  9792. return i;
  9793. }
  9794. }
  9795. return -1;
  9796. },
  9797. forEach: function (arr, fn, scope) {
  9798. var i, j;
  9799. if (Array.prototype.forEach) {
  9800. return arr.forEach(fn, scope);
  9801. }
  9802. for (i = 0, j = arr.length; i < j; i++) {
  9803. fn.call(scope, arr[i], i, arr);
  9804. }
  9805. },
  9806. trim: function (str) {
  9807. if (String.prototype.trim) {
  9808. return str.trim();
  9809. }
  9810. return str.replace(/(^\s*)|(\s*$)/g, '');
  9811. },
  9812. trimRight: function (str) {
  9813. if (String.prototype.trimRight) {
  9814. return str.trimRight();
  9815. }
  9816. return str.replace(/(\s*$)/g, '');
  9817. }
  9818. };
  9819. },{}]},{},[2]);
  9820. define("xss", (function (global) {
  9821. return function () {
  9822. var ret, fn;
  9823. fn = function (xss_noconflict) {
  9824. return {
  9825. filterXSS: window.filterXSS,
  9826. filterCSS: window.filterCSS
  9827. }
  9828. };
  9829. ret = fn.apply(global, arguments);
  9830. return ret;
  9831. };
  9832. }(this)));
  9833. define('tpl!chatbox', ['lodash'], function(_) {return function(obj) {
  9834. obj || (obj = {});
  9835. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  9836. function print() { __p += __j.call(arguments, '') }
  9837. with (obj) {
  9838. __p += '<div class="flyout box-flyout">\n <div class="chat-head chat-head-chatbox">\n <a class="chatbox-btn close-chatbox-button icon-close" title="' +
  9839. __e(info_close) +
  9840. '"></a>\n <div class="chat-title">\n ';
  9841. if (url) { ;
  9842. __p += '\n <a href="' +
  9843. __e(url) +
  9844. '" target="_blank" rel="noopener" class="user">\n ';
  9845. } ;
  9846. __p += '\n ' +
  9847. __e( title ) +
  9848. '\n ';
  9849. if (url) { ;
  9850. __p += '\n </a>\n ';
  9851. } ;
  9852. __p += '\n <p class="user-custom-message"><p/>\n </div>\n </div>\n <div class="chat-body">\n <div class="chat-content ';
  9853. if (show_send_button) { ;
  9854. __p += 'chat-content-sendbutton';
  9855. } ;
  9856. __p += '"></div>\n <div class="new-msgs-indicator hidden">▼ ' +
  9857. __e( unread_msgs ) +
  9858. ' ▼</div>\n ';
  9859. if (show_textarea) { ;
  9860. __p += '\n <form class="sendXMPPMessage">\n ';
  9861. if (show_toolbar) { ;
  9862. __p += '\n <ul class="chat-toolbar no-text-select"></ul>\n ';
  9863. } ;
  9864. __p += '\n <textarea\n type="text"\n class="chat-textarea ';
  9865. if (show_send_button) { ;
  9866. __p += 'chat-textarea-send-button';
  9867. } ;
  9868. __p += '"\n placeholder="' +
  9869. __e(label_personal_message) +
  9870. '"/>\n\n ';
  9871. if (show_send_button) { ;
  9872. __p += '\n <button type="submit" class="pure-button send-button">' +
  9873. __e( label_send ) +
  9874. '</button>\n ';
  9875. } ;
  9876. __p += '\n </form>\n ';
  9877. } ;
  9878. __p += '\n </div>\n</div>\n';
  9879. }
  9880. return __p
  9881. };});
  9882. define('tpl!new_day', ['lodash'], function(_) {return function(obj) {
  9883. obj || (obj = {});
  9884. var __t, __p = '', __e = _.escape;
  9885. with (obj) {
  9886. __p += '<time class="chat-info chat-date" data-isodate="' +
  9887. __e(isodate) +
  9888. '">' +
  9889. __e(datestring) +
  9890. '</time>\n';
  9891. }
  9892. return __p
  9893. };});
  9894. define('tpl!action', ['lodash'], function(_) {return function(obj) {
  9895. obj || (obj = {});
  9896. var __t, __p = '', __e = _.escape;
  9897. with (obj) {
  9898. __p += '<div class="chat-message ' +
  9899. __e(extra_classes) +
  9900. '" data-isodate="' +
  9901. __e(isodate) +
  9902. '">\n <span class="chat-msg-author chat-msg-' +
  9903. __e(sender) +
  9904. '">' +
  9905. __e(time) +
  9906. ' **' +
  9907. __e(username) +
  9908. '&nbsp;</span>\n <span class="chat-msg-content chat-action"><!-- message gets added here via renderMessage --></span>\n</div>\n';
  9909. }
  9910. return __p
  9911. };});
  9912. define('tpl!emojis', ['lodash'], function(_) {return function(obj) {
  9913. obj || (obj = {});
  9914. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  9915. function print() { __p += __j.call(arguments, '') }
  9916. with (obj) {
  9917. _.forEach(emojis_by_category, function (obj, category) { ;
  9918. __p += '\n <ul class="emoji-picker emoji-picker-' +
  9919. __e(category) +
  9920. ' ';
  9921. if (current_category !== category) { ;
  9922. __p += ' hidden ';
  9923. } ;
  9924. __p += '">\n ';
  9925. _.forEach(emojis_by_category[category], function (emoji) { ;
  9926. __p += '\n <li class="emoji insert-emoji ';
  9927. if (shouldBeHidden(emoji._shortname, current_skintone, toned_emojis)) { ;
  9928. __p += ' hidden ';
  9929. }; ;
  9930. __p += '"\n data-emoji="' +
  9931. __e(emoji._shortname) +
  9932. '">\n <a href="#" data-emoji="' +
  9933. __e(emoji._shortname) +
  9934. '"> ' +
  9935. ((__t = ( transform(emoji._shortname) )) == null ? '' : __t) +
  9936. ' </a>\n </li>\n ';
  9937. }); ;
  9938. __p += '\n </ul>\n';
  9939. }); ;
  9940. __p += '\n<ul class="emoji-toolbar">\n <li class="emoji-category-picker">\n <ul>\n ';
  9941. _.forEach(emojis_by_category, function (obj, category) { ;
  9942. __p += '\n <li data-category="' +
  9943. __e(category) +
  9944. '" class="emoji-category ';
  9945. if (current_category === category) { ;
  9946. __p += ' picked ';
  9947. } ;
  9948. __p += '">\n <a class="pick-category" href="#" data-category="' +
  9949. __e(category) +
  9950. '"> ' +
  9951. ((__t = ( transform(emojis_by_category[category][0]._shortname) )) == null ? '' : __t) +
  9952. ' </a>\n </li>\n ';
  9953. }); ;
  9954. __p += '\n </ul>\n </li>\n <li class="emoji-skintone-picker">\n <ul>\n ';
  9955. _.forEach(skintones, function (skintone) { ;
  9956. __p += '\n <li data-skintone="' +
  9957. __e(skintone) +
  9958. '" class="emoji-skintone ';
  9959. if (current_skintone === skintone) { ;
  9960. __p += ' picked ';
  9961. } ;
  9962. __p += '">\n <a class="pick-skintone" href="#" data-skintone="' +
  9963. __e(skintone) +
  9964. '"> ' +
  9965. ((__t = ( transform(':'+skintone+':') )) == null ? '' : __t) +
  9966. ' </a>\n </li>\n ';
  9967. }); ;
  9968. __p += '\n </ul>\n </li>\n</ul>\n';
  9969. }
  9970. return __p
  9971. };});
  9972. define('tpl!message', ['lodash'], function(_) {return function(obj) {
  9973. obj || (obj = {});
  9974. var __t, __p = '', __e = _.escape;
  9975. with (obj) {
  9976. __p += '<div class="chat-message ' +
  9977. __e(extra_classes) +
  9978. '" data-isodate="' +
  9979. __e(isodate) +
  9980. '" data-msgid="' +
  9981. __e(msgid) +
  9982. '">\n <span class="chat-msg-author chat-msg-' +
  9983. __e(sender) +
  9984. '">' +
  9985. __e(time) +
  9986. ' ' +
  9987. __e(username) +
  9988. ':&nbsp;</span>\n <span class="chat-msg-content"><!-- message gets added here via renderMessage --></span>\n</div>\n';
  9989. }
  9990. return __p
  9991. };});
  9992. define('tpl!help_message', ['lodash'], function(_) {return function(obj) {
  9993. obj || (obj = {});
  9994. var __t, __p = '', __e = _.escape;
  9995. with (obj) {
  9996. __p += '<div class="chat-' +
  9997. __e(type) +
  9998. '">' +
  9999. __e(message) +
  10000. '</div>\n';
  10001. }
  10002. return __p
  10003. };});
  10004. define('tpl!toolbar', ['lodash'], function(_) {return function(obj) {
  10005. obj || (obj = {});
  10006. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  10007. function print() { __p += __j.call(arguments, '') }
  10008. with (obj) {
  10009. if (use_emoji) { ;
  10010. __p += '\n <li class="toggle-toolbar-menu toggle-smiley icon-happy" title="' +
  10011. __e(label_insert_smiley) +
  10012. '">\n <ul class="emoji-picker"></ul>\n </li>\n';
  10013. } ;
  10014. __p += '\n';
  10015. if (show_call_button) { ;
  10016. __p += '\n<li class="toggle-call"><a class="icon-phone" title="' +
  10017. __e(label_start_call) +
  10018. '"></a></li>\n';
  10019. } ;
  10020. __p += '\n';
  10021. if (show_clear_button) { ;
  10022. __p += '\n<li class="toggle-clear"><a class="icon-trash" title="' +
  10023. __e(label_clear) +
  10024. '"></a></li>\n';
  10025. } ;
  10026. __p += '\n';
  10027. }
  10028. return __p
  10029. };});
  10030. define('tpl!avatar', ['lodash'], function(_) {return function(obj) {
  10031. obj || (obj = {});
  10032. var __t, __p = '';
  10033. with (obj) {
  10034. __p += '<canvas height="' +
  10035. ((__t = (height)) == null ? '' : __t) +
  10036. 'px" width="' +
  10037. ((__t = (width)) == null ? '' : __t) +
  10038. 'px" class="avatar"></canvas>\n';
  10039. }
  10040. return __p
  10041. };});
  10042. define('tpl!spinner', ['lodash'], function(_) {return function(obj) {
  10043. obj || (obj = {});
  10044. var __t, __p = '';
  10045. with (obj) {
  10046. __p += '<span class="spinner centered"/>\n';
  10047. }
  10048. return __p
  10049. };});
  10050. // Converse.js (A browser based XMPP chat client)
  10051. // http://conversejs.org
  10052. //
  10053. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  10054. // Licensed under the Mozilla Public License (MPLv2)
  10055. //
  10056. /*global define */
  10057. (function (root, factory) {
  10058. define('converse-chatview',["jquery.noconflict", "converse-core", "emojione", "xss", "tpl!chatbox", "tpl!new_day", "tpl!action", "tpl!emojis", "tpl!message", "tpl!help_message", "tpl!toolbar", "tpl!avatar", "tpl!spinner"], factory);
  10059. })(undefined, function ($, converse, emojione, xss, tpl_chatbox, tpl_new_day, tpl_action, tpl_emojis, tpl_message, tpl_help_message, tpl_toolbar, tpl_avatar, tpl_spinner) {
  10060. "use strict";
  10061. var _converse$env = converse.env,
  10062. $msg = _converse$env.$msg,
  10063. Backbone = _converse$env.Backbone,
  10064. Strophe = _converse$env.Strophe,
  10065. _ = _converse$env._,
  10066. b64_sha1 = _converse$env.b64_sha1,
  10067. moment = _converse$env.moment,
  10068. utils = _converse$env.utils;
  10069. var KEY = {
  10070. ENTER: 13,
  10071. FORWARD_SLASH: 47
  10072. };
  10073. converse.plugins.add('converse-chatview', {
  10074. overrides: {
  10075. // Overrides mentioned here will be picked up by converse.js's
  10076. // plugin architecture they will replace existing methods on the
  10077. // relevant objects or classes.
  10078. //
  10079. // New functions which don't exist yet can also be added.
  10080. //
  10081. registerGlobalEventHandlers: function registerGlobalEventHandlers() {
  10082. this.__super__.registerGlobalEventHandlers();
  10083. document.addEventListener('click', function (ev) {
  10084. if (_.includes(ev.target.classList, 'toggle-toolbar-menu') || _.includes(ev.target.classList, 'insert-emoji')) {
  10085. return;
  10086. }
  10087. utils.slideInAllElements(document.querySelectorAll('.toolbar-menu'));
  10088. });
  10089. },
  10090. ChatBoxViews: {
  10091. onChatBoxAdded: function onChatBoxAdded(item) {
  10092. var _converse = this.__super__._converse;
  10093. var view = this.get(item.get('id'));
  10094. if (!view) {
  10095. view = new _converse.ChatBoxView({ model: item });
  10096. this.add(item.get('id'), view);
  10097. return view;
  10098. } else {
  10099. return this.__super__.onChatBoxAdded.apply(this, arguments);
  10100. }
  10101. }
  10102. }
  10103. },
  10104. initialize: function initialize() {
  10105. /* The initialize function gets called as soon as the plugin is
  10106. * loaded by converse.js's plugin machinery.
  10107. */
  10108. var _converse = this._converse,
  10109. __ = _converse.__;
  10110. _converse.api.settings.update({
  10111. 'use_emojione': true,
  10112. 'emojione_image_path': emojione.imagePathPNG,
  10113. 'chatview_avatar_height': 32,
  10114. 'chatview_avatar_width': 32,
  10115. 'show_toolbar': true,
  10116. 'time_format': 'HH:mm',
  10117. 'visible_toolbar_buttons': {
  10118. 'emoji': true,
  10119. 'call': false,
  10120. 'clear': true
  10121. }
  10122. });
  10123. emojione.imagePathPNG = _converse.emojione_image_path;
  10124. emojione.ascii = true;
  10125. function onWindowStateChanged(data) {
  10126. _converse.chatboxviews.each(function (chatboxview) {
  10127. chatboxview.onWindowStateChanged(data.state);
  10128. });
  10129. }
  10130. _converse.api.listen.on('windowStateChanged', onWindowStateChanged);
  10131. _converse.EmojiPicker = Backbone.Model.extend({
  10132. defaults: {
  10133. 'current_category': 'people',
  10134. 'current_skintone': '',
  10135. 'scroll_position': 0
  10136. },
  10137. initialize: function initialize() {
  10138. var id = "converse.emoji-" + _converse.bare_jid;
  10139. this.id = id;
  10140. this.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
  10141. }
  10142. });
  10143. _converse.EmojiPickerView = Backbone.View.extend({
  10144. className: 'emoji-picker-container toolbar-menu collapsed',
  10145. events: {
  10146. 'click .emoji-category-picker li.emoji-category': 'chooseCategory',
  10147. 'click .emoji-skintone-picker li.emoji-skintone': 'chooseSkinTone'
  10148. },
  10149. initialize: function initialize() {
  10150. this.model.on('change:current_skintone', this.render, this);
  10151. this.model.on('change:current_category', this.render, this);
  10152. this.setScrollPosition = _.debounce(this.setScrollPosition, 50);
  10153. },
  10154. render: function render() {
  10155. var _this = this;
  10156. var emojis_html = tpl_emojis(_.extend(this.model.toJSON(), {
  10157. 'transform': _converse.use_emojione ? emojione.shortnameToImage : emojione.shortnameToUnicode,
  10158. 'emojis_by_category': utils.getEmojisByCategory(_converse, emojione),
  10159. 'toned_emojis': utils.getTonedEmojis(_converse),
  10160. 'skintones': ['tone1', 'tone2', 'tone3', 'tone4', 'tone5'],
  10161. 'shouldBeHidden': this.shouldBeHidden
  10162. }));
  10163. this.el.innerHTML = emojis_html;
  10164. _.forEach(this.el.querySelectorAll('.emoji-picker'), function (el) {
  10165. el.addEventListener('scroll', _this.setScrollPosition.bind(_this));
  10166. });
  10167. this.restoreScrollPosition();
  10168. return this;
  10169. },
  10170. shouldBeHidden: function shouldBeHidden(shortname, current_skintone, toned_emojis) {
  10171. /* Helper method for the template which decides whether an
  10172. * emoji should be hidden, based on which skin tone is
  10173. * currently being applied.
  10174. */
  10175. if (_.includes(shortname, '_tone')) {
  10176. if (!current_skintone || !_.includes(shortname, current_skintone)) {
  10177. return true;
  10178. }
  10179. } else {
  10180. if (current_skintone && _.includes(toned_emojis, shortname)) {
  10181. return true;
  10182. }
  10183. }
  10184. return false;
  10185. },
  10186. restoreScrollPosition: function restoreScrollPosition() {
  10187. var current_picker = _.difference(this.el.querySelectorAll('.emoji-picker'), this.el.querySelectorAll('.emoji-picker.hidden'));
  10188. if (current_picker.length === 1 && this.model.get('scroll_position')) {
  10189. current_picker[0].scrollTop = this.model.get('scroll_position');
  10190. }
  10191. },
  10192. setScrollPosition: function setScrollPosition(ev) {
  10193. this.model.save('scroll_position', ev.target.scrollTop);
  10194. },
  10195. chooseSkinTone: function chooseSkinTone(ev) {
  10196. ev.preventDefault();
  10197. ev.stopPropagation();
  10198. var target = ev.target.nodeName === 'IMG' ? ev.target.parentElement : ev.target;
  10199. var skintone = target.getAttribute("data-skintone").trim();
  10200. if (this.model.get('current_skintone') === skintone) {
  10201. this.model.save({ 'current_skintone': '' });
  10202. } else {
  10203. this.model.save({ 'current_skintone': skintone });
  10204. }
  10205. },
  10206. chooseCategory: function chooseCategory(ev) {
  10207. ev.preventDefault();
  10208. ev.stopPropagation();
  10209. var target = ev.target.nodeName === 'IMG' ? ev.target.parentElement : ev.target;
  10210. var category = target.getAttribute("data-category").trim();
  10211. this.model.save({
  10212. 'current_category': category,
  10213. 'scroll_position': 0
  10214. });
  10215. }
  10216. });
  10217. _converse.ChatBoxView = Backbone.View.extend({
  10218. length: 200,
  10219. tagName: 'div',
  10220. className: 'chatbox hidden',
  10221. is_chatroom: false, // Leaky abstraction from MUC
  10222. events: {
  10223. 'click .close-chatbox-button': 'close',
  10224. 'keypress .chat-textarea': 'keyPressed',
  10225. 'click .send-button': 'onFormSubmitted',
  10226. 'click .toggle-smiley': 'toggleEmojiMenu',
  10227. 'click .toggle-smiley ul.emoji-picker li': 'insertEmoji',
  10228. 'click .toggle-clear': 'clearMessages',
  10229. 'click .toggle-call': 'toggleCall',
  10230. 'click .new-msgs-indicator': 'viewUnreadMessages'
  10231. },
  10232. initialize: function initialize() {
  10233. this.markScrolled = _.debounce(this.markScrolled, 100);
  10234. this.createEmojiPicker();
  10235. this.model.messages.on('add', this.onMessageAdded, this);
  10236. this.model.on('show', this.show, this);
  10237. this.model.on('destroy', this.hide, this);
  10238. // TODO check for changed fullname as well
  10239. this.model.on('change:chat_state', this.sendChatState, this);
  10240. this.model.on('change:chat_status', this.onChatStatusChanged, this);
  10241. this.model.on('change:image', this.renderAvatar, this);
  10242. this.model.on('change:status', this.onStatusChanged, this);
  10243. this.model.on('showHelpMessages', this.showHelpMessages, this);
  10244. this.model.on('sendMessage', this.sendMessage, this);
  10245. this.render().fetchMessages();
  10246. _converse.emit('chatBoxInitialized', this);
  10247. },
  10248. render: function render() {
  10249. this.$el.attr('id', this.model.get('box_id')).html(tpl_chatbox(_.extend(this.model.toJSON(), {
  10250. show_toolbar: _converse.show_toolbar,
  10251. show_textarea: true,
  10252. show_send_button: _converse.show_send_button,
  10253. title: this.model.get('fullname'),
  10254. unread_msgs: __('You have unread messages'),
  10255. info_close: __('Close this chat box'),
  10256. label_personal_message: __('Personal message'),
  10257. label_send: __('Send')
  10258. })));
  10259. this.$content = this.$el.find('.chat-content');
  10260. this.renderToolbar().renderAvatar();
  10261. _converse.emit('chatBoxOpened', this);
  10262. utils.refreshWebkit();
  10263. return this.showStatusMessage();
  10264. },
  10265. createEmojiPicker: function createEmojiPicker() {
  10266. if (_.isUndefined(_converse.emojipicker)) {
  10267. _converse.emojipicker = new _converse.EmojiPicker();
  10268. _converse.emojipicker.fetch();
  10269. }
  10270. this.emoji_picker_view = new _converse.EmojiPickerView({
  10271. 'model': _converse.emojipicker
  10272. });
  10273. },
  10274. afterMessagesFetched: function afterMessagesFetched() {
  10275. this.insertIntoDOM();
  10276. this.scrollDown();
  10277. // We only start listening for the scroll event after
  10278. // cached messages have been fetched
  10279. this.$content.on('scroll', this.markScrolled.bind(this));
  10280. _converse.emit('afterMessagesFetched', this);
  10281. },
  10282. fetchMessages: function fetchMessages() {
  10283. this.model.messages.fetch({
  10284. 'add': true,
  10285. 'success': this.afterMessagesFetched.bind(this),
  10286. 'error': this.afterMessagesFetched.bind(this)
  10287. });
  10288. return this;
  10289. },
  10290. insertIntoDOM: function insertIntoDOM() {
  10291. /* This method gets overridden in src/converse-controlbox.js if
  10292. * the controlbox plugin is active.
  10293. */
  10294. var container = document.querySelector('#conversejs');
  10295. if (this.el.parentNode !== container) {
  10296. container.insertBefore(this.el, container.firstChild);
  10297. }
  10298. return this;
  10299. },
  10300. clearStatusNotification: function clearStatusNotification() {
  10301. this.$content.find('div.chat-event').remove();
  10302. },
  10303. showStatusNotification: function showStatusNotification(message, keep_old, permanent) {
  10304. if (!keep_old) {
  10305. this.clearStatusNotification();
  10306. }
  10307. var $el = $('<div class="chat-info"></div>').text(message);
  10308. if (!permanent) {
  10309. $el.addClass('chat-event');
  10310. }
  10311. this.$content.append($el);
  10312. this.scrollDown();
  10313. },
  10314. addSpinner: function addSpinner() {
  10315. if (_.isNull(this.el.querySelector('.spinner'))) {
  10316. this.$content.prepend(tpl_spinner);
  10317. }
  10318. },
  10319. clearSpinner: function clearSpinner() {
  10320. if (this.$content.children(':first').is('span.spinner')) {
  10321. this.$content.children(':first').remove();
  10322. }
  10323. },
  10324. insertDayIndicator: function insertDayIndicator(date, prepend) {
  10325. /* Appends (or prepends if "prepend" is truthy) an indicator
  10326. * into the chat area, showing the day as given by the
  10327. * passed in date.
  10328. *
  10329. * Parameters:
  10330. * (String) date - An ISO8601 date string.
  10331. */
  10332. var day_date = moment(date).startOf('day');
  10333. var insert = prepend ? this.$content.prepend : this.$content.append;
  10334. insert.call(this.$content, tpl_new_day({
  10335. isodate: day_date.format(),
  10336. datestring: day_date.format("dddd MMM Do YYYY")
  10337. }));
  10338. },
  10339. insertMessage: function insertMessage(attrs, prepend) {
  10340. var _this2 = this;
  10341. /* Helper method which appends a message (or prepends if the
  10342. * 2nd parameter is set to true) to the end of the chat box's
  10343. * content area.
  10344. *
  10345. * Parameters:
  10346. * (Object) attrs: An object containing the message attributes.
  10347. */
  10348. var insert = prepend ? this.$content.prepend : this.$content.append;
  10349. _.flow(function ($el) {
  10350. insert.call(_this2.$content, $el);
  10351. return $el;
  10352. }, this.scrollDown.bind(this))(this.renderMessage(attrs));
  10353. },
  10354. showMessage: function showMessage(attrs) {
  10355. /* Inserts a chat message into the content area of the chat box.
  10356. * Will also insert a new day indicator if the message is on a
  10357. * different day.
  10358. *
  10359. * The message to show may either be newer than the newest
  10360. * message, or older than the oldest message.
  10361. *
  10362. * Parameters:
  10363. * (Object) attrs: An object containing the message
  10364. * attributes.
  10365. */
  10366. var current_msg_date = moment(attrs.time) || moment;
  10367. var $first_msg = this.$content.find('.chat-message:first'),
  10368. first_msg_date = $first_msg.data('isodate');
  10369. if (!first_msg_date) {
  10370. // This is the first received message, so we insert a
  10371. // date indicator before it.
  10372. this.insertDayIndicator(current_msg_date);
  10373. this.insertMessage(attrs);
  10374. return;
  10375. }
  10376. var last_msg_date = this.$content.find('.chat-message:last').data('isodate');
  10377. if (current_msg_date.isAfter(last_msg_date) || current_msg_date.isSame(last_msg_date)) {
  10378. // The new message is after the last message
  10379. if (current_msg_date.isAfter(last_msg_date, 'day')) {
  10380. // Append a new day indicator
  10381. this.insertDayIndicator(current_msg_date);
  10382. }
  10383. this.insertMessage(attrs);
  10384. return;
  10385. }
  10386. if (current_msg_date.isBefore(first_msg_date) || current_msg_date.isSame(first_msg_date)) {
  10387. // The message is before the first, but on the same day.
  10388. // We need to prepend the message immediately before the
  10389. // first message (so that it'll still be after the day
  10390. // indicator).
  10391. this.insertMessage(attrs, 'prepend');
  10392. if (current_msg_date.isBefore(first_msg_date, 'day')) {
  10393. // This message is also on a different day, so
  10394. // we prepend a day indicator.
  10395. this.insertDayIndicator(current_msg_date, 'prepend');
  10396. }
  10397. return;
  10398. }
  10399. // Find the correct place to position the message
  10400. current_msg_date = current_msg_date.format();
  10401. var msg_dates = _.map(this.$content.find('.chat-message'), function (el) {
  10402. return $(el).data('isodate');
  10403. });
  10404. msg_dates.push(current_msg_date);
  10405. msg_dates.sort();
  10406. var idx = msg_dates.indexOf(current_msg_date) - 1;
  10407. var $latest_message = this.$content.find(".chat-message[data-isodate=\"" + msg_dates[idx] + "\"]:last");
  10408. _.flow(function ($el) {
  10409. $el.insertAfter($latest_message);
  10410. return $el;
  10411. }, this.scrollDown.bind(this))(this.renderMessage(attrs));
  10412. },
  10413. getExtraMessageTemplateAttributes: function getExtraMessageTemplateAttributes() {
  10414. /* Provides a hook for sending more attributes to the
  10415. * message template.
  10416. *
  10417. * Parameters:
  10418. * (Object) attrs: An object containing message attributes.
  10419. */
  10420. return {};
  10421. },
  10422. getExtraMessageClasses: function getExtraMessageClasses(attrs) {
  10423. return attrs.delayed && 'delayed' || '';
  10424. },
  10425. renderMessage: function renderMessage(attrs) {
  10426. /* Renders a chat message based on the passed in attributes.
  10427. *
  10428. * Parameters:
  10429. * (Object) attrs: An object containing the message attributes.
  10430. *
  10431. * Returns:
  10432. * The DOM element representing the message.
  10433. */
  10434. var text = attrs.message,
  10435. fullname = this.model.get('fullname') || attrs.fullname,
  10436. template = void 0,
  10437. username = void 0;
  10438. var match = text.match(/^\/(.*?)(?: (.*))?$/);
  10439. if (match && match[1] === 'me') {
  10440. text = text.replace(/^\/me/, '');
  10441. template = tpl_action;
  10442. if (attrs.sender === 'me') {
  10443. fullname = _converse.xmppstatus.get('fullname') || attrs.fullname;
  10444. username = _.isNil(fullname) ? _converse.bare_jid : fullname;
  10445. } else {
  10446. username = attrs.fullname;
  10447. }
  10448. } else {
  10449. template = tpl_message;
  10450. username = attrs.sender === 'me' && __('me') || fullname;
  10451. }
  10452. this.$content.find('div.chat-event').remove();
  10453. if (text.length > 8000) {
  10454. text = text.substring(0, 10) + '...';
  10455. this.showStatusNotification(__("A very large message has been received." + "This might be due to an attack meant to degrade the chat performance." + "Output has been shortened."), true, true);
  10456. }
  10457. var msg_time = moment(attrs.time) || moment;
  10458. var $msg = $(template(_.extend(this.getExtraMessageTemplateAttributes(attrs), {
  10459. 'msgid': attrs.msgid,
  10460. 'sender': attrs.sender,
  10461. 'time': msg_time.format(_converse.time_format),
  10462. 'isodate': msg_time.format(),
  10463. 'username': username,
  10464. 'extra_classes': this.getExtraMessageClasses(attrs)
  10465. })));
  10466. var msg_content = $msg[0].querySelector('.chat-msg-content');
  10467. msg_content.innerHTML = utils.addEmoji(_converse, emojione, utils.addHyperlinks(xss.filterXSS(text, { 'whiteList': {} })));
  10468. utils.renderImageURLs(msg_content);
  10469. return $msg;
  10470. },
  10471. showHelpMessages: function showHelpMessages(msgs, type, spinner) {
  10472. var _this3 = this;
  10473. _.each(msgs, function (msg) {
  10474. _this3.$content.append($(tpl_help_message({
  10475. 'type': type || 'info',
  10476. 'message': msgs
  10477. })));
  10478. });
  10479. if (spinner === true) {
  10480. this.$content.append(tpl_spinner);
  10481. } else if (spinner === false) {
  10482. this.$content.find('span.spinner').remove();
  10483. }
  10484. return this.scrollDown();
  10485. },
  10486. handleChatStateMessage: function handleChatStateMessage(message) {
  10487. if (message.get('chat_state') === _converse.COMPOSING) {
  10488. if (message.get('sender') === 'me') {
  10489. this.showStatusNotification(__('Typing from another device'));
  10490. } else {
  10491. this.showStatusNotification(message.get('fullname') + ' ' + __('is typing'));
  10492. }
  10493. this.clear_status_timeout = window.setTimeout(this.clearStatusNotification.bind(this), 30000);
  10494. } else if (message.get('chat_state') === _converse.PAUSED) {
  10495. if (message.get('sender') === 'me') {
  10496. this.showStatusNotification(__('Stopped typing on the other device'));
  10497. } else {
  10498. this.showStatusNotification(message.get('fullname') + ' ' + __('has stopped typing'));
  10499. }
  10500. } else if (_.includes([_converse.INACTIVE, _converse.ACTIVE], message.get('chat_state'))) {
  10501. this.$content.find('div.chat-event').remove();
  10502. } else if (message.get('chat_state') === _converse.GONE) {
  10503. this.showStatusNotification(message.get('fullname') + ' ' + __('has gone away'));
  10504. }
  10505. },
  10506. shouldShowOnTextMessage: function shouldShowOnTextMessage() {
  10507. return !this.$el.is(':visible');
  10508. },
  10509. handleTextMessage: function handleTextMessage(message) {
  10510. this.showMessage(_.clone(message.attributes));
  10511. if (utils.isNewMessage(message) && message.get('sender') === 'me') {
  10512. // We remove the "scrolled" flag so that the chat area
  10513. // gets scrolled down. We always want to scroll down
  10514. // when the user writes a message as opposed to when a
  10515. // message is received.
  10516. this.model.set('scrolled', false);
  10517. } else {
  10518. if (utils.isNewMessage(message) && this.model.get('scrolled', true)) {
  10519. this.$el.find('.new-msgs-indicator').removeClass('hidden');
  10520. }
  10521. }
  10522. if (this.shouldShowOnTextMessage()) {
  10523. this.show();
  10524. } else {
  10525. this.scrollDown();
  10526. }
  10527. },
  10528. handleErrorMessage: function handleErrorMessage(message) {
  10529. var $message = $("[data-msgid=" + message.get('msgid') + "]");
  10530. if ($message.length) {
  10531. $message.after($('<div class="chat-info chat-error"></div>').text(message.get('message')));
  10532. this.scrollDown();
  10533. }
  10534. },
  10535. onMessageAdded: function onMessageAdded(message) {
  10536. /* Handler that gets called when a new message object is created.
  10537. *
  10538. * Parameters:
  10539. * (Object) message - The message Backbone object that was added.
  10540. */
  10541. if (!_.isUndefined(this.clear_status_timeout)) {
  10542. window.clearTimeout(this.clear_status_timeout);
  10543. delete this.clear_status_timeout;
  10544. }
  10545. if (message.get('type') === 'error') {
  10546. this.handleErrorMessage(message);
  10547. } else if (!message.get('message')) {
  10548. this.handleChatStateMessage(message);
  10549. } else {
  10550. this.handleTextMessage(message);
  10551. }
  10552. _converse.emit('messageAdded', {
  10553. 'message': message,
  10554. 'chatbox': this.model
  10555. });
  10556. },
  10557. createMessageStanza: function createMessageStanza(message) {
  10558. return $msg({
  10559. from: _converse.connection.jid,
  10560. to: this.model.get('jid'),
  10561. type: 'chat',
  10562. id: message.get('msgid')
  10563. }).c('body').t(message.get('message')).up().c(_converse.ACTIVE, { 'xmlns': Strophe.NS.CHATSTATES }).up();
  10564. },
  10565. sendMessage: function sendMessage(message) {
  10566. /* Responsible for sending off a text message.
  10567. *
  10568. * Parameters:
  10569. * (Message) message - The chat message
  10570. */
  10571. // TODO: We might want to send to specfic resources.
  10572. // Especially in the OTR case.
  10573. var messageStanza = this.createMessageStanza(message);
  10574. _converse.connection.send(messageStanza);
  10575. if (_converse.forward_messages) {
  10576. // Forward the message, so that other connected resources are also aware of it.
  10577. _converse.connection.send($msg({ to: _converse.bare_jid, type: 'chat', id: message.get('msgid') }).c('forwarded', { xmlns: 'urn:xmpp:forward:0' }).c('delay', { xmns: 'urn:xmpp:delay', stamp: new Date().getTime() }).up().cnode(messageStanza.tree()));
  10578. }
  10579. },
  10580. onMessageSubmitted: function onMessageSubmitted(text) {
  10581. /* This method gets called once the user has typed a message
  10582. * and then pressed enter in a chat box.
  10583. *
  10584. * Parameters:
  10585. * (string) text - The chat message text.
  10586. */
  10587. if (!_converse.connection.authenticated) {
  10588. return this.showHelpMessages(['Sorry, the connection has been lost, ' + 'and your message could not be sent'], 'error');
  10589. }
  10590. var match = text.replace(/^\s*/, "").match(/^\/(.*)\s*$/);
  10591. if (match) {
  10592. if (match[1] === "clear") {
  10593. return this.clearMessages();
  10594. } else if (match[1] === "help") {
  10595. var msgs = ["<strong>/help</strong>:" + __('Show this menu'), "<strong>/me</strong>:" + __('Write in the third person'), "<strong>/clear</strong>:" + __('Remove messages')];
  10596. this.showHelpMessages(msgs);
  10597. return;
  10598. }
  10599. }
  10600. var fullname = _converse.xmppstatus.get('fullname');
  10601. fullname = _.isEmpty(fullname) ? _converse.bare_jid : fullname;
  10602. var message = this.model.messages.create({
  10603. fullname: fullname,
  10604. sender: 'me',
  10605. time: moment().format(),
  10606. message: text
  10607. });
  10608. this.sendMessage(message);
  10609. },
  10610. sendChatState: function sendChatState() {
  10611. /* Sends a message with the status of the user in this chat session
  10612. * as taken from the 'chat_state' attribute of the chat box.
  10613. * See XEP-0085 Chat State Notifications.
  10614. */
  10615. _converse.connection.send($msg({ 'to': this.model.get('jid'), 'type': 'chat' }).c(this.model.get('chat_state'), { 'xmlns': Strophe.NS.CHATSTATES }).up().c('no-store', { 'xmlns': Strophe.NS.HINTS }).up().c('no-permanent-store', { 'xmlns': Strophe.NS.HINTS }));
  10616. },
  10617. setChatState: function setChatState(state, no_save) {
  10618. /* Mutator for setting the chat state of this chat session.
  10619. * Handles clearing of any chat state notification timeouts and
  10620. * setting new ones if necessary.
  10621. * Timeouts are set when the state being set is COMPOSING or PAUSED.
  10622. * After the timeout, COMPOSING will become PAUSED and PAUSED will become INACTIVE.
  10623. * See XEP-0085 Chat State Notifications.
  10624. *
  10625. * Parameters:
  10626. * (string) state - The chat state (consts ACTIVE, COMPOSING, PAUSED, INACTIVE, GONE)
  10627. * (Boolean) no_save - Just do the cleanup or setup but don't actually save the state.
  10628. */
  10629. if (!_.isUndefined(this.chat_state_timeout)) {
  10630. window.clearTimeout(this.chat_state_timeout);
  10631. delete this.chat_state_timeout;
  10632. }
  10633. if (state === _converse.COMPOSING) {
  10634. this.chat_state_timeout = window.setTimeout(this.setChatState.bind(this), _converse.TIMEOUTS.PAUSED, _converse.PAUSED);
  10635. } else if (state === _converse.PAUSED) {
  10636. this.chat_state_timeout = window.setTimeout(this.setChatState.bind(this), _converse.TIMEOUTS.INACTIVE, _converse.INACTIVE);
  10637. }
  10638. if (!no_save && this.model.get('chat_state') !== state) {
  10639. this.model.set('chat_state', state);
  10640. }
  10641. return this;
  10642. },
  10643. onFormSubmitted: function onFormSubmitted(ev) {
  10644. ev.preventDefault();
  10645. var textarea = this.el.querySelector('.chat-textarea'),
  10646. message = textarea.value;
  10647. textarea.value = '';
  10648. textarea.focus();
  10649. if (message !== '') {
  10650. this.onMessageSubmitted(message);
  10651. _converse.emit('messageSend', message);
  10652. }
  10653. this.setChatState(_converse.ACTIVE);
  10654. },
  10655. keyPressed: function keyPressed(ev) {
  10656. /* Event handler for when a key is pressed in a chat box textarea.
  10657. */
  10658. if (ev.keyCode === KEY.ENTER) {
  10659. this.onFormSubmitted(ev);
  10660. } else {
  10661. // Set chat state to composing if keyCode is not a forward-slash
  10662. // (which would imply an internal command and not a message).
  10663. this.setChatState(_converse.COMPOSING, ev.keyCode === KEY.FORWARD_SLASH);
  10664. }
  10665. },
  10666. clearMessages: function clearMessages(ev) {
  10667. if (ev && ev.preventDefault) {
  10668. ev.preventDefault();
  10669. }
  10670. var result = confirm(__("Are you sure you want to clear the messages from this chat box?"));
  10671. if (result === true) {
  10672. this.$content.empty();
  10673. this.model.messages.reset();
  10674. this.model.messages.browserStorage._clear();
  10675. }
  10676. return this;
  10677. },
  10678. insertIntoTextArea: function insertIntoTextArea(value) {
  10679. var $textbox = this.$el.find('textarea.chat-textarea');
  10680. var existing = $textbox.val();
  10681. if (existing && existing[existing.length - 1] !== ' ') {
  10682. existing = existing + ' ';
  10683. }
  10684. $textbox.focus().val(existing + value + ' ');
  10685. },
  10686. insertEmoji: function insertEmoji(ev) {
  10687. ev.stopPropagation();
  10688. this.toggleEmojiMenu();
  10689. var target = ev.target.nodeName === 'IMG' ? ev.target.parentElement : ev.target;
  10690. this.insertIntoTextArea(target.getAttribute('data-emoji'));
  10691. },
  10692. toggleEmojiMenu: function toggleEmojiMenu(ev) {
  10693. if (!_.isUndefined(ev)) {
  10694. ev.stopPropagation();
  10695. if (ev.target.classList.contains('emoji-category-picker') || ev.target.classList.contains('emoji-skintone-picker') || ev.target.classList.contains('emoji-category')) {
  10696. return;
  10697. }
  10698. }
  10699. var elements = _.difference(document.querySelectorAll('.toolbar-menu'), [this.emoji_picker_view.el]);
  10700. utils.slideInAllElements(elements).then(_.partial(utils.slideToggleElement, this.emoji_picker_view.el));
  10701. },
  10702. toggleCall: function toggleCall(ev) {
  10703. ev.stopPropagation();
  10704. _converse.emit('callButtonClicked', {
  10705. connection: _converse.connection,
  10706. model: this.model
  10707. });
  10708. },
  10709. onChatStatusChanged: function onChatStatusChanged(item) {
  10710. var chat_status = item.get('chat_status');
  10711. var fullname = item.get('fullname');
  10712. fullname = _.isEmpty(fullname) ? item.get('jid') : fullname;
  10713. if (this.$el.is(':visible')) {
  10714. if (chat_status === 'offline') {
  10715. this.showStatusNotification(fullname + ' ' + __('has gone offline'));
  10716. } else if (chat_status === 'away') {
  10717. this.showStatusNotification(fullname + ' ' + __('has gone away'));
  10718. } else if (chat_status === 'dnd') {
  10719. this.showStatusNotification(fullname + ' ' + __('is busy'));
  10720. } else if (chat_status === 'online') {
  10721. this.$el.find('div.chat-event').remove();
  10722. }
  10723. }
  10724. },
  10725. onStatusChanged: function onStatusChanged(item) {
  10726. this.showStatusMessage();
  10727. _converse.emit('contactStatusMessageChanged', {
  10728. 'contact': item.attributes,
  10729. 'message': item.get('status')
  10730. });
  10731. },
  10732. showStatusMessage: function showStatusMessage(msg) {
  10733. msg = msg || this.model.get('status');
  10734. if (_.isString(msg)) {
  10735. this.$el.find('p.user-custom-message').text(msg).attr('title', msg);
  10736. }
  10737. return this;
  10738. },
  10739. close: function close(ev) {
  10740. if (ev && ev.preventDefault) {
  10741. ev.preventDefault();
  10742. }
  10743. if (_converse.connection.connected) {
  10744. // Immediately sending the chat state, because the
  10745. // model is going to be destroyed afterwards.
  10746. this.model.set('chat_state', _converse.INACTIVE);
  10747. this.sendChatState();
  10748. }
  10749. try {
  10750. this.model.destroy();
  10751. } catch (e) {
  10752. _converse.log(e, Strophe.LogLevel.ERROR);
  10753. }
  10754. this.remove();
  10755. _converse.emit('chatBoxClosed', this);
  10756. return this;
  10757. },
  10758. getToolbarOptions: function getToolbarOptions(options) {
  10759. return _.extend(options || {}, {
  10760. 'label_clear': __('Clear all messages'),
  10761. 'label_insert_smiley': __('Insert a smiley'),
  10762. 'label_start_call': __('Start a call'),
  10763. 'show_call_button': _converse.visible_toolbar_buttons.call,
  10764. 'show_clear_button': _converse.visible_toolbar_buttons.clear,
  10765. 'use_emoji': _converse.visible_toolbar_buttons.emoji
  10766. });
  10767. },
  10768. renderToolbar: function renderToolbar(toolbar, options) {
  10769. if (!_converse.show_toolbar) {
  10770. return;
  10771. }
  10772. toolbar = toolbar || tpl_toolbar;
  10773. options = _.assign(this.model.toJSON(), this.getToolbarOptions(options || {}));
  10774. this.el.querySelector('.chat-toolbar').innerHTML = toolbar(options);
  10775. var toggle = this.el.querySelector('.toggle-smiley');
  10776. toggle.innerHTML = '';
  10777. toggle.appendChild(this.emoji_picker_view.render().el);
  10778. return this;
  10779. },
  10780. renderAvatar: function renderAvatar() {
  10781. if (!this.model.get('image')) {
  10782. return;
  10783. }
  10784. var width = _converse.chatview_avatar_width;
  10785. var height = _converse.chatview_avatar_height;
  10786. var img_src = "data:" + this.model.get('image_type') + ";base64," + this.model.get('image'),
  10787. canvas = $(tpl_avatar({
  10788. 'width': width,
  10789. 'height': height
  10790. })).get(0);
  10791. if (!(canvas.getContext && canvas.getContext('2d'))) {
  10792. return this;
  10793. }
  10794. var ctx = canvas.getContext('2d');
  10795. var img = new Image(); // Create new Image object
  10796. img.onload = function () {
  10797. var ratio = img.width / img.height;
  10798. if (ratio < 1) {
  10799. ctx.drawImage(img, 0, 0, width, height * (1 / ratio));
  10800. } else {
  10801. ctx.drawImage(img, 0, 0, width, height * ratio);
  10802. }
  10803. };
  10804. img.src = img_src;
  10805. this.$el.find('.chat-title').before(canvas);
  10806. return this;
  10807. },
  10808. focus: function focus() {
  10809. this.$el.find('.chat-textarea').focus();
  10810. _converse.emit('chatBoxFocused', this);
  10811. return this;
  10812. },
  10813. hide: function hide() {
  10814. this.el.classList.add('hidden');
  10815. utils.refreshWebkit();
  10816. return this;
  10817. },
  10818. afterShown: function afterShown(focus) {
  10819. if (utils.isPersistableModel(this.model)) {
  10820. this.model.save();
  10821. }
  10822. this.setChatState(_converse.ACTIVE);
  10823. this.scrollDown();
  10824. if (focus) {
  10825. this.focus();
  10826. }
  10827. },
  10828. _show: function _show(focus) {
  10829. /* Inner show method that gets debounced */
  10830. if (this.$el.is(':visible') && this.$el.css('opacity') === "1") {
  10831. if (focus) {
  10832. this.focus();
  10833. }
  10834. return;
  10835. }
  10836. utils.fadeIn(this.el, _.bind(this.afterShown, this, focus));
  10837. },
  10838. show: function show(focus) {
  10839. if (_.isUndefined(this.debouncedShow)) {
  10840. /* We wrap the method in a debouncer and set it on the
  10841. * instance, so that we have it debounced per instance.
  10842. * Debouncing it on the class-level is too broad.
  10843. */
  10844. this.debouncedShow = _.debounce(this._show, 250, { 'leading': true });
  10845. }
  10846. this.debouncedShow.apply(this, arguments);
  10847. return this;
  10848. },
  10849. hideNewMessagesIndicator: function hideNewMessagesIndicator() {
  10850. var new_msgs_indicator = this.el.querySelector('.new-msgs-indicator');
  10851. if (!_.isNull(new_msgs_indicator)) {
  10852. new_msgs_indicator.classList.add('hidden');
  10853. }
  10854. },
  10855. markScrolled: function markScrolled(ev) {
  10856. /* Called when the chat content is scrolled up or down.
  10857. * We want to record when the user has scrolled away from
  10858. * the bottom, so that we don't automatically scroll away
  10859. * from what the user is reading when new messages are
  10860. * received.
  10861. */
  10862. if (ev && ev.preventDefault) {
  10863. ev.preventDefault();
  10864. }
  10865. if (this.model.get('auto_scrolled')) {
  10866. this.model.set({
  10867. 'scrolled': false,
  10868. 'auto_scrolled': false
  10869. });
  10870. return;
  10871. }
  10872. var scrolled = true;
  10873. var is_at_bottom = this.$content.scrollTop() + this.$content.innerHeight() >= this.$content[0].scrollHeight - 10;
  10874. if (is_at_bottom) {
  10875. scrolled = false;
  10876. this.onScrolledDown();
  10877. }
  10878. utils.safeSave(this.model, { 'scrolled': scrolled });
  10879. },
  10880. viewUnreadMessages: function viewUnreadMessages() {
  10881. this.model.save('scrolled', false);
  10882. this.scrollDown();
  10883. },
  10884. _scrollDown: function _scrollDown() {
  10885. /* Inner method that gets debounced */
  10886. if (this.$content.is(':visible') && !this.model.get('scrolled')) {
  10887. this.$content.scrollTop(this.$content[0].scrollHeight);
  10888. this.onScrolledDown();
  10889. this.model.save({ 'auto_scrolled': true });
  10890. }
  10891. },
  10892. onScrolledDown: function onScrolledDown() {
  10893. this.hideNewMessagesIndicator();
  10894. if (_converse.windowState !== 'hidden') {
  10895. this.model.clearUnreadMsgCounter();
  10896. }
  10897. _converse.emit('chatBoxScrolledDown', { 'chatbox': this.model });
  10898. },
  10899. scrollDown: function scrollDown() {
  10900. if (_.isUndefined(this.debouncedScrollDown)) {
  10901. /* We wrap the method in a debouncer and set it on the
  10902. * instance, so that we have it debounced per instance.
  10903. * Debouncing it on the class-level is too broad.
  10904. */
  10905. this.debouncedScrollDown = _.debounce(this._scrollDown, 250);
  10906. }
  10907. this.debouncedScrollDown.apply(this, arguments);
  10908. return this;
  10909. },
  10910. onWindowStateChanged: function onWindowStateChanged(state) {
  10911. if (this.model.get('num_unread', 0) && !this.model.newMessageWillBeHidden()) {
  10912. this.model.clearUnreadMsgCounter();
  10913. }
  10914. }
  10915. });
  10916. }
  10917. });
  10918. return converse;
  10919. });
  10920. //# sourceMappingURL=converse-chatview.js.map;
  10921. define('tpl!add_contact_dropdown', ['lodash'], function(_) {return function(obj) {
  10922. obj || (obj = {});
  10923. var __t, __p = '', __e = _.escape;
  10924. with (obj) {
  10925. __p += '<dl class="add-converse-contact dropdown">\n <dt id="xmpp-contact-search" class="fancy-dropdown">\n <a class="toggle-xmpp-contact-form icon-plus" href="#" title="' +
  10926. __e(label_click_to_chat) +
  10927. '"> ' +
  10928. __e(label_add_contact) +
  10929. '</a>\n </dt>\n <dd class="search-xmpp">\n <div class="contact-form-container collapsed"></div>\n <ul></ul>\n </dd>\n</dl>\n';
  10930. }
  10931. return __p
  10932. };});
  10933. define('tpl!add_contact_form', ['lodash'], function(_) {return function(obj) {
  10934. obj || (obj = {});
  10935. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  10936. function print() { __p += __j.call(arguments, '') }
  10937. with (obj) {
  10938. __p += '<form class="pure-form add-xmpp-contact">\n ';
  10939. if (error_message) { ;
  10940. __p += '\n <span class="pure-form-message error">' +
  10941. __e(error_message) +
  10942. '</span>\n ';
  10943. } ;
  10944. __p += '\n <input type="text"\n name="identifier"\n value="' +
  10945. __e(value) +
  10946. '"\n class="username ';
  10947. if (error_message) { ;
  10948. __p += ' error ';
  10949. } ;
  10950. __p += '"\n placeholder="' +
  10951. __e(label_contact_username) +
  10952. '"/>\n <button class="pure-button button-primary" type="submit">' +
  10953. __e(label_add) +
  10954. '</button>\n</form>\n';
  10955. }
  10956. return __p
  10957. };});
  10958. define('tpl!change_status_message', ['lodash'], function(_) {return function(obj) {
  10959. obj || (obj = {});
  10960. var __t, __p = '', __e = _.escape;
  10961. with (obj) {
  10962. __p += '<fieldset>\n <span class="input-button-group">\n <input type="text" class="custom-xmpp-status" value="' +
  10963. __e(status_message) +
  10964. '" placeholder="' +
  10965. __e(label_custom_status) +
  10966. '"/>\n <input type="submit" class="pure-button button-primary" value="' +
  10967. __e(label_save) +
  10968. '"/>\n </span>\n</fieldset>\n';
  10969. }
  10970. return __p
  10971. };});
  10972. define('tpl!chat_status', ['lodash'], function(_) {return function(obj) {
  10973. obj || (obj = {});
  10974. var __t, __p = '', __e = _.escape;
  10975. with (obj) {
  10976. __p += '<div class="xmpp-status">\n <a class="choose-xmpp-status ' +
  10977. __e(chat_status) +
  10978. ' icon-' +
  10979. __e(chat_status) +
  10980. '" data-value="' +
  10981. __e(status_message) +
  10982. '" href="#" title="' +
  10983. __e(desc_change_status) +
  10984. '">\n ' +
  10985. __e(status_message) +
  10986. '\n </a>\n <a class="change-xmpp-status-message icon-pencil" href="#" title="' +
  10987. __e(desc_custom_status) +
  10988. '"></a>\n</div>\n';
  10989. }
  10990. return __p
  10991. };});
  10992. define('tpl!choose_status', ['lodash'], function(_) {return function(obj) {
  10993. obj || (obj = {});
  10994. var __t, __p = '';
  10995. with (obj) {
  10996. __p += '<dl id="target" class="dropdown">\n <dt id="fancy-xmpp-status-select" class="fancy-dropdown"></dt>\n <dd><ul class="xmpp-status-menu"></ul></dd>\n</dl>\n';
  10997. }
  10998. return __p
  10999. };});
  11000. define('tpl!contacts_panel', ['lodash'], function(_) {return function(obj) {
  11001. obj || (obj = {});
  11002. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  11003. function print() { __p += __j.call(arguments, '') }
  11004. with (obj) {
  11005. __p += '<form class="pure-form set-xmpp-status" id="set-xmpp-status" action="" method="post">\n <select id="select-xmpp-status">\n <option value="online">' +
  11006. __e(label_online) +
  11007. '</option>\n <option value="dnd">' +
  11008. __e(label_busy) +
  11009. '</option>\n <option value="away">' +
  11010. __e(label_away) +
  11011. '</option>\n ';
  11012. if (include_offline_state) { ;
  11013. __p += '\n <option value="offline">' +
  11014. __e(label_offline) +
  11015. '</option>\n ';
  11016. } ;
  11017. __p += '\n ';
  11018. if (allow_logout) { ;
  11019. __p += '\n <option value="logout">' +
  11020. __e(label_logout) +
  11021. '</option>\n ';
  11022. } ;
  11023. __p += '\n </select>\n</form>\n';
  11024. }
  11025. return __p
  11026. };});
  11027. define('tpl!contacts_tab', ['lodash'], function(_) {return function(obj) {
  11028. obj || (obj = {});
  11029. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  11030. function print() { __p += __j.call(arguments, '') }
  11031. with (obj) {
  11032. __p += '<a class="s contacts-tab\n ';
  11033. if (is_current) { ;
  11034. __p += ' current ';
  11035. } ;
  11036. __p += '\n ';
  11037. if (num_unread) { ;
  11038. __p += ' unread-msgs ';
  11039. } ;
  11040. __p += '"\n data-id="users" href="#users">\n ' +
  11041. __e(label_contacts) +
  11042. '\n ';
  11043. if (num_unread) { ;
  11044. __p += '\n <span class="msgs-indicator">' +
  11045. __e( num_unread ) +
  11046. '</span>\n ';
  11047. } ;
  11048. __p += '\n</a>\n';
  11049. }
  11050. return __p
  11051. };});
  11052. define('tpl!controlbox', ['lodash'], function(_) {return function(obj) {
  11053. obj || (obj = {});
  11054. var __t, __p = '', __j = Array.prototype.join;
  11055. function print() { __p += __j.call(arguments, '') }
  11056. with (obj) {
  11057. __p += '<div class="flyout box-flyout">\n <div class="chat-head controlbox-head">\n <ul id="controlbox-tabs"></ul>\n ';
  11058. if (!sticky_controlbox) { ;
  11059. __p += '\n <a class="chatbox-btn close-chatbox-button icon-close"></a>\n ';
  11060. } ;
  11061. __p += '\n </div>\n <div class="controlbox-panes"></div>\n</div>\n';
  11062. }
  11063. return __p
  11064. };});
  11065. define('tpl!controlbox_toggle', ['lodash'], function(_) {return function(obj) {
  11066. obj || (obj = {});
  11067. var __t, __p = '', __e = _.escape;
  11068. with (obj) {
  11069. __p += '<span class="conn-feedback">' +
  11070. __e(label_toggle) +
  11071. '</span>\n';
  11072. }
  11073. return __p
  11074. };});
  11075. define('tpl!login_panel', ['lodash'], function(_) {return function(obj) {
  11076. obj || (obj = {});
  11077. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  11078. function print() { __p += __j.call(arguments, '') }
  11079. with (obj) {
  11080. __p += '<form class="pure-form pure-form-stacked converse-form" id="converse-login" method="post">\n ';
  11081. if (auto_login) { ;
  11082. __p += '\n <span class="spinner login-submit"/>\n ';
  11083. } ;
  11084. __p += '\n ';
  11085. if (!auto_login) { ;
  11086. __p += '\n ';
  11087. if (authentication == LOGIN || authentication == EXTERNAL) { ;
  11088. __p += '\n <label>' +
  11089. __e(label_username) +
  11090. '</label>\n <input type="text" name="jid" placeholder="' +
  11091. __e(placeholder_username) +
  11092. '">\n ';
  11093. if (authentication !== EXTERNAL) { ;
  11094. __p += '\n <label>' +
  11095. __e(label_password) +
  11096. '</label>\n <input type="password" name="password" placeholder="' +
  11097. __e(placeholder_password) +
  11098. '">\n ';
  11099. } ;
  11100. __p += '\n <input class="pure-button button-primary" type="submit" value="' +
  11101. __e(label_login) +
  11102. '">\n <span class="conn-feedback"></span>\n ';
  11103. } ;
  11104. __p += '\n ';
  11105. if (authentication == ANONYMOUS) { ;
  11106. __p += '\n <input class="pure-button button-primary login-anon" type="submit" value="' +
  11107. __e(label_anon_login) +
  11108. '"/>\n ';
  11109. } ;
  11110. __p += '\n ';
  11111. if (authentication == PREBIND) { ;
  11112. __p += '\n <p>Disconnected.</p>\n ';
  11113. } ;
  11114. __p += '\n ';
  11115. } ;
  11116. __p += '\n</form>\n';
  11117. }
  11118. return __p
  11119. };});
  11120. define('tpl!login_tab', ['lodash'], function(_) {return function(obj) {
  11121. obj || (obj = {});
  11122. var __t, __p = '', __e = _.escape;
  11123. with (obj) {
  11124. __p += '<li><a class="current" data-id="login" href="#login-dialog">' +
  11125. __e(label_sign_in) +
  11126. '</a></li>\n';
  11127. }
  11128. return __p
  11129. };});
  11130. define('tpl!search_contact', ['lodash'], function(_) {return function(obj) {
  11131. obj || (obj = {});
  11132. var __t, __p = '', __e = _.escape;
  11133. with (obj) {
  11134. __p += '<li>\n <form class="search-xmpp-contact">\n <input type="text"\n name="identifier"\n class="username"\n placeholder="' +
  11135. __e(label_contact_name) +
  11136. '"/>\n <button type="submit">' +
  11137. __e(label_search) +
  11138. '</button>\n </form>\n</li>\n';
  11139. }
  11140. return __p
  11141. };});
  11142. define('tpl!status_option', ['lodash'], function(_) {return function(obj) {
  11143. obj || (obj = {});
  11144. var __t, __p = '', __e = _.escape;
  11145. with (obj) {
  11146. __p += '<li>\n <a href="#" class="' +
  11147. __e( value ) +
  11148. '" data-value="' +
  11149. __e( value ) +
  11150. '">\n <span class="icon-' +
  11151. __e( value ) +
  11152. '"></span>\n ' +
  11153. __e( text ) +
  11154. '\n </a>\n</li>\n';
  11155. }
  11156. return __p
  11157. };});
  11158. define('tpl!group_header', ['lodash'], function(_) {return function(obj) {
  11159. obj || (obj = {});
  11160. var __t, __p = '', __e = _.escape;
  11161. with (obj) {
  11162. __p += '<a href="#" class="group-toggle icon-' +
  11163. __e(toggle_state) +
  11164. '" title="' +
  11165. __e(desc_group_toggle) +
  11166. '">' +
  11167. __e(label_group) +
  11168. '</a>\n';
  11169. }
  11170. return __p
  11171. };});
  11172. define('tpl!pending_contact', ['lodash'], function(_) {return function(obj) {
  11173. obj || (obj = {});
  11174. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  11175. function print() { __p += __j.call(arguments, '') }
  11176. with (obj) {
  11177. if (allow_chat_pending_contacts) { ;
  11178. __p += '\n<a class="open-chat"href="#">\n';
  11179. } ;
  11180. __p += '\n<span class="pending-contact-name" title="Name: ' +
  11181. __e(fullname) +
  11182. '\nJID: ' +
  11183. __e(jid) +
  11184. '">' +
  11185. __e(fullname) +
  11186. '</span> \n';
  11187. if (allow_chat_pending_contacts) { ;
  11188. __p += '\n</a>\n';
  11189. } ;
  11190. __p += '\n<a class="remove-xmpp-contact icon-remove" title="' +
  11191. __e(desc_remove) +
  11192. '" href="#"></a>\n';
  11193. }
  11194. return __p
  11195. };});
  11196. define('tpl!requesting_contact', ['lodash'], function(_) {return function(obj) {
  11197. obj || (obj = {});
  11198. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  11199. function print() { __p += __j.call(arguments, '') }
  11200. with (obj) {
  11201. if (allow_chat_pending_contacts) { ;
  11202. __p += '\n<a class="open-chat"href="#">\n';
  11203. } ;
  11204. __p += '\n<span class="req-contact-name" title="Name: ' +
  11205. __e(fullname) +
  11206. '\nJID: ' +
  11207. __e(jid) +
  11208. '">' +
  11209. __e(fullname) +
  11210. '</span>\n';
  11211. if (allow_chat_pending_contacts) { ;
  11212. __p += '\n</a>\n';
  11213. } ;
  11214. __p += '\n<span class="request-actions">\n <a class="accept-xmpp-request icon-checkmark" aria-label="' +
  11215. __e(desc_accept) +
  11216. '" title="' +
  11217. __e(desc_accept) +
  11218. '" href="#"></a>\n <a class="decline-xmpp-request icon-close" aria-label="' +
  11219. __e(desc_decline) +
  11220. '" title="' +
  11221. __e(desc_decline) +
  11222. '" href="#"></a>\n</span>\n';
  11223. }
  11224. return __p
  11225. };});
  11226. define('tpl!roster', ['lodash'], function(_) {return function(obj) {
  11227. obj || (obj = {});
  11228. var __t, __p = '';
  11229. with (obj) {
  11230. __p += '<dl class="roster-contacts"></dl>\n';
  11231. }
  11232. return __p
  11233. };});
  11234. define('tpl!roster_filter', ['lodash'], function(_) {return function(obj) {
  11235. obj || (obj = {});
  11236. var __t, __p = '', __j = Array.prototype.join;
  11237. function print() { __p += __j.call(arguments, '') }
  11238. with (obj) {
  11239. __p += '<form class="pure-form roster-filter-form input-button-group">\n <input value="' +
  11240. ((__t = (filter_text)) == null ? '' : __t) +
  11241. '" class="roster-filter roster-filter-' +
  11242. ((__t = (filter_type)) == null ? '' : __t) +
  11243. '"\n placeholder="' +
  11244. ((__t = (placeholder)) == null ? '' : __t) +
  11245. '">\n <select class="state-type state-type-' +
  11246. ((__t = (filter_type)) == null ? '' : __t) +
  11247. '">\n <option value="">' +
  11248. ((__t = (label_any)) == null ? '' : __t) +
  11249. '</option>\n <option ';
  11250. if (chat_state === 'unread_messages') { ;
  11251. __p += ' selected="selected" ';
  11252. } ;
  11253. __p += '\n value="unread_messages">' +
  11254. ((__t = (label_unread_messages)) == null ? '' : __t) +
  11255. '</option>\n <option ';
  11256. if (chat_state === 'online') { ;
  11257. __p += ' selected="selected" ';
  11258. } ;
  11259. __p += '\n value="online">' +
  11260. ((__t = (label_online)) == null ? '' : __t) +
  11261. '</option>\n <option ';
  11262. if (chat_state === 'chat') { ;
  11263. __p += ' selected="selected" ';
  11264. } ;
  11265. __p += '\n value="chat">' +
  11266. ((__t = (label_chatty)) == null ? '' : __t) +
  11267. '</option>\n <option ';
  11268. if (chat_state === 'dnd') { ;
  11269. __p += ' selected="selected" ';
  11270. } ;
  11271. __p += '\n value="dnd">' +
  11272. ((__t = (label_busy)) == null ? '' : __t) +
  11273. '</option>\n <option ';
  11274. if (chat_state === 'away') { ;
  11275. __p += ' selected="selected" ';
  11276. } ;
  11277. __p += '\n value="away">' +
  11278. ((__t = (label_away)) == null ? '' : __t) +
  11279. '</option>\n <option ';
  11280. if (chat_state === 'xa') { ;
  11281. __p += ' selected="selected" ';
  11282. } ;
  11283. __p += '\n value="xa">' +
  11284. ((__t = (label_xa)) == null ? '' : __t) +
  11285. '</option>\n <option ';
  11286. if (chat_state === 'offline') { ;
  11287. __p += ' selected="selected" ';
  11288. } ;
  11289. __p += '\n value="offline">' +
  11290. ((__t = (label_offline)) == null ? '' : __t) +
  11291. '</option>\n </select>\n <select class="filter-type">\n <option ';
  11292. if (filter_type === 'contacts') { ;
  11293. __p += ' selected="selected" ';
  11294. } ;
  11295. __p += '\n value="contacts">' +
  11296. ((__t = (label_contacts)) == null ? '' : __t) +
  11297. '</option>\n <option ';
  11298. if (filter_type === 'groups') { ;
  11299. __p += ' selected="selected" ';
  11300. } ;
  11301. __p += '\n value="groups">' +
  11302. ((__t = (label_groups)) == null ? '' : __t) +
  11303. '</option>\n <option ';
  11304. if (filter_type === 'state') { ;
  11305. __p += ' selected="selected" ';
  11306. } ;
  11307. __p += '\n value="state">' +
  11308. ((__t = (label_state)) == null ? '' : __t) +
  11309. '</option>\n </select>\n</form>\n';
  11310. }
  11311. return __p
  11312. };});
  11313. define('tpl!roster_item', ['lodash'], function(_) {return function(obj) {
  11314. obj || (obj = {});
  11315. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  11316. function print() { __p += __j.call(arguments, '') }
  11317. with (obj) {
  11318. __p += '<a class="open-chat ';
  11319. if (num_unread) { ;
  11320. __p += ' unread-msgs ';
  11321. } ;
  11322. __p += '"\n title="' +
  11323. __e(title_fullname) +
  11324. ': ' +
  11325. __e(fullname) +
  11326. ' JID: ' +
  11327. __e(jid) +
  11328. ' ' +
  11329. __e(desc_chat) +
  11330. '"\n href="#">\n <div class="avatar avatar-' +
  11331. __e(chat_status) +
  11332. '">\n <span class="status-icon icon-' +
  11333. __e(chat_status) +
  11334. '" title="' +
  11335. __e(desc_status) +
  11336. '"></span>\n </div>\n ';
  11337. if (num_unread) { ;
  11338. __p += '\n <span class="msgs-indicator">' +
  11339. __e( num_unread ) +
  11340. '</span>\n ';
  11341. } ;
  11342. __p += '\n <span class="contact-name ';
  11343. if (num_unread) { ;
  11344. __p += ' unread-msgs ';
  11345. } ;
  11346. __p += '">' +
  11347. __e(fullname) +
  11348. '</span>\n</a>\n';
  11349. if (allow_contact_removal) { ;
  11350. __p += '\n<a class="remove-xmpp-contact icon-remove" title="' +
  11351. __e(desc_remove) +
  11352. '" href="#"></a>\n';
  11353. } ;
  11354. __p += '\n\n\n';
  11355. }
  11356. return __p
  11357. };});
  11358. // Converse.js (A browser based XMPP chat client)
  11359. // http://conversejs.org
  11360. //
  11361. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  11362. // Licensed under the Mozilla Public License (MPLv2)
  11363. //
  11364. /*global define */
  11365. (function (root, factory) {
  11366. define('converse-rosterview',["jquery.noconflict", "converse-core", "tpl!group_header", "tpl!pending_contact", "tpl!requesting_contact", "tpl!roster", "tpl!roster_filter", "tpl!roster_item"], factory);
  11367. })(undefined, function ($, converse, tpl_group_header, tpl_pending_contact, tpl_requesting_contact, tpl_roster, tpl_roster_filter, tpl_roster_item) {
  11368. "use strict";
  11369. var _converse$env = converse.env,
  11370. Backbone = _converse$env.Backbone,
  11371. utils = _converse$env.utils,
  11372. Strophe = _converse$env.Strophe,
  11373. $iq = _converse$env.$iq,
  11374. b64_sha1 = _converse$env.b64_sha1,
  11375. sizzle = _converse$env.sizzle,
  11376. _ = _converse$env._;
  11377. converse.plugins.add('converse-rosterview', {
  11378. overrides: {
  11379. // Overrides mentioned here will be picked up by converse.js's
  11380. // plugin architecture they will replace existing methods on the
  11381. // relevant objects or classes.
  11382. //
  11383. // New functions which don't exist yet can also be added.
  11384. afterReconnected: function afterReconnected() {
  11385. this.__super__.afterReconnected.apply(this, arguments);
  11386. },
  11387. _tearDown: function _tearDown() {
  11388. /* Remove the rosterview when tearing down. It gets created
  11389. * anew when reconnecting or logging in.
  11390. */
  11391. this.__super__._tearDown.apply(this, arguments);
  11392. if (!_.isUndefined(this.rosterview)) {
  11393. this.rosterview.remove();
  11394. }
  11395. },
  11396. RosterGroups: {
  11397. comparator: function comparator() {
  11398. // RosterGroupsComparator only gets set later (once i18n is
  11399. // set up), so we need to wrap it in this nameless function.
  11400. var _converse = this.__super__._converse;
  11401. return _converse.RosterGroupsComparator.apply(this, arguments);
  11402. }
  11403. }
  11404. },
  11405. initialize: function initialize() {
  11406. /* The initialize function gets called as soon as the plugin is
  11407. * loaded by converse.js's plugin machinery.
  11408. */
  11409. var _converse = this._converse,
  11410. __ = _converse.__,
  11411. ___ = _converse.___;
  11412. _converse.api.settings.update({
  11413. allow_chat_pending_contacts: true,
  11414. allow_contact_removal: true,
  11415. show_toolbar: true
  11416. });
  11417. var STATUSES = {
  11418. 'dnd': __('This contact is busy'),
  11419. 'online': __('This contact is online'),
  11420. 'offline': __('This contact is offline'),
  11421. 'unavailable': __('This contact is unavailable'),
  11422. 'xa': __('This contact is away for an extended period'),
  11423. 'away': __('This contact is away')
  11424. };
  11425. var LABEL_CONTACTS = __('Contacts');
  11426. var LABEL_GROUPS = __('Groups');
  11427. var HEADER_CURRENT_CONTACTS = __('My contacts');
  11428. var HEADER_PENDING_CONTACTS = __('Pending contacts');
  11429. var HEADER_REQUESTING_CONTACTS = __('Contact requests');
  11430. var HEADER_UNGROUPED = __('Ungrouped');
  11431. var HEADER_WEIGHTS = {};
  11432. HEADER_WEIGHTS[HEADER_REQUESTING_CONTACTS] = 0;
  11433. HEADER_WEIGHTS[HEADER_CURRENT_CONTACTS] = 1;
  11434. HEADER_WEIGHTS[HEADER_UNGROUPED] = 2;
  11435. HEADER_WEIGHTS[HEADER_PENDING_CONTACTS] = 3;
  11436. _converse.RosterGroupsComparator = function (a, b) {
  11437. /* Groups are sorted alphabetically, ignoring case.
  11438. * However, Ungrouped, Requesting Contacts and Pending Contacts
  11439. * appear last and in that order.
  11440. */
  11441. a = a.get('name');
  11442. b = b.get('name');
  11443. var special_groups = _.keys(HEADER_WEIGHTS);
  11444. var a_is_special = _.includes(special_groups, a);
  11445. var b_is_special = _.includes(special_groups, b);
  11446. if (!a_is_special && !b_is_special) {
  11447. return a.toLowerCase() < b.toLowerCase() ? -1 : a.toLowerCase() > b.toLowerCase() ? 1 : 0;
  11448. } else if (a_is_special && b_is_special) {
  11449. return HEADER_WEIGHTS[a] < HEADER_WEIGHTS[b] ? -1 : HEADER_WEIGHTS[a] > HEADER_WEIGHTS[b] ? 1 : 0;
  11450. } else if (!a_is_special && b_is_special) {
  11451. return b === HEADER_REQUESTING_CONTACTS ? 1 : -1;
  11452. } else if (a_is_special && !b_is_special) {
  11453. return a === HEADER_REQUESTING_CONTACTS ? -1 : 1;
  11454. }
  11455. };
  11456. _converse.RosterFilter = Backbone.Model.extend({
  11457. initialize: function initialize() {
  11458. this.set({
  11459. 'filter_text': '',
  11460. 'filter_type': 'contacts',
  11461. 'chat_state': ''
  11462. });
  11463. }
  11464. });
  11465. _converse.RosterFilterView = Backbone.View.extend({
  11466. tagName: 'span',
  11467. events: {
  11468. "keydown .roster-filter": "liveFilter",
  11469. "submit form.roster-filter-form": "submitFilter",
  11470. "click .onX": "clearFilter",
  11471. "mousemove .x": "toggleX",
  11472. "change .filter-type": "changeTypeFilter",
  11473. "change .state-type": "changeChatStateFilter"
  11474. },
  11475. initialize: function initialize() {
  11476. this.model.on('change:filter_type', this.render, this);
  11477. this.model.on('change:filter_text', this.renderClearButton, this);
  11478. },
  11479. render: function render() {
  11480. this.el.innerHTML = tpl_roster_filter(_.extend(this.model.toJSON(), {
  11481. placeholder: __('Filter'),
  11482. label_contacts: LABEL_CONTACTS,
  11483. label_groups: LABEL_GROUPS,
  11484. label_state: __('State'),
  11485. label_any: __('Any'),
  11486. label_unread_messages: __('Unread'),
  11487. label_online: __('Online'),
  11488. label_chatty: __('Chatty'),
  11489. label_busy: __('Busy'),
  11490. label_away: __('Away'),
  11491. label_xa: __('Extended Away'),
  11492. label_offline: __('Offline')
  11493. }));
  11494. this.renderClearButton();
  11495. return this.$el;
  11496. },
  11497. renderClearButton: function renderClearButton() {
  11498. var roster_filter = this.el.querySelector('.roster-filter');
  11499. if (_.isNull(roster_filter)) {
  11500. return;
  11501. }
  11502. roster_filter.classList[this.tog(roster_filter.value)]('x');
  11503. },
  11504. tog: function tog(v) {
  11505. return v ? 'add' : 'remove';
  11506. },
  11507. toggleX: function toggleX(ev) {
  11508. if (ev && ev.preventDefault) {
  11509. ev.preventDefault();
  11510. }
  11511. var el = ev.target;
  11512. el.classList[this.tog(el.offsetWidth - 18 < ev.clientX - el.getBoundingClientRect().left)]('onX');
  11513. },
  11514. changeChatStateFilter: function changeChatStateFilter(ev) {
  11515. if (ev && ev.preventDefault) {
  11516. ev.preventDefault();
  11517. }
  11518. this.model.save({
  11519. 'chat_state': this.el.querySelector('.state-type').value
  11520. });
  11521. },
  11522. changeTypeFilter: function changeTypeFilter(ev) {
  11523. if (ev && ev.preventDefault) {
  11524. ev.preventDefault();
  11525. }
  11526. var type = ev.target.value;
  11527. if (type === 'state') {
  11528. this.model.save({
  11529. 'filter_type': type,
  11530. 'chat_state': this.el.querySelector('.state-type').value
  11531. });
  11532. } else {
  11533. this.model.save({
  11534. 'filter_type': type,
  11535. 'filter_text': this.el.querySelector('.roster-filter').value
  11536. });
  11537. }
  11538. },
  11539. liveFilter: _.debounce(function (ev) {
  11540. this.model.save({
  11541. 'filter_type': this.el.querySelector('.filter-type').value,
  11542. 'filter_text': this.el.querySelector('.roster-filter').value
  11543. });
  11544. }, 250),
  11545. submitFilter: function submitFilter(ev) {
  11546. if (ev && ev.preventDefault) {
  11547. ev.preventDefault();
  11548. }
  11549. this.liveFilter();
  11550. this.render();
  11551. },
  11552. isActive: function isActive() {
  11553. /* Returns true if the filter is enabled (i.e. if the user
  11554. * has added values to the filter).
  11555. */
  11556. if (this.model.get('filter_type') === 'state' || this.model.get('filter_text')) {
  11557. return true;
  11558. }
  11559. return false;
  11560. },
  11561. show: function show() {
  11562. if (this.$el.is(':visible')) {
  11563. return this;
  11564. }
  11565. this.$el.show();
  11566. return this;
  11567. },
  11568. hide: function hide() {
  11569. if (!this.$el.is(':visible')) {
  11570. return this;
  11571. }
  11572. if (this.el.querySelector('.roster-filter').value.length > 0) {
  11573. // Don't hide if user is currently filtering.
  11574. return;
  11575. }
  11576. this.model.save({
  11577. 'filter_text': '',
  11578. 'chat_state': ''
  11579. });
  11580. this.$el.hide();
  11581. return this;
  11582. },
  11583. clearFilter: function clearFilter(ev) {
  11584. if (ev && ev.preventDefault) {
  11585. ev.preventDefault();
  11586. $(ev.target).removeClass('x onX').val('');
  11587. }
  11588. this.model.save({
  11589. 'filter_text': ''
  11590. });
  11591. }
  11592. });
  11593. _converse.RosterView = Backbone.Overview.extend({
  11594. tagName: 'div',
  11595. id: 'converse-roster',
  11596. initialize: function initialize() {
  11597. _converse.roster.on("add", this.onContactAdd, this);
  11598. _converse.roster.on('change', this.onContactChange, this);
  11599. _converse.roster.on("destroy", this.update, this);
  11600. _converse.roster.on("remove", this.update, this);
  11601. this.model.on("add", this.onGroupAdd, this);
  11602. this.model.on("reset", this.reset, this);
  11603. _converse.on('rosterGroupsFetched', this.positionFetchedGroups, this);
  11604. _converse.on('rosterContactsFetched', this.update, this);
  11605. this.createRosterFilter();
  11606. },
  11607. render: function render() {
  11608. this.renderRoster();
  11609. this.$el.html(this.filter_view.render());
  11610. if (!_converse.allow_contact_requests) {
  11611. // XXX: if we ever support live editing of config then
  11612. // we'll need to be able to remove this class on the fly.
  11613. this.el.classList.add('no-contact-requests');
  11614. }
  11615. return this;
  11616. },
  11617. renderRoster: function renderRoster() {
  11618. this.$roster = $(tpl_roster());
  11619. this.roster = this.$roster[0];
  11620. },
  11621. createRosterFilter: function createRosterFilter() {
  11622. // Create a model on which we can store filter properties
  11623. var model = new _converse.RosterFilter();
  11624. model.id = b64_sha1("_converse.rosterfilter" + _converse.bare_jid);
  11625. model.browserStorage = new Backbone.BrowserStorage.local(this.filter.id);
  11626. this.filter_view = new _converse.RosterFilterView({ 'model': model });
  11627. this.filter_view.model.on('change', this.updateFilter, this);
  11628. this.filter_view.model.fetch();
  11629. },
  11630. updateFilter: _.debounce(function () {
  11631. /* Filter the roster again.
  11632. * Called whenever the filter settings have been changed or
  11633. * when contacts have been added, removed or changed.
  11634. *
  11635. * Debounced so that it doesn't get called for every
  11636. * contact fetched from browser storage.
  11637. */
  11638. var type = this.filter_view.model.get('filter_type');
  11639. if (type === 'state') {
  11640. this.filter(this.filter_view.model.get('chat_state'), type);
  11641. } else {
  11642. this.filter(this.filter_view.model.get('filter_text'), type);
  11643. }
  11644. }, 100),
  11645. update: _.debounce(function () {
  11646. if (_.isNull(this.roster.parentElement)) {
  11647. this.$el.append(this.$roster.show());
  11648. }
  11649. return this.showHideFilter();
  11650. }, _converse.animate ? 100 : 0),
  11651. showHideFilter: function showHideFilter() {
  11652. if (!this.$el.is(':visible')) {
  11653. return;
  11654. }
  11655. if (_converse.roster.length >= 10) {
  11656. this.filter_view.show();
  11657. } else if (!this.filter_view.isActive()) {
  11658. this.filter_view.hide();
  11659. }
  11660. return this;
  11661. },
  11662. filter: function filter(query, type) {
  11663. // First we make sure the filter is restored to its
  11664. // original state
  11665. _.each(this.getAll(), function (view) {
  11666. if (view.model.contacts.length > 0) {
  11667. view.show().filter('');
  11668. }
  11669. });
  11670. // Now we can filter
  11671. query = query.toLowerCase();
  11672. if (type === 'groups') {
  11673. _.each(this.getAll(), function (view, idx) {
  11674. if (!_.includes(view.model.get('name').toLowerCase(), query.toLowerCase())) {
  11675. view.hide();
  11676. } else if (view.model.contacts.length > 0) {
  11677. view.show();
  11678. }
  11679. });
  11680. } else {
  11681. _.each(this.getAll(), function (view) {
  11682. view.filter(query, type);
  11683. });
  11684. }
  11685. },
  11686. reset: function reset() {
  11687. _converse.roster.reset();
  11688. this.removeAll();
  11689. this.renderRoster();
  11690. this.render().update();
  11691. return this;
  11692. },
  11693. onGroupAdd: function onGroupAdd(group) {
  11694. var view = new _converse.RosterGroupView({ model: group });
  11695. this.add(group.get('name'), view.render());
  11696. this.positionGroup(view);
  11697. },
  11698. onContactAdd: function onContactAdd(contact) {
  11699. this.addRosterContact(contact).update();
  11700. this.updateFilter();
  11701. },
  11702. onContactChange: function onContactChange(contact) {
  11703. this.updateChatBox(contact).update();
  11704. if (_.has(contact.changed, 'subscription')) {
  11705. if (contact.changed.subscription === 'from') {
  11706. this.addContactToGroup(contact, HEADER_PENDING_CONTACTS);
  11707. } else if (_.includes(['both', 'to'], contact.get('subscription'))) {
  11708. this.addExistingContact(contact);
  11709. }
  11710. }
  11711. if (_.has(contact.changed, 'ask') && contact.changed.ask === 'subscribe') {
  11712. this.addContactToGroup(contact, HEADER_PENDING_CONTACTS);
  11713. }
  11714. if (_.has(contact.changed, 'subscription') && contact.changed.requesting === 'true') {
  11715. this.addContactToGroup(contact, HEADER_REQUESTING_CONTACTS);
  11716. }
  11717. this.updateFilter();
  11718. },
  11719. updateChatBox: function updateChatBox(contact) {
  11720. var chatbox = _converse.chatboxes.get(contact.get('jid')),
  11721. changes = {};
  11722. if (!chatbox) {
  11723. return this;
  11724. }
  11725. if (_.has(contact.changed, 'chat_status')) {
  11726. changes.chat_status = contact.get('chat_status');
  11727. }
  11728. if (_.has(contact.changed, 'status')) {
  11729. changes.status = contact.get('status');
  11730. }
  11731. chatbox.save(changes);
  11732. return this;
  11733. },
  11734. positionFetchedGroups: function positionFetchedGroups() {
  11735. /* Instead of throwing an add event for each group
  11736. * fetched, we wait until they're all fetched and then
  11737. * we position them.
  11738. * Works around the problem of positionGroup not
  11739. * working when all groups besides the one being
  11740. * positioned aren't already in inserted into the
  11741. * roster DOM element.
  11742. */
  11743. var that = this;
  11744. this.model.sort();
  11745. this.model.each(function (group, idx) {
  11746. var view = that.get(group.get('name'));
  11747. if (!view) {
  11748. view = new _converse.RosterGroupView({ model: group });
  11749. that.add(group.get('name'), view.render());
  11750. }
  11751. if (idx === 0) {
  11752. that.$roster.append(view.$el);
  11753. } else {
  11754. that.appendGroup(view);
  11755. }
  11756. });
  11757. },
  11758. positionGroup: function positionGroup(view) {
  11759. /* Place the group's DOM element in the correct alphabetical
  11760. * position amongst the other groups in the roster.
  11761. */
  11762. var $groups = this.$roster.find('.roster-group'),
  11763. index = $groups.length ? this.model.indexOf(view.model) : 0;
  11764. if (index === 0) {
  11765. this.$roster.prepend(view.$el);
  11766. } else if (index === this.model.length - 1) {
  11767. this.appendGroup(view);
  11768. } else {
  11769. $($groups.eq(index)).before(view.$el);
  11770. }
  11771. return this;
  11772. },
  11773. appendGroup: function appendGroup(view) {
  11774. /* Add the group at the bottom of the roster
  11775. */
  11776. var $last = this.$roster.find('.roster-group').last();
  11777. var $siblings = $last.siblings('dd');
  11778. if ($siblings.length > 0) {
  11779. $siblings.last().after(view.$el);
  11780. } else {
  11781. $last.after(view.$el);
  11782. }
  11783. return this;
  11784. },
  11785. getGroup: function getGroup(name) {
  11786. /* Returns the group as specified by name.
  11787. * Creates the group if it doesn't exist.
  11788. */
  11789. var view = this.get(name);
  11790. if (view) {
  11791. return view.model;
  11792. }
  11793. return this.model.create({ name: name, id: b64_sha1(name) });
  11794. },
  11795. addContactToGroup: function addContactToGroup(contact, name) {
  11796. this.getGroup(name).contacts.add(contact);
  11797. },
  11798. addExistingContact: function addExistingContact(contact) {
  11799. var groups = void 0;
  11800. if (_converse.roster_groups) {
  11801. groups = contact.get('groups');
  11802. if (groups.length === 0) {
  11803. groups = [HEADER_UNGROUPED];
  11804. }
  11805. } else {
  11806. groups = [HEADER_CURRENT_CONTACTS];
  11807. }
  11808. _.each(groups, _.bind(this.addContactToGroup, this, contact));
  11809. },
  11810. addRosterContact: function addRosterContact(contact) {
  11811. if (contact.get('subscription') === 'both' || contact.get('subscription') === 'to') {
  11812. this.addExistingContact(contact);
  11813. } else {
  11814. if (contact.get('ask') === 'subscribe' || contact.get('subscription') === 'from') {
  11815. this.addContactToGroup(contact, HEADER_PENDING_CONTACTS);
  11816. } else if (contact.get('requesting') === true) {
  11817. this.addContactToGroup(contact, HEADER_REQUESTING_CONTACTS);
  11818. }
  11819. }
  11820. return this;
  11821. }
  11822. });
  11823. _converse.RosterContactView = Backbone.View.extend({
  11824. tagName: 'dd',
  11825. events: {
  11826. "click .accept-xmpp-request": "acceptRequest",
  11827. "click .decline-xmpp-request": "declineRequest",
  11828. "click .open-chat": "openChat",
  11829. "click .remove-xmpp-contact": "removeContact"
  11830. },
  11831. initialize: function initialize() {
  11832. this.model.on("change", this.render, this);
  11833. this.model.on("remove", this.remove, this);
  11834. this.model.on("destroy", this.remove, this);
  11835. this.model.on("open", this.openChat, this);
  11836. },
  11837. render: function render() {
  11838. var that = this;
  11839. if (!this.mayBeShown()) {
  11840. this.$el.hide();
  11841. return this;
  11842. }
  11843. var item = this.model,
  11844. ask = item.get('ask'),
  11845. chat_status = item.get('chat_status'),
  11846. requesting = item.get('requesting'),
  11847. subscription = item.get('subscription');
  11848. var classes_to_remove = ['current-xmpp-contact', 'pending-xmpp-contact', 'requesting-xmpp-contact'].concat(_.keys(STATUSES));
  11849. _.each(classes_to_remove, function (cls) {
  11850. if (_.includes(that.el.className, cls)) {
  11851. that.el.classList.remove(cls);
  11852. }
  11853. });
  11854. this.$el.addClass(chat_status).data('status', chat_status);
  11855. if (ask === 'subscribe' || subscription === 'from') {
  11856. /* ask === 'subscribe'
  11857. * Means we have asked to subscribe to them.
  11858. *
  11859. * subscription === 'from'
  11860. * They are subscribed to use, but not vice versa.
  11861. * We assume that there is a pending subscription
  11862. * from us to them (otherwise we're in a state not
  11863. * supported by converse.js).
  11864. *
  11865. * So in both cases the user is a "pending" contact.
  11866. */
  11867. this.el.classList.add('pending-xmpp-contact');
  11868. this.$el.html(tpl_pending_contact(_.extend(item.toJSON(), {
  11869. 'desc_remove': __(___('Click to remove %1$s as a contact'), item.get('fullname')),
  11870. 'allow_chat_pending_contacts': _converse.allow_chat_pending_contacts
  11871. })));
  11872. } else if (requesting === true) {
  11873. this.el.classList.add('requesting-xmpp-contact');
  11874. this.$el.html(tpl_requesting_contact(_.extend(item.toJSON(), {
  11875. 'desc_accept': __(___("Click to accept the contact request from %1$s"), item.get('fullname')),
  11876. 'desc_decline': __(___("Click to decline the contact request from %1$s"), item.get('fullname')),
  11877. 'allow_chat_pending_contacts': _converse.allow_chat_pending_contacts
  11878. })));
  11879. } else if (subscription === 'both' || subscription === 'to') {
  11880. this.el.classList.add('current-xmpp-contact');
  11881. this.el.classList.remove(_.without(['both', 'to'], subscription)[0]);
  11882. this.el.classList.add(subscription);
  11883. this.renderRosterItem(item);
  11884. }
  11885. return this;
  11886. },
  11887. renderRosterItem: function renderRosterItem(item) {
  11888. var chat_status = item.get('chat_status');
  11889. this.$el.html(tpl_roster_item(_.extend(item.toJSON(), {
  11890. 'desc_status': STATUSES[chat_status || 'offline'],
  11891. 'desc_chat': __('Click to chat with this contact'),
  11892. 'desc_remove': __(___('Click to remove %1$s as a contact'), item.get('fullname')),
  11893. 'title_fullname': __('Name'),
  11894. 'allow_contact_removal': _converse.allow_contact_removal,
  11895. 'num_unread': item.get('num_unread') || 0
  11896. })));
  11897. return this;
  11898. },
  11899. isGroupCollapsed: function isGroupCollapsed() {
  11900. /* Check whether the group in which this contact appears is
  11901. * collapsed.
  11902. */
  11903. // XXX: this sucks and is fragile.
  11904. // It's because I tried to do the "right thing"
  11905. // and use definition lists to represent roster groups.
  11906. // If roster group items were inside the group elements, we
  11907. // would simplify things by not having to check whether the
  11908. // group is collapsed or not.
  11909. var name = this.$el.prevAll('dt:first').data('group');
  11910. var group = _.head(_converse.rosterview.model.where({ 'name': name.toString() }));
  11911. if (group.get('state') === _converse.CLOSED) {
  11912. return true;
  11913. }
  11914. return false;
  11915. },
  11916. mayBeShown: function mayBeShown() {
  11917. /* Return a boolean indicating whether this contact should
  11918. * generally be visible in the roster.
  11919. *
  11920. * It doesn't check for the more specific case of whether
  11921. * the group it's in is collapsed (see isGroupCollapsed).
  11922. */
  11923. var chatStatus = this.model.get('chat_status');
  11924. if (_converse.show_only_online_users && chatStatus !== 'online' || _converse.hide_offline_users && chatStatus === 'offline') {
  11925. // If pending or requesting, show
  11926. if (this.model.get('ask') === 'subscribe' || this.model.get('subscription') === 'from' || this.model.get('requesting') === true) {
  11927. return true;
  11928. }
  11929. return false;
  11930. }
  11931. return true;
  11932. },
  11933. openChat: function openChat(ev) {
  11934. if (ev && ev.preventDefault) {
  11935. ev.preventDefault();
  11936. }
  11937. return _converse.chatboxviews.showChat(this.model.attributes, true);
  11938. },
  11939. removeContact: function removeContact(ev) {
  11940. var _this = this;
  11941. if (ev && ev.preventDefault) {
  11942. ev.preventDefault();
  11943. }
  11944. if (!_converse.allow_contact_removal) {
  11945. return;
  11946. }
  11947. var result = confirm(__("Are you sure you want to remove this contact?"));
  11948. if (result === true) {
  11949. var iq = $iq({ type: 'set' }).c('query', { xmlns: Strophe.NS.ROSTER }).c('item', { jid: this.model.get('jid'), subscription: "remove" });
  11950. _converse.connection.sendIQ(iq, function (iq) {
  11951. _this.model.destroy();
  11952. _this.remove();
  11953. }, function (err) {
  11954. alert(__("Sorry, there was an error while trying to remove " + name + " as a contact."));
  11955. _converse.log(err, Strophe.LogLevel.ERROR);
  11956. });
  11957. }
  11958. },
  11959. acceptRequest: function acceptRequest(ev) {
  11960. var _this2 = this;
  11961. if (ev && ev.preventDefault) {
  11962. ev.preventDefault();
  11963. }
  11964. _converse.roster.sendContactAddIQ(this.model.get('jid'), this.model.get('fullname'), [], function () {
  11965. _this2.model.authorize().subscribe();
  11966. });
  11967. },
  11968. declineRequest: function declineRequest(ev) {
  11969. if (ev && ev.preventDefault) {
  11970. ev.preventDefault();
  11971. }
  11972. var result = confirm(__("Are you sure you want to decline this contact request?"));
  11973. if (result === true) {
  11974. this.model.unauthorize().destroy();
  11975. }
  11976. return this;
  11977. }
  11978. });
  11979. _converse.RosterGroupView = Backbone.Overview.extend({
  11980. tagName: 'dt',
  11981. className: 'roster-group',
  11982. events: {
  11983. "click a.group-toggle": "toggle"
  11984. },
  11985. initialize: function initialize() {
  11986. this.model.contacts.on("add", this.addContact, this);
  11987. this.model.contacts.on("change:subscription", this.onContactSubscriptionChange, this);
  11988. this.model.contacts.on("change:requesting", this.onContactRequestChange, this);
  11989. this.model.contacts.on("change:chat_status", function (contact) {
  11990. // This might be optimized by instead of first sorting,
  11991. // finding the correct position in positionContact
  11992. this.model.contacts.sort();
  11993. this.positionContact(contact).render();
  11994. }, this);
  11995. this.model.contacts.on("destroy", this.onRemove, this);
  11996. this.model.contacts.on("remove", this.onRemove, this);
  11997. _converse.roster.on('change:groups', this.onContactGroupChange, this);
  11998. },
  11999. render: function render() {
  12000. this.el.setAttribute('data-group', this.model.get('name'));
  12001. var html = tpl_group_header({
  12002. label_group: this.model.get('name'),
  12003. desc_group_toggle: this.model.get('description'),
  12004. toggle_state: this.model.get('state')
  12005. });
  12006. this.el.innerHTML = html;
  12007. return this;
  12008. },
  12009. addContact: function addContact(contact) {
  12010. var view = new _converse.RosterContactView({ model: contact });
  12011. this.add(contact.get('id'), view);
  12012. view = this.positionContact(contact).render();
  12013. if (view.mayBeShown()) {
  12014. if (this.model.get('state') === _converse.CLOSED) {
  12015. if (view.$el[0].style.display !== "none") {
  12016. view.$el.hide();
  12017. }
  12018. if (!this.$el.is(':visible')) {
  12019. this.$el.show();
  12020. }
  12021. } else {
  12022. if (this.$el[0].style.display !== "block") {
  12023. this.show();
  12024. }
  12025. }
  12026. }
  12027. },
  12028. positionContact: function positionContact(contact) {
  12029. /* Place the contact's DOM element in the correct alphabetical
  12030. * position amongst the other contacts in this group.
  12031. */
  12032. var view = this.get(contact.get('id'));
  12033. var index = this.model.contacts.indexOf(contact);
  12034. view.$el.detach();
  12035. if (index === 0) {
  12036. this.$el.after(view.$el);
  12037. } else if (index === this.model.contacts.length - 1) {
  12038. this.$el.nextUntil('dt').last().after(view.$el);
  12039. } else {
  12040. this.$el.nextUntil('dt').eq(index).before(view.$el);
  12041. }
  12042. return view;
  12043. },
  12044. show: function show() {
  12045. this.$el.show();
  12046. _.each(this.getAll(), function (view) {
  12047. if (view.mayBeShown() && !view.isGroupCollapsed()) {
  12048. view.$el.show();
  12049. }
  12050. });
  12051. return this;
  12052. },
  12053. hide: function hide() {
  12054. this.$el.nextUntil('dt').addBack().hide();
  12055. },
  12056. filter: function filter(q, type) {
  12057. var _this3 = this;
  12058. /* Filter the group's contacts based on the query "q".
  12059. * The query is matched against the contact's full name.
  12060. * If all contacts are filtered out (i.e. hidden), then the
  12061. * group must be filtered out as well.
  12062. */
  12063. var matches = void 0;
  12064. if (q.length === 0) {
  12065. if (this.model.get('state') === _converse.OPENED) {
  12066. this.model.contacts.each(function (item) {
  12067. var view = _this3.get(item.get('id'));
  12068. if (view.mayBeShown() && !view.isGroupCollapsed()) {
  12069. view.$el.show();
  12070. }
  12071. });
  12072. }
  12073. this.showIfNecessary();
  12074. } else {
  12075. q = q.toLowerCase();
  12076. if (type === 'state') {
  12077. if (this.model.get('name') === HEADER_REQUESTING_CONTACTS) {
  12078. // When filtering by chat state, we still want to
  12079. // show requesting contacts, even though they don't
  12080. // have the state in question.
  12081. matches = this.model.contacts.filter(function (contact) {
  12082. return utils.contains.not('chat_status', q)(contact) && !contact.get('requesting');
  12083. });
  12084. } else if (q === 'unread_messages') {
  12085. matches = this.model.contacts.filter({ 'num_unread': 0 });
  12086. } else {
  12087. matches = this.model.contacts.filter(utils.contains.not('chat_status', q));
  12088. }
  12089. } else {
  12090. matches = this.model.contacts.filter(utils.contains.not('fullname', q));
  12091. }
  12092. if (matches.length === this.model.contacts.length) {
  12093. // hide the whole group
  12094. this.hide();
  12095. } else {
  12096. _.each(matches, function (item) {
  12097. _this3.get(item.get('id')).$el.hide();
  12098. });
  12099. if (this.model.get('state') === _converse.OPENED) {
  12100. _.each(this.model.contacts.reject(utils.contains.not('fullname', q)), function (item) {
  12101. _this3.get(item.get('id')).$el.show();
  12102. });
  12103. }
  12104. this.showIfNecessary();
  12105. }
  12106. }
  12107. },
  12108. showIfNecessary: function showIfNecessary() {
  12109. if (!this.$el.is(':visible') && this.model.contacts.length > 0) {
  12110. this.$el.show();
  12111. }
  12112. },
  12113. toggle: function toggle(ev) {
  12114. if (ev && ev.preventDefault) {
  12115. ev.preventDefault();
  12116. }
  12117. var $el = $(ev.target);
  12118. if ($el.hasClass("icon-opened")) {
  12119. this.$el.nextUntil('dt').slideUp();
  12120. this.model.save({ state: _converse.CLOSED });
  12121. $el.removeClass("icon-opened").addClass("icon-closed");
  12122. } else {
  12123. $el.removeClass("icon-closed").addClass("icon-opened");
  12124. this.model.save({ state: _converse.OPENED });
  12125. this.filter(_converse.rosterview.$('.roster-filter').val() || '', _converse.rosterview.$('.filter-type').val());
  12126. }
  12127. },
  12128. onContactGroupChange: function onContactGroupChange(contact) {
  12129. var in_this_group = _.includes(contact.get('groups'), this.model.get('name'));
  12130. var cid = contact.get('id');
  12131. var in_this_overview = !this.get(cid);
  12132. if (in_this_group && !in_this_overview) {
  12133. this.model.contacts.remove(cid);
  12134. } else if (!in_this_group && in_this_overview) {
  12135. this.addContact(contact);
  12136. }
  12137. },
  12138. onContactSubscriptionChange: function onContactSubscriptionChange(contact) {
  12139. if (this.model.get('name') === HEADER_PENDING_CONTACTS && contact.get('subscription') !== 'from') {
  12140. this.model.contacts.remove(contact.get('id'));
  12141. }
  12142. },
  12143. onContactRequestChange: function onContactRequestChange(contact) {
  12144. if (this.model.get('name') === HEADER_REQUESTING_CONTACTS && !contact.get('requesting')) {
  12145. /* We suppress events, otherwise the remove event will
  12146. * also cause the contact's view to be removed from the
  12147. * "Pending Contacts" group.
  12148. */
  12149. this.model.contacts.remove(contact.get('id'), { 'silent': true });
  12150. // Since we suppress events, we make sure the view and
  12151. // contact are removed from this group.
  12152. this.get(contact.get('id')).remove();
  12153. this.onRemove(contact);
  12154. }
  12155. },
  12156. onRemove: function onRemove(contact) {
  12157. this.remove(contact.get('id'));
  12158. if (this.model.contacts.length === 0) {
  12159. this.$el.hide();
  12160. }
  12161. }
  12162. });
  12163. /* -------- Event Handlers ----------- */
  12164. var onChatBoxMaximized = function onChatBoxMaximized(chatboxview) {
  12165. /* When a chat box gets maximized, the num_unread counter needs
  12166. * to be cleared, but if chatbox is scrolled up, then num_unread should not be cleared.
  12167. */
  12168. var chatbox = chatboxview.model;
  12169. if (chatbox.get('type') !== 'chatroom') {
  12170. var contact = _.head(_converse.roster.where({ 'jid': chatbox.get('jid') }));
  12171. if (!_.isUndefined(contact) && !chatbox.isScrolledUp()) {
  12172. contact.save({ 'num_unread': 0 });
  12173. }
  12174. }
  12175. };
  12176. var onMessageReceived = function onMessageReceived(data) {
  12177. /* Given a newly received message, update the unread counter on
  12178. * the relevant roster contact.
  12179. */
  12180. var chatbox = data.chatbox;
  12181. if (_.isUndefined(chatbox)) {
  12182. return;
  12183. }
  12184. if (_.isNull(data.stanza.querySelector('body'))) {
  12185. return; // The message has no text
  12186. }
  12187. if (chatbox.get('type') !== 'chatroom' && utils.isNewMessage(data.stanza) && chatbox.newMessageWillBeHidden()) {
  12188. var contact = _.head(_converse.roster.where({ 'jid': chatbox.get('jid') }));
  12189. if (!_.isUndefined(contact)) {
  12190. contact.save({ 'num_unread': contact.get('num_unread') + 1 });
  12191. }
  12192. }
  12193. };
  12194. var onChatBoxScrolledDown = function onChatBoxScrolledDown(data) {
  12195. var chatbox = data.chatbox;
  12196. if (_.isUndefined(chatbox)) {
  12197. return;
  12198. }
  12199. var contact = _.head(_converse.roster.where({ 'jid': chatbox.get('jid') }));
  12200. if (!_.isUndefined(contact)) {
  12201. contact.save({ 'num_unread': 0 });
  12202. }
  12203. };
  12204. var initRoster = function initRoster() {
  12205. /* Create an instance of RosterView once the RosterGroups
  12206. * collection has been created (in converse-core.js)
  12207. */
  12208. _converse.rosterview = new _converse.RosterView({
  12209. 'model': _converse.rostergroups
  12210. });
  12211. _converse.rosterview.render();
  12212. };
  12213. _converse.api.listen.on('rosterInitialized', initRoster);
  12214. _converse.api.listen.on('rosterReadyAfterReconnection', initRoster);
  12215. _converse.api.listen.on('message', onMessageReceived);
  12216. _converse.api.listen.on('chatBoxMaximized', onChatBoxMaximized);
  12217. _converse.api.listen.on('chatBoxScrolledDown', onChatBoxScrolledDown);
  12218. }
  12219. });
  12220. });
  12221. //# sourceMappingURL=converse-rosterview.js.map;
  12222. // Converse.js (A browser based XMPP chat client)
  12223. // http://conversejs.org
  12224. //
  12225. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  12226. // Licensed under the Mozilla Public License (MPLv2)
  12227. //
  12228. /*global define */
  12229. (function (root, factory) {
  12230. define('converse-controlbox',["jquery.noconflict", "converse-core", "tpl!add_contact_dropdown", "tpl!add_contact_form", "tpl!change_status_message", "tpl!chat_status", "tpl!choose_status", "tpl!contacts_panel", "tpl!contacts_tab", "tpl!controlbox", "tpl!controlbox_toggle", "tpl!login_panel", "tpl!login_tab", "tpl!search_contact", "tpl!status_option", "converse-chatview", "converse-rosterview"], factory);
  12231. })(undefined, function ($, converse, tpl_add_contact_dropdown, tpl_add_contact_form, tpl_change_status_message, tpl_chat_status, tpl_choose_status, tpl_contacts_panel, tpl_contacts_tab, tpl_controlbox, tpl_controlbox_toggle, tpl_login_panel, tpl_login_tab, tpl_search_contact, tpl_status_option) {
  12232. "use strict";
  12233. var USERS_PANEL_ID = 'users';
  12234. var CHATBOX_TYPE = 'chatbox';
  12235. var _converse$env = converse.env,
  12236. Strophe = _converse$env.Strophe,
  12237. Backbone = _converse$env.Backbone,
  12238. utils = _converse$env.utils,
  12239. _ = _converse$env._,
  12240. fp = _converse$env.fp,
  12241. moment = _converse$env.moment;
  12242. converse.plugins.add('converse-controlbox', {
  12243. overrides: {
  12244. // Overrides mentioned here will be picked up by converse.js's
  12245. // plugin architecture they will replace existing methods on the
  12246. // relevant objects or classes.
  12247. //
  12248. // New functions which don't exist yet can also be added.
  12249. initChatBoxes: function initChatBoxes() {
  12250. this.__super__.initChatBoxes.apply(this, arguments);
  12251. this.controlboxtoggle = new this.ControlBoxToggle();
  12252. },
  12253. initConnection: function initConnection() {
  12254. this.__super__.initConnection.apply(this, arguments);
  12255. if (this.connection) {
  12256. this.addControlBox();
  12257. }
  12258. },
  12259. _tearDown: function _tearDown() {
  12260. this.__super__._tearDown.apply(this, arguments);
  12261. if (this.rosterview) {
  12262. // Removes roster groups
  12263. this.rosterview.model.off().reset();
  12264. this.rosterview.each(function (groupview) {
  12265. groupview.removeAll();
  12266. groupview.remove();
  12267. });
  12268. this.rosterview.removeAll().remove();
  12269. }
  12270. },
  12271. clearSession: function clearSession() {
  12272. this.__super__.clearSession.apply(this, arguments);
  12273. var controlbox = this.chatboxes.get('controlbox');
  12274. if (controlbox && controlbox.collection && controlbox.collection.browserStorage) {
  12275. controlbox.save({ 'connected': false });
  12276. }
  12277. },
  12278. ChatBoxes: {
  12279. chatBoxMayBeShown: function chatBoxMayBeShown(chatbox) {
  12280. return this.__super__.chatBoxMayBeShown.apply(this, arguments) && chatbox.get('id') !== 'controlbox';
  12281. },
  12282. onChatBoxesFetched: function onChatBoxesFetched(collection, resp) {
  12283. var _converse = this.__super__._converse;
  12284. this.__super__.onChatBoxesFetched.apply(this, arguments);
  12285. if (!_.includes(_.map(collection, 'id'), 'controlbox')) {
  12286. _converse.addControlBox();
  12287. }
  12288. this.get('controlbox').save({ connected: true });
  12289. }
  12290. },
  12291. ChatBoxViews: {
  12292. onChatBoxAdded: function onChatBoxAdded(item) {
  12293. var _converse = this.__super__._converse;
  12294. if (item.get('box_id') === 'controlbox') {
  12295. var view = this.get(item.get('id'));
  12296. if (view) {
  12297. view.model = item;
  12298. view.initialize();
  12299. return view;
  12300. } else {
  12301. view = new _converse.ControlBoxView({ model: item });
  12302. return this.add(item.get('id'), view);
  12303. }
  12304. } else {
  12305. return this.__super__.onChatBoxAdded.apply(this, arguments);
  12306. }
  12307. },
  12308. closeAllChatBoxes: function closeAllChatBoxes() {
  12309. var _converse = this.__super__._converse;
  12310. this.each(function (view) {
  12311. if (view.model.get('id') === 'controlbox' && (_converse.disconnection_cause !== _converse.LOGOUT || _converse.show_controlbox_by_default)) {
  12312. return;
  12313. }
  12314. view.close();
  12315. });
  12316. return this;
  12317. },
  12318. getChatBoxWidth: function getChatBoxWidth(view) {
  12319. var _converse = this.__super__._converse;
  12320. var controlbox = this.get('controlbox');
  12321. if (view.model.get('id') === 'controlbox') {
  12322. /* We return the width of the controlbox or its toggle,
  12323. * depending on which is visible.
  12324. */
  12325. if (!controlbox || !controlbox.$el.is(':visible')) {
  12326. return _converse.controlboxtoggle.$el.outerWidth(true);
  12327. } else {
  12328. return controlbox.$el.outerWidth(true);
  12329. }
  12330. } else {
  12331. return this.__super__.getChatBoxWidth.apply(this, arguments);
  12332. }
  12333. }
  12334. },
  12335. ChatBox: {
  12336. initialize: function initialize() {
  12337. if (this.get('id') === 'controlbox') {
  12338. this.set({ 'time_opened': moment(0).valueOf() });
  12339. } else {
  12340. this.__super__.initialize.apply(this, arguments);
  12341. }
  12342. }
  12343. },
  12344. ChatBoxView: {
  12345. insertIntoDOM: function insertIntoDOM() {
  12346. var _converse = this.__super__._converse;
  12347. this.$el.insertAfter(_converse.chatboxviews.get("controlbox").$el);
  12348. return this;
  12349. }
  12350. }
  12351. },
  12352. initialize: function initialize() {
  12353. /* The initialize function gets called as soon as the plugin is
  12354. * loaded by converse.js's plugin machinery.
  12355. */
  12356. var _converse = this._converse,
  12357. __ = _converse.__;
  12358. _converse.api.settings.update({
  12359. allow_logout: true,
  12360. default_domain: undefined,
  12361. show_controlbox_by_default: false,
  12362. sticky_controlbox: false,
  12363. xhr_user_search: false,
  12364. xhr_user_search_url: ''
  12365. });
  12366. var LABEL_CONTACTS = __('Contacts');
  12367. _converse.addControlBox = function () {
  12368. return _converse.chatboxes.add({
  12369. id: 'controlbox',
  12370. box_id: 'controlbox',
  12371. type: 'controlbox',
  12372. closed: !_converse.show_controlbox_by_default
  12373. });
  12374. };
  12375. _converse.ControlBoxView = _converse.ChatBoxView.extend({
  12376. tagName: 'div',
  12377. className: 'chatbox',
  12378. id: 'controlbox',
  12379. events: {
  12380. 'click a.close-chatbox-button': 'close',
  12381. 'click ul#controlbox-tabs li a': 'switchTab'
  12382. },
  12383. initialize: function initialize() {
  12384. this.$el.insertAfter(_converse.controlboxtoggle.$el);
  12385. this.model.on('change:connected', this.onConnected, this);
  12386. this.model.on('destroy', this.hide, this);
  12387. this.model.on('hide', this.hide, this);
  12388. this.model.on('show', this.show, this);
  12389. this.model.on('change:closed', this.ensureClosedState, this);
  12390. this.render();
  12391. if (this.model.get('connected')) {
  12392. this.insertRoster();
  12393. }
  12394. },
  12395. render: function render() {
  12396. if (this.model.get('connected')) {
  12397. if (_.isUndefined(this.model.get('closed'))) {
  12398. this.model.set('closed', !_converse.show_controlbox_by_default);
  12399. }
  12400. }
  12401. if (!this.model.get('closed')) {
  12402. this.show();
  12403. } else {
  12404. this.hide();
  12405. }
  12406. this.el.innerHTML = tpl_controlbox(_.extend(this.model.toJSON(), {
  12407. 'sticky_controlbox': _converse.sticky_controlbox
  12408. }));
  12409. if (!_converse.connection.connected || !_converse.connection.authenticated || _converse.connection.disconnecting) {
  12410. this.renderLoginPanel();
  12411. } else if (this.model.get('connected') && (!this.contactspanel || !this.contactspanel.$el.is(':visible'))) {
  12412. this.renderContactsPanel();
  12413. }
  12414. return this;
  12415. },
  12416. onConnected: function onConnected() {
  12417. if (this.model.get('connected')) {
  12418. this.render().insertRoster();
  12419. this.model.save();
  12420. }
  12421. },
  12422. insertRoster: function insertRoster() {
  12423. /* Place the rosterview inside the "Contacts" panel.
  12424. */
  12425. this.contactspanel.$el.append(_converse.rosterview.$el);
  12426. return this;
  12427. },
  12428. renderLoginPanel: function renderLoginPanel() {
  12429. this.loginpanel = new _converse.LoginPanel({
  12430. '$parent': this.$el.find('.controlbox-panes'),
  12431. 'model': this
  12432. });
  12433. this.loginpanel.render();
  12434. return this;
  12435. },
  12436. renderContactsPanel: function renderContactsPanel() {
  12437. if (_.isUndefined(this.model.get('active-panel'))) {
  12438. this.model.save({ 'active-panel': USERS_PANEL_ID });
  12439. }
  12440. this.contactspanel = new _converse.ContactsPanel({
  12441. '$parent': this.$el.find('.controlbox-panes')
  12442. });
  12443. this.contactspanel.insertIntoDOM();
  12444. _converse.xmppstatusview = new _converse.XMPPStatusView({
  12445. 'model': _converse.xmppstatus
  12446. });
  12447. _converse.xmppstatusview.render();
  12448. },
  12449. close: function close(ev) {
  12450. if (ev && ev.preventDefault) {
  12451. ev.preventDefault();
  12452. }
  12453. if (_converse.sticky_controlbox) {
  12454. return;
  12455. }
  12456. if (_converse.connection.connected && !_converse.connection.disconnecting) {
  12457. this.model.save({ 'closed': true });
  12458. } else {
  12459. this.model.trigger('hide');
  12460. }
  12461. _converse.emit('controlBoxClosed', this);
  12462. return this;
  12463. },
  12464. ensureClosedState: function ensureClosedState() {
  12465. if (this.model.get('closed')) {
  12466. this.hide();
  12467. } else {
  12468. this.show();
  12469. }
  12470. },
  12471. hide: function hide(callback) {
  12472. if (_converse.sticky_controlbox) {
  12473. return;
  12474. }
  12475. this.$el.addClass('hidden');
  12476. utils.refreshWebkit();
  12477. _converse.emit('chatBoxClosed', this);
  12478. if (!_converse.connection.connected) {
  12479. _converse.controlboxtoggle.render();
  12480. }
  12481. _converse.controlboxtoggle.show(callback);
  12482. return this;
  12483. },
  12484. onControlBoxToggleHidden: function onControlBoxToggleHidden() {
  12485. var that = this;
  12486. utils.fadeIn(this.el, function () {
  12487. _converse.controlboxtoggle.updateOnlineCount();
  12488. utils.refreshWebkit();
  12489. that.model.set('closed', false);
  12490. _converse.emit('controlBoxOpened', that);
  12491. });
  12492. },
  12493. show: function show() {
  12494. _converse.controlboxtoggle.hide(this.onControlBoxToggleHidden.bind(this));
  12495. return this;
  12496. },
  12497. switchTab: function switchTab(ev) {
  12498. // TODO: automatically focus the relevant input
  12499. if (ev && ev.preventDefault) {
  12500. ev.preventDefault();
  12501. }
  12502. var $tab = $(ev.target),
  12503. $sibling = $tab.parent().siblings('li').children('a'),
  12504. $tab_panel = $($tab.attr('href'));
  12505. $($sibling.attr('href')).addClass('hidden');
  12506. $sibling.removeClass('current');
  12507. $tab.addClass('current');
  12508. $tab_panel.removeClass('hidden');
  12509. if (!_.isUndefined(_converse.chatboxes.browserStorage)) {
  12510. this.model.save({ 'active-panel': $tab.data('id') });
  12511. }
  12512. return this;
  12513. },
  12514. showHelpMessages: function showHelpMessages() {
  12515. /* Override showHelpMessages in ChatBoxView, for now do nothing.
  12516. *
  12517. * Parameters:
  12518. * (Array) msgs: Array of messages
  12519. */
  12520. return;
  12521. }
  12522. });
  12523. _converse.LoginPanel = Backbone.View.extend({
  12524. tagName: 'div',
  12525. id: "login-dialog",
  12526. className: 'controlbox-pane',
  12527. events: {
  12528. 'submit form#converse-login': 'authenticate'
  12529. },
  12530. initialize: function initialize(cfg) {
  12531. cfg.$parent.html(this.$el.html(tpl_login_panel({
  12532. 'ANONYMOUS': _converse.ANONYMOUS,
  12533. 'EXTERNAL': _converse.EXTERNAL,
  12534. 'LOGIN': _converse.LOGIN,
  12535. 'PREBIND': _converse.PREBIND,
  12536. 'auto_login': _converse.auto_login,
  12537. 'authentication': _converse.authentication,
  12538. 'label_username': __('XMPP Username:'),
  12539. 'label_password': __('Password:'),
  12540. 'label_anon_login': __('Click here to log in anonymously'),
  12541. 'label_login': __('Log In'),
  12542. 'placeholder_username': (_converse.locked_domain || _converse.default_domain) && __('Username') || __('user@server'),
  12543. 'placeholder_password': __('password')
  12544. })));
  12545. this.$tabs = cfg.$parent.parent().find('#controlbox-tabs');
  12546. },
  12547. render: function render() {
  12548. this.$tabs.append(tpl_login_tab({ label_sign_in: __('Sign in') }));
  12549. this.$el.find('input#jid').focus();
  12550. if (!this.$el.is(':visible')) {
  12551. this.$el.show();
  12552. }
  12553. return this;
  12554. },
  12555. authenticate: function authenticate(ev) {
  12556. if (ev && ev.preventDefault) {
  12557. ev.preventDefault();
  12558. }
  12559. var $form = $(ev.target);
  12560. if (_converse.authentication === _converse.ANONYMOUS) {
  12561. this.connect($form, _converse.jid, null);
  12562. return;
  12563. }
  12564. var $jid_input = $form.find('input[name=jid]');
  12565. var $pw_input = $form.find('input[name=password]');
  12566. var password = $pw_input.val();
  12567. var jid = $jid_input.val(),
  12568. errors = false;
  12569. if (!jid || _.filter(jid.split('@')).length < 2) {
  12570. errors = true;
  12571. $jid_input.addClass('error');
  12572. }
  12573. if (!password && _converse.authentication !== _converse.EXTERNAL) {
  12574. errors = true;
  12575. $pw_input.addClass('error');
  12576. }
  12577. if (errors) {
  12578. return;
  12579. }
  12580. if (_converse.locked_domain) {
  12581. jid = Strophe.escapeNode(jid) + '@' + _converse.locked_domain;
  12582. } else if (_converse.default_domain && !_.includes(jid, '@')) {
  12583. jid = jid + '@' + _converse.default_domain;
  12584. }
  12585. this.connect($form, jid, password);
  12586. return false;
  12587. },
  12588. connect: function connect($form, jid, password) {
  12589. var resource = void 0;
  12590. if ($form) {
  12591. $form.find('input[type=submit]').hide().after('<span class="spinner login-submit"/>');
  12592. }
  12593. if (jid) {
  12594. resource = Strophe.getResourceFromJid(jid);
  12595. if (!resource) {
  12596. jid = jid.toLowerCase() + _converse.generateResource();
  12597. } else {
  12598. jid = Strophe.getBareJidFromJid(jid).toLowerCase() + '/' + resource;
  12599. }
  12600. }
  12601. _converse.connection.reset();
  12602. _converse.connection.connect(jid, password, _converse.onConnectStatusChanged);
  12603. },
  12604. remove: function remove() {
  12605. this.$tabs.empty();
  12606. this.$el.parent().empty();
  12607. }
  12608. });
  12609. _converse.XMPPStatusView = Backbone.View.extend({
  12610. el: "form#set-xmpp-status",
  12611. events: {
  12612. "click a.choose-xmpp-status": "toggleOptions",
  12613. "click #fancy-xmpp-status-select a.change-xmpp-status-message": "renderStatusChangeForm",
  12614. "submit": "setStatusMessage",
  12615. "click .dropdown dd ul li a": "setStatus"
  12616. },
  12617. initialize: function initialize() {
  12618. this.model.on("change:status", this.updateStatusUI, this);
  12619. this.model.on("change:status_message", this.updateStatusUI, this);
  12620. this.model.on("update-status-ui", this.updateStatusUI, this);
  12621. },
  12622. render: function render() {
  12623. // Replace the default dropdown with something nicer
  12624. var $select = this.$el.find('select#select-xmpp-status');
  12625. var chat_status = this.model.get('status') || 'offline';
  12626. var options = $('option', $select);
  12627. var options_list = [];
  12628. this.$el.html(tpl_choose_status());
  12629. this.$el.find('#fancy-xmpp-status-select').html(tpl_chat_status({
  12630. 'status_message': this.model.get('status_message') || __("I am %1$s", this.getPrettyStatus(chat_status)),
  12631. 'chat_status': chat_status,
  12632. 'desc_custom_status': __('Click here to write a custom status message'),
  12633. 'desc_change_status': __('Click to change your chat status')
  12634. }));
  12635. // iterate through all the <option> elements and add option values
  12636. options.each(function () {
  12637. options_list.push(tpl_status_option({
  12638. 'value': $(this).val(),
  12639. 'text': this.text
  12640. }));
  12641. });
  12642. var $options_target = this.$el.find("#target dd ul").hide();
  12643. $options_target.append(options_list.join(''));
  12644. $select.remove();
  12645. return this;
  12646. },
  12647. toggleOptions: function toggleOptions(ev) {
  12648. ev.preventDefault();
  12649. utils.slideInAllElements(document.querySelectorAll('#conversejs .contact-form-container'));
  12650. $(ev.target).parent().parent().siblings('dd').find('ul').toggle('fast');
  12651. },
  12652. renderStatusChangeForm: function renderStatusChangeForm(ev) {
  12653. ev.preventDefault();
  12654. var status_message = _converse.xmppstatus.get('status_message') || '';
  12655. var input = tpl_change_status_message({
  12656. 'status_message': status_message,
  12657. 'label_custom_status': __('Custom status'),
  12658. 'label_save': __('Save')
  12659. });
  12660. var $xmppstatus = this.$el.find('.xmpp-status');
  12661. $xmppstatus.parent().addClass('no-border');
  12662. $xmppstatus.replaceWith(input);
  12663. this.$el.find('.custom-xmpp-status').focus().focus();
  12664. },
  12665. setStatusMessage: function setStatusMessage(ev) {
  12666. ev.preventDefault();
  12667. this.model.setStatusMessage($(ev.target).find('input').val());
  12668. },
  12669. setStatus: function setStatus(ev) {
  12670. ev.preventDefault();
  12671. var $el = $(ev.currentTarget),
  12672. value = $el.attr('data-value');
  12673. if (value === 'logout') {
  12674. this.$el.find(".dropdown dd ul").hide();
  12675. _converse.logOut();
  12676. } else {
  12677. this.model.setStatus(value);
  12678. this.$el.find(".dropdown dd ul").hide();
  12679. }
  12680. },
  12681. getPrettyStatus: function getPrettyStatus(stat) {
  12682. if (stat === 'chat') {
  12683. return __('online');
  12684. } else if (stat === 'dnd') {
  12685. return __('busy');
  12686. } else if (stat === 'xa') {
  12687. return __('away for long');
  12688. } else if (stat === 'away') {
  12689. return __('away');
  12690. } else if (stat === 'offline') {
  12691. return __('offline');
  12692. } else {
  12693. return __(stat) || __('online');
  12694. }
  12695. },
  12696. updateStatusUI: function updateStatusUI(model) {
  12697. var stat = model.get('status');
  12698. // For translators: the %1$s part gets replaced with the status
  12699. // Example, I am online
  12700. var status_message = model.get('status_message') || __("I am %1$s", this.getPrettyStatus(stat));
  12701. this.$el.find('#fancy-xmpp-status-select').removeClass('no-border').html(tpl_chat_status({
  12702. 'chat_status': stat,
  12703. 'status_message': status_message,
  12704. 'desc_custom_status': __('Click here to write a custom status message'),
  12705. 'desc_change_status': __('Click to change your chat status')
  12706. }));
  12707. }
  12708. });
  12709. _converse.ContactsPanel = Backbone.View.extend({
  12710. tagName: 'div',
  12711. className: 'controlbox-pane',
  12712. id: 'users',
  12713. events: {
  12714. 'click a.toggle-xmpp-contact-form': 'toggleContactForm',
  12715. 'submit form.add-xmpp-contact': 'addContactFromForm',
  12716. 'submit form.search-xmpp-contact': 'searchContacts',
  12717. 'click a.subscribe-to-user': 'addContactFromList'
  12718. },
  12719. initialize: function initialize(cfg) {
  12720. this.parent_el = cfg.$parent[0];
  12721. this.tab_el = document.createElement('li');
  12722. _converse.chatboxes.on('change:num_unread', this.renderTab, this);
  12723. _converse.chatboxes.on('add', _.debounce(this.renderTab, 100), this);
  12724. },
  12725. render: function render() {
  12726. this.renderTab();
  12727. var widgets = tpl_contacts_panel({
  12728. label_online: __('Online'),
  12729. label_busy: __('Busy'),
  12730. label_away: __('Away'),
  12731. label_offline: __('Offline'),
  12732. label_logout: __('Log out'),
  12733. include_offline_state: _converse.include_offline_state,
  12734. allow_logout: _converse.allow_logout
  12735. });
  12736. if (_converse.allow_contact_requests) {
  12737. widgets += tpl_add_contact_dropdown({
  12738. label_click_to_chat: __('Click to add new chat contacts'),
  12739. label_add_contact: __('Add a contact')
  12740. });
  12741. }
  12742. this.el.innerHTML = widgets;
  12743. var controlbox = _converse.chatboxes.get('controlbox');
  12744. if (controlbox.get('active-panel') !== USERS_PANEL_ID) {
  12745. this.el.classList.add('hidden');
  12746. }
  12747. return this;
  12748. },
  12749. renderTab: function renderTab() {
  12750. var controlbox = _converse.chatboxes.get('controlbox');
  12751. var chats = fp.filter(_.partial(utils.isOfType, CHATBOX_TYPE), _converse.chatboxes.models);
  12752. this.tab_el.innerHTML = tpl_contacts_tab({
  12753. 'label_contacts': LABEL_CONTACTS,
  12754. 'is_current': controlbox.get('active-panel') === USERS_PANEL_ID,
  12755. 'num_unread': fp.sum(fp.map(fp.curry(utils.getAttribute)('num_unread'), chats))
  12756. });
  12757. },
  12758. insertIntoDOM: function insertIntoDOM() {
  12759. this.parent_el.appendChild(this.render().el);
  12760. this.tabs = this.parent_el.parentNode.querySelector('#controlbox-tabs');
  12761. this.tabs.appendChild(this.tab_el);
  12762. return this;
  12763. },
  12764. generateAddContactHTML: function generateAddContactHTML() {
  12765. var settings = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  12766. if (_converse.xhr_user_search) {
  12767. return tpl_search_contact({
  12768. label_contact_name: __('Contact name'),
  12769. label_search: __('Search')
  12770. });
  12771. } else {
  12772. return tpl_add_contact_form(_.assign({
  12773. error_message: null,
  12774. label_contact_username: __('e.g. user@example.org'),
  12775. label_add: __('Add'),
  12776. value: ''
  12777. }, settings));
  12778. }
  12779. },
  12780. toggleContactForm: function toggleContactForm(ev) {
  12781. ev.preventDefault();
  12782. this.el.querySelector('.search-xmpp div').innerHTML = this.generateAddContactHTML();
  12783. var dropdown = this.el.querySelector('.contact-form-container');
  12784. utils.slideToggleElement(dropdown).then(function () {
  12785. if ($(dropdown).is(':visible')) {
  12786. $(dropdown).find('input.username').focus();
  12787. }
  12788. });
  12789. },
  12790. searchContacts: function searchContacts(ev) {
  12791. ev.preventDefault();
  12792. $.getJSON(_converse.xhr_user_search_url + "?q=" + $(ev.target).find('input.username').val(), function (data) {
  12793. var $ul = $('.search-xmpp ul');
  12794. $ul.find('li.found-user').remove();
  12795. $ul.find('li.chat-info').remove();
  12796. if (!data.length) {
  12797. $ul.append("<li class=\"chat-info\">" + __('No users found') + "</li>");
  12798. }
  12799. $(data).each(function (idx, obj) {
  12800. $ul.append($('<li class="found-user"></li>').append($("<a class=\"subscribe-to-user\" href=\"#\" title=\"" + __('Click to add as a chat contact') + "\"></a>").attr('data-recipient', Strophe.getNodeFromJid(obj.id) + "@" + Strophe.getDomainFromJid(obj.id)).text(obj.fullname)));
  12801. });
  12802. });
  12803. },
  12804. addContactFromForm: function addContactFromForm(ev) {
  12805. ev.preventDefault();
  12806. var $input = $(ev.target).find('input');
  12807. var jid = $input.val();
  12808. if (!jid || _.filter(jid.split('@')).length < 2) {
  12809. this.el.querySelector('.search-xmpp div').innerHTML = this.generateAddContactHTML({
  12810. error_message: __('Please enter a valid XMPP username'),
  12811. label_contact_username: __('e.g. user@example.org'),
  12812. label_add: __('Add'),
  12813. value: jid
  12814. });
  12815. return;
  12816. }
  12817. _converse.roster.addAndSubscribe(jid);
  12818. utils.slideIn(this.el.querySelector('.contact-form-container'));
  12819. },
  12820. addContactFromList: function addContactFromList(ev) {
  12821. ev.preventDefault();
  12822. var $target = $(ev.target),
  12823. jid = $target.attr('data-recipient'),
  12824. name = $target.text();
  12825. _converse.roster.addAndSubscribe(jid, name);
  12826. $target.parent().remove();
  12827. utils.slideIn(this.el.querySelector('.contact-form-container'));
  12828. }
  12829. });
  12830. _converse.ControlBoxToggle = Backbone.View.extend({
  12831. tagName: 'a',
  12832. className: 'toggle-controlbox hidden',
  12833. id: 'toggle-controlbox',
  12834. events: {
  12835. 'click': 'onClick'
  12836. },
  12837. attributes: {
  12838. 'href': "#"
  12839. },
  12840. initialize: function initialize() {
  12841. _converse.chatboxviews.$el.prepend(this.render());
  12842. this.updateOnlineCount();
  12843. var that = this;
  12844. _converse.on('initialized', function () {
  12845. _converse.roster.on("add", that.updateOnlineCount, that);
  12846. _converse.roster.on('change', that.updateOnlineCount, that);
  12847. _converse.roster.on("destroy", that.updateOnlineCount, that);
  12848. _converse.roster.on("remove", that.updateOnlineCount, that);
  12849. });
  12850. },
  12851. render: function render() {
  12852. // We let the render method of ControlBoxView decide whether
  12853. // the ControlBox or the Toggle must be shown. This prevents
  12854. // artifacts (i.e. on page load the toggle is shown only to then
  12855. // seconds later be hidden in favor of the control box).
  12856. return this.$el.html(tpl_controlbox_toggle({
  12857. 'label_toggle': __('Toggle chat')
  12858. }));
  12859. },
  12860. updateOnlineCount: _.debounce(function () {
  12861. if (_.isUndefined(_converse.roster)) {
  12862. return;
  12863. }
  12864. var $count = this.$('#online-count');
  12865. $count.text("(" + _converse.roster.getNumOnlineContacts() + ")");
  12866. if (!$count.is(':visible')) {
  12867. $count.show();
  12868. }
  12869. }, _converse.animate ? 100 : 0),
  12870. hide: function hide(callback) {
  12871. this.el.classList.add('hidden');
  12872. callback();
  12873. },
  12874. show: function show(callback) {
  12875. utils.fadeIn(this.el, callback);
  12876. },
  12877. showControlBox: function showControlBox() {
  12878. var controlbox = _converse.chatboxes.get('controlbox');
  12879. if (!controlbox) {
  12880. controlbox = _converse.addControlBox();
  12881. }
  12882. if (_converse.connection.connected) {
  12883. controlbox.save({ closed: false });
  12884. } else {
  12885. controlbox.trigger('show');
  12886. }
  12887. },
  12888. onClick: function onClick(e) {
  12889. e.preventDefault();
  12890. if ($("div#controlbox").is(':visible')) {
  12891. var controlbox = _converse.chatboxes.get('controlbox');
  12892. if (_converse.connection.connected) {
  12893. controlbox.save({ closed: true });
  12894. } else {
  12895. controlbox.trigger('hide');
  12896. }
  12897. } else {
  12898. this.showControlBox();
  12899. }
  12900. }
  12901. });
  12902. var disconnect = function disconnect() {
  12903. /* Upon disconnection, set connected to `false`, so that if
  12904. * we reconnect,
  12905. * "onConnected" will be called, to fetch the roster again and
  12906. * to send out a presence stanza.
  12907. */
  12908. var view = _converse.chatboxviews.get('controlbox');
  12909. view.model.set({ connected: false });
  12910. view.$('#controlbox-tabs').empty();
  12911. view.renderLoginPanel();
  12912. };
  12913. _converse.on('disconnected', disconnect);
  12914. var afterReconnected = function afterReconnected() {
  12915. /* After reconnection makes sure the controlbox's is aware.
  12916. */
  12917. var view = _converse.chatboxviews.get('controlbox');
  12918. if (view.model.get('connected')) {
  12919. _converse.chatboxviews.get("controlbox").onConnected();
  12920. } else {
  12921. view.model.set({ connected: true });
  12922. }
  12923. };
  12924. _converse.on('reconnected', afterReconnected);
  12925. }
  12926. });
  12927. });
  12928. //# sourceMappingURL=converse-controlbox.js.map;
  12929. define('tpl!chatarea', ['lodash'], function(_) {return function(obj) {
  12930. obj || (obj = {});
  12931. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  12932. function print() { __p += __j.call(arguments, '') }
  12933. with (obj) {
  12934. __p += '<div class="chat-area">\n <div class="chat-content ';
  12935. if (show_send_button) { ;
  12936. __p += 'chat-content-sendbutton';
  12937. } ;
  12938. __p += '"></div>\n <div class="new-msgs-indicator hidden">▼ ' +
  12939. __e( unread_msgs ) +
  12940. ' ▼</div>\n <form class="sendXMPPMessage">\n ';
  12941. if (show_toolbar) { ;
  12942. __p += '\n <ul class="chat-toolbar no-text-select"></ul>\n ';
  12943. } ;
  12944. __p += '\n <textarea type="text" class="chat-textarea ';
  12945. if (show_send_button) { ;
  12946. __p += 'chat-textarea-send-button';
  12947. } ;
  12948. __p += '"\n placeholder="' +
  12949. __e(label_message) +
  12950. '"/>\n ';
  12951. if (show_send_button) { ;
  12952. __p += '\n <button type="submit" class="pure-button send-button">' +
  12953. __e( label_send ) +
  12954. '</button>\n ';
  12955. } ;
  12956. __p += '\n </form>\n</div>\n';
  12957. }
  12958. return __p
  12959. };});
  12960. define('tpl!chatroom', ['lodash'], function(_) {return function(obj) {
  12961. obj || (obj = {});
  12962. var __t, __p = '';
  12963. with (obj) {
  12964. __p += '<div class="flyout box-flyout">\n <div class="chat-head chat-head-chatroom"></div>\n <div class="chat-body chatroom-body"><span class="spinner centered"/></div>\n</div>\n';
  12965. }
  12966. return __p
  12967. };});
  12968. define('tpl!chatroom_disconnect', ['lodash'], function(_) {return function(obj) {
  12969. obj || (obj = {});
  12970. var __t, __p = '', __e = _.escape;
  12971. with (obj) {
  12972. __p += '<p class="disconnect-msg">' +
  12973. __e(disconnect_message) +
  12974. '</p>\n';
  12975. }
  12976. return __p
  12977. };});
  12978. define('tpl!chatroom_features', ['lodash'], function(_) {return function(obj) {
  12979. obj || (obj = {});
  12980. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  12981. function print() { __p += __j.call(arguments, '') }
  12982. with (obj) {
  12983. if (has_features) { ;
  12984. __p += '\n<p class="occupants-heading">' +
  12985. __e(label_features) +
  12986. '</p>\n';
  12987. } ;
  12988. __p += '\n<ul class="features-list">\n';
  12989. if (passwordprotected) { ;
  12990. __p += '\n<li class="feature" title="' +
  12991. __e( tt_passwordprotected ) +
  12992. '"><span class="icon-lock-2"></span>' +
  12993. __e( label_passwordprotected ) +
  12994. '</li>\n';
  12995. } ;
  12996. __p += '\n';
  12997. if (unsecured) { ;
  12998. __p += '\n<li class="feature" title="' +
  12999. __e( tt_unsecured ) +
  13000. '"><span class="icon-unlocked"></span>' +
  13001. __e( label_unsecured ) +
  13002. '</li>\n';
  13003. } ;
  13004. __p += '\n';
  13005. if (hidden) { ;
  13006. __p += '\n<li class="feature" title="' +
  13007. __e( tt_hidden ) +
  13008. '"><span class="icon-eye-blocked"></span>' +
  13009. __e( label_hidden ) +
  13010. '</li>\n';
  13011. } ;
  13012. __p += '\n';
  13013. if (public) { ;
  13014. __p += '\n<li class="feature" title="' +
  13015. __e( tt_public ) +
  13016. '"><span class="icon-eye"></span>' +
  13017. __e( label_public ) +
  13018. '</li>\n';
  13019. } ;
  13020. __p += '\n';
  13021. if (membersonly) { ;
  13022. __p += '\n<li class="feature" title="' +
  13023. __e( tt_membersonly ) +
  13024. '"><span class="icon-address-book"></span>' +
  13025. __e( label_membersonly ) +
  13026. '</li>\n';
  13027. } ;
  13028. __p += '\n';
  13029. if (open) { ;
  13030. __p += '\n<li class="feature" title="' +
  13031. __e( tt_open ) +
  13032. '"><span class="icon-globe"></span>' +
  13033. __e( label_open ) +
  13034. '</li>\n';
  13035. } ;
  13036. __p += '\n';
  13037. if (persistent) { ;
  13038. __p += '\n<li class="feature" title="' +
  13039. __e( tt_persistent ) +
  13040. '"><span class="icon-save"></span>' +
  13041. __e( label_persistent ) +
  13042. '</li>\n';
  13043. } ;
  13044. __p += '\n';
  13045. if (temporary) { ;
  13046. __p += '\n<li class="feature" title="' +
  13047. __e( tt_temporary ) +
  13048. '"><span class="icon-snowflake"></span>' +
  13049. __e( label_temporary ) +
  13050. '</li>\n';
  13051. } ;
  13052. __p += '\n';
  13053. if (nonanonymous) { ;
  13054. __p += '\n<li class="feature" title="' +
  13055. __e( tt_nonanonymous ) +
  13056. '"><span class="icon-idcard-dark"></span>' +
  13057. __e( label_nonanonymous ) +
  13058. '</li>\n';
  13059. } ;
  13060. __p += '\n';
  13061. if (semianonymous) { ;
  13062. __p += '\n<li class="feature" title="' +
  13063. __e( tt_semianonymous ) +
  13064. '"><span class="icon-info"></span>' +
  13065. __e( label_semianonymous ) +
  13066. '</li>\n';
  13067. } ;
  13068. __p += '\n';
  13069. if (moderated) { ;
  13070. __p += '\n<li class="feature" title="' +
  13071. __e( tt_moderated ) +
  13072. '"><span class="icon-legal"></span>' +
  13073. __e( label_moderated ) +
  13074. '</li>\n';
  13075. } ;
  13076. __p += '\n';
  13077. if (unmoderated) { ;
  13078. __p += '\n<li class="feature" title="' +
  13079. __e( tt_unmoderated ) +
  13080. '"><span class="icon-info"></span>' +
  13081. __e( label_unmoderated ) +
  13082. '</li>\n';
  13083. } ;
  13084. __p += '\n';
  13085. if (mam_enabled) { ;
  13086. __p += '\n<li class="feature" title="' +
  13087. __e( tt_mam_enabled ) +
  13088. '"><span class="icon-database"></span>' +
  13089. __e( label_mam_enabled ) +
  13090. '</li>\n';
  13091. } ;
  13092. __p += '\n</ul>\n';
  13093. }
  13094. return __p
  13095. };});
  13096. define('tpl!chatroom_form', ['lodash'], function(_) {return function(obj) {
  13097. obj || (obj = {});
  13098. var __t, __p = '';
  13099. with (obj) {
  13100. __p += '<div class="chatroom-form-container">\n <form class="pure-form pure-form-stacked converse-form chatroom-form">\n <fieldset>\n <span class="spinner centered"/>\n </fieldset>\n </form>\n</div>\n';
  13101. }
  13102. return __p
  13103. };});
  13104. define('tpl!chatroom_head', ['lodash'], function(_) {return function(obj) {
  13105. obj || (obj = {});
  13106. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13107. function print() { __p += __j.call(arguments, '') }
  13108. with (obj) {
  13109. __p += '<a class="chatbox-btn close-chatbox-button icon-close" title="' +
  13110. __e(info_close) +
  13111. '"></a>\n';
  13112. if (affiliation == 'owner') { ;
  13113. __p += '\n <a class="chatbox-btn configure-chatroom-button icon-wrench" title="' +
  13114. __e(info_configure) +
  13115. ' "></a>\n';
  13116. } ;
  13117. __p += '\n<div class="chat-title" title="' +
  13118. __e(jid) +
  13119. '">\n ';
  13120. if (name && name !== Strophe.getNodeFromJid(jid)) { ;
  13121. __p += '\n <span class="chatroom-name">' +
  13122. __e( name ) +
  13123. '</span>\n ';
  13124. } else { ;
  13125. __p += '\n <span class="chatroom-name">' +
  13126. __e( Strophe.getNodeFromJid(jid) ) +
  13127. '</span>@' +
  13128. __e( Strophe.getDomainFromJid(jid) ) +
  13129. '\n ';
  13130. } ;
  13131. __p += '\n <p class="chatroom-description">' +
  13132. __e( description ) +
  13133. '<p/>\n</div>\n';
  13134. }
  13135. return __p
  13136. };});
  13137. define('tpl!chatroom_invite', ['lodash'], function(_) {return function(obj) {
  13138. obj || (obj = {});
  13139. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13140. function print() { __p += __j.call(arguments, '') }
  13141. with (obj) {
  13142. __p += '<form class="pure-form room-invite">\n ';
  13143. if (error_message) { ;
  13144. __p += '\n <span class="pure-form-message error">' +
  13145. __e(error_message) +
  13146. '</span>\n ';
  13147. } ;
  13148. __p += '\n <input class="invited-contact" placeholder="' +
  13149. __e(label_invitation) +
  13150. '" type="text"/>\n</form>\n';
  13151. }
  13152. return __p
  13153. };});
  13154. define('tpl!chatroom_nickname_form', ['lodash'], function(_) {return function(obj) {
  13155. obj || (obj = {});
  13156. var __t, __p = '', __e = _.escape;
  13157. with (obj) {
  13158. __p += '<div class="chatroom-form-container">\n <form class="pure-form converse-form chatroom-form converse-centered-form">\n <fieldset>\n <label>' +
  13159. __e(heading) +
  13160. '</label>\n <p class="validation-message">' +
  13161. __e(validation_message) +
  13162. '</p>\n <input type="text" required="required" name="nick" class="new-chatroom-nick" placeholder="' +
  13163. __e(label_nickname) +
  13164. '"/>\n </fieldset>\n <fieldset>\n <input type="submit" class="pure-button button-primary" name="join" value="' +
  13165. __e(label_join) +
  13166. '"/>\n </fieldset>\n </form>\n</div>\n';
  13167. }
  13168. return __p
  13169. };});
  13170. define('tpl!chatroom_password_form', ['lodash'], function(_) {return function(obj) {
  13171. obj || (obj = {});
  13172. var __t, __p = '', __e = _.escape;
  13173. with (obj) {
  13174. __p += '<div class="chatroom-form-container">\n <form class="pure-form converse-form chatroom-form">\n <fieldset>\n <legend>' +
  13175. __e(heading) +
  13176. '</legend>\n <label>' +
  13177. __e(label_password) +
  13178. '</label>\n <input type="password" name="password"/>\n </fieldset>\n <fieldset>\n <input class="pure-button button-primary" type="submit" value="' +
  13179. __e(label_submit) +
  13180. '"/>\n </fieldset>\n </form>\n</div>\n';
  13181. }
  13182. return __p
  13183. };});
  13184. define('tpl!chatroom_sidebar', ['lodash'], function(_) {return function(obj) {
  13185. obj || (obj = {});
  13186. var __t, __p = '', __e = _.escape;
  13187. with (obj) {
  13188. __p += '<!-- <div class="occupants"> -->\n<p class="occupants-heading">' +
  13189. __e(label_occupants) +
  13190. '</p>\n<ul class="occupant-list"></ul>\n<div class="chatroom-features"></div>\n<!-- </div> -->\n';
  13191. }
  13192. return __p
  13193. };});
  13194. define('tpl!chatroom_toolbar', ['lodash'], function(_) {return function(obj) {
  13195. obj || (obj = {});
  13196. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13197. function print() { __p += __j.call(arguments, '') }
  13198. with (obj) {
  13199. if (use_emoji) { ;
  13200. __p += '\n <li class="toggle-smiley icon-happy" title="' +
  13201. __e(label_insert_smiley) +
  13202. '">\n <ul class="emoji-picker"></ul>\n </li>\n';
  13203. } ;
  13204. __p += '\n';
  13205. if (show_call_button) { ;
  13206. __p += '\n<li class="toggle-call"><a class="icon-phone" title="' +
  13207. __e(label_start_call) +
  13208. '"></a></li>\n';
  13209. } ;
  13210. __p += '\n';
  13211. if (show_occupants_toggle) { ;
  13212. __p += '\n<li class="toggle-occupants"><a class="icon-hide-users" title="' +
  13213. __e(label_hide_occupants) +
  13214. '"></a></li>\n';
  13215. } ;
  13216. __p += '\n';
  13217. if (show_clear_button) { ;
  13218. __p += '\n<li class="toggle-clear"><a class="icon-trash" title="' +
  13219. __e(label_clear) +
  13220. '"></a></li>\n';
  13221. } ;
  13222. __p += '\n\n';
  13223. }
  13224. return __p
  13225. };});
  13226. define('tpl!chatrooms_tab', ['lodash'], function(_) {return function(obj) {
  13227. obj || (obj = {});
  13228. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13229. function print() { __p += __j.call(arguments, '') }
  13230. with (obj) {
  13231. __p += '<a class="s rooms-tab\n ';
  13232. if (is_current) { ;
  13233. __p += ' current ';
  13234. } ;
  13235. __p += '\n ';
  13236. if (num_unread) { ;
  13237. __p += ' unread-msgs ';
  13238. } ;
  13239. __p += '"\n data-id="chatrooms" href="#chatrooms">\n ' +
  13240. ((__t = (label_rooms)) == null ? '' : __t) +
  13241. '\n ';
  13242. if (num_unread) { ;
  13243. __p += '\n <span class="msgs-indicator">' +
  13244. __e( num_unread ) +
  13245. '</span>\n ';
  13246. } ;
  13247. __p += '\n</a>\n';
  13248. }
  13249. return __p
  13250. };});
  13251. define('tpl!info', ['lodash'], function(_) {return function(obj) {
  13252. obj || (obj = {});
  13253. var __t, __p = '', __e = _.escape;
  13254. with (obj) {
  13255. __p += '<div class="chat-info">' +
  13256. __e(message) +
  13257. '</div>\n';
  13258. }
  13259. return __p
  13260. };});
  13261. define('tpl!occupant', ['lodash'], function(_) {return function(obj) {
  13262. obj || (obj = {});
  13263. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13264. function print() { __p += __j.call(arguments, '') }
  13265. with (obj) {
  13266. __p += '<li class="' +
  13267. __e( role ) +
  13268. ' occupant" id="' +
  13269. __e( id ) +
  13270. '"\n ';
  13271. if (role === "moderator") { ;
  13272. __p += '\n title="' +
  13273. __e( jid ) +
  13274. ' ' +
  13275. __e( desc_moderator ) +
  13276. ' ' +
  13277. __e( hint_occupant ) +
  13278. '"\n ';
  13279. } ;
  13280. __p += '\n ';
  13281. if (role === "occupant") { ;
  13282. __p += '\n title="' +
  13283. __e( jid ) +
  13284. ' ' +
  13285. __e( desc_occupant ) +
  13286. ' ' +
  13287. __e( hint_occupant ) +
  13288. '"\n ';
  13289. } ;
  13290. __p += '\n ';
  13291. if (role === "visitor") { ;
  13292. __p += '\n title="' +
  13293. __e( jid ) +
  13294. ' ' +
  13295. __e( desc_visitor ) +
  13296. ' ' +
  13297. __e( hint_occupant ) +
  13298. '"\n ';
  13299. } ;
  13300. __p += '\n ';
  13301. if (!_.includes(["visitor", "occupant", "moderator"], role)) { ;
  13302. __p += '\n title="' +
  13303. __e( jid ) +
  13304. ' ' +
  13305. __e( hint_occupant ) +
  13306. '"\n ';
  13307. } ;
  13308. __p += '><div class="occupant-status occupant-' +
  13309. __e(show) +
  13310. ' circle" title="' +
  13311. __e(hint_show) +
  13312. '"></div>' +
  13313. __e(nick) +
  13314. '</li>\n';
  13315. }
  13316. return __p
  13317. };});
  13318. define('tpl!room_description', ['lodash'], function(_) {return function(obj) {
  13319. obj || (obj = {});
  13320. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  13321. function print() { __p += __j.call(arguments, '') }
  13322. with (obj) {
  13323. __p += '<!-- FIXME: check markup in mockup -->\n<div class="room-info">\n<p class="room-info"><strong>' +
  13324. __e(label_jid) +
  13325. '</strong> ' +
  13326. __e(jid) +
  13327. '</p>\n<p class="room-info"><strong>' +
  13328. __e(label_desc) +
  13329. '</strong> ' +
  13330. __e(desc) +
  13331. '</p>\n<p class="room-info"><strong>' +
  13332. __e(label_occ) +
  13333. '</strong> ' +
  13334. __e(occ) +
  13335. '</p>\n<p class="room-info"><strong>' +
  13336. __e(label_features) +
  13337. '</strong>\n <ul>\n ';
  13338. if (passwordprotected) { ;
  13339. __p += '\n <li class="room-info locked">' +
  13340. __e(label_requires_auth) +
  13341. '</li>\n ';
  13342. } ;
  13343. __p += '\n ';
  13344. if (hidden) { ;
  13345. __p += '\n <li class="room-info">' +
  13346. __e(label_hidden) +
  13347. '</li>\n ';
  13348. } ;
  13349. __p += '\n ';
  13350. if (membersonly) { ;
  13351. __p += '\n <li class="room-info">' +
  13352. __e(label_requires_invite) +
  13353. '</li>\n ';
  13354. } ;
  13355. __p += '\n ';
  13356. if (moderated) { ;
  13357. __p += '\n <li class="room-info">' +
  13358. __e(label_moderated) +
  13359. '</li>\n ';
  13360. } ;
  13361. __p += '\n ';
  13362. if (nonanonymous) { ;
  13363. __p += '\n <li class="room-info">' +
  13364. __e(label_non_anon) +
  13365. '</li>\n ';
  13366. } ;
  13367. __p += '\n ';
  13368. if (open) { ;
  13369. __p += '\n <li class="room-info">' +
  13370. __e(label_open_room) +
  13371. '</li>\n ';
  13372. } ;
  13373. __p += '\n ';
  13374. if (persistent) { ;
  13375. __p += '\n <li class="room-info">' +
  13376. __e(label_permanent_room) +
  13377. '</li>\n ';
  13378. } ;
  13379. __p += '\n ';
  13380. if (publicroom) { ;
  13381. __p += '\n <li class="room-info">' +
  13382. __e(label_public) +
  13383. '</li>\n ';
  13384. } ;
  13385. __p += '\n ';
  13386. if (semianonymous) { ;
  13387. __p += '\n <li class="room-info">' +
  13388. __e(label_semi_anon) +
  13389. '</li>\n ';
  13390. } ;
  13391. __p += '\n ';
  13392. if (temporary) { ;
  13393. __p += '\n <li class="room-info">' +
  13394. __e(label_temp_room) +
  13395. '</li>\n ';
  13396. } ;
  13397. __p += '\n ';
  13398. if (unmoderated) { ;
  13399. __p += '\n <li class="room-info">' +
  13400. __e(label_unmoderated) +
  13401. '</li>\n ';
  13402. } ;
  13403. __p += '\n </ul>\n</p>\n</div>\n';
  13404. }
  13405. return __p
  13406. };});
  13407. define('tpl!room_item', ['lodash'], function(_) {return function(obj) {
  13408. obj || (obj = {});
  13409. var __t, __p = '', __e = _.escape;
  13410. with (obj) {
  13411. __p += '<dd class="available-chatroom">\n<a class="open-room available-room"\n data-room-jid="' +
  13412. __e(jid) +
  13413. '"\n title="' +
  13414. __e(open_title) +
  13415. '"\n href="#">' +
  13416. __e(name) +
  13417. '</a>\n<a class="right room-info icon-room-info"\n data-room-jid="' +
  13418. __e(jid) +
  13419. '"\n title="' +
  13420. __e(info_title) +
  13421. '" href="#">&nbsp;</a>\n</dd>\n';
  13422. }
  13423. return __p
  13424. };});
  13425. define('tpl!room_panel', ['lodash'], function(_) {return function(obj) {
  13426. obj || (obj = {});
  13427. var __t, __p = '', __j = Array.prototype.join;
  13428. function print() { __p += __j.call(arguments, '') }
  13429. with (obj) {
  13430. __p += '<form class="pure-form pure-form-stacked converse-form add-chatroom" action="" method="post">\n <fieldset>\n <label>' +
  13431. ((__t = (label_room_name)) == null ? '' : __t) +
  13432. '</label>\n <input type="text" name="chatroom" class="new-chatroom-name" placeholder="' +
  13433. ((__t = (label_room_name)) == null ? '' : __t) +
  13434. '"/>\n ';
  13435. if (server_input_type != 'hidden') { ;
  13436. __p += '\n <label' +
  13437. ((__t = (server_label_global_attr)) == null ? '' : __t) +
  13438. '>' +
  13439. ((__t = (label_server)) == null ? '' : __t) +
  13440. '</label>\n ';
  13441. } ;
  13442. __p += '\n <input type="' +
  13443. ((__t = (server_input_type)) == null ? '' : __t) +
  13444. '" name="server" class="new-chatroom-server" placeholder="' +
  13445. ((__t = (label_server)) == null ? '' : __t) +
  13446. '"/>\n <input type="submit" class="pure-button button-primary" name="join" value="' +
  13447. ((__t = (label_join)) == null ? '' : __t) +
  13448. '"/>\n <input type="button" class="pure-button button-secondary" name="show" id="show-rooms" value="' +
  13449. ((__t = (label_show_rooms)) == null ? '' : __t) +
  13450. '"/>\n </fieldset>\n</form>\n<div class="rooms-list-container">\n <dl id="available-chatrooms" class="rooms-list"></dl>\n</div>\n';
  13451. }
  13452. return __p
  13453. };});
  13454. // Converse.js (A browser based XMPP chat client)
  13455. // http://conversejs.org
  13456. //
  13457. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  13458. // Licensed under the Mozilla Public License (MPLv2)
  13459. //
  13460. /* This is a Converse.js plugin which add support for XEP-0030: Service Discovery */
  13461. /*global Backbone, define, window, document */
  13462. (function (root, factory) {
  13463. define('converse-disco',["converse-core", "sizzle", "strophe.disco"], factory);
  13464. }(this, function (converse, sizzle) {
  13465. const { Backbone, Promise, Strophe, b64_sha1, _ } = converse.env;
  13466. converse.plugins.add('converse-disco', {
  13467. initialize () {
  13468. /* The initialize function gets called as soon as the plugin is
  13469. * loaded by converse.js's plugin machinery.
  13470. */
  13471. const { _converse } = this;
  13472. function onDiscoItems (stanza) {
  13473. _.each(stanza.querySelectorAll('query item'), (item) => {
  13474. if (item.getAttribute("node")) {
  13475. // XXX: ignore nodes for now.
  13476. // See: https://xmpp.org/extensions/xep-0030.html#items-nodes
  13477. return;
  13478. }
  13479. const jid = item.getAttribute('jid');
  13480. const entities = _converse.disco_entities;
  13481. if (_.isUndefined(entities.get(jid))) {
  13482. entities.create({'jid': jid});
  13483. }
  13484. });
  13485. }
  13486. // Promises exposed by this plugin
  13487. _converse.api.promises.add('discoInitialized');
  13488. _converse.DiscoEntity = Backbone.Model.extend({
  13489. /* A Disco Entity is a JID addressable entity that can be queried
  13490. * for features.
  13491. *
  13492. * See XEP-0030: https://xmpp.org/extensions/xep-0030.html
  13493. */
  13494. idAttribute: 'jid',
  13495. initialize () {
  13496. this.features = new Backbone.Collection();
  13497. this.features.browserStorage = new Backbone.BrowserStorage[_converse.storage](
  13498. b64_sha1(`converse.features-${this.get('jid')}`)
  13499. );
  13500. this.features.on('add', this.onFeatureAdded);
  13501. this.identities = new Backbone.Collection();
  13502. this.identities.browserStorage = new Backbone.BrowserStorage[_converse.storage](
  13503. b64_sha1(`converse.identities-${this.get('jid')}`)
  13504. );
  13505. this.fetchFeatures();
  13506. },
  13507. onFeatureAdded (feature) {
  13508. _converse.emit('serviceDiscovered', feature);
  13509. },
  13510. fetchFeatures () {
  13511. if (this.features.browserStorage.records.length === 0) {
  13512. this.queryInfo();
  13513. } else {
  13514. this.features.fetch({add: true});
  13515. this.identities.fetch({add: true});
  13516. }
  13517. },
  13518. queryInfo () {
  13519. _converse.connection.disco.info(this.get('jid'), null, this.onInfo.bind(this));
  13520. },
  13521. queryForItems () {
  13522. if (_.isEmpty(this.identities.where({'category': 'server'}))) {
  13523. // Don't fetch features and items if this is not a
  13524. // server or a conference component.
  13525. return;
  13526. }
  13527. _converse.connection.disco.items(this.get('jid'), null, onDiscoItems);
  13528. },
  13529. onInfo (stanza) {
  13530. _.forEach(stanza.querySelectorAll('identity'), (identity) => {
  13531. this.identities.create({
  13532. 'category': identity.getAttribute('category'),
  13533. 'type': stanza.getAttribute('type'),
  13534. 'name': stanza.getAttribute('name')
  13535. });
  13536. });
  13537. if (stanza.querySelector('feature[var="'+Strophe.NS.DISCO_ITEMS+'"]')) {
  13538. this.queryForItems();
  13539. }
  13540. _.forEach(stanza.querySelectorAll('feature'), (feature) => {
  13541. this.features.create({
  13542. 'var': feature.getAttribute('var'),
  13543. 'from': stanza.getAttribute('from')
  13544. });
  13545. });
  13546. this.trigger('featuresDiscovered');
  13547. }
  13548. });
  13549. _converse.DiscoEntities = Backbone.Collection.extend({
  13550. model: _converse.DiscoEntity,
  13551. initialize () {
  13552. this.browserStorage = new Backbone.BrowserStorage[_converse.storage](
  13553. b64_sha1(`converse.disco-entities-${_converse.bare_jid}`)
  13554. );
  13555. this.fetchEntities().then(
  13556. _.partial(_converse.emit, 'discoInitialized'),
  13557. _.partial(_converse.emit, 'discoInitialized')
  13558. ).catch(_.partial(_converse.log, _, Strophe.LogLevel.FATAL));
  13559. },
  13560. fetchEntities () {
  13561. return new Promise((resolve, reject) => {
  13562. this.fetch({
  13563. add: true,
  13564. success: function (collection) {
  13565. if (collection.length === 0 || !collection.get(_converse.domain)) {
  13566. this.create({'jid': _converse.domain});
  13567. }
  13568. resolve();
  13569. }.bind(this),
  13570. error () {
  13571. reject (new Error("Could not fetch disco entities"));
  13572. }
  13573. });
  13574. });
  13575. }
  13576. });
  13577. function addClientFeatures () {
  13578. /* The strophe.disco.js plugin keeps a list of features which
  13579. * it will advertise to any #info queries made to it.
  13580. *
  13581. * See: http://xmpp.org/extensions/xep-0030.html#info
  13582. */
  13583. // See http://xmpp.org/registrar/disco-categories.html
  13584. _converse.connection.disco.addIdentity('client', 'web', 'Converse.js');
  13585. _converse.connection.disco.addFeature(Strophe.NS.BOSH);
  13586. _converse.connection.disco.addFeature(Strophe.NS.CHATSTATES);
  13587. _converse.connection.disco.addFeature(Strophe.NS.DISCO_INFO);
  13588. _converse.connection.disco.addFeature(Strophe.NS.ROSTERX); // Limited support
  13589. if (_converse.message_carbons) {
  13590. _converse.connection.disco.addFeature(Strophe.NS.CARBONS);
  13591. }
  13592. _converse.emit('addClientFeatures');
  13593. return this;
  13594. }
  13595. function initializeDisco () {
  13596. addClientFeatures();
  13597. _converse.disco_entities = new _converse.DiscoEntities();
  13598. }
  13599. _converse.api.listen.on('reconnected', initializeDisco);
  13600. _converse.api.listen.on('connected', initializeDisco);
  13601. _converse.api.listen.on('beforeTearDown', () => {
  13602. if (_converse.disco_entities) {
  13603. _converse.disco_entities.each((entity) => {
  13604. entity.features.reset();
  13605. entity.features.browserStorage._clear();
  13606. });
  13607. _converse.disco_entities.reset();
  13608. _converse.disco_entities.browserStorage._clear();
  13609. }
  13610. });
  13611. }
  13612. });
  13613. }));
  13614. // Converse.js (A browser based XMPP chat client)
  13615. // http://conversejs.org
  13616. //
  13617. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  13618. // Licensed under the Mozilla Public License (MPLv2)
  13619. //
  13620. /*global define */
  13621. /* This is a Converse.js plugin which add support for multi-user chat rooms, as
  13622. * specified in XEP-0045 Multi-user chat.
  13623. */
  13624. (function (root, factory) {
  13625. define('converse-muc',["jquery.noconflict", "converse-core", "tpl!chatarea", "tpl!chatroom", "tpl!chatroom_disconnect", "tpl!chatroom_features", "tpl!chatroom_form", "tpl!chatroom_head", "tpl!chatroom_invite", "tpl!chatroom_nickname_form", "tpl!chatroom_password_form", "tpl!chatroom_sidebar", "tpl!chatroom_toolbar", "tpl!chatrooms_tab", "tpl!info", "tpl!occupant", "tpl!room_description", "tpl!room_item", "tpl!room_panel", "tpl!spinner", "awesomplete", "converse-chatview", "converse-disco"], factory);
  13626. })(undefined, function ($, converse, tpl_chatarea, tpl_chatroom, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, tpl_chatroom_head, tpl_chatroom_invite, tpl_chatroom_nickname_form, tpl_chatroom_password_form, tpl_chatroom_sidebar, tpl_chatroom_toolbar, tpl_chatrooms_tab, tpl_info, tpl_occupant, tpl_room_description, tpl_room_item, tpl_room_panel, tpl_spinner, Awesomplete) {
  13627. "use strict";
  13628. var ROOMS_PANEL_ID = 'chatrooms';
  13629. var CHATROOMS_TYPE = 'chatroom';
  13630. var _converse$env = converse.env,
  13631. Strophe = _converse$env.Strophe,
  13632. Backbone = _converse$env.Backbone,
  13633. Promise = _converse$env.Promise,
  13634. $iq = _converse$env.$iq,
  13635. $build = _converse$env.$build,
  13636. $msg = _converse$env.$msg,
  13637. $pres = _converse$env.$pres,
  13638. b64_sha1 = _converse$env.b64_sha1,
  13639. sizzle = _converse$env.sizzle,
  13640. utils = _converse$env.utils,
  13641. _ = _converse$env._,
  13642. fp = _converse$env.fp,
  13643. moment = _converse$env.moment;
  13644. // Add Strophe Namespaces
  13645. Strophe.addNamespace('MUC_ADMIN', Strophe.NS.MUC + "#admin");
  13646. Strophe.addNamespace('MUC_OWNER', Strophe.NS.MUC + "#owner");
  13647. Strophe.addNamespace('MUC_REGISTER', "jabber:iq:register");
  13648. Strophe.addNamespace('MUC_ROOMCONF', Strophe.NS.MUC + "#roomconfig");
  13649. Strophe.addNamespace('MUC_USER', Strophe.NS.MUC + "#user");
  13650. var ROOM_FEATURES = ['passwordprotected', 'unsecured', 'hidden', 'public', 'membersonly', 'open', 'persistent', 'temporary', 'nonanonymous', 'semianonymous', 'moderated', 'unmoderated', 'mam_enabled'];
  13651. var ROOM_FEATURES_MAP = {
  13652. 'passwordprotected': 'unsecured',
  13653. 'unsecured': 'passwordprotected',
  13654. 'hidden': 'public',
  13655. 'public': 'hidden',
  13656. 'membersonly': 'open',
  13657. 'open': 'membersonly',
  13658. 'persistent': 'temporary',
  13659. 'temporary': 'persistent',
  13660. 'nonanonymous': 'semianonymous',
  13661. 'semianonymous': 'nonanonymous',
  13662. 'moderated': 'unmoderated',
  13663. 'unmoderated': 'moderated'
  13664. };
  13665. converse.ROOMSTATUS = {
  13666. CONNECTED: 0,
  13667. CONNECTING: 1,
  13668. NICKNAME_REQUIRED: 2,
  13669. PASSWORD_REQUIRED: 3,
  13670. DISCONNECTED: 4,
  13671. ENTERED: 5
  13672. };
  13673. converse.plugins.add('converse-muc', {
  13674. /* Optional dependencies are other plugins which might be
  13675. * overridden or relied upon, and therefore need to be loaded before
  13676. * this plugin. They are called "optional" because they might not be
  13677. * available, in which case any overrides applicable to them will be
  13678. * ignored.
  13679. *
  13680. * It's possible however to make optional dependencies non-optional.
  13681. * If the setting "strict_plugin_dependencies" is set to true,
  13682. * an error will be raised if the plugin is not found.
  13683. *
  13684. * NB: These plugins need to have already been loaded via require.js.
  13685. */
  13686. optional_dependencies: ["converse-controlbox"],
  13687. overrides: {
  13688. // Overrides mentioned here will be picked up by converse.js's
  13689. // plugin architecture they will replace existing methods on the
  13690. // relevant objects or classes.
  13691. //
  13692. // New functions which don't exist yet can also be added.
  13693. _tearDown: function _tearDown() {
  13694. var rooms = this.chatboxes.where({ 'type': CHATROOMS_TYPE });
  13695. _.each(rooms, function (room) {
  13696. utils.safeSave(room, { 'connection_status': converse.ROOMSTATUS.DISCONNECTED });
  13697. });
  13698. this.__super__._tearDown.call(this, arguments);
  13699. },
  13700. ChatBoxes: {
  13701. model: function model(attrs, options) {
  13702. var _converse = this.__super__._converse;
  13703. if (attrs.type == CHATROOMS_TYPE) {
  13704. return new _converse.ChatRoom(attrs, options);
  13705. } else {
  13706. return this.__super__.model.apply(this, arguments);
  13707. }
  13708. }
  13709. },
  13710. ControlBoxView: {
  13711. renderRoomsPanel: function renderRoomsPanel() {
  13712. var _converse = this.__super__._converse;
  13713. this.roomspanel = new _converse.RoomsPanel({
  13714. '$parent': this.$el.find('.controlbox-panes'),
  13715. 'model': new (Backbone.Model.extend({
  13716. id: b64_sha1("converse.roomspanel" + _converse.bare_jid), // Required by sessionStorage
  13717. browserStorage: new Backbone.BrowserStorage[_converse.storage](b64_sha1("converse.roomspanel" + _converse.bare_jid))
  13718. }))()
  13719. });
  13720. this.roomspanel.insertIntoDOM().model.fetch();
  13721. if (!this.roomspanel.model.get('nick')) {
  13722. this.roomspanel.model.save({
  13723. nick: Strophe.getNodeFromJid(_converse.bare_jid)
  13724. });
  13725. }
  13726. _converse.emit('roomsPanelRendered');
  13727. },
  13728. renderContactsPanel: function renderContactsPanel() {
  13729. var _converse = this.__super__._converse;
  13730. this.__super__.renderContactsPanel.apply(this, arguments);
  13731. if (_converse.allow_muc) {
  13732. this.renderRoomsPanel();
  13733. }
  13734. },
  13735. featureAdded: function featureAdded(feature) {
  13736. var _converse = this.__super__._converse;
  13737. if (feature.get('var') === Strophe.NS.MUC && _converse.allow_muc) {
  13738. this.setMUCDomain(feature.get('from'));
  13739. }
  13740. },
  13741. getMUCDomainFromDisco: function getMUCDomainFromDisco() {
  13742. var _this = this;
  13743. /* Check whether service discovery for the user's domain
  13744. * returned MUC information and use that to automatically
  13745. * set the MUC domain for the "Rooms" panel of the
  13746. * controlbox.
  13747. */
  13748. var _converse = this.__super__._converse;
  13749. _converse.api.waitUntil('discoInitialized').then(function () {
  13750. _converse.api.listen.on('serviceDiscovered', _this.featureAdded, _this);
  13751. // Features could have been added before the controlbox was
  13752. // initialized. We're only interested in MUC
  13753. var feature = _converse.disco_entities[_converse.domain].features.findWhere({
  13754. 'var': Strophe.NS.MUC
  13755. });
  13756. if (feature) {
  13757. _this.featureAdded(feature);
  13758. }
  13759. });
  13760. },
  13761. onConnected: function onConnected() {
  13762. var _converse = this.__super__._converse;
  13763. this.__super__.onConnected.apply(this, arguments);
  13764. if (!this.model.get('connected')) {
  13765. return;
  13766. }
  13767. if (_.isUndefined(_converse.muc_domain)) {
  13768. this.getMUCDomainFromDisco();
  13769. } else {
  13770. this.setMUCDomain(_converse.muc_domain);
  13771. }
  13772. },
  13773. setMUCDomain: function setMUCDomain(domain) {
  13774. var _converse = this.__super__._converse;
  13775. _converse.muc_domain = domain;
  13776. this.roomspanel.model.save({ 'muc_domain': domain });
  13777. var $server = this.$el.find('input.new-chatroom-server');
  13778. if (!$server.is(':focus')) {
  13779. $server.val(this.roomspanel.model.get('muc_domain'));
  13780. }
  13781. }
  13782. },
  13783. ChatBoxViews: {
  13784. onChatBoxAdded: function onChatBoxAdded(item) {
  13785. var _converse = this.__super__._converse;
  13786. var view = this.get(item.get('id'));
  13787. if (!view && item.get('type') === CHATROOMS_TYPE) {
  13788. view = new _converse.ChatRoomView({ 'model': item });
  13789. return this.add(item.get('id'), view);
  13790. } else {
  13791. return this.__super__.onChatBoxAdded.apply(this, arguments);
  13792. }
  13793. }
  13794. }
  13795. },
  13796. initialize: function initialize() {
  13797. /* The initialize function gets called as soon as the plugin is
  13798. * loaded by converse.js's plugin machinery.
  13799. */
  13800. var _converse = this._converse,
  13801. __ = _converse.__,
  13802. ___ = _converse.___;
  13803. // XXX: Inside plugins, all calls to the translation machinery
  13804. // (e.g. utils.__) should only be done in the initialize function.
  13805. // If called before, we won't know what language the user wants,
  13806. // and it'll fall back to English.
  13807. /* http://xmpp.org/extensions/xep-0045.html
  13808. * ----------------------------------------
  13809. * 100 message Entering a room Inform user that any occupant is allowed to see the user's full JID
  13810. * 101 message (out of band) Affiliation change Inform user that his or her affiliation changed while not in the room
  13811. * 102 message Configuration change Inform occupants that room now shows unavailable members
  13812. * 103 message Configuration change Inform occupants that room now does not show unavailable members
  13813. * 104 message Configuration change Inform occupants that a non-privacy-related room configuration change has occurred
  13814. * 110 presence Any room presence Inform user that presence refers to one of its own room occupants
  13815. * 170 message or initial presence Configuration change Inform occupants that room logging is now enabled
  13816. * 171 message Configuration change Inform occupants that room logging is now disabled
  13817. * 172 message Configuration change Inform occupants that the room is now non-anonymous
  13818. * 173 message Configuration change Inform occupants that the room is now semi-anonymous
  13819. * 174 message Configuration change Inform occupants that the room is now fully-anonymous
  13820. * 201 presence Entering a room Inform user that a new room has been created
  13821. * 210 presence Entering a room Inform user that the service has assigned or modified the occupant's roomnick
  13822. * 301 presence Removal from room Inform user that he or she has been banned from the room
  13823. * 303 presence Exiting a room Inform all occupants of new room nickname
  13824. * 307 presence Removal from room Inform user that he or she has been kicked from the room
  13825. * 321 presence Removal from room Inform user that he or she is being removed from the room because of an affiliation change
  13826. * 322 presence Removal from room Inform user that he or she is being removed from the room because the room has been changed to members-only and the user is not a member
  13827. * 332 presence Removal from room Inform user that he or she is being removed from the room because of a system shutdown
  13828. */
  13829. _converse.muc = {
  13830. info_messages: {
  13831. 100: __('This room is not anonymous'),
  13832. 102: __('This room now shows unavailable members'),
  13833. 103: __('This room does not show unavailable members'),
  13834. 104: __('The room configuration has changed'),
  13835. 170: __('Room logging is now enabled'),
  13836. 171: __('Room logging is now disabled'),
  13837. 172: __('This room is now no longer anonymous'),
  13838. 173: __('This room is now semi-anonymous'),
  13839. 174: __('This room is now fully-anonymous'),
  13840. 201: __('A new room has been created')
  13841. },
  13842. disconnect_messages: {
  13843. 301: __('You have been banned from this room'),
  13844. 307: __('You have been kicked from this room'),
  13845. 321: __("You have been removed from this room because of an affiliation change"),
  13846. 322: __("You have been removed from this room because the room has changed to members-only and you're not a member"),
  13847. 332: __("You have been removed from this room because the MUC (Multi-user chat) service is being shut down.")
  13848. },
  13849. action_info_messages: {
  13850. /* XXX: Note the triple underscore function and not double
  13851. * underscore.
  13852. *
  13853. * This is a hack. We can't pass the strings to __ because we
  13854. * don't yet know what the variable to interpolate is.
  13855. *
  13856. * Triple underscore will just return the string again, but we
  13857. * can then at least tell gettext to scan for it so that these
  13858. * strings are picked up by the translation machinery.
  13859. */
  13860. 301: ___("%1$s has been banned"),
  13861. 303: ___("%1$s's nickname has changed"),
  13862. 307: ___("%1$s has been kicked out"),
  13863. 321: ___("%1$s has been removed because of an affiliation change"),
  13864. 322: ___("%1$s has been removed for not being a member")
  13865. },
  13866. new_nickname_messages: {
  13867. 210: ___('Your nickname has been automatically set to: %1$s'),
  13868. 303: ___('Your nickname has been changed to: %1$s')
  13869. }
  13870. };
  13871. // Configuration values for this plugin
  13872. // ====================================
  13873. // Refer to docs/source/configuration.rst for explanations of these
  13874. // configuration settings.
  13875. _converse.api.settings.update({
  13876. allow_muc: true,
  13877. allow_muc_invitations: true,
  13878. auto_join_on_invite: false,
  13879. auto_join_rooms: [],
  13880. auto_list_rooms: false,
  13881. hide_muc_server: false,
  13882. muc_disable_moderator_commands: false,
  13883. muc_domain: undefined,
  13884. muc_history_max_stanzas: undefined,
  13885. muc_instant_rooms: true,
  13886. muc_nickname_from_jid: false,
  13887. muc_show_join_leave: true,
  13888. visible_toolbar_buttons: {
  13889. 'toggle_occupants': true
  13890. }
  13891. });
  13892. _converse.api.promises.add('roomsPanelRendered');
  13893. _converse.openChatRoom = function (settings, bring_to_foreground) {
  13894. /* Opens a chat room, making sure that certain attributes
  13895. * are correct, for example that the "type" is set to
  13896. * "chatroom".
  13897. */
  13898. if (_.isUndefined(settings.jid)) {
  13899. throw new Error("openChatRoom needs to be called with a JID");
  13900. }
  13901. settings.type = CHATROOMS_TYPE;
  13902. settings.id = settings.jid;
  13903. settings.box_id = b64_sha1(settings.jid);
  13904. return _converse.chatboxviews.showChat(settings, bring_to_foreground);
  13905. };
  13906. _converse.ChatRoom = _converse.ChatBox.extend({
  13907. defaults: function defaults() {
  13908. return _.assign(_.clone(_converse.ChatBox.prototype.defaults), _.zipObject(ROOM_FEATURES, _.map(ROOM_FEATURES, _.stubFalse)), {
  13909. // For group chats, we distinguish between generally unread
  13910. // messages and those ones that specifically mention the
  13911. // user.
  13912. //
  13913. // To keep things simple, we reuse `num_unread` from
  13914. // _converse.ChatBox to indicate unread messages which
  13915. // mention the user and `num_unread_general` to indicate
  13916. // generally unread messages (which *includes* mentions!).
  13917. 'num_unread_general': 0,
  13918. 'affiliation': null,
  13919. 'connection_status': converse.ROOMSTATUS.DISCONNECTED,
  13920. 'name': '',
  13921. 'description': '',
  13922. 'features_fetched': false,
  13923. 'roomconfig': {},
  13924. 'type': CHATROOMS_TYPE
  13925. });
  13926. },
  13927. isUserMentioned: function isUserMentioned(message) {
  13928. /* Returns a boolean to indicate whether the current user
  13929. * was mentioned in a message.
  13930. *
  13931. * Parameters:
  13932. * (String): The text message
  13933. */
  13934. return new RegExp("\\b" + this.get('nick') + "\\b").test(message);
  13935. },
  13936. incrementUnreadMsgCounter: function incrementUnreadMsgCounter(stanza) {
  13937. /* Given a newly received message, update the unread counter if
  13938. * necessary.
  13939. *
  13940. * Parameters:
  13941. * (XMLElement): The <messsage> stanza
  13942. */
  13943. var body = stanza.querySelector('body');
  13944. if (_.isNull(body)) {
  13945. return; // The message has no text
  13946. }
  13947. if (utils.isNewMessage(stanza) && this.newMessageWillBeHidden()) {
  13948. this.save({ 'num_unread_general': this.get('num_unread_general') + 1 });
  13949. if (this.isUserMentioned(body.textContent)) {
  13950. this.save({ 'num_unread': this.get('num_unread') + 1 });
  13951. _converse.incrementMsgCounter();
  13952. }
  13953. }
  13954. },
  13955. clearUnreadMsgCounter: function clearUnreadMsgCounter() {
  13956. utils.safeSave(this, {
  13957. 'num_unread': 0,
  13958. 'num_unread_general': 0
  13959. });
  13960. }
  13961. });
  13962. _converse.ChatRoomView = _converse.ChatBoxView.extend({
  13963. /* Backbone View which renders a chat room, based upon the view
  13964. * for normal one-on-one chat boxes.
  13965. */
  13966. length: 300,
  13967. tagName: 'div',
  13968. className: 'chatbox chatroom hidden',
  13969. is_chatroom: true,
  13970. events: {
  13971. 'click .close-chatbox-button': 'close',
  13972. 'click .configure-chatroom-button': 'getAndRenderConfigurationForm',
  13973. 'click .toggle-smiley': 'toggleEmojiMenu',
  13974. 'click .toggle-smiley ul.emoji-picker li': 'insertEmoji',
  13975. 'click .toggle-clear': 'clearChatRoomMessages',
  13976. 'click .toggle-call': 'toggleCall',
  13977. 'click .toggle-occupants a': 'toggleOccupants',
  13978. 'click .new-msgs-indicator': 'viewUnreadMessages',
  13979. 'click .occupant': 'onOccupantClicked',
  13980. 'keypress .chat-textarea': 'keyPressed',
  13981. 'click .send-button': 'onSendButtonClicked'
  13982. },
  13983. initialize: function initialize() {
  13984. var _this2 = this;
  13985. this.model.messages.on('add', this.onMessageAdded, this);
  13986. this.model.on('show', this.show, this);
  13987. this.model.on('destroy', this.hide, this);
  13988. this.model.on('change:connection_status', this.afterConnected, this);
  13989. this.model.on('change:affiliation', this.renderHeading, this);
  13990. this.model.on('change:chat_state', this.sendChatState, this);
  13991. this.model.on('change:description', this.renderHeading, this);
  13992. this.model.on('change:name', this.renderHeading, this);
  13993. this.createEmojiPicker();
  13994. this.createOccupantsView();
  13995. this.render().insertIntoDOM();
  13996. this.registerHandlers();
  13997. if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
  13998. var handler = function handler() {
  13999. _this2.join();
  14000. _this2.fetchMessages();
  14001. _converse.emit('chatRoomOpened', _this2);
  14002. };
  14003. this.getRoomFeatures().then(handler, handler);
  14004. } else {
  14005. this.fetchMessages();
  14006. _converse.emit('chatRoomOpened', this);
  14007. }
  14008. },
  14009. render: function render() {
  14010. this.el.setAttribute('id', this.model.get('box_id'));
  14011. this.el.innerHTML = tpl_chatroom();
  14012. this.renderHeading();
  14013. this.renderChatArea();
  14014. if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
  14015. this.showSpinner();
  14016. }
  14017. utils.refreshWebkit();
  14018. return this;
  14019. },
  14020. renderHeading: function renderHeading() {
  14021. /* Render the heading UI of the chat room. */
  14022. this.el.querySelector('.chat-head-chatroom').innerHTML = this.generateHeadingHTML();
  14023. },
  14024. renderChatArea: function renderChatArea() {
  14025. /* Render the UI container in which chat room messages will
  14026. * appear.
  14027. */
  14028. if (!this.$('.chat-area').length) {
  14029. this.$('.chatroom-body').empty().append(tpl_chatarea({
  14030. 'label_message': __('Message'),
  14031. 'label_send': __('Send'),
  14032. 'show_send_button': _converse.show_send_button,
  14033. 'show_toolbar': _converse.show_toolbar,
  14034. 'unread_msgs': __('You have unread messages')
  14035. })).append(this.occupantsview.$el);
  14036. this.renderToolbar(tpl_chatroom_toolbar);
  14037. this.$content = this.$el.find('.chat-content');
  14038. }
  14039. this.toggleOccupants(null, true);
  14040. return this;
  14041. },
  14042. createOccupantsView: function createOccupantsView() {
  14043. /* Create the ChatRoomOccupantsView Backbone.View
  14044. */
  14045. var model = new _converse.ChatRoomOccupants();
  14046. model.chatroomview = this;
  14047. this.occupantsview = new _converse.ChatRoomOccupantsView({ 'model': model });
  14048. var id = b64_sha1("converse.occupants" + _converse.bare_jid + this.model.get('jid'));
  14049. this.occupantsview.model.browserStorage = new Backbone.BrowserStorage.session(id);
  14050. this.occupantsview.render();
  14051. this.occupantsview.model.fetch({ add: true });
  14052. return this;
  14053. },
  14054. insertIntoDOM: function insertIntoDOM() {
  14055. if (document.querySelector('body').contains(this.el)) {
  14056. return;
  14057. }
  14058. var view = _converse.chatboxviews.get("controlbox");
  14059. if (view) {
  14060. this.$el.insertAfter(view.$el);
  14061. } else {
  14062. $('#conversejs').prepend(this.$el);
  14063. }
  14064. return this;
  14065. },
  14066. generateHeadingHTML: function generateHeadingHTML() {
  14067. /* Returns the heading HTML to be rendered.
  14068. */
  14069. return tpl_chatroom_head(_.extend(this.model.toJSON(), {
  14070. Strophe: Strophe,
  14071. info_close: __('Close and leave this room'),
  14072. info_configure: __('Configure this room'),
  14073. description: this.model.get('description') || ''
  14074. }));
  14075. },
  14076. afterShown: function afterShown() {
  14077. /* Override from converse-chatview, specifically to avoid
  14078. * the 'active' chat state from being sent out prematurely.
  14079. *
  14080. * This is instead done in `afterConnected` below.
  14081. */
  14082. if (this.model.collection && this.model.collection.browserStorage) {
  14083. // Without a connection, we haven't yet initialized
  14084. // localstorage
  14085. this.model.save();
  14086. }
  14087. this.occupantsview.setOccupantsHeight();
  14088. },
  14089. afterConnected: function afterConnected() {
  14090. if (this.model.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
  14091. this.setChatState(_converse.ACTIVE);
  14092. this.scrollDown();
  14093. this.focus();
  14094. }
  14095. },
  14096. getExtraMessageClasses: function getExtraMessageClasses(attrs) {
  14097. var extra_classes = _converse.ChatBoxView.prototype.getExtraMessageClasses.apply(this, arguments);
  14098. if (this.is_chatroom && attrs.sender === 'them' && this.model.isUserMentioned(attrs.message)) {
  14099. // Add special class to mark groupchat messages
  14100. // in which we are mentioned.
  14101. extra_classes += ' mentioned';
  14102. }
  14103. return extra_classes;
  14104. },
  14105. getToolbarOptions: function getToolbarOptions() {
  14106. return _.extend(_converse.ChatBoxView.prototype.getToolbarOptions.apply(this, arguments), {
  14107. label_hide_occupants: __('Hide the list of occupants'),
  14108. show_occupants_toggle: this.is_chatroom && _converse.visible_toolbar_buttons.toggle_occupants
  14109. });
  14110. },
  14111. close: function close(ev) {
  14112. /* Close this chat box, which implies leaving the room as
  14113. * well.
  14114. */
  14115. this.leave();
  14116. },
  14117. toggleOccupants: function toggleOccupants(ev, preserve_state) {
  14118. /* Show or hide the right sidebar containing the chat
  14119. * occupants (and the invite widget).
  14120. */
  14121. if (ev) {
  14122. ev.preventDefault();
  14123. ev.stopPropagation();
  14124. }
  14125. if (preserve_state) {
  14126. // Bit of a hack, to make sure that the sidebar's state doesn't change
  14127. this.model.set({ hidden_occupants: !this.model.get('hidden_occupants') });
  14128. }
  14129. if (!this.model.get('hidden_occupants')) {
  14130. this.model.save({ hidden_occupants: true });
  14131. this.$('.icon-hide-users').removeClass('icon-hide-users').addClass('icon-show-users');
  14132. this.$('.occupants').addClass('hidden');
  14133. this.$('.chat-area').addClass('full');
  14134. this.scrollDown();
  14135. } else {
  14136. this.model.save({ hidden_occupants: false });
  14137. this.$('.icon-show-users').removeClass('icon-show-users').addClass('icon-hide-users');
  14138. this.$('.chat-area').removeClass('full');
  14139. this.$('div.occupants').removeClass('hidden');
  14140. this.scrollDown();
  14141. }
  14142. },
  14143. onOccupantClicked: function onOccupantClicked(ev) {
  14144. /* When an occupant is clicked, insert their nickname into
  14145. * the chat textarea input.
  14146. */
  14147. this.insertIntoTextArea(ev.target.textContent);
  14148. },
  14149. requestMemberList: function requestMemberList(chatroom_jid, affiliation) {
  14150. /* Send an IQ stanza to the server, asking it for the
  14151. * member-list of this room.
  14152. *
  14153. * See: http://xmpp.org/extensions/xep-0045.html#modifymember
  14154. *
  14155. * Parameters:
  14156. * (String) chatroom_jid: The JID of the chatroom for
  14157. * which the member-list is being requested
  14158. * (String) affiliation: The specific member list to
  14159. * fetch. 'admin', 'owner' or 'member'.
  14160. *
  14161. * Returns:
  14162. * A promise which resolves once the list has been
  14163. * retrieved.
  14164. */
  14165. return new Promise(function (resolve, reject) {
  14166. affiliation = affiliation || 'member';
  14167. var iq = $iq({ to: chatroom_jid, type: "get" }).c("query", { xmlns: Strophe.NS.MUC_ADMIN }).c("item", { 'affiliation': affiliation });
  14168. _converse.connection.sendIQ(iq, resolve, reject);
  14169. });
  14170. },
  14171. parseMemberListIQ: function parseMemberListIQ(iq) {
  14172. /* Given an IQ stanza with a member list, create an array of member
  14173. * objects.
  14174. */
  14175. return _.map($(iq).find("query[xmlns=\"" + Strophe.NS.MUC_ADMIN + "\"] item"), function (item) {
  14176. return {
  14177. 'jid': item.getAttribute('jid'),
  14178. 'affiliation': item.getAttribute('affiliation')
  14179. };
  14180. });
  14181. },
  14182. computeAffiliationsDelta: function computeAffiliationsDelta(exclude_existing, remove_absentees, new_list, old_list) {
  14183. /* Given two lists of objects with 'jid', 'affiliation' and
  14184. * 'reason' properties, return a new list containing
  14185. * those objects that are new, changed or removed
  14186. * (depending on the 'remove_absentees' boolean).
  14187. *
  14188. * The affiliations for new and changed members stay the
  14189. * same, for removed members, the affiliation is set to 'none'.
  14190. *
  14191. * The 'reason' property is not taken into account when
  14192. * comparing whether affiliations have been changed.
  14193. *
  14194. * Parameters:
  14195. * (Boolean) exclude_existing: Indicates whether JIDs from
  14196. * the new list which are also in the old list
  14197. * (regardless of affiliation) should be excluded
  14198. * from the delta. One reason to do this
  14199. * would be when you want to add a JID only if it
  14200. * doesn't have *any* existing affiliation at all.
  14201. * (Boolean) remove_absentees: Indicates whether JIDs
  14202. * from the old list which are not in the new list
  14203. * should be considered removed and therefore be
  14204. * included in the delta with affiliation set
  14205. * to 'none'.
  14206. * (Array) new_list: Array containing the new affiliations
  14207. * (Array) old_list: Array containing the old affiliations
  14208. */
  14209. var new_jids = _.map(new_list, 'jid');
  14210. var old_jids = _.map(old_list, 'jid');
  14211. // Get the new affiliations
  14212. var delta = _.map(_.difference(new_jids, old_jids), function (jid) {
  14213. return new_list[_.indexOf(new_jids, jid)];
  14214. });
  14215. if (!exclude_existing) {
  14216. // Get the changed affiliations
  14217. delta = delta.concat(_.filter(new_list, function (item) {
  14218. var idx = _.indexOf(old_jids, item.jid);
  14219. if (idx >= 0) {
  14220. return item.affiliation !== old_list[idx].affiliation;
  14221. }
  14222. return false;
  14223. }));
  14224. }
  14225. if (remove_absentees) {
  14226. // Get the removed affiliations
  14227. delta = delta.concat(_.map(_.difference(old_jids, new_jids), function (jid) {
  14228. return { 'jid': jid, 'affiliation': 'none' };
  14229. }));
  14230. }
  14231. return delta;
  14232. },
  14233. sendAffiliationIQ: function sendAffiliationIQ(chatroom_jid, affiliation, member) {
  14234. /* Send an IQ stanza specifying an affiliation change.
  14235. *
  14236. * Paremeters:
  14237. * (String) chatroom_jid: JID of the relevant room
  14238. * (String) affiliation: affiliation (could also be stored
  14239. * on the member object).
  14240. * (Object) member: Map containing the member's jid and
  14241. * optionally a reason and affiliation.
  14242. */
  14243. return new Promise(function (resolve, reject) {
  14244. var iq = $iq({ to: chatroom_jid, type: "set" }).c("query", { xmlns: Strophe.NS.MUC_ADMIN }).c("item", {
  14245. 'affiliation': member.affiliation || affiliation,
  14246. 'jid': member.jid
  14247. });
  14248. if (!_.isUndefined(member.reason)) {
  14249. iq.c("reason", member.reason);
  14250. }
  14251. _converse.connection.sendIQ(iq, resolve, reject);
  14252. });
  14253. },
  14254. setAffiliation: function setAffiliation(affiliation, members) {
  14255. /* Send IQ stanzas to the server to set an affiliation for
  14256. * the provided JIDs.
  14257. *
  14258. * See: http://xmpp.org/extensions/xep-0045.html#modifymember
  14259. *
  14260. * XXX: Prosody doesn't accept multiple JIDs' affiliations
  14261. * being set in one IQ stanza, so as a workaround we send
  14262. * a separate stanza for each JID.
  14263. * Related ticket: https://prosody.im/issues/issue/795
  14264. *
  14265. * Parameters:
  14266. * (String) affiliation: The affiliation
  14267. * (Object) members: A map of jids, affiliations and
  14268. * optionally reasons. Only those entries with the
  14269. * same affiliation as being currently set will be
  14270. * considered.
  14271. *
  14272. * Returns:
  14273. * A promise which resolves and fails depending on the
  14274. * XMPP server response.
  14275. */
  14276. members = _.filter(members, function (member) {
  14277. return (
  14278. // We only want those members who have the right
  14279. // affiliation (or none, which implies the provided
  14280. // one).
  14281. _.isUndefined(member.affiliation) || member.affiliation === affiliation
  14282. );
  14283. });
  14284. var promises = _.map(members, _.partial(this.sendAffiliationIQ, this.model.get('jid'), affiliation));
  14285. return Promise.all(promises);
  14286. },
  14287. setAffiliations: function setAffiliations(members) {
  14288. /* Send IQ stanzas to the server to modify the
  14289. * affiliations in this room.
  14290. *
  14291. * See: http://xmpp.org/extensions/xep-0045.html#modifymember
  14292. *
  14293. * Parameters:
  14294. * (Object) members: A map of jids, affiliations and optionally reasons
  14295. * (Function) onSuccess: callback for a succesful response
  14296. * (Function) onError: callback for an error response
  14297. */
  14298. var affiliations = _.uniq(_.map(members, 'affiliation'));
  14299. _.each(affiliations, _.partial(this.setAffiliation.bind(this), _, members));
  14300. },
  14301. marshallAffiliationIQs: function marshallAffiliationIQs() {
  14302. /* Marshall a list of IQ stanzas into a map of JIDs and
  14303. * affiliations.
  14304. *
  14305. * Parameters:
  14306. * Any amount of XMLElement objects, representing the IQ
  14307. * stanzas.
  14308. */
  14309. return _.flatMap(arguments, this.parseMemberListIQ);
  14310. },
  14311. getJidsWithAffiliations: function getJidsWithAffiliations(affiliations) {
  14312. var _this3 = this;
  14313. /* Returns a map of JIDs that have the affiliations
  14314. * as provided.
  14315. */
  14316. if (_.isString(affiliations)) {
  14317. affiliations = [affiliations];
  14318. }
  14319. return new Promise(function (resolve, reject) {
  14320. var promises = _.map(affiliations, _.partial(_this3.requestMemberList, _this3.model.get('jid')));
  14321. Promise.all(promises).then(_.flow(_this3.marshallAffiliationIQs.bind(_this3), resolve), _.flow(_this3.marshallAffiliationIQs.bind(_this3), resolve));
  14322. });
  14323. },
  14324. updateMemberLists: function updateMemberLists(members, affiliations, deltaFunc) {
  14325. var _this4 = this;
  14326. /* Fetch the lists of users with the given affiliations.
  14327. * Then compute the delta between those users and
  14328. * the passed in members, and if it exists, send the delta
  14329. * to the XMPP server to update the member list.
  14330. *
  14331. * Parameters:
  14332. * (Object) members: Map of member jids and affiliations.
  14333. * (String|Array) affiliation: An array of affiliations or
  14334. * a string if only one affiliation.
  14335. * (Function) deltaFunc: The function to compute the delta
  14336. * between old and new member lists.
  14337. *
  14338. * Returns:
  14339. * A promise which is resolved once the list has been
  14340. * updated or once it's been established there's no need
  14341. * to update the list.
  14342. */
  14343. this.getJidsWithAffiliations(affiliations).then(function (old_members) {
  14344. _this4.setAffiliations(deltaFunc(members, old_members));
  14345. });
  14346. },
  14347. directInvite: function directInvite(recipient, reason) {
  14348. /* Send a direct invitation as per XEP-0249
  14349. *
  14350. * Parameters:
  14351. * (String) recipient - JID of the person being invited
  14352. * (String) reason - Optional reason for the invitation
  14353. */
  14354. if (this.model.get('membersonly')) {
  14355. // When inviting to a members-only room, we first add
  14356. // the person to the member list by giving them an
  14357. // affiliation of 'member' (if they're not affiliated
  14358. // already), otherwise they won't be able to join.
  14359. var map = {};map[recipient] = 'member';
  14360. var deltaFunc = _.partial(this.computeAffiliationsDelta, true, false);
  14361. this.updateMemberLists([{ 'jid': recipient, 'affiliation': 'member', 'reason': reason }], ['member', 'owner', 'admin'], deltaFunc);
  14362. }
  14363. var attrs = {
  14364. 'xmlns': 'jabber:x:conference',
  14365. 'jid': this.model.get('jid')
  14366. };
  14367. if (reason !== null) {
  14368. attrs.reason = reason;
  14369. }
  14370. if (this.model.get('password')) {
  14371. attrs.password = this.model.get('password');
  14372. }
  14373. var invitation = $msg({
  14374. from: _converse.connection.jid,
  14375. to: recipient,
  14376. id: _converse.connection.getUniqueId()
  14377. }).c('x', attrs);
  14378. _converse.connection.send(invitation);
  14379. _converse.emit('roomInviteSent', {
  14380. 'room': this,
  14381. 'recipient': recipient,
  14382. 'reason': reason
  14383. });
  14384. },
  14385. handleChatStateMessage: function handleChatStateMessage(message) {
  14386. /* Override the method on the ChatBoxView base class to
  14387. * ignore <gone/> notifications in groupchats.
  14388. *
  14389. * As laid out in the business rules in XEP-0085
  14390. * http://xmpp.org/extensions/xep-0085.html#bizrules-groupchat
  14391. */
  14392. if (message.get('fullname') === this.model.get('nick')) {
  14393. // Don't know about other servers, but OpenFire sends
  14394. // back to you your own chat state notifications.
  14395. // We ignore them here...
  14396. return;
  14397. }
  14398. if (message.get('chat_state') !== _converse.GONE) {
  14399. _converse.ChatBoxView.prototype.handleChatStateMessage.apply(this, arguments);
  14400. }
  14401. },
  14402. sendChatState: function sendChatState() {
  14403. /* Sends a message with the status of the user in this chat session
  14404. * as taken from the 'chat_state' attribute of the chat box.
  14405. * See XEP-0085 Chat State Notifications.
  14406. */
  14407. if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) {
  14408. return;
  14409. }
  14410. var chat_state = this.model.get('chat_state');
  14411. if (chat_state === _converse.GONE) {
  14412. // <gone/> is not applicable within MUC context
  14413. return;
  14414. }
  14415. _converse.connection.send($msg({ 'to': this.model.get('jid'), 'type': 'groupchat' }).c(chat_state, { 'xmlns': Strophe.NS.CHATSTATES }).up().c('no-store', { 'xmlns': Strophe.NS.HINTS }).up().c('no-permanent-store', { 'xmlns': Strophe.NS.HINTS }));
  14416. },
  14417. sendChatRoomMessage: function sendChatRoomMessage(text) {
  14418. /* Constuct a message stanza to be sent to this chat room,
  14419. * and send it to the server.
  14420. *
  14421. * Parameters:
  14422. * (String) text: The message text to be sent.
  14423. */
  14424. var msgid = _converse.connection.getUniqueId();
  14425. var msg = $msg({
  14426. to: this.model.get('jid'),
  14427. from: _converse.connection.jid,
  14428. type: 'groupchat',
  14429. id: msgid
  14430. }).c("body").t(text).up().c("x", { xmlns: "jabber:x:event" }).c(_converse.COMPOSING);
  14431. _converse.connection.send(msg);
  14432. this.model.messages.create({
  14433. fullname: this.model.get('nick'),
  14434. sender: 'me',
  14435. time: moment().format(),
  14436. message: text,
  14437. msgid: msgid
  14438. });
  14439. },
  14440. modifyRole: function modifyRole(room, nick, role, reason, onSuccess, onError) {
  14441. var item = $build("item", { nick: nick, role: role });
  14442. var iq = $iq({ to: room, type: "set" }).c("query", { xmlns: Strophe.NS.MUC_ADMIN }).cnode(item.node);
  14443. if (reason !== null) {
  14444. iq.c("reason", reason);
  14445. }
  14446. return _converse.connection.sendIQ(iq.tree(), onSuccess, onError);
  14447. },
  14448. validateRoleChangeCommand: function validateRoleChangeCommand(command, args) {
  14449. /* Check that a command to change a chat room user's role or
  14450. * affiliation has anough arguments.
  14451. */
  14452. // TODO check if first argument is valid
  14453. if (args.length < 1 || args.length > 2) {
  14454. this.showStatusNotification(__("Error: the \"" + command + "\" command takes two arguments, the user's nickname and optionally a reason."), true);
  14455. return false;
  14456. }
  14457. return true;
  14458. },
  14459. clearChatRoomMessages: function clearChatRoomMessages(ev) {
  14460. /* Remove all messages from the chat room UI.
  14461. */
  14462. if (!_.isUndefined(ev)) {
  14463. ev.stopPropagation();
  14464. }
  14465. var result = confirm(__("Are you sure you want to clear the messages from this room?"));
  14466. if (result === true) {
  14467. this.$content.empty();
  14468. }
  14469. return this;
  14470. },
  14471. onCommandError: function onCommandError() {
  14472. this.showStatusNotification(__("Error: could not execute the command"), true);
  14473. },
  14474. onMessageSubmitted: function onMessageSubmitted(text) {
  14475. /* Gets called when the user presses enter to send off a
  14476. * message in a chat room.
  14477. *
  14478. * Parameters:
  14479. * (String) text - The message text.
  14480. */
  14481. if (_converse.muc_disable_moderator_commands) {
  14482. return this.sendChatRoomMessage(text);
  14483. }
  14484. var match = text.replace(/^\s*/, "").match(/^\/(.*?)(?: (.*))?$/) || [false, '', ''],
  14485. args = match[2] && match[2].splitOnce(' ') || [],
  14486. command = match[1].toLowerCase();
  14487. switch (command) {
  14488. case 'admin':
  14489. if (!this.validateRoleChangeCommand(command, args)) {
  14490. break;
  14491. }
  14492. this.setAffiliation('admin', [{ 'jid': args[0],
  14493. 'reason': args[1]
  14494. }]).then(null, this.onCommandError.bind(this));
  14495. break;
  14496. case 'ban':
  14497. if (!this.validateRoleChangeCommand(command, args)) {
  14498. break;
  14499. }
  14500. this.setAffiliation('outcast', [{ 'jid': args[0],
  14501. 'reason': args[1]
  14502. }]).then(null, this.onCommandError.bind(this));
  14503. break;
  14504. case 'clear':
  14505. this.clearChatRoomMessages();
  14506. break;
  14507. case 'deop':
  14508. if (!this.validateRoleChangeCommand(command, args)) {
  14509. break;
  14510. }
  14511. this.modifyRole(this.model.get('jid'), args[0], 'occupant', args[1], undefined, this.onCommandError.bind(this));
  14512. break;
  14513. case 'help':
  14514. this.showHelpMessages(["<strong>/admin</strong>: " + __("Change user's affiliation to admin"), "<strong>/ban</strong>: " + __('Ban user from room'), "<strong>/clear</strong>: " + __('Remove messages'), "<strong>/deop</strong>: " + __('Change user role to occupant'), "<strong>/help</strong>: " + __('Show this menu'), "<strong>/kick</strong>: " + __('Kick user from room'), "<strong>/me</strong>: " + __('Write in 3rd person'), "<strong>/member</strong>: " + __('Grant membership to a user'), "<strong>/mute</strong>: " + __("Remove user's ability to post messages"), "<strong>/nick</strong>: " + __('Change your nickname'), "<strong>/op</strong>: " + __('Grant moderator role to user'), "<strong>/owner</strong>: " + __('Grant ownership of this room'), "<strong>/revoke</strong>: " + __("Revoke user's membership"), "<strong>/subject</strong>: " + __('Set room subject'), "<strong>/topic</strong>: " + __('Set room subject (alias for /subject)'), "<strong>/voice</strong>: " + __('Allow muted user to post messages')]);
  14515. break;
  14516. case 'kick':
  14517. if (!this.validateRoleChangeCommand(command, args)) {
  14518. break;
  14519. }
  14520. this.modifyRole(this.model.get('jid'), args[0], 'none', args[1], undefined, this.onCommandError.bind(this));
  14521. break;
  14522. case 'mute':
  14523. if (!this.validateRoleChangeCommand(command, args)) {
  14524. break;
  14525. }
  14526. this.modifyRole(this.model.get('jid'), args[0], 'visitor', args[1], undefined, this.onCommandError.bind(this));
  14527. break;
  14528. case 'member':
  14529. if (!this.validateRoleChangeCommand(command, args)) {
  14530. break;
  14531. }
  14532. this.setAffiliation('member', [{ 'jid': args[0],
  14533. 'reason': args[1]
  14534. }]).then(null, this.onCommandError.bind(this));
  14535. break;
  14536. case 'nick':
  14537. _converse.connection.send($pres({
  14538. from: _converse.connection.jid,
  14539. to: this.getRoomJIDAndNick(match[2]),
  14540. id: _converse.connection.getUniqueId()
  14541. }).tree());
  14542. break;
  14543. case 'owner':
  14544. if (!this.validateRoleChangeCommand(command, args)) {
  14545. break;
  14546. }
  14547. this.setAffiliation('owner', [{ 'jid': args[0],
  14548. 'reason': args[1]
  14549. }]).then(null, this.onCommandError.bind(this));
  14550. break;
  14551. case 'op':
  14552. if (!this.validateRoleChangeCommand(command, args)) {
  14553. break;
  14554. }
  14555. this.modifyRole(this.model.get('jid'), args[0], 'moderator', args[1], undefined, this.onCommandError.bind(this));
  14556. break;
  14557. case 'revoke':
  14558. if (!this.validateRoleChangeCommand(command, args)) {
  14559. break;
  14560. }
  14561. this.setAffiliation('none', [{ 'jid': args[0],
  14562. 'reason': args[1]
  14563. }]).then(null, this.onCommandError.bind(this));
  14564. break;
  14565. case 'topic':
  14566. case 'subject':
  14567. _converse.connection.send($msg({
  14568. to: this.model.get('jid'),
  14569. from: _converse.connection.jid,
  14570. type: "groupchat"
  14571. }).c("subject", { xmlns: "jabber:client" }).t(match[2]).tree());
  14572. break;
  14573. case 'voice':
  14574. if (!this.validateRoleChangeCommand(command, args)) {
  14575. break;
  14576. }
  14577. this.modifyRole(this.model.get('jid'), args[0], 'occupant', args[1], undefined, this.onCommandError.bind(this));
  14578. break;
  14579. default:
  14580. this.sendChatRoomMessage(text);
  14581. break;
  14582. }
  14583. },
  14584. handleMUCMessage: function handleMUCMessage(stanza) {
  14585. /* Handler for all MUC messages sent to this chat room.
  14586. *
  14587. * Parameters:
  14588. * (XMLElement) stanza: The message stanza.
  14589. */
  14590. var configuration_changed = stanza.querySelector("status[code='104']");
  14591. var logging_enabled = stanza.querySelector("status[code='170']");
  14592. var logging_disabled = stanza.querySelector("status[code='171']");
  14593. var room_no_longer_anon = stanza.querySelector("status[code='172']");
  14594. var room_now_semi_anon = stanza.querySelector("status[code='173']");
  14595. var room_now_fully_anon = stanza.querySelector("status[code='173']");
  14596. if (configuration_changed || logging_enabled || logging_disabled || room_no_longer_anon || room_now_semi_anon || room_now_fully_anon) {
  14597. this.getRoomFeatures();
  14598. }
  14599. _.flow(this.showStatusMessages.bind(this), this.onChatRoomMessage.bind(this))(stanza);
  14600. return true;
  14601. },
  14602. getRoomJIDAndNick: function getRoomJIDAndNick(nick) {
  14603. /* Utility method to construct the JID for the current user
  14604. * as occupant of the room.
  14605. *
  14606. * This is the room JID, with the user's nick added at the
  14607. * end.
  14608. *
  14609. * For example: room@conference.example.org/nickname
  14610. */
  14611. if (nick) {
  14612. this.model.save({ 'nick': nick });
  14613. } else {
  14614. nick = this.model.get('nick');
  14615. }
  14616. var room = this.model.get('jid');
  14617. var node = Strophe.getNodeFromJid(room);
  14618. var domain = Strophe.getDomainFromJid(room);
  14619. return node + "@" + domain + (nick !== null ? "/" + nick : "");
  14620. },
  14621. registerHandlers: function registerHandlers() {
  14622. /* Register presence and message handlers for this chat
  14623. * room
  14624. */
  14625. var room_jid = this.model.get('jid');
  14626. this.removeHandlers();
  14627. this.presence_handler = _converse.connection.addHandler(this.onChatRoomPresence.bind(this), Strophe.NS.MUC, 'presence', null, null, room_jid, { 'ignoreNamespaceFragment': true, 'matchBareFromJid': true });
  14628. this.message_handler = _converse.connection.addHandler(this.handleMUCMessage.bind(this), null, 'message', 'groupchat', null, room_jid, { 'matchBareFromJid': true });
  14629. },
  14630. removeHandlers: function removeHandlers() {
  14631. /* Remove the presence and message handlers that were
  14632. * registered for this chat room.
  14633. */
  14634. if (this.message_handler) {
  14635. _converse.connection.deleteHandler(this.message_handler);
  14636. delete this.message_handler;
  14637. }
  14638. if (this.presence_handler) {
  14639. _converse.connection.deleteHandler(this.presence_handler);
  14640. delete this.presence_handler;
  14641. }
  14642. return this;
  14643. },
  14644. join: function join(nick, password) {
  14645. /* Join the chat room.
  14646. *
  14647. * Parameters:
  14648. * (String) nick: The user's nickname
  14649. * (String) password: Optional password, if required by
  14650. * the room.
  14651. */
  14652. nick = nick ? nick : this.model.get('nick');
  14653. if (!nick) {
  14654. return this.checkForReservedNick();
  14655. }
  14656. if (this.model.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
  14657. // We have restored a chat room from session storage,
  14658. // so we don't send out a presence stanza again.
  14659. return this;
  14660. }
  14661. var stanza = $pres({
  14662. 'from': _converse.connection.jid,
  14663. 'to': this.getRoomJIDAndNick(nick)
  14664. }).c("x", { 'xmlns': Strophe.NS.MUC }).c("history", { 'maxstanzas': _converse.muc_history_max_stanzas }).up();
  14665. if (password) {
  14666. stanza.cnode(Strophe.xmlElement("password", [], password));
  14667. }
  14668. this.model.save('connection_status', converse.ROOMSTATUS.CONNECTING);
  14669. _converse.connection.send(stanza);
  14670. return this;
  14671. },
  14672. sendUnavailablePresence: function sendUnavailablePresence(exit_msg) {
  14673. var presence = $pres({
  14674. type: "unavailable",
  14675. from: _converse.connection.jid,
  14676. to: this.getRoomJIDAndNick()
  14677. });
  14678. if (exit_msg !== null) {
  14679. presence.c("status", exit_msg);
  14680. }
  14681. _converse.connection.sendPresence(presence);
  14682. },
  14683. leave: function leave(exit_msg) {
  14684. /* Leave the chat room.
  14685. *
  14686. * Parameters:
  14687. * (String) exit_msg: Optional message to indicate your
  14688. * reason for leaving.
  14689. */
  14690. this.hide();
  14691. this.occupantsview.model.reset();
  14692. this.occupantsview.model.browserStorage._clear();
  14693. if (_converse.connection.connected) {
  14694. this.sendUnavailablePresence(exit_msg);
  14695. }
  14696. utils.safeSave(this.model, { 'connection_status': converse.ROOMSTATUS.DISCONNECTED });
  14697. this.removeHandlers();
  14698. _converse.ChatBoxView.prototype.close.apply(this, arguments);
  14699. },
  14700. renderConfigurationForm: function renderConfigurationForm(stanza) {
  14701. var _this5 = this;
  14702. /* Renders a form given an IQ stanza containing the current
  14703. * room configuration.
  14704. *
  14705. * Returns a promise which resolves once the user has
  14706. * either submitted the form, or canceled it.
  14707. *
  14708. * Parameters:
  14709. * (XMLElement) stanza: The IQ stanza containing the room
  14710. * config.
  14711. */
  14712. var $body = this.$('.chatroom-body');
  14713. $body.children().addClass('hidden');
  14714. // Remove any existing forms
  14715. $body.find('form.chatroom-form').remove();
  14716. $body.append(tpl_chatroom_form());
  14717. var $form = $body.find('form.chatroom-form');
  14718. var $fieldset = $form.children('fieldset:first');
  14719. var $stanza = $(stanza),
  14720. $fields = $stanza.find('field'),
  14721. title = $stanza.find('title').text(),
  14722. instructions = $stanza.find('instructions').text();
  14723. $fieldset.find('span.spinner').remove();
  14724. $fieldset.append($('<legend>').text(title));
  14725. if (instructions && instructions !== title) {
  14726. $fieldset.append($('<p class="instructions">').text(instructions));
  14727. }
  14728. _.each($fields, function (field) {
  14729. $fieldset.append(utils.xForm2webForm($(field), $stanza));
  14730. });
  14731. $form.append('<fieldset></fieldset>');
  14732. $fieldset = $form.children('fieldset:last');
  14733. $fieldset.append("<input type=\"submit\" class=\"pure-button button-primary\" value=\"" + __('Save') + "\"/>");
  14734. $fieldset.append("<input type=\"button\" class=\"pure-button button-cancel\" value=\"" + __('Cancel') + "\"/>");
  14735. $fieldset.find('input[type=button]').on('click', function (ev) {
  14736. ev.preventDefault();
  14737. _this5.cancelConfiguration();
  14738. });
  14739. $form.on('submit', function (ev) {
  14740. ev.preventDefault();
  14741. _this5.saveConfiguration(ev.target).then(_this5.getRoomFeatures.bind(_this5));
  14742. });
  14743. },
  14744. sendConfiguration: function sendConfiguration(config, onSuccess, onError) {
  14745. /* Send an IQ stanza with the room configuration.
  14746. *
  14747. * Parameters:
  14748. * (Array) config: The room configuration
  14749. * (Function) onSuccess: Callback upon succesful IQ response
  14750. * The first parameter passed in is IQ containing the
  14751. * room configuration.
  14752. * The second is the response IQ from the server.
  14753. * (Function) onError: Callback upon error IQ response
  14754. * The first parameter passed in is IQ containing the
  14755. * room configuration.
  14756. * The second is the response IQ from the server.
  14757. */
  14758. var iq = $iq({ to: this.model.get('jid'), type: "set" }).c("query", { xmlns: Strophe.NS.MUC_OWNER }).c("x", { xmlns: Strophe.NS.XFORM, type: "submit" });
  14759. _.each(config || [], function (node) {
  14760. iq.cnode(node).up();
  14761. });
  14762. onSuccess = _.isUndefined(onSuccess) ? _.noop : _.partial(onSuccess, iq.nodeTree);
  14763. onError = _.isUndefined(onError) ? _.noop : _.partial(onError, iq.nodeTree);
  14764. return _converse.connection.sendIQ(iq, onSuccess, onError);
  14765. },
  14766. saveConfiguration: function saveConfiguration(form) {
  14767. var _this6 = this;
  14768. /* Submit the room configuration form by sending an IQ
  14769. * stanza to the server.
  14770. *
  14771. * Returns a promise which resolves once the XMPP server
  14772. * has return a response IQ.
  14773. *
  14774. * Parameters:
  14775. * (HTMLElement) form: The configuration form DOM element.
  14776. */
  14777. return new Promise(function (resolve, reject) {
  14778. var $inputs = $(form).find(':input:not([type=button]):not([type=submit])'),
  14779. configArray = [];
  14780. $inputs.each(function () {
  14781. configArray.push(utils.webForm2xForm(this));
  14782. });
  14783. _this6.sendConfiguration(configArray, resolve, reject);
  14784. _this6.$el.find('div.chatroom-form-container').hide(function (el) {
  14785. $(el).remove();
  14786. _this6.renderAfterTransition();
  14787. });
  14788. });
  14789. },
  14790. autoConfigureChatRoom: function autoConfigureChatRoom() {
  14791. var _this7 = this;
  14792. /* Automatically configure room based on the
  14793. * 'roomconfig' data on this view's model.
  14794. *
  14795. * Returns a promise which resolves once a response IQ has
  14796. * been received.
  14797. *
  14798. * Parameters:
  14799. * (XMLElement) stanza: IQ stanza from the server,
  14800. * containing the configuration.
  14801. */
  14802. var that = this;
  14803. return new Promise(function (resolve, reject) {
  14804. _this7.fetchRoomConfiguration().then(function (stanza) {
  14805. var configArray = [],
  14806. fields = stanza.querySelectorAll('field'),
  14807. config = that.model.get('roomconfig');
  14808. var count = fields.length;
  14809. _.each(fields, function (field) {
  14810. var fieldname = field.getAttribute('var').replace('muc#roomconfig_', ''),
  14811. type = field.getAttribute('type');
  14812. var value = void 0;
  14813. if (fieldname in config) {
  14814. switch (type) {
  14815. case 'boolean':
  14816. value = config[fieldname] ? 1 : 0;
  14817. break;
  14818. case 'list-multi':
  14819. // TODO: we don't yet handle "list-multi" types
  14820. value = field.innerHTML;
  14821. break;
  14822. default:
  14823. value = config[fieldname];
  14824. }
  14825. field.innerHTML = $build('value').t(value);
  14826. }
  14827. configArray.push(field);
  14828. if (! --count) {
  14829. that.sendConfiguration(configArray, resolve, reject);
  14830. }
  14831. });
  14832. });
  14833. });
  14834. },
  14835. cancelConfiguration: function cancelConfiguration() {
  14836. var _this8 = this;
  14837. /* Remove the configuration form without submitting and
  14838. * return to the chat view.
  14839. */
  14840. this.$el.find('div.chatroom-form-container').hide(function (el) {
  14841. $(el).remove();
  14842. _this8.renderAfterTransition();
  14843. });
  14844. },
  14845. fetchRoomConfiguration: function fetchRoomConfiguration(handler) {
  14846. var _this9 = this,
  14847. _arguments = arguments;
  14848. /* Send an IQ stanza to fetch the room configuration data.
  14849. * Returns a promise which resolves once the response IQ
  14850. * has been received.
  14851. *
  14852. * Parameters:
  14853. * (Function) handler: The handler for the response IQ
  14854. */
  14855. return new Promise(function (resolve, reject) {
  14856. _converse.connection.sendIQ($iq({
  14857. 'to': _this9.model.get('jid'),
  14858. 'type': "get"
  14859. }).c("query", { xmlns: Strophe.NS.MUC_OWNER }), function (iq) {
  14860. if (handler) {
  14861. handler.apply(_this9, _arguments);
  14862. }
  14863. resolve(iq);
  14864. }, reject // errback
  14865. );
  14866. });
  14867. },
  14868. parseRoomFeatures: function parseRoomFeatures(iq) {
  14869. /* See http://xmpp.org/extensions/xep-0045.html#disco-roominfo
  14870. *
  14871. * <identity
  14872. * category='conference'
  14873. * name='A Dark Cave'
  14874. * type='text'/>
  14875. * <feature var='http://jabber.org/protocol/muc'/>
  14876. * <feature var='muc_passwordprotected'/>
  14877. * <feature var='muc_hidden'/>
  14878. * <feature var='muc_temporary'/>
  14879. * <feature var='muc_open'/>
  14880. * <feature var='muc_unmoderated'/>
  14881. * <feature var='muc_nonanonymous'/>
  14882. * <feature var='urn:xmpp:mam:0'/>
  14883. */
  14884. var features = {
  14885. 'features_fetched': true,
  14886. 'name': iq.querySelector('identity').getAttribute('name')
  14887. };
  14888. _.each(iq.querySelectorAll('feature'), function (field) {
  14889. var fieldname = field.getAttribute('var');
  14890. if (!fieldname.startsWith('muc_')) {
  14891. if (fieldname === Strophe.NS.MAM) {
  14892. features.mam_enabled = true;
  14893. }
  14894. return;
  14895. }
  14896. features[fieldname.replace('muc_', '')] = true;
  14897. });
  14898. var desc_field = iq.querySelector('field[var="muc#roominfo_description"] value');
  14899. if (!_.isNull(desc_field)) {
  14900. features.description = desc_field.textContent;
  14901. }
  14902. this.model.save(features);
  14903. },
  14904. getRoomFeatures: function getRoomFeatures() {
  14905. var _this10 = this;
  14906. /* Fetch the room disco info, parse it and then
  14907. * save it on the Backbone.Model of this chat rooms.
  14908. */
  14909. return new Promise(function (resolve, reject) {
  14910. _converse.connection.disco.info(_this10.model.get('jid'), null, _.flow(_this10.parseRoomFeatures.bind(_this10), resolve), function () {
  14911. reject(new Error("Could not parse the room features"));
  14912. }, 5000);
  14913. });
  14914. },
  14915. getAndRenderConfigurationForm: function getAndRenderConfigurationForm(ev) {
  14916. /* Start the process of configuring a chat room, either by
  14917. * rendering a configuration form, or by auto-configuring
  14918. * based on the "roomconfig" data stored on the
  14919. * Backbone.Model.
  14920. *
  14921. * Stores the new configuration on the Backbone.Model once
  14922. * completed.
  14923. *
  14924. * Paremeters:
  14925. * (Event) ev: DOM event that might be passed in if this
  14926. * method is called due to a user action. In this
  14927. * case, auto-configure won't happen, regardless of
  14928. * the settings.
  14929. */
  14930. this.showSpinner();
  14931. this.fetchRoomConfiguration().then(this.renderConfigurationForm.bind(this));
  14932. },
  14933. submitNickname: function submitNickname(ev) {
  14934. /* Get the nickname value from the form and then join the
  14935. * chat room with it.
  14936. */
  14937. ev.preventDefault();
  14938. var nick_el = ev.target.nick;
  14939. var nick = nick_el.value;
  14940. if (!nick) {
  14941. nick_el.classList.add('error');
  14942. return;
  14943. } else {
  14944. nick_el.classList.remove('error');
  14945. }
  14946. this.$el.find('.chatroom-form-container').replaceWith(tpl_spinner);
  14947. this.join(nick);
  14948. },
  14949. checkForReservedNick: function checkForReservedNick() {
  14950. /* User service-discovery to ask the XMPP server whether
  14951. * this user has a reserved nickname for this room.
  14952. * If so, we'll use that, otherwise we render the nickname
  14953. * form.
  14954. */
  14955. this.showSpinner();
  14956. _converse.connection.sendIQ($iq({
  14957. 'to': this.model.get('jid'),
  14958. 'from': _converse.connection.jid,
  14959. 'type': "get"
  14960. }).c("query", {
  14961. 'xmlns': Strophe.NS.DISCO_INFO,
  14962. 'node': 'x-roomuser-item'
  14963. }), this.onNickNameFound.bind(this), this.onNickNameNotFound.bind(this));
  14964. return this;
  14965. },
  14966. onNickNameFound: function onNickNameFound(iq) {
  14967. /* We've received an IQ response from the server which
  14968. * might contain the user's reserved nickname.
  14969. * If no nickname is found we either render a form for
  14970. * them to specify one, or we try to join the room with the
  14971. * node of the user's JID.
  14972. *
  14973. * Parameters:
  14974. * (XMLElement) iq: The received IQ stanza
  14975. */
  14976. var nick = $(iq).find('query[node="x-roomuser-item"] identity').attr('name');
  14977. if (!nick) {
  14978. this.onNickNameNotFound();
  14979. } else {
  14980. this.join(nick);
  14981. }
  14982. },
  14983. onNickNameNotFound: function onNickNameNotFound(message) {
  14984. if (_converse.muc_nickname_from_jid) {
  14985. // We try to enter the room with the node part of
  14986. // the user's JID.
  14987. this.join(Strophe.unescapeNode(Strophe.getNodeFromJid(_converse.bare_jid)));
  14988. } else {
  14989. this.renderNicknameForm(message);
  14990. }
  14991. },
  14992. getDefaultNickName: function getDefaultNickName() {
  14993. /* The default nickname (used when muc_nickname_from_jid is true)
  14994. * is the node part of the user's JID.
  14995. * We put this in a separate method so that it can be
  14996. * overridden by plugins.
  14997. */
  14998. return Strophe.unescapeNode(Strophe.getNodeFromJid(_converse.bare_jid));
  14999. },
  15000. onNicknameClash: function onNicknameClash(presence) {
  15001. /* When the nickname is already taken, we either render a
  15002. * form for the user to choose a new nickname, or we
  15003. * try to make the nickname unique by adding an integer to
  15004. * it. So john will become john-2, and then john-3 and so on.
  15005. *
  15006. * Which option is take depends on the value of
  15007. * muc_nickname_from_jid.
  15008. */
  15009. if (_converse.muc_nickname_from_jid) {
  15010. var nick = presence.getAttribute('from').split('/')[1];
  15011. if (nick === this.getDefaultNickName()) {
  15012. this.join(nick + '-2');
  15013. } else {
  15014. var del = nick.lastIndexOf("-");
  15015. var num = nick.substring(del + 1, nick.length);
  15016. this.join(nick.substring(0, del + 1) + String(Number(num) + 1));
  15017. }
  15018. } else {
  15019. this.renderNicknameForm(__("The nickname you chose is reserved or " + "currently in use, please choose a different one."));
  15020. }
  15021. },
  15022. renderNicknameForm: function renderNicknameForm(message) {
  15023. /* Render a form which allows the user to choose their
  15024. * nickname.
  15025. */
  15026. this.$('.chatroom-body').children().addClass('hidden');
  15027. this.$('span.centered.spinner').remove();
  15028. if (!_.isString(message)) {
  15029. message = '';
  15030. }
  15031. this.$('.chatroom-body').append(tpl_chatroom_nickname_form({
  15032. heading: __('Please choose your nickname'),
  15033. label_nickname: __('Nickname'),
  15034. label_join: __('Enter room'),
  15035. validation_message: message
  15036. }));
  15037. this.model.save('connection_status', converse.ROOMSTATUS.NICKNAME_REQUIRED);
  15038. this.$('.chatroom-form').on('submit', this.submitNickname.bind(this));
  15039. },
  15040. submitPassword: function submitPassword(ev) {
  15041. ev.preventDefault();
  15042. var password = this.$el.find('.chatroom-form').find('input[type=password]').val();
  15043. this.$el.find('.chatroom-form-container').replaceWith(tpl_spinner);
  15044. this.join(this.model.get('nick'), password);
  15045. },
  15046. renderPasswordForm: function renderPasswordForm() {
  15047. this.$('.chatroom-body').children().addClass('hidden');
  15048. this.$('span.centered.spinner').remove();
  15049. this.$('.chatroom-body').append(tpl_chatroom_password_form({
  15050. heading: __('This chatroom requires a password'),
  15051. label_password: __('Password: '),
  15052. label_submit: __('Submit')
  15053. }));
  15054. this.model.save('connection_status', converse.ROOMSTATUS.PASSWORD_REQUIRED);
  15055. this.$('.chatroom-form').on('submit', this.submitPassword.bind(this));
  15056. },
  15057. showDisconnectMessage: function showDisconnectMessage(msg) {
  15058. this.$('.chat-area').addClass('hidden');
  15059. this.$('.occupants').addClass('hidden');
  15060. this.$('span.centered.spinner').remove();
  15061. this.$('.chatroom-body').append(tpl_chatroom_disconnect({
  15062. 'disconnect_message': msg
  15063. }));
  15064. },
  15065. getMessageFromStatus: function getMessageFromStatus(stat, stanza, is_self) {
  15066. /* Parameters:
  15067. * (XMLElement) stat: A <status> element.
  15068. * (Boolean) is_self: Whether the element refers to the
  15069. * current user.
  15070. * (XMLElement) stanza: The original stanza received.
  15071. */
  15072. var code = stat.getAttribute('code');
  15073. if (code === '110') {
  15074. return;
  15075. }
  15076. if (code in _converse.muc.info_messages) {
  15077. return _converse.muc.info_messages[code];
  15078. }
  15079. var nick = void 0;
  15080. if (!is_self) {
  15081. if (code in _converse.muc.action_info_messages) {
  15082. nick = Strophe.getResourceFromJid(stanza.getAttribute('from'));
  15083. return __(_converse.muc.action_info_messages[code], nick);
  15084. }
  15085. } else if (code in _converse.muc.new_nickname_messages) {
  15086. if (is_self && code === "210") {
  15087. nick = Strophe.getResourceFromJid(stanza.getAttribute('from'));
  15088. } else if (is_self && code === "303") {
  15089. nick = stanza.querySelector('x item').getAttribute('nick');
  15090. }
  15091. return __(_converse.muc.new_nickname_messages[code], nick);
  15092. }
  15093. return;
  15094. },
  15095. saveAffiliationAndRole: function saveAffiliationAndRole(pres) {
  15096. /* Parse the presence stanza for the current user's
  15097. * affiliation.
  15098. *
  15099. * Parameters:
  15100. * (XMLElement) pres: A <presence> stanza.
  15101. */
  15102. var item = sizzle("x[xmlns=\"" + Strophe.NS.MUC_USER + "\"] item", pres).pop();
  15103. var is_self = pres.querySelector("status[code='110']");
  15104. if (is_self && !_.isNil(item)) {
  15105. var affiliation = item.getAttribute('affiliation');
  15106. var role = item.getAttribute('role');
  15107. if (affiliation) {
  15108. this.model.save({ 'affiliation': affiliation });
  15109. }
  15110. if (role) {
  15111. this.model.save({ 'role': role });
  15112. }
  15113. }
  15114. },
  15115. parseXUserElement: function parseXUserElement(x, stanza, is_self) {
  15116. /* Parse the passed-in <x xmlns='http://jabber.org/protocol/muc#user'>
  15117. * element and construct a map containing relevant
  15118. * information.
  15119. */
  15120. // 1. Get notification messages based on the <status> elements.
  15121. var statuses = x.querySelectorAll('status');
  15122. var mapper = _.partial(this.getMessageFromStatus, _, stanza, is_self);
  15123. var notification = {};
  15124. var messages = _.reject(_.map(statuses, mapper), _.isUndefined);
  15125. if (messages.length) {
  15126. notification.messages = messages;
  15127. }
  15128. // 2. Get disconnection messages based on the <status> elements
  15129. var codes = _.invokeMap(statuses, Element.prototype.getAttribute, 'code');
  15130. var disconnection_codes = _.intersection(codes, _.keys(_converse.muc.disconnect_messages));
  15131. var disconnected = is_self && disconnection_codes.length > 0;
  15132. if (disconnected) {
  15133. notification.disconnected = true;
  15134. notification.disconnection_message = _converse.muc.disconnect_messages[disconnection_codes[0]];
  15135. }
  15136. // 3. Find the reason and actor from the <item> element
  15137. var item = x.querySelector('item');
  15138. // By using querySelector above, we assume here there is
  15139. // one <item> per <x xmlns='http://jabber.org/protocol/muc#user'>
  15140. // element. This appears to be a safe assumption, since
  15141. // each <x/> element pertains to a single user.
  15142. if (!_.isNull(item)) {
  15143. var reason = item.querySelector('reason');
  15144. if (reason) {
  15145. notification.reason = reason ? reason.textContent : undefined;
  15146. }
  15147. var actor = item.querySelector('actor');
  15148. if (actor) {
  15149. notification.actor = actor ? actor.getAttribute('nick') : undefined;
  15150. }
  15151. }
  15152. return notification;
  15153. },
  15154. displayNotificationsforUser: function displayNotificationsforUser(notification) {
  15155. var _this11 = this;
  15156. /* Given the notification object generated by
  15157. * parseXUserElement, display any relevant messages and
  15158. * information to the user.
  15159. */
  15160. if (notification.disconnected) {
  15161. this.showDisconnectMessage(notification.disconnection_message);
  15162. if (notification.actor) {
  15163. this.showDisconnectMessage(__(___('This action was done by %1$s.'), notification.actor));
  15164. }
  15165. if (notification.reason) {
  15166. this.showDisconnectMessage(__(___('The reason given is: "%1$s".'), notification.reason));
  15167. }
  15168. this.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
  15169. return;
  15170. }
  15171. _.each(notification.messages, function (message) {
  15172. _this11.$content.append(tpl_info({ 'message': message }));
  15173. });
  15174. if (notification.reason) {
  15175. this.showStatusNotification(__("The reason given is: \"" + notification.reason + "\""), true);
  15176. }
  15177. if (notification.messages.length) {
  15178. this.scrollDown();
  15179. }
  15180. },
  15181. getJoinLeaveMessages: function getJoinLeaveMessages(stanza) {
  15182. /* Parse the given stanza and return notification messages
  15183. * for join/leave events.
  15184. */
  15185. // XXX: some mangling required to make the returned
  15186. // result look like the structure returned by
  15187. // parseXUserElement. Not nice...
  15188. var nick = Strophe.getResourceFromJid(stanza.getAttribute('from'));
  15189. var stat = stanza.querySelector('status');
  15190. if (stanza.getAttribute('type') === 'unavailable') {
  15191. if (!_.isNull(stat) && stat.textContent) {
  15192. return [{ 'messages': [__(nick + ' has left the room. "' + stat.textContent + '"')] }];
  15193. } else {
  15194. return [{ 'messages': [__(nick + ' has left the room')] }];
  15195. }
  15196. }
  15197. if (!this.occupantsview.model.find({ 'nick': nick })) {
  15198. // Only show join message if we don't already have the
  15199. // occupant model. Doing so avoids showing duplicate
  15200. // join messages.
  15201. if (!_.isNull(stat) && stat.textContent) {
  15202. return [{ 'messages': [__(nick + ' has joined the room. "' + stat.textContent + '"')] }];
  15203. } else {
  15204. return [{ 'messages': [__(nick + ' has joined the room.')] }];
  15205. }
  15206. }
  15207. },
  15208. showStatusMessages: function showStatusMessages(stanza) {
  15209. /* Check for status codes and communicate their purpose to the user.
  15210. * See: http://xmpp.org/registrar/mucstatus.html
  15211. *
  15212. * Parameters:
  15213. * (XMLElement) stanza: The message or presence stanza
  15214. * containing the status codes.
  15215. */
  15216. var elements = sizzle("x[xmlns=\"" + Strophe.NS.MUC_USER + "\"]", stanza);
  15217. var is_self = stanza.querySelectorAll("status[code='110']").length;
  15218. var iteratee = _.partial(this.parseXUserElement.bind(this), _, stanza, is_self);
  15219. var notifications = _.reject(_.map(elements, iteratee), _.isEmpty);
  15220. if (_.isEmpty(notifications) && _converse.muc_show_join_leave && stanza.nodeName === 'presence' && this.model.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
  15221. notifications = this.getJoinLeaveMessages(stanza);
  15222. }
  15223. _.each(notifications, this.displayNotificationsforUser.bind(this));
  15224. return stanza;
  15225. },
  15226. showErrorMessage: function showErrorMessage(presence) {
  15227. // We didn't enter the room, so we must remove it from the MUC add-on
  15228. var error = presence.querySelector('error');
  15229. if (error.getAttribute('type') === 'auth') {
  15230. if (!_.isNull(error.querySelector('not-authorized'))) {
  15231. this.renderPasswordForm();
  15232. } else if (!_.isNull(error.querySelector('registration-required'))) {
  15233. this.showDisconnectMessage(__('You are not on the member list of this room.'));
  15234. } else if (!_.isNull(error.querySelector('forbidden'))) {
  15235. this.showDisconnectMessage(__('You have been banned from this room.'));
  15236. }
  15237. } else if (error.getAttribute('type') === 'modify') {
  15238. if (!_.isNull(error.querySelector('jid-malformed'))) {
  15239. this.showDisconnectMessage(__('No nickname was specified.'));
  15240. }
  15241. } else if (error.getAttribute('type') === 'cancel') {
  15242. if (!_.isNull(error.querySelector('not-allowed'))) {
  15243. this.showDisconnectMessage(__('You are not allowed to create new rooms.'));
  15244. } else if (!_.isNull(error.querySelector('not-acceptable'))) {
  15245. this.showDisconnectMessage(__("Your nickname doesn't conform to this room's policies."));
  15246. } else if (!_.isNull(error.querySelector('conflict'))) {
  15247. this.onNicknameClash(presence);
  15248. } else if (!_.isNull(error.querySelector('item-not-found'))) {
  15249. this.showDisconnectMessage(__("This room does not (yet) exist."));
  15250. } else if (!_.isNull(error.querySelector('service-unavailable'))) {
  15251. this.showDisconnectMessage(__("This room has reached its maximum number of occupants."));
  15252. }
  15253. }
  15254. },
  15255. renderAfterTransition: function renderAfterTransition() {
  15256. /* Rerender the room after some kind of transition. For
  15257. * example after the spinner has been removed or after a
  15258. * form has been submitted and removed.
  15259. */
  15260. if (this.model.get('connection_status') == converse.ROOMSTATUS.NICKNAME_REQUIRED) {
  15261. this.renderNicknameForm();
  15262. } else if (this.model.get('connection_status') == converse.ROOMSTATUS.PASSWORD_REQUIRED) {
  15263. this.renderPasswordForm();
  15264. } else {
  15265. this.$el.find('.chat-area').removeClass('hidden');
  15266. this.$el.find('.occupants').removeClass('hidden');
  15267. this.occupantsview.setOccupantsHeight();
  15268. this.scrollDown();
  15269. }
  15270. },
  15271. showSpinner: function showSpinner() {
  15272. this.$('.chatroom-body').children().addClass('hidden');
  15273. this.$el.find('.chatroom-body').prepend(tpl_spinner);
  15274. },
  15275. hideSpinner: function hideSpinner() {
  15276. /* Check if the spinner is being shown and if so, hide it.
  15277. * Also make sure then that the chat area and occupants
  15278. * list are both visible.
  15279. */
  15280. var spinner = this.el.querySelector('.spinner');
  15281. if (!_.isNull(spinner)) {
  15282. spinner.parentNode.removeChild(spinner);
  15283. this.renderAfterTransition();
  15284. }
  15285. return this;
  15286. },
  15287. onOwnChatRoomPresence: function onOwnChatRoomPresence(pres) {
  15288. /* Handles a received presence relating to the current
  15289. * user.
  15290. *
  15291. * For locked rooms (which are by definition "new"), the
  15292. * room will either be auto-configured or created instantly
  15293. * (with default config) or a configuration room will be
  15294. * rendered.
  15295. *
  15296. * If the room is not locked, then the room will be
  15297. * auto-configured only if applicable and if the current
  15298. * user is the room's owner.
  15299. *
  15300. * Parameters:
  15301. * (XMLElement) pres: The stanza
  15302. */
  15303. this.saveAffiliationAndRole(pres);
  15304. var locked_room = pres.querySelector("status[code='201']");
  15305. if (locked_room) {
  15306. if (this.model.get('auto_configure')) {
  15307. this.autoConfigureChatRoom().then(this.getRoomFeatures.bind(this));
  15308. } else if (_converse.muc_instant_rooms) {
  15309. // Accept default configuration
  15310. this.saveConfiguration().then(this.getRoomFeatures.bind(this));
  15311. } else {
  15312. this.getAndRenderConfigurationForm();
  15313. return; // We haven't yet entered the room, so bail here.
  15314. }
  15315. } else if (!this.model.get('features_fetched')) {
  15316. // The features for this room weren't fetched.
  15317. // That must mean it's a new room without locking
  15318. // (in which case Prosody doesn't send a 201 status),
  15319. // otherwise the features would have been fetched in
  15320. // the "initialize" method already.
  15321. if (this.model.get('affiliation') === 'owner' && this.model.get('auto_configure')) {
  15322. this.autoConfigureChatRoom().then(this.getRoomFeatures.bind(this));
  15323. } else {
  15324. this.getRoomFeatures();
  15325. }
  15326. }
  15327. this.model.save('connection_status', converse.ROOMSTATUS.ENTERED);
  15328. },
  15329. onChatRoomPresence: function onChatRoomPresence(pres) {
  15330. /* Handles all MUC presence stanzas.
  15331. *
  15332. * Parameters:
  15333. * (XMLElement) pres: The stanza
  15334. */
  15335. if (pres.getAttribute('type') === 'error') {
  15336. this.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
  15337. this.showErrorMessage(pres);
  15338. return true;
  15339. }
  15340. var is_self = pres.querySelector("status[code='110']");
  15341. if (is_self && pres.getAttribute('type') !== 'unavailable') {
  15342. this.onOwnChatRoomPresence(pres);
  15343. }
  15344. this.hideSpinner().showStatusMessages(pres);
  15345. // This must be called after showStatusMessages so that
  15346. // "join" messages are correctly shown.
  15347. this.occupantsview.updateOccupantsOnPresence(pres);
  15348. if (this.model.get('role') !== 'none' && this.model.get('connection_status') === converse.ROOMSTATUS.CONNECTING) {
  15349. this.model.save('connection_status', converse.ROOMSTATUS.CONNECTED);
  15350. }
  15351. return true;
  15352. },
  15353. setChatRoomSubject: function setChatRoomSubject(sender, subject) {
  15354. // For translators: the %1$s and %2$s parts will get
  15355. // replaced by the user and topic text respectively
  15356. // Example: Topic set by JC Brand to: Hello World!
  15357. this.$content.append(tpl_info({ 'message': __('Topic set by %1$s to: %2$s', sender, subject) }));
  15358. this.scrollDown();
  15359. },
  15360. isDuplicateBasedOnTime: function isDuplicateBasedOnTime(message) {
  15361. /* Checks whether a received messages is actually a
  15362. * duplicate based on whether it has a "ts" attribute
  15363. * with a unix timestamp.
  15364. *
  15365. * This is used for better integration with Slack's XMPP
  15366. * gateway, which doesn't use message IDs but instead the
  15367. * aforementioned "ts" attributes.
  15368. */
  15369. var entity = _converse.disco_entities.get(_converse.domain);
  15370. if (entity.identities.where({ 'name': "Slack-XMPP" })) {
  15371. var ts = message.getAttribute('ts');
  15372. if (_.isNull(ts)) {
  15373. return false;
  15374. } else {
  15375. return this.model.messages.where({
  15376. 'sender': 'me',
  15377. 'message': this.model.getMessageBody(message)
  15378. }).filter(function (msg) {
  15379. return Math.abs(moment(msg.get('time')).diff(moment.unix(ts))) < 5000;
  15380. }).length > 0;
  15381. }
  15382. }
  15383. return false;
  15384. },
  15385. isDuplicate: function isDuplicate(message) {
  15386. var msgid = message.getAttribute('id'),
  15387. jid = message.getAttribute('from'),
  15388. resource = Strophe.getResourceFromJid(jid),
  15389. sender = resource && Strophe.unescapeNode(resource) || '';
  15390. if (msgid) {
  15391. return this.model.messages.filter(
  15392. // Some bots (like HAL in the prosody chatroom)
  15393. // respond to commands with the same ID as the
  15394. // original message. So we also check the sender.
  15395. function (msg) {
  15396. return msg.get('msgid') === msgid && msg.get('fullname') === sender;
  15397. }).length > 0;
  15398. }
  15399. return this.isDuplicateBasedOnTime(message);
  15400. },
  15401. onChatRoomMessage: function onChatRoomMessage(message) {
  15402. /* Given a <message> stanza, create a message
  15403. * Backbone.Model if appropriate.
  15404. *
  15405. * Parameters:
  15406. * (XMLElement) msg: The received message stanza
  15407. */
  15408. var original_stanza = message,
  15409. forwarded = message.querySelector('forwarded');
  15410. var delay = void 0;
  15411. if (!_.isNull(forwarded)) {
  15412. message = forwarded.querySelector('message');
  15413. delay = forwarded.querySelector('delay');
  15414. }
  15415. var jid = message.getAttribute('from'),
  15416. resource = Strophe.getResourceFromJid(jid),
  15417. sender = resource && Strophe.unescapeNode(resource) || '',
  15418. subject = _.propertyOf(message.querySelector('subject'))('textContent');
  15419. if (this.isDuplicate(message)) {
  15420. return true;
  15421. }
  15422. if (subject) {
  15423. this.setChatRoomSubject(sender, subject);
  15424. }
  15425. if (sender === '') {
  15426. return true;
  15427. }
  15428. this.model.incrementUnreadMsgCounter(original_stanza);
  15429. this.model.createMessage(message, delay, original_stanza);
  15430. if (sender !== this.model.get('nick')) {
  15431. // We only emit an event if it's not our own message
  15432. _converse.emit('message', { 'stanza': original_stanza, 'chatbox': this.model });
  15433. }
  15434. return true;
  15435. }
  15436. });
  15437. _converse.ChatRoomOccupant = Backbone.Model.extend({
  15438. initialize: function initialize(attributes) {
  15439. this.set(_.extend({
  15440. 'id': _converse.connection.getUniqueId()
  15441. }, attributes));
  15442. }
  15443. });
  15444. _converse.ChatRoomOccupantView = Backbone.View.extend({
  15445. tagName: 'li',
  15446. initialize: function initialize() {
  15447. this.model.on('change', this.render, this);
  15448. this.model.on('destroy', this.destroy, this);
  15449. },
  15450. render: function render() {
  15451. var show = this.model.get('show') || 'online';
  15452. var new_el = tpl_occupant(_.extend({ 'jid': '',
  15453. 'show': show,
  15454. 'hint_show': _converse.PRETTY_CHAT_STATUS[show],
  15455. 'hint_occupant': __("Click to mention " + this.model.get('nick') + " in your message."),
  15456. 'desc_moderator': __('This user is a moderator.'),
  15457. 'desc_occupant': __('This user can send messages in this room.'),
  15458. 'desc_visitor': __('This user can NOT send messages in this room.')
  15459. }, this.model.toJSON()));
  15460. var $parents = this.$el.parents();
  15461. if ($parents.length) {
  15462. this.$el.replaceWith(new_el);
  15463. this.setElement($parents.first().children("#" + this.model.get('id')), true);
  15464. this.delegateEvents();
  15465. } else {
  15466. this.$el.replaceWith(new_el);
  15467. this.setElement(new_el, true);
  15468. }
  15469. return this;
  15470. },
  15471. destroy: function destroy() {
  15472. this.$el.remove();
  15473. }
  15474. });
  15475. _converse.ChatRoomOccupants = Backbone.Collection.extend({
  15476. model: _converse.ChatRoomOccupant
  15477. });
  15478. _converse.ChatRoomOccupantsView = Backbone.Overview.extend({
  15479. tagName: 'div',
  15480. className: 'occupants',
  15481. initialize: function initialize() {
  15482. this.model.on("add", this.onOccupantAdded, this);
  15483. this.chatroomview = this.model.chatroomview;
  15484. this.chatroomview.model.on('change:open', this.renderInviteWidget, this);
  15485. this.chatroomview.model.on('change:affiliation', this.renderInviteWidget, this);
  15486. this.chatroomview.model.on('change:hidden', this.onFeatureChanged, this);
  15487. this.chatroomview.model.on('change:mam_enabled', this.onFeatureChanged, this);
  15488. this.chatroomview.model.on('change:membersonly', this.onFeatureChanged, this);
  15489. this.chatroomview.model.on('change:moderated', this.onFeatureChanged, this);
  15490. this.chatroomview.model.on('change:nonanonymous', this.onFeatureChanged, this);
  15491. this.chatroomview.model.on('change:open', this.onFeatureChanged, this);
  15492. this.chatroomview.model.on('change:passwordprotected', this.onFeatureChanged, this);
  15493. this.chatroomview.model.on('change:persistent', this.onFeatureChanged, this);
  15494. this.chatroomview.model.on('change:public', this.onFeatureChanged, this);
  15495. this.chatroomview.model.on('change:semianonymous', this.onFeatureChanged, this);
  15496. this.chatroomview.model.on('change:temporary', this.onFeatureChanged, this);
  15497. this.chatroomview.model.on('change:unmoderated', this.onFeatureChanged, this);
  15498. this.chatroomview.model.on('change:unsecured', this.onFeatureChanged, this);
  15499. },
  15500. render: function render() {
  15501. this.el.innerHTML = tpl_chatroom_sidebar(_.extend(this.chatroomview.model.toJSON(), {
  15502. 'allow_muc_invitations': _converse.allow_muc_invitations,
  15503. 'label_occupants': __('Occupants')
  15504. }));
  15505. if (_converse.allow_muc_invitations) {
  15506. _converse.api.waitUntil('rosterContactsFetched').then(this.renderInviteWidget.bind(this));
  15507. }
  15508. return this.renderRoomFeatures();
  15509. },
  15510. renderInviteWidget: function renderInviteWidget() {
  15511. var form = this.el.querySelector('form.room-invite');
  15512. if (this.shouldInviteWidgetBeShown()) {
  15513. if (_.isNull(form)) {
  15514. var heading = this.el.querySelector('.occupants-heading');
  15515. form = tpl_chatroom_invite({
  15516. 'error_message': null,
  15517. 'label_invitation': __('Invite')
  15518. });
  15519. heading.insertAdjacentHTML('afterend', form);
  15520. this.initInviteWidget();
  15521. }
  15522. } else {
  15523. if (!_.isNull(form)) {
  15524. form.remove();
  15525. }
  15526. }
  15527. return this;
  15528. },
  15529. renderRoomFeatures: function renderRoomFeatures() {
  15530. var picks = _.pick(this.chatroomview.model.attributes, ROOM_FEATURES),
  15531. iteratee = function iteratee(a, v) {
  15532. return a || v;
  15533. },
  15534. el = this.el.querySelector('.chatroom-features');
  15535. el.innerHTML = tpl_chatroom_features(_.extend(this.chatroomview.model.toJSON(), {
  15536. 'has_features': _.reduce(_.values(picks), iteratee),
  15537. 'label_features': __('Features'),
  15538. 'label_hidden': __('Hidden'),
  15539. 'label_mam_enabled': __('Message archiving'),
  15540. 'label_membersonly': __('Members only'),
  15541. 'label_moderated': __('Moderated'),
  15542. 'label_nonanonymous': __('Non-anonymous'),
  15543. 'label_open': __('Open'),
  15544. 'label_passwordprotected': __('Password protected'),
  15545. 'label_persistent': __('Persistent'),
  15546. 'label_public': __('Public'),
  15547. 'label_semianonymous': __('Semi-anonymous'),
  15548. 'label_temporary': __('Temporary'),
  15549. 'label_unmoderated': __('Unmoderated'),
  15550. 'label_unsecured': __('Unsecured'),
  15551. 'tt_hidden': __('This room is not publicly searchable'),
  15552. 'tt_mam_enabled': __('Messages are archived on the server'),
  15553. 'tt_membersonly': __('This room is restricted to members only'),
  15554. 'tt_moderated': __('This room is being moderated'),
  15555. 'tt_nonanonymous': __('All other room occupants can see your XMPP username'),
  15556. 'tt_open': __('Anyone can join this room'),
  15557. 'tt_passwordprotected': __('This room requires a password before entry'),
  15558. 'tt_persistent': __('This room persists even if it\'s unoccupied'),
  15559. 'tt_public': __('This room is publicly searchable'),
  15560. 'tt_semianonymous': __('Only moderators can see your XMPP username'),
  15561. 'tt_temporary': __('This room will disappear once the last person leaves'),
  15562. 'tt_unmoderated': __('This room is not being moderated'),
  15563. 'tt_unsecured': __('This room does not require a password upon entry')
  15564. }));
  15565. this.setOccupantsHeight();
  15566. return this;
  15567. },
  15568. onFeatureChanged: function onFeatureChanged(model) {
  15569. /* When a feature has been changed, it's logical opposite
  15570. * must be set to the opposite value.
  15571. *
  15572. * So for example, if "temporary" was set to "false", then
  15573. * "persistent" will be set to "true" in this method.
  15574. *
  15575. * Additionally a debounced render method is called to make
  15576. * sure the features widget gets updated.
  15577. */
  15578. if (_.isUndefined(this.debouncedRenderRoomFeatures)) {
  15579. this.debouncedRenderRoomFeatures = _.debounce(this.renderRoomFeatures, 100, { 'leading': false });
  15580. }
  15581. var changed_features = {};
  15582. _.each(_.keys(model.changed), function (k) {
  15583. if (!_.isNil(ROOM_FEATURES_MAP[k])) {
  15584. changed_features[ROOM_FEATURES_MAP[k]] = !model.changed[k];
  15585. }
  15586. });
  15587. this.chatroomview.model.save(changed_features, { 'silent': true });
  15588. this.debouncedRenderRoomFeatures();
  15589. },
  15590. setOccupantsHeight: function setOccupantsHeight() {
  15591. var el = this.el.querySelector('.chatroom-features');
  15592. this.el.querySelector('.occupant-list').style.cssText = "height: calc(100% - " + el.offsetHeight + "px - 5em);";
  15593. },
  15594. onOccupantAdded: function onOccupantAdded(item) {
  15595. var view = this.get(item.get('id'));
  15596. if (!view) {
  15597. view = this.add(item.get('id'), new _converse.ChatRoomOccupantView({ model: item }));
  15598. } else {
  15599. delete view.model; // Remove ref to old model to help garbage collection
  15600. view.model = item;
  15601. view.initialize();
  15602. }
  15603. this.$('.occupant-list').append(view.render().$el);
  15604. },
  15605. parsePresence: function parsePresence(pres) {
  15606. var id = Strophe.getResourceFromJid(pres.getAttribute("from"));
  15607. var data = {
  15608. nick: id,
  15609. type: pres.getAttribute("type"),
  15610. states: []
  15611. };
  15612. _.each(pres.childNodes, function (child) {
  15613. switch (child.nodeName) {
  15614. case "status":
  15615. data.status = child.textContent || null;
  15616. break;
  15617. case "show":
  15618. data.show = child.textContent || 'online';
  15619. break;
  15620. case "x":
  15621. if (child.getAttribute("xmlns") === Strophe.NS.MUC_USER) {
  15622. _.each(child.childNodes, function (item) {
  15623. switch (item.nodeName) {
  15624. case "item":
  15625. data.affiliation = item.getAttribute("affiliation");
  15626. data.role = item.getAttribute("role");
  15627. data.jid = item.getAttribute("jid");
  15628. data.nick = item.getAttribute("nick") || data.nick;
  15629. break;
  15630. case "status":
  15631. if (item.getAttribute("code")) {
  15632. data.states.push(item.getAttribute("code"));
  15633. }
  15634. }
  15635. });
  15636. }
  15637. }
  15638. });
  15639. return data;
  15640. },
  15641. findOccupant: function findOccupant(data) {
  15642. /* Try to find an existing occupant based on the passed in
  15643. * data object.
  15644. *
  15645. * If we have a JID, we use that as lookup variable,
  15646. * otherwise we use the nick. We don't always have both,
  15647. * but should have at least one or the other.
  15648. */
  15649. var jid = Strophe.getBareJidFromJid(data.jid);
  15650. if (jid !== null) {
  15651. return this.model.where({ 'jid': jid }).pop();
  15652. } else {
  15653. return this.model.where({ 'nick': data.nick }).pop();
  15654. }
  15655. },
  15656. updateOccupantsOnPresence: function updateOccupantsOnPresence(pres) {
  15657. /* Given a presence stanza, update the occupant models
  15658. * based on its contents.
  15659. *
  15660. * Parameters:
  15661. * (XMLElement) pres: The presence stanza
  15662. */
  15663. var data = this.parsePresence(pres);
  15664. if (data.type === 'error') {
  15665. return true;
  15666. }
  15667. var occupant = this.findOccupant(data);
  15668. if (data.type === 'unavailable') {
  15669. if (occupant) {
  15670. occupant.destroy();
  15671. }
  15672. } else {
  15673. var jid = Strophe.getBareJidFromJid(data.jid);
  15674. var attributes = _.extend(data, {
  15675. 'jid': jid ? jid : undefined,
  15676. 'resource': data.jid ? Strophe.getResourceFromJid(data.jid) : undefined
  15677. });
  15678. if (occupant) {
  15679. occupant.save(attributes);
  15680. } else {
  15681. this.model.create(attributes);
  15682. }
  15683. }
  15684. },
  15685. promptForInvite: function promptForInvite(suggestion) {
  15686. var reason = prompt(__(___('You are about to invite %1$s to the chat room "%2$s". '), suggestion.text.label, this.model.get('id')) + __("You may optionally include a message, explaining the reason for the invitation."));
  15687. if (reason !== null) {
  15688. this.chatroomview.directInvite(suggestion.text.value, reason);
  15689. }
  15690. var form = suggestion.target.form,
  15691. error = form.querySelector('.pure-form-message.error');
  15692. if (!_.isNull(error)) {
  15693. error.parentNode.removeChild(error);
  15694. }
  15695. suggestion.target.value = '';
  15696. },
  15697. inviteFormSubmitted: function inviteFormSubmitted(evt) {
  15698. evt.preventDefault();
  15699. var el = evt.target.querySelector('input.invited-contact'),
  15700. jid = el.value;
  15701. if (!jid || _.filter(jid.split('@')).length < 2) {
  15702. evt.target.outerHTML = tpl_chatroom_invite({
  15703. 'error_message': __('Please enter a valid XMPP username'),
  15704. 'label_invitation': __('Invite')
  15705. });
  15706. this.initInviteWidget();
  15707. return;
  15708. }
  15709. this.promptForInvite({
  15710. 'target': el,
  15711. 'text': {
  15712. 'label': jid,
  15713. 'value': jid
  15714. } });
  15715. },
  15716. shouldInviteWidgetBeShown: function shouldInviteWidgetBeShown() {
  15717. return _converse.allow_muc_invitations && (this.chatroomview.model.get('open') || this.chatroomview.model.get('affiliation') === "owner");
  15718. },
  15719. initInviteWidget: function initInviteWidget() {
  15720. var form = this.el.querySelector('form.room-invite');
  15721. if (_.isNull(form)) {
  15722. return;
  15723. }
  15724. form.addEventListener('submit', this.inviteFormSubmitted.bind(this));
  15725. var el = this.el.querySelector('input.invited-contact');
  15726. var list = _converse.roster.map(function (item) {
  15727. var label = item.get('fullname') || item.get('jid');
  15728. return { 'label': label, 'value': item.get('jid') };
  15729. });
  15730. var awesomplete = new Awesomplete(el, {
  15731. 'minChars': 1,
  15732. 'list': list
  15733. });
  15734. el.addEventListener('awesomplete-selectcomplete', this.promptForInvite.bind(this));
  15735. }
  15736. });
  15737. _converse.RoomsPanel = Backbone.View.extend({
  15738. /* Backbone View which renders the "Rooms" tab and accompanying
  15739. * panel in the control box.
  15740. *
  15741. * In this panel, chat rooms can be listed, joined and new rooms
  15742. * can be created.
  15743. */
  15744. tagName: 'div',
  15745. className: 'controlbox-pane',
  15746. id: 'chatrooms',
  15747. events: {
  15748. 'submit form.add-chatroom': 'openChatRoom',
  15749. 'click input#show-rooms': 'showRooms',
  15750. 'click a.open-room': 'openChatRoom',
  15751. 'click a.room-info': 'toggleRoomInfo',
  15752. 'change input[name=server]': 'setDomain',
  15753. 'change input[name=nick]': 'setNick'
  15754. },
  15755. initialize: function initialize(cfg) {
  15756. this.parent_el = cfg.$parent[0];
  15757. this.tab_el = document.createElement('li');
  15758. this.model.on('change:muc_domain', this.onDomainChange, this);
  15759. this.model.on('change:nick', this.onNickChange, this);
  15760. _converse.chatboxes.on('change:num_unread', this.renderTab, this);
  15761. _converse.chatboxes.on('add', _.debounce(this.renderTab, 100), this);
  15762. },
  15763. render: function render() {
  15764. this.el.innerHTML = tpl_room_panel({
  15765. 'server_input_type': _converse.hide_muc_server && 'hidden' || 'text',
  15766. 'server_label_global_attr': _converse.hide_muc_server && ' hidden' || '',
  15767. 'label_room_name': __('Room name'),
  15768. 'label_nickname': __('Nickname'),
  15769. 'label_server': __('Server'),
  15770. 'label_join': __('Join Room'),
  15771. 'label_show_rooms': __('Show rooms')
  15772. });
  15773. this.renderTab();
  15774. var controlbox = _converse.chatboxes.get('controlbox');
  15775. if (controlbox.get('active-panel') !== ROOMS_PANEL_ID) {
  15776. this.el.classList.add('hidden');
  15777. }
  15778. return this;
  15779. },
  15780. renderTab: function renderTab() {
  15781. var controlbox = _converse.chatboxes.get('controlbox');
  15782. var chatrooms = fp.filter(_.partial(utils.isOfType, CHATROOMS_TYPE), _converse.chatboxes.models);
  15783. this.tab_el.innerHTML = tpl_chatrooms_tab({
  15784. 'label_rooms': __('Rooms'),
  15785. 'is_current': controlbox.get('active-panel') === ROOMS_PANEL_ID,
  15786. 'num_unread': fp.sum(fp.map(fp.curry(utils.getAttribute)('num_unread'), chatrooms))
  15787. });
  15788. },
  15789. insertIntoDOM: function insertIntoDOM() {
  15790. this.parent_el.appendChild(this.render().el);
  15791. this.tabs = this.parent_el.parentNode.querySelector('#controlbox-tabs');
  15792. this.tabs.appendChild(this.tab_el);
  15793. return this;
  15794. },
  15795. onDomainChange: function onDomainChange(model) {
  15796. var $server = this.$el.find('input.new-chatroom-server');
  15797. $server.val(model.get('muc_domain'));
  15798. if (_converse.auto_list_rooms) {
  15799. this.updateRoomsList();
  15800. }
  15801. },
  15802. onNickChange: function onNickChange(model) {
  15803. var $nick = this.$el.find('input.new-chatroom-nick');
  15804. $nick.val(model.get('nick'));
  15805. },
  15806. informNoRoomsFound: function informNoRoomsFound() {
  15807. var $available_chatrooms = this.$el.find('#available-chatrooms');
  15808. // For translators: %1$s is a variable and will be replaced with the XMPP server name
  15809. $available_chatrooms.html("<dt>" + __('No rooms on %1$s', this.model.get('muc_domain')) + "</dt>");
  15810. $('input#show-rooms').show().siblings('span.spinner').remove();
  15811. },
  15812. onRoomsFound: function onRoomsFound(iq) {
  15813. /* Handle the IQ stanza returned from the server, containing
  15814. * all its public rooms.
  15815. */
  15816. var $available_chatrooms = this.$el.find('#available-chatrooms');
  15817. this.rooms = $(iq).find('query').find('item');
  15818. if (this.rooms.length) {
  15819. // For translators: %1$s is a variable and will be
  15820. // replaced with the XMPP server name
  15821. $available_chatrooms.html("<dt>" + __('Rooms on %1$s', this.model.get('muc_domain')) + "</dt>");
  15822. var fragment = document.createDocumentFragment();
  15823. for (var i = 0; i < this.rooms.length; i++) {
  15824. var name = Strophe.unescapeNode($(this.rooms[i]).attr('name') || $(this.rooms[i]).attr('jid'));
  15825. var jid = $(this.rooms[i]).attr('jid');
  15826. fragment.appendChild($(tpl_room_item({
  15827. 'name': name,
  15828. 'jid': jid,
  15829. 'open_title': __('Click to open this room'),
  15830. 'info_title': __('Show more information on this room')
  15831. }))[0]);
  15832. }
  15833. $available_chatrooms.append(fragment);
  15834. $('input#show-rooms').show().siblings('span.spinner').remove();
  15835. } else {
  15836. this.informNoRoomsFound();
  15837. }
  15838. return true;
  15839. },
  15840. updateRoomsList: function updateRoomsList() {
  15841. /* Send and IQ stanza to the server asking for all rooms
  15842. */
  15843. _converse.connection.sendIQ($iq({
  15844. to: this.model.get('muc_domain'),
  15845. from: _converse.connection.jid,
  15846. type: "get"
  15847. }).c("query", { xmlns: Strophe.NS.DISCO_ITEMS }), this.onRoomsFound.bind(this), this.informNoRoomsFound.bind(this));
  15848. },
  15849. showRooms: function showRooms() {
  15850. var $available_chatrooms = this.$el.find('#available-chatrooms');
  15851. var $server = this.$el.find('input.new-chatroom-server');
  15852. var server = $server.val();
  15853. if (!server) {
  15854. $server.addClass('error');
  15855. return;
  15856. }
  15857. this.$el.find('input.new-chatroom-name').removeClass('error');
  15858. $server.removeClass('error');
  15859. $available_chatrooms.empty();
  15860. $('input#show-rooms').hide().after(tpl_spinner);
  15861. this.model.save({ muc_domain: server });
  15862. this.updateRoomsList();
  15863. },
  15864. insertRoomInfo: function insertRoomInfo(el, stanza) {
  15865. /* Insert room info (based on returned #disco IQ stanza)
  15866. *
  15867. * Parameters:
  15868. * (HTMLElement) el: The HTML DOM element that should
  15869. * contain the info.
  15870. * (XMLElement) stanza: The IQ stanza containing the room
  15871. * info.
  15872. */
  15873. var $stanza = $(stanza);
  15874. // All MUC features found here: http://xmpp.org/registrar/disco-features.html
  15875. el.querySelector('span.spinner').outerHTML = tpl_room_description({
  15876. 'jid': stanza.getAttribute('from'),
  15877. 'desc': $stanza.find('field[var="muc#roominfo_description"] value').text(),
  15878. 'occ': $stanza.find('field[var="muc#roominfo_occupants"] value').text(),
  15879. 'hidden': $stanza.find('feature[var="muc_hidden"]').length,
  15880. 'membersonly': $stanza.find('feature[var="muc_membersonly"]').length,
  15881. 'moderated': $stanza.find('feature[var="muc_moderated"]').length,
  15882. 'nonanonymous': $stanza.find('feature[var="muc_nonanonymous"]').length,
  15883. 'open': $stanza.find('feature[var="muc_open"]').length,
  15884. 'passwordprotected': $stanza.find('feature[var="muc_passwordprotected"]').length,
  15885. 'persistent': $stanza.find('feature[var="muc_persistent"]').length,
  15886. 'publicroom': $stanza.find('feature[var="muc_public"]').length,
  15887. 'semianonymous': $stanza.find('feature[var="muc_semianonymous"]').length,
  15888. 'temporary': $stanza.find('feature[var="muc_temporary"]').length,
  15889. 'unmoderated': $stanza.find('feature[var="muc_unmoderated"]').length,
  15890. 'label_desc': __('Description:'),
  15891. 'label_jid': __('Room Address (JID):'),
  15892. 'label_occ': __('Occupants:'),
  15893. 'label_features': __('Features:'),
  15894. 'label_requires_auth': __('Requires authentication'),
  15895. 'label_hidden': __('Hidden'),
  15896. 'label_requires_invite': __('Requires an invitation'),
  15897. 'label_moderated': __('Moderated'),
  15898. 'label_non_anon': __('Non-anonymous'),
  15899. 'label_open_room': __('Open room'),
  15900. 'label_permanent_room': __('Permanent room'),
  15901. 'label_public': __('Public'),
  15902. 'label_semi_anon': __('Semi-anonymous'),
  15903. 'label_temp_room': __('Temporary room'),
  15904. 'label_unmoderated': __('Unmoderated')
  15905. });
  15906. },
  15907. toggleRoomInfo: function toggleRoomInfo(ev) {
  15908. /* Show/hide extra information about a room in the listing.
  15909. */
  15910. var target = ev.target,
  15911. $parent = $(target).parent('dd'),
  15912. $div = $parent.find('div.room-info');
  15913. if ($div.length) {
  15914. $div.remove();
  15915. } else {
  15916. $parent.find('span.spinner').remove();
  15917. $parent.append(tpl_spinner);
  15918. _converse.connection.disco.info($(target).attr('data-room-jid'), null, _.partial(this.insertRoomInfo, $parent[0]));
  15919. }
  15920. },
  15921. parseRoomDataFromEvent: function parseRoomDataFromEvent(ev) {
  15922. var name = void 0,
  15923. $name = void 0,
  15924. server = void 0,
  15925. $server = void 0,
  15926. jid = void 0;
  15927. if (ev.type === 'click') {
  15928. name = $(ev.target).text();
  15929. jid = $(ev.target).attr('data-room-jid');
  15930. } else {
  15931. var _$name = this.$el.find('input.new-chatroom-name');
  15932. var _$server = this.$el.find('input.new-chatroom-server');
  15933. var _server = _$server.val();
  15934. name = _$name.val().trim();
  15935. _$name.val(''); // Clear the input
  15936. if (name && _server) {
  15937. jid = Strophe.escapeNode(name.toLowerCase()) + '@' + _server.toLowerCase();
  15938. _$name.removeClass('error');
  15939. _$server.removeClass('error');
  15940. this.model.save({ muc_domain: _server });
  15941. } else {
  15942. if (!name) {
  15943. _$name.addClass('error');
  15944. }
  15945. if (!_server) {
  15946. _$server.addClass('error');
  15947. }
  15948. return;
  15949. }
  15950. }
  15951. return {
  15952. 'jid': jid,
  15953. 'name': name || Strophe.unescapeNode(Strophe.getNodeFromJid(jid))
  15954. };
  15955. },
  15956. openChatRoom: function openChatRoom(ev) {
  15957. ev.preventDefault();
  15958. var data = this.parseRoomDataFromEvent(ev);
  15959. if (!_.isUndefined(data)) {
  15960. _converse.openChatRoom(data);
  15961. }
  15962. },
  15963. setDomain: function setDomain(ev) {
  15964. this.model.save({ muc_domain: ev.target.value });
  15965. },
  15966. setNick: function setNick(ev) {
  15967. this.model.save({ nick: ev.target.value });
  15968. }
  15969. });
  15970. /************************ End of ChatRoomView **********************/
  15971. _converse.onDirectMUCInvitation = function (message) {
  15972. /* A direct MUC invitation to join a room has been received
  15973. * See XEP-0249: Direct MUC invitations.
  15974. *
  15975. * Parameters:
  15976. * (XMLElement) message: The message stanza containing the
  15977. * invitation.
  15978. */
  15979. var $message = $(message),
  15980. $x = $message.children('x[xmlns="jabber:x:conference"]'),
  15981. from = Strophe.getBareJidFromJid($message.attr('from')),
  15982. room_jid = $x.attr('jid'),
  15983. reason = $x.attr('reason');
  15984. var contact = _converse.roster.get(from),
  15985. result = void 0;
  15986. if (_converse.auto_join_on_invite) {
  15987. result = true;
  15988. } else {
  15989. // Invite request might come from someone not your roster list
  15990. contact = contact ? contact.get('fullname') : Strophe.getNodeFromJid(from);
  15991. if (!reason) {
  15992. result = confirm(__(___("%1$s has invited you to join a chat room: %2$s"), contact, room_jid));
  15993. } else {
  15994. result = confirm(__(___('%1$s has invited you to join a chat room: %2$s, and left the following reason: "%3$s"'), contact, room_jid, reason));
  15995. }
  15996. }
  15997. if (result === true) {
  15998. var chatroom = _converse.openChatRoom({
  15999. 'jid': room_jid,
  16000. 'password': $x.attr('password')
  16001. });
  16002. if (chatroom.get('connection_status') === converse.ROOMSTATUS.DISCONNECTED) {
  16003. _converse.chatboxviews.get(room_jid).join();
  16004. }
  16005. }
  16006. };
  16007. if (_converse.allow_muc_invitations) {
  16008. var registerDirectInvitationHandler = function registerDirectInvitationHandler() {
  16009. _converse.connection.addHandler(function (message) {
  16010. _converse.onDirectMUCInvitation(message);
  16011. return true;
  16012. }, 'jabber:x:conference', 'message');
  16013. };
  16014. _converse.on('connected', registerDirectInvitationHandler);
  16015. _converse.on('reconnected', registerDirectInvitationHandler);
  16016. }
  16017. function autoJoinRooms() {
  16018. /* Automatically join chat rooms, based on the
  16019. * "auto_join_rooms" configuration setting, which is an array
  16020. * of strings (room JIDs) or objects (with room JID and other
  16021. * settings).
  16022. */
  16023. _.each(_converse.auto_join_rooms, function (room) {
  16024. if (_.isString(room)) {
  16025. _converse.api.rooms.open(room);
  16026. } else if (_.isObject(room)) {
  16027. _converse.api.rooms.open(room.jid, room.nick);
  16028. } else {
  16029. _converse.log('Invalid room criteria specified for "auto_join_rooms"', Strophe.LogLevel.ERROR);
  16030. }
  16031. });
  16032. }
  16033. _converse.on('chatBoxesFetched', autoJoinRooms);
  16034. _converse.getChatRoom = function (jid, attrs, fetcher) {
  16035. jid = jid.toLowerCase();
  16036. return _converse.getViewForChatBox(fetcher(_.extend({
  16037. 'id': jid,
  16038. 'jid': jid,
  16039. 'name': Strophe.unescapeNode(Strophe.getNodeFromJid(jid)),
  16040. 'type': CHATROOMS_TYPE,
  16041. 'box_id': b64_sha1(jid)
  16042. }, attrs)));
  16043. };
  16044. /* We extend the default converse.js API to add methods specific to MUC
  16045. * chat rooms.
  16046. */
  16047. _.extend(_converse.api, {
  16048. 'rooms': {
  16049. 'close': function close(jids) {
  16050. if (_.isUndefined(jids)) {
  16051. _converse.chatboxviews.each(function (view) {
  16052. if (view.is_chatroom && view.model) {
  16053. view.close();
  16054. }
  16055. });
  16056. } else if (_.isString(jids)) {
  16057. var view = _converse.chatboxviews.get(jids);
  16058. if (view) {
  16059. view.close();
  16060. }
  16061. } else {
  16062. _.each(jids, function (jid) {
  16063. var view = _converse.chatboxviews.get(jid);
  16064. if (view) {
  16065. view.close();
  16066. }
  16067. });
  16068. }
  16069. },
  16070. 'open': function open(jids, attrs) {
  16071. if (_.isString(attrs)) {
  16072. attrs = { 'nick': attrs };
  16073. } else if (_.isUndefined(attrs)) {
  16074. attrs = {};
  16075. }
  16076. if (_.isUndefined(attrs.maximize)) {
  16077. attrs.maximize = false;
  16078. }
  16079. if (!attrs.nick && _converse.muc_nickname_from_jid) {
  16080. attrs.nick = Strophe.getNodeFromJid(_converse.bare_jid);
  16081. }
  16082. if (_.isUndefined(jids)) {
  16083. throw new TypeError('rooms.open: You need to provide at least one JID');
  16084. } else if (_.isString(jids)) {
  16085. return _converse.getChatRoom(jids, attrs, _converse.openChatRoom);
  16086. }
  16087. return _.map(jids, _.partial(_converse.getChatRoom, _, attrs, _converse.openChatRoom));
  16088. },
  16089. 'get': function get(jids, attrs, create) {
  16090. if (_.isString(attrs)) {
  16091. attrs = { 'nick': attrs };
  16092. } else if (_.isUndefined(attrs)) {
  16093. attrs = {};
  16094. }
  16095. if (_.isUndefined(jids)) {
  16096. var result = [];
  16097. _converse.chatboxes.each(function (chatbox) {
  16098. if (chatbox.get('type') === CHATROOMS_TYPE) {
  16099. result.push(_converse.getViewForChatBox(chatbox));
  16100. }
  16101. });
  16102. return result;
  16103. }
  16104. var fetcher = _.partial(_converse.chatboxviews.getChatBox.bind(_converse.chatboxviews), _, create);
  16105. if (!attrs.nick) {
  16106. attrs.nick = Strophe.getNodeFromJid(_converse.bare_jid);
  16107. }
  16108. if (_.isString(jids)) {
  16109. return _converse.getChatRoom(jids, attrs, fetcher);
  16110. }
  16111. return _.map(jids, _.partial(_converse.getChatRoom, _, attrs, fetcher));
  16112. }
  16113. }
  16114. });
  16115. /* Event handlers */
  16116. _converse.on('addClientFeatures', function () {
  16117. if (_converse.allow_muc) {
  16118. _converse.connection.disco.addFeature(Strophe.NS.MUC);
  16119. }
  16120. if (_converse.allow_muc_invitations) {
  16121. _converse.connection.disco.addFeature('jabber:x:conference'); // Invites
  16122. }
  16123. });
  16124. _converse.on('reconnected', function reconnectToChatRooms() {
  16125. /* Upon a reconnection event from converse, join again
  16126. * all the open chat rooms.
  16127. */
  16128. _converse.chatboxviews.each(function (view) {
  16129. if (view.model.get('type') === CHATROOMS_TYPE) {
  16130. view.model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
  16131. view.registerHandlers();
  16132. view.join();
  16133. view.fetchMessages();
  16134. }
  16135. });
  16136. });
  16137. function disconnectChatRooms() {
  16138. /* When disconnecting, or reconnecting, mark all chat rooms as
  16139. * disconnected, so that they will be properly entered again
  16140. * when fetched from session storage.
  16141. */
  16142. _converse.chatboxes.each(function (model) {
  16143. if (model.get('type') === CHATROOMS_TYPE) {
  16144. model.save('connection_status', converse.ROOMSTATUS.DISCONNECTED);
  16145. }
  16146. });
  16147. }
  16148. _converse.on('reconnecting', disconnectChatRooms);
  16149. _converse.on('disconnecting', disconnectChatRooms);
  16150. }
  16151. });
  16152. });
  16153. //# sourceMappingURL=converse-muc.js.map;
  16154. define('tpl!chatroom_bookmark_form', ['lodash'], function(_) {return function(obj) {
  16155. obj || (obj = {});
  16156. var __t, __p = '', __e = _.escape;
  16157. with (obj) {
  16158. __p += '<div class="chatroom-form-container">\n <form class="pure-form converse-form chatroom-form">\n <fieldset>\n <legend>' +
  16159. __e(heading) +
  16160. '</legend>\n <label>' +
  16161. __e(label_name) +
  16162. '</label>\n <input type="text" name="name" required="required"/>\n <label>' +
  16163. __e(label_autojoin) +
  16164. '</label>\n <input type="checkbox" name="autojoin"/>\n <label>' +
  16165. __e(label_nick) +
  16166. '</label>\n <input type="text" name="nick" value="' +
  16167. __e(default_nick) +
  16168. '"/>\n </fieldset>\n <fieldset>\n <input class="pure-button button-primary" type="submit" value="' +
  16169. __e(label_submit) +
  16170. '"/>\n <input class="pure-button button-cancel" type="button" value="' +
  16171. __e(label_cancel) +
  16172. '"/>\n </fieldset>\n </form>\n</div>\n';
  16173. }
  16174. return __p
  16175. };});
  16176. define('tpl!chatroom_bookmark_toggle', ['lodash'], function(_) {return function(obj) {
  16177. obj || (obj = {});
  16178. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  16179. function print() { __p += __j.call(arguments, '') }
  16180. with (obj) {
  16181. __p += '<a class="chatbox-btn toggle-bookmark icon-pushpin\n ';
  16182. if (bookmarked) {;
  16183. __p += '\n button-on\n ';
  16184. } ;
  16185. __p += '" title="' +
  16186. __e(info_toggle_bookmark) +
  16187. '"></a>\n';
  16188. }
  16189. return __p
  16190. };});
  16191. define('tpl!bookmark', ['lodash'], function(_) {return function(obj) {
  16192. obj || (obj = {});
  16193. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  16194. function print() { __p += __j.call(arguments, '') }
  16195. with (obj) {
  16196. __p += '<dd class="available-chatroom" data-room-jid="' +
  16197. __e(jid) +
  16198. '">\n<a class="open-room" data-room-jid="' +
  16199. __e(jid) +
  16200. '" title="' +
  16201. __e(open_title) +
  16202. '" href="#">' +
  16203. __e(name) +
  16204. '</a>\n<a class="right remove-bookmark icon-pushpin ';
  16205. if (bookmarked) { ;
  16206. __p += ' button-on ';
  16207. } ;
  16208. __p += '"\n data-room-jid="' +
  16209. __e(jid) +
  16210. '" data-bookmark-name="' +
  16211. __e(name) +
  16212. '"\n title="' +
  16213. __e(info_remove_bookmark) +
  16214. '" href="#">&nbsp;</a>\n<a class="right room-info icon-room-info" data-room-jid="' +
  16215. __e(jid) +
  16216. '"\n title="' +
  16217. __e(info_title) +
  16218. '" href="#">&nbsp;</a>\n</dd>\n';
  16219. }
  16220. return __p
  16221. };});
  16222. define('tpl!bookmarks_list', ['lodash'], function(_) {return function(obj) {
  16223. obj || (obj = {});
  16224. var __t, __p = '', __e = _.escape;
  16225. with (obj) {
  16226. __p += '<a href="#" class="rooms-toggle bookmarks-toggle icon-' +
  16227. __e(toggle_state) +
  16228. '" title="' +
  16229. __e(desc_bookmarks) +
  16230. '">' +
  16231. __e(label_bookmarks) +
  16232. '</a>\n<dl class="bookmarks rooms-list"></dl>\n';
  16233. }
  16234. return __p
  16235. };});
  16236. // Converse.js (A browser based XMPP chat client)
  16237. // http://conversejs.org
  16238. //
  16239. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  16240. // Licensed under the Mozilla Public License (MPLv2)
  16241. //
  16242. /*global define */
  16243. /* This is a Converse.js plugin which add support for bookmarks specified
  16244. * in XEP-0048.
  16245. */
  16246. (function (root, factory) {
  16247. define('converse-bookmarks',["jquery.noconflict", "utils", "converse-core", "converse-muc", "tpl!chatroom_bookmark_form", "tpl!chatroom_bookmark_toggle", "tpl!bookmark", "tpl!bookmarks_list"], factory);
  16248. })(undefined, function ($, utils, converse, muc, tpl_chatroom_bookmark_form, tpl_chatroom_bookmark_toggle, tpl_bookmark, tpl_bookmarks_list) {
  16249. var _converse$env = converse.env,
  16250. Backbone = _converse$env.Backbone,
  16251. Promise = _converse$env.Promise,
  16252. Strophe = _converse$env.Strophe,
  16253. $iq = _converse$env.$iq,
  16254. b64_sha1 = _converse$env.b64_sha1,
  16255. sizzle = _converse$env.sizzle,
  16256. _ = _converse$env._;
  16257. converse.plugins.add('converse-bookmarks', {
  16258. overrides: {
  16259. // Overrides mentioned here will be picked up by converse.js's
  16260. // plugin architecture they will replace existing methods on the
  16261. // relevant objects or classes.
  16262. //
  16263. // New functions which don't exist yet can also be added.
  16264. clearSession: function clearSession() {
  16265. this.__super__.clearSession.apply(this, arguments);
  16266. if (!_.isUndefined(this.bookmarks)) {
  16267. this.bookmarks.reset();
  16268. this.bookmarks.browserStorage._clear();
  16269. window.sessionStorage.removeItem(this.bookmarks.fetched_flag);
  16270. }
  16271. },
  16272. ChatRoomView: {
  16273. events: {
  16274. 'click .toggle-bookmark': 'toggleBookmark'
  16275. },
  16276. initialize: function initialize() {
  16277. this.__super__.initialize.apply(this, arguments);
  16278. this.model.on('change:bookmarked', this.onBookmarked, this);
  16279. this.setBookmarkState();
  16280. },
  16281. generateHeadingHTML: function generateHeadingHTML() {
  16282. var _converse = this.__super__._converse,
  16283. __ = _converse.__,
  16284. html = this.__super__.generateHeadingHTML.apply(this, arguments);
  16285. if (_converse.allow_bookmarks) {
  16286. var div = document.createElement('div');
  16287. div.innerHTML = html;
  16288. var bookmark_button = tpl_chatroom_bookmark_toggle(_.assignIn(this.model.toJSON(), {
  16289. info_toggle_bookmark: __('Bookmark this room'),
  16290. bookmarked: this.model.get('bookmarked')
  16291. }));
  16292. var close_button = div.querySelector('.close-chatbox-button');
  16293. close_button.insertAdjacentHTML('afterend', bookmark_button);
  16294. return div.innerHTML;
  16295. }
  16296. return html;
  16297. },
  16298. checkForReservedNick: function checkForReservedNick() {
  16299. /* Check if the user has a bookmark with a saved nickanme
  16300. * for this room, and if so use it.
  16301. * Otherwise delegate to the super method.
  16302. */
  16303. var _converse = this.__super__._converse;
  16304. if (_.isUndefined(_converse.bookmarks) || !_converse.allow_bookmarks) {
  16305. return this.__super__.checkForReservedNick.apply(this, arguments);
  16306. }
  16307. var model = _converse.bookmarks.findWhere({ 'jid': this.model.get('jid') });
  16308. if (!_.isUndefined(model) && model.get('nick')) {
  16309. this.join(model.get('nick'));
  16310. } else {
  16311. return this.__super__.checkForReservedNick.apply(this, arguments);
  16312. }
  16313. },
  16314. onBookmarked: function onBookmarked() {
  16315. if (this.model.get('bookmarked')) {
  16316. this.$('.icon-pushpin').addClass('button-on');
  16317. } else {
  16318. this.$('.icon-pushpin').removeClass('button-on');
  16319. }
  16320. },
  16321. setBookmarkState: function setBookmarkState() {
  16322. /* Set whether the room is bookmarked or not.
  16323. */
  16324. var _converse = this.__super__._converse;
  16325. if (!_.isUndefined(_converse.bookmarks)) {
  16326. var models = _converse.bookmarks.where({ 'jid': this.model.get('jid') });
  16327. if (!models.length) {
  16328. this.model.save('bookmarked', false);
  16329. } else {
  16330. this.model.save('bookmarked', true);
  16331. }
  16332. }
  16333. },
  16334. renderBookmarkForm: function renderBookmarkForm() {
  16335. var _converse = this.__super__._converse,
  16336. __ = _converse.__,
  16337. $body = this.$('.chatroom-body');
  16338. $body.children().addClass('hidden');
  16339. // Remove any existing forms
  16340. $body.find('form.chatroom-form').remove();
  16341. $body.append(tpl_chatroom_bookmark_form({
  16342. heading: __('Bookmark this room'),
  16343. label_name: __('The name for this bookmark:'),
  16344. label_autojoin: __('Would you like this room to be automatically joined upon startup?'),
  16345. label_nick: __('What should your nickname for this room be?'),
  16346. default_nick: this.model.get('nick'),
  16347. label_submit: __('Save'),
  16348. label_cancel: __('Cancel')
  16349. }));
  16350. this.$('.chatroom-form').submit(this.onBookmarkFormSubmitted.bind(this));
  16351. this.$('.chatroom-form .button-cancel').on('click', this.cancelConfiguration.bind(this));
  16352. },
  16353. onBookmarkFormSubmitted: function onBookmarkFormSubmitted(ev) {
  16354. ev.preventDefault();
  16355. var _converse = this.__super__._converse;
  16356. var $form = $(ev.target),
  16357. that = this;
  16358. _converse.bookmarks.createBookmark({
  16359. 'jid': this.model.get('jid'),
  16360. 'autojoin': $form.find('input[name="autojoin"]').prop('checked'),
  16361. 'name': $form.find('input[name=name]').val(),
  16362. 'nick': $form.find('input[name=nick]').val()
  16363. });
  16364. this.$el.find('div.chatroom-form-container').hide(function () {
  16365. $(this).remove();
  16366. that.renderAfterTransition();
  16367. });
  16368. },
  16369. toggleBookmark: function toggleBookmark(ev) {
  16370. if (ev) {
  16371. ev.preventDefault();
  16372. ev.stopPropagation();
  16373. }
  16374. var _converse = this.__super__._converse;
  16375. var models = _converse.bookmarks.where({ 'jid': this.model.get('jid') });
  16376. if (!models.length) {
  16377. this.renderBookmarkForm();
  16378. } else {
  16379. _.forEach(models, function (model) {
  16380. model.destroy();
  16381. });
  16382. this.$('.icon-pushpin').removeClass('button-on');
  16383. }
  16384. }
  16385. }
  16386. },
  16387. initialize: function initialize() {
  16388. /* The initialize function gets called as soon as the plugin is
  16389. * loaded by converse.js's plugin machinery.
  16390. */
  16391. var _converse = this._converse,
  16392. __ = _converse.__,
  16393. ___ = _converse.___;
  16394. // Configuration values for this plugin
  16395. // ====================================
  16396. // Refer to docs/source/configuration.rst for explanations of these
  16397. // configuration settings.
  16398. _converse.api.settings.update({
  16399. allow_bookmarks: true,
  16400. hide_open_bookmarks: false
  16401. });
  16402. // Promises exposed by this plugin
  16403. _converse.api.promises.add('bookmarksInitialized');
  16404. // Pure functions on the _converse object
  16405. _.extend(_converse, {
  16406. removeBookmarkViaEvent: function removeBookmarkViaEvent(ev) {
  16407. /* Remove a bookmark as determined by the passed in
  16408. * event.
  16409. */
  16410. ev.preventDefault();
  16411. var name = ev.target.getAttribute('data-bookmark-name');
  16412. var jid = ev.target.getAttribute('data-room-jid');
  16413. if (confirm(__(___("Are you sure you want to remove the bookmark \"%1$s\"?"), name))) {
  16414. _.invokeMap(_converse.bookmarks.where({ 'jid': jid }), Backbone.Model.prototype.destroy);
  16415. }
  16416. },
  16417. addBookmarkViaEvent: function addBookmarkViaEvent(ev) {
  16418. /* Add a bookmark as determined by the passed in
  16419. * event.
  16420. */
  16421. ev.preventDefault();
  16422. var jid = ev.target.getAttribute('data-room-jid');
  16423. var chatroom = _converse.openChatRoom({ 'jid': jid }, true);
  16424. _converse.chatboxviews.get(jid).renderBookmarkForm();
  16425. }
  16426. });
  16427. _converse.Bookmark = Backbone.Model;
  16428. _converse.BookmarksList = Backbone.Model.extend({
  16429. defaults: {
  16430. "toggle-state": _converse.OPENED
  16431. }
  16432. });
  16433. _converse.Bookmarks = Backbone.Collection.extend({
  16434. model: _converse.Bookmark,
  16435. initialize: function initialize() {
  16436. this.on('add', _.flow(this.openBookmarkedRoom, this.markRoomAsBookmarked));
  16437. this.on('remove', this.markRoomAsUnbookmarked, this);
  16438. this.on('remove', this.sendBookmarkStanza, this);
  16439. var cache_key = "converse.room-bookmarks" + _converse.bare_jid;
  16440. this.fetched_flag = b64_sha1(cache_key + 'fetched');
  16441. this.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1(cache_key));
  16442. },
  16443. openBookmarkedRoom: function openBookmarkedRoom(bookmark) {
  16444. if (bookmark.get('autojoin')) {
  16445. _converse.api.rooms.open(bookmark.get('jid'), bookmark.get('nick'));
  16446. }
  16447. return bookmark;
  16448. },
  16449. fetchBookmarks: function fetchBookmarks() {
  16450. var deferred = utils.getWrappedPromise();
  16451. if (this.browserStorage.records.length > 0) {
  16452. this.fetch({
  16453. 'success': _.bind(this.onCachedBookmarksFetched, this, deferred),
  16454. 'error': _.bind(this.onCachedBookmarksFetched, this, deferred)
  16455. });
  16456. } else if (!window.sessionStorage.getItem(this.fetched_flag)) {
  16457. // There aren't any cached bookmarks and the
  16458. // `fetched_flag` is off, so we query the XMPP server.
  16459. // If nothing is returned from the XMPP server, we set
  16460. // the `fetched_flag` to avoid calling the server again.
  16461. this.fetchBookmarksFromServer(deferred);
  16462. } else {
  16463. deferred.resolve();
  16464. }
  16465. return deferred.promise;
  16466. },
  16467. onCachedBookmarksFetched: function onCachedBookmarksFetched(deferred) {
  16468. return deferred.resolve();
  16469. },
  16470. createBookmark: function createBookmark(options) {
  16471. _converse.bookmarks.create(options);
  16472. _converse.bookmarks.sendBookmarkStanza();
  16473. },
  16474. sendBookmarkStanza: function sendBookmarkStanza() {
  16475. var stanza = $iq({
  16476. 'type': 'set',
  16477. 'from': _converse.connection.jid
  16478. }).c('pubsub', { 'xmlns': Strophe.NS.PUBSUB }).c('publish', { 'node': 'storage:bookmarks' }).c('item', { 'id': 'current' }).c('storage', { 'xmlns': 'storage:bookmarks' });
  16479. this.each(function (model) {
  16480. stanza = stanza.c('conference', {
  16481. 'name': model.get('name'),
  16482. 'autojoin': model.get('autojoin'),
  16483. 'jid': model.get('jid')
  16484. }).c('nick').t(model.get('nick')).up().up();
  16485. });
  16486. stanza.up().up().up();
  16487. stanza.c('publish-options').c('x', { 'xmlns': Strophe.NS.XFORM, 'type': 'submit' }).c('field', { 'var': 'FORM_TYPE', 'type': 'hidden' }).c('value').t('http://jabber.org/protocol/pubsub#publish-options').up().up().c('field', { 'var': 'pubsub#persist_items' }).c('value').t('true').up().up().c('field', { 'var': 'pubsub#access_model' }).c('value').t('whitelist');
  16488. _converse.connection.sendIQ(stanza, null, this.onBookmarkError.bind(this));
  16489. },
  16490. onBookmarkError: function onBookmarkError(iq) {
  16491. _converse.log("Error while trying to add bookmark", Strophe.LogLevel.ERROR);
  16492. _converse.log(iq);
  16493. // We remove all locally cached bookmarks and fetch them
  16494. // again from the server.
  16495. this.reset();
  16496. this.fetchBookmarksFromServer(null);
  16497. window.alert(__("Sorry, something went wrong while trying to save your bookmark."));
  16498. },
  16499. fetchBookmarksFromServer: function fetchBookmarksFromServer(deferred) {
  16500. var stanza = $iq({
  16501. 'from': _converse.connection.jid,
  16502. 'type': 'get'
  16503. }).c('pubsub', { 'xmlns': Strophe.NS.PUBSUB }).c('items', { 'node': 'storage:bookmarks' });
  16504. _converse.connection.sendIQ(stanza, _.bind(this.onBookmarksReceived, this, deferred), _.bind(this.onBookmarksReceivedError, this, deferred));
  16505. },
  16506. markRoomAsBookmarked: function markRoomAsBookmarked(bookmark) {
  16507. var room = _converse.chatboxes.get(bookmark.get('jid'));
  16508. if (!_.isUndefined(room)) {
  16509. room.save('bookmarked', true);
  16510. }
  16511. },
  16512. markRoomAsUnbookmarked: function markRoomAsUnbookmarked(bookmark) {
  16513. var room = _converse.chatboxes.get(bookmark.get('jid'));
  16514. if (!_.isUndefined(room)) {
  16515. room.save('bookmarked', false);
  16516. }
  16517. },
  16518. onBookmarksReceived: function onBookmarksReceived(deferred, iq) {
  16519. var bookmarks = $(iq).find('items[node="storage:bookmarks"] item[id="current"] storage conference');
  16520. var that = this;
  16521. _.forEach(bookmarks, function (bookmark) {
  16522. that.create({
  16523. 'jid': bookmark.getAttribute('jid'),
  16524. 'name': bookmark.getAttribute('name'),
  16525. 'autojoin': bookmark.getAttribute('autojoin') === 'true',
  16526. 'nick': bookmark.querySelector('nick').textContent
  16527. });
  16528. });
  16529. if (!_.isUndefined(deferred)) {
  16530. return deferred.resolve();
  16531. }
  16532. },
  16533. onBookmarksReceivedError: function onBookmarksReceivedError(deferred, iq) {
  16534. window.sessionStorage.setItem(this.fetched_flag, true);
  16535. _converse.log('Error while fetching bookmarks', Strophe.LogLevel.ERROR);
  16536. _converse.log(iq, Strophe.LogLevel.DEBUG);
  16537. if (!_.isNil(deferred)) {
  16538. return deferred.reject();
  16539. }
  16540. }
  16541. });
  16542. _converse.BookmarksView = Backbone.View.extend({
  16543. tagName: 'div',
  16544. className: 'bookmarks-list, rooms-list-container',
  16545. events: {
  16546. 'click .add-bookmark': 'addBookmark',
  16547. 'click .bookmarks-toggle': 'toggleBookmarksList',
  16548. 'click .remove-bookmark': 'removeBookmark'
  16549. },
  16550. initialize: function initialize() {
  16551. this.model.on('add', this.renderBookmarkListElement, this);
  16552. this.model.on('remove', this.removeBookmarkListElement, this);
  16553. _converse.chatboxes.on('add', this.renderBookmarkListElement, this);
  16554. _converse.chatboxes.on('remove', this.renderBookmarkListElement, this);
  16555. var cachekey = "converse.room-bookmarks" + _converse.bare_jid + "-list-model";
  16556. this.list_model = new _converse.BookmarksList();
  16557. this.list_model.id = cachekey;
  16558. this.list_model.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1(cachekey));
  16559. this.list_model.fetch();
  16560. this.render();
  16561. },
  16562. render: function render() {
  16563. this.$el.html(tpl_bookmarks_list({
  16564. 'toggle_state': this.list_model.get('toggle-state'),
  16565. 'desc_bookmarks': __('Click to toggle the bookmarks list'),
  16566. 'label_bookmarks': __('Bookmarks')
  16567. })).hide();
  16568. if (this.list_model.get('toggle-state') !== _converse.OPENED) {
  16569. this.$('.bookmarks').hide();
  16570. }
  16571. this.model.each(this.renderBookmarkListElement.bind(this));
  16572. var controlboxview = _converse.chatboxviews.get('controlbox');
  16573. if (!_.isUndefined(controlboxview)) {
  16574. this.$el.prependTo(controlboxview.$('#chatrooms'));
  16575. }
  16576. return this.$el;
  16577. },
  16578. removeBookmark: _converse.removeBookmarkViaEvent,
  16579. addBookmark: _converse.addBookmarkViaEvent,
  16580. renderBookmarkListElement: function renderBookmarkListElement(item) {
  16581. if (item instanceof _converse.ChatBox) {
  16582. item = _.head(this.model.where({ 'jid': item.get('jid') }));
  16583. if (_.isNil(item)) {
  16584. // A chat box has been closed, but we don't have a
  16585. // bookmark for it, so nothing further to do here.
  16586. return;
  16587. }
  16588. }
  16589. if (_converse.hide_open_bookmarks && _converse.chatboxes.where({ 'jid': item.get('jid') }).length) {
  16590. // A chat box has been opened, and we don't show
  16591. // bookmarks for open chats, so we remove it.
  16592. this.removeBookmarkListElement(item);
  16593. return;
  16594. }
  16595. var list_el = this.el.querySelector('.bookmarks');
  16596. var div = document.createElement('div');
  16597. div.innerHTML = tpl_bookmark({
  16598. 'bookmarked': true,
  16599. 'info_leave_room': __('Leave this room'),
  16600. 'info_remove': __('Remove this bookmark'),
  16601. 'info_remove_bookmark': __('Unbookmark this room'),
  16602. 'info_title': __('Show more information on this room'),
  16603. 'jid': item.get('jid'),
  16604. 'name': item.get('name'),
  16605. 'open_title': __('Click to open this room')
  16606. });
  16607. var el = _.head(sizzle(".available-chatroom[data-room-jid=\"" + item.get('jid') + "\"]", list_el));
  16608. if (el) {
  16609. el.innerHTML = div.firstChild.innerHTML;
  16610. } else {
  16611. list_el.appendChild(div.firstChild);
  16612. }
  16613. this.show();
  16614. },
  16615. show: function show() {
  16616. if (!this.$el.is(':visible')) {
  16617. this.$el.show();
  16618. }
  16619. },
  16620. hide: function hide() {
  16621. this.$el.hide();
  16622. },
  16623. removeBookmarkListElement: function removeBookmarkListElement(item) {
  16624. var list_el = this.el.querySelector('.bookmarks');
  16625. var el = _.head(sizzle(".available-chatroom[data-room-jid=\"" + item.get('jid') + "\"]", list_el));
  16626. if (el) {
  16627. list_el.removeChild(el);
  16628. }
  16629. if (list_el.childElementCount === 0) {
  16630. this.hide();
  16631. }
  16632. },
  16633. toggleBookmarksList: function toggleBookmarksList(ev) {
  16634. if (ev && ev.preventDefault) {
  16635. ev.preventDefault();
  16636. }
  16637. var $el = $(ev.target);
  16638. if ($el.hasClass("icon-opened")) {
  16639. this.$('.bookmarks').slideUp('fast');
  16640. this.list_model.save({ 'toggle-state': _converse.CLOSED });
  16641. $el.removeClass("icon-opened").addClass("icon-closed");
  16642. } else {
  16643. $el.removeClass("icon-closed").addClass("icon-opened");
  16644. this.$('.bookmarks').slideDown('fast');
  16645. this.list_model.save({ 'toggle-state': _converse.OPENED });
  16646. }
  16647. }
  16648. });
  16649. var initBookmarks = function initBookmarks() {
  16650. if (!_converse.allow_bookmarks) {
  16651. return;
  16652. }
  16653. _converse.bookmarks = new _converse.Bookmarks();
  16654. _converse.bookmarks.fetchBookmarks().then(function () {
  16655. _converse.bookmarksview = new _converse.BookmarksView({ 'model': _converse.bookmarks });
  16656. _converse.emit('bookmarksInitialized');
  16657. });
  16658. };
  16659. Promise.all([_converse.api.waitUntil('chatBoxesFetched'), _converse.api.waitUntil('roomsPanelRendered')]).then(initBookmarks);
  16660. var afterReconnection = function afterReconnection() {
  16661. if (!_converse.allow_bookmarks) {
  16662. return;
  16663. }
  16664. if (_.isUndefined(_converse.bookmarksview)) {
  16665. initBookmarks();
  16666. } else {
  16667. _converse.bookmarksview.render();
  16668. }
  16669. };
  16670. _converse.on('reconnected', afterReconnection);
  16671. }
  16672. });
  16673. });
  16674. //# sourceMappingURL=converse-bookmarks.js.map;
  16675. define('tpl!rooms_list', ['lodash'], function(_) {return function(obj) {
  16676. obj || (obj = {});
  16677. var __t, __p = '', __e = _.escape;
  16678. with (obj) {
  16679. __p += '<a href="#" class="rooms-toggle open-rooms-toggle icon-' +
  16680. __e(toggle_state) +
  16681. '" title="' +
  16682. __e(desc_rooms) +
  16683. '">' +
  16684. __e(label_rooms) +
  16685. '</a>\n<dl class="rooms-list open-rooms-list"></dl>\n';
  16686. }
  16687. return __p
  16688. };});
  16689. define('tpl!rooms_list_item', ['lodash'], function(_) {return function(obj) {
  16690. obj || (obj = {});
  16691. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  16692. function print() { __p += __j.call(arguments, '') }
  16693. with (obj) {
  16694. __p += '<dd class="available-chatroom ';
  16695. if (num_unread_general) { ;
  16696. __p += ' unread-msgs ';
  16697. } ;
  16698. __p += '" data-room-jid="' +
  16699. __e(jid) +
  16700. '">\n';
  16701. if (num_unread) { ;
  16702. __p += '\n <span class="msgs-indicator">' +
  16703. __e( num_unread ) +
  16704. '</span>\n';
  16705. } ;
  16706. __p += '\n<a class="open-room"\n data-room-jid="' +
  16707. __e(jid) +
  16708. '"\n title="' +
  16709. __e(open_title) +
  16710. '" href="#">' +
  16711. __e(name) +
  16712. '</a>\n<a class="right close-room icon-leave"\n data-room-jid="' +
  16713. __e(jid) +
  16714. '"\n data-room-name="' +
  16715. __e(name) +
  16716. '"\n title="' +
  16717. __e(info_leave_room) +
  16718. '" href="#">&nbsp;</a>\n\n';
  16719. if (allow_bookmarks) { ;
  16720. __p += '\n<a class="right icon-pushpin ';
  16721. if (bookmarked) { ;
  16722. __p += ' remove-bookmark button-on ';
  16723. } else { ;
  16724. __p += ' add-bookmark ';
  16725. } ;
  16726. __p += '"\n data-room-jid="' +
  16727. __e(jid) +
  16728. '" data-bookmark-name="' +
  16729. __e(name) +
  16730. '"\n title="';
  16731. if (bookmarked) { ;
  16732. __p += ' ' +
  16733. __e(info_remove_bookmark) +
  16734. ' ';
  16735. } else { ;
  16736. __p += ' ' +
  16737. __e(info_add_bookmark) +
  16738. ' ';
  16739. } ;
  16740. __p += '"\n href="#">&nbsp;</a>\n';
  16741. } ;
  16742. __p += '\n<a class="right room-info icon-room-info" data-room-jid="' +
  16743. __e(jid) +
  16744. '"\n title="' +
  16745. __e(info_title) +
  16746. '" href="#">&nbsp;</a>\n</dd>\n';
  16747. }
  16748. return __p
  16749. };});
  16750. // Converse.js (A browser based XMPP chat client)
  16751. // http://conversejs.org
  16752. //
  16753. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  16754. // Licensed under the Mozilla Public License (MPLv2)
  16755. //
  16756. /*global define */
  16757. /* This is a non-core Converse.js plugin which shows a list of currently open
  16758. * rooms in the "Rooms Panel" of the ControlBox.
  16759. */
  16760. (function (root, factory) {
  16761. define('converse-roomslist',["utils", "converse-core", "converse-muc", "tpl!rooms_list", "tpl!rooms_list_item"], factory);
  16762. })(undefined, function (utils, converse, muc, tpl_rooms_list, tpl_rooms_list_item) {
  16763. var _converse$env = converse.env,
  16764. Backbone = _converse$env.Backbone,
  16765. Promise = _converse$env.Promise,
  16766. b64_sha1 = _converse$env.b64_sha1,
  16767. sizzle = _converse$env.sizzle,
  16768. _ = _converse$env._;
  16769. converse.plugins.add('converse-roomslist', {
  16770. /* Optional dependencies are other plugins which might be
  16771. * overridden or relied upon, and therefore need to be loaded before
  16772. * this plugin. They are called "optional" because they might not be
  16773. * available, in which case any overrides applicable to them will be
  16774. * ignored.
  16775. *
  16776. * It's possible however to make optional dependencies non-optional.
  16777. * If the setting "strict_plugin_dependencies" is set to true,
  16778. * an error will be raised if the plugin is not found.
  16779. *
  16780. * NB: These plugins need to have already been loaded via require.js.
  16781. */
  16782. optional_dependencies: ["converse-bookmarks"],
  16783. initialize: function initialize() {
  16784. /* The initialize function gets called as soon as the plugin is
  16785. * loaded by converse.js's plugin machinery.
  16786. */
  16787. var _converse = this._converse,
  16788. __ = _converse.__,
  16789. ___ = _converse.___;
  16790. _converse.RoomsList = Backbone.Model.extend({
  16791. defaults: {
  16792. "toggle-state": _converse.OPENED
  16793. }
  16794. });
  16795. _converse.RoomsListView = Backbone.View.extend({
  16796. tagName: 'div',
  16797. className: 'open-rooms-list rooms-list-container',
  16798. events: {
  16799. 'click .add-bookmark': 'addBookmark',
  16800. 'click .close-room': 'closeRoom',
  16801. 'click .open-rooms-toggle': 'toggleRoomsList',
  16802. 'click .remove-bookmark': 'removeBookmark'
  16803. },
  16804. initialize: function initialize() {
  16805. this.toggleRoomsList = _.debounce(this.toggleRoomsList, 600, { 'leading': true });
  16806. this.model.on('add', this.renderRoomsListElement, this);
  16807. this.model.on('change:bookmarked', this.renderRoomsListElement, this);
  16808. this.model.on('change:name', this.renderRoomsListElement, this);
  16809. this.model.on('change:num_unread', this.renderRoomsListElement, this);
  16810. this.model.on('change:num_unread_general', this.renderRoomsListElement, this);
  16811. this.model.on('remove', this.removeRoomsListElement, this);
  16812. var cachekey = "converse.roomslist" + _converse.bare_jid;
  16813. this.list_model = new _converse.RoomsList();
  16814. this.list_model.id = cachekey;
  16815. this.list_model.browserStorage = new Backbone.BrowserStorage[_converse.storage](b64_sha1(cachekey));
  16816. this.list_model.fetch();
  16817. this.render();
  16818. },
  16819. render: function render() {
  16820. this.el.innerHTML = tpl_rooms_list({
  16821. 'toggle_state': this.list_model.get('toggle-state'),
  16822. 'desc_rooms': __('Click to toggle the rooms list'),
  16823. 'label_rooms': __('Open Rooms')
  16824. });
  16825. this.hide();
  16826. if (this.list_model.get('toggle-state') !== _converse.OPENED) {
  16827. this.el.querySelector('.open-rooms-list').classList.add('collapsed');
  16828. }
  16829. this.model.each(this.renderRoomsListElement.bind(this));
  16830. var controlboxview = _converse.chatboxviews.get('controlbox');
  16831. if (!_.isUndefined(controlboxview) && !document.body.contains(this.el)) {
  16832. var container = controlboxview.el.querySelector('#chatrooms');
  16833. if (!_.isNull(container)) {
  16834. container.insertBefore(this.el, container.firstChild);
  16835. }
  16836. }
  16837. return this.el;
  16838. },
  16839. hide: function hide() {
  16840. this.el.classList.add('hidden');
  16841. },
  16842. show: function show() {
  16843. this.el.classList.remove('hidden');
  16844. },
  16845. closeRoom: function closeRoom(ev) {
  16846. ev.preventDefault();
  16847. var name = ev.target.getAttribute('data-room-name');
  16848. var jid = ev.target.getAttribute('data-room-jid');
  16849. if (confirm(__(___("Are you sure you want to leave the room \"%1$s\"?"), name))) {
  16850. _converse.chatboxviews.get(jid).leave();
  16851. }
  16852. },
  16853. renderRoomsListElement: function renderRoomsListElement(item) {
  16854. if (item.get('type') !== 'chatroom') {
  16855. return;
  16856. }
  16857. this.removeRoomsListElement(item);
  16858. var name = void 0,
  16859. bookmark = void 0;
  16860. if (item.get('bookmarked')) {
  16861. bookmark = _.head(_converse.bookmarksview.model.where({ 'jid': item.get('jid') }));
  16862. name = bookmark.get('name');
  16863. } else {
  16864. name = item.get('name');
  16865. }
  16866. var div = document.createElement('div');
  16867. div.innerHTML = tpl_rooms_list_item(_.extend(item.toJSON(), {
  16868. 'allow_bookmarks': _converse.allow_bookmarks,
  16869. 'info_leave_room': __('Leave this room'),
  16870. 'info_remove_bookmark': __('Unbookmark this room'),
  16871. 'info_add_bookmark': __('Bookmark this room'),
  16872. 'info_title': __('Show more information on this room'),
  16873. 'name': name,
  16874. 'open_title': __('Click to open this room')
  16875. }));
  16876. this.el.querySelector('.open-rooms-list').appendChild(div.firstChild);
  16877. this.show();
  16878. },
  16879. removeBookmark: _converse.removeBookmarkViaEvent,
  16880. addBookmark: _converse.addBookmarkViaEvent,
  16881. removeRoomsListElement: function removeRoomsListElement(item) {
  16882. var list_el = this.el.querySelector('.open-rooms-list');
  16883. var el = _.head(sizzle(".available-chatroom[data-room-jid=\"" + item.get('jid') + "\"]", list_el));
  16884. if (el) {
  16885. list_el.removeChild(el);
  16886. }
  16887. if (list_el.childElementCount === 0) {
  16888. this.hide();
  16889. }
  16890. },
  16891. toggleRoomsList: function toggleRoomsList(ev) {
  16892. var _this = this;
  16893. if (ev && ev.preventDefault) {
  16894. ev.preventDefault();
  16895. }
  16896. var el = ev.target;
  16897. if (el.classList.contains("icon-opened")) {
  16898. utils.slideIn(this.el.querySelector('.open-rooms-list')).then(function () {
  16899. _this.list_model.save({ 'toggle-state': _converse.CLOSED });
  16900. el.classList.remove("icon-opened");
  16901. el.classList.add("icon-closed");
  16902. });
  16903. } else {
  16904. utils.slideOut(this.el.querySelector('.open-rooms-list')).then(function () {
  16905. _this.list_model.save({ 'toggle-state': _converse.OPENED });
  16906. el.classList.remove("icon-closed");
  16907. el.classList.add("icon-opened");
  16908. });
  16909. }
  16910. }
  16911. });
  16912. var initRoomsListView = function initRoomsListView() {
  16913. _converse.rooms_list_view = new _converse.RoomsListView({ 'model': _converse.chatboxes });
  16914. };
  16915. Promise.all([_converse.api.waitUntil('chatBoxesFetched'), _converse.api.waitUntil('roomsPanelRendered')]).then(function () {
  16916. if (_converse.allow_bookmarks) {
  16917. _converse.api.waitUntil('bookmarksInitialized').then(initRoomsListView);
  16918. } else {
  16919. initRoomsListView();
  16920. }
  16921. });
  16922. var afterReconnection = function afterReconnection() {
  16923. if (_.isUndefined(_converse.rooms_list_view)) {
  16924. initRoomsListView();
  16925. } else {
  16926. _converse.rooms_list_view.render();
  16927. }
  16928. };
  16929. _converse.api.listen.on('reconnected', afterReconnection);
  16930. }
  16931. });
  16932. });
  16933. //# sourceMappingURL=converse-roomslist.js.map;
  16934. // Converse.js (A browser based XMPP chat client)
  16935. // http://conversejs.org
  16936. //
  16937. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  16938. // Licensed under the Mozilla Public License (MPLv2)
  16939. //
  16940. /*global define */
  16941. // XEP-0059 Result Set Management
  16942. (function (root, factory) {
  16943. define('converse-mam',["jquery.noconflict", "converse-core", "converse-disco", "converse-chatview", // Could be made a soft dependency
  16944. "converse-muc", // Could be made a soft dependency
  16945. "strophe.rsm"], factory);
  16946. })(undefined, function ($, converse) {
  16947. "use strict";
  16948. var _converse$env = converse.env,
  16949. Promise = _converse$env.Promise,
  16950. Strophe = _converse$env.Strophe,
  16951. $iq = _converse$env.$iq,
  16952. _ = _converse$env._,
  16953. moment = _converse$env.moment;
  16954. var RSM_ATTRIBUTES = ['max', 'first', 'last', 'after', 'before', 'index', 'count'];
  16955. // XEP-0313 Message Archive Management
  16956. var MAM_ATTRIBUTES = ['with', 'start', 'end'];
  16957. function checkMAMSupport(_converse) {
  16958. /* Returns a promise which resolves when MAM is supported
  16959. * for this user, or which rejects if not.
  16960. */
  16961. return _converse.api.waitUntil('discoInitialized').then(function () {
  16962. return new Promise(function (resolve, reject) {
  16963. function fulfillPromise(entity) {
  16964. if (entity.features.findWhere({ 'var': Strophe.NS.MAM })) {
  16965. resolve(true);
  16966. } else {
  16967. resolve(false);
  16968. }
  16969. }
  16970. var entity = _converse.disco_entities.get(_converse.bare_jid);
  16971. if (_.isUndefined(entity)) {
  16972. entity = _converse.disco_entities.create({ 'jid': _converse.bare_jid });
  16973. entity.on('featuresDiscovered', _.partial(fulfillPromise, entity));
  16974. } else {
  16975. fulfillPromise(entity);
  16976. }
  16977. });
  16978. });
  16979. }
  16980. converse.plugins.add('converse-mam', {
  16981. overrides: {
  16982. // Overrides mentioned here will be picked up by converse.js's
  16983. // plugin architecture they will replace existing methods on the
  16984. // relevant objects or classes.
  16985. //
  16986. // New functions which don't exist yet can also be added.
  16987. ChatBox: {
  16988. getMessageAttributes: function getMessageAttributes($message, $delay, original_stanza) {
  16989. var attrs = this.__super__.getMessageAttributes.apply(this, arguments);
  16990. attrs.archive_id = $(original_stanza).find("result[xmlns=\"" + Strophe.NS.MAM + "\"]").attr('id');
  16991. return attrs;
  16992. }
  16993. },
  16994. ChatBoxView: {
  16995. render: function render() {
  16996. var result = this.__super__.render.apply(this, arguments);
  16997. if (!this.disable_mam) {
  16998. this.$content.on('scroll', _.debounce(this.onScroll.bind(this), 100));
  16999. }
  17000. return result;
  17001. },
  17002. fetchArchivedMessagesIfNecessary: function fetchArchivedMessagesIfNecessary() {
  17003. var _this = this;
  17004. /* Check if archived messages should be fetched, and if so, do so. */
  17005. if (this.disable_mam || this.model.get('mam_initialized')) {
  17006. return;
  17007. }
  17008. var _converse = this.__super__._converse;
  17009. this.addSpinner();
  17010. checkMAMSupport(_converse).then(function (supported) {
  17011. // Success
  17012. if (supported) {
  17013. _this.fetchArchivedMessages();
  17014. } else {
  17015. _this.clearSpinner();
  17016. }
  17017. _this.model.save({ 'mam_initialized': true });
  17018. }, function () {
  17019. // Error
  17020. _this.clearSpinner();
  17021. _converse.log("Error or timeout while checking for MAM support", Strophe.LogLevel.ERROR);
  17022. }).catch(function (msg) {
  17023. _this.clearSpinner();
  17024. _converse.log(msg, Strophe.LogLevel.FATAL);
  17025. });
  17026. },
  17027. fetchArchivedMessages: function fetchArchivedMessages(options) {
  17028. var _this2 = this;
  17029. /* Fetch archived chat messages from the XMPP server.
  17030. *
  17031. * Then, upon receiving them, call onMessage on the chat
  17032. * box, so that they are displayed inside it.
  17033. */
  17034. var _converse = this.__super__._converse;
  17035. if (!_converse.disco_entities.get(_converse.bare_jid).features.findWhere({ 'var': Strophe.NS.MAM })) {
  17036. _converse.log("Attempted to fetch archived messages but this " + "user's server doesn't support XEP-0313", Strophe.LogLevel.WARN);
  17037. return;
  17038. }
  17039. if (this.disable_mam) {
  17040. return;
  17041. }
  17042. this.addSpinner();
  17043. _converse.queryForArchivedMessages(_.extend({
  17044. 'before': '', // Page backwards from the most recent message
  17045. 'max': _converse.archived_messages_page_size,
  17046. 'with': this.model.get('jid')
  17047. }, options), function (messages) {
  17048. // Success
  17049. _this2.clearSpinner();
  17050. if (messages.length) {
  17051. _.each(messages, _converse.chatboxes.onMessage.bind(_converse.chatboxes));
  17052. }
  17053. }, function () {
  17054. // Error
  17055. _this2.clearSpinner();
  17056. _converse.log("Error or timeout while trying to fetch " + "archived messages", Strophe.LogLevel.ERROR);
  17057. });
  17058. },
  17059. onScroll: function onScroll(ev) {
  17060. var _converse = this.__super__._converse;
  17061. if ($(ev.target).scrollTop() === 0 && this.model.messages.length) {
  17062. this.fetchArchivedMessages({
  17063. 'before': this.model.messages.at(0).get('archive_id')
  17064. });
  17065. }
  17066. }
  17067. },
  17068. ChatRoomView: {
  17069. initialize: function initialize() {
  17070. var _converse = this.__super__._converse;
  17071. this.__super__.initialize.apply(this, arguments);
  17072. this.model.on('change:mam_enabled', this.fetchArchivedMessagesIfNecessary, this);
  17073. this.model.on('change:connection_status', this.fetchArchivedMessagesIfNecessary, this);
  17074. },
  17075. render: function render() {
  17076. var result = this.__super__.render.apply(this, arguments);
  17077. if (!this.disable_mam) {
  17078. this.$content.on('scroll', _.debounce(this.onScroll.bind(this), 100));
  17079. }
  17080. return result;
  17081. },
  17082. handleMUCMessage: function handleMUCMessage(stanza) {
  17083. /* MAM (message archive management XEP-0313) messages are
  17084. * ignored, since they're handled separately.
  17085. */
  17086. var is_mam = $(stanza).find("[xmlns=\"" + Strophe.NS.MAM + "\"]").length > 0;
  17087. if (is_mam) {
  17088. return true;
  17089. }
  17090. return this.__super__.handleMUCMessage.apply(this, arguments);
  17091. },
  17092. fetchArchivedMessagesIfNecessary: function fetchArchivedMessagesIfNecessary() {
  17093. if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED || !this.model.get('mam_enabled') || this.model.get('mam_initialized')) {
  17094. return;
  17095. }
  17096. this.fetchArchivedMessages();
  17097. this.model.save({ 'mam_initialized': true });
  17098. },
  17099. fetchArchivedMessages: function fetchArchivedMessages(options) {
  17100. /* Fetch archived chat messages for this Chat Room
  17101. *
  17102. * Then, upon receiving them, call onChatRoomMessage
  17103. * so that they are displayed inside it.
  17104. */
  17105. this.addSpinner();
  17106. var that = this;
  17107. var _converse = this.__super__._converse;
  17108. _converse.api.archive.query(_.extend({
  17109. 'groupchat': true,
  17110. 'before': '', // Page backwards from the most recent message
  17111. 'with': this.model.get('jid'),
  17112. 'max': _converse.archived_messages_page_size
  17113. }, options), function (messages) {
  17114. that.clearSpinner();
  17115. if (messages.length) {
  17116. _.each(messages, that.onChatRoomMessage.bind(that));
  17117. }
  17118. }, function () {
  17119. that.clearSpinner();
  17120. _converse.log("Error while trying to fetch archived messages", Strophe.LogLevel.WARN);
  17121. });
  17122. }
  17123. }
  17124. },
  17125. initialize: function initialize() {
  17126. /* The initialize function gets called as soon as the plugin is
  17127. * loaded by Converse.js's plugin machinery.
  17128. */
  17129. var _converse = this._converse;
  17130. _converse.api.settings.update({
  17131. archived_messages_page_size: '50',
  17132. message_archiving: undefined, // Supported values are 'always', 'never', 'roster' (https://xmpp.org/extensions/xep-0313.html#prefs)
  17133. message_archiving_timeout: 8000 // Time (in milliseconds) to wait before aborting MAM request
  17134. });
  17135. _converse.queryForArchivedMessages = function (options, callback, errback) {
  17136. /* Do a MAM (XEP-0313) query for archived messages.
  17137. *
  17138. * Parameters:
  17139. * (Object) options - Query parameters, either MAM-specific or also for Result Set Management.
  17140. * (Function) callback - A function to call whenever we receive query-relevant stanza.
  17141. * (Function) errback - A function to call when an error stanza is received.
  17142. *
  17143. * The options parameter can also be an instance of
  17144. * Strophe.RSM to enable easy querying between results pages.
  17145. *
  17146. * The callback function may be called multiple times, first
  17147. * for the initial IQ result and then for each message
  17148. * returned. The last time the callback is called, a
  17149. * Strophe.RSM object is returned on which "next" or "previous"
  17150. * can be called before passing it in again to this method, to
  17151. * get the next or previous page in the result set.
  17152. */
  17153. var date = void 0;
  17154. if (_.isFunction(options)) {
  17155. callback = options;
  17156. errback = callback;
  17157. }
  17158. var queryid = _converse.connection.getUniqueId();
  17159. var attrs = { 'type': 'set' };
  17160. if (!_.isUndefined(options) && options.groupchat) {
  17161. if (!options['with']) {
  17162. // eslint-disable-line dot-notation
  17163. throw new Error('You need to specify a "with" value containing ' + 'the chat room JID, when querying groupchat messages.');
  17164. }
  17165. attrs.to = options['with']; // eslint-disable-line dot-notation
  17166. }
  17167. var stanza = $iq(attrs).c('query', { 'xmlns': Strophe.NS.MAM, 'queryid': queryid });
  17168. if (!_.isUndefined(options)) {
  17169. stanza.c('x', { 'xmlns': Strophe.NS.XFORM, 'type': 'submit' }).c('field', { 'var': 'FORM_TYPE', 'type': 'hidden' }).c('value').t(Strophe.NS.MAM).up().up();
  17170. if (options['with'] && !options.groupchat) {
  17171. // eslint-disable-line dot-notation
  17172. stanza.c('field', { 'var': 'with' }).c('value').t(options['with']).up().up(); // eslint-disable-line dot-notation
  17173. }
  17174. _.each(['start', 'end'], function (t) {
  17175. if (options[t]) {
  17176. date = moment(options[t]);
  17177. if (date.isValid()) {
  17178. stanza.c('field', { 'var': t }).c('value').t(date.format()).up().up();
  17179. } else {
  17180. throw new TypeError("archive.query: invalid date provided for: " + t);
  17181. }
  17182. }
  17183. });
  17184. stanza.up();
  17185. if (options instanceof Strophe.RSM) {
  17186. stanza.cnode(options.toXML());
  17187. } else if (_.intersection(RSM_ATTRIBUTES, _.keys(options)).length) {
  17188. stanza.cnode(new Strophe.RSM(options).toXML());
  17189. }
  17190. }
  17191. var messages = [];
  17192. var message_handler = _converse.connection.addHandler(function (message) {
  17193. var result = message.querySelector('result');
  17194. if (!_.isNull(result) && result.getAttribute('queryid') === queryid) {
  17195. messages.push(message);
  17196. }
  17197. return true;
  17198. }, Strophe.NS.MAM);
  17199. _converse.connection.sendIQ(stanza, function (iq) {
  17200. _converse.connection.deleteHandler(message_handler);
  17201. if (_.isFunction(callback)) {
  17202. var set = iq.querySelector('set');
  17203. var rsm = new Strophe.RSM({ xml: set });
  17204. _.extend(rsm, _.pick(options, _.concat(MAM_ATTRIBUTES, ['max'])));
  17205. callback(messages, rsm);
  17206. }
  17207. }, function () {
  17208. _converse.connection.deleteHandler(message_handler);
  17209. if (_.isFunction(errback)) {
  17210. errback.apply(this, arguments);
  17211. }
  17212. }, _converse.message_archiving_timeout);
  17213. };
  17214. _.extend(_converse.api, {
  17215. /* Extend default converse.js API to add methods specific to MAM
  17216. */
  17217. 'archive': {
  17218. 'query': _converse.queryForArchivedMessages.bind(_converse)
  17219. }
  17220. });
  17221. _converse.onMAMError = function (iq) {
  17222. if ($(iq).find('feature-not-implemented').length) {
  17223. _converse.log("Message Archive Management (XEP-0313) not supported by this server", Strophe.LogLevel.WARN);
  17224. } else {
  17225. _converse.log("An error occured while trying to set archiving preferences.", Strophe.LogLevel.ERROR);
  17226. _converse.log(iq);
  17227. }
  17228. };
  17229. _converse.onMAMPreferences = function (feature, iq) {
  17230. /* Handle returned IQ stanza containing Message Archive
  17231. * Management (XEP-0313) preferences.
  17232. *
  17233. * XXX: For now we only handle the global default preference.
  17234. * The XEP also provides for per-JID preferences, which is
  17235. * currently not supported in converse.js.
  17236. *
  17237. * Per JID preferences will be set in chat boxes, so it'll
  17238. * probbaly be handled elsewhere in any case.
  17239. */
  17240. var $prefs = $(iq).find("prefs[xmlns=\"" + Strophe.NS.MAM + "\"]");
  17241. var default_pref = $prefs.attr('default');
  17242. var stanza = void 0;
  17243. if (default_pref !== _converse.message_archiving) {
  17244. stanza = $iq({ 'type': 'set' }).c('prefs', { 'xmlns': Strophe.NS.MAM, 'default': _converse.message_archiving });
  17245. $prefs.children().each(function (idx, child) {
  17246. stanza.cnode(child).up();
  17247. });
  17248. _converse.connection.sendIQ(stanza, _.partial(function (feature, iq) {
  17249. // XXX: Strictly speaking, the server should respond with the updated prefs
  17250. // (see example 18: https://xmpp.org/extensions/xep-0313.html#config)
  17251. // but Prosody doesn't do this, so we don't rely on it.
  17252. feature.save({ 'preferences': { 'default': _converse.message_archiving } });
  17253. }, feature), _converse.onMAMError);
  17254. } else {
  17255. feature.save({ 'preferences': { 'default': _converse.message_archiving } });
  17256. }
  17257. };
  17258. /* Event handlers */
  17259. _converse.on('serviceDiscovered', function (feature) {
  17260. var prefs = feature.get('preferences') || {};
  17261. if (feature.get('var') === Strophe.NS.MAM && prefs['default'] !== _converse.message_archiving && // eslint-disable-line dot-notation
  17262. !_.isUndefined(_converse.message_archiving)) {
  17263. // Ask the server for archiving preferences
  17264. _converse.connection.sendIQ($iq({ 'type': 'get' }).c('prefs', { 'xmlns': Strophe.NS.MAM }), _.partial(_converse.onMAMPreferences, feature), _.partial(_converse.onMAMError, feature));
  17265. }
  17266. });
  17267. _converse.on('addClientFeatures', function () {
  17268. _converse.connection.disco.addFeature(Strophe.NS.MAM);
  17269. });
  17270. _converse.on('afterMessagesFetched', function (chatboxview) {
  17271. chatboxview.fetchArchivedMessagesIfNecessary();
  17272. });
  17273. }
  17274. });
  17275. });
  17276. //# sourceMappingURL=converse-mam.js.map;
  17277. // Converse.js (A browser based XMPP chat client)
  17278. // http://conversejs.org
  17279. //
  17280. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  17281. // Licensed under the Mozilla Public License (MPLv2)
  17282. //
  17283. /*global define */
  17284. (function (root, factory) {
  17285. define('converse-vcard',["converse-core", "strophe.vcard"], factory);
  17286. })(undefined, function (converse) {
  17287. "use strict";
  17288. var _converse$env = converse.env,
  17289. Strophe = _converse$env.Strophe,
  17290. _ = _converse$env._,
  17291. moment = _converse$env.moment,
  17292. sizzle = _converse$env.sizzle;
  17293. converse.plugins.add('converse-vcard', {
  17294. overrides: {
  17295. // Overrides mentioned here will be picked up by converse.js's
  17296. // plugin architecture they will replace existing methods on the
  17297. // relevant objects or classes.
  17298. //
  17299. // New functions which don't exist yet can also be added.
  17300. RosterContacts: {
  17301. createRequestingContact: function createRequestingContact(presence) {
  17302. var _converse = this.__super__._converse;
  17303. var bare_jid = Strophe.getBareJidFromJid(presence.getAttribute('from'));
  17304. _converse.getVCard(bare_jid, _.partial(_converse.createRequestingContactFromVCard, presence), function (iq, jid) {
  17305. _converse.log("Error while retrieving vcard for " + jid, Strophe.LogLevel.ERROR);
  17306. _converse.createRequestingContactFromVCard(presence, iq, jid);
  17307. });
  17308. }
  17309. }
  17310. },
  17311. initialize: function initialize() {
  17312. /* The initialize function gets called as soon as the plugin is
  17313. * loaded by converse.js's plugin machinery.
  17314. */
  17315. var _converse = this._converse;
  17316. _converse.api.settings.update({
  17317. use_vcards: true
  17318. });
  17319. _converse.createRequestingContactFromVCard = function (presence, iq, jid, fullname, img, img_type, url) {
  17320. var bare_jid = Strophe.getBareJidFromJid(jid);
  17321. if (!fullname) {
  17322. var nick_el = sizzle("nick[xmlns=\"" + Strophe.NS.NICK + "\"]", presence);
  17323. fullname = nick_el.length ? nick_el[0].textContent : bare_jid;
  17324. }
  17325. var user_data = {
  17326. jid: bare_jid,
  17327. subscription: 'none',
  17328. ask: null,
  17329. requesting: true,
  17330. fullname: fullname,
  17331. image: img,
  17332. image_type: img_type,
  17333. url: url,
  17334. vcard_updated: moment().format()
  17335. };
  17336. _converse.roster.create(user_data);
  17337. _converse.emit('contactRequest', user_data);
  17338. };
  17339. _converse.onVCardError = function (jid, iq, errback) {
  17340. var contact = _converse.roster.get(jid);
  17341. if (contact) {
  17342. contact.save({ 'vcard_updated': moment().format() });
  17343. }
  17344. if (errback) {
  17345. errback(iq, jid);
  17346. }
  17347. };
  17348. _converse.onVCardData = function (jid, iq, callback) {
  17349. var vcard = iq.querySelector('vCard'),
  17350. img_type = _.get(vcard.querySelector('TYPE'), 'textContent'),
  17351. img = _.get(vcard.querySelector('BINVAL'), 'textContent'),
  17352. url = _.get(vcard.querySelector('URL'), 'textContent'),
  17353. fullname = _.get(vcard.querySelector('FN'), 'textContent');
  17354. if (jid) {
  17355. var contact = _converse.roster.get(jid);
  17356. if (contact) {
  17357. contact.save({
  17358. 'fullname': fullname || _.get(contact, 'fullname', jid),
  17359. 'image_type': img_type,
  17360. 'image': img,
  17361. 'url': url,
  17362. 'vcard_updated': moment().format()
  17363. });
  17364. }
  17365. }
  17366. if (callback) {
  17367. callback(iq, jid, fullname, img, img_type, url);
  17368. }
  17369. };
  17370. _converse.getVCard = function (jid, callback, errback) {
  17371. /* Request the VCard of another user.
  17372. *
  17373. * Parameters:
  17374. * (String) jid - The Jabber ID of the user whose VCard
  17375. * is being requested.
  17376. * (Function) callback - A function to call once the VCard is
  17377. * returned.
  17378. * (Function) errback - A function to call if an error occured
  17379. * while trying to fetch the VCard.
  17380. */
  17381. if (!_converse.use_vcards) {
  17382. if (callback) {
  17383. callback(null, jid);
  17384. }
  17385. } else {
  17386. _converse.connection.vcard.get(_.partial(_converse.onVCardData, jid, _, callback), jid, _.partial(_converse.onVCardError, jid, _, errback));
  17387. }
  17388. };
  17389. /* Event handlers */
  17390. _converse.on('addClientFeatures', function () {
  17391. if (_converse.use_vcards) {
  17392. _converse.connection.disco.addFeature(Strophe.NS.VCARD);
  17393. }
  17394. });
  17395. var updateVCardForChatBox = function updateVCardForChatBox(chatbox) {
  17396. if (!_converse.use_vcards) {
  17397. return;
  17398. }
  17399. var jid = chatbox.model.get('jid'),
  17400. contact = _converse.roster.get(jid);
  17401. if (contact && !contact.get('vcard_updated')) {
  17402. _converse.getVCard(jid, function (iq, jid, fullname, image, image_type, url) {
  17403. chatbox.model.save({
  17404. 'fullname': fullname || jid,
  17405. 'url': url,
  17406. 'image_type': image_type,
  17407. 'image': image
  17408. });
  17409. }, function () {
  17410. _converse.log("updateVCardForChatBox: Error occured while fetching vcard", Strophe.LogLevel.ERROR);
  17411. });
  17412. }
  17413. };
  17414. _converse.on('chatBoxInitialized', updateVCardForChatBox);
  17415. var onContactAdd = function onContactAdd(contact) {
  17416. if (!contact.get('vcard_updated')) {
  17417. // This will update the vcard, which triggers a change
  17418. // request which will rerender the roster contact.
  17419. _converse.getVCard(contact.get('jid'));
  17420. }
  17421. };
  17422. _converse.on('initialized', function () {
  17423. _converse.roster.on("add", onContactAdd);
  17424. });
  17425. _converse.on('statusInitialized', function fetchOwnVCard() {
  17426. if (_converse.xmppstatus.get('fullname') === undefined) {
  17427. _converse.getVCard(null, // No 'to' attr when getting one's own vCard
  17428. function (iq, jid, fullname) {
  17429. _converse.xmppstatus.save({ 'fullname': fullname });
  17430. });
  17431. }
  17432. });
  17433. }
  17434. });
  17435. });
  17436. //# sourceMappingURL=converse-vcard.js.map;
  17437. define('tpl!toolbar_otr', ['lodash'], function(_) {return function(obj) {
  17438. obj || (obj = {});
  17439. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  17440. function print() { __p += __j.call(arguments, '') }
  17441. with (obj) {
  17442. if (allow_otr) { ;
  17443. __p += '\n <li class="toggle-toolbar-menu toggle-otr ' +
  17444. __e(otr_status_class) +
  17445. '" title="' +
  17446. __e(otr_tooltip) +
  17447. '">\n <span class="chat-toolbar-text">' +
  17448. __e(otr_translated_status) +
  17449. '</span>\n ';
  17450. if (otr_status == UNENCRYPTED) { ;
  17451. __p += '\n <span class="icon-unlocked"></span>\n ';
  17452. } ;
  17453. __p += '\n ';
  17454. if (otr_status == UNVERIFIED) { ;
  17455. __p += '\n <span class="icon-lock"></span>\n ';
  17456. } ;
  17457. __p += '\n ';
  17458. if (otr_status == VERIFIED) { ;
  17459. __p += '\n <span class="icon-lock"></span>\n ';
  17460. } ;
  17461. __p += '\n ';
  17462. if (otr_status == FINISHED) { ;
  17463. __p += '\n <span class="icon-unlocked"></span>\n ';
  17464. } ;
  17465. __p += '\n <ul class="toolbar-menu collapsed">\n ';
  17466. if (otr_status == UNENCRYPTED) { ;
  17467. __p += '\n <li><a class="start-otr" href="#">' +
  17468. __e(label_start_encrypted_conversation) +
  17469. '</a></li>\n ';
  17470. } ;
  17471. __p += '\n ';
  17472. if (otr_status != UNENCRYPTED) { ;
  17473. __p += '\n <li><a class="start-otr" href="#">' +
  17474. __e(label_refresh_encrypted_conversation) +
  17475. '</a></li>\n <li><a class="end-otr" href="#">' +
  17476. __e(label_end_encrypted_conversation) +
  17477. '</a></li>\n <li><a class="auth-otr" data-scheme="smp" href="#">' +
  17478. __e(label_verify_with_smp) +
  17479. '</a></li>\n ';
  17480. } ;
  17481. __p += '\n ';
  17482. if (otr_status == UNVERIFIED) { ;
  17483. __p += '\n <li><a class="auth-otr" data-scheme="fingerprint" href="#">' +
  17484. __e(label_verify_with_fingerprints) +
  17485. '</a></li>\n ';
  17486. } ;
  17487. __p += '\n <li><a href="http://www.cypherpunks.ca/otr/help/3.2.0/levels.php" target="_blank" rel="noopener">' +
  17488. __e(label_whats_this) +
  17489. '</a></li>\n </ul>\n </li>\n';
  17490. } ;
  17491. __p += '\n';
  17492. }
  17493. return __p
  17494. };});
  17495. // Converse.js (A browser based XMPP chat client)
  17496. // http://conversejs.org
  17497. //
  17498. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  17499. // Licensed under the Mozilla Public License (MPLv2)
  17500. //
  17501. /*global define, window, crypto, CryptoJS */
  17502. /* This is a Converse.js plugin which add support Off-the-record (OTR)
  17503. * encryption of one-on-one chat messages.
  17504. */
  17505. (function (root, factory) {
  17506. define('converse-otr',["jquery.noconflict", "converse-chatview", "tpl!toolbar_otr", 'otr'], factory);
  17507. })(undefined, function ($, converse, tpl_toolbar_otr, otr) {
  17508. "use strict";
  17509. var _converse$env = converse.env,
  17510. Strophe = _converse$env.Strophe,
  17511. utils = _converse$env.utils,
  17512. b64_sha1 = _converse$env.b64_sha1,
  17513. _ = _converse$env._;
  17514. var HAS_CSPRNG = !_.isUndefined(crypto) && (_.isFunction(crypto.randomBytes) || _.isFunction(crypto.getRandomValues));
  17515. var HAS_CRYPTO = HAS_CSPRNG && !_.isUndefined(otr.OTR) && !_.isUndefined(otr.DSA);
  17516. var UNENCRYPTED = 0;
  17517. var UNVERIFIED = 1;
  17518. var VERIFIED = 2;
  17519. var FINISHED = 3;
  17520. var OTR_TRANSLATED_MAPPING = {}; // Populated in initialize
  17521. var OTR_CLASS_MAPPING = {};
  17522. OTR_CLASS_MAPPING[UNENCRYPTED] = 'unencrypted';
  17523. OTR_CLASS_MAPPING[UNVERIFIED] = 'unverified';
  17524. OTR_CLASS_MAPPING[VERIFIED] = 'verified';
  17525. OTR_CLASS_MAPPING[FINISHED] = 'finished';
  17526. converse.plugins.add('converse-otr', {
  17527. overrides: {
  17528. // Overrides mentioned here will be picked up by converse.js's
  17529. // plugin architecture they will replace existing methods on the
  17530. // relevant objects or classes.
  17531. //
  17532. // New functions which don't exist yet can also be added.
  17533. ChatBox: {
  17534. initialize: function initialize() {
  17535. this.__super__.initialize.apply(this, arguments);
  17536. if (this.get('box_id') !== 'controlbox') {
  17537. this.save({ 'otr_status': this.get('otr_status') || UNENCRYPTED });
  17538. }
  17539. },
  17540. shouldPlayNotification: function shouldPlayNotification($message) {
  17541. /* Don't play a notification if this is an OTR message but
  17542. * encryption is not yet set up. That would mean that the
  17543. * OTR session is still being established, so there are no
  17544. * "visible" OTR messages being exchanged.
  17545. */
  17546. return this.__super__.shouldPlayNotification.apply(this, arguments) && !(utils.isOTRMessage($message[0]) && !_.includes([UNVERIFIED, VERIFIED], this.get('otr_status')));
  17547. },
  17548. createMessage: function createMessage(message, delay, original_stanza) {
  17549. var _converse = this.__super__._converse,
  17550. text = _.propertyOf(message.querySelector('body'))('textContent');
  17551. if (!text || !_converse.allow_otr) {
  17552. return this.__super__.createMessage.apply(this, arguments);
  17553. }
  17554. if (utils.isNewMessage(original_stanza)) {
  17555. if (text.match(/^\?OTRv23?/)) {
  17556. return this.initiateOTR(text);
  17557. } else if (_.includes([UNVERIFIED, VERIFIED], this.get('otr_status'))) {
  17558. return this.otr.receiveMsg(text);
  17559. } else if (text.match(/^\?OTR/)) {
  17560. if (!this.otr) {
  17561. return this.initiateOTR(text);
  17562. } else {
  17563. return this.otr.receiveMsg(text);
  17564. }
  17565. }
  17566. }
  17567. // Normal unencrypted message (or archived message)
  17568. return this.__super__.createMessage.apply(this, arguments);
  17569. },
  17570. generatePrivateKey: function generatePrivateKey(instance_tag) {
  17571. var _converse = this.__super__._converse;
  17572. var key = new otr.DSA();
  17573. var jid = _converse.connection.jid;
  17574. if (_converse.cache_otr_key) {
  17575. this.save({
  17576. 'otr_priv_key': key.packPrivate(),
  17577. 'otr_instance_tag': instance_tag
  17578. });
  17579. }
  17580. return key;
  17581. },
  17582. getSession: function getSession(callback) {
  17583. var _converse = this.__super__._converse,
  17584. __ = _converse.__;
  17585. var instance_tag = void 0,
  17586. saved_key = void 0,
  17587. encrypted_key = void 0;
  17588. if (_converse.cache_otr_key) {
  17589. encrypted_key = this.get('otr_priv_key');
  17590. if (_.isString(encrypted_key)) {
  17591. instance_tag = this.get('otr_instance_tag');
  17592. saved_key = otr.DSA.parsePrivate(encrypted_key);
  17593. if (saved_key && instance_tag) {
  17594. this.trigger('showHelpMessages', [__('Re-establishing encrypted session')]);
  17595. callback({
  17596. 'key': saved_key,
  17597. 'instance_tag': instance_tag
  17598. });
  17599. return; // Our work is done here
  17600. }
  17601. }
  17602. }
  17603. // We need to generate a new key and instance tag
  17604. this.trigger('showHelpMessages', [__('Generating private key.'), __('Your browser might become unresponsive.')], null, true // show spinner
  17605. );
  17606. var that = this;
  17607. window.setTimeout(function () {
  17608. callback({
  17609. 'key': that.generatePrivateKey(instance_tag),
  17610. 'instance_tag': otr.OTR.makeInstanceTag()
  17611. });
  17612. }, 500);
  17613. },
  17614. updateOTRStatus: function updateOTRStatus(state) {
  17615. switch (state) {
  17616. case otr.OTR.CONST.STATUS_AKE_SUCCESS:
  17617. if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_ENCRYPTED) {
  17618. this.save({ 'otr_status': UNVERIFIED });
  17619. }
  17620. break;
  17621. case otr.OTR.CONST.STATUS_END_OTR:
  17622. if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_FINISHED) {
  17623. this.save({ 'otr_status': FINISHED });
  17624. } else if (this.otr.msgstate === otr.OTR.CONST.MSGSTATE_PLAINTEXT) {
  17625. this.save({ 'otr_status': UNENCRYPTED });
  17626. }
  17627. break;
  17628. }
  17629. },
  17630. onSMP: function onSMP(type, data) {
  17631. // Event handler for SMP (Socialist's Millionaire Protocol)
  17632. // used by OTR (off-the-record).
  17633. var _converse = this.__super__._converse,
  17634. __ = _converse.__;
  17635. switch (type) {
  17636. case 'question':
  17637. this.otr.smpSecret(prompt(__('Authentication request from %1$s\n\nYour chat contact is attempting to verify your identity, by asking you the question below.\n\n%2$s', [this.get('fullname'), data])));
  17638. break;
  17639. case 'trust':
  17640. if (data === true) {
  17641. this.save({ 'otr_status': VERIFIED });
  17642. } else {
  17643. this.trigger('showHelpMessages', [__("Could not verify this user's identify.")], 'error');
  17644. this.save({ 'otr_status': UNVERIFIED });
  17645. }
  17646. break;
  17647. default:
  17648. throw new TypeError('ChatBox.onSMP: Unknown type for SMP');
  17649. }
  17650. },
  17651. initiateOTR: function initiateOTR(query_msg) {
  17652. var _this = this;
  17653. // Sets up an OTR object through which we can send and receive
  17654. // encrypted messages.
  17655. //
  17656. // If 'query_msg' is passed in, it means there is an alread incoming
  17657. // query message from our contact. Otherwise, it is us who will
  17658. // send the query message to them.
  17659. var _converse = this.__super__._converse,
  17660. __ = _converse.__;
  17661. this.save({ 'otr_status': UNENCRYPTED });
  17662. this.getSession(function (session) {
  17663. var _converse = _this.__super__._converse;
  17664. _this.otr = new otr.OTR({
  17665. fragment_size: 140,
  17666. send_interval: 200,
  17667. priv: session.key,
  17668. instance_tag: session.instance_tag,
  17669. debug: _this.debug
  17670. });
  17671. _this.otr.on('status', _this.updateOTRStatus.bind(_this));
  17672. _this.otr.on('smp', _this.onSMP.bind(_this));
  17673. _this.otr.on('ui', function (msg) {
  17674. _this.trigger('showReceivedOTRMessage', msg);
  17675. });
  17676. _this.otr.on('io', function (msg) {
  17677. _this.trigger('sendMessage', new _converse.Message({ message: msg }));
  17678. });
  17679. _this.otr.on('error', function (msg) {
  17680. _this.trigger('showOTRError', msg);
  17681. });
  17682. _this.trigger('showHelpMessages', [__('Exchanging private key with contact.')]);
  17683. if (query_msg) {
  17684. _this.otr.receiveMsg(query_msg);
  17685. } else {
  17686. _this.otr.sendQueryMsg();
  17687. }
  17688. });
  17689. },
  17690. endOTR: function endOTR() {
  17691. if (this.otr) {
  17692. this.otr.endOtr();
  17693. }
  17694. this.save({ 'otr_status': UNENCRYPTED });
  17695. }
  17696. },
  17697. ChatBoxView: {
  17698. events: {
  17699. 'click .toggle-otr': 'toggleOTRMenu',
  17700. 'click .start-otr': 'startOTRFromToolbar',
  17701. 'click .end-otr': 'endOTR',
  17702. 'click .auth-otr': 'authOTR'
  17703. },
  17704. initialize: function initialize() {
  17705. var _converse = this.__super__._converse;
  17706. this.__super__.initialize.apply(this, arguments);
  17707. this.model.on('change:otr_status', this.onOTRStatusChanged, this);
  17708. this.model.on('showOTRError', this.showOTRError, this);
  17709. this.model.on('showSentOTRMessage', function (text) {
  17710. this.showMessage({ 'message': text, 'sender': 'me' });
  17711. }, this);
  17712. this.model.on('showReceivedOTRMessage', function (text) {
  17713. this.showMessage({ 'message': text, 'sender': 'them' });
  17714. }, this);
  17715. if (_.includes([UNVERIFIED, VERIFIED], this.model.get('otr_status')) || _converse.use_otr_by_default) {
  17716. this.model.initiateOTR();
  17717. }
  17718. },
  17719. createMessageStanza: function createMessageStanza() {
  17720. var stanza = this.__super__.createMessageStanza.apply(this, arguments);
  17721. if (this.model.get('otr_status') !== UNENCRYPTED || utils.isOTRMessage(stanza.nodeTree)) {
  17722. // OTR messages aren't carbon copied
  17723. stanza.c('private', { 'xmlns': Strophe.NS.CARBONS }).up().c('no-store', { 'xmlns': Strophe.NS.HINTS }).up().c('no-permanent-store', { 'xmlns': Strophe.NS.HINTS }).up().c('no-copy', { 'xmlns': Strophe.NS.HINTS });
  17724. }
  17725. return stanza;
  17726. },
  17727. onMessageSubmitted: function onMessageSubmitted(text) {
  17728. var _converse = this.__super__._converse;
  17729. if (!_converse.connection.authenticated) {
  17730. return this.showHelpMessages(['Sorry, the connection has been lost, ' + 'and your message could not be sent'], 'error');
  17731. }
  17732. var match = text.replace(/^\s*/, "").match(/^\/(.*)\s*$/);
  17733. if (match) {
  17734. if (_converse.allow_otr && match[1] === "endotr") {
  17735. return this.endOTR();
  17736. } else if (_converse.allow_otr && match[1] === "otr") {
  17737. return this.model.initiateOTR();
  17738. }
  17739. }
  17740. if (_.includes([UNVERIFIED, VERIFIED], this.model.get('otr_status'))) {
  17741. // Off-the-record encryption is active
  17742. this.model.otr.sendMsg(text);
  17743. this.model.trigger('showSentOTRMessage', text);
  17744. } else {
  17745. this.__super__.onMessageSubmitted.apply(this, arguments);
  17746. }
  17747. },
  17748. onOTRStatusChanged: function onOTRStatusChanged() {
  17749. this.renderToolbar().informOTRChange();
  17750. },
  17751. informOTRChange: function informOTRChange() {
  17752. var _converse = this.__super__._converse,
  17753. __ = _converse.__,
  17754. data = this.model.toJSON(),
  17755. msgs = [];
  17756. if (data.otr_status === UNENCRYPTED) {
  17757. msgs.push(__("Your messages are not encrypted anymore"));
  17758. } else if (data.otr_status === UNVERIFIED) {
  17759. msgs.push(__("Your messages are now encrypted but your contact's identity has not been verified."));
  17760. } else if (data.otr_status === VERIFIED) {
  17761. msgs.push(__("Your contact's identify has been verified."));
  17762. } else if (data.otr_status === FINISHED) {
  17763. msgs.push(__("Your contact has ended encryption on their end, you should do the same."));
  17764. }
  17765. return this.showHelpMessages(msgs, 'info', false);
  17766. },
  17767. showOTRError: function showOTRError(msg) {
  17768. var _converse = this.__super__._converse,
  17769. __ = _converse.__;
  17770. if (msg === 'Message cannot be sent at this time.') {
  17771. this.showHelpMessages([__('Your message could not be sent')], 'error');
  17772. } else if (msg === 'Received an unencrypted message.') {
  17773. this.showHelpMessages([__('We received an unencrypted message')], 'error');
  17774. } else if (msg === 'Received an unreadable encrypted message.') {
  17775. this.showHelpMessages([__('We received an unreadable encrypted message')], 'error');
  17776. } else {
  17777. this.showHelpMessages(["Encryption error occured: " + msg], 'error');
  17778. }
  17779. _converse.log("OTR ERROR:" + msg, Strophe.LogLevel.ERROR);
  17780. },
  17781. startOTRFromToolbar: function startOTRFromToolbar(ev) {
  17782. ev.stopPropagation();
  17783. this.model.initiateOTR();
  17784. },
  17785. endOTR: function endOTR(ev) {
  17786. if (!_.isUndefined(ev)) {
  17787. ev.preventDefault();
  17788. ev.stopPropagation();
  17789. }
  17790. this.model.endOTR();
  17791. },
  17792. authOTR: function authOTR(ev) {
  17793. var _converse = this.__super__._converse,
  17794. __ = _converse.__,
  17795. _$$data = $(ev.target).data(),
  17796. scheme = _$$data.scheme;
  17797. var result = void 0,
  17798. question = void 0,
  17799. answer = void 0;
  17800. if (scheme === 'fingerprint') {
  17801. result = confirm(__('Here are the fingerprints, please confirm them with %1$s, outside of this chat.\n\nFingerprint for you, %2$s: %3$s\n\nFingerprint for %1$s: %4$s\n\nIf you have confirmed that the fingerprints match, click OK, otherwise click Cancel.', [this.model.get('fullname'), _converse.xmppstatus.get('fullname') || _converse.bare_jid, this.model.otr.priv.fingerprint(), this.model.otr.their_priv_pk.fingerprint()]));
  17802. if (result === true) {
  17803. this.model.save({ 'otr_status': VERIFIED });
  17804. } else {
  17805. this.model.save({ 'otr_status': UNVERIFIED });
  17806. }
  17807. } else if (scheme === 'smp') {
  17808. alert(__('You will be prompted to provide a security question and then an answer to that question.\n\nYour contact will then be prompted the same question and if they type the exact same answer (case sensitive), their identity will be verified.'));
  17809. question = prompt(__('What is your security question?'));
  17810. if (question) {
  17811. answer = prompt(__('What is the answer to the security question?'));
  17812. this.model.otr.smpSecret(answer, question);
  17813. }
  17814. } else {
  17815. this.showHelpMessages([__('Invalid authentication scheme provided')], 'error');
  17816. }
  17817. },
  17818. toggleOTRMenu: function toggleOTRMenu(ev) {
  17819. ev.stopPropagation();
  17820. var menu = this.el.querySelector('.toggle-otr ul');
  17821. var elements = _.difference(document.querySelectorAll('.toolbar-menu'), [menu]);
  17822. utils.slideInAllElements(elements).then(_.partial(utils.slideToggleElement, menu));
  17823. },
  17824. getOTRTooltip: function getOTRTooltip() {
  17825. var _converse = this.__super__._converse,
  17826. __ = _converse.__,
  17827. data = this.model.toJSON();
  17828. if (data.otr_status === UNENCRYPTED) {
  17829. return __('Your messages are not encrypted. Click here to enable OTR encryption.');
  17830. } else if (data.otr_status === UNVERIFIED) {
  17831. return __('Your messages are encrypted, but your contact has not been verified.');
  17832. } else if (data.otr_status === VERIFIED) {
  17833. return __('Your messages are encrypted and your contact verified.');
  17834. } else if (data.otr_status === FINISHED) {
  17835. return __('Your contact has closed their end of the private session, you should do the same');
  17836. }
  17837. },
  17838. renderToolbar: function renderToolbar(toolbar, options) {
  17839. var _converse = this.__super__._converse,
  17840. __ = _converse.__;
  17841. if (!_converse.show_toolbar) {
  17842. return;
  17843. }
  17844. var data = this.model.toJSON();
  17845. options = _.extend(options || {}, {
  17846. FINISHED: FINISHED,
  17847. UNENCRYPTED: UNENCRYPTED,
  17848. UNVERIFIED: UNVERIFIED,
  17849. VERIFIED: VERIFIED,
  17850. // FIXME: Leaky abstraction MUC
  17851. allow_otr: _converse.allow_otr && !this.is_chatroom,
  17852. label_end_encrypted_conversation: __('End encrypted conversation'),
  17853. label_refresh_encrypted_conversation: __('Refresh encrypted conversation'),
  17854. label_start_encrypted_conversation: __('Start encrypted conversation'),
  17855. label_verify_with_fingerprints: __('Verify with fingerprints'),
  17856. label_verify_with_smp: __('Verify with SMP'),
  17857. label_whats_this: __("What\'s this?"),
  17858. otr_status_class: OTR_CLASS_MAPPING[data.otr_status],
  17859. otr_tooltip: this.getOTRTooltip(),
  17860. otr_translated_status: OTR_TRANSLATED_MAPPING[data.otr_status]
  17861. });
  17862. this.__super__.renderToolbar.apply(this, arguments);
  17863. this.$el.find('.chat-toolbar').append(tpl_toolbar_otr(_.extend(this.model.toJSON(), options || {})));
  17864. return this;
  17865. }
  17866. }
  17867. },
  17868. initialize: function initialize() {
  17869. /* The initialize function gets called as soon as the plugin is
  17870. * loaded by converse.js's plugin machinery.
  17871. */
  17872. var _converse = this._converse,
  17873. __ = _converse.__;
  17874. _converse.api.settings.update({
  17875. allow_otr: true,
  17876. cache_otr_key: false,
  17877. use_otr_by_default: false
  17878. });
  17879. // Translation aware constants
  17880. // ---------------------------
  17881. // We can only call the __ translation method *after* converse.js
  17882. // has been initialized and with it the i18n machinery. That's why
  17883. // we do it here in the "initialize" method and not at the top of
  17884. // the module.
  17885. OTR_TRANSLATED_MAPPING[UNENCRYPTED] = __('unencrypted');
  17886. OTR_TRANSLATED_MAPPING[UNVERIFIED] = __('unverified');
  17887. OTR_TRANSLATED_MAPPING[VERIFIED] = __('verified');
  17888. OTR_TRANSLATED_MAPPING[FINISHED] = __('finished');
  17889. // Only allow OTR if we have the capability
  17890. _converse.allow_otr = _converse.allow_otr && HAS_CRYPTO;
  17891. // Only use OTR by default if allow OTR is enabled to begin with
  17892. _converse.use_otr_by_default = _converse.use_otr_by_default && _converse.allow_otr;
  17893. }
  17894. });
  17895. });
  17896. //# sourceMappingURL=converse-otr.js.map;
  17897. define('tpl!register_panel', ['lodash'], function(_) {return function(obj) {
  17898. obj || (obj = {});
  17899. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  17900. function print() { __p += __j.call(arguments, '') }
  17901. with (obj) {
  17902. __p += '<form id="converse-register" class="pure-form converse-form">\n <span class="reg-feedback"></span>\n <label>' +
  17903. __e(label_domain) +
  17904. '</label>\n ';
  17905. if (default_domain) { ;
  17906. __p += '\n ' +
  17907. __e(default_domain) +
  17908. '\n ';
  17909. } ;
  17910. __p += '\n ';
  17911. if (!default_domain) { ;
  17912. __p += '\n <input type="text" name="domain" placeholder="' +
  17913. __e(domain_placeholder) +
  17914. '">\n <p class="form-help">' +
  17915. __e(help_providers) +
  17916. ' <a href="' +
  17917. __e(href_providers) +
  17918. '" class="url" target="_blank" rel="noopener">' +
  17919. __e(help_providers_link) +
  17920. '</a>.</p>\n <input class="pure-button button-primary" type="submit" value="' +
  17921. __e(label_register) +
  17922. '">\n ';
  17923. } ;
  17924. __p += '\n</form>\n';
  17925. }
  17926. return __p
  17927. };});
  17928. define('tpl!register_tab', ['lodash'], function(_) {return function(obj) {
  17929. obj || (obj = {});
  17930. var __t, __p = '', __e = _.escape;
  17931. with (obj) {
  17932. __p += '<li><a class="s" data-id="register" href="#register">' +
  17933. __e(label_register) +
  17934. '</a></li>\n';
  17935. }
  17936. return __p
  17937. };});
  17938. define('tpl!registration_form', ['lodash'], function(_) {return function(obj) {
  17939. obj || (obj = {});
  17940. var __t, __p = '', __e = _.escape;
  17941. with (obj) {
  17942. __p += '<p class="provider-title">' +
  17943. __e(domain) +
  17944. '</p>\n<p class="title">' +
  17945. __e(title) +
  17946. '</p>\n<p class="instructions">' +
  17947. __e(instructions) +
  17948. '</p>\n';
  17949. }
  17950. return __p
  17951. };});
  17952. define('tpl!registration_request', ['lodash'], function(_) {return function(obj) {
  17953. obj || (obj = {});
  17954. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  17955. function print() { __p += __j.call(arguments, '') }
  17956. with (obj) {
  17957. __p += '<span class="spinner login-submit"></span>\n<p class="info">' +
  17958. __e(info_message) +
  17959. '</p>\n';
  17960. if (cancel) { ;
  17961. __p += '\n <button class="pure-button button-cancel hor_centered">' +
  17962. __e(cancel) +
  17963. '</button>\n';
  17964. } ;
  17965. __p += '\n';
  17966. }
  17967. return __p
  17968. };});
  17969. // Converse.js (A browser based XMPP chat client)
  17970. // http://conversejs.org
  17971. //
  17972. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  17973. // Licensed under the Mozilla Public License (MPLv2)
  17974. //
  17975. /*global define */
  17976. /* This is a Converse.js plugin which add support for in-band registration
  17977. * as specified in XEP-0077.
  17978. */
  17979. (function (root, factory) {
  17980. define('converse-register',["jquery.noconflict", "converse-core", "tpl!form_username", "tpl!register_panel", "tpl!register_tab", "tpl!registration_form", "tpl!registration_request", "tpl!spinner", "converse-controlbox"], factory);
  17981. })(undefined, function ($, converse, tpl_form_username, tpl_register_panel, tpl_register_tab, tpl_registration_form, tpl_registration_request, tpl_spinner) {
  17982. "use strict";
  17983. // Strophe methods for building stanzas
  17984. var _converse$env = converse.env,
  17985. Strophe = _converse$env.Strophe,
  17986. Backbone = _converse$env.Backbone,
  17987. utils = _converse$env.utils,
  17988. $iq = _converse$env.$iq,
  17989. _ = _converse$env._;
  17990. // Add Strophe Namespaces
  17991. Strophe.addNamespace('REGISTER', 'jabber:iq:register');
  17992. // Add Strophe Statuses
  17993. var i = 0;
  17994. _.each(_.keys(Strophe.Status), function (key) {
  17995. i = Math.max(i, Strophe.Status[key]);
  17996. });
  17997. Strophe.Status.REGIFAIL = i + 1;
  17998. Strophe.Status.REGISTERED = i + 2;
  17999. Strophe.Status.CONFLICT = i + 3;
  18000. Strophe.Status.NOTACCEPTABLE = i + 5;
  18001. converse.plugins.add('converse-register', {
  18002. overrides: {
  18003. // Overrides mentioned here will be picked up by converse.js's
  18004. // plugin architecture they will replace existing methods on the
  18005. // relevant objects or classes.
  18006. //
  18007. // New functions which don't exist yet can also be added.
  18008. ControlBoxView: {
  18009. switchTab: function switchTab(ev) {
  18010. var _converse = this.__super__._converse;
  18011. var result = this.__super__.switchTab.apply(this, arguments);
  18012. if (_converse.registration_domain && ev.target.getAttribute('data-id') === "register" && !this.model.get('registration_form_rendered')) {
  18013. this.registerpanel.fetchRegistrationForm(_converse.registration_domain);
  18014. }
  18015. return result;
  18016. },
  18017. renderRegistrationPanel: function renderRegistrationPanel() {
  18018. var _converse = this.__super__._converse;
  18019. if (_converse.allow_registration) {
  18020. this.registerpanel = new _converse.RegisterPanel({
  18021. '$parent': this.$el.find('.controlbox-panes'),
  18022. 'model': this.model
  18023. });
  18024. this.registerpanel.render().$el.addClass('hidden');
  18025. }
  18026. return this;
  18027. },
  18028. renderLoginPanel: function renderLoginPanel() {
  18029. /* Also render a registration panel, when rendering the
  18030. * login panel.
  18031. */
  18032. this.__super__.renderLoginPanel.apply(this, arguments);
  18033. this.renderRegistrationPanel();
  18034. return this;
  18035. }
  18036. }
  18037. },
  18038. initialize: function initialize() {
  18039. /* The initialize function gets called as soon as the plugin is
  18040. * loaded by converse.js's plugin machinery.
  18041. */
  18042. var _converse = this._converse,
  18043. __ = _converse.__;
  18044. // Add new templates
  18045. _converse.templates.form_username = tpl_form_username;
  18046. _converse.templates.register_panel = tpl_register_panel;
  18047. _converse.templates.register_tab = tpl_register_tab;
  18048. _converse.templates.registration_form = tpl_registration_form;
  18049. _converse.templates.registration_request = tpl_registration_request;
  18050. _converse.api.settings.update({
  18051. allow_registration: true,
  18052. domain_placeholder: __(" e.g. conversejs.org"), // Placeholder text shown in the domain input on the registration form
  18053. providers_link: 'https://xmpp.net/directory.php' // Link to XMPP providers shown on registration page
  18054. });
  18055. _converse.RegisterPanel = Backbone.View.extend({
  18056. tagName: 'div',
  18057. id: "register",
  18058. className: 'controlbox-pane',
  18059. events: {
  18060. 'submit form#converse-register': 'onProviderChosen'
  18061. },
  18062. initialize: function initialize(cfg) {
  18063. this.reset();
  18064. this.$parent = cfg.$parent;
  18065. this.$tabs = cfg.$parent.parent().find('#controlbox-tabs');
  18066. this.registerHooks();
  18067. },
  18068. render: function render() {
  18069. this.model.set('registration_form_rendered', false);
  18070. this.$parent.append(this.$el.html(tpl_register_panel({
  18071. 'default_domain': _converse.registration_domain,
  18072. 'label_domain': __("Your XMPP provider's domain name:"),
  18073. 'label_register': __('Fetch registration form'),
  18074. 'help_providers': __('Tip: A list of public XMPP providers is available'),
  18075. 'help_providers_link': __('here'),
  18076. 'href_providers': _converse.providers_link,
  18077. 'domain_placeholder': _converse.domain_placeholder
  18078. })));
  18079. this.$tabs.append(tpl_register_tab({ label_register: __('Register') }));
  18080. return this;
  18081. },
  18082. registerHooks: function registerHooks() {
  18083. var _this = this;
  18084. /* Hook into Strophe's _connect_cb, so that we can send an IQ
  18085. * requesting the registration fields.
  18086. */
  18087. var conn = _converse.connection;
  18088. var connect_cb = conn._connect_cb.bind(conn);
  18089. conn._connect_cb = function (req, callback, raw) {
  18090. if (!_this._registering) {
  18091. connect_cb(req, callback, raw);
  18092. } else {
  18093. if (_this.getRegistrationFields(req, callback, raw)) {
  18094. _this._registering = false;
  18095. }
  18096. }
  18097. };
  18098. },
  18099. getRegistrationFields: function getRegistrationFields(req, _callback, raw) {
  18100. /* Send an IQ stanza to the XMPP server asking for the
  18101. * registration fields.
  18102. * Parameters:
  18103. * (Strophe.Request) req - The current request
  18104. * (Function) callback
  18105. */
  18106. var conn = _converse.connection;
  18107. conn.connected = true;
  18108. var body = conn._proto._reqToData(req);
  18109. if (!body) {
  18110. return;
  18111. }
  18112. if (conn._proto._connect_cb(body) === Strophe.Status.CONNFAIL) {
  18113. return false;
  18114. }
  18115. var register = body.getElementsByTagName("register");
  18116. var mechanisms = body.getElementsByTagName("mechanism");
  18117. if (register.length === 0 && mechanisms.length === 0) {
  18118. conn._proto._no_auth_received(_callback);
  18119. return false;
  18120. }
  18121. if (register.length === 0) {
  18122. conn._changeConnectStatus(Strophe.Status.REGIFAIL, __("Sorry, the given provider does not support in " + "band account registration. Please try with a " + "different provider."));
  18123. return true;
  18124. }
  18125. // Send an IQ stanza to get all required data fields
  18126. conn._addSysHandler(this.onRegistrationFields.bind(this), null, "iq", null, null);
  18127. conn.send($iq({ type: "get" }).c("query", { xmlns: Strophe.NS.REGISTER }).tree());
  18128. conn.connected = false;
  18129. return true;
  18130. },
  18131. onRegistrationFields: function onRegistrationFields(stanza) {
  18132. /* Handler for Registration Fields Request.
  18133. *
  18134. * Parameters:
  18135. * (XMLElement) elem - The query stanza.
  18136. */
  18137. if (stanza.getElementsByTagName("query").length !== 1) {
  18138. _converse.connection._changeConnectStatus(Strophe.Status.REGIFAIL, "unknown");
  18139. return false;
  18140. }
  18141. this.setFields(stanza);
  18142. this.renderRegistrationForm(stanza);
  18143. return false;
  18144. },
  18145. reset: function reset(settings) {
  18146. var defaults = {
  18147. fields: {},
  18148. urls: [],
  18149. title: "",
  18150. instructions: "",
  18151. registered: false,
  18152. _registering: false,
  18153. domain: null,
  18154. form_type: null
  18155. };
  18156. _.extend(this, defaults);
  18157. if (settings) {
  18158. _.extend(this, _.pick(settings, _.keys(defaults)));
  18159. }
  18160. },
  18161. onProviderChosen: function onProviderChosen(ev) {
  18162. /* Callback method that gets called when the user has chosen an
  18163. * XMPP provider.
  18164. *
  18165. * Parameters:
  18166. * (Submit Event) ev - Form submission event.
  18167. */
  18168. if (ev && ev.preventDefault) {
  18169. ev.preventDefault();
  18170. }
  18171. var $form = $(ev.target),
  18172. $domain_input = $form.find('input[name=domain]'),
  18173. domain = $domain_input.val();
  18174. if (!domain) {
  18175. $domain_input.addClass('error');
  18176. return;
  18177. }
  18178. $form.find('input[type=submit]').hide();
  18179. this.fetchRegistrationForm(domain, __('Cancel'));
  18180. },
  18181. fetchRegistrationForm: function fetchRegistrationForm(domain_name, cancel_label) {
  18182. /* This is called with a domain name based on which, it fetches a
  18183. * registration form from the requested domain.
  18184. *
  18185. * Parameters:
  18186. * (Domain name) domain_name - XMPP server domain
  18187. */
  18188. this.renderRegistrationRequest(cancel_label);
  18189. this.reset({
  18190. domain: Strophe.getDomainFromJid(domain_name),
  18191. _registering: true
  18192. });
  18193. _converse.connection.connect(this.domain, "", this.onRegistering.bind(this));
  18194. return false;
  18195. },
  18196. renderRegistrationRequest: function renderRegistrationRequest(cancel_label) {
  18197. var form = this.el.querySelector('#converse-register');
  18198. var markup = tpl_registration_request({
  18199. 'cancel': cancel_label,
  18200. 'info_message': _converse.__('Requesting a registration form from the XMPP server')
  18201. });
  18202. form.appendChild(utils.createFragmentFromText(markup));
  18203. if (!_converse.registration_domain) {
  18204. var cancel_button = document.querySelector('button.button-cancel');
  18205. cancel_button.addEventListener('click', this.cancelRegistration.bind(this));
  18206. }
  18207. },
  18208. giveFeedback: function giveFeedback(message, klass) {
  18209. this.$('.reg-feedback').attr('class', 'reg-feedback').text(message);
  18210. if (klass) {
  18211. $('.reg-feedback').addClass(klass);
  18212. }
  18213. },
  18214. onRegistering: function onRegistering(status, error) {
  18215. var that = void 0;
  18216. _converse.log('onRegistering');
  18217. if (_.includes([Strophe.Status.DISCONNECTED, Strophe.Status.CONNFAIL, Strophe.Status.REGIFAIL, Strophe.Status.NOTACCEPTABLE, Strophe.Status.CONFLICT], status)) {
  18218. _converse.log("Problem during registration: Strophe.Status is: " + status, Strophe.LogLevel.ERROR);
  18219. this.cancelRegistration();
  18220. if (error) {
  18221. this.giveFeedback(error, 'error');
  18222. } else {
  18223. this.giveFeedback(__('Something went wrong while establishing a connection with "%1$s". Are you sure it exists?', this.domain), 'error');
  18224. }
  18225. } else if (status === Strophe.Status.REGISTERED) {
  18226. _converse.log("Registered successfully.");
  18227. _converse.connection.reset();
  18228. that = this;
  18229. this.$('form').hide(function () {
  18230. $(this).replaceWith(tpl_spinner);
  18231. if (that.fields.password && that.fields.username) {
  18232. // automatically log the user in
  18233. _converse.connection.connect(that.fields.username.toLowerCase() + '@' + that.domain.toLowerCase(), that.fields.password, _converse.onConnectStatusChanged);
  18234. _converse.chatboxviews.get('controlbox').switchTab({ 'target': that.$tabs.find('.current') });
  18235. _converse.giveFeedback(__('Now logging you in'));
  18236. } else {
  18237. _converse.chatboxviews.get('controlbox').renderLoginPanel();
  18238. _converse.giveFeedback(__('Registered successfully'));
  18239. }
  18240. that.reset();
  18241. });
  18242. }
  18243. },
  18244. renderRegistrationForm: function renderRegistrationForm(stanza) {
  18245. var _this2 = this;
  18246. /* Renders the registration form based on the XForm fields
  18247. * received from the XMPP server.
  18248. *
  18249. * Parameters:
  18250. * (XMLElement) stanza - The IQ stanza received from the XMPP server.
  18251. */
  18252. this.model.set('registration_form_rendered', true);
  18253. var $form = this.$('form'),
  18254. $stanza = $(stanza);
  18255. var $fields = void 0,
  18256. $input = void 0;
  18257. $form.empty().append(tpl_registration_form({
  18258. 'domain': this.domain,
  18259. 'title': this.title,
  18260. 'instructions': this.instructions
  18261. }));
  18262. if (this.form_type === 'xform') {
  18263. $fields = $stanza.find('field');
  18264. _.each($fields, function (field) {
  18265. $form.append(utils.xForm2webForm.bind(_this2, $(field), $stanza));
  18266. });
  18267. } else {
  18268. // Show fields
  18269. _.each(_.keys(this.fields), function (key) {
  18270. if (key === "username") {
  18271. $input = tpl_form_username({
  18272. domain: " @" + _this2.domain,
  18273. name: key,
  18274. type: "text",
  18275. label: key,
  18276. value: '',
  18277. required: 1
  18278. });
  18279. } else {
  18280. $form.append("<label>" + key + "</label>");
  18281. $input = $("<input placeholder=\"" + key + "\" name=\"" + key + "\"></input>");
  18282. if (key === 'password' || key === 'email') {
  18283. $input.attr('type', key);
  18284. }
  18285. }
  18286. $form.append($input);
  18287. });
  18288. // Show urls
  18289. _.each(this.urls, function (url) {
  18290. $form.append($('<a target="blank"></a>').attr('href', url).text(url));
  18291. });
  18292. }
  18293. if (this.fields) {
  18294. $form.append("<input type=\"submit\" class=\"pure-button button-primary\" value=\"" + __('Register') + "\"/>");
  18295. $form.on('submit', this.submitRegistrationForm.bind(this));
  18296. $form.append("<input type=\"button\" class=\"pure-button button-cancel\" value=\"" + __('Cancel') + "\"/>");
  18297. $form.find('input[type=button]').on('click', this.cancelRegistration.bind(this));
  18298. } else {
  18299. $form.append("<input type=\"button\" class=\"submit\" value=\"" + __('Return') + "\"/>");
  18300. $form.find('input[type=button]').on('click', this.cancelRegistration.bind(this));
  18301. }
  18302. if (_converse.registration_domain) {
  18303. $form.find('input[type=button]').hide();
  18304. }
  18305. },
  18306. reportErrors: function reportErrors(stanza) {
  18307. /* Report back to the user any error messages received from the
  18308. * XMPP server after attempted registration.
  18309. *
  18310. * Parameters:
  18311. * (XMLElement) stanza - The IQ stanza received from the
  18312. * XMPP server.
  18313. */
  18314. var $form = this.$('form'),
  18315. $errmsgs = $(stanza).find('error text');
  18316. var $flash = $form.find('.form-errors');
  18317. if (!$flash.length) {
  18318. var flash = '<legend class="form-errors"></legend>';
  18319. if ($form.find('p.instructions').length) {
  18320. $form.find('p.instructions').append(flash);
  18321. } else {
  18322. $form.prepend(flash);
  18323. }
  18324. $flash = $form.find('.form-errors');
  18325. } else {
  18326. $flash.empty();
  18327. }
  18328. $errmsgs.each(function (idx, txt) {
  18329. $flash.append($('<p>').text($(txt).text()));
  18330. });
  18331. if (!$errmsgs.length) {
  18332. $flash.append($('<p>').text(__('The provider rejected your registration attempt. ' + 'Please check the values you entered for correctness.')));
  18333. }
  18334. $flash.show();
  18335. },
  18336. cancelRegistration: function cancelRegistration(ev) {
  18337. /* Handler, when the user cancels the registration form.
  18338. */
  18339. if (ev && ev.preventDefault) {
  18340. ev.preventDefault();
  18341. }
  18342. _converse.connection.reset();
  18343. this.model.set('registration_form_rendered', false);
  18344. this.render();
  18345. if (_converse.registration_domain) {
  18346. document.querySelector('button.button-cancel').onclick = _.bind(this.fetchRegistrationForm, this, _converse.registration_domain, __('Retry'));
  18347. }
  18348. },
  18349. submitRegistrationForm: function submitRegistrationForm(ev) {
  18350. /* Handler, when the user submits the registration form.
  18351. * Provides form error feedback or starts the registration
  18352. * process.
  18353. *
  18354. * Parameters:
  18355. * (Event) ev - the submit event.
  18356. */
  18357. if (ev && ev.preventDefault) {
  18358. ev.preventDefault();
  18359. }
  18360. var has_empty_inputs = _.reduce(this.el.querySelectorAll('input.required'), function (result, input) {
  18361. if (input.value === '') {
  18362. input.classList.add('error');
  18363. return result + 1;
  18364. }
  18365. return result;
  18366. }, 0);
  18367. if (has_empty_inputs) {
  18368. return;
  18369. }
  18370. var $inputs = $(ev.target).find(':input:not([type=button]):not([type=submit])'),
  18371. iq = $iq({ type: "set" }).c("query", { xmlns: Strophe.NS.REGISTER });
  18372. if (this.form_type === 'xform') {
  18373. iq.c("x", { xmlns: Strophe.NS.XFORM, type: 'submit' });
  18374. $inputs.each(function () {
  18375. iq.cnode(utils.webForm2xForm(this)).up();
  18376. });
  18377. } else {
  18378. $inputs.each(function () {
  18379. var $input = $(this);
  18380. iq.c($input.attr('name'), {}, $input.val());
  18381. });
  18382. }
  18383. this.model.set('registration_form_rendered', false);
  18384. _converse.connection._addSysHandler(this._onRegisterIQ.bind(this), null, "iq", null, null);
  18385. _converse.connection.send(iq);
  18386. this.setFields(iq.tree());
  18387. },
  18388. setFields: function setFields(stanza) {
  18389. /* Stores the values that will be sent to the XMPP server
  18390. * during attempted registration.
  18391. *
  18392. * Parameters:
  18393. * (XMLElement) stanza - the IQ stanza that will be sent to the XMPP server.
  18394. */
  18395. var $query = $(stanza).find('query');
  18396. if ($query.length > 0) {
  18397. var $xform = $query.find("x[xmlns=\"" + Strophe.NS.XFORM + "\"]");
  18398. if ($xform.length > 0) {
  18399. this._setFieldsFromXForm($xform);
  18400. } else {
  18401. this._setFieldsFromLegacy($query);
  18402. }
  18403. }
  18404. },
  18405. _setFieldsFromLegacy: function _setFieldsFromLegacy($query) {
  18406. var _this3 = this;
  18407. $query.children().each(function (idx, field) {
  18408. var $field = $(field);
  18409. if (field.tagName.toLowerCase() === 'instructions') {
  18410. _this3.instructions = Strophe.getText(field);
  18411. return;
  18412. } else if (field.tagName.toLowerCase() === 'x') {
  18413. if ($field.attr('xmlns') === 'jabber:x:oob') {
  18414. $field.find('url').each(function (idx, url) {
  18415. _this3.urls.push($(url).text());
  18416. });
  18417. }
  18418. return;
  18419. }
  18420. _this3.fields[field.tagName.toLowerCase()] = Strophe.getText(field);
  18421. });
  18422. this.form_type = 'legacy';
  18423. },
  18424. _setFieldsFromXForm: function _setFieldsFromXForm($xform) {
  18425. var _this4 = this;
  18426. this.title = $xform.find('title').text();
  18427. this.instructions = $xform.find('instructions').text();
  18428. $xform.find('field').each(function (idx, field) {
  18429. var _var = field.getAttribute('var');
  18430. if (_var) {
  18431. _this4.fields[_var.toLowerCase()] = $(field).children('value').text();
  18432. } else {
  18433. // TODO: other option seems to be type="fixed"
  18434. _converse.log("Found field we couldn't parse", Strophe.LogLevel.WARN);
  18435. }
  18436. });
  18437. this.form_type = 'xform';
  18438. },
  18439. _onRegisterIQ: function _onRegisterIQ(stanza) {
  18440. /* Callback method that gets called when a return IQ stanza
  18441. * is received from the XMPP server, after attempting to
  18442. * register a new user.
  18443. *
  18444. * Parameters:
  18445. * (XMLElement) stanza - The IQ stanza.
  18446. */
  18447. var error = null,
  18448. query = stanza.getElementsByTagName("query");
  18449. if (query.length > 0) {
  18450. query = query[0];
  18451. }
  18452. if (stanza.getAttribute("type") === "error") {
  18453. _converse.log("Registration failed.", Strophe.LogLevel.ERROR);
  18454. error = stanza.getElementsByTagName("error");
  18455. if (error.length !== 1) {
  18456. _converse.connection._changeConnectStatus(Strophe.Status.REGIFAIL, "unknown");
  18457. return false;
  18458. }
  18459. error = error[0].firstChild.tagName.toLowerCase();
  18460. if (error === 'conflict') {
  18461. _converse.connection._changeConnectStatus(Strophe.Status.CONFLICT, error);
  18462. } else if (error === 'not-acceptable') {
  18463. _converse.connection._changeConnectStatus(Strophe.Status.NOTACCEPTABLE, error);
  18464. } else {
  18465. _converse.connection._changeConnectStatus(Strophe.Status.REGIFAIL, error);
  18466. }
  18467. this.reportErrors(stanza);
  18468. } else {
  18469. _converse.connection._changeConnectStatus(Strophe.Status.REGISTERED, null);
  18470. }
  18471. return false;
  18472. },
  18473. remove: function remove() {
  18474. this.$tabs.empty();
  18475. this.$el.parent().empty();
  18476. }
  18477. });
  18478. }
  18479. });
  18480. });
  18481. //# sourceMappingURL=converse-register.js.map;
  18482. // Converse.js (A browser based XMPP chat client)
  18483. // http://conversejs.org
  18484. //
  18485. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  18486. // Licensed under the Mozilla Public License (MPLv2)
  18487. //
  18488. /*global define */
  18489. /* This is a Converse.js plugin which add support for application-level pings
  18490. * as specified in XEP-0199 XMPP Ping.
  18491. */
  18492. (function (root, factory) {
  18493. define('converse-ping',["converse-core", "strophe.ping"], factory);
  18494. })(undefined, function (converse) {
  18495. "use strict";
  18496. // Strophe methods for building stanzas
  18497. var _converse$env = converse.env,
  18498. Strophe = _converse$env.Strophe,
  18499. _ = _converse$env._;
  18500. converse.plugins.add('converse-ping', {
  18501. initialize: function initialize() {
  18502. /* The initialize function gets called as soon as the plugin is
  18503. * loaded by converse.js's plugin machinery.
  18504. */
  18505. var _converse = this._converse;
  18506. _converse.api.settings.update({
  18507. ping_interval: 180 //in seconds
  18508. });
  18509. _converse.ping = function (jid, success, error, timeout) {
  18510. // XXX: We could first check here if the server advertised that
  18511. // it supports PING.
  18512. // However, some servers don't advertise while still keeping the
  18513. // connection option due to pings.
  18514. //
  18515. // var feature = _converse.disco_entities[_converse.domain].features.findWhere({'var': Strophe.NS.PING});
  18516. _converse.lastStanzaDate = new Date();
  18517. if (_.isNil(jid)) {
  18518. jid = Strophe.getDomainFromJid(_converse.bare_jid);
  18519. }
  18520. if (_.isUndefined(timeout)) {
  18521. timeout = null;
  18522. }
  18523. if (_.isUndefined(success)) {
  18524. success = null;
  18525. }
  18526. if (_.isUndefined(error)) {
  18527. error = null;
  18528. }
  18529. if (_converse.connection) {
  18530. _converse.connection.ping.ping(jid, success, error, timeout);
  18531. return true;
  18532. }
  18533. return false;
  18534. };
  18535. _converse.pong = function (ping) {
  18536. _converse.lastStanzaDate = new Date();
  18537. _converse.connection.ping.pong(ping);
  18538. return true;
  18539. };
  18540. _converse.registerPongHandler = function () {
  18541. _converse.connection.disco.addFeature(Strophe.NS.PING);
  18542. _converse.connection.ping.addPingHandler(_converse.pong);
  18543. };
  18544. _converse.registerPingHandler = function () {
  18545. _converse.registerPongHandler();
  18546. if (_converse.ping_interval > 0) {
  18547. _converse.connection.addHandler(function () {
  18548. /* Handler on each stanza, saves the received date
  18549. * in order to ping only when needed.
  18550. */
  18551. _converse.lastStanzaDate = new Date();
  18552. return true;
  18553. });
  18554. _converse.connection.addTimedHandler(1000, function () {
  18555. var now = new Date();
  18556. if (!_converse.lastStanzaDate) {
  18557. _converse.lastStanzaDate = now;
  18558. }
  18559. if ((now - _converse.lastStanzaDate) / 1000 > _converse.ping_interval) {
  18560. return _converse.ping();
  18561. }
  18562. return true;
  18563. });
  18564. }
  18565. };
  18566. var onConnected = function onConnected() {
  18567. // Wrapper so that we can spy on registerPingHandler in tests
  18568. _converse.registerPingHandler();
  18569. };
  18570. _converse.on('connected', onConnected);
  18571. _converse.on('reconnected', onConnected);
  18572. }
  18573. });
  18574. });
  18575. //# sourceMappingURL=converse-ping.js.map;
  18576. // Converse.js (A browser based XMPP chat client)
  18577. // http://conversejs.org
  18578. //
  18579. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  18580. // Licensed under the Mozilla Public License (MPLv2)
  18581. //
  18582. /*global define */
  18583. (function (root, factory) {
  18584. define('converse-notification',["converse-core"], factory);
  18585. })(undefined, function (converse) {
  18586. "use strict";
  18587. var _converse$env = converse.env,
  18588. utils = _converse$env.utils,
  18589. Strophe = _converse$env.Strophe,
  18590. _ = _converse$env._;
  18591. converse.plugins.add('converse-notification', {
  18592. initialize: function initialize() {
  18593. /* The initialize function gets called as soon as the plugin is
  18594. * loaded by converse.js's plugin machinery.
  18595. */
  18596. var _converse = this._converse;
  18597. // For translations
  18598. var __ = _converse.__;
  18599. var ___ = _converse.___;
  18600. _converse.supports_html5_notification = "Notification" in window;
  18601. _converse.api.settings.update({
  18602. notify_all_room_messages: false,
  18603. show_desktop_notifications: true,
  18604. show_chatstate_notifications: false,
  18605. chatstate_notification_blacklist: [],
  18606. // ^ a list of JIDs to ignore concerning chat state notifications
  18607. play_sounds: true,
  18608. sounds_path: '/sounds/',
  18609. notification_icon: '/logo/conversejs128.png'
  18610. });
  18611. _converse.isOnlyChatStateNotification = function (msg) {
  18612. return (
  18613. // See XEP-0085 Chat State Notification
  18614. _.isNull(msg.querySelector('body')) && (_.isNull(msg.querySelector(_converse.ACTIVE)) || _.isNull(msg.querySelector(_converse.COMPOSING)) || _.isNull(msg.querySelector(_converse.INACTIVE)) || _.isNull(msg.querySelector(_converse.PAUSED)) || _.isNull(msg.querySelector(_converse.GONE)))
  18615. );
  18616. };
  18617. _converse.shouldNotifyOfGroupMessage = function (message) {
  18618. /* Is this a group message worthy of notification?
  18619. */
  18620. var notify_all = _converse.notify_all_room_messages;
  18621. var jid = message.getAttribute('from'),
  18622. resource = Strophe.getResourceFromJid(jid),
  18623. room_jid = Strophe.getBareJidFromJid(jid),
  18624. sender = resource && Strophe.unescapeNode(resource) || '';
  18625. if (sender === '' || message.querySelectorAll('delay').length > 0) {
  18626. return false;
  18627. }
  18628. var room = _converse.chatboxes.get(room_jid);
  18629. var body = message.querySelector('body');
  18630. if (_.isNull(body)) {
  18631. return false;
  18632. }
  18633. var mentioned = new RegExp("\\b" + room.get('nick') + "\\b").test(body.textContent);
  18634. notify_all = notify_all === true || _.isArray(notify_all) && _.includes(notify_all, room_jid);
  18635. if (sender === room.get('nick') || !notify_all && !mentioned) {
  18636. return false;
  18637. }
  18638. return true;
  18639. };
  18640. _converse.shouldNotifyOfMessage = function (message) {
  18641. /* Is this a message worthy of notification?
  18642. */
  18643. if (utils.isOTRMessage(message)) {
  18644. return false;
  18645. }
  18646. var forwarded = message.querySelector('forwarded');
  18647. if (!_.isNull(forwarded)) {
  18648. return false;
  18649. } else if (message.getAttribute('type') === 'groupchat') {
  18650. return _converse.shouldNotifyOfGroupMessage(message);
  18651. } else if (utils.isHeadlineMessage(message)) {
  18652. // We want to show notifications for headline messages.
  18653. return true;
  18654. }
  18655. var is_me = Strophe.getBareJidFromJid(message.getAttribute('from')) === _converse.bare_jid;
  18656. return !_converse.isOnlyChatStateNotification(message) && !is_me;
  18657. };
  18658. _converse.playSoundNotification = function () {
  18659. /* Plays a sound to notify that a new message was recieved.
  18660. */
  18661. // XXX Eventually this can be refactored to use Notification's sound
  18662. // feature, but no browser currently supports it.
  18663. // https://developer.mozilla.org/en-US/docs/Web/API/notification/sound
  18664. var audio = void 0;
  18665. if (_converse.play_sounds && !_.isUndefined(window.Audio)) {
  18666. audio = new Audio(_converse.sounds_path + "msg_received.ogg");
  18667. if (audio.canPlayType('/audio/ogg')) {
  18668. audio.play();
  18669. } else {
  18670. audio = new Audio(_converse.sounds_path + "msg_received.mp3");
  18671. audio.play();
  18672. }
  18673. }
  18674. };
  18675. _converse.areDesktopNotificationsEnabled = function (ignore_hidden) {
  18676. var enabled = _converse.supports_html5_notification && _converse.show_desktop_notifications && Notification.permission === "granted";
  18677. if (ignore_hidden) {
  18678. return enabled;
  18679. } else {
  18680. return enabled && _converse.windowState === 'hidden';
  18681. }
  18682. };
  18683. _converse.showMessageNotification = function (message) {
  18684. /* Shows an HTML5 Notification to indicate that a new chat
  18685. * message was received.
  18686. */
  18687. var title = void 0,
  18688. roster_item = void 0;
  18689. var full_from_jid = message.getAttribute('from'),
  18690. from_jid = Strophe.getBareJidFromJid(full_from_jid);
  18691. if (message.getAttribute('type') === 'headline') {
  18692. if (!_.includes(from_jid, '@') || _converse.allow_non_roster_messaging) {
  18693. title = __(___("Notification from %1$s"), from_jid);
  18694. } else {
  18695. return;
  18696. }
  18697. } else if (!_.includes(from_jid, '@')) {
  18698. // XXX: workaround for Prosody which doesn't give type "headline"
  18699. title = __(___("Notification from %1$s"), from_jid);
  18700. } else if (message.getAttribute('type') === 'groupchat') {
  18701. title = __(___("%1$s says"), Strophe.getResourceFromJid(full_from_jid));
  18702. } else {
  18703. if (_.isUndefined(_converse.roster)) {
  18704. _converse.log("Could not send notification, because roster is undefined", Strophe.LogLevel.ERROR);
  18705. return;
  18706. }
  18707. roster_item = _converse.roster.get(from_jid);
  18708. if (!_.isUndefined(roster_item)) {
  18709. title = __(___("%1$s says"), roster_item.get('fullname'));
  18710. } else {
  18711. if (_converse.allow_non_roster_messaging) {
  18712. title = __(___("%1$s says"), from_jid);
  18713. } else {
  18714. return;
  18715. }
  18716. }
  18717. }
  18718. var n = new Notification(title, {
  18719. body: message.querySelector('body').textContent,
  18720. lang: _converse.locale,
  18721. icon: _converse.notification_icon
  18722. });
  18723. setTimeout(n.close.bind(n), 5000);
  18724. };
  18725. _converse.showChatStateNotification = function (contact) {
  18726. /* Creates an HTML5 Notification to inform of a change in a
  18727. * contact's chat state.
  18728. */
  18729. if (_.includes(_converse.chatstate_notification_blacklist, contact.jid)) {
  18730. // Don't notify if the user is being ignored.
  18731. return;
  18732. }
  18733. var chat_state = contact.chat_status;
  18734. var message = null;
  18735. if (chat_state === 'offline') {
  18736. message = __('has gone offline');
  18737. } else if (chat_state === 'away') {
  18738. message = __('has gone away');
  18739. } else if (chat_state === 'dnd') {
  18740. message = __('is busy');
  18741. } else if (chat_state === 'online') {
  18742. message = __('has come online');
  18743. }
  18744. if (message === null) {
  18745. return;
  18746. }
  18747. var n = new Notification(contact.fullname, {
  18748. body: message,
  18749. lang: _converse.locale,
  18750. icon: _converse.notification_icon
  18751. });
  18752. setTimeout(n.close.bind(n), 5000);
  18753. };
  18754. _converse.showContactRequestNotification = function (contact) {
  18755. var n = new Notification(contact.fullname, {
  18756. body: __('wants to be your contact'),
  18757. lang: _converse.locale,
  18758. icon: _converse.notification_icon
  18759. });
  18760. setTimeout(n.close.bind(n), 5000);
  18761. };
  18762. _converse.showFeedbackNotification = function (data) {
  18763. if (data.klass === 'error' || data.klass === 'warn') {
  18764. var n = new Notification(data.subject, {
  18765. body: data.message,
  18766. lang: _converse.locale,
  18767. icon: _converse.notification_icon
  18768. });
  18769. setTimeout(n.close.bind(n), 5000);
  18770. }
  18771. };
  18772. _converse.handleChatStateNotification = function (contact) {
  18773. /* Event handler for on('contactStatusChanged').
  18774. * Will show an HTML5 notification to indicate that the chat
  18775. * status has changed.
  18776. */
  18777. if (_converse.areDesktopNotificationsEnabled() && _converse.show_chatstate_notifications) {
  18778. _converse.showChatStateNotification(contact);
  18779. }
  18780. };
  18781. _converse.handleMessageNotification = function (data) {
  18782. /* Event handler for the on('message') event. Will call methods
  18783. * to play sounds and show HTML5 notifications.
  18784. */
  18785. var message = data.stanza;
  18786. if (!_converse.shouldNotifyOfMessage(message)) {
  18787. return false;
  18788. }
  18789. _converse.playSoundNotification();
  18790. if (_converse.areDesktopNotificationsEnabled()) {
  18791. _converse.showMessageNotification(message);
  18792. }
  18793. };
  18794. _converse.handleContactRequestNotification = function (contact) {
  18795. if (_converse.areDesktopNotificationsEnabled(true)) {
  18796. _converse.showContactRequestNotification(contact);
  18797. }
  18798. };
  18799. _converse.handleFeedback = function (data) {
  18800. if (_converse.areDesktopNotificationsEnabled(true)) {
  18801. _converse.showFeedbackNotification(data);
  18802. }
  18803. };
  18804. _converse.requestPermission = function () {
  18805. if (_converse.supports_html5_notification && !_.includes(['denied', 'granted'], Notification.permission)) {
  18806. // Ask user to enable HTML5 notifications
  18807. Notification.requestPermission();
  18808. }
  18809. };
  18810. _converse.on('pluginsInitialized', function () {
  18811. // We only register event handlers after all plugins are
  18812. // registered, because other plugins might override some of our
  18813. // handlers.
  18814. _converse.on('contactRequest', _converse.handleContactRequestNotification);
  18815. _converse.on('contactStatusChanged', _converse.handleChatStateNotification);
  18816. _converse.on('message', _converse.handleMessageNotification);
  18817. _converse.on('feedback', _converse.handleFeedback);
  18818. _converse.on('connected', _converse.requestPermission);
  18819. });
  18820. }
  18821. });
  18822. });
  18823. //# sourceMappingURL=converse-notification.js.map;
  18824. define('tpl!chatbox_minimize', ['lodash'], function(_) {return function(obj) {
  18825. obj || (obj = {});
  18826. var __t, __p = '', __e = _.escape;
  18827. with (obj) {
  18828. __p += '<a class="chatbox-btn toggle-chatbox-button icon-minus" title="' +
  18829. __e(info_minimize) +
  18830. '"></a>\n';
  18831. }
  18832. return __p
  18833. };});
  18834. define('tpl!toggle_chats', ['lodash'], function(_) {return function(obj) {
  18835. obj || (obj = {});
  18836. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  18837. function print() { __p += __j.call(arguments, '') }
  18838. with (obj) {
  18839. __p +=
  18840. __e(Minimized) +
  18841. ' <span id="minimized-count">(' +
  18842. __e(num_minimized) +
  18843. ')</span>\n<span class="unread-message-count\n ';
  18844. if (!num_unread) { ;
  18845. __p += ' unread-message-count-hidden ';
  18846. } ;
  18847. __p += '\n href="#">' +
  18848. __e(num_unread) +
  18849. '</span>\n';
  18850. }
  18851. return __p
  18852. };});
  18853. define('tpl!trimmed_chat', ['lodash'], function(_) {return function(obj) {
  18854. obj || (obj = {});
  18855. var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
  18856. function print() { __p += __j.call(arguments, '') }
  18857. with (obj) {
  18858. __p += '<a class="chatbox-btn close-chatbox-button icon-close"></a>\n<a class="chat-head-message-count\n ';
  18859. if (!num_unread) { ;
  18860. __p += ' chat-head-message-count-hidden ';
  18861. } ;
  18862. __p += '"\n href="#">' +
  18863. __e(num_unread) +
  18864. '</a>\n<a href="#" class="restore-chat" title="' +
  18865. __e(tooltip) +
  18866. '">\n ' +
  18867. __e( title ) +
  18868. '\n</a>\n';
  18869. }
  18870. return __p
  18871. };});
  18872. define('tpl!chats_panel', ['lodash'], function(_) {return function(obj) {
  18873. obj || (obj = {});
  18874. var __t, __p = '';
  18875. with (obj) {
  18876. __p += '<a id="toggle-minimized-chats" href="#"></a>\n<div class="flyout minimized-chats-flyout"></div>\n';
  18877. }
  18878. return __p
  18879. };});
  18880. // Converse.js (A browser based XMPP chat client)
  18881. // http://conversejs.org
  18882. //
  18883. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  18884. // Licensed under the Mozilla Public License (MPLv2)
  18885. //
  18886. /*global define, window */
  18887. (function (root, factory) {
  18888. define('converse-minimize',["jquery.noconflict", "converse-core", "tpl!chatbox_minimize", "tpl!toggle_chats", "tpl!trimmed_chat", "tpl!chats_panel", "converse-controlbox", "converse-chatview", "converse-muc"], factory);
  18889. })(undefined, function ($, converse, tpl_chatbox_minimize, tpl_toggle_chats, tpl_trimmed_chat, tpl_chats_panel) {
  18890. "use strict";
  18891. var _converse$env = converse.env,
  18892. _ = _converse$env._,
  18893. utils = _converse$env.utils,
  18894. Backbone = _converse$env.Backbone,
  18895. b64_sha1 = _converse$env.b64_sha1,
  18896. moment = _converse$env.moment;
  18897. converse.plugins.add('converse-minimize', {
  18898. overrides: {
  18899. // Overrides mentioned here will be picked up by converse.js's
  18900. // plugin architecture they will replace existing methods on the
  18901. // relevant objects or classes.
  18902. //
  18903. // New functions which don't exist yet can also be added.
  18904. initChatBoxes: function initChatBoxes() {
  18905. var _converse = this.__super__._converse;
  18906. var result = this.__super__.initChatBoxes.apply(this, arguments);
  18907. _converse.minimized_chats = new _converse.MinimizedChats({
  18908. model: _converse.chatboxes
  18909. });
  18910. return result;
  18911. },
  18912. registerGlobalEventHandlers: function registerGlobalEventHandlers() {
  18913. var _converse = this.__super__._converse;
  18914. $(window).on("resize", _.debounce(function (ev) {
  18915. if (_converse.connection.connected) {
  18916. _converse.chatboxviews.trimChats();
  18917. }
  18918. }, 200));
  18919. return this.__super__.registerGlobalEventHandlers.apply(this, arguments);
  18920. },
  18921. ChatBox: {
  18922. initialize: function initialize() {
  18923. this.__super__.initialize.apply(this, arguments);
  18924. if (this.get('id') === 'controlbox') {
  18925. return;
  18926. }
  18927. this.save({
  18928. 'minimized': this.get('minimized') || false,
  18929. 'time_minimized': this.get('time_minimized') || moment()
  18930. });
  18931. },
  18932. maximize: function maximize() {
  18933. utils.safeSave(this, {
  18934. 'minimized': false,
  18935. 'time_opened': moment().valueOf()
  18936. });
  18937. },
  18938. minimize: function minimize() {
  18939. utils.safeSave(this, {
  18940. 'minimized': true,
  18941. 'time_minimized': moment().format()
  18942. });
  18943. }
  18944. },
  18945. ChatBoxView: {
  18946. events: {
  18947. 'click .toggle-chatbox-button': 'minimize'
  18948. },
  18949. initialize: function initialize() {
  18950. this.model.on('change:minimized', this.onMinimizedChanged, this);
  18951. return this.__super__.initialize.apply(this, arguments);
  18952. },
  18953. _show: function _show() {
  18954. var _converse = this.__super__._converse;
  18955. if (!this.model.get('minimized')) {
  18956. this.__super__._show.apply(this, arguments);
  18957. _converse.chatboxviews.trimChats(this);
  18958. } else {
  18959. this.minimize();
  18960. }
  18961. },
  18962. isNewMessageHidden: function isNewMessageHidden() {
  18963. return this.model.get('minimized') || this.__super__.isNewMessageHidden.apply(this, arguments);
  18964. },
  18965. shouldShowOnTextMessage: function shouldShowOnTextMessage() {
  18966. return !this.model.get('minimized') && this.__super__.shouldShowOnTextMessage.apply(this, arguments);
  18967. },
  18968. setChatBoxHeight: function setChatBoxHeight(height) {
  18969. if (!this.model.get('minimized')) {
  18970. return this.__super__.setChatBoxHeight.apply(this, arguments);
  18971. }
  18972. },
  18973. setChatBoxWidth: function setChatBoxWidth(width) {
  18974. if (!this.model.get('minimized')) {
  18975. return this.__super__.setChatBoxWidth.apply(this, arguments);
  18976. }
  18977. },
  18978. onMinimizedChanged: function onMinimizedChanged(item) {
  18979. if (item.get('minimized')) {
  18980. this.minimize();
  18981. } else {
  18982. this.maximize();
  18983. }
  18984. },
  18985. maximize: function maximize() {
  18986. // Restores a minimized chat box
  18987. var _converse = this.__super__._converse;
  18988. this.$el.insertAfter(_converse.chatboxviews.get("controlbox").$el);
  18989. if (!this.model.isScrolledUp()) {
  18990. this.model.clearUnreadMsgCounter();
  18991. }
  18992. this.show();
  18993. _converse.emit('chatBoxMaximized', this);
  18994. return this;
  18995. },
  18996. minimize: function minimize(ev) {
  18997. var _converse = this.__super__._converse;
  18998. if (ev && ev.preventDefault) {
  18999. ev.preventDefault();
  19000. }
  19001. // save the scroll position to restore it on maximize
  19002. if (this.model.collection && this.model.collection.browserStorage) {
  19003. this.model.save({ 'scroll': this.$content.scrollTop() });
  19004. } else {
  19005. this.model.set({ 'scroll': this.$content.scrollTop() });
  19006. }
  19007. this.setChatState(_converse.INACTIVE).model.minimize();
  19008. this.hide();
  19009. _converse.emit('chatBoxMinimized', this);
  19010. }
  19011. },
  19012. ChatRoomView: {
  19013. events: {
  19014. 'click .toggle-chatbox-button': 'minimize'
  19015. },
  19016. initialize: function initialize() {
  19017. this.model.on('change:minimized', function (item) {
  19018. if (item.get('minimized')) {
  19019. this.hide();
  19020. } else {
  19021. this.maximize();
  19022. }
  19023. }, this);
  19024. var result = this.__super__.initialize.apply(this, arguments);
  19025. if (this.model.get('minimized')) {
  19026. this.hide();
  19027. }
  19028. return result;
  19029. },
  19030. generateHeadingHTML: function generateHeadingHTML() {
  19031. var _converse = this.__super__._converse,
  19032. __ = _converse.__;
  19033. var html = this.__super__.generateHeadingHTML.apply(this, arguments);
  19034. var div = document.createElement('div');
  19035. div.innerHTML = html;
  19036. var el = tpl_chatbox_minimize({ info_minimize: __('Minimize this chat box') });
  19037. var button = div.querySelector('.close-chatbox-button');
  19038. button.insertAdjacentHTML('afterend', el);
  19039. return div.innerHTML;
  19040. }
  19041. },
  19042. ChatBoxes: {
  19043. chatBoxMayBeShown: function chatBoxMayBeShown(chatbox) {
  19044. return this.__super__.chatBoxMayBeShown.apply(this, arguments) && !chatbox.get('minimized');
  19045. }
  19046. },
  19047. ChatBoxViews: {
  19048. showChat: function showChat(attrs) {
  19049. /* Find the chat box and show it. If it doesn't exist, create it.
  19050. */
  19051. var chatbox = this.__super__.showChat.apply(this, arguments);
  19052. var maximize = _.isUndefined(attrs.maximize) ? true : attrs.maximize;
  19053. if (chatbox.get('minimized') && maximize) {
  19054. chatbox.maximize();
  19055. }
  19056. return chatbox;
  19057. },
  19058. getChatBoxWidth: function getChatBoxWidth(view) {
  19059. if (!view.model.get('minimized') && view.$el.is(':visible')) {
  19060. return view.$el.outerWidth(true);
  19061. }
  19062. return 0;
  19063. },
  19064. getShownChats: function getShownChats() {
  19065. return this.filter(function (view) {
  19066. return (
  19067. // The controlbox can take a while to close,
  19068. // so we need to check its state. That's why we checked
  19069. // the 'closed' state.
  19070. !view.model.get('minimized') && !view.model.get('closed') && view.$el.is(':visible')
  19071. );
  19072. });
  19073. },
  19074. trimChats: function trimChats(newchat) {
  19075. var _this = this;
  19076. /* This method is called when a newly created chat box will
  19077. * be shown.
  19078. *
  19079. * It checks whether there is enough space on the page to show
  19080. * another chat box. Otherwise it minimizes the oldest chat box
  19081. * to create space.
  19082. */
  19083. var _converse = this.__super__._converse;
  19084. var shown_chats = this.getShownChats();
  19085. if (_converse.no_trimming || shown_chats.length <= 1) {
  19086. return;
  19087. }
  19088. if (this.getChatBoxWidth(shown_chats[0]) === $('body').outerWidth(true)) {
  19089. // If the chats shown are the same width as the body,
  19090. // then we're in responsive mode and the chats are
  19091. // fullscreen. In this case we don't trim.
  19092. return;
  19093. }
  19094. var $minimized = _converse.minimized_chats.$el,
  19095. minimized_width = _.includes(this.model.pluck('minimized'), true) ? $minimized.outerWidth(true) : 0,
  19096. new_id = newchat ? newchat.model.get('id') : null;
  19097. var boxes_width = _.reduce(this.xget(new_id), function (memo, view) {
  19098. return memo + _this.getChatBoxWidth(view);
  19099. }, newchat ? newchat.$el.outerWidth(true) : 0);
  19100. if (minimized_width + boxes_width > $('body').outerWidth(true)) {
  19101. var oldest_chat = this.getOldestMaximizedChat([new_id]);
  19102. if (oldest_chat) {
  19103. // We hide the chat immediately, because waiting
  19104. // for the event to fire (and letting the
  19105. // ChatBoxView hide it then) causes race
  19106. // conditions.
  19107. var view = this.get(oldest_chat.get('id'));
  19108. if (view) {
  19109. view.hide();
  19110. }
  19111. oldest_chat.minimize();
  19112. }
  19113. }
  19114. },
  19115. getOldestMaximizedChat: function getOldestMaximizedChat(exclude_ids) {
  19116. // Get oldest view (if its id is not excluded)
  19117. exclude_ids.push('controlbox');
  19118. var i = 0;
  19119. var model = this.model.sort().at(i);
  19120. while (_.includes(exclude_ids, model.get('id')) || model.get('minimized') === true) {
  19121. i++;
  19122. model = this.model.at(i);
  19123. if (!model) {
  19124. return null;
  19125. }
  19126. }
  19127. return model;
  19128. }
  19129. }
  19130. },
  19131. initialize: function initialize() {
  19132. /* The initialize function gets called as soon as the plugin is
  19133. * loaded by Converse.js's plugin machinery.
  19134. */
  19135. var _converse = this._converse,
  19136. __ = _converse.__;
  19137. // Add new HTML templates.
  19138. _converse.templates.chatbox_minimize = tpl_chatbox_minimize;
  19139. _converse.templates.toggle_chats = tpl_toggle_chats;
  19140. _converse.templates.trimmed_chat = tpl_trimmed_chat;
  19141. _converse.templates.chats_panel = tpl_chats_panel;
  19142. _converse.api.settings.update({
  19143. no_trimming: false // Set to true for phantomjs tests (where browser apparently has no width)
  19144. });
  19145. _converse.MinimizedChatBoxView = Backbone.View.extend({
  19146. tagName: 'div',
  19147. className: 'chat-head',
  19148. events: {
  19149. 'click .close-chatbox-button': 'close',
  19150. 'click .restore-chat': 'restore'
  19151. },
  19152. initialize: function initialize() {
  19153. this.model.on('change:num_unread', this.render, this);
  19154. },
  19155. render: function render() {
  19156. var data = _.extend(this.model.toJSON(), { 'tooltip': __('Click to restore this chat') });
  19157. if (this.model.get('type') === 'chatroom') {
  19158. data.title = this.model.get('name');
  19159. this.$el.addClass('chat-head-chatroom');
  19160. } else {
  19161. data.title = this.model.get('fullname');
  19162. this.$el.addClass('chat-head-chatbox');
  19163. }
  19164. return this.$el.html(tpl_trimmed_chat(data));
  19165. },
  19166. close: function close(ev) {
  19167. if (ev && ev.preventDefault) {
  19168. ev.preventDefault();
  19169. }
  19170. this.remove();
  19171. var view = _converse.chatboxviews.get(this.model.get('id'));
  19172. if (view) {
  19173. // This will call model.destroy(), removing it from the
  19174. // collection and will also emit 'chatBoxClosed'
  19175. view.close();
  19176. } else {
  19177. this.model.destroy();
  19178. _converse.emit('chatBoxClosed', this);
  19179. }
  19180. return this;
  19181. },
  19182. restore: _.debounce(function (ev) {
  19183. if (ev && ev.preventDefault) {
  19184. ev.preventDefault();
  19185. }
  19186. this.model.off('change:num_unread', null, this);
  19187. this.remove();
  19188. this.model.maximize();
  19189. }, 200, { 'leading': true })
  19190. });
  19191. _converse.MinimizedChats = Backbone.Overview.extend({
  19192. tagName: 'div',
  19193. id: "minimized-chats",
  19194. className: 'hidden',
  19195. events: {
  19196. "click #toggle-minimized-chats": "toggle"
  19197. },
  19198. initialize: function initialize() {
  19199. this.render();
  19200. this.initToggle();
  19201. this.model.on("add", this.onChanged, this);
  19202. this.model.on("destroy", this.removeChat, this);
  19203. this.model.on("change:minimized", this.onChanged, this);
  19204. this.model.on('change:num_unread', this.updateUnreadMessagesCounter, this);
  19205. },
  19206. tearDown: function tearDown() {
  19207. this.model.off("add", this.onChanged);
  19208. this.model.off("destroy", this.removeChat);
  19209. this.model.off("change:minimized", this.onChanged);
  19210. this.model.off('change:num_unread', this.updateUnreadMessagesCounter);
  19211. return this;
  19212. },
  19213. initToggle: function initToggle() {
  19214. this.toggleview = new _converse.MinimizedChatsToggleView({
  19215. model: new _converse.MinimizedChatsToggle()
  19216. });
  19217. var id = b64_sha1("converse.minchatstoggle" + _converse.bare_jid);
  19218. this.toggleview.model.id = id; // Appears to be necessary for backbone.browserStorage
  19219. this.toggleview.model.browserStorage = new Backbone.BrowserStorage[_converse.storage](id);
  19220. this.toggleview.model.fetch();
  19221. },
  19222. render: function render() {
  19223. if (!this.el.parentElement) {
  19224. this.el.innerHTML = tpl_chats_panel();
  19225. _converse.chatboxviews.el.appendChild(this.el);
  19226. }
  19227. if (this.keys().length === 0) {
  19228. this.el.classList.add('hidden');
  19229. _converse.chatboxviews.trimChats.bind(_converse.chatboxviews);
  19230. } else if (this.keys().length > 0 && !this.$el.is(':visible')) {
  19231. this.el.classList.remove('hidden');
  19232. _converse.chatboxviews.trimChats();
  19233. }
  19234. return this.$el;
  19235. },
  19236. toggle: function toggle(ev) {
  19237. if (ev && ev.preventDefault) {
  19238. ev.preventDefault();
  19239. }
  19240. this.toggleview.model.save({ 'collapsed': !this.toggleview.model.get('collapsed') });
  19241. this.$('.minimized-chats-flyout').toggle();
  19242. },
  19243. onChanged: function onChanged(item) {
  19244. if (item.get('id') === 'controlbox') {
  19245. // The ControlBox has it's own minimize toggle
  19246. return;
  19247. }
  19248. if (item.get('minimized')) {
  19249. this.addChat(item);
  19250. } else if (this.get(item.get('id'))) {
  19251. this.removeChat(item);
  19252. }
  19253. },
  19254. addChat: function addChat(item) {
  19255. var existing = this.get(item.get('id'));
  19256. if (existing && existing.$el.parent().length !== 0) {
  19257. return;
  19258. }
  19259. var view = new _converse.MinimizedChatBoxView({ model: item });
  19260. this.$('.minimized-chats-flyout').append(view.render());
  19261. this.add(item.get('id'), view);
  19262. this.toggleview.model.set({ 'num_minimized': this.keys().length });
  19263. this.render();
  19264. },
  19265. removeChat: function removeChat(item) {
  19266. this.remove(item.get('id'));
  19267. this.toggleview.model.set({ 'num_minimized': this.keys().length });
  19268. this.render();
  19269. },
  19270. updateUnreadMessagesCounter: function updateUnreadMessagesCounter() {
  19271. var ls = this.model.pluck('num_unread');
  19272. var count = 0,
  19273. i = void 0;
  19274. for (i = 0; i < ls.length; i++) {
  19275. count += ls[i];
  19276. }
  19277. this.toggleview.model.save({ 'num_unread': count });
  19278. this.render();
  19279. }
  19280. });
  19281. _converse.MinimizedChatsToggle = Backbone.Model.extend({
  19282. defaults: {
  19283. 'collapsed': false,
  19284. 'num_minimized': 0,
  19285. 'num_unread': 0
  19286. }
  19287. });
  19288. _converse.MinimizedChatsToggleView = Backbone.View.extend({
  19289. el: '#toggle-minimized-chats',
  19290. initialize: function initialize() {
  19291. this.model.on('change:num_minimized', this.render, this);
  19292. this.model.on('change:num_unread', this.render, this);
  19293. this.$flyout = this.$el.siblings('.minimized-chats-flyout');
  19294. },
  19295. render: function render() {
  19296. this.$el.html(tpl_toggle_chats(_.extend(this.model.toJSON(), {
  19297. 'Minimized': __('Minimized')
  19298. })));
  19299. if (this.model.get('collapsed')) {
  19300. this.$flyout.hide();
  19301. } else {
  19302. this.$flyout.show();
  19303. }
  19304. return this.$el;
  19305. }
  19306. });
  19307. var renderMinimizeButton = function renderMinimizeButton(view) {
  19308. // Inserts a "minimize" button in the chatview's header
  19309. var $el = view.$el.find('.toggle-chatbox-button');
  19310. var $new_el = tpl_chatbox_minimize({ info_minimize: __('Minimize this chat box') });
  19311. if ($el.length) {
  19312. $el.replaceWith($new_el);
  19313. } else {
  19314. view.$el.find('.close-chatbox-button').after($new_el);
  19315. }
  19316. };
  19317. _converse.on('chatBoxOpened', renderMinimizeButton);
  19318. _converse.on('controlBoxOpened', function (chatbox) {
  19319. // Wrapped in anon method because at scan time, chatboxviews
  19320. // attr not set yet.
  19321. if (_converse.connection.connected) {
  19322. _converse.chatboxviews.trimChats(chatbox);
  19323. }
  19324. });
  19325. var logOut = function logOut() {
  19326. _converse.minimized_chats.remove();
  19327. };
  19328. _converse.on('logout', logOut);
  19329. }
  19330. });
  19331. });
  19332. //# sourceMappingURL=converse-minimize.js.map;
  19333. define('tpl!dragresize', ['lodash'], function(_) {return function(obj) {
  19334. obj || (obj = {});
  19335. var __t, __p = '';
  19336. with (obj) {
  19337. __p += '<div class="dragresize dragresize-top"></div>\n<div class="dragresize dragresize-topleft"></div>\n<div class="dragresize dragresize-left"></div>\n';
  19338. }
  19339. return __p
  19340. };});
  19341. // Converse.js (A browser based XMPP chat client)
  19342. // http://conversejs.org
  19343. //
  19344. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  19345. // Licensed under the Mozilla Public License (MPLv2)
  19346. //
  19347. /*global define, window */
  19348. (function (root, factory) {
  19349. define('converse-dragresize',["jquery.noconflict", "converse-core", "tpl!dragresize", "converse-chatview", "converse-muc", // XXX: would like to remove this
  19350. "converse-controlbox"], factory);
  19351. })(undefined, function ($, converse, tpl_dragresize) {
  19352. "use strict";
  19353. var _ = converse.env._;
  19354. function renderDragResizeHandles(_converse, view) {
  19355. var flyout = view.el.querySelector('.box-flyout');
  19356. var div = document.createElement('div');
  19357. div.innerHTML = tpl_dragresize();
  19358. flyout.insertBefore(div, flyout.firstChild);
  19359. }
  19360. converse.plugins.add('converse-dragresize', {
  19361. /* Optional dependencies are other plugins which might be
  19362. * overridden or relied upon, and therefore need to be loaded before
  19363. * this plugin. They are called "optional" because they might not be
  19364. * available, in which case any overrides applicable to them will be
  19365. * ignored.
  19366. *
  19367. * It's possible however to make optional dependencies non-optional.
  19368. * If the setting "strict_plugin_dependencies" is set to true,
  19369. * an error will be raised if the plugin is not found.
  19370. *
  19371. * NB: These plugins need to have already been loaded via require.js.
  19372. */
  19373. optional_dependencies: ["converse-headline"],
  19374. overrides: {
  19375. // Overrides mentioned here will be picked up by converse.js's
  19376. // plugin architecture they will replace existing methods on the
  19377. // relevant objects or classes.
  19378. //
  19379. // New functions which don't exist yet can also be added.
  19380. registerGlobalEventHandlers: function registerGlobalEventHandlers() {
  19381. var that = this;
  19382. $(document).on('mousemove', function (ev) {
  19383. if (!that.resizing || !that.allow_dragresize) {
  19384. return true;
  19385. }
  19386. ev.preventDefault();
  19387. that.resizing.chatbox.resizeChatBox(ev);
  19388. });
  19389. $(document).on('mouseup', function (ev) {
  19390. if (!that.resizing || !that.allow_dragresize) {
  19391. return true;
  19392. }
  19393. ev.preventDefault();
  19394. var height = that.applyDragResistance(that.resizing.chatbox.height, that.resizing.chatbox.model.get('default_height'));
  19395. var width = that.applyDragResistance(that.resizing.chatbox.width, that.resizing.chatbox.model.get('default_width'));
  19396. if (that.connection.connected) {
  19397. that.resizing.chatbox.model.save({ 'height': height });
  19398. that.resizing.chatbox.model.save({ 'width': width });
  19399. } else {
  19400. that.resizing.chatbox.model.set({ 'height': height });
  19401. that.resizing.chatbox.model.set({ 'width': width });
  19402. }
  19403. that.resizing = null;
  19404. });
  19405. return this.__super__.registerGlobalEventHandlers.apply(this, arguments);
  19406. },
  19407. ChatBox: {
  19408. initialize: function initialize() {
  19409. var _converse = this.__super__._converse;
  19410. var result = this.__super__.initialize.apply(this, arguments),
  19411. height = this.get('height'),
  19412. width = this.get('width'),
  19413. save = this.get('id') === 'controlbox' ? this.set.bind(this) : this.save.bind(this);
  19414. save({
  19415. 'height': _converse.applyDragResistance(height, this.get('default_height')),
  19416. 'width': _converse.applyDragResistance(width, this.get('default_width'))
  19417. });
  19418. return result;
  19419. }
  19420. },
  19421. ChatBoxView: {
  19422. events: {
  19423. 'mousedown .dragresize-top': 'onStartVerticalResize',
  19424. 'mousedown .dragresize-left': 'onStartHorizontalResize',
  19425. 'mousedown .dragresize-topleft': 'onStartDiagonalResize'
  19426. },
  19427. initialize: function initialize() {
  19428. $(window).on('resize', _.debounce(this.setDimensions.bind(this), 100));
  19429. this.__super__.initialize.apply(this, arguments);
  19430. },
  19431. render: function render() {
  19432. var result = this.__super__.render.apply(this, arguments);
  19433. renderDragResizeHandles(this.__super__._converse, this);
  19434. this.setWidth();
  19435. return result;
  19436. },
  19437. setWidth: function setWidth() {
  19438. // If a custom width is applied (due to drag-resizing),
  19439. // then we need to set the width of the .chatbox element as well.
  19440. if (this.model.get('width')) {
  19441. this.$el.css('width', this.model.get('width'));
  19442. }
  19443. },
  19444. _show: function _show() {
  19445. this.initDragResize().setDimensions();
  19446. this.__super__._show.apply(this, arguments);
  19447. },
  19448. initDragResize: function initDragResize() {
  19449. /* Determine and store the default box size.
  19450. * We need this information for the drag-resizing feature.
  19451. */
  19452. var _converse = this.__super__._converse;
  19453. var $flyout = this.$el.find('.box-flyout');
  19454. if (_.isUndefined(this.model.get('height'))) {
  19455. var height = $flyout.height();
  19456. var width = $flyout.width();
  19457. this.model.set('height', height);
  19458. this.model.set('default_height', height);
  19459. this.model.set('width', width);
  19460. this.model.set('default_width', width);
  19461. }
  19462. var min_width = $flyout.css('min-width');
  19463. var min_height = $flyout.css('min-height');
  19464. this.model.set('min_width', min_width.endsWith('px') ? Number(min_width.replace(/px$/, '')) : 0);
  19465. this.model.set('min_height', min_height.endsWith('px') ? Number(min_height.replace(/px$/, '')) : 0);
  19466. // Initialize last known mouse position
  19467. this.prev_pageY = 0;
  19468. this.prev_pageX = 0;
  19469. if (_converse.connection.connected) {
  19470. this.height = this.model.get('height');
  19471. this.width = this.model.get('width');
  19472. }
  19473. return this;
  19474. },
  19475. setDimensions: function setDimensions() {
  19476. // Make sure the chat box has the right height and width.
  19477. this.adjustToViewport();
  19478. this.setChatBoxHeight(this.model.get('height'));
  19479. this.setChatBoxWidth(this.model.get('width'));
  19480. },
  19481. setChatBoxHeight: function setChatBoxHeight(height) {
  19482. var _converse = this.__super__._converse;
  19483. if (height) {
  19484. height = _converse.applyDragResistance(height, this.model.get('default_height')) + 'px';
  19485. } else {
  19486. height = "";
  19487. }
  19488. this.$el.children('.box-flyout')[0].style.height = height;
  19489. },
  19490. setChatBoxWidth: function setChatBoxWidth(width) {
  19491. var _converse = this.__super__._converse;
  19492. if (width) {
  19493. width = _converse.applyDragResistance(width, this.model.get('default_width')) + 'px';
  19494. } else {
  19495. width = "";
  19496. }
  19497. this.$el[0].style.width = width;
  19498. this.$el.children('.box-flyout')[0].style.width = width;
  19499. },
  19500. adjustToViewport: function adjustToViewport() {
  19501. /* Event handler called when viewport gets resized. We remove
  19502. * custom width/height from chat boxes.
  19503. */
  19504. var viewport_width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
  19505. var viewport_height = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
  19506. if (viewport_width <= 480) {
  19507. this.model.set('height', undefined);
  19508. this.model.set('width', undefined);
  19509. } else if (viewport_width <= this.model.get('width')) {
  19510. this.model.set('width', undefined);
  19511. } else if (viewport_height <= this.model.get('height')) {
  19512. this.model.set('height', undefined);
  19513. }
  19514. },
  19515. onStartVerticalResize: function onStartVerticalResize(ev) {
  19516. var _converse = this.__super__._converse;
  19517. if (!_converse.allow_dragresize) {
  19518. return true;
  19519. }
  19520. // Record element attributes for mouseMove().
  19521. this.height = this.$el.children('.box-flyout').height();
  19522. _converse.resizing = {
  19523. 'chatbox': this,
  19524. 'direction': 'top'
  19525. };
  19526. this.prev_pageY = ev.pageY;
  19527. },
  19528. onStartHorizontalResize: function onStartHorizontalResize(ev) {
  19529. var _converse = this.__super__._converse;
  19530. if (!_converse.allow_dragresize) {
  19531. return true;
  19532. }
  19533. this.width = this.$el.children('.box-flyout').width();
  19534. _converse.resizing = {
  19535. 'chatbox': this,
  19536. 'direction': 'left'
  19537. };
  19538. this.prev_pageX = ev.pageX;
  19539. },
  19540. onStartDiagonalResize: function onStartDiagonalResize(ev) {
  19541. var _converse = this.__super__._converse;
  19542. this.onStartHorizontalResize(ev);
  19543. this.onStartVerticalResize(ev);
  19544. _converse.resizing.direction = 'topleft';
  19545. },
  19546. resizeChatBox: function resizeChatBox(ev) {
  19547. var diff = void 0;
  19548. var _converse = this.__super__._converse;
  19549. if (_converse.resizing.direction.indexOf('top') === 0) {
  19550. diff = ev.pageY - this.prev_pageY;
  19551. if (diff) {
  19552. this.height = this.height - diff > (this.model.get('min_height') || 0) ? this.height - diff : this.model.get('min_height');
  19553. this.prev_pageY = ev.pageY;
  19554. this.setChatBoxHeight(this.height);
  19555. }
  19556. }
  19557. if (_.includes(_converse.resizing.direction, 'left')) {
  19558. diff = this.prev_pageX - ev.pageX;
  19559. if (diff) {
  19560. this.width = this.width + diff > (this.model.get('min_width') || 0) ? this.width + diff : this.model.get('min_width');
  19561. this.prev_pageX = ev.pageX;
  19562. this.setChatBoxWidth(this.width);
  19563. }
  19564. }
  19565. }
  19566. },
  19567. HeadlinesBoxView: {
  19568. events: {
  19569. 'mousedown .dragresize-top': 'onStartVerticalResize',
  19570. 'mousedown .dragresize-left': 'onStartHorizontalResize',
  19571. 'mousedown .dragresize-topleft': 'onStartDiagonalResize'
  19572. },
  19573. initialize: function initialize() {
  19574. $(window).on('resize', _.debounce(this.setDimensions.bind(this), 100));
  19575. return this.__super__.initialize.apply(this, arguments);
  19576. },
  19577. render: function render() {
  19578. var result = this.__super__.render.apply(this, arguments);
  19579. renderDragResizeHandles(this.__super__._converse, this);
  19580. this.setWidth();
  19581. return result;
  19582. }
  19583. },
  19584. ControlBoxView: {
  19585. events: {
  19586. 'mousedown .dragresize-top': 'onStartVerticalResize',
  19587. 'mousedown .dragresize-left': 'onStartHorizontalResize',
  19588. 'mousedown .dragresize-topleft': 'onStartDiagonalResize'
  19589. },
  19590. initialize: function initialize() {
  19591. $(window).on('resize', _.debounce(this.setDimensions.bind(this), 100));
  19592. this.__super__.initialize.apply(this, arguments);
  19593. },
  19594. render: function render() {
  19595. var result = this.__super__.render.apply(this, arguments);
  19596. renderDragResizeHandles(this.__super__._converse, this);
  19597. this.setWidth();
  19598. return result;
  19599. },
  19600. renderLoginPanel: function renderLoginPanel() {
  19601. var result = this.__super__.renderLoginPanel.apply(this, arguments);
  19602. this.initDragResize().setDimensions();
  19603. return result;
  19604. },
  19605. renderContactsPanel: function renderContactsPanel() {
  19606. var result = this.__super__.renderContactsPanel.apply(this, arguments);
  19607. this.initDragResize().setDimensions();
  19608. return result;
  19609. }
  19610. },
  19611. ChatRoomView: {
  19612. events: {
  19613. 'mousedown .dragresize-top': 'onStartVerticalResize',
  19614. 'mousedown .dragresize-left': 'onStartHorizontalResize',
  19615. 'mousedown .dragresize-topleft': 'onStartDiagonalResize'
  19616. },
  19617. initialize: function initialize() {
  19618. $(window).on('resize', _.debounce(this.setDimensions.bind(this), 100));
  19619. this.__super__.initialize.apply(this, arguments);
  19620. },
  19621. render: function render() {
  19622. var result = this.__super__.render.apply(this, arguments);
  19623. renderDragResizeHandles(this.__super__._converse, this);
  19624. this.setWidth();
  19625. return result;
  19626. }
  19627. }
  19628. },
  19629. initialize: function initialize() {
  19630. /* The initialize function gets called as soon as the plugin is
  19631. * loaded by converse.js's plugin machinery.
  19632. */
  19633. var _converse = this._converse;
  19634. _converse.api.settings.update({
  19635. allow_dragresize: true
  19636. });
  19637. _converse.applyDragResistance = function (value, default_value) {
  19638. /* This method applies some resistance around the
  19639. * default_value. If value is close enough to
  19640. * default_value, then default_value is returned instead.
  19641. */
  19642. if (_.isUndefined(value)) {
  19643. return undefined;
  19644. } else if (_.isUndefined(default_value)) {
  19645. return value;
  19646. }
  19647. var resistance = 10;
  19648. if (value !== default_value && Math.abs(value - default_value) < resistance) {
  19649. return default_value;
  19650. }
  19651. return value;
  19652. };
  19653. }
  19654. });
  19655. });
  19656. //# sourceMappingURL=converse-dragresize.js.map;
  19657. // Converse.js (A browser based XMPP chat client)
  19658. // http://conversejs.org
  19659. //
  19660. // Copyright (c) 2012-2017, Jan-Carel Brand <jc@opkode.com>
  19661. // Licensed under the Mozilla Public License (MPLv2)
  19662. //
  19663. /*global define */
  19664. (function (root, factory) {
  19665. define('converse-headline',["converse-core", "tpl!chatbox", "converse-chatview"], factory);
  19666. })(undefined, function (converse, tpl_chatbox) {
  19667. "use strict";
  19668. var _converse$env = converse.env,
  19669. _ = _converse$env._,
  19670. utils = _converse$env.utils;
  19671. converse.plugins.add('converse-headline', {
  19672. overrides: {
  19673. // Overrides mentioned here will be picked up by converse.js's
  19674. // plugin architecture they will replace existing methods on the
  19675. // relevant objects or classes.
  19676. //
  19677. // New functions which don't exist yet can also be added.
  19678. ChatBoxViews: {
  19679. onChatBoxAdded: function onChatBoxAdded(item) {
  19680. var _converse = this.__super__._converse;
  19681. var view = this.get(item.get('id'));
  19682. if (!view && item.get('type') === 'headline') {
  19683. view = new _converse.HeadlinesBoxView({ model: item });
  19684. this.add(item.get('id'), view);
  19685. return view;
  19686. } else {
  19687. return this.__super__.onChatBoxAdded.apply(this, arguments);
  19688. }
  19689. }
  19690. }
  19691. },
  19692. initialize: function initialize() {
  19693. /* The initialize function gets called as soon as the plugin is
  19694. * loaded by converse.js's plugin machinery.
  19695. */
  19696. var _converse = this._converse,
  19697. __ = _converse.__;
  19698. _converse.HeadlinesBoxView = _converse.ChatBoxView.extend({
  19699. className: 'chatbox headlines',
  19700. events: {
  19701. 'click .close-chatbox-button': 'close',
  19702. 'click .toggle-chatbox-button': 'minimize',
  19703. 'keypress textarea.chat-textarea': 'keyPressed'
  19704. },
  19705. initialize: function initialize() {
  19706. this.disable_mam = true; // Don't do MAM queries for this box
  19707. this.model.messages.on('add', this.onMessageAdded, this);
  19708. this.model.on('show', this.show, this);
  19709. this.model.on('destroy', this.hide, this);
  19710. this.model.on('change:minimized', this.onMinimizedChanged, this);
  19711. this.render().fetchMessages().insertIntoDOM().hide();
  19712. _converse.emit('chatBoxInitialized', this);
  19713. },
  19714. render: function render() {
  19715. this.$el.attr('id', this.model.get('box_id')).html(tpl_chatbox(_.extend(this.model.toJSON(), {
  19716. show_toolbar: _converse.show_toolbar,
  19717. show_textarea: false,
  19718. show_send_button: _converse.show_send_button,
  19719. title: this.model.get('fullname'),
  19720. unread_msgs: __('You have unread messages'),
  19721. info_close: __('Close this box'),
  19722. label_personal_message: ''
  19723. })));
  19724. this.$content = this.$el.find('.chat-content');
  19725. _converse.emit('chatBoxOpened', this);
  19726. utils.refreshWebkit();
  19727. return this;
  19728. }
  19729. });
  19730. function onHeadlineMessage(message) {
  19731. /* Handler method for all incoming messages of type "headline". */
  19732. var from_jid = message.getAttribute('from');
  19733. if (utils.isHeadlineMessage(message)) {
  19734. if (_.includes(from_jid, '@') && !_converse.allow_non_roster_messaging) {
  19735. return;
  19736. }
  19737. var chatbox = _converse.chatboxes.create({
  19738. 'id': from_jid,
  19739. 'jid': from_jid,
  19740. 'fullname': from_jid,
  19741. 'type': 'headline'
  19742. });
  19743. chatbox.createMessage(message, undefined, message);
  19744. _converse.emit('message', { 'chatbox': chatbox, 'stanza': message });
  19745. }
  19746. return true;
  19747. }
  19748. function registerHeadlineHandler() {
  19749. _converse.connection.addHandler(onHeadlineMessage, null, 'message');
  19750. }
  19751. _converse.on('connected', registerHeadlineHandler);
  19752. _converse.on('reconnected', registerHeadlineHandler);
  19753. }
  19754. });
  19755. });
  19756. //# sourceMappingURL=converse-headline.js.map;
  19757. /*global define */
  19758. if (typeof define !== 'undefined') {
  19759. // The section below determines which plugins will be included in a build
  19760. define('converse',[
  19761. "converse-core",
  19762. // PLEASE NOTE: By default all translations are included.
  19763. // You can modify the file src/locales.js to include only those
  19764. // translations that you care about.
  19765. /* START: Removable components
  19766. * --------------------
  19767. * Any of the following components may be removed if they're not needed.
  19768. */
  19769. "converse-chatview", // Renders standalone chat boxes for single user chat
  19770. "converse-controlbox", // The control box
  19771. "converse-bookmarks", // XEP-0048 Bookmarks
  19772. "converse-roomslist", // Show currently open chat rooms
  19773. "converse-mam", // XEP-0313 Message Archive Management
  19774. "converse-muc", // XEP-0045 Multi-user chat
  19775. "converse-vcard", // XEP-0054 VCard-temp
  19776. "converse-otr", // Off-the-record encryption for one-on-one messages
  19777. "converse-register", // XEP-0077 In-band registration
  19778. "converse-ping", // XEP-0199 XMPP Ping
  19779. "converse-notification",// HTML5 Notifications
  19780. "converse-minimize", // Allows chat boxes to be minimized
  19781. "converse-dragresize", // Allows chat boxes to be resized by dragging them
  19782. "converse-headline", // Support for headline messages
  19783. /* END: Removable components */
  19784. ], function (converse) {
  19785. return converse;
  19786. });
  19787. }
  19788. ;
  19789. define('jquery', [], function () { return jQuery; });
  19790. define('jquery.noconflict', [], function () { return jQuery; });
  19791. define('jquery.browser', [], function () { return jQuery; });
  19792. define('awesomplete', [], function () { return jQuery; });
  19793. define('lodash', [], function () { return _; });
  19794. define('lodash.converter', [], function () { return fp; });
  19795. define('lodash.noconflict', [], function () { return _; });
  19796. define('moment_with_locales', [], function () { return moment; });
  19797. define('strophe', [], function () {
  19798. return {
  19799. 'Strophe': Strophe,
  19800. '$build': $build,
  19801. '$iq': $iq,
  19802. '$msg': $msg,
  19803. '$pres': $pres,
  19804. 'SHA1': SHA1,
  19805. 'MD5': MD5,
  19806. 'b64_hmac_sha1': SHA1.b64_hmac_sha1,
  19807. 'b64_sha1': SHA1.b64_sha1,
  19808. 'str_hmac_sha1': SHA1.str_hmac_sha1,
  19809. 'str_sha1': SHA1.str_sha1
  19810. };
  19811. });
  19812. var strophePlugin = function () { return Strophe; };
  19813. var emptyFunction = function () { };
  19814. define('strophe.disco', ['strophe'], strophePlugin);
  19815. define('strophe.ping', ['strophe'], strophePlugin);
  19816. define('strophe.rsm', ['strophe'], strophePlugin);
  19817. define('strophe.vcard', ['strophe'], strophePlugin);
  19818. define('backbone', [], function () { return Backbone; });
  19819. define('backbone.noconflict', [], function () { return Backbone; });
  19820. define('backbone.browserStorage', ['backbone'], emptyFunction);
  19821. define('backbone.overview', ['backbone'], emptyFunction);
  19822. define('otr', [], function () { return { 'DSA': DSA, 'OTR': OTR };});
  19823. define("locales", [], emptyFunction);
  19824. return require('converse');
  19825. }));