Highly-opinionated (ex-bullshit-free) MTPROTO proxy for Telegram. If you use v1.0 or upgrade broke you proxy, please read the chapter Version 2
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

telegram.go 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. package telegram
  2. import (
  3. "context"
  4. "fmt"
  5. "strings"
  6. "sync"
  7. "time"
  8. "github.com/9seconds/mtg/v2/essentials"
  9. "github.com/gotd/td/telegram"
  10. )
  11. type Telegram struct {
  12. ctx context.Context
  13. ctxCancel context.CancelFunc
  14. lock sync.RWMutex
  15. dialer Dialer
  16. preferIP preferIP
  17. addresses dcAddresses
  18. rpc rpcClient
  19. }
  20. func (t *Telegram) Dial(ctx context.Context, dc int) (essentials.Conn, error) {
  21. var addresses []tgAddr
  22. t.lock.RLock()
  23. switch t.preferIP {
  24. case preferIPOnlyIPv4:
  25. addresses = t.addresses.getV4(dc)
  26. case preferIPOnlyIPv6:
  27. addresses = t.addresses.getV6(dc)
  28. case preferIPPreferIPv4:
  29. addresses = append(t.addresses.getV4(dc), t.addresses.getV6(dc)...)
  30. case preferIPPreferIPv6:
  31. addresses = append(t.addresses.getV6(dc), t.addresses.getV4(dc)...)
  32. }
  33. t.lock.RUnlock()
  34. var conn essentials.Conn
  35. err := errNoAddresses
  36. for _, v := range addresses {
  37. conn, err = t.dialer.DialContext(ctx, v.network, v.address)
  38. if err == nil {
  39. return conn, nil
  40. }
  41. }
  42. return nil, fmt.Errorf("cannot dial to %d dc: %w", dc, err)
  43. }
  44. func (t *Telegram) IsKnownDC(dc int) bool {
  45. return t.addresses.isValidDC(dc)
  46. }
  47. func (t *Telegram) GetFallbackDC() int {
  48. return defaultDC
  49. }
  50. func (t *Telegram) Shutdown() {
  51. t.ctxCancel()
  52. }
  53. func (t *Telegram) Run(logger loggerInterface, updateEach time.Duration) {
  54. if updateEach == 0 {
  55. updateEach = defaultUpdateDCAddressesEach
  56. }
  57. t.update(logger)
  58. ticker := time.NewTicker(updateEach)
  59. defer func() {
  60. ticker.Stop()
  61. select {
  62. case <-ticker.C:
  63. default:
  64. }
  65. }()
  66. for {
  67. select {
  68. case <-t.ctx.Done():
  69. return
  70. case <-ticker.C:
  71. t.update(logger)
  72. }
  73. }
  74. }
  75. func (t *Telegram) update(logger loggerInterface) {
  76. otherAddresses, err := t.rpc.getDCAddresses(logger, t.ctx)
  77. if err != nil {
  78. logger.WarningError("Cannot update DC list", err)
  79. return
  80. }
  81. t.lock.Lock()
  82. t.addresses = otherAddresses
  83. t.lock.Unlock()
  84. logger.Info(fmt.Sprintf("DC are updated: %v", t.addresses))
  85. }
  86. func New(dialer Dialer, ipPreference string) (*Telegram, error) {
  87. var pref preferIP
  88. switch strings.ToLower(ipPreference) {
  89. case "prefer-ipv4":
  90. pref = preferIPPreferIPv4
  91. case "prefer-ipv6":
  92. pref = preferIPPreferIPv6
  93. case "only-ipv4":
  94. pref = preferIPOnlyIPv4
  95. case "only-ipv6":
  96. pref = preferIPOnlyIPv6
  97. default:
  98. return nil, fmt.Errorf("unknown ip preference %s", ipPreference)
  99. }
  100. ctx, cancel := context.WithCancel(context.Background())
  101. return &Telegram{
  102. ctx: ctx,
  103. ctxCancel: cancel,
  104. dialer: dialer,
  105. preferIP: pref,
  106. addresses: dcAddresses{
  107. v4: defaultV4Addresses,
  108. v6: defaultV6Addresses,
  109. },
  110. rpc: rpcClient{
  111. Client: telegram.NewClient(defaultAppID, defaultAppHash, telegram.Options{}),
  112. },
  113. }, nil
  114. }