Визуализация результатов Telegram-опросов в Grafana

Хотел бы поделиться интересным решением, которое, уверен, было бы полезно для кооперативов и товариществ.

Современные технологии постепенно проникают во все области нашей жизни. Сегодня сложно представить соседей многоквартирных домов или земельных участков СНТ/ДНТ без группового чата в мессенджере. Такие группы удобны для общения, они позволяют оперативно решать вопросы, публиковать объявления, делиться новостями и даже проводить опросы и голосования.

Кстати, голосование в мессенджере может иметь юридическую силу. Для этого нужно принять решение о возможности применения электронных средств при принятии решений общим собранием членов товарищества и внести соответствующие изменения в устав товарищества (п. 25 ч. 1 ст. 17 федерального закона № 217-ФЗ). При создании нашего товарищества так мы и сделали, и теперь большинство вопросов мы решаем удаленно через Telegram.

Результаты опросов, проведенных в Telegram, отображаются почти моментально в интерфейсе мессенджера. Однако такие результаты не учитывают случаи, когда количество голосов у членов товарищества отличается. Кроме того, в общем чате могут присутствовать супруги/родственники участников, которые могут проголосовать без права голоса. В итоге всё сводится к тому, что необходимо каждый раз пересчитывать голоса.

Чтобы не утомлять секретаря собрания лишней рутиной, мы решили автоматизировать этот процесс. И вот, что у нас получилось.

На скриншотах ниже представлены результаты одного из первых Telegram-опросов, которые мы провели.

Панели Pie Chart и Stat

Панели Pie Chart и Stat

Панель Geomap

Панель Geomap

Таким образом, участник товарищества просто отдает голос в опросе Telegram, а система автоматически в онлайн-режиме учитывает его голос (голоса) и отображает данные на дашборде.

Здорово, не так ли?

Визуальная часть нашего решения реализована в Grafana. Мы использовали панели Pie Chart, Stat и Geomap. Источником данных служит база данных MongoDB с коллекциями «Соседи», «Земли», «Опросы». Для подключения MongoDB в Grafana мы используем плагин grafana-mongodb-community-plugin.

Чтобы программно «отлавливать» голоса в Telegram, нужно чтобы опрос был создан Telegram-ботом. Такого бота мы написали на Golang с использованием библиотеки telegram-bot-api.

Учет голосов реализован в функции handlePollAnswer. Ниже представлена её упрощенная версия.

func handlePollAnswer(pollAnswer *tgbotapi.PollAnswer) {
	// Ищем пользователя в БД
	neighbor, err := db.GetNeighborByChatID(pollAnswer.User.ID)
	if err != nil {
		// handle error
        return
	}
	// Если пользователь отменил голос, исключим его голос из базы
	if len(pollAnswer.OptionIDs) == 0 {
		err := db.DeleteVote(pollAnswer.PollID, neighbor.ID)
		if err != nil {
			// handle error
			return
		}
	} else { // Если проголосовал, добавим голоса в базу
		for _, optionID := range pollAnswer.OptionIDs {
			err := db.AddVote(pollAnswer.PollID, neighbor, optionID)
			if err != nil {
				// handle error
				return
			}
		}
	}
}

Пример создания опроса в интерфейсе Telegram приведен на скриншоте ниже.

Пример создания опроса через интерфейс Telegram-бота

Пример создания опроса через интерфейс Telegram-бота

Для отображения данных на карте мы написали небольшой веб-сервис, который по данным коллекций «Опросы» и «Земли» формирует GeoJSON и возвращет его по HTTP-запросу. URL до нашего веб-сервиса мы указали в настройках панели Geomap. Там же настроили правила отображения.

Подложку для карты (тайлы) для нашего некоммерческого проекта мы сначала попросили у Yandex, так как на ней указаны названия улиц нашего посёлка. Но Yandex нам отказал. В итоге было принято решение взять подложку Here, за что мы им очень благодарны.

На этом у меня всё. Пишите Ваши вопросы в комментариях.
Спасибо за внимание!

© Habrahabr.ru