Привет, друзья!
Дело было вечером, делать было нечего… Разбирая пример чата в Socket.IO, заинтересовала возможности без особых ухищрений сделать чат приватным. Идея не новая, и достаточна простая — выбираешь свой пол и возраст, указываешь желаемый пол и возраст собеседника, и, поехали! Своего рода рулетка.
Итак, начнем с требований:
Node.JS (на момент написания — 0.6.14) c модулями express, socket.io. Дополнительно используются nib, stylus, i18n и util.
Итак, поехали.
Тут все достаточно просто. Создаем объект пользователя, инкриментим счетчики, обновляем цифры у клиентов.
Под входом имеется ввиду уже вход в сам чат — после выбора требуемых параметров на начальной форме.
Сам механизм выбора собеседника реализован в виде простого цикла (не знаю, насколько это будет быстро работать при большой нагрузке). Проверяем введенные параметры, сравниваем их и при совпадении инициируем подключение к другому пользователю, либо оставляем ждать.
Осталось дело за малым — собственно позволить пользователям общаться между собой.
Ну и собственно…
На этом всё. Тестировалось под нагрузкой < 10 человек, проблем не возникало :) Если сообщество заинтересует проект такого чата — сегодня же выложу на github, делалось just for fun.
P.S. Топик начинал писаться давно, и перенесен из черновиков — поэтому версии указанных продуктов могут быть не актуальны.
P.S.S. Посмотреть в живую можно тут — virt.in
UPD. Обещанные исходики лежат тут — github.com/eudj1n/virtin
Дело было вечером, делать было нечего… Разбирая пример чата в Socket.IO, заинтересовала возможности без особых ухищрений сделать чат приватным. Идея не новая, и достаточна простая — выбираешь свой пол и возраст, указываешь желаемый пол и возраст собеседника, и, поехали! Своего рода рулетка.
Итак, начнем с требований:
- Форма входа — указание пола и возраста (как для себя, так и для собеседника);
- Возможность создания приватных комнат (при отсутствии подходящего собеседника);
- Подключение к приватной комнате (при наличии собеседника);
- Анонимность (не будем сохранять никакие данные пользователя).
Что нам потребуется?
Node.JS (на момент написания — 0.6.14) c модулями express, socket.io. Дополнительно используются nib, stylus, i18n и util.
Итак, поехали.
Подключение нового пользователя
Тут все достаточно просто. Создаем объект пользователя, инкриментим счетчики, обновляем цифры у клиентов.
var user = {}; var uid = socket.store.id; var room_id = uid + "_room"; online++; total++; socket.broadcast.emit('online', total, free); socket.emit('online', total, free); user.id = socket.store.id; users[socket.store.id] = user;
Вход пользователя
Под входом имеется ввиду уже вход в сам чат — после выбора требуемых параметров на начальной форме.
Сам механизм выбора собеседника реализован в виде простого цикла (не знаю, насколько это будет быстро работать при большой нагрузке). Проверяем введенные параметры, сравниваем их и при совпадении инициируем подключение к другому пользователю, либо оставляем ждать.
socket.on('nickname', function (nick, m_sex, m_age, c_sex, c_age, fn) { if (nicknames[socket.user_id]) { fn(true); } else { fn(false); nicknames[socket.store.id] = socket.nickname = socket.store.id; socket.user_id = socket.store.id; socket.gender = m_sex; var user = users[socket.store.id]; user.m_sex = m_sex; user.m_age = m_age; user.c_sex = c_sex; user.c_age = c_age; user.active = 0; free++; // Check existing rooms for(var __room in rooms){ if(user.active == 0){ _room = rooms[__room]; if(_room.c_sex == m_sex && _room.c_age == m_age && _room.m_sex == c_sex && _room.m_age == c_age && _room.active == 0){ room_id = _room.id; _room.active = 1; _room.nicknames[socket.user_id] = socket.user_id; user.active = 1 free--; console.log(' room finded! this - ' + room_id); } } } // Create own room if(user.active == 0){ console.log(' no room finded :( create own - ' + room_id); var room = {}; room.id = room_id; room.m_sex = m_sex; room.m_age = m_age; room.c_sex = c_sex; room.c_age = c_age; room.active = 0 room.nicknames = {}; room.nicknames[socket.user_id] = socket.user_id; rooms[room_id] = room; socket.emit("user message", "System", i18n.__("waiting")); } users[socket.store.id] = user; socket.join(room_id); socket.broadcast.to(room_id).emit('announcement', socket.user_id + ' ' + i18n.__('connected')); socket.broadcast.to(room_id).emit('nicknames', rooms[room_id].nicknames); socket.emit('nicknames', rooms[room_id].nicknames); } });
Осталось дело за малым — собственно позволить пользователям общаться между собой.
Отправка сообщений
socket.on('user message', function (msg) { msg = sanitize(msg).entityEncode(); console.log(' message from ' + socket.user_id + ' to room ' + room_id + ": " + msg); socket.broadcast.to(room_id).emit('user message', socket.gender == 1 ? i18n.__("he") : i18n.__("she") , msg); });
Ну и собственно…
Выход
socket.on('disconnect', function () { online--; total--; socket.broadcast.emit('online', total, free); if (!socket.user_id) return; if(free > 0) free--; socket.broadcast.emit('online', total, free); console.log(socket.user_id); socket.leave(room_id); socket.broadcast.to(room_id).emit('announcement', socket.user_id + ' ' + i18n.__('disconnected')); if(rooms[room_id]) delete rooms[room_id].nicknames[socket.user_id]; if(rooms[room_id]) socket.broadcast.to(room_id).emit('nicknames', rooms[room_id].nicknames); delete users[socket.user_id]; delete nicknames[socket.user_id]; delete rooms[room_id]; });
На этом всё. Тестировалось под нагрузкой < 10 человек, проблем не возникало :) Если сообщество заинтересует проект такого чата — сегодня же выложу на github, делалось just for fun.
P.S. Топик начинал писаться давно, и перенесен из черновиков — поэтому версии указанных продуктов могут быть не актуальны.
P.S.S. Посмотреть в живую можно тут — virt.in
UPD. Обещанные исходики лежат тут — github.com/eudj1n/virtin
