This commit is contained in:
2025-09-12 16:42:10 +08:00
commit 0878cef03b
10 changed files with 512 additions and 0 deletions

8
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/randomLink.iml" filepath="$PROJECT_DIR$/.idea/randomLink.iml" />
</modules>
</component>
</project>

9
.idea/randomLink.iml generated Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

16
.idea/remote-targets.xml generated Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteTargetsManager">
<targets>
<target name="root@192.3.55.124:22" type="ssh/sftp" uuid="caa814af-46f3-40d3-8fc3-b39c5a1ec66e">
<config>
<option name="projectRootOnTarget" value="/root/randomLink" />
<option name="serverName" value="root@192.3.55.124:22 password" />
</config>
<ContributedStateBase type="GoLanguageRuntime">
<config />
</ContributedStateBase>
</target>
</targets>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

10
go.mod Normal file
View File

@ -0,0 +1,10 @@
module randomLink
go 1.21
require (
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 // indirect
)

8
go.sum Normal file
View File

@ -0,0 +1,8 @@
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1 h1:wG8n/XJQ07TmjbITcGiUaOtXxdrINDz1b0J1w0SzqDc=
github.com/go-telegram-bot-api/telegram-bot-api/v5 v5.5.1/go.mod h1:A2S0CWkNylc2phvKXWBBdD3K0iGnDBGbzRpISP2zBl8=

69
lib/redis.go Normal file
View File

@ -0,0 +1,69 @@
package lib
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"sync/atomic"
)
var (
rdb *redis.Client
ctx = context.Background()
counter uint64
)
// 初始化 Redis 客户端
func init() {
rdb = redis.NewClient(&redis.Options{
Addr: "127.0.0.1:6379",
Password: "WKJXXmPchENCYK7x",
DB: 2,
})
}
func GetAllLinks() ([]string, error) {
// 使用 LRange 获取整个列表,范围为 0 到 -1表示获取所有元素
links, err := rdb.LRange(ctx, "links", 0, -1).Result()
if err != nil {
return nil, err
}
return links, nil
}
// 添加链接到 Redis List
func AddLink(link string) error {
return rdb.LPush(ctx, "links", link).Err()
}
// 删除指定的链接
func DeleteLink(link string) error {
// LREM count 参数为 0 表示删除所有匹配的元素
return rdb.LRem(ctx, "links", 0, link).Err()
}
// 修改指定索引位置的链接
func UpdateLink(index int64, newLink string) error {
return rdb.LSet(ctx, "links", index, newLink).Err()
}
func GetLink() (string, error) {
length, err := rdb.LLen(ctx, "links").Result()
if err != nil || length == 0 {
return "", fmt.Errorf("no available links")
}
index := atomic.AddUint64(&counter, 1) % uint64(length)
return rdb.LIndex(ctx, "links", int64(index)).Result()
}
func ClearRedis() string {
// 清空当前数据库中的所有数据
err := rdb.FlushDB(ctx).Err()
if err != nil {
mes := fmt.Sprintf("无法清空链接: %v", err)
return mes
} else {
return "成功清空链接,请即使新增链接"
}
}

257
lib/tg.go Normal file
View File

