7a04f298d2
- update to latest telegram layer - remove some references to fields in tg.Entities that don't exist in the schema - originally added here: https://github.com/beeper/td/commit/820929062a2ba0104397bc01235ab58a9cff780e - referenced here - https://github.com/mautrix/telegramgo/commit/124f0967ed195b5a380c9bd02e170ada9710dde3 - https://github.com/mautrix/telegramgo/commit/4205047aab2e0639217148b5d125bfaab668bd8e
153 lines
2.9 KiB
Go
153 lines
2.9 KiB
Go
// Package tgerr implements helpers for error handling.
|
|
package tgerr
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/go-faster/errors"
|
|
|
|
"go.mau.fi/mautrix-telegram/pkg/gotd/ascii"
|
|
)
|
|
|
|
// Error represents RPC error returned as result to request.
|
|
type Error struct {
|
|
Code int // 420
|
|
Message string // FLOOD_WAIT_3
|
|
Type string // FLOOD_WAIT
|
|
Argument int // 3
|
|
}
|
|
|
|
// New creates new *Error from code and message, extracting argument
|
|
// and type.
|
|
func New(code int, msg string) *Error {
|
|
e := &Error{
|
|
Code: code,
|
|
Message: msg,
|
|
}
|
|
e.extractArgument()
|
|
return e
|
|
}
|
|
|
|
// IsType reports whether error has type t.
|
|
func (e *Error) IsType(t string) bool {
|
|
if e == nil {
|
|
return false
|
|
}
|
|
return e.Type == t
|
|
}
|
|
|
|
// IsCode reports whether error Code is equal to code.
|
|
func (e *Error) IsCode(code int) bool {
|
|
if e == nil {
|
|
return false
|
|
}
|
|
return e.Code == code
|
|
}
|
|
|
|
// IsOneOf returns true if error type is in tt.
|
|
func (e *Error) IsOneOf(tt ...string) bool {
|
|
if e == nil {
|
|
return false
|
|
}
|
|
for _, t := range tt {
|
|
if e.IsType(t) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IsCodeOneOf returns true if error code is one of codes.
|
|
func (e *Error) IsCodeOneOf(codes ...int) bool {
|
|
if e == nil {
|
|
return false
|
|
}
|
|
for _, code := range codes {
|
|
if e.IsCode(code) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// extractArgument extracts Type and Argument from Message.
|
|
func (e *Error) extractArgument() {
|
|
if e.Message == "" {
|
|
return
|
|
}
|
|
|
|
// Defaulting Type to Message.
|
|
e.Type = e.Message
|
|
|
|
// Splitting by underscore.
|
|
parts := strings.Split(e.Message, "_")
|
|
if len(parts) < 2 {
|
|
return
|
|
}
|
|
|
|
var nonDigit []string
|
|
Parts:
|
|
for _, part := range parts {
|
|
for _, r := range part {
|
|
if ascii.IsDigit(r) {
|
|
continue
|
|
}
|
|
|
|
// Found non-digit part, skipping.
|
|
nonDigit = append(nonDigit, part)
|
|
continue Parts
|
|
}
|
|
|
|
// Found digit-only part, using as argument.
|
|
argument, err := strconv.Atoi(part)
|
|
if err != nil {
|
|
// Should be unreachable.
|
|
return
|
|
}
|
|
e.Argument = argument
|
|
}
|
|
|
|
e.Type = strings.Join(nonDigit, "_")
|
|
}
|
|
|
|
func (e *Error) Error() string {
|
|
if e.Type != e.Message {
|
|
return fmt.Sprintf("rpc error code %d: %s (%d)", e.Code, e.Type, e.Argument)
|
|
}
|
|
return fmt.Sprintf("rpc error code %d: %s", e.Code, e.Message)
|
|
}
|
|
|
|
// AsType returns *Error from err if rpc error type is t.
|
|
func AsType(err error, t string) (rpcErr *Error, ok bool) {
|
|
if errors.As(err, &rpcErr) && rpcErr.Type == t {
|
|
return rpcErr, true
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
// As extracts *Error from err if possible.
|
|
func As(err error) (rpcErr *Error, ok bool) {
|
|
if errors.As(err, &rpcErr) {
|
|
return rpcErr, true
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
// Is returns true if err type is t.
|
|
func Is(err error, tt ...string) bool {
|
|
if rpcErr, ok := As(err); ok {
|
|
return rpcErr.IsOneOf(tt...)
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IsCode returns true of error code is as provided.
|
|
func IsCode(err error, code ...int) bool {
|
|
if rpcErr, ok := As(err); ok {
|
|
return rpcErr.IsCodeOneOf(code...)
|
|
}
|
|
return false
|
|
}
|