You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
3.0 KiB
132 lines
3.0 KiB
package peer |
|
|
|
import ( |
|
"context" |
|
"strings" |
|
|
|
"github.com/go-faster/errors" |
|
|
|
"github.com/gotd/td/internal/ascii" |
|
"github.com/gotd/td/telegram/internal/deeplink" |
|
"github.com/gotd/td/tg" |
|
) |
|
|
|
// Promise is a peer promise. |
|
type Promise func(ctx context.Context) (tg.InputPeerClass, error) |
|
|
|
// Resolve uses given string to create new peer promise. |
|
// It resolves peer of message using given Resolver. |
|
// Input examples: |
|
// |
|
// @telegram |
|
// telegram |
|
// t.me/telegram |
|
// https://t.me/telegram |
|
// tg:resolve?domain=telegram |
|
// tg://resolve?domain=telegram |
|
// +13115552368 |
|
// +1 (311) 555-0123 |
|
// +1 311 555-6162 |
|
// 13115556162 |
|
// |
|
func Resolve(r Resolver, from string) Promise { |
|
from = strings.TrimSpace(from) |
|
|
|
if deeplink.IsDeeplinkLike(from) { |
|
return ResolveDeeplink(r, from) |
|
} |
|
if isPhoneNumber(from) { |
|
return ResolvePhone(r, from) |
|
} |
|
|
|
return ResolveDomain(r, from) |
|
} |
|
|
|
func isPhoneNumber(s string) bool { |
|
if s == "" { |
|
return false |
|
} |
|
r := rune(s[0]) |
|
return r == '+' || ascii.IsDigit(r) |
|
} |
|
|
|
func cleanupPhone(phone string) string { |
|
clean := strings.Builder{} |
|
clean.Grow(len(phone) + 1) |
|
|
|
for _, ch := range phone { |
|
if ascii.IsDigit(ch) { |
|
clean.WriteRune(ch) |
|
} |
|
} |
|
|
|
return clean.String() |
|
} |
|
|
|
// ResolvePhone uses given phone to create new peer promise. |
|
// It resolves peer of message using given Resolver. |
|
// Input example: |
|
// |
|
// +13115552368 |
|
// +1 (311) 555-0123 |
|
// +1 311 555-6162 |
|
// 13115556162 |
|
// |
|
// Note that Telegram represents phone numbers according to the E.164 standard |
|
// without the plus sign (”+”) prefix. The resolver therefore takes an easy |
|
// route and just deletes any non-digit symbols from phone number string. |
|
func ResolvePhone(r Resolver, phone string) Promise { |
|
return func(ctx context.Context) (tg.InputPeerClass, error) { |
|
return r.ResolvePhone(ctx, cleanupPhone(phone)) |
|
} |
|
} |
|
|
|
// ResolveDomain uses given domain to create new peer promise. |
|
// It resolves peer of message using given Resolver. |
|
// Can has prefix with @ or not. |
|
// Input examples: |
|
// |
|
// @telegram |
|
// telegram |
|
// |
|
func ResolveDomain(r Resolver, domain string) Promise { |
|
return func(ctx context.Context) (tg.InputPeerClass, error) { |
|
domain = strings.TrimPrefix(domain, "@") |
|
|
|
if err := validateDomain(domain); err != nil { |
|
return nil, errors.Wrap(err, "validate domain") |
|
} |
|
|
|
return r.ResolveDomain(ctx, domain) |
|
} |
|
} |
|
|
|
func validateDomain(domain string) error { |
|
return deeplink.ValidateDomain(domain) |
|
} |
|
|
|
// ResolveDeeplink uses given deeplink to create new peer promise. |
|
// Deeplink is a URL like https://t.me/telegram. |
|
// It resolves peer of message using given Resolver. |
|
// Input examples: |
|
// |
|
// t.me/telegram |
|
// https://t.me/telegram |
|
// tg:resolve?domain=telegram |
|
// tg://resolve?domain=telegram |
|
// |
|
func ResolveDeeplink(r Resolver, u string) Promise { |
|
return func(ctx context.Context) (tg.InputPeerClass, error) { |
|
link, err := deeplink.Expect(u, deeplink.Resolve) |
|
if err != nil { |
|
return nil, err |
|
} |
|
domain := link.Args.Get("domain") |
|
|
|
if err := validateDomain(domain); err != nil { |
|
return nil, errors.Wrap(err, "validate domain") |
|
} |
|
|
|
return r.ResolveDomain(ctx, domain) |
|
} |
|
}
|
|
|