go-tg-screenshot-bot

Форк
0
159 строк · 5.4 Кб
1
package main
2

3
import (
4
	"bytes"
5
	"flag"
6
	"fmt"
7
	"image/png"
8
	"log"
9
	"net/http"
10
	"strconv"
11
	"time"
12

13
	tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
14
	"github.com/kbinani/screenshot"
15
)
16

17
// Структура application содержит конфигурацию и экземпляр бота Telegram.
18
type application struct {
19
	config struct {
20
		token   string // Токен для Telegram API
21
		debug   bool   // Режим отладки
22
		webPort string // Порт для веб-сервера
23
	}
24
	tgBot *tgbotapi.BotAPI // Экземпляр бота Telegram
25
}
26

27
func main() {
28
	// Конфигурация приложения
29
	app := configure()
30

31
	// Запуск прослушивания сообщений Telegram в отдельной горутине
32
	go listenTg(app)
33

34
	// Запуск веб-сервера в отдельной горутине
35
	go listenWeb(app)
36

37
	// Блокировка основного потока, чтобы программа продолжала работать
38
	select {}
39
}
40

41
// configure настраивает приложение и возвращает его экземпляр.
42
func configure() *application {
43
	// Определение флагов командной строки
44
	token := flag.String("token", "Token", "Enter telegram token")
45
	debug := flag.Bool("debug", false, "Debug mode")
46
	port := flag.String("port", "8080", "Web port")
47
	flag.Parse()
48

49
	// Создание нового бота Telegram
50
	bot, err := tgbotapi.NewBotAPI(*token)
51
	if err != nil {
52
		log.Panic(err)
53
	}
54
	bot.Debug = *debug
55
	log.Printf("Authorized on account %s", bot.Self.UserName)
56

57
	// Возврат настроенного экземпляра приложения
58
	return &application{
59
		config: struct {
60
			token   string
61
			debug   bool
62
			webPort string
63
		}{
64
			token:   *token,
65
			debug:   *debug,
66
			webPort: *port,
67
		},
68
		tgBot: bot,
69
	}
70
}
71

72
// listenTg обрабатывает входящие сообщения Telegram.
73
func listenTg(app *application) {
74
	u := tgbotapi.NewUpdate(0)
75
	u.Timeout = 60
76

77
	// Получаем канал для чтения обновлений от Telegram
78
	updates := app.tgBot.GetUpdatesChan(u)
79

80
	// Обработка каждого обновления
81
	for update := range updates {
82
		if update.Message == nil {
83
			return
84
		}
85

86
		// Запускаем обработку сообщения в новой горутине
87
		go func() {
88
			disNum, _ := strconv.Atoi(update.Message.Text) // Преобразование текста сообщения в номер дисплея
89
			fileName, buf := screen(disNum)                // Захват экрана
90

91
			// Подготовка сообщения с изображением для отправки
92
			msg := tgbotapi.PhotoConfig{
93
				BaseFile: tgbotapi.BaseFile{
94
					BaseChat: tgbotapi.BaseChat{
95
						ChatID: update.Message.From.ID,
96
					},
97
					File: tgbotapi.FileReader{
98
						Name:   fileName,
99
						Reader: buf,
100
					},
101
				},
102
			}
103
			app.tgBot.Send(&msg) // Отправка сообщения
104
		}()
105
	}
106
}
107

108
// screen выполняет захват экрана для указанного дисплея и возвращает имя файла и буфер с изображением.
109
func screen(disNum int) (string, *bytes.Buffer) {
110
	bounds := screenshot.GetDisplayBounds(disNum) // Получение границ дисплея
111
	img, err := screenshot.CaptureRect(bounds)    // Захват изображения экрана
112
	if err != nil {
113
		// Попытка повторного захвата экрана до 5 раз при ошибке
114
		for i := 0; i < 5; i++ {
115
			fmt.Printf("Error while capture rect %s. Trying again\n", err.Error())
116
			time.Sleep(1 * time.Second)
117
			bounds = screenshot.GetDisplayBounds(disNum)
118
			img, err = screenshot.CaptureRect(bounds)
119
			if err == nil {
120
				break
121
			}
122
		}
123
		if err != nil {
124
			fmt.Printf("Error while capture rect %s\n", err.Error())
125
			return "", nil
126
		}
127
	}
128
	// Формирование имени файла
129
	fileName := fmt.Sprintf("%d_%dx%d.png", disNum, bounds.Dx(), bounds.Dy())
130
	var buf bytes.Buffer
131
	png.Encode(&buf, img) // Кодирование изображения в PNG и запись в буфер
132
	fmt.Printf("#%d : %v \"%s\"\n", disNum, bounds, fileName)
133
	return fileName, &buf
134
}
135

136
// listenWeb запускает веб-сервер и обрабатывает HTTP-запросы.
137
func listenWeb(app *application) {
138
	// Обработчик для главной страницы
139
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
140
		displayNumberStr := r.URL.Query().Get("d")  // Получение параметра "d" из запроса
141
		disNum, _ := strconv.Atoi(displayNumberStr) // Преобразование параметра в номер дисплея
142
		_, buf := screen(disNum)                    // Захват экрана
143

144
		// Устанавливаем заголовки ответа
145
		w.Header().Set("Content-Type", "image/png")
146
		w.Header().Set("Content-Length", strconv.Itoa(len(buf.Bytes())))
147

148
		// Отправляем изображение в ответе
149
		if _, err := w.Write(buf.Bytes()); err != nil {
150
			log.Printf("Failed to write image to response: %v", err)
151
		}
152
	})
153

154
	// Запуск веб-сервера на указанном порту
155
	fmt.Printf("Starting web server on %s", app.config.webPort)
156
	if err := http.ListenAndServe(":"+app.config.webPort, nil); err != nil {
157
		log.Fatalf("Server failed to start: %v", err)
158
	}
159
}
160

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.