Проект Чат

У меня есть определенный опыт по созданию комьюнити на основе мобильного портала (включая мобильные приложения).

Я занимался подключением SMS знакомств в предустановленное приложение, потом созданием форума для общения пользователей портала и в итоге чата.

В прошлом были сложности с тем, что мобильный интернет был жутко дорогой и нестабильный. Это повлияло на выбор технологий. А именно голый javascript и минималистический дизайн. Я ними я и сейчас, ну почти :)

Итак представляю мой собственный чат с блекджеком и ... сами знаете чем.

Перейти в чат

Технологии:

  • HTML+Javasript
  • Websocket
  • Node.js
  • Mongodb

Все это работает на CentOS 7 64bit, в качестве веб сервера используется Nginx, для контроля выполнения используется Forever.

Возможности которые предоставляются в чате:

  • Личный профиль, в котором можно загрузить фото (устарело, но старым пользователям доступно) и установить цвет фона для сообщений профиля.
  • Вход с помощью виджета авторизации Вконтакте
  • Модерация (роли Admin, Moderator, User, Banned). Админ может назначать модераторов и банить, модератор может только банить.
  • Чат бот, который задает вопросы, делает подсказки, начисляет очки
  • Рейтинг игроков
  • Список онлайн пользователей
  • Смайлы

Весь проект состоит из нескольких частей

  • Сам чат.
  • Чат бот подключается к чату как обычный пользователь. Т.е. это независимое приложение.
  • Приложение поддержки. Для выдачи рейтинга игроков, для загрузки и выдачи фотографий на сервере, как прокси-сервер для фотографий пользователей Вконтакте

Сервер и клиент общаются с помощью технологии websocket. Каждая из сторон инициирует передачу по собственной логике, т.е. полностью асинхронная работа.

Соединение через websocket работает через SSL (шифруется на уровне протокола передачи данных). Например так.

var https = require('https'),fs = require('fs');
var options = {
    key : fs.readFileSync('/etc/ssl/private/marychat.key'),
    cert : fs.readFileSync('/etc/ssl/public/marychat.crt')
};
var app = https.createServer(options, function(req, res) {
    res.end("It's ok");
});
app.listen(9000);

var WebSocketServer = require('/home/flinter/node_modules/ws').Server,
    wss = new WebSocketServer({server: app});

База данных состоит из двух таблиц. Я думаю тут без вопросов.

  • Пользователи
  • Сообщения

Серверная логика

При присоединении пользователя создается пользовательский таймер для реализации логики "Пинг-Понг". Смысл логики заключается в том, что сервер каждую минуту отправляет пакет ping на клиент, если в следующий тик таймера пакет pong от клиента так и не пришел - сервер прерывает соединение с клиентом.

После того как клиент присоединился, сервер ожидает пакет authorize, в котором клиент присылает свои идентификационные данные. В качестве альтернативного входа используется пакет unauthorize, для тех пользователей, у которых нет идентификационных данных.

В качестве идентификатора пользователей Вконтакте используется пара uid пользователя и hash сумма с секретным кодом известным только серверу. Взлом возможен только подбором или коллизией hash.

В любом случае, после успешной авторизации или входа без авторизации - пользователь добавляется в список онлайн юзеров, и ему отправляются последние 50 сообщений чата. Всем онлайн юзерам(включая нового) рассылается новый список онлайн. Неавторизованному пользователю выдается имя Инкогнито с номером соединения.

Сообщения передаются пакетом message. Сервер после получения данного пакета, рассылает это сообщение всем онлайн пользователям чата, включая того кто его прислал.

Клиентская логика

В целом симметрична логике сервера, слушаем ping в ответ отправляем pong, при соединении с сервером пытаемся авторизоваться или войти неавторизованным. При получении пакета message создаем HTML объект с сообщением и добавляем его вверх списка сообщений.

Чат-бот

Тут все довольно просто, вопросы лежат в файле с разделителями. Чат-бот загружает вопросы в массив и рандомно их задает. Так как размер файла с вопросами занимает чуть больше мегабайта, то и не задумывался о том как хранить.

Бот может давать две подсказки, уменьшая тем стоимость выигрыша. Бот пишет сообщения всегда только если последнее сообщение в чате не от него самого. Выигранные очки приложение записывает прямо в базу пользователю.

Приложение поддержки

Из интересностей могу рассказать как сделать в Node.js прокси картинок.

var server = https.createServer(options, function(req, res) {
//Здесь какая-то там логика
//...
//photo_url это ссылка на оригинальную картинку

  var proxy = https.request(photo_url, function(local_res){
      console.log('piped request');
      local_res.pipe(res,{end:true});
  });
  req.pipe(proxy,{end:true});
}