diff --git a/README.md b/README.md index 4bfcac3..5d35105 100644 --- a/README.md +++ b/README.md @@ -9,129 +9,129 @@ tgState 搭配CLoudFlare使用:https://www.csz.net/proj/tgstate/ -默认运行模式为图床模式,只允许`.jpg .png .jpeg`文件上传且限制不超过20MB,网盘模式为不限制后缀和大小 +如有疑惑,可以咨询TG @tgstate123 -支持发送文件给bot,bot返回下载地址 +# 演示 -如有疑惑,可以咨询TG @tgstate123 +https://tgstate.vercel.app / https://tgstate.ikun123.com/ -**版本说明** - - 1.2版本开始采用file_id形式留存外链,对以往版本外链不兼容,需要保留外链的谨慎更新 - - 1.1版本开始只保留/d外链,对以往版本外链不兼容,需要保留外链的谨慎更新 +搭建在vercel,资源限制,大于5MB的文件不支持 -**特性** - - 不限制上传文件大小(可选 - - 支持访问密码限制 - - 提供API - - 支持Vercel一键搭建 +演示图片: -**Demo** +![tgState](https://tgstate.vercel.app/d/BQACAgUAAx0EcyK3ugACByxlOR-Nfl4esavoO4zdaYIP_k1KYQACDAsAAkf4yFVpf_awaEkS8jAE) -实时预览:https://tgstate.vercel.app / https://tgstate.ikun123.com/ +# 参数说明 +目前必填参数为 -旧版本:https://tgtu.ikun123.com/ -搭建在Vercel,大于5MB的文件不支持 + - target + - token -测试图片: +可选参数为 -![tgState](https://tgstate.vercel.app/d/BQACAgUAAx0EcyK3ugACByxlOR-Nfl4esavoO4zdaYIP_k1KYQACDAsAAkf4yFVpf_awaEkS8jAE) + - pass + - mode + - url + - port -**准备说明** -部署前需要准备一个Telegram Bot(@botfather处申请) -如果是需要存储在频道,则需要将Bot拉入频道作为管理员,公开频道并自定义频道Link -如果储存在群组,需要将Bot拉入,公开频道并自定义频道Link +## target -后台管理 -=== +目标可为频道、群组、个人 -后台管理计划是全Telegram管理,Vercel目前不支持,目前实现的有: +当目标为频道时,需要将Bot拉入频道作为管理员,公开频道并自定义频道Link,target值填写Link,如@xxxx -获取FileID ---- +当目标为群组时,需要将Bot拉入群组,公开群组并自定义群组Link,target值填写Link,如@xxxx -对bot聊天中的文件引用并回复```get```可以获取FileID,搭建地址+/d/+FileID即可访问资源 +当目标为个人时,则为telegram id(@getmyid_bot获取) -![image](https://github.com/csznet/tgState/assets/127601663/5b1fd6c0-652c-41de-bb63-e2f20b257022) +## token +填写你的bot token -Vercel部署 -==== +## pass - [点我传送至Vercel配置页面](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fcsznet%2FtgState&env=token&env=channel&env=pass&env=mode&project-name=tgState&repository-name=tgState) +填写访问密码,如不需要,直接填写```none```即可 - 1. ```token```填写你的bot token - 2. ```channel```可以为频道(@xxxx),也可以为你的telegram id(@getmyid_bot获取) - 3. ```pass```填写访问密码,如不需要,直接填写```none```即可 - 4. ```mode```填写```pan```,代表以网盘模式运行,只需要以图床模式运行的话就随便填 +## mode - Docker部署 -==== + - ```p``` 代表网盘模式运行,不限制上传后缀 + - ```m``` 在p模式的基础上关闭网页上传,可私聊进行上传(如果target是个人,则只支持指定用户进行私聊上传 -pull镜像 -``` -docker pull csznet/tgstate:latest -``` +## url + +bot获取FileID的前置域名地址自动补充 + +## port + +自定义运行端口 + +# 管理 + +## 获取FIleID + +对bot聊天中的文件引用并回复```get```可以获取FileID,搭建地址+/d/+FileID即可访问资源 + +如果配置了url参数,会直接返回完整的地址 + +![image](https://github.com/csznet/tgState/assets/127601663/5b1fd6c0-652c-41de-bb63-e2f20b257022) + +# 部署 + +## 二进制 + +Linux amd64下载 -启动 ``` -docker run -d -p 8088:8088 --name tgstate -e TOKEN=aaa -e CHANNEL=@bbb --net=host csznet/tgstate:latest +wget https://github.com/csznet/tgState/releases/latest/download/tgState.zip && unzip tgState.zip && rm tgState.zip ``` -请提前将```aaa```和```bbb```替换为你的bot token和频道地址群组地址or个人id - -如果需要以网盘模式启动 +Linux arm64下载 ``` -docker run -d -p 8088:8088 --name tgstate -e TOKEN=aaa -e CHANNEL=@bbb -e MODE=pan csznet/tgstate:latest +wget https://github.com/csznet/tgState/releases/latest/download/tgState_arm64.zip && unzip tgState_arm64.zip && rm tgState_arm64.zip ``` +**使用方法** - 二进制部署 -==== - 下载Linux amd64环境的二进制文件 - - ``` - wget https://github.com/csznet/tgState/releases/latest/download/tgState.zip && unzip tgState.zip && rm tgState.zip - ``` +``` + ./tgState 参数 +``` -Linux arm64一键脚本: - ``` - wget https://github.com/csznet/tgState/releases/latest/download/tgState_arm64.zip && unzip tgState_arm64.zip && rm tgState_arm64.zip - ``` +**例子** +``` + ./tgState -token xxxx -target @xxxx +``` - 使用方法 ----- +**后台运行** ``` - ./tgState -token xxxx -channel @xxxx +nohup ./tgstate 参数 & ``` -其中的```xxxx```为bot token ```@xxxx```为频道地址群组地址or个人id(个人ID只需要数字不需要@) +## Docker -如果需要自定义端口,可以带上-port参数,如 +pull镜像 ``` --port 8888 +docker pull csznet/tgstate:latest ``` -如果不需要首页,只需要API和图片展示页面,则带上-index参数,如 + +启动 +``` +docker run -d -p 8088:8088 --name tgstate 参数 --net=host csznet/tgstate:latest ``` -./tgState -token xxxx -channel @xxxx -port 8888 -index -``` -如果需要限制密码访问,只需要带上-pass参数即可,如设置密码为csznet: +其中docker的参数需要设置为环境变量 +**例子** ``` -./tgState -token xxxx -channel @xxxx -port 8888 -pass csznet +docker run -d -p 8088:8088 --name tgstate -e token=aaa -e target=@bbb --net=host csznet/tgstate:latest ``` -如果需要网盘模式运行,请带上-mode pan,如 +## Vercel -``` -./tgState -token xxxx -channel @xxxx -port 8888 -mode pan -``` + [点我传送至Vercel配置页面](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fcsznet%2FtgState&env=token&env=target&env=pass&env=mode&project-name=tgState&repository-name=tgState) -关于API -==== -POST形式 +# API说明 -路径:```/api``` +POST方法到路径```/api``` -表单传输,字段名为image,内容为二进制数据 +表单传输,字段名为image,内容为二进制数据 \ No newline at end of file diff --git a/conf/conf.go b/conf/conf.go index b65316d..cf932f5 100644 --- a/conf/conf.go +++ b/conf/conf.go @@ -4,6 +4,7 @@ var BotToken string var ChannelName string var Pass string var Mode string +var BaseUrl string type UploadResponse struct { Code int `json:"code"` diff --git a/control/control.go b/control/control.go index ebf8e56..185f74e 100644 --- a/control/control.go +++ b/control/control.go @@ -34,7 +34,7 @@ func UploadImageAPI(w http.ResponseWriter, r *http.Request) { return } defer file.Close() - if conf.Mode != "pan" && r.ContentLength > 20*1024*1024 { + if conf.Mode != "p" && r.ContentLength > 20*1024*1024 { // 检查文件大小 errJsonMsg("File size exceeds 20MB limit", w) return @@ -49,7 +49,7 @@ func UploadImageAPI(w http.ResponseWriter, r *http.Request) { break } } - if conf.Mode != "pan" && !valid { + if conf.Mode != "p" && !valid { errJsonMsg("Invalid file type. Only .jpg, .jpeg, and .png are allowed.", w) // http.Error(w, "Invalid file type. Only .jpg, .jpeg, and .png are allowed.", http.StatusBadRequest) return @@ -163,7 +163,7 @@ func D(w http.ResponseWriter, r *http.Request) { // Index 首页 func Index(w http.ResponseWriter, r *http.Request) { htmlPath := "templates/images.tmpl" - if conf.Mode == "pan" { + if conf.Mode == "p" { htmlPath = "templates/files.tmpl" } file, err := assets.Templates.ReadFile(htmlPath) diff --git a/main.go b/main.go index 5aa7183..34a3c06 100644 --- a/main.go +++ b/main.go @@ -13,7 +13,7 @@ import ( ) var webPort string -var index = true +var OptApi = true func main() { //判断是否设置参数 @@ -26,12 +26,12 @@ func main() { } func web() { - if conf.Pass != "" && conf.Pass != "none" { - http.HandleFunc("/pwd", control.Pwd) - } http.HandleFunc(conf.FileRoute, control.D) - http.HandleFunc("/api", control.Middleware(control.UploadImageAPI)) - if index { + if OptApi { + if conf.Pass != "" && conf.Pass != "none" { + http.HandleFunc("/pwd", control.Pwd) + } + http.HandleFunc("/api", control.Middleware(control.UploadImageAPI)) http.HandleFunc("/", control.Middleware(control.Index)) } @@ -48,10 +48,14 @@ func web() { func init() { flag.StringVar(&webPort, "port", "8088", "Web Port") - flag.StringVar(&conf.BotToken, "token", os.Getenv("TOKEN"), "Bot Token") - flag.StringVar(&conf.ChannelName, "channel", os.Getenv("CHANNEL"), "Channel Name") - flag.StringVar(&conf.Pass, "pass", os.Getenv("PASS"), "Visit Password") - flag.StringVar(&conf.Mode, "mode", os.Getenv("MODE"), "Run mode") - flag.BoolVar(&index, "index", true, "Show Index") + flag.StringVar(&conf.BotToken, "token", os.Getenv("token"), "Bot Token") + flag.StringVar(&conf.ChannelName, "target", os.Getenv("target"), "Channel Name or ID") + flag.StringVar(&conf.Pass, "pass", os.Getenv("pass"), "Visit Password") + flag.StringVar(&conf.Mode, "mode", os.Getenv("mode"), "Run mode") + flag.StringVar(&conf.BaseUrl, "url", os.Getenv("url"), "Base Url") flag.Parse() + if conf.Mode == "m" { + OptApi = false + conf.Mode = "p" + } } diff --git a/utils/utils.go b/utils/utils.go index f5e6973..92db808 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -4,6 +4,8 @@ import ( "encoding/json" "io" "log" + "strconv" + "strings" "csz.net/tgstate/conf" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" @@ -94,9 +96,16 @@ func BotDo() { fileID = msg.ReplyToMessage.Sticker.FileID } if fileID != "" { - newMsg := tgbotapi.NewMessage(msg.Chat.ID, fileID) + newMsg := tgbotapi.NewMessage(msg.Chat.ID, conf.BaseUrl+fileID) newMsg.ReplyToMessageID = msg.MessageID - bot.Send(newMsg) + if !strings.HasPrefix(conf.ChannelName, "@") { + man, err := strconv.Atoi(conf.ChannelName) + if err == nil && newMsg.ReplyToMessageID == man { + bot.Send(newMsg) + } + } else { + bot.Send(newMsg) + } } } }