diff --git a/README.md b/README.md index e749587..e6769d2 100644 --- a/README.md +++ b/README.md @@ -1 +1,14 @@ -## Fork for [modded TDLib](https://github.com/c0re100/td) +## Forked library for [modded TDLib](https://github.com/c0re100/td) + +When I'm refactoring my own bot from `Arman92/go-tdlib` to `zelenin/go-tdlib ` + +I realized that zelenin's library doesn't meet my need😕 + +So I fork it and make some changes + +1. Static build by default +2. Add update event filter +3. Add command parser +4. Receive correct message id to patch text/dice message response. + +[Here](example) are a few example codes about how to use **c0re100/gotdlib**. \ No newline at end of file diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..5635bf4 --- /dev/null +++ b/example/README.md @@ -0,0 +1,17 @@ +## Example + +### Bot +Login to bot account. + +### Command +Handle user command and reply it. + +### Event Filter +Since we can have many update type in updates. +So we need to filter update events, like UpdateNewMessage, UpdateMessageSendSucceeded, UpdateMessageSendFailed, etc. + +### Media +Send photo or album to chat. + +### Raw Update +Get update without event filter. \ No newline at end of file diff --git a/example/bot/Bot.go b/example/bot/Bot.go new file mode 100644 index 0000000..53e10f1 --- /dev/null +++ b/example/bot/Bot.go @@ -0,0 +1,102 @@ +package main + +import ( + "log" + "os" + "os/signal" + "syscall" + + tdlib "github.com/c0re100/gotdlib/client" +) + +func GetTdParameters() *tdlib.TdlibParameters { + return &tdlib.TdlibParameters{ + UseTestDc: false, + DatabaseDirectory: "./tdlib-db", + FilesDirectory: "./tdlib-files", + UseFileDatabase: true, + UseChatInfoDatabase: true, + UseMessageDatabase: true, + UseSecretChats: false, + ApiId: 132712, + ApiHash: "e82c07ad653399a37baca8d1e498e472", + SystemLanguageCode: "en", + DeviceModel: "HuskyNG", + SystemVersion: "3.0", + ApplicationVersion: "3.0", + EnableStorageOptimizer: true, + IgnoreFileNames: false, + } +} + +func main() { + tdlib.SetLogLevel(0) + tdlib.SetFilePath("./errors.txt") + + botToken := "your_bot_token" + authorizer := tdlib.BotAuthorizer(botToken) + + authorizer.TdlibParameters <- GetTdParameters() + + client, err := tdlib.NewClient(authorizer) + if err != nil { + log.Fatalf("NewClient error: %s", err) + } + + // Handle SIGINT + ch := make(chan os.Signal, 2) + signal.Notify(ch, os.Interrupt, syscall.SIGINT) + signal.Notify(ch, os.Interrupt, syscall.SIGKILL) + signal.Notify(ch, os.Interrupt, syscall.SIGTERM) + signal.Notify(ch, os.Interrupt, syscall.SIGQUIT) + signal.Notify(ch, os.Interrupt, syscall.SIGSEGV) + go func() { + <-ch + client.Destroy() + }() + + me, err := client.GetMe() + if err != nil { + log.Fatalf("GetMe error: %s", err) + } + + log.Printf("%s connected", me.Username) + + listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000) + + defer listener.Close() + for update := range listener.Updates { + updateMsg := update.(*tdlib.UpdateNewMessage) + chatId := updateMsg.Message.ChatId + msgId := updateMsg.Message.Id + + var msgText string + var msgEnt []*tdlib.TextEntity + + switch updateMsg.Message.Content.MessageContentType() { + case "messageText": + msgText = updateMsg.Message.Content.(*tdlib.MessageText).Text.Text + msgEnt = updateMsg.Message.Content.(*tdlib.MessageText).Text.Entities + + cmd := tdlib.CheckCommand(msgText, msgEnt) + switch cmd { + case "/ping": + text, _ := tdlib.ParseTextEntities(&tdlib.ParseTextEntitiesRequest{ + Text: "pong!", + ParseMode: &tdlib.TextParseModeHTML{}, + }) + m, err := client.SendMessage(&tdlib.SendMessageRequest{ + ChatId: chatId, + ReplyToMessageId: msgId, + InputMessageContent: &tdlib.InputMessageText{ + Text: text, + }, + }) + if err != nil { + continue + } + log.Printf("Message sent, ID: %d", m.Id) + } + } + } +} diff --git a/example/command/ReplyCommand.go b/example/command/ReplyCommand.go new file mode 100644 index 0000000..9278674 --- /dev/null +++ b/example/command/ReplyCommand.go @@ -0,0 +1,113 @@ +package main + +import ( + "log" + "os" + "os/signal" + "syscall" + + tdlib "github.com/c0re100/gotdlib/client" +) + +func GetSenderId(sender tdlib.MessageSender) int64 { + if sender.MessageSenderType() == "messageSenderUser" { + return sender.(*tdlib.MessageSenderUser).UserId + } else { + return sender.(*tdlib.MessageSenderChat).ChatId + } +} + +func GetTdParameters() *tdlib.TdlibParameters { + return &tdlib.TdlibParameters{ + UseTestDc: false, + DatabaseDirectory: "./tdlib-db", + FilesDirectory: "./tdlib-files", + UseFileDatabase: true, + UseChatInfoDatabase: true, + UseMessageDatabase: true, + UseSecretChats: false, + ApiId: 132712, + ApiHash: "e82c07ad653399a37baca8d1e498e472", + SystemLanguageCode: "en", + DeviceModel: "HuskyNG", + SystemVersion: "3.0", + ApplicationVersion: "3.0", + EnableStorageOptimizer: true, + IgnoreFileNames: false, + } +} + +func main() { + tdlib.SetLogLevel(0) + tdlib.SetFilePath("./errors.txt") + + authorizer := tdlib.ClientAuthorizer() + go tdlib.CliInteractor(authorizer) + + authorizer.TdlibParameters <- GetTdParameters() + + client, err := tdlib.NewClient(authorizer) + if err != nil { + log.Fatalf("NewClient error: %s", err) + } + + // Handle SIGINT + ch := make(chan os.Signal, 2) + signal.Notify(ch, os.Interrupt, syscall.SIGINT) + signal.Notify(ch, os.Interrupt, syscall.SIGKILL) + signal.Notify(ch, os.Interrupt, syscall.SIGTERM) + signal.Notify(ch, os.Interrupt, syscall.SIGQUIT) + signal.Notify(ch, os.Interrupt, syscall.SIGSEGV) + go func() { + <-ch + client.Destroy() + }() + + me, err := client.GetMe() + if err != nil { + log.Fatalf("GetMe error: %s", err) + } + + log.Printf("%s connected", me.Username) + + listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000) + + defer listener.Close() + for update := range listener.Updates { + updateMsg := update.(*tdlib.UpdateNewMessage) + chatId := updateMsg.Message.ChatId + senderId := GetSenderId(updateMsg.Message.SenderId) + msgId := updateMsg.Message.Id + + if senderId == me.Id { + var msgText string + var msgEnt []*tdlib.TextEntity + + switch updateMsg.Message.Content.MessageContentType() { + case "messageText": + msgText = updateMsg.Message.Content.(*tdlib.MessageText).Text.Text + msgEnt = updateMsg.Message.Content.(*tdlib.MessageText).Text.Entities + } + + cmd := tdlib.CheckCommand(msgText, msgEnt) + switch cmd { + case "/test": + text, _ := tdlib.ParseTextEntities(&tdlib.ParseTextEntitiesRequest{ + Text: "Hi test user", + ParseMode: &tdlib.TextParseModeHTML{}, + }) + m, err := client.SendMessage(&tdlib.SendMessageRequest{ + ChatId: chatId, + ReplyToMessageId: msgId, + InputMessageContent: &tdlib.InputMessageText{ + Text: text, + }, + }) + if err != nil { + continue + } + log.Printf("Message sent, ID: %d", m.Id) + } + } + } +} diff --git a/example/event/CustomEventFilter.go b/example/event/CustomEventFilter.go new file mode 100644 index 0000000..26614f5 --- /dev/null +++ b/example/event/CustomEventFilter.go @@ -0,0 +1,84 @@ +package main + +import ( + "log" + "os" + "os/signal" + "syscall" + + tdlib "github.com/c0re100/gotdlib/client" +) + +func GetSenderId(sender tdlib.MessageSender) int64 { + if sender.MessageSenderType() == "messageSenderUser" { + return sender.(*tdlib.MessageSenderUser).UserId + } else { + return sender.(*tdlib.MessageSenderChat).ChatId + } +} + +func GetTdParameters() *tdlib.TdlibParameters { + return &tdlib.TdlibParameters{ + UseTestDc: false, + DatabaseDirectory: "./tdlib-db", + FilesDirectory: "./tdlib-files", + UseFileDatabase: true, + UseChatInfoDatabase: true, + UseMessageDatabase: true, + UseSecretChats: false, + ApiId: 132712, + ApiHash: "e82c07ad653399a37baca8d1e498e472", + SystemLanguageCode: "en", + DeviceModel: "HuskyNG", + SystemVersion: "3.0", + ApplicationVersion: "3.0", + EnableStorageOptimizer: true, + IgnoreFileNames: false, + } +} + +func main() { + tdlib.SetLogLevel(0) + tdlib.SetFilePath("./errors.txt") + + authorizer := tdlib.ClientAuthorizer() + go tdlib.CliInteractor(authorizer) + + authorizer.TdlibParameters <- GetTdParameters() + + client, err := tdlib.NewClient(authorizer) + if err != nil { + log.Fatalf("NewClient error: %s", err) + } + + // Handle SIGINT + ch := make(chan os.Signal, 2) + signal.Notify(ch, os.Interrupt, syscall.SIGINT) + signal.Notify(ch, os.Interrupt, syscall.SIGKILL) + signal.Notify(ch, os.Interrupt, syscall.SIGTERM) + signal.Notify(ch, os.Interrupt, syscall.SIGQUIT) + signal.Notify(ch, os.Interrupt, syscall.SIGSEGV) + go func() { + <-ch + client.Destroy() + }() + + me, err := client.GetMe() + if err != nil { + log.Fatalf("GetMe error: %s", err) + } + + log.Printf("%s connected", me.Username) + + listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000) + + defer listener.Close() + for update := range listener.Updates { + updateMsg := update.(*tdlib.UpdateNewMessage) + chatId := updateMsg.Message.ChatId + senderId := GetSenderId(updateMsg.Message.SenderId) + msgId := updateMsg.Message.Id + + log.Printf("[Received new message from chat %d]: Sender ID: %d, Message ID: %d", chatId, senderId, msgId) + } +} diff --git a/example/media/Photo_or_Album.go b/example/media/Photo_or_Album.go new file mode 100644 index 0000000..5a4dae4 --- /dev/null +++ b/example/media/Photo_or_Album.go @@ -0,0 +1,142 @@ +package main + +import ( + "log" + "os" + "os/signal" + "syscall" + + tdlib "github.com/c0re100/gotdlib/client" +) + +func GetSenderId(sender tdlib.MessageSender) int64 { + if sender.MessageSenderType() == "messageSenderUser" { + return sender.(*tdlib.MessageSenderUser).UserId + } else { + return sender.(*tdlib.MessageSenderChat).ChatId + } +} + +func GetTdParameters() *tdlib.TdlibParameters { + return &tdlib.TdlibParameters{ + UseTestDc: false, + DatabaseDirectory: "./tdlib-db", + FilesDirectory: "./tdlib-files", + UseFileDatabase: true, + UseChatInfoDatabase: true, + UseMessageDatabase: true, + UseSecretChats: false, + ApiId: 132712, + ApiHash: "e82c07ad653399a37baca8d1e498e472", + SystemLanguageCode: "en", + DeviceModel: "HuskyNG", + SystemVersion: "3.0", + ApplicationVersion: "3.0", + EnableStorageOptimizer: true, + IgnoreFileNames: false, + } +} + +func main() { + tdlib.SetLogLevel(0) + tdlib.SetFilePath("./errors.txt") + + authorizer := tdlib.ClientAuthorizer() + go tdlib.CliInteractor(authorizer) + + authorizer.TdlibParameters <- GetTdParameters() + + client, err := tdlib.NewClient(authorizer) + if err != nil { + log.Fatalf("NewClient error: %s", err) + } + + // Handle SIGINT + ch := make(chan os.Signal, 2) + signal.Notify(ch, os.Interrupt, syscall.SIGINT) + signal.Notify(ch, os.Interrupt, syscall.SIGKILL) + signal.Notify(ch, os.Interrupt, syscall.SIGTERM) + signal.Notify(ch, os.Interrupt, syscall.SIGQUIT) + signal.Notify(ch, os.Interrupt, syscall.SIGSEGV) + go func() { + <-ch + client.Destroy() + }() + + me, err := client.GetMe() + if err != nil { + log.Fatalf("GetMe error: %s", err) + } + + log.Printf("%s connected", me.Username) + + listener := client.AddEventReceiver(&tdlib.UpdateNewMessage{}, 1000) + + defer listener.Close() + for update := range listener.Updates { + updateMsg := update.(*tdlib.UpdateNewMessage) + chatId := updateMsg.Message.ChatId + senderId := GetSenderId(updateMsg.Message.SenderId) + msgId := updateMsg.Message.Id + + if senderId == me.Id { + var msgText string + var msgEnt []*tdlib.TextEntity + + switch updateMsg.Message.Content.MessageContentType() { + case "messageText": + msgText = updateMsg.Message.Content.(*tdlib.MessageText).Text.Text + msgEnt = updateMsg.Message.Content.(*tdlib.MessageText).Text.Entities + } + + cmd := tdlib.CheckCommand(msgText, msgEnt) + switch cmd { + case "/photo": + text, _ := tdlib.ParseTextEntities(&tdlib.ParseTextEntitiesRequest{ + Text: "test photo", + ParseMode: &tdlib.TextParseModeHTML{}, + }) + m, err := client.SendMessage(&tdlib.SendMessageRequest{ + ChatId: chatId, + ReplyToMessageId: msgId, + InputMessageContent: &tdlib.InputMessagePhoto{ + Photo: &tdlib.InputFileLocal{ + Path: "./myht9-1486821485193084928.jpg", + }, + Caption: text, + }, + }) + if err != nil { + continue + } + log.Printf("Photo sent, ID: %d", m.Id) + case "/album": + text, _ := tdlib.ParseTextEntities(&tdlib.ParseTextEntitiesRequest{ + Text: "test album", + ParseMode: &tdlib.TextParseModeHTML{}, + }) + m, err := client.SendMessageAlbum(&tdlib.SendMessageAlbumRequest{ + ChatId: chatId, + ReplyToMessageId: msgId, + InputMessageContents: []tdlib.InputMessageContent{ + &tdlib.InputMessagePhoto{ + Photo: &tdlib.InputFileLocal{ + Path: "./myht9-1486821485193084928.jpg", + }, + Caption: text, + }, + &tdlib.InputMessagePhoto{ + Photo: &tdlib.InputFileLocal{ + Path: "./hisagi_02-1486983199280738309.jpg", + }, + }, + }, + }) + if err != nil { + continue + } + log.Printf("Media album sent, Album ID: %v", m.Messages[0].MediaAlbumId) + } + } + } +} diff --git a/example/media/hisagi_02-1486983199280738309.jpg b/example/media/hisagi_02-1486983199280738309.jpg new file mode 100644 index 0000000..7bc282f Binary files /dev/null and b/example/media/hisagi_02-1486983199280738309.jpg differ diff --git a/example/media/myht9-1486821485193084928.jpg b/example/media/myht9-1486821485193084928.jpg new file mode 100644 index 0000000..3acc5b1 Binary files /dev/null and b/example/media/myht9-1486821485193084928.jpg differ diff --git a/example/raw_update/raw.go b/example/raw_update/raw.go new file mode 100644 index 0000000..75ce414 --- /dev/null +++ b/example/raw_update/raw.go @@ -0,0 +1,81 @@ +package main + +import ( + "log" + "os" + "os/signal" + "syscall" + + tdlib "github.com/c0re100/gotdlib/client" +) + +func GetSenderId(sender tdlib.MessageSender) int64 { + if sender.MessageSenderType() == "messageSenderUser" { + return sender.(*tdlib.MessageSenderUser).UserId + } else { + return sender.(*tdlib.MessageSenderChat).ChatId + } +} + +func GetTdParameters() *tdlib.TdlibParameters { + return &tdlib.TdlibParameters{ + UseTestDc: false, + DatabaseDirectory: "./tdlib-db", + FilesDirectory: "./tdlib-files", + UseFileDatabase: true, + UseChatInfoDatabase: true, + UseMessageDatabase: true, + UseSecretChats: false, + ApiId: 132712, + ApiHash: "e82c07ad653399a37baca8d1e498e472", + SystemLanguageCode: "en", + DeviceModel: "HuskyNG", + SystemVersion: "3.0", + ApplicationVersion: "3.0", + EnableStorageOptimizer: true, + IgnoreFileNames: false, + } +} + +func main() { + tdlib.SetLogLevel(0) + tdlib.SetFilePath("./errors.txt") + + authorizer := tdlib.ClientAuthorizer() + go tdlib.CliInteractor(authorizer) + + authorizer.TdlibParameters <- GetTdParameters() + + client, err := tdlib.NewClient(authorizer) + if err != nil { + log.Fatalf("NewClient error: %s", err) + } + + // Handle SIGINT + ch := make(chan os.Signal, 2) + signal.Notify(ch, os.Interrupt, syscall.SIGINT) + signal.Notify(ch, os.Interrupt, syscall.SIGKILL) + signal.Notify(ch, os.Interrupt, syscall.SIGTERM) + signal.Notify(ch, os.Interrupt, syscall.SIGQUIT) + signal.Notify(ch, os.Interrupt, syscall.SIGSEGV) + go func() { + <-ch + client.Destroy() + }() + + me, err := client.GetMe() + if err != nil { + log.Fatalf("GetMe error: %s", err) + } + + log.Printf("%s connected", me.Username) + + listener := client.GetListener() + + defer listener.Close() + for update := range listener.RawUpdates { + if update.GetClass() == tdlib.ClassUpdate { + log.Printf("%#v", update) + } + } +}