Created
May 3, 2017 18:10
-
-
Save shelomentsevd/a9f8d12bdb0a05b4644350cf73f09a58 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "os" | |
| "os/signal" | |
| "syscall" | |
| "fmt" | |
| "time" | |
| "reflect" | |
| "mtproto" | |
| ) | |
| func findUserById(id int32, users []mtproto.TL) mtproto.TL { | |
| // TODO: Refactoring needed | |
| for i:=0; i<len(users); i+=1 { | |
| user := users[i] | |
| switch user.(type) { | |
| case mtproto.TL_userEmpty: | |
| user, _ := user.(mtproto.TL_userEmpty) | |
| if user.Id == id { | |
| return user | |
| } | |
| case mtproto.TL_user: | |
| user, _ := user.(mtproto.TL_user) | |
| if user.Id == id { | |
| return user | |
| } | |
| } | |
| } | |
| return mtproto.TL_null{} | |
| } | |
| func getUsername(user mtproto.TL) (username string) { | |
| switch user.(type) { | |
| case mtproto.TL_userEmpty: | |
| user, _ := user.(mtproto.TL_userEmpty) | |
| username = fmt.Sprintf("%d", user.Id) | |
| case mtproto.TL_user: | |
| user, _ := user.(mtproto.TL_user) | |
| username = fmt.Sprintf("%s @%s %s", user.First_name, user.Username, user.Last_name) | |
| default: | |
| username = "Unknow username" | |
| } | |
| return | |
| } | |
| func findChatById(id int32, chats []mtproto.TL) mtproto.TL { | |
| // TODO: Refactoring needed | |
| for i:=0;i<len(chats);i+=1 { | |
| chat := chats[i] | |
| switch chat.(type) { | |
| case mtproto.TL_chatEmpty: | |
| chat, _ := chat.(mtproto.TL_chatEmpty) | |
| if chat.Id == id { | |
| return chat | |
| } | |
| case mtproto.TL_chat: | |
| chat, _ := chat.(mtproto.TL_chat) | |
| if chat.Id == id { | |
| return chat | |
| } | |
| case mtproto.TL_chatForbidden: | |
| chat, _ := chat.(mtproto.TL_chatForbidden) | |
| if chat.Id == id { | |
| return chat | |
| } | |
| case mtproto.TL_channel: | |
| chat, _ := chat.(mtproto.TL_channel) | |
| if chat.Id == id { | |
| return chat | |
| } | |
| case mtproto.TL_channelForbidden: | |
| chat, _ := chat.(mtproto.TL_channelForbidden) | |
| if chat.Id == id { | |
| return chat | |
| } | |
| } | |
| } | |
| return mtproto.TL_null{} | |
| } | |
| func getChatname(chat mtproto.TL) (chatname string) { | |
| switch chat.(type) { | |
| case mtproto.TL_chatEmpty: | |
| chat, _ := chat.(mtproto.TL_chatEmpty) | |
| chatname = fmt.Sprintf("%d", chat.Id) | |
| case mtproto.TL_chat: | |
| chat, _ := chat.(mtproto.TL_chat) | |
| chatname = chat.Title | |
| case mtproto.TL_chatForbidden: | |
| chat, _ := chat.(mtproto.TL_chatForbidden) | |
| chatname = chat.Title | |
| case mtproto.TL_channel: | |
| chat, _ := chat.(mtproto.TL_channel) | |
| chatname = chat.Title | |
| case mtproto.TL_channelForbidden: | |
| chat, _ := chat.(mtproto.TL_channelForbidden) | |
| chatname = chat.Title | |
| default: | |
| chatname = "Unknow chat" | |
| } | |
| return | |
| } | |
| func processMessage(users, chats []mtproto.TL, message mtproto.TL) { | |
| switch message.(type) { | |
| case mtproto.TL_messageEmpty: | |
| message, _ := message.(mtproto.TL_messageEmpty) | |
| fmt.Println("Empty message", message) | |
| case mtproto.TL_message: | |
| message, _ := message.(mtproto.TL_message) | |
| var id int32 | |
| var to string | |
| var from string | |
| fromUser := findUserById(message.From_id, users) | |
| from = getUsername(fromUser) | |
| switch message.To_id.(type) { | |
| case mtproto.TL_peerChannel: | |
| peer, _ := message.To_id.(mtproto.TL_peerChannel) | |
| id = peer.Channel_id | |
| chat := findChatById(id, chats) | |
| to = getChatname(chat) | |
| case mtproto.TL_peerChat: | |
| peer, _ := message.To_id.(mtproto.TL_peerChat) | |
| id = peer.Chat_id | |
| chat := findChatById(id, chats) | |
| to = getChatname(chat) | |
| case mtproto.TL_peerUser: | |
| peer, _ := message.To_id.(mtproto.TL_peerUser) | |
| id = peer.User_id | |
| user := findUserById(id, users) | |
| to = getUsername(user) | |
| } | |
| fmt.Printf("%s to %s: %s\n", from, to, message.Message) | |
| case mtproto.TL_messageService: | |
| message, _ := message.(mtproto.TL_messageService) | |
| fmt.Println("Service message", message) | |
| } | |
| } | |
| func process(users, messages, chats, updates []mtproto.TL, state * mtproto.TL_updates_state) error { | |
| for i:=0;i<len(updates);i+=1 { | |
| update := updates[i] | |
| switch update.(type) { | |
| case mtproto.TL_updateNewMessage: | |
| update, _ := update.(mtproto.TL_updateNewMessage) | |
| fmt.Println("New message: ") | |
| processMessage(users, chats, update.Message) | |
| case mtproto.TL_updateMessageID: | |
| update, _ := update.(mtproto.TL_updateMessageID) | |
| fmt.Println("Update message id", update) | |
| case mtproto.TL_updateDeleteMessages: | |
| update, _ := update.(mtproto.TL_updateDeleteMessages) | |
| fmt.Println("Delete message", update) | |
| case mtproto.TL_updateUserTyping: | |
| update, _ := update.(mtproto.TL_updateUserTyping) | |
| fmt.Println("User is typing", update) | |
| case mtproto.TL_updateChatParticipants: | |
| update, _ := update.(mtproto.TL_updateChatParticipants) | |
| fmt.Println("Update chat participants", update) | |
| case mtproto.TL_updateUserStatus: | |
| update, _ := update.(mtproto.TL_updateUserStatus) | |
| fmt.Println("User update status", update) | |
| case mtproto.TL_updateEditMessage: | |
| update, _ := update.(mtproto.TL_updateEditMessage) | |
| fmt.Println("Message edited") | |
| processMessage(users, chats, update.Message) | |
| case mtproto.TL_updateNewChannelMessage: | |
| update, _ := update.(mtproto.TL_updateNewChannelMessage) | |
| fmt.Println("Message from channel") | |
| processMessage(users, chats, update.Message) | |
| case mtproto.TL_updateChannelTooLong: | |
| update, _ := update.(mtproto.TL_updateChannelTooLong) | |
| fmt.Println("Update channel too long", update) | |
| res := findChatById(update.Channel_id, chats) | |
| channel, ok := res.(mtproto.TL_channel) | |
| fmt.Printf("Update %s too long\n", channel.Username) | |
| if !ok { | |
| fmt.Println("error") | |
| fmt.Println(res) | |
| return nil | |
| } | |
| _, result := m.UpdatesGetChannelDifference(false, mtproto.TL_inputChannel{ | |
| Channel_id: channel.Id, | |
| Access_hash: channel.Access_hash, | |
| }, mtproto.TL_channelMessagesFilterEmpty{}, state.Pts, 50) | |
| switch (*result).(type) { | |
| case mtproto.TL_updates_channelDifferenceEmpty: | |
| diff, _ := (*result).(mtproto.TL_updates_channelDifferenceEmpty) | |
| state.Pts = diff.Pts | |
| case mtproto.TL_updates_channelDifference: | |
| diff, _ := (*result).(mtproto.TL_updates_channelDifference) | |
| state.Pts = diff.Pts | |
| process(diff.Users, diff.New_messages, diff.Chats, diff.Other_updates, state) | |
| } | |
| default: | |
| fmt.Println(reflect.TypeOf(update)) | |
| fmt.Println("Unknow type", update) | |
| } | |
| } | |
| return nil | |
| } | |
| var m *mtproto.MTProto | |
| func main() { | |
| fmt.Println("Started") | |
| // Signals | |
| stop := make(chan struct{}, 1) | |
| sigc := make(chan os.Signal, 1) | |
| signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) | |
| go func() { | |
| s := <-sigc | |
| fmt.Println(s) | |
| stop <- struct{}{} | |
| }() | |
| // Telegram | |
| appConfig, err := mtproto.NewConfiguration(41994, | |
| "269069e15c81241f5670c397941016a2", | |
| "0.0.1", | |
| "", | |
| "", | |
| "") | |
| if err != nil { | |
| fmt.Printf("Create failed: %s\n", err) | |
| os.Exit(2) | |
| } | |
| const telegramAddr = "149.154.167.50:443" | |
| m, err = mtproto.NewMTProto(false, telegramAddr, os.Getenv("HOME")+"/.telegram_go", *appConfig) | |
| if err != nil { | |
| fmt.Printf("Create failed: %s\n", err) | |
| os.Exit(2) | |
| } | |
| err = m.Connect() | |
| if err != nil { | |
| fmt.Printf("Connect failed: %s\n", err) | |
| os.Exit(2) | |
| } | |
| err, tl := m.UpdatesGetState() | |
| if err != nil { | |
| fmt.Println("Failed to get state", err) | |
| return | |
| } | |
| state, ok := (*tl).(mtproto.TL_updates_state) | |
| if !ok { | |
| fmt.Println("Wrong state type", ok) | |
| return | |
| } | |
| // Life cycle | |
| LifeCycle: | |
| for { | |
| select { | |
| case <-stop: | |
| break LifeCycle; | |
| case <-time.After(time.Second * 2): | |
| } | |
| //fmt.Println("Next state") | |
| err, news := m.UpdatesGetDifference(state.Pts, state.Unread_count, state.Date, state.Qts) | |
| if err != nil { | |
| fmt.Println("Failed to get state difference", err) | |
| } | |
| switch (*news).(type) { | |
| case mtproto.TL_updates_differenceEmpty: | |
| //fmt.Println("Difference is empty") | |
| diff, _ := (*news).(mtproto.TL_updates_differenceEmpty) | |
| state.Date = diff.Date | |
| state.Seq = diff.Seq | |
| case mtproto.TL_updates_difference: | |
| //fmt.Println("Difference") | |
| diff, _ := (*news).(mtproto.TL_updates_difference) | |
| state, ok = diff.State.(mtproto.TL_updates_state) | |
| if !ok { | |
| fmt.Println("Wrong state type", ok) | |
| break LifeCycle | |
| } | |
| //fmt.Println(diff) | |
| process(diff.Users, diff.New_messages, diff.Chats ,diff.Other_updates, &state) | |
| //fmt.Println("Chats: ") | |
| //fmt.Println(diff.Chats) | |
| //fmt.Println("Users: ") | |
| //fmt.Println(diff.Users) | |
| //fmt.Println("Other updates: ") | |
| //fmt.Println(diff.Other_updates) | |
| //fmt.Println("New messages: ") | |
| //fmt.Println(diff.New_messages) | |
| //for i:=0; i < len(diff.New_messages); i+=1 { | |
| // fmt.Println(reflect.TypeOf(diff.New_messages[i])) | |
| //} | |
| //for message := range diff.New_messages { | |
| // fmt.Println(reflect.TypeOf(message)) | |
| //} | |
| case mtproto.TL_updates_differenceSlice: | |
| //fmt.Println("Difference slice") | |
| diff, _ := (*news).(mtproto.TL_updates_differenceSlice) | |
| state, ok = diff.Intermediate_state.(mtproto.TL_updates_state) | |
| if !ok { | |
| fmt.Println("Wrong state type", ok) | |
| break LifeCycle | |
| } | |
| process(diff.Users, diff.New_messages, diff.Chats ,diff.Other_updates, &state) | |
| //fmt.Println(diff) | |
| //fmt.Println("Chats: ") | |
| //fmt.Println(diff.Chats) | |
| //fmt.Println("Users: ") | |
| //fmt.Println(diff.Users) | |
| //fmt.Println("Other updates: ") | |
| //fmt.Println(diff.Other_updates) | |
| //fmt.Println("New messages: ") | |
| //fmt.Println(diff.New_messages) | |
| //for i:=0; i < len(diff.New_messages); i+=1 { | |
| // fmt.Println(reflect.TypeOf(diff.New_messages[i])) | |
| //} | |
| //for message := range diff.New_messages { | |
| // fmt.Println(reflect.TypeOf(message)) | |
| //} | |
| case mtproto.TL_updates_differenceTooLong: | |
| //fmt.Println("Difference is too long") | |
| diff, _ := (*news).(mtproto.TL_updates_differenceTooLong) | |
| state.Pts = diff.Pts | |
| //err, tl := m.UpdatesGetState() | |
| //if err != nil { | |
| // fmt.Println("Failed to get state", err) | |
| // return | |
| //} | |
| //state, ok = (*tl).(mtproto.TL_updates_state) | |
| //if !ok { | |
| // fmt.Println("Wrong state type", ok) | |
| // return | |
| //} | |
| } | |
| } | |
| fmt.Println("Finished") | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment