Skip to content

Commit f71af39

Browse files
committed
feat: implement buy and sell handlers, add keyboard configurations, and enhance message handling in TelegramAdapter
1 parent bf9f514 commit f71af39

File tree

9 files changed

+299
-37
lines changed

9 files changed

+299
-37
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Context } from "grammy";
2+
import { closeKeyboard } from "../controllers/listKeyboard";
3+
4+
export const buyHandler = async (
5+
context: Context,
6+
amount?: number
7+
) => {
8+
if(!amount){
9+
return context.reply("Please enter the amount of the cryptocurrency you want to buy", {
10+
11+
reply_markup: closeKeyboard,
12+
});
13+
}
14+
15+
const message = `You have successfully bought ${amount} of the cryptocurrency`;
16+
return context.reply(message, {
17+
reply_markup: closeKeyboard,
18+
});
19+
20+
21+
};
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Context } from "grammy";
2+
import { CallbackQuery } from "grammy/types";
3+
import {
4+
backKeyboard,
5+
menuKeyboard,
6+
editKeyboard,
7+
settingKeyboard,
8+
walletKeyboard,
9+
} from "./listKeyboard";
10+
import { buyHandler } from "./buy.handler";
11+
import { selHandler } from "./sel.handler";
12+
import { deleteHandler } from "./delete.handler";
13+
import { screenHandler } from "./screen.handler";
14+
import { settingsMessage } from "../utils/messages";
15+
import { BaseBot } from "src/bots/@base";
16+
17+
export const callbackQueryHandler = async (bot: BaseBot, context: Context) => {
18+
try {
19+
if (!context.update.callback_query) {
20+
return;
21+
}
22+
const callbackQuery: CallbackQuery = context.update.callback_query;
23+
24+
const { data, message } = callbackQuery;
25+
26+
if (!message || !message.text || context.chat?.type !== "private") {
27+
return;
28+
}
29+
30+
const messageId = message.message_id;
31+
32+
if (data === "complete") {
33+
await screenHandler(
34+
context,
35+
messageId,
36+
message.text + "Edited",
37+
backKeyboard,
38+
);
39+
await context.answerCallbackQuery();
40+
} else if (data === "delete") {
41+
await deleteHandler(context, messageId);
42+
await context.answerCallbackQuery();
43+
} else if (data === "refresh") {
44+
await context.answerCallbackQuery("Refreshing...");
45+
} else if (data === "edit") {
46+
await screenHandler(context, messageId, "Choose an option", editKeyboard);
47+
await context.answerCallbackQuery;
48+
} else if (data === "back") {
49+
await screenHandler(
50+
context,
51+
messageId,
52+
"Choose a cryptocurrency",
53+
menuKeyboard,
54+
);
55+
await context.answerCallbackQuery();
56+
} else if (data === "close") {
57+
await deleteHandler(context, messageId);
58+
await context.answerCallbackQuery();
59+
} else if (data === "buy_custom") {
60+
await buyHandler(context, 10);
61+
await context.answerCallbackQuery();
62+
} else if (data === "sell_custom") {
63+
await selHandler(context, 10, 10);
64+
await context.answerCallbackQuery();
65+
} else if (data === "settings") {
66+
await screenHandler(context, messageId, settingsMessage, settingKeyboard);
67+
await context.answerCallbackQuery();
68+
} else if (data === "wallet_view") {
69+
await screenHandler(context, messageId, "Wallet", walletKeyboard);
70+
await context.answerCallbackQuery();
71+
}
72+
} catch (error) {}
73+
};
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Context } from "grammy";
2+
3+
export const deleteHandler = async (context: Context, messageId: number) => {
4+
if (!context.chat?.id) {
5+
return;
6+
}
7+
const chatId = context.chat.id;
8+
await context.api.deleteMessage(chatId, messageId);
9+
};
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { InlineKeyboard } from "grammy";
2+
3+
export const menuKeyboard = new InlineKeyboard()
4+
.text("Buy 💰", "buy_custom")
5+
.text("Sell ⚡️", "sell_custom")
6+
.text("Wallet", "wallet_view")
7+
.row()
8+
.text("Payout 📈", "payout_custom")
9+
.text("Edit", "edit")
10+
.row()
11+
.text("Settings", "settings")
12+
.row()
13+
.text("Refresh", "refresh")
14+
.row();
15+
16+
17+
export const editKeyboard = new InlineKeyboard()
18+
.text("Save", "complete")
19+
.text("Delete", "delete")
20+
.text("crypto", "crypto")
21+
.row();
22+
23+
24+
export const backKeyboard = new InlineKeyboard().text("Back", "back");
25+
export const closeKeyboard = new InlineKeyboard().text("Close", "close");
26+
27+
export const settingKeyboard = new InlineKeyboard()
28+
.text("Change Address", "change_address")
29+
.text("Change Security", "change_security")
30+
.row()
31+
.text("Change Currency", "change_currency")
32+
.text("Change Language", "change_language")
33+
.row()
34+
.text("Change Notification", "change_notification")
35+
.text("Change Theme", "change_theme")
36+
.row()
37+
.text("Change Timezone", "change_timezone")
38+
.text("Change Privacy", "change_privacy")
39+
.row()
40+
.text("Change Backup", "change_backup")
41+
.text("Change Delete", "change_delete")
42+
.row()
43+
.text("Back", "back")
44+
.text("Close", "close")
45+
.row();
46+
47+
export const walletKeyboard = new InlineKeyboard()
48+
.text("Deposit", "deposit")
49+
.text("Withdraw", "withdraw")
50+
.row()
51+
.text("History", "history")
52+
.text("Settings", "settings")
53+
.row()
54+
.text("Back", "back")
55+
.text("Close", "close")
56+
.row();
57+
58+
// export const auditInlineKeyboard = (chain: any, address: string) => {
59+
// const auditUrl = `https://gopluslabs.io/token-security/${chain.id}/${address}`
60+
// const scanUrl = `${chain.scan}${address}`
61+
// const swapUrl = `https://app.1inch.io/#/${chain.id}/simple/swap/${chain.coin}/${address}`
62+
// const chartUrl = `https://${
63+
// chain.name === 'BSC' ? 'poocoin.app/tokens' : 'coingecko.com/en/coins'
64+
// }/${address}`
65+
66+
// return new InlineKeyboard()
67+
// .url('Audit', auditUrl)
68+
// .url('Contract', scanUrl)
69+
// .row()
70+
// .url('Buy', swapUrl)
71+
// .url('Chart', chartUrl)
72+
// }
73+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { Context } from "grammy";
2+
import { IMessage, ISender } from "../../types";
3+
import { BaseBot } from "src/bots/@base";
4+
5+
export const messageHandler = async (bot: BaseBot, ctx: Context) => {
6+
if (!bot) {
7+
return;
8+
}
9+
console.log("first messageHandler bot", bot);
10+
if (!ctx.message) {
11+
return;
12+
}
13+
console.log("messageHandler chatId", ctx.message.chat.id);
14+
const sender: ISender = {
15+
id: ctx.message.chat.id.toString(),
16+
name: ctx.message.from.username || ctx.message.from.first_name,
17+
isDirect: true,
18+
};
19+
const message: IMessage = {
20+
chatId: ctx.message.chat.id.toString(), // TODO
21+
text: ctx.message.text || "",
22+
};
23+
if (message.text) {
24+
bot.onMessage(
25+
sender,
26+
message,
27+
(reply: any) => {
28+
ctx.reply(reply, {
29+
parse_mode: "Markdown",
30+
});
31+
32+
return reply;
33+
},
34+
(isTyping: any) => {
35+
if (isTyping) {
36+
ctx.replyWithChatAction("typing");
37+
}
38+
},
39+
);
40+
}
41+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Context } from "grammy";
2+
3+
export const screenHandler = async (
4+
context: Context,
5+
messageId: number,
6+
message: string,
7+
keyboard?: any,
8+
) => {
9+
if (!context.chat?.id) {
10+
return;
11+
}
12+
13+
const chatId = context.chat.id;
14+
await context.api.editMessageText(
15+
chatId,
16+
messageId,
17+
`
18+
👋 Hello, ${context.from?.first_name}
19+
${message}
20+
`,
21+
{
22+
reply_markup: keyboard,
23+
},
24+
);
25+
};
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Context } from "grammy";
2+
import { closeKeyboard } from "../controllers/listKeyboard";
3+
4+
export const selHandler = async (
5+
context: Context,
6+
amount?: number,
7+
percent?: number,
8+
) => {
9+
if (!amount || !percent) {
10+
return context.reply(
11+
"Please enter the amount and the percentage of the cryptocurrency you want to sell",
12+
{
13+
reply_markup: closeKeyboard,
14+
},
15+
);
16+
}
17+
18+
const message = `You have successfully sold ${amount} of the cryptocurrency at ${percent}% profit`;
19+
return context.reply(message, {
20+
reply_markup: closeKeyboard,
21+
});
22+
};

