Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions server/src/defaults/achievements/achievements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ export const getDefaultAchievementsData = (stagesId: string): AchievementCreateD
name: ACHIEVEMENTS.SONG_REQUEST,
description: "Achievements for song requests in message",
stages: stagesId
},
{
name: ACHIEVEMENTS.BADGES_COUNT,
description: "Achievements for user collected badges count",
stages: stagesId
}
];
};
3 changes: 2 additions & 1 deletion server/src/defaults/achievements/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ export enum ACHIEVEMENTS {
LUL = "LUL",
COMMANDS_COUNT = "COMMANDS",
SONG_REQUEST = "MY MUSIC",
SONG_VOTING = "MY MUSIC TASTE"
SONG_VOTING = "MY MUSIC TASTE",
BADGES_COUNT = "OBTAINED BADGES"
}

//sorry for swearing LUL
Expand Down
19 changes: 11 additions & 8 deletions server/src/models/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Document } from "mongoose";
import { Document, Types } from "mongoose";

interface BaseModel {
_id: string;
Expand All @@ -18,6 +18,7 @@ export interface UserModel extends BaseModel {
twitchName?: string;
twitchCreated?: Date;
follower?: Date;
badges?: Types.ObjectId[] | BadgeModel[];
}

export type UserDocument = UserModel & Document;
Expand Down Expand Up @@ -287,27 +288,29 @@ export interface BadgeModel extends BaseModel {

export type BadgeDocument = BadgeModel & Document;

export interface StageData {
export interface StageData<T = string> {
name: string;
stage: number;
goal: number;
badge: string | BadgeModel;
badge: T;
}

export interface AchievementStageModel extends BaseModel {
export type StageDataWithBadgePopulated = StageData<BadgeModel>;
export interface AchievementStageModel<T = string> extends BaseModel {
name: string;
stageData: StageData[];
stageData: StageData<T>[];
}

export type AchievementStageDocument = AchievementStageModel & Document;

export interface AchievementModel extends BaseModel {
export interface AchievementModel<T = string | BadgeModel> extends BaseModel {
name: string;
description: string;
stages: AchievementStageModel;
stages: AchievementStageModel<T>;
isTime: boolean;
}

export type AchievementWithBadgePopulated = AchievementModel<BadgeModel>;

export type AchievementDocument = AchievementModel & Document;

export interface AchievementUserProgressModel extends BaseModel {
Expand Down
5 changes: 4 additions & 1 deletion server/src/models/userModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ const UserSchema: Schema<UserDocument> = new Schema(
lastSeen: { type: Date, default: Date.now },
points: { type: Number, default: 0 },
watchTime: { type: Number, default: 0 },
messageCount: { type: Number, default: 0 }
messageCount: { type: Number, default: 0 },
badges: {
type: [{ type: Schema.Types.ObjectId, ref: "Badge" }]
}
},
{ timestamps: true }
);
Expand Down
4 changes: 2 additions & 2 deletions server/src/services/achievements/achievementsService.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Achievement, AchievementDocument } from "@models";
import { Achievement, AchievementDocument, AchievementWithBadgePopulated } from "@models";
import { AppError, checkExistResource, handleAppError, logger } from "@utils";
import { FilterQuery, UpdateQuery } from "mongoose";
import {
Expand Down Expand Up @@ -58,7 +58,7 @@ export const getOneAchievement = async (
) => {
const { select = { __v: 0 } } = achievementFindOptions;
try {
const foundAchievement = await Achievement.findOne(filter)
const foundAchievement: AchievementWithBadgePopulated | null = await Achievement.findOne(filter)
.select(select)
.populate({
path: "stages",
Expand Down
5 changes: 2 additions & 3 deletions server/src/services/achievements/achivementUserProgresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import {
AchievementUserProgressDocument,
AchievementUserProgress,
AchievementModel,
AchievementUserProgressModel,
StageData
AchievementUserProgressModel
} from "@models";
import { logger, handleAppError, checkExistResource } from "@utils";
import { FilterQuery, UpdateQuery } from "mongoose";
Expand Down Expand Up @@ -137,7 +136,7 @@ export const updateAchievementUserProgressProgresses = async ({
export const getDataForObtainAchievementEmit = (
data: UpdateAchievementUserProgressProgressesReturnData
): GetDataForObtainAchievementEmitReturnData => {
const newStages: StageData[] = [];
const newStages: GetDataForObtainAchievementEmitReturnData["stages"] = [];

data.nowFinishedStages.forEach((stage) => {
const stageData = data.foundAchievement.stages.stageData.find((innerStage) => innerStage.stage === stage[0]);
Expand Down
12 changes: 9 additions & 3 deletions server/src/services/achievements/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { SortQuery, SelectQuery } from "@services";
import { AchievementModel, AchievementStageModel, AchievementUserProgressModel, StageData } from "@models";
import {
AchievementModel,
AchievementStageModel,
AchievementUserProgressModel,
AchievementWithBadgePopulated,
StageDataWithBadgePopulated
} from "@models";

export interface AchievementsFindOptions<T = AchievementModel> {
select?: SelectQuery<T>;
Expand All @@ -26,13 +32,13 @@ export type AchievementStageCreateData = Pick<AchievementStageModel, "name" | "s
export type AchievementStageUpdateData = Partial<AchievementStageCreateData>;

export type UpdateAchievementUserProgressProgressesReturnData = {
foundAchievement: AchievementModel;
foundAchievement: AchievementWithBadgePopulated;
nowFinishedStages: AchievementUserProgressModel["progresses"];
};

export interface GetDataForObtainAchievementEmitReturnData {
achievementName: string;
stages: StageData[];
stages: StageDataWithBadgePopulated[];
}

export interface UpdateAchievementUserProgressProgressesArgs {
Expand Down
2 changes: 1 addition & 1 deletion server/src/services/users/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ export interface ManyUsersFindOptions extends UserFindOptions {
limit?: number;
}

export type UserCreateData = Omit<UserModel, "_id" | "createdAt" | "updatedAt">;
export type UserCreateData = Omit<UserModel, "_id" | "createdAt" | "updatedAt" | "badges">;

export type UserUpdateData = Partial<UserCreateData>;
13 changes: 12 additions & 1 deletion server/src/services/users/usersService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { UserDocument, User } from "@models";
import { checkExistResource, handleAppError, logger } from "@utils";
import { AppError, checkExistResource, handleAppError, logger } from "@utils";
import { FilterQuery, UpdateQuery } from "mongoose";
import { ManyUsersFindOptions, UserCreateData, UserFindOptions, UserUpdateData } from "./types";

Expand Down Expand Up @@ -171,3 +171,14 @@ export const getFollowersCount = async (startDate?: Date, endDate?: Date) => {
handleAppError(err);
}
};

export const addBadgesToUser = async (filter: FilterQuery<UserDocument>, badgesToAdd: string[]) => {
const updatedUser = await updateUser(filter, { $push: { badges: badgesToAdd } });

if (!updatedUser) {
logger.error(`User not updated in - addBadgesTouser filter: ${filter}`);
return { badgesCount: 0 };
}

return { badgesCount: updatedUser.badges?.length || 0 };
};
4 changes: 2 additions & 2 deletions server/src/socketIO/types/dataTypes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { StageData, UserModel } from "@models";
import { StageDataWithBadgePopulated, UserModel } from "@models";

export interface AudioDataRequester {
id: string;
Expand Down Expand Up @@ -83,6 +83,6 @@ export interface RewardData {

export interface ObtainAchievementData {
achievementName: string;
stage: StageData;
stage: StageDataWithBadgePopulated;
username: string;
}
39 changes: 37 additions & 2 deletions server/src/stream/AchievementsHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ import {
updateAchievementUserProgressProgresses,
UpdateAchievementUserProgressProgressesReturnData,
GetDataForObtainAchievementEmitReturnData,
UpdateAchievementUserProgressProgressesArgs
UpdateAchievementUserProgressProgressesArgs,
addBadgesToUser
} from "@services";
import { ACHIEVEMENTS, POLISH_SWEARING } from "@defaults";
import { achievementsLogger } from "@utils";
Expand Down Expand Up @@ -40,6 +41,18 @@ interface CheckGlobalUserDetailsDateArgs extends Omit<CheckGlobalUserDetailsArgs
}

type IncrementCommandAchievementsArgs = Pick<CheckMessageForAchievement, "userId" | "username">;

interface CheckBadgesLogicForUserArgs {
userId: string;
username: string;
stages: GetDataForObtainAchievementEmitReturnData["stages"];
}

interface ManageObtainAchievementDataArgs extends GetDataForObtainAchievementEmitReturnData {
userId: string;
username: string;
}

class AchievementsHandler extends QueueHandler<ObtainAchievementData> {
private socketIO: Server<ClientToServerEvents, ServerToClientEvents, InterServerEvents, SocketData>;
constructor(socketIO: Server<ClientToServerEvents, ServerToClientEvents, InterServerEvents, SocketData>) {
Expand Down Expand Up @@ -78,13 +91,31 @@ class AchievementsHandler extends QueueHandler<ObtainAchievementData> {

const modifiedUpdateData = this.convertUpdateDataToObtainAchievementData(updateData);

this.addObtainedAchievementDataToQueue(modifiedUpdateData, username);
if (modifiedUpdateData.stages.length > 0)
await this.manageObtainAchievementData({ userId: rest.userId, username, ...modifiedUpdateData });
}

private async manageObtainAchievementData({ username, ...rest }: ManageObtainAchievementDataArgs) {
await this.addBadgesToUser({
userId: rest.userId,
username: username,
stages: rest.stages
});
this.addObtainedAchievementDataToQueue(rest, username);
}

private addObtainedAchievementDataToQueue(data: GetDataForObtainAchievementEmitReturnData, username: string) {
data.stages.forEach((stage) => this.enqueue({ achievementName: data.achievementName, stage, username }));
}

private async addBadgesToUser({ userId, stages }: CheckBadgesLogicForUserArgs) {
const badges = stages.map((stage) => stage.badge._id);

const badgesInfo = await addBadgesToUser({ _id: userId }, badges);

return badgesInfo;
}

private emitObtainAchievement({ achievementName, stage, username }: ObtainAchievementData) {
this.socketIO.emit("obtainAchievement", { achievementName: achievementName, stage, username });
}
Expand Down Expand Up @@ -146,6 +177,10 @@ class AchievementsHandler extends QueueHandler<ObtainAchievementData> {
await this.updateAchievementUserProgressAndAddToQueue({ achievementName: ACHIEVEMENTS.POINTS, ...args });
}

public async checkUserBadgesCountForAchievement(args: CheckGlobalUserDetailsArgs) {
await this.updateAchievementUserProgressAndAddToQueue({ achievementName: ACHIEVEMENTS.BADGES_COUNT, ...args });
}

public async checkUserFollowageForAchievement({ dateProgress, ...rest }: CheckGlobalUserDetailsDateArgs) {
const daysFollow = moment().diff(moment(dateProgress), "seconds");
await this.updateAchievementUserProgressAndAddToQueue({
Expand Down
12 changes: 9 additions & 3 deletions server/src/stream/LoyaltyHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,18 @@ class LoyaltyHandler extends HeadHandler {
progress: { value: foundUser.points || 0 }
});

if (!foundUser.follower) return;
if (foundUser.follower) {
await this.achievementsHandler.checkUserFollowageForAchievement({
userId: foundUser._id,
username: foundUser.username,
dateProgress: foundUser.follower
});
}

await this.achievementsHandler.checkUserFollowageForAchievement({
await this.achievementsHandler.checkUserBadgesCountForAchievement({
userId: foundUser._id,
username: foundUser.username,
dateProgress: foundUser.follower
progress: { value: foundUser.badges?.length || 0 }
});
}
}
Expand Down