📜 ⬆️ ⬇️

Chat VKontakte as a terminal

Inspired by the post “Simple Task Manager with Web Interface, written in GO for Unix-systems including Android” , Go and the simple status utility, I decided to write a chat bot for the Vkontakte social network with similar functionality as a fun experiment.

Why did you choose chat bot and social network? In addition to the obvious just for fun, there are practical calculations:


The utility is a simple chat bot that responds to text commands. We write to VK a message to oneself, the utility polls the VK API with a certain frequency and receives a list of messages. Then it remains only to compare the entered message with a list of predefined text commands.
Nothing complicated, although there are some nuances that you need to know about the VK API.
First, to access private messages, you need to register the VK application as a desktop. And when access token is requested, set access rights to private messages and a “blank” page for callback.
The address for access token will look something like this:
  https://oauth.vk.com/authorize?client_id=#####&scope=offline,messages&redirect_uri=https%3A%2F%2Foauth.vk.com%2Fblank.html&display=page&v=5.28&response_type=token 

Secondly, there is a limit on the number of requests per second, so receiving messages occurs with a timer of 2 seconds.
c := time.Tick(2 * time.Second) lastMsgId := int64(0) for _ = range c { msgs, err := getMsgs(lastMsgId) if err != nil { fmt.Println(err) } else { if len(msgs.Response.Items) > 0 { lastMsgId = msgs.Response.Items[0].Id } for _, msg := range msgs.Response.Items { msgBody := strings.Trim(msg.Body, "") if checkVkId(msg.UserId) && checkTime(msg.Date) && checkResultPrefix(msgBody) { go doCmd(msgBody) } } } } 

Parsing an incoming message and sending the result of the command execution:

 func doSysCmd(msg string) { switch true { case strings.HasPrefix(msg, "@sys/host"): sendMsg(*vk_id, fmt.Sprintf("%+v", sysstat.GetHost())) case strings.HasPrefix(msg, "@sys/disk"): sendMsg(*vk_id, fmt.Sprintf("%+v", sysstat.GetDisk("/"))) case strings.HasPrefix(msg, "@sys/load"): sendMsg(*vk_id, fmt.Sprintf("%+v", sysstat.GetLoad())) case strings.HasPrefix(msg, "@sys/ram"): sendMsg(*vk_id, fmt.Sprintf("%+v", sysstat.GetRam())) case strings.HasPrefix(msg, "@sys"): sendMsg(*vk_id, fmt.Sprintf("\n%+v", sysstat.GetSystem("/"))) case strings.HasPrefix(msg, "@sh"): args := strings.SplitN(msg, " ", 2) if len(args) < 2 { return } fmt.Println("exec: ", args[1]) sendMsg(*vk_id, fmt.Sprintf(" %+v", sysstat.ExecShell(args[1]))) } } 

In addition to receiving the current status of the system as a bonus, you can save arbitrary notes with the commands:
! list - output the saved list with id numbers
! add [text] - add new entry
! del [number] - delete the record with the specified id

Notes are stored exclusively in memory.
Protection against the collapse of the application is not provided, I took the practice of running such things under the supervisor, who himself restarts the application if a critical error occurs. The consumption of RAM for go programs is traditionally minimal and fluctuates around 10 MB, the supervisor takes the same amount.
')
Sources on github .

Source: https://habr.com/ru/post/251083/


All Articles