Skip to content

Commit

Permalink
feat(be): add get quest detail api
Browse files Browse the repository at this point in the history
  • Loading branch information
harisato committed Oct 19, 2023
1 parent c05bacf commit 83e4f34
Show file tree
Hide file tree
Showing 14 changed files with 299 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
table:
name: user_quest
schema: public
array_relationships:
- name: user_quest_rewards
using:
foreign_key_constraint_on:
column: user_quest_id
table:
name: user_quest_reward
schema: public
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
table:
name: user_quest_reward
schema: public
object_relationships:
- name: user_quest
using:
foreign_key_constraint_on: user_quest_id
11 changes: 11 additions & 0 deletions src/quest/dto/get-campaign-quest.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';

export class GetCampaignQuestParamDto {
@ApiProperty()
quest_id: number;
}

export class GetCampaignQuestRequestDto {
@ApiPropertyOptional()
user_id: string;
}
16 changes: 14 additions & 2 deletions src/quest/quest.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
Body,
Controller,
Get,
Param,
Post,
Query,
UploadedFiles,
Expand All @@ -18,6 +19,10 @@ import { RolesGuard } from '../auth/role.guard';
import { UploadNftImageRequestDto } from './dto/upload-nft-image.dto';
import { QuestService } from './quest.service';
import { GetAllCampaignQuestRequestDto } from './dto/get-all-campaign-quest.dto';
import {
GetCampaignQuestParamDto,
GetCampaignQuestRequestDto,
} from './dto/get-campaign-quest.dto';

