Skip to content

Commit

Permalink
- Collection entry creation now nets users EXP points
Browse files Browse the repository at this point in the history
- Finishing work on activities feed logic
- Learned to never use exceptions with status code 401 unless we want Supertokens to go crazy
  • Loading branch information
Lamarcke committed Apr 19, 2024
1 parent 6f979ad commit 51559e3
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 15 deletions.
2 changes: 1 addition & 1 deletion server_swagger.json

Large diffs are not rendered by default.

12 changes: 10 additions & 2 deletions src/activities/activities-feed/activities-feed.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { Controller, Get, Query, UseInterceptors } from "@nestjs/common";
import {
Controller,
Get,
Query,
UseGuards,
UseInterceptors,
} from "@nestjs/common";
import { ActivitiesFeedService } from "./activities-feed.service";
import { ApiOkResponse, ApiTags } from "@nestjs/swagger";
import { ActivitiesFeedRequestDto } from "./dto/activities-feed-request.dto";
Expand All @@ -9,9 +15,11 @@ import { SessionContainer } from "supertokens-node/recipe/session";
import { CacheInterceptor, CacheTTL } from "@nestjs/cache-manager";
import { minutes } from "@nestjs/throttler";
import { Public } from "../../auth/public.decorator";
import { AuthGuard } from "../../auth/auth.guard";

