From 72d086520191e10563a1ff29b9eac0bec41d9d78 Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Tue, 25 May 2021 14:37:15 -0500 Subject: [PATCH] feat(content): new pet color achievements --- .../2021/20210525_pet_color_achievements.js | 82 ++++++++++++++++++ .../client/src/components/notifications.vue | 19 ++++ website/common/locales/en/achievements.json | 8 +- website/common/script/content/achievements.js | 10 +++ .../constants/animalColorAchievements.js | 7 ++ website/common/script/libs/achievements.js | 2 + .../achievement-violetsAreBlue2x.png | Bin 0 -> 16713 bytes .../achievement-wildBlueYonder2x.png | Bin 0 -> 9713 bytes website/server/models/user/schema.js | 2 + website/server/models/userNotification.js | 2 + 10 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 migrations/archive/2021/20210525_pet_color_achievements.js create mode 100644 website/raw_sprites/spritesmith/achievements/achievement-violetsAreBlue2x.png create mode 100644 website/raw_sprites/spritesmith/achievements/achievement-wildBlueYonder2x.png diff --git a/migrations/archive/2021/20210525_pet_color_achievements.js b/migrations/archive/2021/20210525_pet_color_achievements.js new file mode 100644 index 0000000000..66cea73444 --- /dev/null +++ b/migrations/archive/2021/20210525_pet_color_achievements.js @@ -0,0 +1,82 @@ +/* eslint-disable no-console */ +const MIGRATION_NAME = '20210525_pet_color_achievements'; +import { model as User } from '../../../website/server/models/user'; + +const progressCount = 1000; +let count = 0; + +async function updateUser (user) { + count++; + + const set = { + migration: MIGRATION_NAME, + }; + + if (user && user.items && user.items.pets) { + const pets = user.items.pets; + if (pets['Wolf-CottonCandyBlue'] > 0 + && pets['TigerCub-CottonCandyBlue'] > 0 + && pets['PandaCub-CottonCandyBlue'] > 0 + && pets['LionCub-CottonCandyBlue'] > 0 + && pets['Fox-CottonCandyBlue'] > 0 + && pets['FlyingPig-CottonCandyBlue'] > 0 + && pets['Dragon-CottonCandyBlue'] > 0 + && pets['Cactus-CottonCandyBlue'] > 0 + && pets['BearCub-CottonCandyBlue'] > 0) { + set['achievements.violetsAreBlue'] = true; + } + } + + if (user && user.items && user.items.mounts) { + const mounts = user.items.mounts; + if (mounts['Wolf-CottonCandyBlue'] + && mounts['TigerCub-CottonCandyBlue'] + && mounts['PandaCub-CottonCandyBlue'] + && mounts['LionCub-CottonCandyBlue'] + && mounts['Fox-CottonCandyBlue'] + && mounts['FlyingPig-CottonCandyBlue'] + && mounts['Dragon-CottonCandyBlue'] + && mounts['Cactus-CottonCandyBlue'] + && mounts['BearCub-CottonCandyBlue'] ) { + set['achievements.wildBlueYonder'] = true; + } + } + + if (count % progressCount === 0) console.warn(`${count} ${user._id}`); + + return await User.update({ _id: user._id }, { $set: set }).exec(); +} + +module.exports = async function processUsers () { + let query = { + migration: { $ne: MIGRATION_NAME }, + 'auth.timestamps.loggedin': { $gt: new Date('2021-05-01') }, + }; + + const fields = { + _id: 1, + items: 1, + }; + + while (true) { // eslint-disable-line no-constant-condition + const users = await User // eslint-disable-line no-await-in-loop + .find(query) + .limit(250) + .sort({_id: 1}) + .select(fields) + .lean() + .exec(); + + if (users.length === 0) { + console.warn('All appropriate users found and modified.'); + console.warn(`\n${count} users processed\n`); + break; + } else { + query._id = { + $gt: users[users.length - 1]._id, + }; + } + + await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop + } +}; diff --git a/website/client/src/components/notifications.vue b/website/client/src/components/notifications.vue index d4ebf738d3..770b8bdeb4 100644 --- a/website/client/src/components/notifications.vue +++ b/website/client/src/components/notifications.vue @@ -403,6 +403,22 @@ const NOTIFICATIONS = { achievement: 'seasonalSpecialist', }, }, + ACHIEVEMENT_VIOLETS_ARE_BLUE: { + achievement: true, + label: $t => `${$t('achievement')}: ${$t('achievementVioletsAreBlue')}`, + modalId: 'generic-achievement', + data: { + achievement: 'violetsAreBlue', + }, + }, + ACHIEVEMENT_WILD_BLUE_YONDER: { + achievement: true, + label: $t => `${$t('achievement')}: ${$t('achievementWildBlueYonder')}`, + modalId: 'generic-achievement', + data: { + achievement: 'wildBlueYonder', + }, + }, }; export default { @@ -466,6 +482,7 @@ export default { 'ACHIEVEMENT_FRESHWATER_FRIENDS', 'ACHIEVEMENT_GOOD_AS_GOLD', 'ACHIEVEMENT_ALL_THAT_GLITTERS', 'ACHIEVEMENT_BONE_COLLECTOR', 'ACHIEVEMENT_SKELETON_CREW', 'ACHIEVEMENT_SEEING_RED', 'ACHIEVEMENT_RED_LETTER_DAY', 'ACHIEVEMENT_LEGENDARY_BESTIARY', 'ACHIEVEMENT_SEASONAL_SPECIALIST', + 'ACHIEVEMENT_VIOLETS_ARE_BLUE', 'ACHIEVEMENT_WILD_BLUE_YONDER', ].forEach(type => { handledNotifications[type] = true; }); @@ -890,6 +907,8 @@ export default { case 'ACHIEVEMENT_RED_LETTER_DAY': case 'ACHIEVEMENT_LEGENDARY_BESTIARY': case 'ACHIEVEMENT_SEASONAL_SPECIALIST': + case 'ACHIEVEMENT_VIOLETS_ARE_BLUE': + case 'ACHIEVEMENT_WILD_BLUE_YONDER': case 'GENERIC_ACHIEVEMENT': this.showNotificationWithModal(notification); break; diff --git a/website/common/locales/en/achievements.json b/website/common/locales/en/achievements.json index 85a64c9870..799274037b 100644 --- a/website/common/locales/en/achievements.json +++ b/website/common/locales/en/achievements.json @@ -108,5 +108,11 @@ "achievementLegendaryBestiaryModalText": "You collected all the mythical pets!", "achievementSeasonalSpecialist": "Seasonal Specialist", "achievementSeasonalSpecialistText": "Has completed all the Spring and Winter seasonal quests: Egg Hunt, Trapper Santa, and Find the Cub!", - "achievementSeasonalSpecialistModalText": "You completed all the seasonal quests!" + "achievementSeasonalSpecialistModalText": "You completed all the seasonal quests!", + "achievementVioletsAreBlue": "Violets are Blue", + "achievementVioletsAreBlueText": "Has collected all Cotton Candy Blue Pets.", + "achievementVioletsAreBlueModalText": "You collected all the Cotton Candy Blue Pets!", + "achievementWildBlueYonder": "Wild Blue Yonder", + "achievementWildBlueYonderText": "Has tamed all Cotton Candy Blue Mounts.", + "achievementWildBlueYonderModalText": "You tamed all the Cotton Candy Blue Mounts!" } diff --git a/website/common/script/content/achievements.js b/website/common/script/content/achievements.js index 68551150f3..e2dfdce6d6 100644 --- a/website/common/script/content/achievements.js +++ b/website/common/script/content/achievements.js @@ -242,6 +242,16 @@ const basicAchievs = { titleKey: 'achievementSeasonalSpecialist', textKey: 'achievementSeasonalSpecialistText', }, + violetsAreBlue: { + icon: 'achievement-violetsAreBlue', + titleKey: 'achievementVioletsAreBlue', + textKey: 'achievementVioletsAreBlueText', + }, + wildBlueYonder: { + icon: 'achievement-wildBlueYonder', + titleKey: 'achievementWildBlueYonder', + textKey: 'achievementWildBlueYonderText', + }, }; Object.assign(achievementsData, basicAchievs); diff --git a/website/common/script/content/constants/animalColorAchievements.js b/website/common/script/content/constants/animalColorAchievements.js index df2918faae..e507cb7355 100644 --- a/website/common/script/content/constants/animalColorAchievements.js +++ b/website/common/script/content/constants/animalColorAchievements.js @@ -55,6 +55,13 @@ const ANIMAL_COLOR_ACHIEVEMENTS = [ mountAchievement: 'redLetterDay', mountNotificationType: 'ACHIEVEMENT_RED_LETTER_DAY', }, + { + color: 'CottonCandyBlue', + petAchievement: 'violetsAreBlue', + petNotificationType: 'ACHIEVEMENT_VIOLETS_ARE_BLUE', + mountAchievement: 'wildBlueYonder', + mountNotificationType: 'ACHIEVEMENT_WILD_BLUE_YONDER', + }, ]; export default ANIMAL_COLOR_ACHIEVEMENTS; diff --git a/website/common/script/libs/achievements.js b/website/common/script/libs/achievements.js index 6fb63a7225..9f59d5b501 100644 --- a/website/common/script/libs/achievements.js +++ b/website/common/script/libs/achievements.js @@ -210,6 +210,8 @@ function _getBasicAchievements (user, language) { _addSimple(result, user, { path: 'redLetterDay', language }); _addSimple(result, user, { path: 'legendaryBestiary', language }); _addSimple(result, user, { path: 'seasonalSpecialist', language }); + _addSimple(result, user, { path: 'violetsAreBlue', language }); + _addSimple(result, user, { path: 'wildBlueYonder', language }); _addSimpleWithMasterCount(result, user, { path: 'beastMaster', language }); _addSimpleWithMasterCount(result, user, { path: 'mountMaster', language }); diff --git a/website/raw_sprites/spritesmith/achievements/achievement-violetsAreBlue2x.png b/website/raw_sprites/spritesmith/achievements/achievement-violetsAreBlue2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d360f2d47d43be6bd16a8efd031e82a3ab974670 GIT binary patch literal 16713 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 O2^N&$guJ(jF=yB5quwY^+&Ck<;DUoz z7(P$GFtO#8t@bH-<0Cfo<&Rp-+R2-R%{`)<--}*IJeydM^tCrhyd)}IMU%fuj1=ZN zI?m4HUYngOy``8MW`D4L7#nwQG|^6R^yv@REUM8J?d3;^gW@Z5<=*3MBs+oiua9nF zh;oy+Nd*S6V(Z!yZ{xK9j^oy$xT-4qfWX;h*U5-eWF$pqa+SAFsba_#RkRyzO53i) zl*RqEPgxNPqy$;@Y6$sHCwt~(^$j^R6YdS*p@!b^PQ6<#!#sgOy=~72JrY<;u6**J z*sr=IK&CKSqxJIQgeaN6un*Ja0EfwX!_vRKj>lJ>cVE}y@BO=eTL zw7;o}e$13B>792iS?)?q^O*1YszTRzDqQTt9p|YXF~CI~)3t9CiKI`DkVca1y{rOZ zLF*ll5IpDcpW;rA$8@FTcE{WEN>$^jE6d(;+~yc4HIF1rV^Ke|k?x24mdtC0aCum^ zYN~!?dbc?*YVz5XD?VipC$jVb@N(jUgJ@KURwrM{)~l6w?R`GJG>LEglSo&Z*LxRp zw^#eWage`i*;#$_?2BYTCB=HYSAYve{FCbpbiwfc$Rg?(yZU1BynReFch6~UerUex zOG)=v;rukER*Xg=>=GQyA72W9cc1K4s;V^)Hb1WUeoZlz%G8+S_U)kjR+1IIif9Vk z60Waxm7yAk`ecb8JWtm+2lS&pE}T%EG@jgIj=h1n`0>=5#Ikof&7y8iq?9LH9ntdS zDTIfaP?ZAvIW0uuY#(&S!VubcS{sQ@FBfWA_k9}>_`s(j>aHm~r(Uox9q00nlwe}> zvbjmtSCjQe*SznhQW|A-_!OQ6elb$tskq*@M{xsJU?f3w=op(a{dSvMVaVIiZ|ZpB z!RVU&U5*~NoJRg@$R8Z06Xl*ce%g--2nZ7#l$G@~m6iW?wh(`!F!N4QvsR}bb5CnQ zDoauHxZ*R7$Tc1o6-Ca>;u;E;>$lpA!~DMS3OHyOSa6a~hK7A!avG6Wzp4w?yk$~B7dFX;;(VbF$@L5-CiR2>gozXQ-rDS>_xCS{%OIONc&s7R$qAMW4WdQ&=)7 zh!eXD7Ly)~VB>mk3cX~2w}-MG?;fiJ9L>~pXDwD zre&B?ZkV1)EM9j8A|mk#QTtGLH{PY$o#-$p#Hmcm>KUiqD~$@t+9}=-n6C>Ke=L-MKt|pdi$pnL za6C2`I|o-;zU}5#J{||OET4&l4p0ZHjInpn@b|zN`rj}@`8%Pc(0uZ8R5HE@Jb?=a zhve~fad!1Y_{#GA;zi)Ee>RKr@%)0|oMib-b@X_Y-8?WnP%)?&5TNSo;0@-JqvDbA zK-(e=RMdW_z~9O8+2e3ngt)kmkB^uSM9j^@P8=j9B_$37i-W-cJObe9=ZZu60$e@$ ze^UI$p@Q*5c{pHk4sNbIKRJ;$ZeBQ9K0bUu&+p{;UX-dYzVUYjKkt9hd*aaIn)n+i zem;1BI2Z_o1At%vSW5h_^7vjIoj;^qJ%6_%-k##VNUS(W3@Gm6@^=!RI92aI_5D)` zPb2*4TX6%7r<<1t3Zv?camDffRVmil%k!@~y*x2Ln|_Vk8Eq?$AJi|+f0a?!)Y1Dx z=BF9$99*!!Bz~g*ibSLSz+t^SoPS}^C~=H4#sxnRPdqc|@9(t zAKm}gknoECxyauv_iI$YER0ZbLwWsFuc`7kheErd9MFhA*b!h`2pj`NK>2!5|b&5(9z2ZBTz9)O7X4Aze|JpM-c7Vh(sRNhw>11WXD9z+XTCPzkUt zK*|OJ0sw7oAW$$G4o2GA{Dnf-!vP-|Naw$f?I#r)PX&?!0#TB978KML41n68Q2;pp z5@3r2VmC=?uy`9<|}T@Z?TnzDRgG2ovqdd^6kt(%7nKHMB!(QZDTe|8x;xL^!% z$e+do!N4FXNe~bs1%XRKC18JoZelz<@oxW<6$BImfq(U&Q3y3WClc>|4lYPLj5yZS z?pMd3R#bL#cJt72Lt|w5Apg*XPvLsMoer1f^E6Ob;?Y!9hJmDDFaTc1FD!oY2xSip z5{FU2fAG42ASnP40sz8{Ku`n(hydZQB@n>h=J^NO&BMse%~_W3rzv=Tj`t5T9el<> zBXP+8EggQ~4z_;(6Z&U<;F0+~@)6o@DCEx!@!P=BzdCaX`!J_Da^KtWV()G}_am1i-|DNZcf&XAKz$b1`oQI$0|1hb4z{%hjMn?ys zftPjj@cWB?LyY@xcfXm(+2L0n<>C32(GW<~Pb=ud1Oni2Bnkkvm9Pb)&`2Q2_8+YI5A#)b z#+N8h3=ckk@d*E(2LHvfg7HaO0sxlyJwfqx(Ja=-27{;~K1foPNs3Jn9;0&O7x zGz^L_cW@{aAO(a0kr))j249>-dH%U96a&RqR}30}#ybT7iN*(q4F-h)*uc?}AQVah zg0@BeD_IF37=l7c!T}Jd6cB*6g@S$-eFy*pu|XpxQ20WNl>Aq+Fo*;Y4TnkrkWye6 zzy=5f0+2Ac1ON#~fq+0MAPNQf*RoPjG)xLVW*bSQEdU1lsaFcW3$=m6z-S2w2!ugN z{VTn27!U;pVITloFa`#|*KNFV2oUeU7$_WWD~X1I!FauRNBy;tfWjb>5GV+56EFn7 znSo&70JyCL9AFE<*Io%U3J3o)m(Y6pY9ERVU;A!z&9Vkdr5`aY7;MV{OLxXMMV5k%Z@>>8oJN)hxzryKnULhm? zKX}n^!hhL@<5_-d!*B2LPYdFIJTCn1W%yM8|MKtmg7yDW1rN`EmHbEc{ja(HYp(yu z0{;>CzuxsaK<^{)TV%tiI*3rCDA{(;H||2pwaTm>KgRV0~>mbwbT`Op8{ zmggz>7D}v!nI{1OHPg=zA;F_eHhd#FPE$vf{1YiV6SojS6psS|0g;rZilUMI+-8Qj zhO$0$&l@HkzH3)Nlq@p}V{P_kH8caFwCMKo%7PETaI-oa$gnkY>Xp(Mo^+KsG6p~- z`^xjVPU$(H?K{-c+jll!$sfdT`@GuQnv1*i5O!Zv85ZC3qK{dp;py`gV%kuZXPIqXFCh0N0=jWL~_`JOP!L~~xA{r*xz<2^x4j1UlzrLlH+{e^;x%JUg7AtmX}D+~-DXe?u* z3(d2I_@3T4c<*pWmc)0nlW>d1hdVTnC*;v;hZlX0mHD<%N~!dhf#8oaJ*P)JnrliH z>AD_sshTaf`zHLxgVw7AEkORm<1oh;W^Jc^EKP>qO^Nx~)geD@mP)9P6bEGsiEoas z2z=;ZFEG;x#&`^|F1fQIws=}$NZRR_EjSzHmoNJ9c3(k4+*Y5T2uH6JrDbPe>-M!f zB!SIzoSy<%`j0;Ezb@hU#Gbf+t_s&)KR>5D_vUUkoZrez3m&h(t*No=WqEx2cy6$a z+u1K^LD!xGWVKpB_a<6n?6K6BO`LFy-uukSG(xeNw1b)$jd|i9r8!CB(BypQL&l`7 zG{@VUDeyzBI|h8PUYFWzCXGiI9xo?4m93HlR=0B*TXfqzu$8{=X}q7&gY!_zQo$um`Tl6o(+S+ zq%6#-4$yBy=tG({1Nv#L^o0w9&FKwsa^XABgm4a*&1Ct4aDFfcgo8mWCJYwz;9L^x zkV=_U%mhz^e~P zK%yJ3sGPpLmFOQ=kryf;9INV)PfG}z@Ou>9W^yc}8vp20u)%wkuDdP^0Tn-jZW_%L1Rx?Kxkc@FuzV z@O#Hk+C}$8-W=#JJ)cT!4OV;|*lgYQDDair4wWNHS(^aG> z>wP4nx*?*lI)CfK&c@1hBfy24#ujvoo&rz*ZU6N#(i_{YmB@>i=&w>DOLUyuyIUpE zCP^(-^^x;0EneGlxh*O5{OZcYc34zjwHwLf!njWJfzgl7B>kDma~->6@7TP!0Goea zSfixqQO!JM*>N^Vw{aV=Ep2=ED(X{O_0j`lS1cEs+}P__KG1;eY;;Q-TeM~q91)`` z?(OZhS00EXTdpj&!)l*6;&9W#!2(~X%B|P#S-C-wZLwF&qF|@onLCzR=TGd9Pjv8R zwYEj7ot7(fH-N3Jgvz4YJ$n7+;9+-R=!N0@rrlSU1E251e7Gx^8DTmYBn zh0%^=i<=8~ed_gaOB7Lku)?#bSg8VYD&_vmD9K(0=VePhDd5~0UEEcEBQFMOAL#~T z(?^BD?^gqjT7n7b7rPurVoFxO8m;Gu;D}0g&pm~ z8jkoc=Tu)7U%L0@t@kQ1&x3uh=30IBUMQJpN1Uw%*kaykobyOv)}43G4fXKLbE)^d zHY2N-dOtUT@JNj%yR$UHN+>huu3Yk5u8XSG>$sxS3cOKjSxxgmgKh3?^UYTuCoenH z@67U-c{@m}5J9Yb7hZKQFXr)1^fPu`bp7DJyJ5+`=mRD<0nBQN1zl%+TsrW*OCLt+z1?Kz>)^c{d;au?(_!h7 z0;$-(f_;sLDx3UIl*+^V`?vPJUAwO$wYMRR+@EyN@tt7w?gq8nFU8^(mVZ$zuDtHt zmFtr^PfIbk(b=g`Ri;lR=~bb2Tk+2HI)wS5%&lW>!oWDvOr2CqR`#q!u`(%vvlz#H zjp3(D^F=mjzIITHXh{N zJHNiy$<}th>GFj;IvcXths4ijTS?s22n&fh>fEtj;bd>40a4&56&vq5tSny}lZy8@ zzC~@h-z$|<=Z&~cqnoyBpSdG4rvtfua}c&HbImIAj8LJ|^RD*Sk)0~UWlzf8XRjDq ztlx3c{$;*$>oDb=)d~8rh<-C8<>u*!m2T`|#Qsos&E2pyP0IV--yv4F;^y5HmsyyB zyQB0G#rEDtle1d6%(h>3{#GZ+ri|X3qRNW>hvfXiQ<{qBa|;tbhJ+qNHC)TII$a5O zJ-*E)&6*>xdT{@auG}2L&*zEaOK&R8UFVAl_T~is>IaE#E8qkDalzer2 zyyLEG)s~4?<4AXQvDT?Tte}+@kldDE=D{w2ap4aG-R@PalU~0>S_ZcT;ZwBZpk#2} z!xI4?1-YU^tCEh4;3A9sO@)aMvQqesoIMDTorFG+kf8fzLZa?c{ zJz=@6i_lGx_SW2QS;JG!o5?q+X|cCsE>IVJ3acsEVJZI6&N(8xtyhD$Cr-{x%&dBS zc|knx%68)}?{kZ>_THU7oq@xoS4dCh99%jiky<>?K-&1%~a~NSeKR)X>SRO^R)HnPS^BWx+71E3581=6>l|B$jdf zMwI#iHfohlW}EqthORPt#w_Vr?WVi!&OW(o`&?S*v>RwU*Ph+Ta-w=Xu=&99@{7!I zJDO1KEM}o$xy4uq0PN{k+m7t zZrP5mwba`I2_@DoVl#|aoX~mTRCG}75>Vr9y?2I0XV9?n^F0=p6>51i_Dah!d7RwR zP!6?uj#dS;|I0|Nde2R>H#@1`thx6JK&L)Utpx<@u)HH8@v?igZnPiFLaZ_xt5bTP zqO`krM~q3@7i`AKn0%kTrB4zc0;Q>&V>M>MH{<%H4ah?ec}Y$U`wBu;5b0IM9bSqK z{`d15T`8W|@9T)o9ICDiwvQh@_q<5)lHL)1w3TbZmM0Du((g0w9XLgTRg=feWO15V z)R|twxLFz7gjb&4t3CRe6tgyeyNA*Gqb;sC6kX@L&X}nn{VCbW{O&qm`+k|F0WXe+ zW~qu$$OP}TUUJ;$YO7boZ%W_5d3csxy64YquNZ4qQ}c2J?$+LgOU}Sz)GaMuH5J~D?lw6U z{Jw7ck;*fL$mP%X44gieon@UP8mV?edzpRVnA2Qhy5sUJZircRVR~W@ApHrRhKb$a zrMyU%@6pl?{nB+#Oj~pxX&xYJVVsrOxNzUwVI6kdu}Cgtx9Bjw?Dfh7cOUBah`Qu z81o_J_@Tk2=E@h+2jUdB;_dRhj_NJhFNp0~7v@~_s$mA3tL$wWZ5PT?G|AeyTzLI? zLFT=pX0JL4)98f8>(}}`Qp81=R#Eq~XU}Wz^MqxkSavb;vL#9qlzX%n#vFys?<*)A z@M(7(-DMWuxv(Otn;I@nGxn_0NA=1~J$4(hSx+=EPuY5GId_vd$JnYGe_&Y!!Wat5mOHO!c}jFC=;N;sThT zNUctI>dm^xS>_{8T;OY}=7y{)WbYac_`(gF7&aXrKUh1yEF##nbw%U#^Sg9hKXeov zZgU^qWRukLM9pW@olfawkOY5tyO>LYCnsQ#QVd>hk_z^THnml&p(y2r4{yI)W&*;Q*d|K zctG4Z*Io10GJ;aJ?W?e~YwAgcSos0PRbOs7o>FTb2+V$SY|mEz)L~37C|&q?Q}b9% z*O*$?se6VA9JT%{FZzt?CU736b(w2MaC7%HCWX*)4bBF}n;BZxqAPbNZw`MWyx#D5 zVbX5cC0qB2+(V0V$YS8qg;={`L4!=`v-c@2ne7D68;p%D1)*)P`xY;19m_NOJY-x& zS-uCGQ~07PI?Y9MQQo6Qa8s3Ni;U{+^trv-kT2lKiyJMVx{b{YLppSp zSfrb}>bf=RZf^WkJW>V|=9*{U$BUdk3Njoex0K}9%zQe(8jes}lLk);p&YJ1-t~D) zL_+H*>HW(`ZGl5KOdUnT^aC93NW~W$>sPS)b|vf_JsAg=-8?@*g>TroJ}X{lD@I4J zK1NC9(`(g$#3QuoX+Nay*dh zcqBzkw`d$KDlXi%=5f*1J$_{Yq94|Bt=MTLdfWhRBvY^K?7wfeYfbFM4W3cI+#koYmN!%#WD}!f{r0JPC$qcKxQCTubQnNM1cVOKt2r~L_2>6r;-^T#qVr>UEVRJz^P6wxhLYfA#0x^hHv*G$&29x4IUGo(J zx-vj`@%bEzuC7oh)DdEJ*j!ItG?`4+MPYO?7$hWt> zpT+ivPh!&OYysZ@fq?emU%{bWz%&S2{AytGdJ3M$XXsi$7dYrVkbo`*g(4wQ7$kLGv<^zw&+iuv9^W+ZhrK`5;5k80#kvk4k1gN=plKlJ z&tLMhQI4;G_p?m_51d?@^4pie)PK~3Hlijkd#0Rp4*(~6xh zjn8Cr{h)GV`7_u;-Vb3XmLKTIr%eVAO~9bZL^KMABVtKpGWv&*GsxvZX+MdIM(Ln2 zQ#%ZRvIfGWLFvcxqj`e59DmQLjUQ1oVf(VV)@%l7fWZD?3!-ql>9;lp2%dwPG2Ft` zgn%X!pm6C-TZRr#G2wzVK1hW=kZly2j6`9PD1s9jM?s+}c&LQ%6x8%Nze}^ZPHeWX z0b()~@JWBC3{P%bLyW_yGp07D>BE@j zsXHyJ`&YvMf#m4L7W)5pI6p+cqZo1dLN?dOmTOD*1_AzGJM`IP~@$xDdvzan;ZO-eMc~0`f55nzN{%8g~O*9jY0z^qiBEtrV@ZLbq}F9Pj9mR zq}u-L68Vn8V>9_e8W%M3gqXkpVKmvW;CA2W2M&!GTGljx`|2{7U0}_}tGzLk-(jhhl@N^`d1`r{BhSr%x6q!t%uJqsCUo&5*Me#s5 z#9wf&uQd3Z+loO$#Dc`&CwT^oqTq0duQya*ce3$+%Uu1**7%3q)}L&h6pKkdbQEwn zzATXYYtDb;fZxddq(4O=?7vn2S!`O{gv|+tnu!VjRws- zG#r6}VUjR7GKifnAYazkq?jtFZ&{(Q`!`uMt^Cs%4xvo1LE}C2w4nR_ap7y0K~(U6 z`SrD7{a>1Z!~Zq%kK+4pxc&{-KZ?LV68<;4{teeZioib-{x`e+*TOaX#|uZ$A9|n? zLa!4Ai-dEbSCKR5R%TS##N>B+#i;|(iX_K;0}uLl64}X*2<&Kz60|szZ((gZvs+@J ztlG-M>ppeBU}6>)R3j&^C;dlPdpX)eZ<{qKvHSoTMG3`AhI;Z8%8_PMw@!M7Lcn@X zi@S#WgOl!$R9i0F-$*pR1fSK9u+c&Ech28Yu3IzeyZqv?F=w}r&zO66mI6_-w-fVnI@hx|TOl$B+MkKzx?g1%AGM%1oWCsT^`Omh z_p6tCq^xWWuldh6?2~osRvZ$zPV~puj1Kj%_uorR9TSC}weWQ*3pjbZ`|5z0;S2HS z;=43T6^^B!46AQL#*m+sUf5K;Wvp;ept3zv9>GiQ;vLem}&S#--V5^h^QwC=`|l%4-Sm$z&r-u2EHl9 zHzA@m_z&7dV0wc#Rx8W~wuYqHR7Xe5g*8ftE`cd!y2FjE51tY=3{G5cdTwQP@cEUO z2fJ4l=aqb>Cazxn`tmE7I{e7unVKps*Kt6${?n&^yJP#}2b&3lyYpUed4MmvQ`h5n zD7RIMLi0geRg=XJh!V^OnS*g z=v+HdTvc9WShT*L`0=Wt6HWQ{mOF>v9(p%c-X7$;xm-GD6G!yyN|brM=+VO)@ARLK z?2q} K)Ldha$o~ONI87!1 literal 0 HcmV?d00001 diff --git a/website/server/models/user/schema.js b/website/server/models/user/schema.js index 5c64499f1d..9114767e3e 100644 --- a/website/server/models/user/schema.js +++ b/website/server/models/user/schema.js @@ -142,6 +142,8 @@ export default new Schema({ redLetterDay: Boolean, legendaryBestiary: Boolean, seasonalSpecialist: Boolean, + violetsAreBlue: Boolean, + wildBlueYonder: Boolean, // Onboarding Guide createdTask: Boolean, completedTask: Boolean, diff --git a/website/server/models/userNotification.js b/website/server/models/userNotification.js index 45b0f1bdba..5bee1533c8 100644 --- a/website/server/models/userNotification.js +++ b/website/server/models/userNotification.js @@ -65,6 +65,8 @@ const NOTIFICATION_TYPES = [ 'ACHIEVEMENT_RED_LETTER_DAY', 'ACHIEVEMENT_LEGENDARY_BESTIARY', 'ACHIEVEMENT_SEASONAL_SPECIALIST', + 'ACHIEVEMENT_VIOLETS_ARE_BLUE', + 'ACHIEVEMENT_WILD_BLUE_YONDER', 'ACHIEVEMENT', // generic achievement notification, details inside `notification.data` 'DROP_CAP_REACHED', ];