Приватный чат на node.js — что может быть проще?

    Привет, друзья!

    Дело было вечером, делать было нечего… Разбирая пример чата в Socket.IO, заинтересовала возможности без особых ухищрений сделать чат приватным. Идея не новая, и достаточна простая — выбираешь свой пол и возраст, указываешь желаемый пол и возраст собеседника, и, поехали! Своего рода рулетка.

    Итак, начнем с требований:

    1. Форма входа — указание пола и возраста (как для себя, так и для собеседника);
    2. Возможность создания приватных комнат (при отсутствии подходящего собеседника);
    3. Подключение к приватной комнате (при наличии собеседника);
    4. Анонимность (не будем сохранять никакие данные пользователя).


    Что нам потребуется?


    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

    Комментарии 21

      0
      Голосую за исходники :)

      P.S. А домен virt.in тоже пофану купили?
        0
        Домен прикупил на распродаже за 1$ :)
        Изначально были задумки по поводу такого чата — но в итоге от них отказался. Сейчас же стало жалко, что проект, который возможно кого-то заинтересует — пылится на жестком диске.
        +1
          0
          error connecting to server
          :(
          0
          Было бы интересно посмотреть целиком весь код проекта. Спасибо за топик!
            0
            немного «причешу», выложу и добавлю ссылку в апдейте к топику :)
            +1
            Прокомментируйте свою стену кода, пжалста.
            image
              –3
              Такое впечатление, что на nodejs только чатики можно делать.
                0
                Вот-вот.
                Node.js — любопытная платформа, но информации по ней не так уж много, а судя по разделу q&a далеко не все даже знают основы.
                И очередной пост — опять чат — тема, которая на здесь уже не раз была.
                Писать посты нелегко, но давайте всё же в их основу вкладывать какую-то новизну?
                  0
                  Какие темы Вас интересуют? Топик родился из проекта, поэтому тут не убавить, не прибавить. Есть наработки по групповому рисованию с использованием canvas, есть достаточно сложные парсеры форм.
                    0
                    Мне интересно всё новое, но групповое использование канваса прям заинтересовало :)
                    Я вообще что имел в виду — вот недавно пост был о роутинге в node.js — и имхо это было изобретение велосипеда, причём не лучшего.
                    Потому и говорю — от примеров и подробного описания более прикладных задач, нежели хитрого чата, пользы будет больше.
                  0
                  Это сильное преуменьшение.

                  Я на Node.js, например, заголовки фидопочты читал. Это никак не чатик.

                  Ещё на нём можно, например, в ZIP архивировать.

                  И так далее.
                  +1
                  А хостится node.js где?
                    0
                    Vps на хетцнере
                    0
                    А вот в nowjs.org/examples/hw коду в 4 раза меньше
                      +1
                      а архив с исходничками где можно скачать? :)
                        +1
                        Если сообщество заинтересует проект такого чата — сегодня же выложу на github, делалось just for fun.
                        Выкладывайте, пожалуйста.
                          0
                          room finded, говорите.
                            0
                            virt.in сдох
                              0
                              пользуйтесь, оживил :)
                                0
                                2 месяца… спасибо :)

                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                            Самое читаемое