@Controller('quest')
@ApiTags('quest')
Expand All @@ -26,8 +31,15 @@ export class QuestController {

@Get()
getAllCampaignQuest(@Query() query: GetAllCampaignQuestRequestDto) {
const userId = query.user_id;
return this.questSvc.getAllCampaignQuest(userId);
return this.questSvc.getAllCampaignQuest(query.user_id);
}

@Get(':quest_id')
getCampaignQuestDetail(
@Param() param: GetCampaignQuestParamDto,
@Query() query: GetCampaignQuestRequestDto
) {
return this.questSvc.get(param.quest_id, query.user_id);
}

@UseGuards(AuthGuard, RolesGuard)
Expand Down
15 changes: 14 additions & 1 deletion src/quest/quest.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,22 @@ import { JwtModule } from '@nestjs/jwt';
import { QuestGraphql } from './quest.graphql';
import { GraphqlModule } from '../graphql/graphql.module';
import { UserModule } from '../user/user.module';
import { RepeatQuestModule } from '../repeat-quests/repeat-quests.module';
import { SocialActivitiesModule } from '../social-activites/social-activities.module';
import { UserQuestModule } from '../user-quests/user-quests.module';
import { SubscribersModule } from '../subscribers/subscribers.module';

@Module({
imports: [FilesModule, JwtModule, GraphqlModule, UserModule],
imports: [
FilesModule,
JwtModule,
GraphqlModule,
UserModule,
RepeatQuestModule,
SocialActivitiesModule,
UserQuestModule,
SubscribersModule,
],
providers: [QuestService, QuestGraphql],
controllers: [QuestController],
exports: [],
Expand Down
86 changes: 81 additions & 5 deletions src/quest/quest.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { Injectable, Logger, NotFoundException } from '@nestjs/common';
import { FilesService } from '../files/files.service';
import { QuestGraphql } from './quest.graphql';
import { UserGraphql } from '../user/user.graphql';
import { SocialActivitiesGraphql } from '../social-activites/social-activities.graphql';
import { SubscribersGraphql } from '../subscribers/subscribers.graphql';
import { UserQuestsGraphql } from '../user-quests/user-quests.graphql';
import { RepeatQuestsGraphql } from '../repeat-quests/repeat-quests.graphql';

@Injectable()
export class QuestService {
Expand All @@ -11,7 +15,11 @@ export class QuestService {
constructor(
private filesService: FilesService,
private questGraphql: QuestGraphql,
private userGraphql: UserGraphql
private socialActivitiesGraphql: SocialActivitiesGraphql,
private subscribersGraphql: SubscribersGraphql,
private userGraphql: UserGraphql,
private userQuestGraphql: UserQuestsGraphql,
private repeatQuestGraphql: RepeatQuestsGraphql
) {}

async get(questId: number, userId?: string) {
Expand All @@ -23,34 +31,102 @@ export class QuestService {

let reward_status = 0;
if (userId) {
reward_status = await this.checkRewardStatus(quest.requirement, userId);
const isClaimed = await this.isClaimed(quest, userId);
if (isClaimed) {
reward_status = 2;
} else {
const canClaimReward = await this.canClaimReward(
quest.requirement,
userId
);

if (canClaimReward) reward_status = 1;
}
}
quest.reward_status = reward_status;

return quest;
}

async isClaimed(quest: any, userId: string): Promise<boolean> {
let queryUserQuestCondition;
// check reward claimed
if (quest.type === 'Once') {
queryUserQuestCondition = {
where: {
quest_id: {
_eq: quest.id,
},
user_id: {
_eq: userId,
},
},
};
} else {
// get latest repeat quest by quest id
const repeatQuest = await this.repeatQuestGraphql.queryRepeatQuest({
quest_id: quest.id,
});

queryUserQuestCondition = {
where: {
repeat_quest_id: {
_eq: repeatQuest.id,
},
user_id: {
_eq: userId,
},
},
};
}

// query user quest
const userQuest = await this.userQuestGraphql.queryUserQuests(
queryUserQuestCondition
);

if (
userQuest?.user_quest_rewards &&
userQuest?.user_quest_rewards !== null
) {
return true;
}
return false;
}

/** Reward status
* 0: Can not claim reward
* 1: Can claim reward
* TODO: 2: Claimed
*/
async checkRewardStatus(requirement: any, userId: string) {
async canClaimReward(requirement: any, userId: string) {
const requirementType = Object.keys(requirement);

if (requirementType.includes('read')) {
// TODO: do something
}

if (requirementType.includes('comment')) {
// do something
const chapterId = requirement.comment.chapter.id;
const result = await this.socialActivitiesGraphql.queryActivities({
chapter_id: chapterId,
user_id: userId,
});

if (result.data.social_activities[0]) return true;
}

if (requirementType.includes('subscribe')) {
// do something
const mangaId = requirement.subscribe.manga.id;
const result = await this.subscribersGraphql.querySubscribers({
manga_id: mangaId,
user_id: userId,
});
if (result.data.subscribers[0]) return true;
}
return 0;

return false;
}

async upload(file: Express.Multer.File) {
Expand Down
30 changes: 30 additions & 0 deletions src/repeat-quests/repeat-quests.graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';

import { GraphqlService } from '../graphql/graphql.service';

@Injectable()
export class RepeatQuestsGraphql {
constructor(
private configSvc: ConfigService,
private graphqlSvc: GraphqlService
) {}

async queryRepeatQuest(variables: any) {
const result = await this.graphqlSvc.query(
this.configSvc.get<string>('graphql.endpoint'),
'',
`query repeat_quests($quest_id: Int!) {
repeat_quests(where: {quest_id: {_eq: $quest_id}}, order_by: {created_at: desc}, limit: 1) {
id
quest_id
created_at
}
}`,
'repeat_quests',
variables
);

return result.data.repeat_quests[0];
}
}
11 changes: 11 additions & 0 deletions src/repeat-quests/repeat-quests.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';

import { GraphqlModule } from '../graphql/graphql.module';
import { RepeatQuestsGraphql } from './repeat-quests.graphql';

@Module({
imports: [GraphqlModule],
providers: [RepeatQuestsGraphql],
exports: [RepeatQuestsGraphql],
})
export class RepeatQuestModule {}
30 changes: 30 additions & 0 deletions src/social-activites/social-activities.graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';

import { GraphqlService } from '../graphql/graphql.service';

@Injectable()
export class SocialActivitiesGraphql {
constructor(
private configSvc: ConfigService,
private graphqlSvc: GraphqlService
) {}

queryActivities(variables: any) {
return this.graphqlSvc.query(
this.configSvc.get<string>('graphql.endpoint'),
'',
`query social_activities($chapter_id: Int!, $user_id: bpchar!) {
social_activities(where: {_and: [{chapter_id: {_eq: $chapter_id}}, {user_id: {_eq: $user_id}}]}) {
id
content
user_id
chapter_id
}
}
`,
'social_activities',
variables
);
}
}
11 changes: 11 additions & 0 deletions src/social-activites/social-activities.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';

import { GraphqlModule } from '../graphql/graphql.module';
import { SocialActivitiesGraphql } from './social-activities.graphql';

@Module({
imports: [GraphqlModule],
providers: [SocialActivitiesGraphql],
exports: [SocialActivitiesGraphql],
})
export class SocialActivitiesModule {}
30 changes: 30 additions & 0 deletions src/subscribers/subscribers.graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';

import { GraphqlService } from '../graphql/graphql.service';

@Injectable()
export class SubscribersGraphql {
constructor(
private configSvc: ConfigService,
private graphqlSvc: GraphqlService
) {}

querySubscribers(variables: any) {
return this.graphqlSvc.query(
this.configSvc.get<string>('graphql.endpoint'),
'',
`query subscribers($user_id: bpchar!, $manga_id: Int!) {
subscribers(where: {manga_id: {_eq: $manga_id}, user_id: {_eq: $user_id}}) {
id
manga_id
created_at
user_id
}
}
`,
'subscribers',
variables
);
}
}
11 changes: 11 additions & 0 deletions src/subscribers/subscribers.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';

import { GraphqlModule } from '../graphql/graphql.module';
import { SubscribersGraphql } from './subscribers.graphql';

@Module({
imports: [GraphqlModule],
providers: [SubscribersGraphql],
exports: [SubscribersGraphql],
})
export class SubscribersModule {}
33 changes: 33 additions & 0 deletions src/user-quests/user-quests.graphql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';

import { GraphqlService } from '../graphql/graphql.service';

@Injectable()
export class UserQuestsGraphql {
constructor(
private configSvc: ConfigService,
private graphqlSvc: GraphqlService
) {}

async queryUserQuests(variables: any) {
const result = await this.graphqlSvc.query(
this.configSvc.get<string>('graphql.endpoint'),
'',
`query user_quest($where: user_quest_bool_exp = {_and: {}}) {
user_quest(where: $where) {
id
user_quest_rewards {
tx_hash
id
created_at
}
}
}`,
'user_quest',
variables
);

return result.data.user_quest[0];
}
}
11 changes: 11 additions & 0 deletions src/user-quests/user-quests.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';

import { GraphqlModule } from '../graphql/graphql.module';
import { UserQuestsGraphql } from './user-quests.graphql';

@Module({
imports: [GraphqlModule],
providers: [UserQuestsGraphql],
exports: [UserQuestsGraphql],
})
export class UserQuestModule {}

0 comments on commit 83e4f34

Please sign in to comment.