2023-02-09 19:18:06 +00:00
package job
import (
"fmt"
"net"
"os"
"time"
"x-ui/logger"
"x-ui/util/common"
"x-ui/web/service"
2023-02-18 12:37:32 +00:00
2023-02-09 19:18:06 +00:00
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
)
type LoginStatus byte
const (
LoginSuccess LoginStatus = 1
LoginFail LoginStatus = 0
)
type StatsNotifyJob struct {
enable bool
xrayService service . XrayService
inboundService service . InboundService
settingService service . SettingService
}
func NewStatsNotifyJob ( ) * StatsNotifyJob {
return new ( StatsNotifyJob )
}
func ( j * StatsNotifyJob ) SendMsgToTgbot ( msg string ) {
//Telegram bot basic info
tgBottoken , err := j . settingService . GetTgBotToken ( )
if err != nil || tgBottoken == "" {
2023-02-20 13:36:56 +00:00
logger . Warning ( "ارسال پیام به ربات ناموفق بود, دریافت توکن ربات ناموفق بود:" , err )
2023-02-09 19:18:06 +00:00
return
}
tgBotid , err := j . settingService . GetTgBotChatId ( )
if err != nil {
2023-02-20 13:36:56 +00:00
logger . Warning ( "ارسال پیام به ربات ناموفق بود, دریافت توکن ربات ناموفق بود:" , err )
2023-02-09 19:18:06 +00:00
return
}
bot , err := tgbotapi . NewBotAPI ( tgBottoken )
if err != nil {
2023-02-20 13:36:56 +00:00
fmt . Println ( "ارور اتصال به ربات:" , err )
2023-02-09 19:18:06 +00:00
return
}
bot . Debug = true
2023-02-20 13:36:56 +00:00
fmt . Printf ( "اهراز شده بر روی اکانت %s" , bot . Self . UserName )
2023-02-09 19:18:06 +00:00
info := tgbotapi . NewMessage ( int64 ( tgBotid ) , msg )
//msg.ReplyToMessageID = int(tgBotid)
bot . Send ( info )
}
2023-02-18 12:37:32 +00:00
// Here run is a interface method of Job interface
2023-02-09 19:18:06 +00:00
func ( j * StatsNotifyJob ) Run ( ) {
if ! j . xrayService . IsXrayRunning ( ) {
return
}
var info string
//get hostname
name , err := os . Hostname ( )
if err != nil {
2023-02-20 13:36:56 +00:00
fmt . Println ( "ارور اتصال به هاست:" , err )
2023-02-09 19:18:06 +00:00
return
}
2023-02-20 13:36:56 +00:00
info = fmt . Sprintf ( "هاست:%s\r\n" , name )
2023-02-09 19:18:06 +00:00
//get ip address
var ip string
netInterfaces , err := net . Interfaces ( )
if err != nil {
fmt . Println ( "net.Interfaces failed, err:" , err . Error ( ) )
return
}
for i := 0 ; i < len ( netInterfaces ) ; i ++ {
if ( netInterfaces [ i ] . Flags & net . FlagUp ) != 0 {
addrs , _ := netInterfaces [ i ] . Addrs ( )
for _ , address := range addrs {
if ipnet , ok := address . ( * net . IPNet ) ; ok && ! ipnet . IP . IsLoopback ( ) {
if ipnet . IP . To4 ( ) != nil {
ip = ipnet . IP . String ( )
break
} else {
ip = ipnet . IP . String ( )
break
}
}
}
}
}
info += fmt . Sprintf ( "IP:%s\r\n \r\n" , ip )
2023-02-18 12:37:32 +00:00
// get traffic
2023-02-09 19:18:06 +00:00
inbouds , err := j . inboundService . GetAllInbounds ( )
if err != nil {
logger . Warning ( "StatsNotifyJob run failed:" , err )
return
}
2023-02-18 12:37:32 +00:00
// NOTE:If there no any sessions here,need to notify here
// TODO:Sub-node push, automatic conversion format
2023-02-09 19:18:06 +00:00
for _ , inbound := range inbouds {
2023-02-20 13:36:56 +00:00
info += fmt . Sprintf ( "نام کاربری:%s\r\nپورت:%d\r\nآپلود↑:%s\r\nدا نلود↓:%s\r\nمجموع:%s\r\n" , inbound . Remark , inbound . Port , common . FormatTraffic ( inbound . Up ) , common . FormatTraffic ( inbound . Down ) , common . FormatTraffic ( ( inbound . Up + inbound . Down ) ) )
2023-02-09 19:18:06 +00:00
if inbound . ExpiryTime == 0 {
2023-02-20 13:36:56 +00:00
info += fmt . Sprintf ( "تاریخ انقضاء::نامحدود\r\n \r\n" )
2023-02-09 19:18:06 +00:00
} else {
2023-02-20 13:36:56 +00:00
info += fmt . Sprintf ( "تاریخ انقضاء:%s\r\n \r\n" , time . Unix ( ( inbound . ExpiryTime / 1000 ) , 0 ) . Format ( "2006-01-02 15:04:05" ) )
2023-02-09 19:18:06 +00:00
}
}
j . SendMsgToTgbot ( info )
}
func ( j * StatsNotifyJob ) UserLoginNotify ( username string , ip string , time string , status LoginStatus ) {
if username == "" || ip == "" || time == "" {
2023-02-20 13:36:56 +00:00
logger . Warning ( "اتصال به پنا ناموفق بود، مشخصات نادرست" )
2023-02-09 19:18:06 +00:00
return
}
var msg string
2023-02-18 12:37:32 +00:00
// Get hostname
2023-02-09 19:18:06 +00:00
name , err := os . Hostname ( )
if err != nil {
fmt . Println ( "get hostname error:" , err )
return
}
if status == LoginSuccess {
2023-02-20 13:36:56 +00:00
msg = fmt . Sprintf ( "با موفقیت به پنل وارد شدید\r\nHostname:%s\r\n" , name )
2023-02-09 19:18:06 +00:00
} else if status == LoginFail {
2023-02-20 13:36:56 +00:00
msg = fmt . Sprintf ( "اتصال به پنل ناموفق بود\r\nHostname:%s\r\n" , name )
2023-02-09 19:18:06 +00:00
}
2023-02-20 13:36:56 +00:00
msg += fmt . Sprintf ( "مدت زمان:%s\r\n" , time )
msg += fmt . Sprintf ( "نام کاربری:%s\r\n" , username )
2023-02-09 19:18:06 +00:00
msg += fmt . Sprintf ( "IP:%s\r\n" , ip )
j . SendMsgToTgbot ( msg )
}
var numericKeyboard = tgbotapi . NewInlineKeyboardMarkup (
2023-02-18 12:37:32 +00:00
tgbotapi . NewInlineKeyboardRow (
2023-02-20 13:36:56 +00:00
tgbotapi . NewInlineKeyboardButtonData ( "وضعیت کاربری" , "وضعیت کاربری" ) ,
2023-02-18 12:37:32 +00:00
) ,
2023-02-09 19:18:06 +00:00
)
func ( j * StatsNotifyJob ) OnReceive ( ) * StatsNotifyJob {
tgBottoken , err := j . settingService . GetTgBotToken ( )
if err != nil || tgBottoken == "" {
2023-02-20 13:36:56 +00:00
logger . Warning ( "ارسال پیام به ربات ناموفق بود, دریافت توکن ربات ناموفق بود:" , err )
2023-02-09 19:18:06 +00:00
return j
}
bot , err := tgbotapi . NewBotAPI ( tgBottoken )
if err != nil {
2023-02-20 13:36:56 +00:00
fmt . Println ( "ارور اتصال به ربات:" , err )
2023-02-09 19:18:06 +00:00
return j
}
bot . Debug = false
u := tgbotapi . NewUpdate ( 0 )
2023-02-18 12:37:32 +00:00
u . Timeout = 10
2023-02-09 19:18:06 +00:00
2023-02-18 12:37:32 +00:00
updates := bot . GetUpdatesChan ( u )
for update := range updates {
if update . Message == nil {
2023-02-09 19:18:06 +00:00
if update . CallbackQuery != nil {
// Respond to the callback query, telling Telegram to show the user
// a message with the data received.
callback := tgbotapi . NewCallback ( update . CallbackQuery . ID , update . CallbackQuery . Data )
if _ , err := bot . Request ( callback ) ; err != nil {
logger . Warning ( err )
}
2023-02-18 12:37:32 +00:00
2023-02-09 19:18:06 +00:00
// And finally, send a message containing the data received.
msg := tgbotapi . NewMessage ( update . CallbackQuery . Message . Chat . ID , "" )
switch update . CallbackQuery . Data {
2023-02-20 13:36:56 +00:00
case "وضعیت کاربری" :
msg . Text = " برای دریافت وضعیت کاربری، دستوری به شکل زیر ارسال کنید: : \n <code>/usage uuid | id</code> \n مثال : <code>/usage fc3239ed-8f3b-4151-ff51-b183d5182142</code>"
2023-02-18 12:37:32 +00:00
msg . ParseMode = "HTML"
}
2023-02-09 19:18:06 +00:00
if _ , err := bot . Send ( msg ) ; err != nil {
logger . Warning ( err )
}
}
2023-02-18 12:37:32 +00:00
continue
}
if ! update . Message . IsCommand ( ) { // ignore any non-command Messages
continue
}
// Create a new MessageConfig. We don't have text yet,
// so we leave it empty.
msg := tgbotapi . NewMessage ( update . Message . Chat . ID , "" )
// Extract the command from the Message.
switch update . Message . Command ( ) {
case "help" :
2023-02-20 13:36:56 +00:00
msg . Text = "چه کمکی از دست من برمیاد؟"
2023-02-09 19:18:06 +00:00
msg . ReplyMarkup = numericKeyboard
2023-02-18 12:37:32 +00:00
case "start" :
2023-02-20 13:36:56 +00:00
msg . Text = "سلام :) \n چه کمکی از دست من برمیاد؟"
2023-02-09 19:18:06 +00:00
msg . ReplyMarkup = numericKeyboard
2023-02-18 12:37:32 +00:00
case "status" :
2023-02-20 13:36:56 +00:00
msg . Text = "ربات حالش خوبه، تو خوبی؟ :)"
2023-02-09 19:18:06 +00:00
2023-02-18 12:37:32 +00:00
case "usage" :
msg . Text = j . getClientUsage ( update . Message . CommandArguments ( ) )
default :
2023-02-20 13:36:56 +00:00
msg . Text = "این دستور شناخته شده نیست :(, /help"
2023-02-09 19:18:06 +00:00
msg . ReplyMarkup = numericKeyboard
2023-02-18 12:37:32 +00:00
}
2023-02-09 19:18:06 +00:00
2023-02-18 12:37:32 +00:00
if _ , err := bot . Send ( msg ) ; err != nil {
logger . Warning ( err )
}
}
2023-02-09 19:18:06 +00:00
return j
}
func ( j * StatsNotifyJob ) getClientUsage ( id string ) string {
2023-02-18 12:37:32 +00:00
traffic , err := j . inboundService . GetClientTrafficById ( id )
2023-02-09 19:18:06 +00:00
if err != nil {
logger . Warning ( err )
2023-02-20 13:36:56 +00:00
return "یه اشتباهی رخ داد!"
2023-02-09 19:18:06 +00:00
}
expiryTime := ""
if traffic . ExpiryTime == 0 {
2023-02-20 13:36:56 +00:00
expiryTime = fmt . Sprintf ( "نامحدود" )
2023-02-09 19:18:06 +00:00
} else {
expiryTime = fmt . Sprintf ( "%s" , time . Unix ( ( traffic . ExpiryTime / 1000 ) , 0 ) . Format ( "2006-01-02 15:04:05" ) )
}
total := ""
if traffic . Total == 0 {
2023-02-20 13:36:56 +00:00
total = fmt . Sprintf ( "نامحدود" )
2023-02-09 19:18:06 +00:00
} else {
total = fmt . Sprintf ( "%s" , common . FormatTraffic ( ( traffic . Total ) ) )
}
2023-02-20 13:36:56 +00:00
output := fmt . Sprintf ( "💡 فعال: %t\r\n📧 نام کاربری: %s\r\n🔼 آپلود↑: %s\r\n🔽 دانلود↓: %s\r\n🔄 مجموع: %s / %s\r\n📅 تاریخ انقضاء: %s\r\n" ,
2023-02-18 12:37:32 +00:00
traffic . Enable , traffic . Email , common . FormatTraffic ( traffic . Up ) , common . FormatTraffic ( traffic . Down ) , common . FormatTraffic ( ( traffic . Up + traffic . Down ) ) ,
total , expiryTime )
2023-02-09 19:18:06 +00:00
return output
}