Skip to content

Commit

Permalink
chore: format and wallet command
Browse files Browse the repository at this point in the history
  • Loading branch information
Keyrxng committed Oct 4, 2024
1 parent ea6e4bc commit c55f9e5
Show file tree
Hide file tree
Showing 14 changed files with 168 additions and 95 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,4 @@
"@commitlint/config-conventional"
]
}
}
}
8 changes: 4 additions & 4 deletions src/adapters/github/storage-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import {
StorageTypes,
UserBaseStorage,
SessionStorage,
Withsha
Withsha,
} from "../../types/github-storage";

/**
* Uses GitHub as a storage layer, in particular, a JSON
* based private repository. TODO: confirm repo location.
* based private repository.
*/
export class GithubStorage {
octokit: Octokit;
Expand Down Expand Up @@ -159,7 +159,7 @@ export class GithubStorage {
* "delete" will remove the session, this will break things without a new session.
*/
async handleSession<TAction extends "create" | "delete">(session: string, action: TAction) {
const dbObject = await this.retrieveStorageDataObject("session");
const dbObject = await this.retrieveStorageDataObject("session", true);

if (action === "create") {
dbObject.session = session;
Expand Down Expand Up @@ -292,7 +292,7 @@ export class GithubStorage {

try {
parsedData = JSON.parse(content);
} catch (e) {
} catch {
throw new Error("Failed to parse JSON data");
}

Expand Down
17 changes: 10 additions & 7 deletions src/bot/features/commands/private-chat/notify-subscribe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const composer = new Composer<GrammyContext>();
const feature = composer.chatType("private");

feature.command("subscribe", logHandle("command-notifySubscribe"), chatAction("typing"), async (ctx) => {
const user = ctx.adapters.github.retrieveUserByTelegramId(ctx.from?.id);
const user = await ctx.adapters.github.retrieveUserByTelegramId(ctx.from?.id);

if (!user) {
await ctx.reply("You are not registered. Please register first.");
Expand Down Expand Up @@ -37,7 +37,8 @@ feature.callbackQuery(/^notifySubscribe:(\d+)/, logHandle("callback-notifySubscr
}

const selected = ctx.match[1];
const trigger = Object.keys(notifyTriggers).find((_, index) => index === parseInt(selected));

const trigger = Object.keys(notifyTriggers).find((a, index) => index === parseInt(selected));

if (!trigger) {
await ctx.reply("Invalid trigger selected.");
Expand All @@ -49,8 +50,8 @@ feature.callbackQuery(/^notifySubscribe:(\d+)/, logHandle("callback-notifySubscr
user.listeningTo.push(trigger);

try {
await ctx.adapters.github.handleUserBank(user, "update");
} catch (er) {
await ctx.adapters.github.handleUserBaseStorage(user, "update");
} catch {
await ctx.reply("An error occurred while updating your subscription.");
}
});
Expand Down Expand Up @@ -84,7 +85,9 @@ feature.callbackQuery(/^notifyUnsubscribe:(\d+)/, logHandle("callback-notifyUnsu
}

const selected = ctx.match[1];
const trigger = user.listeningTo.find((_, index) => index === parseInt(selected));
// - ignoring "_" in this case

const trigger = user.listeningTo.find((a, index) => index === parseInt(selected));
if (!trigger) {
await ctx.reply("Invalid trigger selected.");
return;
Expand All @@ -95,8 +98,8 @@ feature.callbackQuery(/^notifyUnsubscribe:(\d+)/, logHandle("callback-notifyUnsu
user.listeningTo = user.listeningTo.filter((part) => part !== trigger);

try {
await ctx.adapters.github.handleUserBank(user, "update");
} catch (er) {
await ctx.adapters.github.handleUserBaseStorage(user, "update");
} catch {
await ctx.reply("An error occurred while updating your subscription.");
}
});
Expand Down
14 changes: 7 additions & 7 deletions src/bot/features/commands/private-chat/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ feature.command("register", logHandle("command-register"), chatAction("typing"),
}

try {
await ctx.adapters.github.handleUserBank(
await ctx.adapters.github.handleUserBaseStorage(
{
additionalUserListeners: [],
githubId,
walletAddress: null,
telegramId: userId,
githubUsername,
listeningTo: [],
Expand All @@ -67,13 +68,12 @@ feature.command("register", logHandle("command-register"), chatAction("typing"),
return;
}

await ctx
.reply(`Successfully paired your GitHub account.\n\n${parts.join("\n")}\n\nYou can now use the <b>/subscribe</b> command to subscribe to notifications.`, {
await ctx.reply(
`Successfully paired your GitHub account.\n\n${parts.join("\n")}\n\nYou can now use the <b>/subscribe</b> command to subscribe to notifications.`,
{
parse_mode: "HTML",
})
.catch((er) => {
ctx.logger.error(er.message, { er, userId, githubId }).logMessage.raw;
});
}
);
});

export { composer as registerFeature };
44 changes: 44 additions & 0 deletions src/bot/features/commands/private-chat/wallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { chatAction } from "@grammyjs/auto-chat-action";
import { Composer } from "grammy";
import { GrammyContext } from "../../../helpers/grammy-context";
import { logHandle } from "../../../helpers/logging";

const composer = new Composer<GrammyContext>();

const feature = composer.chatType("private");

/**
* Pairs the user's Telegram ID with the user's GitHub ID.
*/
feature.command("wallet", logHandle("command-wallet"), chatAction("typing"), async (ctx) => {
const userId = ctx.from?.id;
const walletAddress = ctx.message?.text?.split(" ")[1];

const user = await ctx.adapters.github.retrieveUserByTelegramId(userId);

if (!user) {
await ctx.reply("You are not registered. Please register first.");
return;
}

try {
await ctx.adapters.github.handleUserBaseStorage(
{
...user,
walletAddress,
},
"update"
);
} catch (er) {
if (er instanceof Error) {
await ctx.reply(ctx.logger.error(`${er.message}`, { er, userId, walletAddress }).logMessage.raw);
return;
}
await ctx.reply("An error occurred while trying to register your wallet.");
return;
}

await ctx.reply(`Your wallet address has been successfully registered.`);
});

export { composer as walletFeature };
4 changes: 4 additions & 0 deletions src/bot/handlers/commands/setcommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ function getPrivateChatCommands(): BotCommand[] {
command: "unsubscribe",
description: "Unsubscribe from selected notifications",
},
{
command: "wallet",
description: "Register your wallet address",
},
];
}

Expand Down
6 changes: 4 additions & 2 deletions src/bot/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { welcomeFeature } from "./features/welcome";
import { unhandledFeature } from "./features/helpers/unhandled";
import { registerFeature } from "./features/commands/private-chat/register";
import { notifySubscribeFeature } from "./features/commands/private-chat/notify-subscribe";
import { walletFeature } from "./features/commands/private-chat/wallet";

interface Dependencies {
config: UbiquityOsContext["env"];
Expand Down Expand Up @@ -66,8 +67,9 @@ export function createBot(token: string, dependencies: Dependencies, options: Op
protectedBot.use(botIdFeature);

// Private chat commands
protectedBot.use(registerFeature); // /register 0x4007
protectedBot.use(notifySubscribeFeature); // /subscribe ... TODO:
protectedBot.use(registerFeature); // /register <GitHub username>
protectedBot.use(notifySubscribeFeature); // /subscribe
protectedBot.use(walletFeature); // /wallet <wallet address>

// group commands
protectedBot.use(banCommand);
Expand Down
28 changes: 20 additions & 8 deletions src/bot/mtproto-api/bot/scripts/sms-auth/auth-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class AuthHandler {
TELEGRAM_API_HASH: string | null;
TELEGRAM_APP_ID: number;
TELEGRAM_BOT_TOKEN: string | null;
}
};

constructor() {
const env = process.env.TELEGRAM_BOT_ENV;
Expand Down Expand Up @@ -81,10 +81,22 @@ export class AuthHandler {
* The session data will be saved to Supabase for future use.
*/
async smsLogin() {
const env = process.env.TELEGRAM_BOT_ENV;
if (!env) {
throw new Error("Have you ran the setup script? Try running 'yarn setup-env' first.");
}

const key = process.env.REPO_ADMIN_ACCESS_TOKEN;

if (!key) {
throw new Error("Missing Github PAT token.");
}

this._github = new GithubStorage(new Octokit({ auth: key }));

const mtProto = new BaseMtProto();
// empty string as it's a new session


if (this._env.TELEGRAM_API_HASH === null) {
throw new Error("Missing required environment variables for Telegram API");
}
Expand All @@ -101,12 +113,12 @@ export class AuthHandler {
TELEGRAM_API_HASH: this._env.TELEGRAM_API_HASH,
TELEGRAM_APP_ID: this._env.TELEGRAM_APP_ID,
TELEGRAM_BOT_TOKEN: this._env.TELEGRAM_BOT_TOKEN,
}
};

await mtProto.initialize(envObj, null);
await mtProto.initialize(envObj);
try {
await mtProto.client?.start({
phoneNumber: async () => await input.text("Enter your phone number:"),
phoneNumber: async () => await input.password("Enter your phone number:"),
password: async () => await input.password("Enter your password if required:"),
phoneCode: async () => await input.text("Enter the code you received:"),
onError: (err: unknown) => console.error("Error during login:", { err }),
Expand All @@ -116,10 +128,10 @@ export class AuthHandler {
throw new Error("Failed to get session data.");
}

const data = await this._github?.handleSession(mtProto.session.save(), "create");
const didSave = await this._github.handleSession(mtProto.session.save(), "create");

if (data === false) {
throw new Error("Failed to save session data to Supabase.");
if (!didSave) {
throw new Error("Failed to save session data to GitHub.");
}

logger.ok("Successfully logged in and saved session data. You can now run the bot.");
Expand Down
7 changes: 4 additions & 3 deletions src/bot/mtproto-api/bot/scripts/sms-auth/base-mtproto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ export class BaseMtProto {
_api: typeof Api = Api;
_session: StringSession | null = null;

async initialize(env: Context["env"]["TELEGRAM_BOT_ENV"]["mtProtoSettings"], session: string | null) {
async initialize(env: Context["env"]["TELEGRAM_BOT_ENV"]["mtProtoSettings"], session?: string) {
this._api = Api;
this._session = new StringSession(session ?? ""); // Empty String Required.
this._session = new StringSession(session);
this._client = await this._mtProtoInit(env, this._session);
}

Expand All @@ -45,7 +45,8 @@ export class BaseMtProto {
const clientParams: TelegramClientParams = {
connectionRetries: 5,
};
const client = new TelegramClient(session, TELEGRAM_APP_ID, TELEGRAM_API_HASH, clientParams);

const client = new TelegramClient(session ?? "", TELEGRAM_APP_ID, TELEGRAM_API_HASH, clientParams);
await client.connect();
return client;
}
Expand Down
70 changes: 39 additions & 31 deletions src/bot/mtproto-api/bot/scripts/sms-auth/setup-env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,37 +131,7 @@ class SetUpHandler {
const questions = step.questions;

for (const question of questions) {
answers[step.title] ??= {};

// Skip these as they are already set
if (question.name === "TELEGRAM_BOT_REPOSITORY_FULL_NAME" && this.hasSetRepository) {
answers[step.title][question.name] = process.env.TELEGRAM_BOT_REPOSITORY_FULL_NAME as string;
continue;
}
if (question.name === "REPO_ADMIN_ACCESS_TOKEN" && (await this.testAccessToken())) {
answers[step.title][question.name] = process.env.REPO_ADMIN_ACCESS_TOKEN as string;
continue;
}

console.log(step.title);

const passwords = ["TELEGRAM_BOT_WEBHOOK_SECRET", "REPO_ADMIN_ACCESS_TOKEN", "TELEGRAM_API_HASH", "TELEGRAM_BOT_TOKEN", "TELEGRAM_APP_ID"];
let answer;

if (passwords.includes(question.name)) {
answer = await input.password(` ${question.message}\n> `);
} else {
answer = await input.text(` ${question.message}\n> `);
}

await this.handleFirstTwo(question, answer);

if (question.name === "TELEGRAM_BOT_ADMINS") {
answers[step.title][question.name] = JSON.stringify(answer.split(",").map((id: string) => Number(id)));
continue;
}

answers[step.title][question.name] = answer;
await this.handleQuestions(answers, step, question);
}
}
console.clear();
Expand All @@ -185,6 +155,44 @@ class SetUpHandler {
await this.validateEnv();
}

async handleQuestions(
answers: Record<string, Record<string, string>>,
step: { title: string; questions: { type: string; name: string; message: string }[] },
question: { name: string; message: string }
) {
answers[step.title] ??= {};

// Skip these as they are already set
if (question.name === "TELEGRAM_BOT_REPOSITORY_FULL_NAME" && this.hasSetRepository) {
answers[step.title][question.name] = process.env.TELEGRAM_BOT_REPOSITORY_FULL_NAME as string;
return;
}
if (question.name === "REPO_ADMIN_ACCESS_TOKEN" && (await this.testAccessToken())) {
answers[step.title][question.name] = process.env.REPO_ADMIN_ACCESS_TOKEN as string;
return;
}

console.log(step.title);

const passwords = ["TELEGRAM_BOT_WEBHOOK_SECRET", "REPO_ADMIN_ACCESS_TOKEN", "TELEGRAM_API_HASH", "TELEGRAM_BOT_TOKEN", "TELEGRAM_APP_ID"];
let answer;

if (passwords.includes(question.name)) {
answer = await input.password(` ${question.message}\n> `);
} else {
answer = await input.text(` ${question.message}\n> `);
}

await this.handleFirstTwo(question, answer);

if (question.name === "TELEGRAM_BOT_ADMINS") {
answers[step.title][question.name] = JSON.stringify(answer.split(",").map((id: string) => Number(id)));
return;
}

answers[step.title][question.name] = answer;
}

async validateEnv() {
const env = this.env.TELEGRAM_BOT_ENV;
const { botSettings, mtProtoSettings } = env;
Expand Down
4 changes: 2 additions & 2 deletions src/bot/mtproto-api/bot/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ import { GithubStorage } from "../../../adapters/github/storage-layer";
export class GithubSession extends StringSession {
github: GithubStorage;
context: Context;
session?: string
session?: string;

constructor(github: GithubStorage, context: Context, session?: string) {
super(session);
this.github = github;
this.context = context;
this.session = session
this.session = session;
}

async saveSession(): Promise<void> {
Expand Down
Loading

0 comments on commit c55f9e5

Please sign in to comment.