Нехитрая история о том, как мне стало стыдно постоянно просить у одногруппников пропущенную информацию и я решил чуть-чуть облегчить нам жизнь.  UPD: С введение ботов в вк статья потеряла актуальность, однако код может быть интересен.  Полагаю, многим моим ровесникам знакома знакома ситуация, когда в общем чате, где довольно часто мелькает важная информация, расположилось около 30 активных собеседников, постоянно нагружающих базы данных Вконтакте своими сообщениями. При таких условиях маловероятно, что эту важную информацию увидят все. Так случается и со мной. Год назад было принято решение исправить это недоразумение. Тех, кто готов не возмущаться по поводу очередной статьи про бота, прошу под кат. Так как являюсь студентом первого уровня, примеры будут связаны с этой тематикой.
Итак, есть задача: сделать передачу информации от старосты к студентам удобной как для старосты, так и для студентов. Благодаря относительно новым фичам Вконтакте (а именно личные сообщения сообществ) решение бросилось в глаза сразу. Бот, сидящий в группе должен принимать сообщения от старосты (старост, если на потоке много групп) и рассылать их заинтересованным лицам (студентам).  Задача поставлена, приступаем. Нам понадобятся: Также перед прочтением предлагаю освежить в памяти паттерны "Наблюдатель" (хабр, вики) и "Фасад" (хабр, вики)  Часть 1. "Приятно познакомиться, товарищ бот." Для начала следует научить нашего бота понимать себя как сообщество. Создадим класс с названием Group. В качестве аргументов пусть принимает объект сессии и объект представителя (Proxy) базы данных. Решение вынести эту функциональность в отдельный класс объясняется тем, что в будущем, возможно, кто-то из вас решит дополнить бота каким-нибудь другим функционалом Вконтакте.
Ну и чтобы разгрузить абстракцию сообщества, естественно.  Создадим метод для обновления участников сообщества. Сразу разделим их на администраторов и участников и сохраним в бд. Еще этот класс должен уметь рассылать сообщения адресатам, поэтому следующий метод в студию. В параметрах: список адресатов, текст сообщения и приложения. Запускается всё это дело в отдельном потоке чтобы бот мог принимать сообщения от других участников.
Принимаются сообщения в синхронном режиме, поэтому с увеличением числа активных клиентов скорость отклика, очевидно, поубавится. На этом, вроде бы, абстракция группы закончена. Со всеми участниками сообщества познакомились, теперь надо научиться их понимать. Часть 2. "Пш… прием.." Заставим бота слушать все сообщения от участников нашего сообщества.
Для этого создадим класс СhatHandler, который и будет этим заниматься
В параметрах: Дальше, собственно, слушаем сообщения от пользователей и распознаем команды. Часть 3. "Что ты там написал про мою ..?" Распознаванием команд занимается отдельная подсистема реализуемая через паттерн "Наблюдатель".
Внимание, CommandObserver: Опять же, вынесение сделано для будущего возможного расширения. Но что же этот наблюдатель будет распознавать?
Вот и добрались до самого интересного — команды.
Каждая команда — независимый класс, потомок базового класса Command.
Все что требуется от команды — запустить метод proceed(), если в начале сообщения пользователя найдено его ключевое слово. Ключевые слова команд определяются в переменной triggers класса команды (строка либо список строк)  Как видно из сигнатуры метода proceed(), каждая команда получает на вход ссылку на экземпляр участника группы, его сообщение (уже без ключевого слова), приложения и ссылку на экземпляр группы. То есть, всё взаимодействие с участником группы ложится на плечи команды. Я считаю это наиболее верным решением, так как таким образом возможно создание шелла (Shell) для большей интерактивности.
(По правде говоря, для этого нужно будет либо вносить асинхронщину, потому что обработка проходит синхронно, либо каждое полученное сообщение обрабатывать в новом потоке, что отнюдь не выгодно) Примеры реализации команд: Часть 4. "Мы же одна большая команда." Теперь все эти модули и обработчики нужно объединить и настроить.
Еще один класс, пожалуйста!
Создаем фасад, который настроит нашего бота. Последний этап — запуск. Всегда самый противный, потому что может вылезти какая-нибудь неожиданность. Не в этот раз. project_path импортируется из модуля settings в корне проекта. На этом, кажется, всё. На данный момент эта программа принесла пользу, как минимум, трем группам и, надеюсь, вам тоже принесет. Развернуть можно бесплатно на Heroku, но это уже другая история. Ссылки:  Multitool