Telegram-клиент на Golang

Kate

Administrator
Команда форума
Работая разработчиком в одной веб-студии, пришел клиент с довольно интересной работкой, ему нужен был агрегатор постов из чужих телеграм каналов, так как стек в компании был PHP то решили писать на нем, а конкретно на библиотеке MadelineProto о которой уже есть статья от крутого парня (более подробно об этой либе можете почитать в его статье), вот и началось мучительно создание этого сервиса...

Madeline в общей массе свой очень хорошо, полностью асинхронный и имет под капотом кучу методов для работы как с ботами так и с клиентом, но есть у него одна маленькая проблема (а может и не одна ¯\_(ツ)_/¯) , встроенный EventHandler получает не все новые сообщения из постов (и да я понимаю что есть getHistory, но если бы мы брали сообщения через этот метод, все вышло бы очень медленно работающим и высоконагруженным) Долгие часы и даже дни поиска решения этой проблемы не привели к желаемому результату, все так же процент постов которые пропускались именно Madeline был слишком большим.

Ок, было принято волевое решение забить на данную библиотеку и попробовать найти что-то другое на известном нам стеке, взгляд упал на go-tdlib. Развернули либу и поехали пыхтеть в разработку, и о чудо все посты собираются и все стало чудесно, за исключением одного но... Данная библиотека от пользователя Arman92 сильно отстает от офф методов tdlib и имеет внутри несколько логических ошибок, в общем начали у нас сыпаться паники и другие неприятные вещи. Так как пути назад уже не было, перебрали мы всю либу и обновили методы а так же исправили ошибки и теперь все просто чудесно.

Цель статьи — в первую очередь привлечь внимание к работе с телеграмм на Golang и рассказать про проблемы Madeline о которых нигде не узнать. Ну и соответственну приведу кусочек кода EventHandler'а для большей ясности.

func restoreSessions(client *tdlib.Client) {
log.Println("<<<<<<<<<<<<<<<<<<<<<<<<<<RestoreSessionLog>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
rdb := redis.NewClient(&redis.Options{
Addr: "redis:6379",
Password: "", // no password set
DB: 0, // use default DB
})

pong, err := rdb.Ping().Result()
if err == nil {
log.Println("1.Redis connections:" + pong + " - Redis ready")
log.Println("1.1 redis connections successful")
}
log.Println("2. authorization client tdlib ")
go func() {
log.Println("2.1 timeout 6 sec")
time.Sleep(6 * time.Second)
currentState, err := client.Authorize()
if err != nil {
log.Println("2.2 err client authorization ")
log.Println(err)
}
for ; currentState.GetAuthorizationStateEnum() != tdlib.AuthorizationStateReadyType; currentState, _ = client.Authorize() {
time.Sleep(300 * time.Millisecond)
}

eventFilter := func(msg *tdlib.TdMessage) bool {
return true
}
log.Println("2.2 authorization client successful ")
log.Println("2.3 get info session client ")
//cid - ID юзера в тг
user, err := client.GetMe()
if err == nil {
log.Println("2.4 get info session client successful")
}else {
log.Println("2.4 get info session client finished with error:")
log.Println(err)
}
cid := user.ID

/**
Выписываю редис лист, если что можно позырить записывает ли он
*/
log.Println("2.5 redis list for message:")
log.Println("2.5 Redis List ---- " + "gotdlibMessage-" + strconv.Itoa(int(cid)) + " ---- Redis List")

receiver := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, eventFilter, 5)
log.Println("2.6 handle message")
for newMsg := range receiver.Chan {
updateMsg := (newMsg).(*tdlib.UpdateNewMessage)

if updateMsg.Message.Content.GetMessageContentEnum() == "messagePhoto" {
log.Println("2.7 new message with type: messagePhoto")
go messagePhoto(updateMsg, newMsg, rdb, cid,client)
}

if updateMsg.Message.Content.GetMessageContentEnum() == "messageText" {
log.Println("2.7 new message with type: messageText")
go messageText(updateMsg, rdb, cid,client)
}

if updateMsg.Message.Content.GetMessageContentEnum() == "messageVideo" {
log.Println("2.7 new message with type: messageVideo")
go messageVideo(updateMsg, rdb, cid,client)
}

if updateMsg.Message.Content.GetMessageContentEnum() == "messageDocument" {
log.Println("2.7 new message with type: messageDocument")
go messageDocument(updateMsg, rdb, cid,client)
}
}
}()
}

P.S: Доработанную и актуальную либу на 01.08.2021 (Может и дальше буду обновлять) вы можете взять у меня на гите — git

 
Сверху