Files
MengMengCode 9fc3f1c5b8 feat: add Telegram API URL handling and version comparison utilities
- Implemented `telegramAPIURL` and `validateTelegramAPIURL` functions for constructing and validating Telegram API URLs.
- Added semantic versioning utilities in `version.go` to compare versions and validate semantic version formats.
- Created tests for version comparison logic in `version_test.go`.
- Introduced IMS call handling in `call_runtime.go`, including methods for dialing, answering, and hanging up calls.
- Added tests for incoming call handling and validation in `call_runtime_test.go`.
- Developed a new `PluginsCard` component for managing plugins via URL or file upload in the web interface.
- Implemented plugin management functions in `extensions.ts` and created an `ExtensionPage` for displaying plugin contributions.
2026-08-09 19:28:12 +08:00

66 lines
1.8 KiB
Go

package server
import (
"context"
"errors"
"net/url"
"strings"
)
const defaultTelegramBaseURL = "https://api.telegram.org"
// telegramAPIURL accepts either a Telegram API base URL or a printf-style
// endpoint template whose two %s placeholders are the bot token and method.
func telegramAPIURL(baseURL, token, method string) (*url.URL, error) {
raw := strings.TrimSpace(baseURL)
if raw == "" {
raw = defaultTelegramBaseURL
}
placeholderCount := strings.Count(raw, "%s")
if placeholderCount != 0 && placeholderCount != 2 {
return nil, errors.New("Telegram API URL must contain either no %s placeholders or exactly two")
}
if placeholderCount == 2 {
if telegramPlaceholderInAuthority(raw) {
return nil, errors.New("Telegram API URL placeholders are not allowed in the host")
}
endpoint := strings.Replace(raw, "%s", token, 1)
endpoint = strings.Replace(endpoint, "%s", method, 1)
return parseOutboundURL(endpoint, true)
}
parsed, err := parseOutboundURL(raw, true)
if err != nil {
return nil, err
}
parsed.Path = strings.TrimRight(parsed.Path, "/") + "/bot" + token + "/" + method
parsed.RawPath = ""
parsed.RawQuery = ""
parsed.Fragment = ""
return parsed, nil
}
func validateTelegramAPIURL(ctx context.Context, baseURL, token, method string) (*url.URL, error) {
parsed, err := telegramAPIURL(baseURL, token, method)
if err != nil {
return nil, err
}
if _, err := resolvePublicAddresses(ctx, parsed.Hostname()); err != nil {
return nil, err
}
return parsed, nil
}
func telegramPlaceholderInAuthority(raw string) bool {
schemeEnd := strings.Index(raw, "://")
if schemeEnd < 0 {
return false
}
authority := raw[schemeEnd+3:]
if end := strings.IndexAny(authority, "/?#"); end >= 0 {
authority = authority[:end]
}
return strings.Contains(authority, "%s")
}