src/adapters/telegram.ts

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import { Bot } from "grammy";
2-
3-
import { IMessage, ISender } from "../types";
1+
import { Bot, Context } from "grammy";
42
import { BaseAdapter } from "./base";
53
import { BaseBot } from "src/bots/@base";
4+
import { messageHandler } from "./controllers/message.handler";
5+
import { callbackQueryHandler } from "./controllers/callback.handler";
6+
import { menuKeyboard } from "./controllers/listKeyboard";
7+
import { welcomeMessage } from "./utils/messages";
68

79
type TelegramAdapterOptions = {
810
token?: string;
@@ -27,7 +29,7 @@ export class TelegramAdapter extends BaseAdapter {
2729
"No access token provided through environment. Please PERMANENTLY store the access token in an the environment variable.",
2830
);
2931
}
30-
32+
3133
this.token = token;
3234
}
3335

@@ -41,47 +43,34 @@ export class TelegramAdapter extends BaseAdapter {
4143
description: command.description,
4244
});
4345
});
46+
4447
this.client.api.setMyCommands(commands);
4548

4649
return this;
4750
}
4851

4952
async init({ autoJoin }: { autoJoin?: boolean } = { autoJoin: true }) {
53+
this.client.command("start", async (ctx, next) => {
54+
// this middleware does not handle deep-links
55+
if (ctx.match) return next();
56+
await ctx.reply(welcomeMessage, {
57+
parse_mode: "HTML",
58+
reply_markup: menuKeyboard,
59+
});
60+
});
61+
62+
this.client.on(
63+
"callback_query:data",
64+
async function onCallbackQuery(ctx: Context) {
65+
// pass the bot instance to the callbackQueryHandler
66+
// const bot = this.bot;
67+
// console.log("first onCallbackQuery bot", bot);
68+
callbackQueryHandler(this.bot, ctx);
69+
},
70+
);
5071

5172
this.client.on("message", async (ctx) => {
52-
console.log("first chatId", ctx.message.chat.id);
53-
const sender: ISender = {
54-
id: ctx.message.chat.id.toString(),
55-
name: ctx.message.from.username || ctx.message.from.first_name,
56-
isDirect: true,
57-
};
58-
const message: IMessage = {
59-
chatId: ctx.message.chat.id.toString(), // TODO
60-
text: ctx.message.text || "",
61-
};
62-
63-
if (!this.bot) {
64-
return;
65-
}
66-
67-
if (message.text) {
68-
this.bot.onMessage(
69-
sender,
70-
message,
71-
(reply) => {
72-
ctx.reply(reply, {
73-
parse_mode: "Markdown",
74-
});
75-
76-
return reply;
77-
},
78-
(isTyping) => {
79-
if (isTyping) {
80-
ctx.replyWithChatAction("typing");
81-
}
82-
},
83-
);
84-
}
73+
messageHandler(this.bot, ctx);
8574
});
8675

8776
this.client.start();

src/adapters/utils/messages.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const welcomeMessage = `
2+
Welcome to the Crypto Bot.
3+
You can use the following commands:
4+
/start - Start the bot
5+
`;
6+
7+
export const settingsMessage = `
8+
⚙️ This is the bot settings menu. To continue, choose the action you want to perform.
9+
`;

0 commit comments

Comments
 (0)