mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-03-01 01:20:49 +03:00
Add version and log
TGBOT: Add xray config to backup [TGBOT] add seach inbound
This commit is contained in:
parent
162349f8c8
commit
826c7264b5
@ -1,11 +1,10 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
"time"
|
"time"
|
||||||
"x-ui/web/global"
|
"x-ui/web/global"
|
||||||
"x-ui/web/service"
|
"x-ui/web/service"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServerController struct {
|
type ServerController struct {
|
||||||
@ -38,7 +37,6 @@ func (a *ServerController) initRouter(g *gin.RouterGroup) {
|
|||||||
g.POST("/stopXrayService", a.stopXrayService)
|
g.POST("/stopXrayService", a.stopXrayService)
|
||||||
g.POST("/restartXrayService", a.restartXrayService)
|
g.POST("/restartXrayService", a.restartXrayService)
|
||||||
g.POST("/installXray/:version", a.installXray)
|
g.POST("/installXray/:version", a.installXray)
|
||||||
g.POST("/logs", a.getLogs)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ServerController) refreshStatus() {
|
func (a *ServerController) refreshStatus() {
|
||||||
@ -89,13 +87,13 @@ func (a *ServerController) installXray(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *ServerController) stopXrayService(c *gin.Context) {
|
func (a *ServerController) stopXrayService(c *gin.Context) {
|
||||||
a.lastGetStatusTime = time.Now()
|
a.lastGetStatusTime = time.Now()
|
||||||
err := a.serverService.StopXrayService()
|
err := a.serverService.StopXrayService()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonMsg(c, "", err)
|
jsonMsg(c, "", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "Xray stoped", err)
|
jsonMsg(c, "Xray stoped",err)
|
||||||
|
|
||||||
}
|
}
|
||||||
func (a *ServerController) restartXrayService(c *gin.Context) {
|
func (a *ServerController) restartXrayService(c *gin.Context) {
|
||||||
@ -104,15 +102,6 @@ func (a *ServerController) restartXrayService(c *gin.Context) {
|
|||||||
jsonMsg(c, "", err)
|
jsonMsg(c, "", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
jsonMsg(c, "Xray restarted", err)
|
jsonMsg(c, "Xray restarted",err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ServerController) getLogs(c *gin.Context) {
|
|
||||||
logs, err := a.serverService.GetLogs()
|
|
||||||
if err != nil {
|
|
||||||
jsonMsg(c, I18n(c, "getLogs"), err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
jsonObj(c, logs, nil)
|
|
||||||
}
|
|
||||||
|
@ -84,18 +84,16 @@
|
|||||||
</template>
|
</template>
|
||||||
<a-icon type="question-circle" theme="filled"></a-icon>
|
<a-icon type="question-circle" theme="filled"></a-icon>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
<a-tag color="green" style="cursor: pointer;" @click="openSelectV2rayVersion">[[ status.xray.version ]]</a-tag>
|
<a-tag color="green" @click="openSelectV2rayVersion">[[ status.xray.version ]]</a-tag>
|
||||||
<a-tag color="blue" style="cursor: pointer;" @click="stopXrayService">{{ i18n "pages.index.stopXray" }}</a-tag>
|
<a-tag color="blue" @click="stopXrayService">{{ i18n "pages.index.stopXray" }}</a-tag>
|
||||||
<a-tag color="blue" style="cursor: pointer;" @click="restartXrayService">{{ i18n "pages.index.restartXray" }}</a-tag>
|
<a-tag color="blue" @click="restartXrayService">{{ i18n "pages.index.restartXray" }}</a-tag>
|
||||||
<a-tag color="blue" style="cursor: pointer;" @click="openSelectV2rayVersion">{{ i18n "pages.index.xraySwitch" }}</a-tag>
|
<a-tag color="blue" @click="openSelectV2rayVersion">{{ i18n "pages.index.xraySwitch" }}</a-tag>
|
||||||
</a-card>
|
</a-card>
|
||||||
</a-col>
|
</a-col>
|
||||||
<a-col :sm="24" :md="12">
|
<a-col :sm="24" :md="12">
|
||||||
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
|
<a-card hoverable :class="siderDrawer.isDarkTheme ? darkClass : ''">
|
||||||
x-ui: <a-tag color="green">{{ .cur_ver }}</a-tag>
|
|
||||||
<a-tag color="blue" style="cursor: pointer;" @click="openLogs">Logs</a-tag>
|
|
||||||
{{ i18n "pages.index.operationHours" }}:
|
{{ i18n "pages.index.operationHours" }}:
|
||||||
<a-tag color="green">[[ formatSecond(status.uptime) ]]</a-tag>
|
<a-tag color="#87d068">[[ formatSecond(status.uptime) ]]</a-tag>
|
||||||
<a-tooltip>
|
<a-tooltip>
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
{{ i18n "pages.index.operationHoursDesc" }}
|
{{ i18n "pages.index.operationHoursDesc" }}
|
||||||
@ -179,7 +177,7 @@
|
|||||||
<a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}'
|
<a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}'
|
||||||
:closable="true" @ok="() => versionModal.visible = false"
|
:closable="true" @ok="() => versionModal.visible = false"
|
||||||
:class="siderDrawer.isDarkTheme ? darkClass : ''"
|
:class="siderDrawer.isDarkTheme ? darkClass : ''"
|
||||||
footer="">
|
ok-text='{{ i18n "confirm" }}' cancel-text='{{ i18n "cancel"}}'>
|
||||||
<h2>{{ i18n "pages.index.xraySwitchClick"}}</h2>
|
<h2>{{ i18n "pages.index.xraySwitchClick"}}</h2>
|
||||||
<h2>{{ i18n "pages.index.xraySwitchClickDesk"}}</h2>
|
<h2>{{ i18n "pages.index.xraySwitchClickDesk"}}</h2>
|
||||||
<template v-for="version, index in versionModal.versions">
|
<template v-for="version, index in versionModal.versions">
|
||||||
@ -189,17 +187,6 @@
|
|||||||
</a-tag>
|
</a-tag>
|
||||||
</template>
|
</template>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<a-modal id="log-modal" v-model="logModal.visible" title="X-UI logs"
|
|
||||||
:closable="true" @ok="() => logModal.visible = false" @cancel="() => logModal.visible = false"
|
|
||||||
:class="siderDrawer.isDarkTheme ? darkClass : ''"
|
|
||||||
width="800px"
|
|
||||||
footer="">
|
|
||||||
<table style="margin: 0px; width: 100%; background-color: black; color: hsla(0,0%,100%,.65);">
|
|
||||||
<tr v-for="log , index in logModal.logs">
|
|
||||||
<td style="vertical-align: top;">[[ index ]]</td><td>[[ log ]]</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</a-modal>
|
|
||||||
</a-layout>
|
</a-layout>
|
||||||
{{template "js" .}}
|
{{template "js" .}}
|
||||||
<script>
|
<script>
|
||||||
@ -293,18 +280,6 @@
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const logModal = {
|
|
||||||
visible: false,
|
|
||||||
logs: '',
|
|
||||||
show(logs) {
|
|
||||||
this.visible = true;
|
|
||||||
this.logs = logs;
|
|
||||||
},
|
|
||||||
hide() {
|
|
||||||
this.visible = false;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
delimiters: ['[[', ']]'],
|
delimiters: ['[[', ']]'],
|
||||||
el: '#app',
|
el: '#app',
|
||||||
@ -312,7 +287,6 @@
|
|||||||
siderDrawer,
|
siderDrawer,
|
||||||
status: new Status(),
|
status: new Status(),
|
||||||
versionModal,
|
versionModal,
|
||||||
logModal,
|
|
||||||
spinning: false,
|
spinning: false,
|
||||||
loadingTip: '{{ i18n "loading"}}',
|
loadingTip: '{{ i18n "loading"}}',
|
||||||
},
|
},
|
||||||
@ -372,15 +346,6 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async openLogs(){
|
|
||||||
this.loading(true);
|
|
||||||
const msg = await HttpUtil.post('server/logs');
|
|
||||||
this.loading(false);
|
|
||||||
if (!msg.success) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logModal.show(msg.obj);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
<a-list item-layout="horizontal" :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65);': 'background: white;'">
|
<a-list item-layout="horizontal" :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65);': 'background: white;'">
|
||||||
<setting-list-item type="text" title='{{ i18n "pages.setting.panelListeningIP"}}' desc='{{ i18n "pages.setting.panelListeningIPDesc"}}' v-model="allSetting.webListen"></setting-list-item>
|
<setting-list-item type="text" title='{{ i18n "pages.setting.panelListeningIP"}}' desc='{{ i18n "pages.setting.panelListeningIPDesc"}}' v-model="allSetting.webListen"></setting-list-item>
|
||||||
<setting-list-item type="number" title='{{ i18n "pages.setting.panelPort"}}' desc='{{ i18n "pages.setting.panelPortDesc"}}' v-model.number="allSetting.webPort"></setting-list-item>
|
<setting-list-item type="text" title='{{ i18n "pages.setting.panelPort"}}' desc='{{ i18n "pages.setting.panelPortDesc"}}' v-model.number="allSetting.webPort"></setting-list-item>
|
||||||
<setting-list-item type="text" title='{{ i18n "pages.setting.publicKeyPath"}}' desc='{{ i18n "pages.setting.publicKeyPathDesc"}}' v-model="allSetting.webCertFile"></setting-list-item>
|
<setting-list-item type="text" title='{{ i18n "pages.setting.publicKeyPath"}}' desc='{{ i18n "pages.setting.publicKeyPathDesc"}}' v-model="allSetting.webCertFile"></setting-list-item>
|
||||||
<setting-list-item type="text" title='{{ i18n "pages.setting.privateKeyPath"}}' desc='{{ i18n "pages.setting.privateKeyPathDesc"}}' v-model="allSetting.webKeyFile"></setting-list-item>
|
<setting-list-item type="text" title='{{ i18n "pages.setting.privateKeyPath"}}' desc='{{ i18n "pages.setting.privateKeyPathDesc"}}' v-model="allSetting.webKeyFile"></setting-list-item>
|
||||||
<setting-list-item type="text" title='{{ i18n "pages.setting.panelUrlPath"}}' desc='{{ i18n "pages.setting.panelUrlPathDesc"}}' v-model="allSetting.webBasePath"></setting-list-item>
|
<setting-list-item type="text" title='{{ i18n "pages.setting.panelUrlPath"}}' desc='{{ i18n "pages.setting.panelUrlPathDesc"}}' v-model="allSetting.webBasePath"></setting-list-item>
|
||||||
@ -117,7 +117,7 @@
|
|||||||
<a-list item-layout="horizontal" :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65);': 'background: white;'">
|
<a-list item-layout="horizontal" :style="siderDrawer.isDarkTheme ? 'color: hsla(0,0%,100%,.65);': 'background: white;'">
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.setting.telegramBotEnable" }}' desc='{{ i18n "pages.setting.telegramBotEnableDesc" }}' v-model="allSetting.tgBotEnable"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.setting.telegramBotEnable" }}' desc='{{ i18n "pages.setting.telegramBotEnableDesc" }}' v-model="allSetting.tgBotEnable"></setting-list-item>
|
||||||
<setting-list-item type="text" title='{{ i18n "pages.setting.telegramToken"}}' desc='{{ i18n "pages.setting.telegramTokenDesc"}}' v-model="allSetting.tgBotToken"></setting-list-item>
|
<setting-list-item type="text" title='{{ i18n "pages.setting.telegramToken"}}' desc='{{ i18n "pages.setting.telegramTokenDesc"}}' v-model="allSetting.tgBotToken"></setting-list-item>
|
||||||
<setting-list-item type="text" title='{{ i18n "pages.setting.telegramChatId"}}' desc='{{ i18n "pages.setting.telegramChatIdDesc"}}' v-model="allSetting.tgBotChatId"></setting-list-item>
|
<setting-list-item type="number" title='{{ i18n "pages.setting.telegramChatId"}}' desc='{{ i18n "pages.setting.telegramChatIdDesc"}}' v-model="allSetting.tgBotChatId"></setting-list-item>
|
||||||
<setting-list-item type="text" title='{{ i18n "pages.setting.telegramNotifyTime"}}' desc='{{ i18n "pages.setting.telegramNotifyTimeDesc"}}' v-model="allSetting.tgRunTime"></setting-list-item>
|
<setting-list-item type="text" title='{{ i18n "pages.setting.telegramNotifyTime"}}' desc='{{ i18n "pages.setting.telegramNotifyTimeDesc"}}' v-model="allSetting.tgRunTime"></setting-list-item>
|
||||||
<setting-list-item type="switch" title='{{ i18n "pages.setting.tgNotifyBackup" }}' desc='{{ i18n "pages.setting.tgNotifyBackupDesc" }}' v-model="allSetting.tgBotBackup"></setting-list-item>
|
<setting-list-item type="switch" title='{{ i18n "pages.setting.tgNotifyBackup" }}' desc='{{ i18n "pages.setting.tgNotifyBackupDesc" }}' v-model="allSetting.tgBotBackup"></setting-list-item>
|
||||||
<setting-list-item type="number" title='{{ i18n "pages.setting.tgNotifyExpireTimeDiff" }}' desc='{{ i18n "pages.setting.tgNotifyExpireTimeDiffDesc" }}' v-model="allSetting.tgExpireDiff" :min="0"></setting-list-item>
|
<setting-list-item type="number" title='{{ i18n "pages.setting.tgNotifyExpireTimeDiff" }}' desc='{{ i18n "pages.setting.tgNotifyExpireTimeDiffDesc" }}' v-model="allSetting.tgExpireDiff" :min="0"></setting-list-item>
|
||||||
|
@ -634,13 +634,3 @@ func (s *InboundService) ClearClientIps(clientEmail string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InboundService) SearchInbounds(query string) ([]*model.Inbound, error) {
|
|
||||||
db := database.GetDB()
|
|
||||||
var inbounds []*model.Inbound
|
|
||||||
err := db.Model(model.Inbound{}).Preload("ClientStats").Where("remark like ?", "%"+query+"%").Find(&inbounds).Error
|
|
||||||
if err != nil && err != gorm.ErrRecordNotFound {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return inbounds, nil
|
|
||||||
}
|
|
@ -9,9 +9,7 @@ import (
|
|||||||
"io/fs"
|
"io/fs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
"x-ui/logger"
|
"x-ui/logger"
|
||||||
"x-ui/util/sys"
|
"x-ui/util/sys"
|
||||||
@ -202,24 +200,24 @@ func (s *ServerService) GetXrayVersions() ([]string, error) {
|
|||||||
|
|
||||||
func (s *ServerService) StopXrayService() (string error) {
|
func (s *ServerService) StopXrayService() (string error) {
|
||||||
|
|
||||||
err := s.xrayService.StopXray()
|
err := s.xrayService.StopXray()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("stop xray failed:", err)
|
logger.Error("stop xray failed:", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerService) RestartXrayService() (string error) {
|
func (s *ServerService) RestartXrayService() (string error) {
|
||||||
|
|
||||||
s.xrayService.StopXray()
|
s.xrayService.StopXray()
|
||||||
defer func() {
|
defer func() {
|
||||||
err := s.xrayService.RestartXray(true)
|
err := s.xrayService.RestartXray(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("start xray failed:", err)
|
logger.Error("start xray failed:", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -326,26 +324,3 @@ func (s *ServerService) UpdateXray(version string) error {
|
|||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerService) GetLogs() ([]string, error) {
|
|
||||||
// Define the journalctl command and its arguments
|
|
||||||
var cmdArgs []string
|
|
||||||
if runtime.GOOS == "linux" {
|
|
||||||
cmdArgs = []string{"journalctl", "-u", "x-ui", "--no-pager", "-n", "100"}
|
|
||||||
} else {
|
|
||||||
return []string{"Unsupported operating system"}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the command
|
|
||||||
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
|
|
||||||
var out bytes.Buffer
|
|
||||||
cmd.Stdout = &out
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
lines := strings.Split(out.String(), "\n")
|
|
||||||
|
|
||||||
return lines, nil
|
|
||||||
}
|
|
||||||
|
@ -105,6 +105,8 @@ func (t *Tgbot) OnReceive() {
|
|||||||
} else {
|
} else {
|
||||||
if update.Message.IsCommand() {
|
if update.Message.IsCommand() {
|
||||||
t.answerCommand(update.Message, chatId, isAdmin)
|
t.answerCommand(update.Message, chatId, isAdmin)
|
||||||
|
} else {
|
||||||
|
t.aswerChat(update.Message.Text, chatId, isAdmin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,18 +137,16 @@ func (t *Tgbot) answerCommand(message *tgbotapi.Message, chatId int64, isAdmin b
|
|||||||
} else {
|
} else {
|
||||||
msg = "❗Please provide a text for search!"
|
msg = "❗Please provide a text for search!"
|
||||||
}
|
}
|
||||||
case "inbound":
|
|
||||||
if isAdmin {
|
|
||||||
t.searchInbound(chatId, message.CommandArguments())
|
|
||||||
} else {
|
|
||||||
msg = "❗ Unknown command"
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
msg = "❗ Unknown command"
|
msg = "❗ Unknown command"
|
||||||
}
|
}
|
||||||
t.SendAnswer(chatId, msg, isAdmin)
|
t.SendAnswer(chatId, msg, isAdmin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Tgbot) aswerChat(message string, chatId int64, isAdmin bool) {
|
||||||
|
t.SendAnswer(chatId, "❗ Unknown message", isAdmin)
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Tgbot) asnwerCallback(callbackQuery *tgbotapi.CallbackQuery, isAdmin bool) {
|
func (t *Tgbot) asnwerCallback(callbackQuery *tgbotapi.CallbackQuery, isAdmin bool) {
|
||||||
// Respond to the callback query, telling Telegram to show the user
|
// Respond to the callback query, telling Telegram to show the user
|
||||||
// a message with the data received.
|
// a message with the data received.
|
||||||
@ -169,7 +169,7 @@ func (t *Tgbot) asnwerCallback(callbackQuery *tgbotapi.CallbackQuery, isAdmin bo
|
|||||||
case "client_commands":
|
case "client_commands":
|
||||||
t.SendMsgToTgbot(callbackQuery.From.ID, "To search for statistics, just use folowing command:\r\n \r\n<code>/usage [UID|Passowrd]</code>\r\n \r\nUse UID for vmess and vless and Password for Trojan.")
|
t.SendMsgToTgbot(callbackQuery.From.ID, "To search for statistics, just use folowing command:\r\n \r\n<code>/usage [UID|Passowrd]</code>\r\n \r\nUse UID for vmess and vless and Password for Trojan.")
|
||||||
case "commands":
|
case "commands":
|
||||||
t.SendMsgToTgbot(callbackQuery.From.ID, "Search for a client email:\r\n<code>/usage email</code>\r\n \r\nSearch for inbounds (with client stats):\r\n<code>/inbound [remark]</code>")
|
t.SendMsgToTgbot(callbackQuery.From.ID, "To search for a client email, just use folowing command:\r\n \r\n<code>/usage email</code>")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,7 +276,6 @@ func (t *Tgbot) getServerUsage() string {
|
|||||||
name = ""
|
name = ""
|
||||||
}
|
}
|
||||||
info = fmt.Sprintf("💻 Hostname: %s\r\n", name)
|
info = fmt.Sprintf("💻 Hostname: %s\r\n", name)
|
||||||
info += fmt.Sprintf("🚀X-UI Version: %s\r\n", config.GetVersion())
|
|
||||||
//get ip address
|
//get ip address
|
||||||
var ip string
|
var ip string
|
||||||
var ipv6 string
|
var ipv6 string
|
||||||
@ -428,45 +427,6 @@ func (t *Tgbot) searchClient(chatId int64, email string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tgbot) searchInbound(chatId int64, remark string) {
|
|
||||||
inbouds, err := t.inboundService.SearchInbounds(remark)
|
|
||||||
if err != nil {
|
|
||||||
logger.Warning(err)
|
|
||||||
msg := "❌ Something went wrong!"
|
|
||||||
t.SendMsgToTgbot(chatId, msg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, inbound := range inbouds {
|
|
||||||
info := ""
|
|
||||||
info += fmt.Sprintf("📍Inbound:%s\r\nPort:%d\r\n", inbound.Remark, inbound.Port)
|
|
||||||
info += fmt.Sprintf("Traffic: %s (↑%s,↓%s)\r\n", common.FormatTraffic((inbound.Up + inbound.Down)), common.FormatTraffic(inbound.Up), common.FormatTraffic(inbound.Down))
|
|
||||||
if inbound.ExpiryTime == 0 {
|
|
||||||
info += "Expire date: ♾ Unlimited\r\n \r\n"
|
|
||||||
} else {
|
|
||||||
info += fmt.Sprintf("Expire date:%s\r\n \r\n", time.Unix((inbound.ExpiryTime/1000), 0).Format("2006-01-02 15:04:05"))
|
|
||||||
}
|
|
||||||
t.SendMsgToTgbot(chatId, info)
|
|
||||||
for _, traffic := range inbound.ClientStats {
|
|
||||||
expiryTime := ""
|
|
||||||
if traffic.ExpiryTime == 0 {
|
|
||||||
expiryTime = "♾Unlimited"
|
|
||||||
} else {
|
|
||||||
expiryTime = time.Unix((traffic.ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05")
|
|
||||||
}
|
|
||||||
total := ""
|
|
||||||
if traffic.Total == 0 {
|
|
||||||
total = "♾Unlimited"
|
|
||||||
} else {
|
|
||||||
total = common.FormatTraffic((traffic.Total))
|
|
||||||
}
|
|
||||||
output := fmt.Sprintf("💡 Active: %t\r\n📧 Email: %s\r\n🔼 Upload↑: %s\r\n🔽 Download↓: %s\r\n🔄 Total: %s / %s\r\n📅 Expire in: %s\r\n",
|
|
||||||
traffic.Enable, traffic.Email, common.FormatTraffic(traffic.Up), common.FormatTraffic(traffic.Down), common.FormatTraffic((traffic.Up + traffic.Down)),
|
|
||||||
total, expiryTime)
|
|
||||||
t.SendMsgToTgbot(chatId, output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *Tgbot) searchForClient(chatId int64, query string) {
|
func (t *Tgbot) searchForClient(chatId int64, query string) {
|
||||||
traffic, err := t.inboundService.SearchClientTraffic(query)
|
traffic, err := t.inboundService.SearchClientTraffic(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -587,10 +547,4 @@ func (t *Tgbot) sendBackup(chatId int64) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warning("Error in uploading backup: ", err)
|
logger.Warning("Error in uploading backup: ", err)
|
||||||
}
|
}
|
||||||
file = tgbotapi.FilePath(xray.GetConfigPath())
|
|
||||||
msg = tgbotapi.NewDocument(chatId, file)
|
|
||||||
_, err = bot.Send(msg)
|
|
||||||
if err != nil {
|
|
||||||
logger.Warning("Error in uploading config.json: ", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user