Skip to content

Commit

Permalink
Merge pull request #76 from gavrylenkoIvan/dev
Browse files Browse the repository at this point in the history
Add preview steps to register and send-message wizard
  • Loading branch information
havrydotdev authored Dec 16, 2023
2 parents c7917c4 + abb7f2e commit 27d1100
Show file tree
Hide file tree
Showing 24 changed files with 481 additions and 107 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/nodejs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ name: Node.js CI
# This example workflow assumes that the default branch for your repository is `main`. If the default branch has a different name, edit this example and add your repository's default branch.
on:
push:
branches: [master]
branches: [master, dev]
pull_request:
branches: [master]

Expand Down
16 changes: 12 additions & 4 deletions src/controllers/updates/app.update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import { ReportUseCases } from 'src/use-cases/report';
import { deunionize } from 'telegraf';
import { InlineQueryResult } from 'telegraf/typings/core/types/typegram';

// TODO: add release notes command
@Update()
export class AppUpdate {
constructor(
Expand Down Expand Up @@ -121,9 +120,18 @@ export class AppUpdate {
await ctx.scene.enter(PROFILES_WIZARD_ID);
}

// TODO
// @Action(/reporter-info-*/)
// async onReporterInfo(@Ctx() ctx: MessageContext): Promise<HandlerResponse> {}
@Action(/reporter-info-*/)
async onReporterInfo(@Ctx() ctx: MessageContext): Promise<HandlerResponse> {
const userId = parseInt(
deunionize(ctx.callbackQuery).data.replace('sen-', ''),
);

const profile = await this.profileUseCases.findByUser(userId);

await ctx.replyWithPhoto(profile.fileId, {
caption: getCaption(profile),
});
}

@Roles(['admin'])
@Command('send_message')
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/wizards/clear-last.wizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ export class ClearLastProfilesWizard {
];
}

@WizardStep(2)
@On('text')
@WizardStep(2)
async onAnswer(
@Context() ctx: MessageContext,
@Message() msg: { text: string },
Expand Down
1 change: 1 addition & 0 deletions src/controllers/wizards/profiles.wizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export class ProfilesWizard {
);

const caption = getCaption(current);

await ctx.replyWithPhoto(current.fileId, {
caption,
reply_markup,
Expand Down
130 changes: 96 additions & 34 deletions src/controllers/wizards/register.wizard.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,32 @@
/* eslint-disable perfectionist/sort-classes */
import { SkipThrottle } from '@nestjs/throttler';
import { Ctx, Message, On, Wizard, WizardStep } from 'nestjs-telegraf';
import { Ctx, Hears, Message, On, Wizard, WizardStep } from 'nestjs-telegraf';
import {
CANCEL_CALLBACK,
CONFIRM_CALLBACK,
DONT_CHANGE_CALLBACK,
Keyboards,
NEXT_WIZARD_ID,
REGISTER_WIZARD_ID,
} from 'src/core/constants';
import { ReqUser } from 'src/core/decorators';
import { CreateProfileDto } from 'src/core/dtos';
import { Profile, User } from 'src/core/entities';
import { User } from 'src/core/entities';
import { BotException } from 'src/core/errors';
import { AboutPipe, AgePipe, GamePipe } from 'src/core/pipes';
import { getNameMarkup } from 'src/core/utils';
import { AboutPipe, AgePipe, GameExistPipe } from 'src/core/pipes';
import { getCaption, getDontChangeMarkup } from 'src/core/utils';
import {
GameExistMessage,
HandlerResponse,
KeywordMessage,
MsgWithExtra,
PhotoMessage,
RegisterWizardContext,
TextMessage,
} from 'src/types/telegraf';
import { ProfileUseCases } from 'src/use-cases/profile';
import { ReplyUseCases } from 'src/use-cases/reply';

// TODO: add confirm step
// TODO: add "do not change" button for each step
@SkipThrottle()
@Wizard(REGISTER_WIZARD_ID)
export class RegisterWizard {
Expand All @@ -34,23 +38,24 @@ export class RegisterWizard {
@WizardStep(1)
async onEnter(
@Ctx() ctx: RegisterWizardContext,
@ReqUser() profile: Profile,
@ReqUser() user: User,
): Promise<HandlerResponse> {
console.log({ ctx });
ctx.wizard.next();

ctx.wizard.state.games = [];

const resp: MsgWithExtra[] = [];

if (!profile) {
if (!user.profile) {
resp.push(['messages.user.new', {}]);
}

resp.push([
'messages.name.send',
{
reply_markup: getNameMarkup(ctx.from.first_name),
reply_markup: getDontChangeMarkup(
user.profile ? user.profile.name : ctx.from.first_name,
),
},
]);

Expand All @@ -62,6 +67,7 @@ export class RegisterWizard {
async onName(
@Ctx() ctx: RegisterWizardContext,
@Message() msg: { text: string },
@ReqUser() user: User,
): Promise<HandlerResponse> {
ctx.wizard.state.name = msg.text;

Expand All @@ -70,7 +76,9 @@ export class RegisterWizard {
return [
'messages.age.send',
{
reply_markup: Keyboards.remove,
reply_markup: user.profile
? getDontChangeMarkup(user.profile.age.toString())
: Keyboards.remove,
},
];
}
Expand All @@ -80,19 +88,28 @@ export class RegisterWizard {
async onAge(
@Ctx() ctx: RegisterWizardContext,
@Message(AgePipe) msg: { text: number },
@ReqUser() user: User,
): Promise<HandlerResponse> {
ctx.wizard.state['age'] = msg.text;

ctx.wizard.next();

return 'messages.about.send';
return [
'messages.about.send',
{
reply_markup: user.profile
? getDontChangeMarkup(user.profile.about)
: Keyboards.remove,
},
];
}

@On('text')
@WizardStep(4)
async onAbout(
@Ctx() ctx: RegisterWizardContext,
@Message(AboutPipe) msg: { text: string },
@ReqUser() user: User,
): Promise<HandlerResponse> {
const about = msg.text;

Expand All @@ -101,12 +118,13 @@ export class RegisterWizard {
ctx.wizard.next();

return [
'messages.game.send',
user.profile ? 'messages.game.send_existing' : 'messages.game.send',
{
i18nArgs: {
callback: DONT_CHANGE_CALLBACK,
username: ctx.me,
},
reply_markup: Keyboards.games,
reply_markup: user.profile ? Keyboards.gamesWithSkip : Keyboards.games,
},
];
}
Expand All @@ -115,42 +133,68 @@ export class RegisterWizard {
@WizardStep(5)
async onGame(
@Ctx() ctx: RegisterWizardContext,
@Message(GamePipe) msg: { gameId: number; text: string },
@Message(
GameExistPipe({
allow: [CONFIRM_CALLBACK, DONT_CHANGE_CALLBACK],
}),
)
msg: GameExistMessage | KeywordMessage,
@ReqUser() user: User,
): Promise<HandlerResponse> {
if (msg.text === '✅') {
if ((msg as KeywordMessage).keyword) {
if (user.profile && msg.text === DONT_CHANGE_CALLBACK) {
ctx.wizard.state.games = user.profile.games.map((game) => game.id);
}

if (ctx.wizard.state.games.length === 0) {
throw new BotException('errors.unknown');
}

ctx.wizard.next();

return [
'messages.picture.send',
user.profile
? 'messages.picture.send_existing'
: 'messages.picture.send',
{
reply_markup: Keyboards.remove,
i18nArgs: {
callback: DONT_CHANGE_CALLBACK,
},
reply_markup: user.profile
? getDontChangeMarkup(DONT_CHANGE_CALLBACK)
: Keyboards.remove,
},
];
}

if (ctx.wizard.state.games.includes(msg.gameId)) {
const gameMsg = msg as GameExistMessage;

if (ctx.wizard.state.games.includes(gameMsg.gameId)) {
throw new BotException('messages.game.already_added');
}

ctx.wizard.state.games.push(msg.gameId);
if (ctx.wizard.state.games.length === 10) {
throw new BotException('messages.game.maximum_added');
}

ctx.wizard.state.games.push(gameMsg.gameId);

return 'messages.game.ok';
}

@On('photo')
@On('message')
@WizardStep(6)
async onPhoto(
@Ctx()
ctx: RegisterWizardContext,
@Message() msg: PhotoMessage,
@Message()
msg: PhotoMessage | TextMessage,
@ReqUser() user: User,
): Promise<HandlerResponse> {
console.log({ user });
const fileId = msg.photo.pop().file_id;
const fileId =
user.profile && (msg as TextMessage).text === DONT_CHANGE_CALLBACK
? user.profile.fileId
: (msg as PhotoMessage).photo.pop().file_id;

const profileDto: CreateProfileDto = {
about: ctx.wizard.state.about,
Expand All @@ -161,20 +205,38 @@ export class RegisterWizard {
userId: ctx.from.id,
};

if (user.profile) {
await this.profileUseCases.update(user.profile.id, profileDto);
const profile = user.profile
? await this.profileUseCases.update(user.profile.id, profileDto)
: await this.profileUseCases.create(profileDto);

await ctx.scene.enter(NEXT_WIZARD_ID);
await this.replyUseCases.replyI18n(ctx, 'messages.profile.ready');

return;
}

await this.profileUseCases.create(profileDto);
await ctx.replyWithPhoto(user.profile.fileId, {
caption: getCaption(profile),
});

await this.replyUseCases.replyI18n(ctx, 'messages.register.completed');
await this.replyUseCases.replyI18n(ctx, 'messages.profile.refill', {
reply_markup: Keyboards.refill,
});

await ctx.scene.enter(NEXT_WIZARD_ID);
ctx.wizard.next();
}

return;
@Hears([CONFIRM_CALLBACK, CANCEL_CALLBACK])
@WizardStep(7)
async onAnswer(
@Ctx()
ctx: RegisterWizardContext,
@Message() msg: TextMessage,
): Promise<HandlerResponse> {
switch (msg.text) {
case CONFIRM_CALLBACK:
await ctx.scene.reenter();
break;

case CANCEL_CALLBACK:
await ctx.scene.enter(NEXT_WIZARD_ID);
break;
}
}
}
Loading

1 comment on commit 27d1100

@vercel
Copy link

@vercel vercel bot commented on 27d1100 Dec 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.