128 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { Observable, Scheduler } from 'rx';
 | 
						|
import { ObjectID } from 'mongodb';
 | 
						|
import debug from 'debug';
 | 
						|
 | 
						|
import idMap from '../utils/bad-id-map';
 | 
						|
 | 
						|
const log = debug('freecc:migrate');
 | 
						|
const challengeTypes = {
 | 
						|
  html: 0,
 | 
						|
  js: 1,
 | 
						|
  video: 2,
 | 
						|
  zipline: 3,
 | 
						|
  basejump: 4,
 | 
						|
  bonfire: 5,
 | 
						|
  hikes: 6,
 | 
						|
  step: 7,
 | 
						|
  waypoint: 0
 | 
						|
};
 | 
						|
 | 
						|
const challengeTypeReg = /^(waypoint|hike|zipline|basejump)/i;
 | 
						|
const challengeTypeRegWithColon =
 | 
						|
  /^(bonfire|checkpoint|waypoint|hike|zipline|basejump):\s+/i;
 | 
						|
 | 
						|
function updateName(challenge) {
 | 
						|
  if (
 | 
						|
    challenge.name &&
 | 
						|
    challenge.challengeType === 5 &&
 | 
						|
    challengeTypeReg.test(challenge.name)
 | 
						|
  ) {
 | 
						|
 | 
						|
    challenge.name.replace(challengeTypeReg, match => {
 | 
						|
      // find the correct type
 | 
						|
      const type = challengeTypes[''.toLowerCase.call(match)];
 | 
						|
      // if type found, replace current type
 | 
						|
      //
 | 
						|
      if (type) {
 | 
						|
        challenge.challengeType = type;
 | 
						|
      }
 | 
						|
 | 
						|
      return match;
 | 
						|
    });
 | 
						|
 | 
						|
  }
 | 
						|
 | 
						|
  if (challenge.name) {
 | 
						|
    challenge.oldName = challenge.name;
 | 
						|
    challenge.name = challenge.name.replace(challengeTypeRegWithColon, '');
 | 
						|
  }
 | 
						|
  return challenge;
 | 
						|
}
 | 
						|
 | 
						|
function updateId(challenge) {
 | 
						|
  if (idMap.hasOwnProperty(challenge.id)) {
 | 
						|
    challenge.id = idMap[challenge.id];
 | 
						|
  }
 | 
						|
 | 
						|
  return challenge;
 | 
						|
}
 | 
						|
 | 
						|
// buildChallengeMap(
 | 
						|
//  userId: String,
 | 
						|
//  completedChallenges: Object[],
 | 
						|
//  User: User
 | 
						|
// ) => Observable
 | 
						|
function buildChallengeMap(userId, completedChallenges = [], User) {
 | 
						|
  return Observable.from(
 | 
						|
    completedChallenges,
 | 
						|
    null,
 | 
						|
    null,
 | 
						|
    Scheduler.default
 | 
						|
  )
 | 
						|
    .map(challenge => {
 | 
						|
      return challenge && typeof challenge.toJSON === 'function' ?
 | 
						|
        challenge.toJSON() :
 | 
						|
        challenge;
 | 
						|
    })
 | 
						|
    .map(updateId)
 | 
						|
    .filter(({ id, _id }) => ObjectID.isValid(id || _id))
 | 
						|
    .map(updateName)
 | 
						|
    .reduce((challengeMap, challenge) => {
 | 
						|
      const id = challenge.id || challenge._id;
 | 
						|
 | 
						|
      challengeMap[id] = challenge;
 | 
						|
      return challengeMap;
 | 
						|
    }, {})
 | 
						|
    .flatMap(challengeMap => {
 | 
						|
      const updateData = {
 | 
						|
        $set: {
 | 
						|
          challengeMap,
 | 
						|
          isChallengeMapMigrated: true
 | 
						|
        }
 | 
						|
      };
 | 
						|
      return Observable.fromNodeCallback(User.updateAll, User)(
 | 
						|
        { id: userId },
 | 
						|
        updateData,
 | 
						|
        { allowExtendedOperators: true }
 | 
						|
      );
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
export default function migrateCompletedChallenges() {
 | 
						|
  return ({ user, app }, res, next) => {
 | 
						|
    const User = app.models.User;
 | 
						|
    if (!user || user.isChallengeMapMigrated) {
 | 
						|
      return next();
 | 
						|
    }
 | 
						|
    const id = user.id.toString();
 | 
						|
    return User.findOne$({
 | 
						|
      where: { id },
 | 
						|
      fields: { completedChallenges: true }
 | 
						|
    })
 | 
						|
      .map(({ completedChallenges = [] } = {}) => completedChallenges)
 | 
						|
      .flatMap(completedChallenges => {
 | 
						|
        return buildChallengeMap(
 | 
						|
          id,
 | 
						|
          completedChallenges,
 | 
						|
          User
 | 
						|
        );
 | 
						|
      })
 | 
						|
      .subscribe(
 | 
						|
        count => log('documents update', count),
 | 
						|
        // errors go here
 | 
						|
        next,
 | 
						|
        next
 | 
						|
      );
 | 
						|
  };
 | 
						|
}
 |