From 42de623fc66e27f37c7c3b480c772561b656e8fe Mon Sep 17 00:00:00 2001 From: Sabe Jones Date: Wed, 27 Nov 2019 15:00:24 -0600 Subject: [PATCH] feat(content): December Mystery Items prebuild --- migrations/archive/mystery-items-old.js | 110 ------------------ migrations/users/mystery-items.js | 72 ------------ website/common/locales/en/gear.json | 4 + website/common/locales/en/subscriber.json | 1 + .../script/content/gear/sets/mystery.js | 12 ++ .../mystery_201912/back_mystery_201912.png | Bin 0 -> 1161 bytes .../mystery_201912/head_mystery_201912.png | Bin 0 -> 439 bytes .../shop_back_mystery_201912.png | Bin 0 -> 1066 bytes .../shop_head_mystery_201912.png | Bin 0 -> 383 bytes .../shop_set_mystery_201912.png | Bin 0 -> 1240 bytes .../promo_mystery_201912.png | Bin 0 -> 4190 bytes 11 files changed, 17 insertions(+), 182 deletions(-) delete mode 100644 migrations/archive/mystery-items-old.js delete mode 100644 migrations/users/mystery-items.js create mode 100644 website/raw_sprites/spritesmith/gear/events/mystery_201912/back_mystery_201912.png create mode 100644 website/raw_sprites/spritesmith/gear/events/mystery_201912/head_mystery_201912.png create mode 100644 website/raw_sprites/spritesmith/gear/events/mystery_201912/shop_back_mystery_201912.png create mode 100644 website/raw_sprites/spritesmith/gear/events/mystery_201912/shop_head_mystery_201912.png create mode 100644 website/raw_sprites/spritesmith/gear/events/mystery_201912/shop_set_mystery_201912.png create mode 100644 website/raw_sprites/spritesmith_large/promo_mystery_201912.png diff --git a/migrations/archive/mystery-items-old.js b/migrations/archive/mystery-items-old.js deleted file mode 100644 index d298d9b7e7..0000000000 --- a/migrations/archive/mystery-items-old.js +++ /dev/null @@ -1,110 +0,0 @@ -import monk from 'monk'; -import nconf from 'nconf'; - -const migrationName = 'mystery-items-201808.js'; // Update per month -const authorName = 'Sabe'; // in case script author needs to know when their ... -const authorUuid = '7f14ed62-5408-4e1b-be83-ada62d504931'; // ... own data is done - -/* - * Award this month's mystery items to subscribers - */ -const MYSTERY_ITEMS = ['armor_mystery_201810', 'head_mystery_201810']; -const CONNECTION_STRING = nconf.get('MIGRATION_CONNECT_STRING'); - -let dbUsers = monk(CONNECTION_STRING).get('users', { castIds: false }); -let UserNotification = require('../../website/server/models/userNotification').model; - -function processUsers (lastId) { - // specify a query to limit the affected users (empty for all users): - let query = { - migration: {$ne: migrationName}, - 'purchased.plan.customerId': { $ne: null }, - $or: [ - { 'purchased.plan.dateTerminated': { $gte: new Date() } }, - { 'purchased.plan.dateTerminated': { $exists: false } }, - { 'purchased.plan.dateTerminated': { $eq: null } }, - ], - }; - - if (lastId) { - query._id = { - $gt: lastId, - }; - } - - dbUsers.find(query, { - sort: {_id: 1}, - limit: 250, - fields: [ - ], // specify fields we are interested in to limit retrieved data (empty if we're not reading data): - }) - .then(updateUsers) - .catch((err) => { - console.log(err); - return exiting(1, `ERROR! ${ err}`); - }); -} - -let progressCount = 1000; -let count = 0; - -function updateUsers (users) { - if (!users || users.length === 0) { - console.warn('All appropriate users found and modified.'); - displayData(); - return; - } - - let userPromises = users.map(updateUser); - let lastUser = users[users.length - 1]; - - return Promise.all(userPromises) - .then(() => { - processUsers(lastUser._id); - }); -} - -function updateUser (user) { - count++; - - const addToSet = { - 'purchased.plan.mysteryItems': { - $each: MYSTERY_ITEMS, - }, - }; - const push = { - notifications: (new UserNotification({ - type: 'NEW_MYSTERY_ITEMS', - data: { - MYSTERY_ITEMS, - }, - })).toJSON(), - }; - - dbUsers.update({_id: user._id}, {$addToSet: addToSet, $push: push}); - - if (count % progressCount === 0) console.warn(`${count } ${ user._id}`); - if (user._id === authorUuid) console.warn(`${authorName } processed`); -} - -function displayData () { - console.warn(`\n${ count } users processed\n`); - return exiting(0); -} - -function exiting (code, msg) { - code = code || 0; // 0 = success - if (code && !msg) { - msg = 'ERROR!'; - } - if (msg) { - if (code) { - console.error(msg); - } else { - console.log(msg); - } - } - process.exit(code); -} - -module.exports = processUsers; diff --git a/migrations/users/mystery-items.js b/migrations/users/mystery-items.js deleted file mode 100644 index 60357445b8..0000000000 --- a/migrations/users/mystery-items.js +++ /dev/null @@ -1,72 +0,0 @@ -/* eslint-disable no-console */ -import { model as User } from '../../website/server/models/user'; -import { model as UserNotification } from '../../website/server/models/userNotification'; - -const MIGRATION_NAME = 'mystery_items_201911'; -const MYSTERY_ITEMS = ['weapon_mystery_201911', 'head_mystery_201911']; - -const progressCount = 1000; -let count = 0; - -async function updateUser (user) { - count += 1; - - const addToSet = { - 'purchased.plan.mysteryItems': { - $each: MYSTERY_ITEMS, - }, - }; - const push = { - notifications: (new UserNotification({ - type: 'NEW_MYSTERY_ITEMS', - data: { - MYSTERY_ITEMS, - }, - })).toJSON(), - }; - const set = { - migration: MIGRATION_NAME, - }; - - if (count % progressCount === 0) console.warn(`${count} ${user._id}`); - - return User.update({ _id: user._id }, { $set: set, $push: push, $addToSet: addToSet }).exec(); -} - -export default async function processUsers () { - const query = { - migration: { $ne: MIGRATION_NAME }, - 'purchased.plan.customerId': { $ne: null }, - $or: [ - { 'purchased.plan.dateTerminated': { $gte: new Date() } }, - { 'purchased.plan.dateTerminated': { $exists: false } }, - { 'purchased.plan.dateTerminated': { $eq: null } }, - ], - }; - - const fields = { - _id: 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], - }; - } - - await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop - } -} diff --git a/website/common/locales/en/gear.json b/website/common/locales/en/gear.json index 4c70bfb3ff..cefcd8e2c0 100644 --- a/website/common/locales/en/gear.json +++ b/website/common/locales/en/gear.json @@ -1411,6 +1411,8 @@ "headMystery201910Notes": "These flames reveal arcane secrets before your very eyes! Confers no benefit. October 2019 Subscriber Item.", "headMystery201911Text": "Charmed Crystal Hat", "headMystery201911Notes": "Each of the crystal points attached to this hat endows you with a special power: mystic clairvoyance, arcane wisdom, and... sorcerous plate spinning? All right then. Confers no benefit. December 2019 Subscriber Item.", + "headMystery201912Text": "Polar Pixie Crown", + "headMystery201912Notes": "This glittering snowflake grants you resistance to the biting cold no matter how high you fly! Confers no benefit. December 2019 Subscriber Item.", "headMystery301404Text": "Fancy Top Hat", "headMystery301404Notes": "A fancy top hat for the finest of gentlefolk! January 3015 Subscriber Item. Confers no benefit.", "headMystery301405Text": "Basic Top Hat", @@ -1876,6 +1878,8 @@ "backMystery201805Notes": "This gorgeous feathery tail is perfect for a strut down a lovely garden path! Confers no benefit. May 2018 Subscriber Item.", "backMystery201905Text": "Dazzling Dragon Wings", "backMystery201905Notes": "Fly to untold realms with these iridescent wings. Confers no benefit. May 2019 Subscriber Item.", + "backMystery201912Text": "Polar Pixie Wings", + "backMystery201912Notes": "Glide silently across sparkling snowfields and shimmering mountains with these icy wings. Confers no benefit. December 2019 Subscriber Item.", "backSpecialWonderconRedText": "Mighty Cape", "backSpecialWonderconRedNotes": "Swishes with strength and beauty. Confers no benefit. Special Edition Convention Item.", diff --git a/website/common/locales/en/subscriber.json b/website/common/locales/en/subscriber.json index fd310139a4..94d85761eb 100644 --- a/website/common/locales/en/subscriber.json +++ b/website/common/locales/en/subscriber.json @@ -165,6 +165,7 @@ "mysterySet201909": "Affable Acorn Set", "mysterySet201910": "Cryptic Flame Set", "mysterySet201911": "Crystal Charmer Set", + "mysterySet201912": "Polar Pixie Set", "mysterySet301404": "Steampunk Standard Set", "mysterySet301405": "Steampunk Accessories Set", "mysterySet301703": "Peacock Steampunk Set", diff --git a/website/common/script/content/gear/sets/mystery.js b/website/common/script/content/gear/sets/mystery.js index 28c8800783..f7e9b2c898 100644 --- a/website/common/script/content/gear/sets/mystery.js +++ b/website/common/script/content/gear/sets/mystery.js @@ -394,6 +394,12 @@ const back = { mystery: '201905', value: 0, }, + 201912: { + text: t('backMystery201912Text'), + notes: t('backMystery201912Notes'), + mystery: '201912', + value: 0, + }, }; const body = { @@ -763,6 +769,12 @@ const head = { mystery: '201911', value: 0, }, + 201912: { + text: t('headMystery201912Text'), + notes: t('headMystery201912Notes'), + mystery: '201912', + value: 0, + }, 301404: { text: t('headMystery301404Text'), notes: t('headMystery301404Notes'), diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_201912/back_mystery_201912.png b/website/raw_sprites/spritesmith/gear/events/mystery_201912/back_mystery_201912.png new file mode 100644 index 0000000000000000000000000000000000000000..26105949feda681b9f3c04065ca1e8f035693226 GIT binary patch literal 1161 zcmV;41a|w0P)ALFPiyTzt?dlY?o zCIr3s)2h`a%T*lm)pjKMe)YzZ%2e*e@}spUO~+&Lc&@2WHk__K&x`~H61DaKnSDu} zhF48nlla%QDW_Sf)1I_Z>eP!&o*9W+AuZMV+k#iC_3hU#eem$j`ml;O%^x39ai7dU zZmM;hyyl*?(eLwhnEHx>05FiK^$$9g3*Jp<9)(Tcm#UFuX9RLmt>c`o*{O{Izpd7A zg`MSYupU}&XqFj?S|OS6WE(3Z;QwO!PT#Dc&h&CJ?5uCs;_+I`RW+|}sd(>_ar2X@ zvvyp5c~dK~bnHA8@4iy67yF&vQLWInu86VD+#QV#CTj%-61Dy%PIXABpn%W%uHu2Y z8N*aOw|JCR*4>78cU8P+(bze?(Lq};z0f)>n>1Qq+vP`Zu4q+8V$CX!#;yLQTL!gO zU?5Sei&?A8R4eC<)0(~Zr17eXV{t2@;{MrzK`NeIG;+3zONVFsdZUAC-v5Z3R3D4k z_2f@&KU-D2a^@JV)01~zo-$>yWUatJraPY0S|vL#Jv(L6>B7l{i&T8O?(HqRP~gv0 zaqG91Jt7l+s^aR6C6m1D6nQRr4S6|1U7%?1idsUaWu`Vt4p&Sy)?lf%0s~3bYPq*{ zH7Y+#$8v{Va^QO1GZl{>(nlX}`rK~0ty!s4r*my7E1vkTZIMq7I4SpkiU!O`)Cwt` zwaO_kGp=pr6O0O#i{gU5nfa!yRW7t;)@oT+mPv6^eQx2TQ%QZ(2d&?h&Pbd7Kol-y z*4o_m^J}78j9WEWW+ZBbl+IdvlFd3jAt3c~_Wo0R9h@Zb#!M(=j z?J7RFw8)jLb@Rmrt<7151^dKD!}WCz$lIG};V-Y>DO07^3JfG_{Rg#fE1$63q!+oR zCAW2?a%BeF9gXYN_1YOD^cGlQLGDK{JEgI?W2lM`-D#>)@xYwm02RwEw!dxT{_5wh zKP|wFM6E#9`WrHX_4}+m6(6rCPTJ>MzqEI^s8~J~Ad$+A#_abA$af2%R$w4etBV<| z)a!zf{o3fUjc&yvFzO*P|8@nUSa!l9iy>Cy=}6QZ)yz*Xix8RDAQ5 zyalu$wO>cGrK~t)YCAI$7)aFWB2F*RyAhgRnJ%3uZw-+n5AyBehOd(u2@E6v00000 bBqP57@K>&iH<~?Q00000NkvXXu0mjfs@W+1 literal 0 HcmV?d00001 diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_201912/head_mystery_201912.png b/website/raw_sprites/spritesmith/gear/events/mystery_201912/head_mystery_201912.png new file mode 100644 index 0000000000000000000000000000000000000000..20f8a594f272cad2af17cd37c88e9c9956443fab GIT binary patch literal 439 zcmeAS@N?(olHy`uVBq!ia0vp^ML-jA5L~c#`DCC7XMsm# zF#`j)FbFd;%$g$s6l5>)^mS!_%q=9!#3U}rzlVW=(Z$onF{I+w+gpZyOpYRK4`P#( zQlGNw>}i-A<9I$nyEANFiZmCbUyb3ALW-H|I*b+@*~7Oqkb z^k5TPJ5kfH_rjeev%3CVeaguwGO6BZYuh99O_l3Yn%4uZ1%@CNa9~#)OQ@mUw7xtu2rJmFK*Mr}E;OlWW?>x`j*yr`^?tc7! zpYQMY`n|uO?|ng06h%=KMNt$*Q4~e_Ut?S7fIaRTo#yAOu8O_?r2!^dzg?Y}Pe!~4 zwjbDD58$%(d87S)`P1!9=^RLHTi-RAG|1caPSM{YU>5P99mx*T@P5O;%>G0oig$9_Z&S!}18>9CKR z->=Nha029JTJP{@A8x4!Xz#h-4RH3O&DE(ayyfD(E`a9Bk}81Hmxeq5GroWqU~1Ms zuV3;7g6lLxQejA}`Cgug!^TU1HO|a80NyX#PzBIC{J0n3OkK(Dr7ZaPg}YqxlGJpk`g2yfd#a(LN;E3`w*@ z-B6H?xt0)GuMFM>*!bEC07n0sW-+FS8Ik8XR#Wy?Jax$0CeoN#vyU3GP=?4IlXvYz zZTUPSB)tn)W)+wjBB?JK0%V&{RGx66M4BNCjXoU!n3(ZT0T71-gM%w|_^AZNzHKO5mj6S>r+pLV8YZ&;2n4PD z8QG^%LsIpBNUSUoQ@-gL_5l2JXxp;x{eJS@%}#*Bm8DVZiZ?sdkVIFzv5+-`Jb~6L zgB{^DN?P`I#mMP4YiIFTO_|HAGf~u#WDSYjMZfB*X!&tuMF0Q* literal 0 HcmV?d00001 diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_201912/shop_head_mystery_201912.png b/website/raw_sprites/spritesmith/gear/events/mystery_201912/shop_head_mystery_201912.png new file mode 100644 index 0000000000000000000000000000000000000000..e2a8b8f9752ca07242308694dae57481ef309f3f GIT binary patch literal 383 zcmeAS@N?(olHy`uVBq!ia0vp^E+EXo1|%(nCvO5$Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmP-w~#2azW3Fn4h9BB9#0p?kcwMxuNw*-bP#EHD4y)L zw1}~l`^65X^b5y$rcPdw(soU9hf|5(f&#{=UZPixKc#s5!}{r`Kg+c(&@h+SGF8oA>ZBc#Y(r*w75ppS<&tCcjh-f1!sAl zYCXCf+vW7{txS@rX!85VGD4?#E*h0wFWCFLYHvoH%{%X)vY89YByH1Qbj@2I8J5;o zayxK}e)Hrkjn*Ca3Uv>i<9lj#@Ke0n70E|B$G1jT+;i1nfjOUHYYF?G-EFRZ>kM{) O#5`U7T-G@yGywpePL^H( literal 0 HcmV?d00001 diff --git a/website/raw_sprites/spritesmith/gear/events/mystery_201912/shop_set_mystery_201912.png b/website/raw_sprites/spritesmith/gear/events/mystery_201912/shop_set_mystery_201912.png new file mode 100644 index 0000000000000000000000000000000000000000..1b9076992a4efa755712ff347539169e4b80e970 GIT binary patch literal 1240 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 J_|N0#{{zbb6bt|W literal 0 HcmV?d00001