Чат вконтакта в качестве терминала
Вдохновлённый постом «Простой диспетчер задач с веб-интерфейсом, написанный на языке GO для Unix-систем включая Android», языком Go и утилитой simple status, я решил написать в качестве забавного эксперимента чат-бота для социальной сети Vkontakte со схожим функционалом.Почему выбор пал на чат-бота и социальную сеть? Кроме очевидного just for fun имеются и практические выкладки:
Не нужны дополнительные телодвижения для доступа к приложению, запущенном на компьютере с динамическим ip или находящимся за роутером. Доступ к Вконтактике есть практически везде — достаточно иметь при себе телефон с доступом в интернет. Вопрос о реализации аутентификации на уровне конечного приложения практически отпадает. Утилита представляет собой простого чат бота, реагирующего на текстовые команды. Пишем в VK сообщение самому себе, утилита с некоторой периодичностью опрашивает VK API и получает список сообщений. Дальше только остаётся сопоставить введённое сообщение со списком предопределённых текстовых команд.Ничего сложного, правда есть некоторые нюансы, которые надо знать про VK API.Во-первых, для доступа к личным сообщениям надо регистрировать VK приложение как desktop. И при запросе access token выставить права на доступ к личным сообщениям и «бланковую» страницу для callback.Адрес для получения access token будет выглядеть примерно так: 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 Во-вторых, есть ограничение по количеству запросов в секунду, поэтому получение сообщений происходит с таймером в 2 секунды. 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) } } } } Разбор входящего сообщения и отправка результата исполнения команды: 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]))) } } Кроме получения текущего статуса системы в качестве бонуса можно сохранять произвольные заметки командами: !list – вывод сохраненного списка с номерами id!add [текст] – добавить новую запись!del [номер] – удалить запись с указанным id
Заметки сохраняются исключительно в памяти.Защита от краха приложения не предусмотрена, я взял за практику запускать подобные вещи под супервизором, который сам перезапускает приложение, если возникнет критическая ошибка. Потребление ОЗУ для go программ традиционно минимально и колеблется в районе 10 МБ, ещё столько же отнимает супервизор.Исходники на github.