-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* beta9 * beta11 * beta11 * beta13 * beta12 * beta13 * beta15 * beta16 * beta17 * beta18 * beta19 * beta20 * beta21 * add_playermanager_api * beta22 * beta23 * beta24
- Loading branch information
1 parent
50a0854
commit 3783b3c
Showing
43 changed files
with
2,912 additions
and
108 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
package bot | ||
|
||
import ( | ||
"encoding/binary" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"log" | ||
|
||
"github.com/boltdb/bolt" | ||
) | ||
|
||
var ( | ||
db *bolt.DB | ||
) | ||
|
||
const ( | ||
DBName = "bot.db" | ||
BotBucket = "botdata" | ||
) | ||
|
||
func InitializeDB() { | ||
var err error | ||
db, err = bolt.Open(DBName, 0600, nil) | ||
if err != nil { | ||
log.Fatalf("Error opening DB: %v", err) | ||
} | ||
|
||
db.Update(func(tx *bolt.Tx) error { | ||
_, err := tx.CreateBucketIfNotExists([]byte(BotBucket)) | ||
return err | ||
}) | ||
} | ||
|
||
// CloseDatabase 提供关闭数据库的方法 | ||
func CloseDatabase() error { | ||
if db != nil { | ||
return db.Close() | ||
} | ||
return nil | ||
} | ||
|
||
// CheckAndWriteCookie 检查cookie是否存在,如果不存在则写入数据库 | ||
func CheckAndWriteCookie(value string) (bool, error) { | ||
if db == nil { | ||
return false, errors.New("database not initialized") | ||
} | ||
|
||
// 检查键是否存在 | ||
exists := false | ||
err := db.View(func(tx *bolt.Tx) error { | ||
b := tx.Bucket([]byte(BotBucket)) | ||
if b != nil { | ||
v := b.Get([]byte(value)) | ||
exists = v != nil | ||
} | ||
return nil | ||
}) | ||
if err != nil { | ||
return false, err | ||
} | ||
if exists { | ||
return true, nil | ||
} | ||
|
||
// 键不存在,写入新键值对 | ||
err = db.Update(func(tx *bolt.Tx) error { | ||
b, err := tx.CreateBucketIfNotExists([]byte(BotBucket)) | ||
if err != nil { | ||
return err | ||
} | ||
return b.Put([]byte(value), []byte("true")) | ||
}) | ||
return false, err | ||
} | ||
|
||
type UserIPData struct { | ||
IP string `json:"ip"` | ||
UUID string `json:"uuid"` | ||
Https bool `json:"https"` | ||
} | ||
|
||
// StoreUserIDAndIP 用于存储用户ID(int64)、IP地址(string)和UUID(string) | ||
func StoreUserIDAndIP(userID int64, ip string, uuid string, https bool) error { | ||
if db == nil { | ||
return errors.New("database not initialized") | ||
} | ||
|
||
userData := UserIPData{ | ||
IP: ip, | ||
UUID: uuid, | ||
Https: https, | ||
} | ||
userDataBytes, err := json.Marshal(userData) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return db.Update(func(tx *bolt.Tx) error { | ||
bucket, err := tx.CreateBucketIfNotExists([]byte("ipuserdata")) | ||
if err != nil { | ||
return err | ||
} | ||
userIDBytes := make([]byte, 8) | ||
binary.BigEndian.PutUint64(userIDBytes, uint64(userID)) | ||
return bucket.Put(userIDBytes, userDataBytes) | ||
}) | ||
} | ||
|
||
// RetrieveIPByUserID 用于通过用户ID(int64)检索IP地址(string)和UUID(string) | ||
func RetrieveIPByUserID(userID int64) (UserIPData, error) { | ||
var userData UserIPData | ||
if db == nil { | ||
return userData, errors.New("database not initialized") | ||
} | ||
|
||
err := db.View(func(tx *bolt.Tx) error { | ||
bucket := tx.Bucket([]byte("ipuserdata")) | ||
if bucket == nil { | ||
return fmt.Errorf("bucket %s not found", "ipuserdata") | ||
} | ||
userIDBytes := make([]byte, 8) | ||
binary.BigEndian.PutUint64(userIDBytes, uint64(userID)) | ||
value := bucket.Get(userIDBytes) | ||
if value == nil { | ||
return fmt.Errorf("no data found for user ID %d", userID) | ||
} | ||
return json.Unmarshal(value, &userData) | ||
}) | ||
|
||
if err != nil { | ||
return userData, err | ||
} | ||
return userData, nil | ||
} | ||
|
||
type PlayerInfo struct { | ||
PlayerUID string `json:"playerUID"` | ||
SteamID string `json:"steamID"` | ||
Name string `json:"name"` | ||
Online bool `json:"online"` | ||
LastOnline string `json:"last_online"` | ||
} | ||
|
||
// StorePlayerInfo 存储玩家信息并返回唯一ID | ||
func StorePlayerInfo(playerUID, steamID, name string) (int64, error) { | ||
if db == nil { | ||
return 0, errors.New("database not initialized") | ||
} | ||
|
||
playerInfo := PlayerInfo{ | ||
PlayerUID: playerUID, | ||
SteamID: steamID, | ||
Name: name, | ||
} | ||
|
||
var id int64 | ||
err := db.Update(func(tx *bolt.Tx) error { | ||
// 创建或获取PlayerList bucket | ||
bucket, err := tx.CreateBucketIfNotExists([]byte("playerlist")) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// 检查是否已存在相同的玩家信息 | ||
c := bucket.Cursor() | ||
for k, v := c.First(); k != nil; k, v = c.Next() { | ||
var existingPlayerInfo PlayerInfo | ||
if err := json.Unmarshal(v, &existingPlayerInfo); err != nil { | ||
continue | ||
} | ||
if existingPlayerInfo.PlayerUID == playerUID && existingPlayerInfo.SteamID == steamID && existingPlayerInfo.Name == name { | ||
// 解析ID | ||
id = int64(binary.BigEndian.Uint64(k)) | ||
return nil | ||
} | ||
} | ||
|
||
// 分配新的唯一ID | ||
seq, _ := bucket.NextSequence() | ||
id = int64(seq) // 转换为 int64 | ||
idBytes := make([]byte, 8) | ||
binary.BigEndian.PutUint64(idBytes, uint64(id)) | ||
playerInfoBytes, err := json.Marshal(playerInfo) | ||
if err != nil { | ||
return err | ||
} | ||
return bucket.Put(idBytes, playerInfoBytes) | ||
}) | ||
|
||
return id, err | ||
} | ||
|
||
// RetrievePlayerInfoByID 通过ID检索玩家信息 | ||
func RetrievePlayerInfoByID(id int64) (PlayerInfo, error) { | ||
var playerInfo PlayerInfo | ||
if db == nil { | ||
return playerInfo, errors.New("database not initialized") | ||
} | ||
|
||
err := db.View(func(tx *bolt.Tx) error { | ||
bucket := tx.Bucket([]byte("playerlist")) | ||
if bucket == nil { | ||
return fmt.Errorf("bucket %s not found", "playerlist") | ||
} | ||
idBytes := make([]byte, 8) | ||
binary.BigEndian.PutUint64(idBytes, uint64(id)) | ||
value := bucket.Get(idBytes) | ||
if value == nil { | ||
return fmt.Errorf("no player found for ID %d", id) | ||
} | ||
return json.Unmarshal(value, &playerInfo) | ||
}) | ||
|
||
return playerInfo, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package bot | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
func ipToNumber(ip string) (int64, error) { | ||
parts := strings.Split(ip, ".") | ||
if len(parts) != 4 { | ||
return 0, fmt.Errorf("invalid IP address format") | ||
} | ||
|
||
r, err := strconv.Atoi(parts[0]) | ||
if err != nil { | ||
return 0, err | ||
} | ||
g, err := strconv.Atoi(parts[1]) | ||
if err != nil { | ||
return 0, err | ||
} | ||
b, err := strconv.Atoi(parts[2]) | ||
if err != nil { | ||
return 0, err | ||
} | ||
n, err := strconv.Atoi(parts[3]) | ||
if err != nil { | ||
return 0, err | ||
} | ||
|
||
c := int64(r) + int64(g)*256 + int64(b)*256*256 + int64(n)*256*256*256 | ||
c = (c + 250) * 2 | ||
return c, nil | ||
} | ||
|
||
func numberToIP(num int64) string { | ||
// 因为在转换时执行了 (c + 250) * 2 | ||
// 所以先进行反向操作 | ||
num = (num / 2) - 250 | ||
|
||
// 提取IP的四个部分 | ||
n := num / (256 * 256 * 256) % 256 | ||
b := num / (256 * 256) % 256 | ||
g := num / 256 % 256 | ||
r := num % 256 | ||
|
||
// 构造IP地址 | ||
return fmt.Sprintf("%d.%d.%d.%d", r, g, b, n) | ||
} | ||
|
||
func IpToNumberWithPort(ip string) (int64, error) { | ||
parts := strings.Split(ip, ":") | ||
if len(parts) != 2 { | ||
return 0, fmt.Errorf("invalid IP address and port format") | ||
} | ||
|
||
ipPart, portPart := parts[0], parts[1] | ||
port, err := strconv.Atoi(portPart) | ||
if err != nil { | ||
return 0, fmt.Errorf("invalid port: %s", err) | ||
} | ||
|
||
num, err := ipToNumber(ipPart) | ||
if err != nil { | ||
return 0, err | ||
} | ||
|
||
return num*65536 + int64(port), nil // 65536 = 256*256,确保端口不会与IP地址冲突 | ||
} | ||
|
||
func numberToIPWithPort(num int64) string { | ||
port := num % 65536 | ||
num = num / 65536 | ||
|
||
ip := numberToIP(num) | ||
return fmt.Sprintf("%s:%d", ip, port) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
<template> | ||
<div class="my-page"> | ||
<q-btn color="blue" label="生成机器人指令" @click="getBot"></q-btn> | ||
<q-btn color="primary" label="获取机器人" @click="getBotLink"></q-btn> | ||
<q-input v-model="apiResponse" readonly></q-input> | ||
<q-btn color="green" label="点击复制" @click="copyResponse"></q-btn> | ||
<div>如果点击复制无效,请在守护设置开启强制https或手动复制。</div> | ||
<div>指令包含加密后的你的面板地址,需放通webui端口到公网。</div> | ||
<div>建议发出给帕鲁帕鲁后立即撤回。</div> | ||
</div> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
import { ref } from 'vue'; | ||
import { QBtn, QInput } from 'quasar'; | ||
const apiResponse = ref(''); | ||
const getBot = async () => { | ||
const response = await fetch('/api/getbot', { | ||
method: 'POST', | ||
credentials: 'include', | ||
}); | ||
apiResponse.value = await response.text(); | ||
}; | ||
const getBotLink = async () => { | ||
const response = await fetch('/api/getbotlink', { | ||
method: 'POST', | ||
credentials: 'include', | ||
}); | ||
apiResponse.value = await response.text(); | ||
}; | ||
const copyResponse = () => { | ||
navigator.clipboard.writeText(apiResponse.value).catch(() => { | ||
console.error('复制失败,请手动复制'); | ||
}); | ||
}; | ||
</script> | ||
|
||
<style lang="scss"> | ||
.my-page { | ||
.q-btn { | ||
margin-bottom: 10px; | ||
} | ||
.q-input { | ||
margin-bottom: 10px; | ||
} | ||
} | ||
</style> |
Oops, something went wrong.