telegram bot ui settings and code sending
This commit is contained in:
parent
aed212d8f8
commit
e79946b4e4
@ -4,6 +4,7 @@ import 'dart:convert';
|
|||||||
import 'package:bot_toast/bot_toast.dart';
|
import 'package:bot_toast/bot_toast.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:flutter_hbb/common/shared_state.dart';
|
import 'package:flutter_hbb/common/shared_state.dart';
|
||||||
import 'package:flutter_hbb/common/widgets/setting_widgets.dart';
|
import 'package:flutter_hbb/common/widgets/setting_widgets.dart';
|
||||||
import 'package:flutter_hbb/consts.dart';
|
import 'package:flutter_hbb/consts.dart';
|
||||||
@ -218,50 +219,53 @@ void changeWhiteList({Function()? callback}) async {
|
|||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
dialogButton("Cancel", onPressed: close, isOutline: true),
|
dialogButton("Cancel", onPressed: close, isOutline: true),
|
||||||
if (!isOptFixed)dialogButton("Clear", onPressed: () async {
|
if (!isOptFixed)
|
||||||
await bind.mainSetOption(
|
dialogButton("Clear", onPressed: () async {
|
||||||
key: kOptionWhitelist, value: defaultOptionWhitelist);
|
|
||||||
callback?.call();
|
|
||||||
close();
|
|
||||||
}, isOutline: true),
|
|
||||||
if (!isOptFixed) dialogButton(
|
|
||||||
"OK",
|
|
||||||
onPressed: () async {
|
|
||||||
setState(() {
|
|
||||||
msg = "";
|
|
||||||
isInProgress = true;
|
|
||||||
});
|
|
||||||
newWhiteListField = controller.text.trim();
|
|
||||||
var newWhiteList = "";
|
|
||||||
if (newWhiteListField.isEmpty) {
|
|
||||||
// pass
|
|
||||||
} else {
|
|
||||||
final ips = newWhiteListField.trim().split(RegExp(r"[\s,;\n]+"));
|
|
||||||
// test ip
|
|
||||||
final ipMatch = RegExp(
|
|
||||||
r"^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)(\/([1-9]|[1-2][0-9]|3[0-2])){0,1}$");
|
|
||||||
final ipv6Match = RegExp(
|
|
||||||
r"^(((?:[0-9A-Fa-f]{1,4}))*((?::[0-9A-Fa-f]{1,4}))*::((?:[0-9A-Fa-f]{1,4}))*((?::[0-9A-Fa-f]{1,4}))*|((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4})){7})(\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])){0,1}$");
|
|
||||||
for (final ip in ips) {
|
|
||||||
if (!ipMatch.hasMatch(ip) && !ipv6Match.hasMatch(ip)) {
|
|
||||||
msg = "${translate("Invalid IP")} $ip";
|
|
||||||
setState(() {
|
|
||||||
isInProgress = false;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newWhiteList = ips.join(',');
|
|
||||||
}
|
|
||||||
if (newWhiteList.trim().isEmpty) {
|
|
||||||
newWhiteList = defaultOptionWhitelist;
|
|
||||||
}
|
|
||||||
await bind.mainSetOption(
|
await bind.mainSetOption(
|
||||||
key: kOptionWhitelist, value: newWhiteList);
|
key: kOptionWhitelist, value: defaultOptionWhitelist);
|
||||||
callback?.call();
|
callback?.call();
|
||||||
close();
|
close();
|
||||||
},
|
}, isOutline: true),
|
||||||
),
|
if (!isOptFixed)
|
||||||
|
dialogButton(
|
||||||
|
"OK",
|
||||||
|
onPressed: () async {
|
||||||
|
setState(() {
|
||||||
|
msg = "";
|
||||||
|
isInProgress = true;
|
||||||
|
});
|
||||||
|
newWhiteListField = controller.text.trim();
|
||||||
|
var newWhiteList = "";
|
||||||
|
if (newWhiteListField.isEmpty) {
|
||||||
|
// pass
|
||||||
|
} else {
|
||||||
|
final ips =
|
||||||
|
newWhiteListField.trim().split(RegExp(r"[\s,;\n]+"));
|
||||||
|
// test ip
|
||||||
|
final ipMatch = RegExp(
|
||||||
|
r"^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)(\/([1-9]|[1-2][0-9]|3[0-2])){0,1}$");
|
||||||
|
final ipv6Match = RegExp(
|
||||||
|
r"^(((?:[0-9A-Fa-f]{1,4}))*((?::[0-9A-Fa-f]{1,4}))*::((?:[0-9A-Fa-f]{1,4}))*((?::[0-9A-Fa-f]{1,4}))*|((?:[0-9A-Fa-f]{1,4}))((?::[0-9A-Fa-f]{1,4})){7})(\/([1-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])){0,1}$");
|
||||||
|
for (final ip in ips) {
|
||||||
|
if (!ipMatch.hasMatch(ip) && !ipv6Match.hasMatch(ip)) {
|
||||||
|
msg = "${translate("Invalid IP")} $ip";
|
||||||
|
setState(() {
|
||||||
|
isInProgress = false;
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newWhiteList = ips.join(',');
|
||||||
|
}
|
||||||
|
if (newWhiteList.trim().isEmpty) {
|
||||||
|
newWhiteList = defaultOptionWhitelist;
|
||||||
|
}
|
||||||
|
await bind.mainSetOption(
|
||||||
|
key: kOptionWhitelist, value: newWhiteList);
|
||||||
|
callback?.call();
|
||||||
|
close();
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
onCancel: close,
|
onCancel: close,
|
||||||
);
|
);
|
||||||
@ -1762,6 +1766,66 @@ void renameDialog(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void changeBot({Function()? callback}) async {
|
||||||
|
if (bind.mainHasValidBotSync()) {
|
||||||
|
await bind.mainSetOption(key: "bot", value: "");
|
||||||
|
callback?.call();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String errorText = '';
|
||||||
|
bool loading = false;
|
||||||
|
final controller = TextEditingController();
|
||||||
|
gFFI.dialogManager.show((setState, close, context) {
|
||||||
|
onVerify() async {
|
||||||
|
final token = controller.text.trim();
|
||||||
|
if (token == "") return;
|
||||||
|
loading = true;
|
||||||
|
errorText = '';
|
||||||
|
setState(() {});
|
||||||
|
final error = await bind.mainVerifyBot(token: token);
|
||||||
|
if (error == "") {
|
||||||
|
callback?.call();
|
||||||
|
close();
|
||||||
|
} else {
|
||||||
|
errorText = translate(error);
|
||||||
|
loading = false;
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final codeField = TextField(
|
||||||
|
autofocus: true,
|
||||||
|
controller: controller,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: translate('Token'), // 使用hintText设置占位符文本
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return CustomAlertDialog(
|
||||||
|
title: Text(translate("Telegram bot")),
|
||||||
|
content: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
SelectableText(translate("enable-bot-desc"),
|
||||||
|
style: TextStyle(fontSize: 12))
|
||||||
|
.marginOnly(bottom: 12),
|
||||||
|
Row(children: [Expanded(child: codeField)]),
|
||||||
|
if (errorText != '')
|
||||||
|
Text(errorText, style: TextStyle(color: Colors.red))
|
||||||
|
.marginOnly(top: 12),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
dialogButton("Cancel", onPressed: close, isOutline: true),
|
||||||
|
loading
|
||||||
|
? CircularProgressIndicator()
|
||||||
|
: dialogButton("OK", onPressed: onVerify),
|
||||||
|
],
|
||||||
|
onCancel: close,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void change2fa({Function()? callback}) async {
|
void change2fa({Function()? callback}) async {
|
||||||
if (bind.mainHasValid2FaSync()) {
|
if (bind.mainHasValid2FaSync()) {
|
||||||
await bind.mainSetOption(key: "2fa", value: "");
|
await bind.mainSetOption(key: "2fa", value: "");
|
||||||
|
@ -340,7 +340,7 @@ class _ConnectionPageState extends State<ConnectionPage>
|
|||||||
?.merge(TextStyle(height: 1)),
|
?.merge(TextStyle(height: 1)),
|
||||||
).marginOnly(right: 4),
|
).marginOnly(right: 4),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
waitDuration: Duration(milliseconds: 0),
|
waitDuration: Duration(milliseconds: 300),
|
||||||
message: translate("id_input_tip"),
|
message: translate("id_input_tip"),
|
||||||
child: Icon(
|
child: Icon(
|
||||||
Icons.help_outline_outlined,
|
Icons.help_outline_outlined,
|
||||||
|
@ -679,6 +679,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
|||||||
// Simple temp wrapper for PR check
|
// Simple temp wrapper for PR check
|
||||||
tmpWrapper() {
|
tmpWrapper() {
|
||||||
RxBool has2fa = bind.mainHasValid2FaSync().obs;
|
RxBool has2fa = bind.mainHasValid2FaSync().obs;
|
||||||
|
RxBool hasBot = bind.mainHasValidBotSync().obs;
|
||||||
update() async {
|
update() async {
|
||||||
has2fa.value = bind.mainHasValid2FaSync();
|
has2fa.value = bind.mainHasValid2FaSync();
|
||||||
}
|
}
|
||||||
@ -687,7 +688,7 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
|||||||
change2fa(callback: update);
|
change2fa(callback: update);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GestureDetector(
|
final tfa = GestureDetector(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
child: Obx(() => Row(
|
child: Obx(() => Row(
|
||||||
children: [
|
children: [
|
||||||
@ -708,6 +709,44 @@ class _SafetyState extends State<_Safety> with AutomaticKeepAliveClientMixin {
|
|||||||
onChanged(!has2fa.value);
|
onChanged(!has2fa.value);
|
||||||
},
|
},
|
||||||
).marginOnly(left: _kCheckBoxLeftMargin);
|
).marginOnly(left: _kCheckBoxLeftMargin);
|
||||||
|
if (!has2fa.value) {
|
||||||
|
return tfa;
|
||||||
|
}
|
||||||
|
updateBot() async {
|
||||||
|
hasBot.value = bind.mainHasValidBotSync();
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangedBot(bool? checked) async {
|
||||||
|
changeBot(callback: updateBot);
|
||||||
|
}
|
||||||
|
|
||||||
|
final bot = GestureDetector(
|
||||||
|
child: Tooltip(
|
||||||
|
waitDuration: Duration(milliseconds: 300),
|
||||||
|
message: translate("enable-bot-tip"),
|
||||||
|
child: InkWell(
|
||||||
|
child: Obx(() => Row(
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: hasBot.value,
|
||||||
|
onChanged: enabled ? onChangedBot : null)
|
||||||
|
.marginOnly(right: 5),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
translate('Telegram bot'),
|
||||||
|
style: TextStyle(
|
||||||
|
color: disabledTextColor(context, enabled)),
|
||||||
|
))
|
||||||
|
],
|
||||||
|
))),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
onChangedBot(!hasBot.value);
|
||||||
|
},
|
||||||
|
).marginOnly(left: _kCheckBoxLeftMargin + 30);
|
||||||
|
return Column(
|
||||||
|
children: [tfa, bot],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tmpWrapper();
|
return tmpWrapper();
|
||||||
|
@ -4,7 +4,7 @@ use hbb_common::{
|
|||||||
config::Config,
|
config::Config,
|
||||||
get_time,
|
get_time,
|
||||||
password_security::{decrypt_vec_or_original, encrypt_vec_or_original},
|
password_security::{decrypt_vec_or_original, encrypt_vec_or_original},
|
||||||
ResultType,
|
tokio, ResultType,
|
||||||
};
|
};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
@ -133,46 +133,61 @@ impl TelegramBot {
|
|||||||
fn save(&self) -> ResultType<()> {
|
fn save(&self) -> ResultType<()> {
|
||||||
let s = self.into_string()?;
|
let s = self.into_string()?;
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
crate::ipc::set_option("telegram_bot", &s);
|
crate::ipc::set_option("bot", &s);
|
||||||
#[cfg(any(target_os = "android", target_os = "ios"))]
|
#[cfg(any(target_os = "android", target_os = "ios"))]
|
||||||
Config::set_option("telegram_bot".to_owned(), s);
|
Config::set_option("bot".to_owned(), s);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get() -> ResultType<TelegramBot> {
|
pub fn get() -> ResultType<Option<TelegramBot>> {
|
||||||
let data = Config::get_option("telegram_bot");
|
let data = Config::get_option("bot");
|
||||||
|
if data.is_empty() {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
let mut bot = serde_json::from_str::<TelegramBot>(&data)?;
|
let mut bot = serde_json::from_str::<TelegramBot>(&data)?;
|
||||||
let (token, success, _) = decrypt_vec_or_original(&bot.token, "00");
|
let (token, success, _) = decrypt_vec_or_original(&bot.token, "00");
|
||||||
if success {
|
if success {
|
||||||
bot.token_str = String::from_utf8(token)?;
|
bot.token_str = String::from_utf8(token)?;
|
||||||
return Ok(bot);
|
return Ok(Some(bot));
|
||||||
}
|
}
|
||||||
bail!("decrypt_vec_or_original telegram bot token failed")
|
bail!("decrypt_vec_or_original telegram bot token failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://gist.github.com/dideler/85de4d64f66c1966788c1b2304b9caf1
|
// https://gist.github.com/dideler/85de4d64f66c1966788c1b2304b9caf1
|
||||||
pub async fn send_2fa_code_to_telegram(code: &str) -> ResultType<()> {
|
pub async fn send_2fa_code_to_telegram(text: &str, bot: TelegramBot) -> ResultType<()> {
|
||||||
let bot = TelegramBot::get()?;
|
|
||||||
let url = format!("https://api.telegram.org/bot{}/sendMessage", bot.token_str);
|
let url = format!("https://api.telegram.org/bot{}/sendMessage", bot.token_str);
|
||||||
let params = serde_json::json!({"chat_id": bot.chat_id, "text": code});
|
let params = serde_json::json!({"chat_id": bot.chat_id, "text": text});
|
||||||
crate::post_request(url, params.to_string(), "").await?;
|
crate::post_request(url, params.to_string(), "").await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::main(flavor = "current_thread")]
|
||||||
pub async fn get_chatid_telegram(bot_token: &str) -> ResultType<Option<String>> {
|
pub async fn get_chatid_telegram(bot_token: &str) -> ResultType<Option<String>> {
|
||||||
// send a message to the bot first please, otherwise the chat_id will be empty
|
|
||||||
let url = format!("https://api.telegram.org/bot{}/getUpdates", bot_token);
|
let url = format!("https://api.telegram.org/bot{}/getUpdates", bot_token);
|
||||||
let resp = crate::post_request(url, "".to_owned(), "")
|
let resp = crate::post_request(url, "".to_owned(), "")
|
||||||
.await
|
.await
|
||||||
.map_err(|e| anyhow!(e))?;
|
.map_err(|e| anyhow!(e))?;
|
||||||
let res = serde_json::from_str::<serde_json::Value>(&resp)
|
let value = serde_json::from_str::<serde_json::Value>(&resp).map_err(|e| anyhow!(e))?;
|
||||||
.map(|x| {
|
|
||||||
let chat_id = x["result"][0]["message"]["chat"]["id"].as_str();
|
// Check for an error_code in the response
|
||||||
chat_id.map(|x| x.to_owned())
|
if let Some(error_code) = value.get("error_code").and_then(|code| code.as_i64()) {
|
||||||
})
|
// If there's an error_code, try to use the description for the error message
|
||||||
.map_err(|e| anyhow!(e));
|
let description = value["description"]
|
||||||
if let Ok(Some(chat_id)) = res.as_ref() {
|
.as_str()
|
||||||
|
.unwrap_or("Unknown error occurred");
|
||||||
|
return Err(anyhow!(
|
||||||
|
"Telegram API error: {} (error_code: {})",
|
||||||
|
description,
|
||||||
|
error_code
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let chat_id = value["result"][0]["message"]["chat"]["id"]
|
||||||
|
.as_str()
|
||||||
|
.map(|x| x.to_owned());
|
||||||
|
|
||||||
|
if let Some(chat_id) = chat_id.as_ref() {
|
||||||
let bot = TelegramBot {
|
let bot = TelegramBot {
|
||||||
token_str: bot_token.to_owned(),
|
token_str: bot_token.to_owned(),
|
||||||
chat_id: chat_id.to_owned(),
|
chat_id: chat_id.to_owned(),
|
||||||
@ -180,5 +195,6 @@ pub async fn get_chatid_telegram(bot_token: &str) -> ResultType<Option<String>>
|
|||||||
};
|
};
|
||||||
bot.save()?;
|
bot.save()?;
|
||||||
}
|
}
|
||||||
res
|
|
||||||
|
Ok(chat_id)
|
||||||
}
|
}
|
||||||
|
@ -2178,6 +2178,14 @@ pub fn main_has_valid_2fa_sync() -> SyncReturn<bool> {
|
|||||||
SyncReturn(has_valid_2fa())
|
SyncReturn(has_valid_2fa())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn main_verify_bot(token: String) -> String {
|
||||||
|
verify_bot(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn main_has_valid_bot_sync() -> SyncReturn<bool> {
|
||||||
|
SyncReturn(has_valid_bot())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main_get_hard_option(key: String) -> SyncReturn<String> {
|
pub fn main_get_hard_option(key: String) -> SyncReturn<String> {
|
||||||
SyncReturn(get_hard_option(key))
|
SyncReturn(get_hard_option(key))
|
||||||
}
|
}
|
||||||
|
@ -230,5 +230,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("android_new_voice_call_tip", "A new voice call request was received. If you accept, the audio will switch to voice communication."),
|
("android_new_voice_call_tip", "A new voice call request was received. If you accept, the audio will switch to voice communication."),
|
||||||
("texture_render_tip", "Use texture rendering to make the pictures smoother. You could try disabling this option if you encounter rendering issues."),
|
("texture_render_tip", "Use texture rendering to make the pictures smoother. You could try disabling this option if you encounter rendering issues."),
|
||||||
("floating_window_tip", "It helps to keep RustDesk background service"),
|
("floating_window_tip", "It helps to keep RustDesk background service"),
|
||||||
|
("enable-bot-tip", "If you enable this feature, you can receive the 2FA code from your bot. It can also function as a connection notification."),
|
||||||
|
("enable-bot-desc", "1, Open a chat with @BotFather.\n2, Send the command \"/newbot\". You will receive a token after completing this step.\n3, Start a chat with your newly created bot. Send a message like \"hello\" to activate it.\n"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -627,5 +627,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("Volume up", ""),
|
("Volume up", ""),
|
||||||
("Volume down", ""),
|
("Volume down", ""),
|
||||||
("Power", ""),
|
("Power", ""),
|
||||||
|
("Telegram bot", ""),
|
||||||
|
("enable-bot-tip", ""),
|
||||||
|
("enable-bot-desc", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -401,7 +401,8 @@ impl Connection {
|
|||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
start_channel(rx_to_cm, tx_from_cm);
|
start_channel(rx_to_cm, tx_from_cm);
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
conn.send_permission(Permission::Keyboard, conn.keyboard).await;
|
conn.send_permission(Permission::Keyboard, conn.keyboard)
|
||||||
|
.await;
|
||||||
#[cfg(not(target_os = "android"))]
|
#[cfg(not(target_os = "android"))]
|
||||||
if !conn.keyboard {
|
if !conn.keyboard {
|
||||||
conn.send_permission(Permission::Keyboard, false).await;
|
conn.send_permission(Permission::Keyboard, false).await;
|
||||||
@ -1079,6 +1080,33 @@ impl Connection {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if self.require_2fa.is_some() && !self.is_recent_session(true) && !self.from_switch {
|
if self.require_2fa.is_some() && !self.is_recent_session(true) && !self.from_switch {
|
||||||
|
self.require_2fa.as_ref().map(|totp| {
|
||||||
|
let bot = crate::auth_2fa::TelegramBot::get();
|
||||||
|
let bot = match bot {
|
||||||
|
Ok(Some(bot)) => bot,
|
||||||
|
Err(err) => {
|
||||||
|
log::error!("Failed to get telegram bot: {}", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
let code = totp.generate_current();
|
||||||
|
if let Ok(code) = code {
|
||||||
|
let text = format!(
|
||||||
|
"2FA code: {}\n\nA new connection has been established to your device with ID {}. The source IP address is {}.",
|
||||||
|
code,
|
||||||
|
Config::get_id(),
|
||||||
|
self.ip,
|
||||||
|
);
|
||||||
|
tokio::spawn(async move {
|
||||||
|
if let Err(err) =
|
||||||
|
crate::auth_2fa::send_2fa_code_to_telegram(&text, bot).await
|
||||||
|
{
|
||||||
|
log::error!("Failed to send 2fa code to telegram bot: {}", err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
self.send_login_error(crate::client::REQUIRE_2FA).await;
|
self.send_login_error(crate::client::REQUIRE_2FA).await;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1392,6 +1392,20 @@ pub fn verify2fa(code: String) -> bool {
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_valid_bot() -> bool {
|
||||||
|
crate::auth_2fa::TelegramBot::get().map_or(false, |bot| bot.is_some())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_bot(token: String) -> String {
|
||||||
|
match crate::auth_2fa::get_chatid_telegram(&token) {
|
||||||
|
Err(err) => err.to_string(),
|
||||||
|
Ok(None) => {
|
||||||
|
"To activate the bot, simply send a message like \"hello\" to its chat.".to_owned()
|
||||||
|
}
|
||||||
|
_ => "".to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn check_hwcodec() {
|
pub fn check_hwcodec() {
|
||||||
#[cfg(feature = "hwcodec")]
|
#[cfg(feature = "hwcodec")]
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user