diff --git a/api/system_setting.go b/api/system_setting.go index f89351aa..5e23e711 100644 --- a/api/system_setting.go +++ b/api/system_setting.go @@ -182,6 +182,14 @@ func (upsert SystemSettingUpsert) Validate() error { if upsert.Value == "" { return nil } + // Robot Token with Reverse Proxy shoule like `http.../bot` + if strings.HasPrefix(upsert.Value, "http") { + slashIndex := strings.LastIndexAny(upsert.Value, "/") + if strings.HasPrefix(upsert.Value[slashIndex:], "/bot") { + return nil + } + return fmt.Errorf("token start with `http` must end with `/bot`") + } fragments := strings.Split(upsert.Value, ":") if len(fragments) != 2 { return fmt.Errorf(systemSettingUnmarshalError, settingName) diff --git a/plugin/telegram/download.go b/plugin/telegram/download.go index d71b10a6..b04ab3d3 100644 --- a/plugin/telegram/download.go +++ b/plugin/telegram/download.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "net/http" + "strings" ) // downloadFileId download file with fileID, return the filepath and blob. @@ -23,13 +24,19 @@ func (r *Robot) downloadFileID(ctx context.Context, fileID string) (string, []by // downloadFilepath download file with filepath, you can get filepath by calling GetFile. func (r *Robot) downloadFilepath(ctx context.Context, filePath string) ([]byte, error) { - token := r.handler.RobotToken(ctx) - if token == "" { - return nil, ErrNoToken + apiURL, err := r.apiURL(ctx) + if err != nil { + return nil, err } - uri := "https://api.telegram.org/file/bot" + token + "/" + filePath - resp, err := http.Get(uri) + idx := strings.LastIndex(apiURL, "/bot") + if idx < 0 { + return nil, ErrInvalidToken + } + + fileURL := apiURL[:idx] + "/file" + apiURL[idx:] + + resp, err := http.Get(fileURL + "/" + filePath) if err != nil { return nil, fmt.Errorf("fail to http.Get: %s", err) } diff --git a/plugin/telegram/request.go b/plugin/telegram/request.go index 21e3e48a..5c905154 100644 --- a/plugin/telegram/request.go +++ b/plugin/telegram/request.go @@ -3,23 +3,19 @@ package telegram import ( "context" "encoding/json" - "errors" "fmt" "io" "net/http" "net/url" ) -var ErrNoToken = errors.New("token is empty") - func (r *Robot) postForm(ctx context.Context, apiPath string, formData url.Values, result any) error { - token := r.handler.RobotToken(ctx) - if token == "" { - return ErrNoToken + apiURL, err := r.apiURL(ctx) + if err != nil { + return err } - uri := "https://api.telegram.org/bot" + token + apiPath - resp, err := http.PostForm(uri, formData) + resp, err := http.PostForm(apiURL+apiPath, formData) if err != nil { return fmt.Errorf("fail to http.PostForm: %s", err) } diff --git a/plugin/telegram/robot.go b/plugin/telegram/robot.go index aa114cda..df93edae 100644 --- a/plugin/telegram/robot.go +++ b/plugin/telegram/robot.go @@ -2,7 +2,9 @@ package telegram import ( "context" + "errors" "fmt" + "strings" "time" "github.com/usememos/memos/common/log" @@ -32,7 +34,7 @@ func (r *Robot) Start(ctx context.Context) { for { updates, err := r.GetUpdates(ctx, offset) - if err == ErrNoToken { + if err == ErrInvalidToken { time.Sleep(noTokenWait) continue } @@ -79,3 +81,18 @@ func (r *Robot) Start(ctx context.Context) { } } } + +var ErrInvalidToken = errors.New("token is invalid") + +func (r *Robot) apiURL(ctx context.Context) (string, error) { + token := r.handler.RobotToken(ctx) + if token == "" { + return "", ErrInvalidToken + } + + if strings.HasPrefix(token, "http") { + return token, nil + } + + return "https://api.telegram.org/bot" + token, nil +} diff --git a/web/src/components/Settings/SystemSection.tsx b/web/src/components/Settings/SystemSection.tsx index eb1666d5..5e3ad5e0 100644 --- a/web/src/components/Settings/SystemSection.tsx +++ b/web/src/components/Settings/SystemSection.tsx @@ -293,7 +293,10 @@ const SystemSection = () => {
{t("setting.system-section.telegram-robot-token")} - +
diff --git a/web/src/locales/en.json b/web/src/locales/en.json index acbfc1af..dd5ed178 100644 --- a/web/src/locales/en.json +++ b/web/src/locales/en.json @@ -259,7 +259,7 @@ "additional-style-placeholder": "Additional CSS code", "additional-script-placeholder": "Additional JavaScript code", "telegram-robot-token": "Telegram Robot Token", - "telegram-robot-token-description": "Get from @BotFather of Telegram", + "telegram-robot-token-description": "Telegram Robot Token or API Proxy like `http.../bot`", "telegram-robot-token-placeholder": "Your Telegram Robot token", "openai-api-key": "OpenAI: API Key", "openai-api-key-description": "Get API key", diff --git a/web/src/locales/zh-Hans.json b/web/src/locales/zh-Hans.json index 8ad269f7..84a0e8b8 100644 --- a/web/src/locales/zh-Hans.json +++ b/web/src/locales/zh-Hans.json @@ -412,6 +412,7 @@ "ignore-version-upgrade": "忽略版本升级", "telegram-robot-token": "Telegram 机器人 Token", "telegram-robot-token-description": "从 Telegram 的 @BotFather 处获取", + "telegram-robot-token-description": "Telegram 机器人Token或`http.../bot`格式的代理地址", "telegram-robot-token-placeholder": "Telegram 的机器人 Token", "openai-api-host": "OpenAI:API Host", "openai-api-host-placeholder": "默认:https://api.openai.com/",