Lucky_Tools/main.go

174 lines
4.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package main
import (
"database/sql"
"errors"
"fmt"
"github.com/gin-gonic/gin"
_ "github.com/mattn/go-sqlite3"
"log"
"net/http"
"time"
)
// MappingInfo 用于存储映射信息
type MappingInfo struct {
RuleName string `json:"rule_name"`
IpAddr string `json:"ip_addr"`
Ip string `json:"ip"`
Port string `json:"port"`
LastUpdate time.Time `json:"last_update"`
}
// 全局变量,存储所有映射信息
var mappings = make(map[string]*MappingInfo)
var db *sql.DB
var dbFileName = "./mappings.db" // 数据库文件名
var tableName = "mappings" // 数据库表名
var query = `SELECT name FROM sqlite_master WHERE type='table' AND name=?;` // 查询表是否存在的SQL语句
var createTableSQL = `CREATE TABLE IF NOT EXISTS ` + tableName + ` (
"RuleName" TEXT PRIMARY KEY,
"IPAddress" TEXT,
"Ip" TEXT,
"Port" TEXT,
"LastUpdate" TEXT
);` // 创建表的SQL语句
func main() {
InitDB() // 初始化数据库
defer func(db *sql.DB) {
err := db.Close()
if err != nil {
log.Fatal(err)
}
}(db)
router := gin.Default()
// 处理Webhook的路由
router.POST("/webhook", func(c *gin.Context) {
var info MappingInfo
if err := c.BindJSON(&info); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
info.LastUpdate = time.Now()
// 输出一下info
fmt.Println(info)
mappings[info.RuleName] = &info
updateMapping(info) // 更新数据库中的映射信息
c.JSON(http.StatusOK, gin.H{"status": "updated"})
})
// 提供Web服务的路由展示映射信息
router.GET("/mappings", func(c *gin.Context) {
c.JSON(http.StatusOK, mappings)
})
// 根据RuleName查询映射信息
router.GET("/mappings/:RuleName", func(c *gin.Context) {
serviceName := c.Param("RuleName")
if info, exists := mappings[serviceName]; exists {
c.JSON(http.StatusOK, info)
} else {
c.JSON(http.StatusNotFound, gin.H{"code": http.StatusNotFound, "error": "service not found"})
}
})
// 根据RuleName跳转到映射的服务
router.GET("/:RuleName", func(c *gin.Context) {
serviceName := c.Param("RuleName")
if info, exists := mappings[serviceName]; exists {
url := "http://" + info.Ip + ":" + info.Port
c.Redirect(http.StatusMovedPermanently, url)
} else {
c.JSON(http.StatusNotFound, gin.H{"code": http.StatusNotFound, "error": "service not found"})
}
})
// 启动定时任务,检查映射信息更新
go checkMappings()
err := router.Run(":8080")
if err != nil {
return
} // 在8080端口启动服务
}
// 定时检查映射信息是否需要更新
func checkMappings() {
for {
time.Sleep(24 * time.Hour) // 每天检查一次
for _, info := range mappings {
if time.Since(info.LastUpdate) > 24*time.Hour {
// 如果超过一天没有更新则主动查询API这里需要实现API查询逻辑
}
}
}
}
func InitDB() {
log.Println("Init DB...")
var err error
db, err = sql.Open("sqlite3", dbFileName)
if err != nil {
log.Fatal(err)
}
err = db.QueryRow(query, tableName).Scan(&tableName)
if errors.Is(err, sql.ErrNoRows) {
log.Println("Table not exists, create it...")
createTable()
} else if err != nil {
log.Fatal(err)
} else {
// 读取数据库中的映射信息
mappings = readMappings()
fmt.Println(mappings)
}
log.Println("Init DB done.")
}
// 创建映射表
func createTable() {
_, err := db.Exec(createTableSQL)
if err != nil {
log.Fatal(err)
}
}
// 从数据库读取映射信息
func readMappings() map[string]*MappingInfo {
mappings := make(map[string]*MappingInfo)
rows, err := db.Query("SELECT RuleName, IPAddress, Ip, Port, LastUpdate FROM mappings")
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var info MappingInfo
var lastUpdate string
err = rows.Scan(&info.RuleName, &info.IpAddr, &info.Ip, &info.Port, &lastUpdate)
if err != nil {
log.Fatal(err)
}
info.LastUpdate, err = time.Parse(time.RFC3339, lastUpdate)
if err != nil {
log.Fatal(err)
}
mappings[info.RuleName] = &info
}
return mappings
}
// 更新数据库中的映射信息
func updateMapping(info MappingInfo) {
_, err := db.Exec("INSERT OR REPLACE INTO mappings (RuleName, IPAddress, Ip, Port, LastUpdate) VALUES (?, ?, ?, ?, ?)",
info.RuleName, info.IpAddr, info.Ip, info.Port, info.LastUpdate.Format(time.RFC3339))
if err != nil {
log.Fatal(err)
}
}