Skip to content

Commit

Permalink
Merge pull request #310 from Teri-anric/feat/add_telegram_subscriptio…
Browse files Browse the repository at this point in the history
…n_link

 [Backend] add Telegram subscription link
  • Loading branch information
djeck1432 authored Dec 1, 2024
2 parents ab6a2d2 + 8a33b8a commit 852e11e
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 40 deletions.
13 changes: 10 additions & 3 deletions frontend/src/hooks/useTelegramNotification.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import { useMutation } from "@tanstack/react-query";
import { subscribeToNotification } from "services/telegram";
import { subscribeToNotification, generateTelegramLink } from "services/telegram";
import { notifyError, notifySuccess } from "utils/notification";

const useTelegramNotification = () => {
const mutation = useMutation({
mutationFn: ({ telegramId, walletId }) =>
subscribeToNotification(telegramId, walletId),
mutationFn: async ({ telegramId, walletId }) => {
if (!telegramId) {
// Get subscription link from backend
const { subscription_link } = await generateTelegramLink(walletId);
window.open(subscription_link, '_blank');
return;
}
return await subscribeToNotification(telegramId, walletId);
},
onSuccess: () => {
notifySuccess("Subscribed to notifications successfully!");
},
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/services/telegram.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,16 @@ export const subscribeToNotification = async (telegram_id, wallet_id) => {
console.error("Error subscribing to notifications:", error);
throw error;
}
}

export const generateTelegramLink = async (wallet_id) => {
try {
const response = await axiosInstance.post("/api/generate-telegram-link", {
wallet_id: wallet_id,
});
return response.data;
} catch (error) {
console.error("Error generating Telegram link:", error);
throw error;
}
}
30 changes: 29 additions & 1 deletion web_app/api/telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,48 @@

from aiogram.types import Update
from aiogram.utils.web_app import check_webapp_signature
from aiogram.utils.deep_linking import create_start_link
from fastapi import APIRouter, HTTPException, Request
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from web_app.api.serializers.telegram import TelegramUserAuth, TelegramUserCreate
from web_app.db.crud import DBConnector, TelegramUserDBConnector
from web_app.db.crud import DBConnector, TelegramUserDBConnector, UserDBConnector
from web_app.telegram import TELEGRAM_TOKEN, bot, dp
from web_app.telegram.utils import build_response_writer, check_telegram_authorization

# Create a FastAPI router for handling Telegram webhook requests
router = APIRouter()
db_connector = DBConnector()
user_db = UserDBConnector()
telegram_user_db_connector = TelegramUserDBConnector()



@router.get(
"/api/generate-telegram-link",
tags=["Telegram Operations"],
summary="Generate a Telegram subscription link",
)
async def generate_telegram_link(wallet_id: str):
"""
Generate a Telegram subscription link for a user by wallet ID.
Args:
wallet_id (str): The wallet ID of the user
Returns:
dict: Contains the generated subscription link
"""
if not wallet_id:
raise HTTPException(status_code=400, detail="Wallet ID is required")

user = user_db.get_user_by_wallet_id(wallet_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")

subscription_link = create_start_link(bot, user.id, encode=True)
return {"subscription_link": subscription_link}

@router.get(
"/api/webhook/telegram",
tags=["Telegram Operations"],
Expand Down
40 changes: 6 additions & 34 deletions web_app/db/crud/telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,42 +87,14 @@ def delete_telegram_user(self, telegram_id: str) -> None:
if user:
self.delete_object_by_id(user, user.id)

def set_notification_allowed(
self, telegram_id: str = None, wallet_id: str = None
) -> TelegramUser:
def set_allow_notification(self, telegram_id: int, wallet_id: str) -> bool:
"""
Toggles or sets is_allowed_notification for a TelegramUser,
creating a new user if none exists.
Either telegram_id or wallet_id must be provided.
:param telegram_id: str, optional
:param wallet_id: str, optional
:return: TelegramUser
Set wallet_id and is_allowed_notification to True for a user by their telegram ID.
"""
if not telegram_id and not wallet_id:
raise ValueError("Either telegram_id or wallet_id must be provided")

with self.Session() as session:
user = None
if telegram_id:
user = self.get_user_by_telegram_id(telegram_id)
if not user and wallet_id:
user = (
session.query(TelegramUser).filter_by(wallet_id=wallet_id).first()
)

if user:
user.is_allowed_notification = not user.is_allowed_notification
session.commit()
session.refresh(user)
return user
else:
user_data = {
"telegram_id": telegram_id,
"wallet_id": wallet_id,
"is_allowed_notification": True,
}
return self.create_telegram_user(user_data)
return self.update_telegram_user(
telegram_id,
dict(is_allowed_notification=True, wallet_id=wallet_id)
)

def allow_notification(self, telegram_id: int) -> bool:
"""
Expand Down
1 change: 1 addition & 0 deletions web_app/telegram/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This document provides instructions on how to set up and run the Telegram bot, a
```env
TELEGRAM_TOKEN=<your-telegram-bot-token>
TELEGRAM_WEBAPP_URL=<your-webapp-url>
REACT_APP_BOT_ID=<your-telegram-bot-id>
```
Note: You can obtain the bot ID directly from your Telegram bot token in the format `bot_id:secret`.
Expand Down
29 changes: 27 additions & 2 deletions web_app/telegram/handlers/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@
"""

from aiogram import Router
from aiogram.filters import CommandStart
from aiogram.filters import CommandStart, CommandObject
from aiogram.types import Message

from web_app.db.models import User
from ..markups import launch_main_web_app_kb
from ..texts import WELCOME_MESSAGE
from ..texts import WELCOME_MESSAGE, NOTIFICATION_ALLOWED_MESSAGE
from web_app.db.crud.telegram import TelegramUserDBConnector
from web_app.db.crud import DBConnector

# Create a router for handling commands
cmd_router = Router()

telegram_db = TelegramUserDBConnector()
db_connector = DBConnector()

@cmd_router.message(CommandStart())
async def start_cmd(message: Message):
Expand All @@ -27,3 +32,23 @@ async def start_cmd(message: Message):
None: Sends a welcome message with a button to launch the web app.
"""
return message.answer(WELCOME_MESSAGE, reply_markup=launch_main_web_app_kb)


@cmd_router.message(CommandStart(deep_link=True, deep_link_encoded=True))
async def notification_allowed(message: Message, command: CommandObject):
"""
Handle the /start command with user id parameter.
Args:
message (Message): The incoming message containing the command.
command (CommandObject): The command object containing the user id.
"""
user_id = command.args
user = db_connector.get_object(User, user_id)

telegram_db.set_allow_notification(message.from_user.id, user.wallet_id)

return await message.answer(
NOTIFICATION_ALLOWED_MESSAGE,
reply_markup=launch_main_web_app_kb
)
6 changes: 6 additions & 0 deletions web_app/telegram/texts.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@
"This is getting low - please add more deposit to avoid liquidation.\n\n"
"Visit spotnet.xyz to manage your position."
)

NOTIFICATION_ALLOWED_MESSAGE = (
"You have successfully allowed notifications! "
"You will now receive updates and alerts regarding your account. "
"Thank you for staying connected with us! 🎉"
)

0 comments on commit 852e11e

Please sign in to comment.