@ -0,0 +1,257 @@
package lib
import (
"fmt"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"log"
"math/rand"
"net/url"
"strconv"
"time"
)
var (
bot *tgbotapi.BotAPI
err error
)
var userState = make(map[string]int)
var linkState = make(map[int]string)
func init() {
// 7632434434:AAG-Ac9RlLTKHnGtOSUe8_SUD8j_nDWz_AU
// bot, err = tgbotapi.NewBotAPI("7322066653:AAG3qYWH5jzAW8ZtdFEWg0Fjy0Il5FLOsg8")
bot, err = tgbotapi.NewBotAPI("7455883553:AAEwoqr6EAUZehhpJUWkhPiu4r3W-fngelE")
if err != nil {
log.Panic(err)
}
bot.Debug = true
log.Printf("Authorized on account %s", bot.Self.UserName)
//db.Test()
}
func number1() int {
rand.Seed(time.Now().UnixNano())
// 生成一个0到100之间的随机整数
randomNumber := rand.Intn(100) // 生成一个 [0, 100) 范围内的随机数
return randomNumber
}
func number2() int {
rand.Seed(time.Now().UnixNano())
// 生成一个0到100之间的随机整数
randomNumber := rand.Intn(10) // 生成一个 [0, 10) 范围内的随机数
return randomNumber
}
func Start() {
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates := bot.GetUpdatesChan(u)
for update := range updates {
if update.Message != nil { // If we got a message7227826365
//if update.Message
if update.Message.Chat.ID == 6918349523 || update.Message.Chat.ID == 7227826365 {
//if update.Message.Chat.ID == 6918349523 {
chatID := update.Message.Chat.ID
userInput := update.Message.Text
chatIDString := strconv.FormatInt(chatID, 10)
// 定义底部菜单
menu := tgbotapi.NewReplyKeyboard(
tgbotapi.NewKeyboardButtonRow(
tgbotapi.NewKeyboardButton("链接列表"),
tgbotapi.NewKeyboardButton("增加链接"),
),
tgbotapi.NewKeyboardButtonRow(
tgbotapi.NewKeyboardButton("删除链接"),
tgbotapi.NewKeyboardButton("清空链接"),
),
)
var responseText string
switch userInput {
case "链接列表":
linkList, _ := GetAllLinks()
if len(linkList) == 0 {
responseText = "No links available"
} else {
for v, link := range linkList {
vs := strconv.Itoa(v + 1)
responseText += "链接" + vs + ":\t" + link + "\n"
}
}
case "增加链接":
responseText = "请输入你要增加的链接(例: https://google.com),如果需要取消,请发送任意数字"
str := strconv.FormatInt(chatID, 10)
userState[str] = 60224466
userState[str+"_a"] = 0
userState[str+"_b"] = 0
// 隐藏键盘
removeKeyboard := tgbotapi.NewRemoveKeyboard(true)
msg := tgbotapi.NewMessage(update.Message.Chat.ID, responseText)
msg.ReplyMarkup = removeKeyboard
if _, err := bot.Send(msg); err != nil {
log.Println("Error sending message:", err)
}
continue
case "删除链接":
linkList, _ := GetAllLinks()
if len(linkList) == 0 {
responseText = "No links available"
} else {
responseText = "请发送你要删除链接的序号,如果需要取消,请发送任意数字\t()\n"
for v, link := range linkList {
vs := strconv.Itoa(v)
responseText += vs + ".\t" + link + "\n"
linkState[v] = link
}
}
str := strconv.FormatInt(chatID, 10)
userState[str] = 60224467
userState[str+"_a"] = 0
userState[str+"_b"] = 0
case "清空链接":
a := number1()
b := number2()
msgLink := fmt.Sprintf("为了您的安全输入验证: %d+%d=?", a, b)
responseText = msgLink
str := strconv.FormatInt(chatID, 10)
userState[str] = 60224465
userState[str+"_a"] = a
userState[str+"_b"] = b
default:
responseText = "请选择接下来的操作"
}
// 发送响应消息
msg := tgbotapi.NewMessage(update.Message.Chat.ID, responseText)
msg.ReplyMarkup = menu // 保持底部菜单
if _, err := bot.Send(msg); err != nil {
log.Println("Error sending message:", err)
}
// 检查用户状态
if state, exists := userState[chatIDString]; exists && state == 60224465 {
a := userState[chatIDString+"_a"] // 获取存储的 a 和 b
b := userState[chatIDString+"_b"]
// 验证用户输入
expectedAnswer := a + b
userAnswer, err := strconv.Atoi(userInput)
if err != nil {
msg := tgbotapi.NewMessage(chatID, "请输入计算结果")
inlineKeyboard := tgbotapi.NewInlineKeyboardMarkup(
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("取消清空", "Cancel"),
),
)
msg.ReplyMarkup = inlineKeyboard
bot.Send(msg)
continue
}
if userAnswer == expectedAnswer {
msg := tgbotapi.NewMessage(chatID, "验证通过!开始删除操作...")
bot.Send(msg)
msgs := tgbotapi.NewMessage(chatID, ClearRedis())
bot.Send(msgs)
delete(userState, chatIDString) // 删除状态
delete(userState, chatIDString+"_a")
delete(userState, chatIDString+"_b")
} else {
delete(userState, chatIDString) // 删除状态
delete(userState, chatIDString+"_a")
delete(userState, chatIDString+"_b")
}
} else if state, exists := userState[chatIDString]; exists && state == 60224466 {
// 增加链接
if _, err := url.ParseRequestURI(userInput); err != nil {
delete(userState, chatIDString) // 删除状态
delete(userState, chatIDString+"_a")
delete(userState, chatIDString+"_b")
} else {
AddLink(userInput)
msg := tgbotapi.NewMessage(chatID, "链接增加成功")
bot.Send(msg)
delete(userState, chatIDString) // 删除状态
delete(userState, chatIDString+"_a")
delete(userState, chatIDString+"_b")
}
} else if state, exists := userState[chatIDString]; exists && state == 60224467 {
//删除链接
num, err := strconv.Atoi(userInput)
fmt.Println(len(linkState))
if err != nil {
//msg := tgbotapi.NewMessage(chatID, "请输入序号")
//inlineKeyboard := tgbotapi.NewInlineKeyboardMarkup(
// tgbotapi.NewInlineKeyboardRow(
// tgbotapi.NewInlineKeyboardButtonData("取消删除", "Cancel"),
// ),
//)
//msg.ReplyMarkup = inlineKeyboard
//bot.Send(msg)
} else {
if len(linkState) > num && num >= 0 {
DeleteLink(linkState[num])
delete(userState, chatIDString) // 删除状态
delete(userState, chatIDString+"_a")
delete(userState, chatIDString+"_b")
for key := range linkState {
delete(linkState, key)
}
msg := tgbotapi.NewMessage(chatID, "删除成功")
bot.Send(msg)
} else {
delete(userState, chatIDString) // 删除状态
delete(userState, chatIDString+"_a")
delete(userState, chatIDString+"_b")
for key := range linkState {
delete(linkState, key)
}
}
}
} else {
//Menus(&update, "请选择你要操作的内容")
}
}
} else if update.CallbackQuery != nil { // 按钮点击事件
callback := update.CallbackQuery
log.Printf("Button clicked: %s", callback.Data)
switch callback.Data {
case "Cancel":
str := strconv.FormatInt(callback.Message.Chat.ID, 10)
delete(userState, str) // 删除状态
delete(userState, str+"_a")
delete(userState, str+"_b")
if len(linkState) > 0 {
for key := range linkState {
delete(linkState, key)
}
}
msg := tgbotapi.NewMessage(update.CallbackQuery.Message.Chat.ID, "已取消")
if _, err := bot.Send(msg); err != nil {
log.Println("Failed to send message:", err)
}
}
}
}
}

