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.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package dc
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "strconv"
  7. "strings"
  8. "sync"
  9. "time"
  10. "github.com/gotd/td/telegram"
  11. )
  12. type Telegram struct {
  13. logger Logger
  14. lock sync.RWMutex
  15. view dcView
  16. preferIP preferIP
  17. client *telegram.Client
  18. }
  19. func (t *Telegram) GetAddresses(dc int) []Addr {
  20. t.lock.RLock()
  21. defer t.lock.RUnlock()
  22. switch t.preferIP {
  23. case preferIPOnlyIPv4:
  24. return t.view.getV4(dc)
  25. case preferIPOnlyIPv6:
  26. return t.view.getV4(dc)
  27. case preferIPPreferIPv4:
  28. return append(t.view.getV4(dc), t.view.getV6(dc)...)
  29. }
  30. return append(t.view.getV6(dc), t.view.getV4(dc)...)
  31. }
  32. func (t *Telegram) Run(ctx context.Context, updateEach time.Duration) {
  33. t.update(ctx)
  34. ticker := time.NewTicker(updateEach)
  35. defer func() {
  36. ticker.Stop()
  37. select {
  38. case <-ctx.Done():
  39. case <-ticker.C:
  40. default:
  41. }
  42. }()
  43. for {
  44. select {
  45. case <-ctx.Done():
  46. return
  47. case <-ticker.C:
  48. t.update(ctx)
  49. }
  50. }
  51. }
  52. func (t *Telegram) update(ctx context.Context) {
  53. collected := dcAddrSet{
  54. v4: map[int][]Addr{},
  55. v6: map[int][]Addr{},
  56. }
  57. err := t.client.Run(ctx, func(tgctx context.Context) error {
  58. conf, err := t.client.API().HelpGetConfig(tgctx)
  59. if err != nil {
  60. return err
  61. }
  62. for _, opt := range conf.DCOptions {
  63. addr := net.JoinHostPort(opt.IPAddress, strconv.Itoa(opt.Port))
  64. if opt.Ipv6 {
  65. collected.v6[opt.ID] = append(collected.v6[opt.ID], Addr{
  66. Network: "tcp6",
  67. Address: addr,
  68. })
  69. } else {
  70. collected.v4[opt.ID] = append(collected.v4[opt.ID], Addr{
  71. Network: "tcp4",
  72. Address: addr,
  73. })
  74. }
  75. }
  76. return nil
  77. })
  78. if err != nil {
  79. t.logger.WarningError("update has failed", err)
  80. return
  81. }
  82. t.lock.Lock()
  83. t.view.collected = collected
  84. t.lock.Unlock()
  85. t.logger.Info(fmt.Sprintf("updated DC list: %v", collected))
  86. }
  87. func New(logger Logger, ipPreference string, userOverrides map[int][]string) (*Telegram, error) {
  88. var pref preferIP
  89. switch strings.ToLower(ipPreference) {
  90. case "prefer-ipv4":
  91. pref = preferIPPreferIPv4
  92. case "prefer-ipv6":
  93. pref = preferIPPreferIPv6
  94. case "only-ipv4":
  95. pref = preferIPOnlyIPv4
  96. case "only-ipv6":
  97. pref = preferIPOnlyIPv6
  98. default:
  99. return nil, fmt.Errorf("unknown ip preference %s", ipPreference)
  100. }
  101. overrides := dcAddrSet{}
  102. for dc, addrs := range userOverrides {
  103. for _, addr := range addrs {
  104. host, _, err := net.SplitHostPort(addr)
  105. if err != nil {
  106. return nil, fmt.Errorf("incorrect host %s: %w", addr, err)
  107. }
  108. parsed := net.ParseIP(host)
  109. if parsed == nil {
  110. return nil, fmt.Errorf("incorrect host %s", addr)
  111. }
  112. if parsed.To4() != nil {
  113. overrides.v4[dc] = append(overrides.v4[dc], Addr{
  114. Network: "tcp4",
  115. Address: addr,
  116. })
  117. } else {
  118. overrides.v6[dc] = append(overrides.v6[dc], Addr{
  119. Network: "tcp6",
  120. Address: addr,
  121. })
  122. }
  123. }
  124. }
  125. return &Telegram{
  126. view: dcView{
  127. overrides: overrides,
  128. },
  129. logger: logger,
  130. client: telegram.NewClient(defaultAppID, defaultAppHash, telegram.Options{}),
  131. preferIP: pref,
  132. }, nil
  133. }