Skip to content

Commit ce49f55

Browse files
committed
Add test button to Telegram settings to verify bot configuration
1 parent 899983a commit ce49f55

4 files changed

Lines changed: 143 additions & 5 deletions

File tree

backend/app/main.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,34 @@ def check_telegram_settings(
157157
return MessageResponse(
158158
message=f"Telegram configured: {is_configured}"
159159
)
160+
161+
162+
@app.post("/auth/telegram/test", response_model=MessageResponse)
163+
async def send_test_telegram_message(
164+
current_user: User = Depends(get_current_user),
165+
) -> MessageResponse:
166+
"""Send a test message to user's Telegram bot"""
167+
if not current_user.telegram_bot_token or not current_user.telegram_chat_id:
168+
raise HTTPException(
169+
status_code=status.HTTP_400_BAD_REQUEST,
170+
detail="Telegram bot not configured. Please set it up first.",
171+
)
172+
173+
telegram = TelegramService(
174+
bot_token=current_user.telegram_bot_token,
175+
chat_id=current_user.telegram_chat_id,
176+
)
177+
178+
try:
179+
await telegram.send_message(
180+
f"✅ <b>Test Message Successful!</b>\n\n"
181+
f"Your Telegram bot is correctly configured.\n"
182+
f"<b>User:</b> {current_user.full_name}\n"
183+
f"<b>Email:</b> {current_user.email}"
184+
)
185+
return MessageResponse(message="Test message sent successfully to your Telegram bot!")
186+
except Exception as e:
187+
raise HTTPException(
188+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
189+
detail=f"Failed to send test message: {str(e)}",
190+
)

frontend/src/api.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,15 @@ export async function checkTelegramSettings(token: string): Promise<{ message: s
110110
return parseResponse<{ message: string }>(response);
111111
}
112112

113+
export async function sendTestTelegramMessage(token: string): Promise<{ message: string }> {
114+
const response = await fetch(`${API_BASE_URL}/auth/telegram/test`, {
115+
method: 'POST',
116+
headers: {
117+
Authorization: `Bearer ${token}`,
118+
},
119+
});
120+
121+
return parseResponse<{ message: string }>(response);
122+
}
123+
113124
export type { AuthResponse, UserResponse, RegisterPayload, LoginPayload, TelegramSettingsPayload };

frontend/src/pages/TelegramSettingsPage.css

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,52 @@
266266
cursor: not-allowed;
267267
}
268268

269+
.test-section {
270+
margin-top: 2rem;
271+
padding: 1.5rem;
272+
background: var(--code-bg, #f5f5f5);
273+
border-radius: 8px;
274+
border: 1px solid var(--border-color, #ddd);
275+
}
276+
277+
.test-section h3 {
278+
color: var(--text-primary, #000);
279+
margin: 0 0 0.5rem 0;
280+
font-size: 1rem;
281+
}
282+
283+
.test-section p {
284+
color: var(--text-secondary, #666);
285+
margin: 0.5rem 0 1rem 0;
286+
font-size: 0.95rem;
287+
}
288+
289+
.test-button {
290+
padding: 0.75rem 1.5rem;
291+
background: linear-gradient(
292+
135deg,
293+
var(--primary, #4f8cff),
294+
var(--secondary, #7c4dff)
295+
);
296+
color: white;
297+
border: none;
298+
border-radius: 8px;
299+
font-size: 0.95rem;
300+
font-weight: 600;
301+
cursor: pointer;
302+
transition: all 0.3s ease;
303+
}
304+
305+
.test-button:hover:not(:disabled) {
306+
box-shadow: 0 4px 12px rgba(79, 140, 255, 0.4);
307+
transform: translateY(-2px);
308+
}
309+
310+
.test-button:disabled {
311+
opacity: 0.6;
312+
cursor: not-allowed;
313+
}
314+
269315
.info-section {
270316
margin-top: 2rem;
271317
padding-top: 2rem;

frontend/src/pages/TelegramSettingsPage.tsx

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { FC, useState, useEffect } from 'react';
22
import { useAuth } from '../auth/AuthContext';
3-
import { checkTelegramSettings, setTelegramSettings } from '../api';
3+
import { checkTelegramSettings, setTelegramSettings, sendTestTelegramMessage } from '../api';
44
import './TelegramSettingsPage.css';
55

66
export const TelegramSettingsPage: FC = () => {
@@ -14,6 +14,8 @@ export const TelegramSettingsPage: FC = () => {
1414
const [success, setSuccess] = useState(false);
1515
const [isConfigured, setIsConfigured] = useState(false);
1616
const [checkingStatus, setCheckingStatus] = useState(true);
17+
const [testLoading, setTestLoading] = useState(false);
18+
const [testMessage, setTestMessage] = useState('');
1719

1820
useEffect(() => {
1921
checkConfigurationStatus();
@@ -45,6 +47,7 @@ export const TelegramSettingsPage: FC = () => {
4547
e.preventDefault();
4648
setError('');
4749
setSuccess(false);
50+
setTestMessage('');
4851

4952
if (!formData.telegram_bot_token.trim()) {
5053
setError('Bot token is required');
@@ -78,6 +81,32 @@ export const TelegramSettingsPage: FC = () => {
7881
}
7982
};
8083

84+
const handleTestMessage = async () => {
85+
setError('');
86+
setTestMessage('');
87+
88+
if (!isConfigured) {
89+
setError('Please save your settings first');
90+
return;
91+
}
92+
93+
if (!token) {
94+
setError('Not authenticated');
95+
return;
96+
}
97+
98+
setTestLoading(true);
99+
try {
100+
const result = await sendTestTelegramMessage(token);
101+
setTestMessage(result.message);
102+
setTimeout(() => setTestMessage(''), 5000);
103+
} catch (err) {
104+
setError(err instanceof Error ? err.message : 'Failed to send test message');
105+
} finally {
106+
setTestLoading(false);
107+
}
108+
};
109+
81110
return (
82111
<div className="telegram-settings-container">
83112
<div className="telegram-settings-header">
@@ -116,10 +145,10 @@ export const TelegramSettingsPage: FC = () => {
116145
<div className="settings-form-container">
117146
<div
118147
className={`status-indicator ${checkingStatus
119-
? 'checking'
120-
: isConfigured
121-
? 'configured'
122-
: 'not-configured'
148+
? 'checking'
149+
: isConfigured
150+
? 'configured'
151+
: 'not-configured'
123152
}`}
124153
>
125154
<span className="status-dot"></span>
@@ -144,6 +173,12 @@ export const TelegramSettingsPage: FC = () => {
144173
</div>
145174
)}
146175

176+
{testMessage && (
177+
<div className="banner banner-success">
178+
<span>{testMessage}</span>
179+
</div>
180+
)}
181+
147182
<form onSubmit={handleSubmit} className="settings-form">
148183
<div className="form-group">
149184
<label htmlFor="telegram_bot_token">
@@ -191,6 +226,21 @@ export const TelegramSettingsPage: FC = () => {
191226
</button>
192227
</form>
193228

229+
{isConfigured && (
230+
<div className="test-section">
231+
<h3>Test Your Configuration</h3>
232+
<p>Send a test message to verify your bot is working correctly:</p>
233+
<button
234+
type="button"
235+
onClick={handleTestMessage}
236+
disabled={testLoading}
237+
className="test-button"
238+
>
239+
{testLoading ? 'Sending test message...' : 'Send Test Message'}
240+
</button>
241+
</div>
242+
)}
243+
194244
<div className="info-section">
195245
<h3>Why do I need this?</h3>
196246
<p>

0 commit comments

Comments
 (0)