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
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package proxy
  2. import (
  3. "encoding/json"
  4. "net"
  5. "net/http"
  6. "net/url"
  7. "strconv"
  8. "sync/atomic"
  9. "time"
  10. )
  11. type statsUptime time.Time
  12. func (s statsUptime) MarshalJSON() ([]byte, error) {
  13. uptime := int(time.Since(time.Time(s)).Seconds())
  14. return []byte(strconv.Itoa(uptime)), nil
  15. }
  16. type Stats struct {
  17. AllConnections uint64 `json:"all_connections"`
  18. ActiveConnections uint32 `json:"active_connections"`
  19. Traffic struct {
  20. Incoming uint64 `json:"incoming"`
  21. Outgoing uint64 `json:"outgoing"`
  22. } `json:"traffic"`
  23. URLs struct {
  24. TG string `json:"tg_url"`
  25. TMe string `json:"tme_url"`
  26. TGQRCode string `json:"tg_qrcode"`
  27. TMeQRCode string `json:"tme_qrcode"`
  28. } `json:"urls"`
  29. Uptime statsUptime `json:"uptime"`
  30. }
  31. func (s *Stats) newConnection() {
  32. atomic.AddUint64(&s.AllConnections, 1)
  33. atomic.AddUint32(&s.ActiveConnections, 1)
  34. }
  35. func (s *Stats) closeConnection() {
  36. atomic.AddUint32(&s.ActiveConnections, ^uint32(0))
  37. }
  38. func (s *Stats) addIncomingTraffic(n int) {
  39. atomic.AddUint64(&s.Traffic.Incoming, uint64(n))
  40. }
  41. func (s *Stats) addOutgoingTraffic(n int) {
  42. atomic.AddUint64(&s.Traffic.Outgoing, uint64(n))
  43. }
  44. func (s *Stats) Serve(host net.IP, port uint16) {
  45. http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  46. w.Header().Set("Content-Type", "application/json")
  47. encoder := json.NewEncoder(w)
  48. encoder.SetEscapeHTML(false)
  49. encoder.SetIndent("", " ")
  50. encoder.Encode(s)
  51. })
  52. addr := net.JoinHostPort(host.String(), strconv.Itoa(int(port)))
  53. http.ListenAndServe(addr, nil)
  54. }
  55. func NewStats(serverName string, port uint16, secret string) *Stats {
  56. urlQuery := makeURLQuery(serverName, port, secret)
  57. stat := &Stats{Uptime: statsUptime(time.Now())}
  58. stat.URLs.TG = makeTGURL(urlQuery)
  59. stat.URLs.TMe = makeTMeURL(urlQuery)
  60. stat.URLs.TGQRCode = makeQRCodeURL(stat.URLs.TG)
  61. stat.URLs.TMeQRCode = makeQRCodeURL(stat.URLs.TMe)
  62. return stat
  63. }
  64. func makeURLQuery(serverName string, port uint16, secret string) url.Values {
  65. values := url.Values{}
  66. values.Set("server", serverName)
  67. values.Set("port", strconv.Itoa(int(port)))
  68. values.Set("secret", secret)
  69. return values
  70. }
  71. func makeTGURL(values url.Values) string {
  72. tgURL := url.URL{
  73. Scheme: "tg",
  74. Host: "proxy",
  75. RawQuery: values.Encode(),
  76. }
  77. return tgURL.String()
  78. }
  79. func makeTMeURL(values url.Values) string {
  80. tMeURL := url.URL{
  81. Scheme: "https",
  82. Host: "t.me",
  83. Path: "proxy",
  84. RawQuery: values.Encode(),
  85. }
  86. return tMeURL.String()
  87. }
  88. func makeQRCodeURL(data string) string {
  89. QRURL := url.URL{
  90. Scheme: "https",
  91. Host: "api.qrserver.com",
  92. Path: "v1/create-qr-code",
  93. }
  94. values := url.Values{}
  95. values.Set("qzone", "4")
  96. values.Set("format", "svg")
  97. values.Set("data", data)
  98. QRURL.RawQuery = values.Encode()
  99. return QRURL.String()
  100. }