121
main.go Normal file
View File

@ -0,0 +1,121 @@
package main
import (
"fmt"
"net/http"
"randomLink/lib"
)
//type RequestData struct {
// ClientIP string `json:"clientIp"`
// UserAgent string `json:"userAgent"`
// VisitUrl string `json:"visitUrl"`
// ClientLanguage string `json:"clientLanguage"`
// Referer string `json:"referer"`
// Timestamp int64 `json:"timestamp"`
// Sign string `json:"sign"`
//}
//type Response struct {
// Code int `json:"code"`
// Message string `json:"message"`
// Data struct {
// Status bool `json:"status"`
// Message string `json:"message"`
// Jump string `json:"jump"`
// ErrorCode string `json:"errorCode"`
// Custom struct {
// WebId int `json:"webId"`
// Name string `json:"name"`
// } `json:"custom"`
// } `json:"data"`
// Success bool `json:"success"`
//}
//func getRealIP(r *http.Request) string {
// // 优先从 X-Forwarded-For 获取
// xff := r.Header.Get("X-Forwarded-For")
// if xff != "" {
// // X-Forwarded-For 可能包含多个 IP取第一个
// ips := strings.Split(xff, ",")
// return strings.TrimSpace(ips[0])
// }
//
// // 尝试从 X-Real-IP 获取
// xri := r.Header.Get("X-Real-IP")
// if xri != "" {
// return xri
// }
//
// // 最后回退到 RemoteAddr
// host, _, err := net.SplitHostPort(r.RemoteAddr)
// if err != nil {
// return r.RemoteAddr // 返回原始 RemoteAddr
// }
// return host
//}
// HTTP 跳转处理器
func redirectHandler(w http.ResponseWriter, r *http.Request) {
//data := RequestData{
// ClientIP: getRealIP(r),
// UserAgent: r.UserAgent(),
// VisitUrl: "https://app.autostock.tech" + r.URL.String(),
// ClientLanguage: r.Header.Get("Accept-Language"),
// Timestamp: time.Now().Unix(),
// Referer: r.Referer(),
// Sign: "R0QtsCttYCltUlaUYXSzj",
//}
//// 将数据编码为 JSON
//jsonData, err := json.Marshal(data)
//if err != nil {
// fmt.Println("Error marshaling JSON:", err)
// return
//}
//resp, err := http.Post("https://api-visitor.fangyu.io/check/2168/BFqEzXbIQYao3w3j5B", "application/json", bytes.NewBuffer(jsonData))
//if err != nil {
// fmt.Println("Error sending POST request:", err)
// return
//}
//defer resp.Body.Close()
//// 输出响应状态码
//fmt.Println("Response Status:", resp.Status)
//body, err := ioutil.ReadAll(resp.Body)
//fmt.Println("Response Body:", string(body))
//var response Response
//if err := json.Unmarshal([]byte(body), &response); err != nil {
// fmt.Println("Error unmarshaling JSON:", err)
//}
//fmt.Printf("Response: %+v\n", response)
//if response.Data.Status {
// link, err := lib.GetLink()
// if err != nil {
// http.Error(w, "No available links", http.StatusInternalServerError)
// return
// }
// http.Redirect(w, r, link, http.StatusFound)
//
//} else {
// http.Redirect(w, r, "https://#", http.StatusFound)
//}
link, err := lib.GetLink()
if err != nil {
http.Error(w, "No available links", http.StatusInternalServerError)
return
}
http.Redirect(w, r, link, http.StatusFound)
}
func main() {
go lib.Start()
// 启动 HTTP 服务器
http.HandleFunc("/", redirectHandler)
fmt.Println("Server is running on :8083")
if err := http.ListenAndServe(":8083", nil); err != nil {
fmt.Println("Server error:", err)
}
}