Всем привет! Давненько тут ничего мы не публиковали, то времени не было, то нечем было делиться просто. Но теперь всё изменилось! Решил недавно я опробовать Node.JS. И по своему обыкновению решил сделать чат.
Находится он тут: http://chat.shpirat.net/
Обо всём по-порядку. Я нашёл этот чат где-то на просторах интернетов, когда искал мануалы по NodeJS. Он был сделан в качестве демки для демонстрации некоторых возможностей модуля express. Отличный, кстати, модуль! Но речь сейчас не столько о технических подробностях NodeJS, как о самом чате. Сначала я хотел переделать этот чат под себя. Изначально он был рассчитан только на общение между двумя собеседниками в одной комнате, не более. Плюс запрашивался email (для аватарки с gravatar).
Я долго ковырялся в его коде, пытаясь изменить и сделать его пригодным для общения между более, чем 2 человека. Всё понятно было, как оно работает, но… Переделывать в итоге надоело, и я просто взял и написал с нуля всё, лишь немного стянув некоторые дизайнерские кусочки с оригинального чата (потому что сам я плохо дружу с оформлением, хоть и понимаю, как оно работает) .
А весь протокол и все события написаны свои, потому что мне не очень понравилось, как было сделано в демо-примере.
В итоге получился вполне функциональный многопользовательский чат.
Сразу скажу, он ещё сыроват. Общаться можно, но его нужно ещё пилить и пилить, просто времени на него не особо много есть, да и не нужно в принципе это всё. Главное, что чат выполняет свою главную функцию чата!
Суть его вот в чём: создаётся комната со случайным идентификатором, и тот, кто первый к ней подключается, может выбрать себе ник и количество собеседников в комнате (от 2 до 20). Если ник удовлетворяет требованиям (допустимая длина и отсутствие запрещённых символов), то успешно входит в чат этот человек, и в шапке чата пишется сокращённая через goo.gl ссылка на текущую комнату, и можно эту ссылку передать другим людям. Можно делиться и не сокращённой ссылкой, а той, которая в адресной строке находится, потому что это она и есть, та самая ссылка на текущую комнату. Человек, получивший ссылку на комнату, может выбрать себе ник, и если такой ник ещё не используется в комнате и если он удовлетворяет требованиям, то совершается вход в комнату, где уже можно общаться с остальными 🙂
Анонимность и приватность. На сервере не хранится переписка, даже никакие логи не сохранятся. Все сообщения и другие события (кто-то пришёл или вышел из чата) сразу же рассылаются всем пользователям комнаты, в которой произошли эти события. И никак нельзя посмотреть список подключенных пользователей. Один и тот же пользователь может подключиться к разным комнатам, выбрать себе разные ники в тех комнатах, и никто даже не узнает, что это один и тот же пользователь. Поэтому чат можно назвать приватным и даже анонимным. Анонимным потому, что если ссылку дать не определённому человеку, а выложить где-то, или если просто кто-то будет перебирать подряд номера комнат и попадёт в Вашу, то никак и не узнать, что это за человек будет. Но вообще чат рассчитан на то, что определённый человек даёт ссылку на свою комнату именно нужным ему людям, что бы пообщаться приватно, без лишних глаз и без сохранения истории и логов. Я хотел прикрутить ещё и HTTPS к серверу, это тоже было в планах, но потом вот забросил и всё… К тому же, нет у меня сертификата нормального, и при подключении браузер бы говорил, что как-то не хочет доверять этому сайту.
UPD: Теперь работает и HTTPS! 😉
А если кто-то и хочет кого-то прослушать, то он найдёт способ всё равно, и никакой чат не спасёт… ) Так что это уже на совести каждого )
UserList. Справа отображается список участников чата. Цвет ника текущего человека — оранжевый. Остальные для него голубоватого цвета. В сообщениях такая же раскраска. Это сделано наверное для того, что бы легче было визуально отличать свои сообщения от не своих. В планах было: сделать для администратора комнаты всякие кнопки в списке пользователей, что бы он мог выкидывать неугодных пользователей из чата.
Так же есть оповещение о наборе текста. Слева от ника пользователя, который набирает текст, появляется значок карандашика )
Смайлы! Да! Они тут тоже есть! ) Использовал анимированные смайлики из старой доброй аськи. Правда окошко для выбора смайлов не сделано, но зато они вполне обычно заменяются из обычных текстовых смайлов. Так что, пора напрячь мозги и вспомнить коды стандартных смайлов из аськи 🙂 Хотя там есть не только стандартные… Ну и ладно. Кому они нужны, столько разных?… )
BB-коды. Поддержка нескольких простых BB-кодов:
[b]текст здесь довольно-таки жирный[/b]
[i]а тут наклоненный, как Пизанская башня[/i]
[u]за что? за что подчеркнули этот текст?![/u]
[s]вы можете прочитать этот зачёркнутый текст?[/s]
socket.io
Используется socket.io, что обеспечивает общение в режиме реального времени.
Ну, конечно и другие чаты тоже в реальном времени работают, но используют разные технологии, типа обновления по таймеру, постоянный запросы в отдельном скрытом фрейме и другие штуки, которые всё же больше похожи на костыли и являются лишь имитацией реального времени. Здесь же используются разные технологии, от самой новой — WebSocket, и по убывающей по мере поддержки браузером. Если браузер не поддерживает WebSocket, то есть ещё long pooling-запросы, а так же AJAX, а ещё Flash-евые сокеты могут использоваться. В общем, будет всё опробовано и выбрано самое подходящее для текущего браузера. И работать должно везде, скорее всего. К тому же socket.io предоставляет удобный транспорт для передачи событий в обе стороны, от клиента к серверу и наоборот. И это всё намного лучше, чем просто веб-сокеты… ) Ну, другие технические подробности можно и почитать на официальном сайте этой штуки.
Консольные команды. Ну… Название слишком громкое всё же… ) Эти команды — это то, что начинается со слеша и пишется в поле для ввода сообщений. Пока что там есть только одна команда, и это «/part». Если ввести эту команду, то чат отключится от сервера и… и всё. Дальше темнота незримая, пока заново не зайти в комнату или не выбрать или создать другую. А! Есть ещё команда «/alert». Она просто показывает обычное Alert-окошко с текстом, который является вторым параметром (написан через пробел). Остальные же команды можно сделать, но пока как бы и незачем. Хотя можно всякие административные команды, типа забанить или выкинуть пользователя определённого из чата, или известную в IRC команду «/me» (ага. И уж точно получится ещё один IRC, но без IRC сервера… 🙂 ).
Что же в итоге?
А в итоге чатик. Много разных идей было, когда я только начинал его делать. Но потом сделал до определённого рабочего этапа и забросил. А сейчас решил ради статьи доделать хотя бы ещё чуток, что бы уже можно было в общий доступ его пускать… 🙂
Сервер всегда запущен. Правда я не знаю, какую нагрузку он сможет выдержать… ) Вот может после выхода этой статьи и проверим 🙂
Этот чат не претендует на что-то серьёзное. Это лишь так, в качестве пробы и изучения ) Но если будут идеи, то можете писать их тут в комментариях. Если нужны будут исходники кому-то, то с удовольствием поделюсь своими наработками.. )
До встречи в чате 🙂
P.S.: вот архив с исходниками. Поправить нужно будет файл app.js — там установить слушающий порт.
Спасибо за статью. Скачал исходники.
При старте вот что имею:
Error: Cannot find module ‘goo.gl’
Как это победить?
PS nodejs первый раз вижу
Пожалуйста!
Пишет, что не может найти модуль goo.gl (в чате он нужен для вывода короткой ссылки на текущую комнату).
Чтобы это починить, нужно установить этот модуль, введя в консоли в текущей папке проекта команду:
npm install goo.gl
Либо можно просто установить (не в текущей папке, а глобально этот модуль) командой: npm install -g goo.gl
Сразу хочу предупредить: когда делался этот чат, ещё тогда мне было мало известно о всяких тонкостях и т.д., даже не был создан файл с описанием пакета и его зависимостями package.json, поэтому, скорее всего, даже установив необходимые библиотеки (типа express и socket.io) оно не заработает, т.к. версии там нужны немного старее, чем те, что есть сейчас.
В любом случае — пишите. Поможем )
Здравствуйте, установил все модули, запустил, но вышла ошибка Undefined is not a function on indexOf на var index = ns.connected[id].rooms.indexOf(roomId) ;
Изменил на var index = ns.connected[id].rooms.toString().indexOf(roomId) ;
Заработало! Зашел, создал чат комнату, но справа на панели список пуст, даже мой ник не отображается, где должен быть список пользователей… Попробовал подключится к комнате, но ее не видит, т.е. нужно создать ее, id комнаты разумеется одинаковый, сообщение в созданной комнате отправляются.. Запустил сервер на локалке http://localhost:88, думал с портом что то, поменял на http://localhost:8008 все равно такая же проблема, помогите разобраться ?
Прошу прощения за не быстрый ответ. Видимо, из-за ссылок комментарий попал в спам, а сейчас случайно его увидел… )
Проблема ещё актуальна? Если да, то можно написать мне в ВК (можно найти по нику, как и в телеграме).
отличная статья, идея чата очень впечатлила и максимально подходит под мои нужды, а вот проблема остается актуальной
Добрый день.
Не запускаются /socket.io/socket.io.js. Непонятно по какому пути он должен находиться. И не запускаются smileys.js и chat.js. Пути я правильно прописал, но почему-то не хотят. Не понятно зачем нужен порт в app.js, если к нему нет обращения. Если есть возможность, помогите разобраться.
Добрый день)
/socket.io/socket.io.js — это виртуальный путь, который доступен благодаря библиотеке socket.io, так что он и не должен находиться ни по какому пути :).
Можно проверить, пройдя по прямому пути: https://chat.shpirat.net/socket.io/socket.io.js и убедившись, что всё отдаётся как надо, даже если фактически файлика такого нет.
И вообще, этот проект был как первый эксперимент на NodeJS ещё 10 лет назад (!!!), вы только вдумайтесь! Как запущен был тогда, так и работает до сих пор.
Поэтому некоторые вещи могли быть сделаны не очень корректно.
Возможно, на новой версии NodeJS и новых версиях библиотек оно работает неправильно, т.к. поломана обратная совместимость.
Попробуйте сделать вот что:
— используйте NodeJS версии 12 (на ней сейчас работает этот чат)
— поставьте socket.io версии 1.1, а express — 4.13
— возможно, стоит переименовать файл packaje.json в package.json (только сейчас заметил ошибку :D)
Порт в app.js нужен как порт по-умолчанию. Там есть переменная (которую стоило бы сделать константой, да) listenPort, и если проследить по коду, то фактический порт сначала пытается получиться из ENV, который можно задать при запуске процесса, а если нет, тогда используется порт по-умолчанию — 88.
А сам чат из статьи, расположенный на chat.shpirat.net, спрятан за nginx. Поэтому даже если он слушает порт 88, он всё равно проксируется через nginx, чтоб быть доступным по определённому хосту и обычному http(s)