@ApiTags("activities-feed")
@Controller("activities/feed")
@UseGuards(AuthGuard)
export class ActivitiesFeedController {
constructor(
private readonly activitiesFeedService: ActivitiesFeedService,
Expand All @@ -27,7 +35,7 @@ export class ActivitiesFeedController {
@Public()
async buildActivitiesFeed(
@Query() dto: ActivitiesFeedRequestDto,
@Session() session?: SessionContainer,
@Session() session: SessionContainer | undefined,
) {
return this.activitiesFeedService.buildActivitiesFeed(
session?.getUserId(),
Expand Down
3 changes: 2 additions & 1 deletion src/activities/activities-feed/activities-feed.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export class ActivitiesFeedService {
offset: 0,
limit: 9999999,
});
console.log(followedUsersIds);

const baseFindOptions = buildBaseFindOptions(dto);

Expand All @@ -114,7 +115,7 @@ export class ActivitiesFeedService {
if (userId == undefined) {
throw new HttpException(
"User must be logged-in to see following user activities.",
HttpStatus.UNAUTHORIZED,
HttpStatus.BAD_REQUEST,
);
}
return this.buildFollowingActivitiesFeed(userId, dto);
Expand Down
5 changes: 5 additions & 0 deletions src/activities/activities-queue/activities-queue.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,10 @@ export enum ActivityType {
export class ActivityCreate {
type: ActivityType;
sourceId: string | number;
/**
* Extra sourceId that may be necessary to persist an activity
* e.g. related collection id when inserting a collection entry activity
*/
complementarySourceId?: string | number;
profileUserId: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class ActivitiesRepositoryService {
) {}

async create(dto: ActivityCreate) {
const { type, sourceId, profileUserId } = dto;
const { type, sourceId, complementarySourceId, profileUserId } = dto;

const activity = this.activitiesRepository.create({
type,
Expand All @@ -36,10 +36,16 @@ export class ActivitiesRepositoryService {
case ActivityType.COLLECTION_ENTRY:
if (typeof sourceId !== "string") {
throw new Error(
"Collection Entry activities should have a string sourceId",
"CollectionEntry activities should have a string sourceId",
);
}
if (typeof complementarySourceId !== "string") {
throw new Error(
"A string complementarySourceId must be specified for CollectionEntry activities",
);
}
activity.collectionEntryId = sourceId;
activity.collectionId = complementarySourceId;
break;
case ActivityType.REVIEW:
if (typeof sourceId !== "string") {
Expand Down
12 changes: 11 additions & 1 deletion src/activities/activities-repository/entities/activity.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import { Profile } from "../../../profile/entities/profile.entity";
import { CollectionEntry } from "../../../collections/collections-entries/entities/collection-entry.entity";
import { Review } from "../../../reviews/entities/review.entity";
import { UserFollow } from "../../../follow/entity/user-follow.entity";
import { Collection } from "../../../collections/entities/collection.entity";

@Entity()
@Unique(["profile", "collectionEntry"])
@Unique(["profile", "collectionEntry", "collection"])
@Unique(["profile", "userFollow"])
@Unique(["profile", "review"])
export class Activity {
Expand Down Expand Up @@ -43,6 +44,15 @@ export class Activity {
nullable: true,
})
collectionEntryId: string | null;
@ManyToOne(() => Collection, {
nullable: true,
onDelete: "CASCADE",
})
collection: Collection | null;
@Column({
nullable: true,
})
collectionId: string | null;
@ManyToOne(() => Review, {
nullable: true,
onDelete: "CASCADE",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ export class CollectionsEntriesController {
);
}

@Get(":id")
async findEntryById(@Param("id") collectionEntryId: string) {
return await this.collectionsEntriesService.findOneByIdOrFail(
collectionEntryId,
);
}

/**
* Returns a specific collection entry based on game ID
* @param session
Expand Down Expand Up @@ -76,6 +83,7 @@ export class CollectionsEntriesController {
collectionEntryId,
);
}

@Delete(":id")
@HttpCode(HttpStatus.NO_CONTENT)
async deleteOwnEntry(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import { CollectionsEntriesController } from "./collections-entries.controller";
import { CollectionsEntriesService } from "./collections-entries.service";
import { GamePlatform } from "../../game/game-repository/entities/game-platform.entity";
import { AchievementsModule } from "../../achievements/achievements.module";
import { LevelModule } from "../../level/level.module";

@Module({
imports: [
TypeOrmModule.forFeature([CollectionEntry, GamePlatform]),
ActivitiesQueueModule,
AchievementsModule,
LevelModule,
],
controllers: [CollectionsEntriesController],
providers: [CollectionsEntriesService],
Expand Down
31 changes: 24 additions & 7 deletions src/collections/collections-entries/collections-entries.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { ActivityType } from "../../activities/activities-queue/activities-queue
import { AchievementsQueueService } from "../../achievements/achievements-queue/achievements-queue.service";
import { AchievementCategory } from "../../achievements/achievements.constants";
import { getIconNamesForPlatformAbbreviations } from "../../game/game-repository/game-repository.utils";
import { LevelService } from "../../level/level.service";
import { LevelIncreaseActivities } from "../../level/level.constants";

@Injectable()
export class CollectionsEntriesService {
Expand All @@ -24,6 +26,7 @@ export class CollectionsEntriesService {
private collectionEntriesRepository: Repository<CollectionEntry>,
private activitiesQueueService: ActivitiesQueueService,
private achievementsQueueService: AchievementsQueueService,
private levelService: LevelService,
) {}

async findOneById(id: string) {
Expand Down Expand Up @@ -219,9 +222,13 @@ export class CollectionsEntriesService {
id: id,
}));

const entry = await this.findOneByUserIdAndGameId(userId, gameId);
const possibleExistingEntry = await this.findOneByUserIdAndGameId(
userId,
gameId,
);

const upsertedEntry = await this.collectionEntriesRepository.save({
...entry,
...possibleExistingEntry,
isFavorite,
collections,
game: {
Expand All @@ -230,11 +237,21 @@ export class CollectionsEntriesService {
ownedPlatforms,
});

this.activitiesQueueService.register({
sourceId: upsertedEntry.id,
type: ActivityType.COLLECTION_ENTRY,
profileUserId: userId,
});
if (!possibleExistingEntry) {
this.levelService.registerLevelExpIncreaseActivity(
userId,
LevelIncreaseActivities.COLLECTION_ENTRY_CREATED,
);
}

for (const uniqueCollectionId of uniqueCollectionIds) {
this.activitiesQueueService.register({
sourceId: upsertedEntry.id,
complementarySourceId: uniqueCollectionId,
type: ActivityType.COLLECTION_ENTRY,
profileUserId: userId,
});
}

this.achievementsQueueService.addTrackingJob({
targetUserId: userId,
Expand Down
2 changes: 2 additions & 0 deletions src/level/level.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ export const BASE_LEVEL_UP_COST = 100;
*/
export enum LevelIncreaseActivities {
REVIEW_CREATED = "review_created",
COLLECTION_ENTRY_CREATED = "collection_entry_created",
}

export const LevelActivitiesToIncreaseAmountMap = {
[LevelIncreaseActivities.REVIEW_CREATED]: 50,
[LevelIncreaseActivities.COLLECTION_ENTRY_CREATED]: 15,
};
4 changes: 3 additions & 1 deletion src/level/level.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ export class LevelService {
const activityIncreaseAmount =
LevelActivitiesToIncreaseAmountMap[activity];
if (activityIncreaseAmount == undefined) {
throw new Error("Invalid activity when registering level increase");
throw new Error(
`Invalid activity when registering level increase: '${activity}' not valid.`,
);
}

this.increaseExp(userId, activityIncreaseAmount)
Expand Down

0 comments on commit 51559e3

Please sign in to comment.