Русский
Русский
English
Статистика
Реклама

Чат

Чатик с открытым исходным кодом

19.02.2021 16:11:01 | Автор: admin

У меня последнее время нет времени или желания чтобы заниматься своим веб-проектом (чатик), который я разрабатывал 2 года; но очень не хочется чтобы мой труд пропадал.

Я уже показывал Хабру свою разработку, но так как она мало относится к тематике сайта, а исходников я не предоставил, статья не вызвала интерес аудитории.

Сегодня я публикую код. Возможно, кто-то обратит внимание на хорошую разработку и не даст проекту загнуться. Этот движок по настоящему хорошо реализует современный чат, где можно обмениваться медиа-контентом, вести свой альбом, ну и просто общаться. Я пытался сделать что-то лучше тех чатов, в которых сидел сам, и у меня это получилось. Конечно, моя разработка не тянет на широкий захват аудитории уровня вконтакта или телеграма, это просто красивый, юзабильный чатик для аудитории средних размеров, и там можно почти всё (в плане функционала).

Теперь о минусах

Когда я его разрабатывал, я ориентировался в первую очередь на компьютеры, потому что сам привык пользоваться именно им, а не телефоном (я вообще не понимаю как всякие зумеры предпочитают смартфон компьютеру). Поэтому лучше использовать ПК, если вы сидите на том сайте, хотя вам ничего не мешает зайти на него с мобилки, и вы даже сможете пользоваться адаптивной версией сайта. Лично я считаю, что мобильная версия немного подкачала (я, можно сказать, изначально вообще не предполагал ее в принципе, тем не менее она есть, и мне даже пару знакомых сегодня сказали что она весьма неплохая)

Если кому-то всё же интересно

В идеале я хочу отдать проект тому, кто готов его поддерживать, и даже помогу с установкой и настройкой (если вы еще не имели дело с node.js или у вас просто возникли какие-то трудности с работой модулей). А если вы захотите развивать его, помогу разобраться в коде и исправить некоторые баги (сразу скажу, что они есть, но их мало и они незначительные и не препятствуют свободному общению). Также приветствую тех, кто просто хочет использовать этот движок для своих целей, но брать чужой портал под ответственность не готов, я готов поделиться с Вами движком

О чем всё же речь

Сайт crawc.net (не обращайте внимания на ботов, их можно убрать). Исходный код и структуру базы данных можно скачать тут.

Более подробно почитать о сайте и его возможностях можно тут.

Подробнее..

Чаты на вебсокетах, когда на бэкенде WAMP. Теперь про Android

13.01.2021 22:20:55 | Автор: admin

Мой коллега уже писал про наш опыт разработки чатов на вебсокетах для iOS, поэтому часть про особенности бэкенда с точки зрения клиента у нас общая. А вот реализация на Android, конечно, отличается. И ещё мне не приходилось, как в первой статье, искать библиотеку для поддержки старых версий операционной системы, потому что на Android каких-то глобальных изменений в сетевой части не было, всё работало и так.

К реализации вернёмся чуть ниже, а начнём с ответов на вопросы про бэкенд, которые появились после первой статьи: почему WAMP, какой брокер используем и некоторые другие моменты.

На время передам слово нашему бэкенд-разработчику @antoha-gs, а если хочется сразу почитать про клиент-серверное общение и декодирование, то первый раздел можно пропустить.

Что там на бэкенде

Почему WAMP. Изначально искал открытый протокол, который мог бы работать поверх WebSocket с поддержкой функционала PubSub и RPC и с потенциалом масштабирования. Лучше всего подошёл WAMP одни плюсы, разве что не нашёл реализации протокола на Java/Kotlin, которая бы меня устраивала.

Какой брокер мы используем. Продолжая предыдущий пункт, это, собственно, и послужило написанию собственной реализации протокола. Плюсы экспертиза в своём коде и гибкость, то есть при надобности всегда можно отойти от стандарта в нужную сторону. Каких-то серьёзных минусов не выявил.

К небольшим проблемам реализации проекта чатов можно отнести то, что нужно было ресёрчить и ревёрсить то, как работает реализация на Sendbird сервисе, который мы использовали. То есть какими возможностями мы там пользовались и какой дополнительный функционал был реализован поверх. Также к сложностям отнёс бы перенос данных из Sendbird в свою базу.

Ещё был такой момент в комментариях:

Правильно, что не стали использовать Socket.IO, так как рано или поздно столкнулись бы с двумя проблемами: 1) Пропуск сообщений. 2) Дублирование сообщений. WAMP к сожалению также не решает эти вопросы. Поэтому для чатов лучше использовать что-то вроде MQTT.

Насколько я могу судить, протокол не решает таких проблем магическим образом, всё упирается в реализацию. Да, на уровне протокола может поддерживаться дополнительная информация/настройки для указания уровня обслуживания (at most/at least/exactly), но ответственность за её реализацию всё равно лежит на конкретной имплементации. В нашем случае, учитывая специфику, достаточно гарантировать надёжную запись в базу и доставку на клиенты at most once, что WAMP вполне позволяет реализовать. Также он легко расширяем.

MQTT отличный протокол, никаких вопросов, но в данном сравнении у него меньше фич, чем у WAMP, которые могли бы пригодиться нам для сервиса чатов. В качестве альтернативы можно было бы рассмотреть XMPP (aka Jabber), потому что, в отличие от MQTT и WAMP, он предназначен для мессенджеров, но и там без допилов бы не обошлось. Ещё можно создать свой собственный протокол, что нередко делают в компаниях, но это, в том числе, дополнительные временные затраты.

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

Клиент-сервер

Начну с того, что WAMP означает для клиента.

  • В целом протокол предусматривает почти всё. Это облегчает взаимодействие разработчиков клиентской части и бэка.

  • Кодирование всех типов событий в числах (PUBLISH это 16, SUBSCRIBE 32 и так далее). Это усложняет чтение логов разработчику и QA (сразу не догадаться, что значит прилетевшее сообщение [33,11,5862354]).

  • Механизм подписок на события (например, новые сообщения в чат или обновление количества участников) реализован через получение от бэкенда уникального id подписки. Его надо где-то хранить и ни в коем случае не терять во избежание утечек. Как это сделано (было бы сильно проще и подписываться и отписываться просто по id чата):client подписываемся на новые сообщения в чате [32,18,{},"co.fun.chat.testChatId"]backend [33,18,5868752 (id подписки)]client после выхода из чата отписываемся по id [34,20,5868752]

Для работы с сокетом использовали OkHttp (стильно, надёжно, современно, реализация ping-pong таймаутов из коробки) и RxJava, потому что сама концепция чата практически идеальный пример того самого event-based programming, ради которого Rx, в общем, и задумывался.

Теперь рассмотрим пример коннекта к серверу, использующему WAMP-протокол через OkHttpClient:

val request = Request.Builder()    .url(ChatsConfig.SOCKETURL)    .addHeader("Connection", "Upgrade")    .addHeader("Sec-WebSocket-Protocol", "wamp.json")    .addHeader("Authorization", authToken)    .build()val listener = ChatWebSocketListener()webSocket = okHttpClient.newWebSocket(request, listener)

Пример реализации ChatWebSocketListener:

private inner class ChatWebSocketListener : WebSocketListener() {override fun onClosed(webSocket: WebSocket, code: Int, reason: String) { connectionStatusSubject.onNext(ChatConnectionStatuses.NOTCONNECTED) //subject, оповещающий пользователей о состоянии коннекта (в UI нужен для отображения лоадеров, оффлайн-стейтов и так далее)}override fun onClosing(webSocket: WebSocket, code: Int, reason: String) { webSocket.close(1000, null)}override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { onConnectionError("${t.message} ${response?.body}")}override fun onMessage(webSocket: WebSocket, text: String) { socketMessagesSubject.onNext(serverMessageFactory.processMessage(text)) //subject, через который идут все сообщения, которые в дальнейшем фильтруются для конкретных получателей (см. ниже)}override fun onOpen(webSocket: WebSocket, response: Response) { authorize() }}

Здесь мы видим, что все сообщения от сокета приходят в виде обычного String, представляющего собой JSON, закодированный по правилам WAMP протокола и имеющий структуру:

[ResultCode: Int, RequestId: Long, ArgumentsMap: JsonObject ]

Например:

[50, 7, {"type":100, "chats":[список чатов]}]

Декодирование и отправка сообщений

Для декодинга сообщений в объекты мы использовали библиотеку Gson. Все модели ответа отписываются обычными data-классами вида:

@DontObfuscatedata class ChatListResponse(@SerializedName("chats") val chatList: List<Chat>)

А декодирование происходит с помощью следующего кода:

private fun chatListUpdateInternal(jsonChatsResponse: JSONObject):ChatsListUpdatesEvent { return gson.fromJson(jsonChatsResponse.toString(), ChatsListUpdatesEvent::class.java)}

Теперь рассмотрим базовый пример отправки сообщения по сокету. Для удобства мы сделали обёртку для всех базовых типов WAMP сообщений:

sealed class WampMessage { class BaseMessage(val wampId: Int, val seq: Long, val jsonData: JSONArray) : WampMessage()  class ErrorMessage(val procedureId: Int, val seq: Long, val jsonData: JSONArray) : WampMessage() object WelcomeMessage : WampMessage() class AbortMessage(val jsonData: JSONArray) : WampMessage()}

А также добавили фабрику для формирования этих сообщений:

fun getCallMessage(rpc: String,         options: Map<String, Any> = emptyMap(),         arguments: List<Any?> = emptyList(),         argumentsDict: Map<String, Any?> = emptyMap()):WampMessage.BaseMessage { //[CALL, Request|id, Options|dict, Procedure|uri, Arguments|list] val seq = nextSeq.getAndIncrement() return WampMessage.BaseMessage(WAMP.MessageIds.CALL,               seq,               JSONArray(listOfNotNull(WAMP.MessageIds.CALL,               seq,               options,               rpc,               arguments,               argumentsDict)))}

Пример отправки сообщений:

val messages: Observable<WampMessage> = socketMessagesSubjectfun sendMessage(msgToSend: WampMessage.BaseMessage): Observable<WampMessage> { return messages.filter {   it is WampMessage.BaseMessage && it.seq == msgToSend.seq}    .take(1)    .doOnSubscribe {     webSocket.send(msgToSend.jsonData.toString())    }}

Сопоставление отправленного сообщения и ответа на него в WAMP происходит с помощью уникального идентификатора seq, отправляемого клиентом, который потом кладётся в ответ.

В клиенте генерация идентификатора делается следующим образом:

companion object { private val nextSeq: AtomicLong = AtomicLong(1)}fun getNextSeq() = nextSeq.getAndIncrement()

Взаимодействие с WAMP Subscriptions

Подписки в протоколе WAMP концепт, по которому подписчик (клиент) подписывается на какие-либо события, приходящие от бэкенда. В нашей реализации мы использовали:

  • обновление списка чатов;

  • новые сообщения в конкретном чате;

  • изменение онлайн-статуса собеседника;

  • изменение в составе участников чата;

  • смена роли юзера (например, когда его назначают модератором);

  • и так далее.

Клиент сообщает серверу о желании получать события с помощью следующего сообщения:

[SUBSCRIBE: Int, RequestId: Long, Options: Map, Topic: String]

Где topic это скоуп событий, которые нужны подписчику.

Для формирования базового события подписки используется код:

fun getSubscribeMessage(topic: String, options: Map<String, Any> = emptyMap()): WampMessage.BaseMessage { val seq = nextSeq.getAndIncrement() return WampMessage.BaseMessage(WAMP.MessageIds.SUBSCRIBE,                 seq,                JSONArray(listOfNotNull(WAMP.MessageIds.SUBSCRIBE,                                seq,                                options,                                topic)))}

Разумеется, при выходе с экрана (например, списка чатов), необходимо соответствующую подписку корректно отменять. И вот тут выявляется одно из свойств протокола WAMP: при отправке subscribe-сообщения бэкенд возвращает числовой id подписки, и выходит, что отписаться от конкретного топика нельзя нужно запоминать и хранить этот id, чтобы использовать его при необходимости.

А так как хочется оградить пользователей API подписок от лишнего менеджмента айдишников, было сделано следующее:

private val subscriptionsMap = ArrayMap<String, Long>()private fun getBaseSubscription(topic: String): Observable<WampMessage> { val msg = wampClientMessageFactory.getSubscribeMessage(topic) return send(msg).map {   val subscriptionId = converter.getSubscriptionId((it.asBaseMessage()).jsonData)   subscriptionsMap[topic] = subscriptionId   subscriptionId}    .switchMap { subscriptionId ->      chatClient.messages.filter {       it.isMessageFromSubscription(subscriptionId)     }    }}

Так клиент ничего не будет знать об id, и для отписки ему будет достаточно указать имя подписки, которую необходимо отменить:

fun unsubscribeFromTopic(topic: String) { if (!subscriptionsMap.contains(topic)) {    return } val msg = wampClientMessageFactory.getUnsubscribeMessage(subscriptionsMap[topic]) send(msg, true).exSubscribe() subscriptionsMap.remove(topic)}

Это то, что я хотел рассказать про реализацию на Android, но если есть вопросы постараюсь ответить на них в комментариях. Напомню, что про чаты на вебсокетах в iOS мы уже писали вот здесь, а также готовим отдельную часть про бэкенд.

Подробнее..

Из песочницы Онлайн Магазин будущего

04.11.2020 18:10:50 | Автор: admin
Последний кризис показал, как важно уметь продавать онлайн. Угроза второй волны гонит магазины в киберпространство.

Мало сделать сайт. Надо привести в него людей. Стоимость привлечения посетителей в веб-магазины зашкаливает. Остается горестно вспоминать те времена, когда пионеры индустрии деловито занимали места на новой торговой площадке. Поисковики были маленькими, а цены зелеными.

Между тем, новые привычки уже формируются, и важно оказаться в правильном месте раньше конкурентов. Для этого, предлагаю совершить мысленную прогулку в недалекое будущее интернета вообще и онлайн магазина в частности. А направление зададут тренды.

Мы как-то все привыкли, что серьезный интернет бизнес строится на компьютерном интернете. А между тем

image

Уходим от конкуренции


По данным Digital 2020 больше половины времени(50.1%), которое мы проводим в интернете теперь приходится на мобильные телефоны.
Тренд 1: Мобильный интернет начинает доминировать
Аналитики из App Annie заявляют, что на мобильные приложения теперь приходится 10 из каждых 11 минут пользования мобильным устройством, а на просмотр веб-страниц уходит только 9% нашего мобильного времени. Приходится признать, что роль магазинов здесь выполняют мобильные приложения. Правила игры совсем другие. И конкуренция существенно ниже.
Тренд 2: В мобильной среде первую скрипку играют мобильные приложения

Снимаем ограничения


Обычно мобильные магазины работают с небольшим ассортиментом товаров/услуг. Ограничение напрямую связано с маленьким экраном смартфона.

Мы привыкли использовать меню классификации для поиска товара. Прайс в несколько тысяч наименований, в маленьком окошке, превращается в кошмар с картинками (как же без них). Большой объем данных делает классификатор не эффективным.



На заре интернета существовали классификаторы сайтов желтые страницы интернета. Они забыты. Сейчас, мы считаем нормальным, написать запрос и найти ответ в первой десятке выдачи поисковиков.

Похоже, что мы лучше стали общаться с компьютером. Монолог: "Смотри что у меня есть", меняется на диалог: "Что вам угодно?". Если пофантазировать, то вполне естественно сообщить телефону: "Хочу капучино", и получить его, где-нибудь поблизости.
Тренд 3: Среди большого объема данных, доминирует поиск по запросам, близким к естественному общению.
Заменяя классификатор на запросы, мы получим несколько плюшек.

  • Не надо ломать голову что важнее: категория Сапоги/Туфли или Мужские/Женские.
  • Легко использовать сложный товар с характеристиками. Для обуви это размеры и цвет, для автомобилей это марка авто или номер кузова.
  • Мы, побуждаем пользователя формулировать желание. Это помогает онлайн продавцу мониторить ход визита и помогать покупателю не задавая лишних вопросов.

Развивающийся искусственный интеллект делает язык запросов естественнее и точнее. Известны удачные кейсы с запросами по фотографиям или голосом. Обратите внимание, что та-же Яндекс Алиса наиболее полезна именно в мобильном секторе. С компьютера не сделать фотографию или видео так же свободно, как с телефона.
Смартфон в наименьшей степени удобен для коммуникации на экране, в наибольшей для голоса, фото или видео общения.
Примерно половина из 3,7 часов в день, которые люди проводят с мобильными в руках, они тратят на приложения социальных сетей и мессенджеры.

image
Тренд 4: Самые популярные мобильные приложения социальные сети и месcенджеры.
Время подвести итоги и заметить, что интернет смещается в сторону мессенджеров в мобильных устройствах. Вот удивил! Поддержка общения, это прямое назначение телефона. Можно ли утверждать, что к этому стремится центр тяжести всего интернета?

Давайте рассуждать: Интернет, это в первую очередь способ коммуникации. Мобильный телефон это средство коммуникации которое всегда под рукой. Коммуникации с кем? Не только с человеком, но и программой. Самое время вспомнить очередной тренд:


Тренд 5: Чат-боты набирают популярность
В более общем случае я бы сформулировал общее направление так:
Развитие интернета идет в сторону естественного общения человека
с человеком или машиной посредством мобильного терминала.
Я далек от радикальных мыслей, что все остальное вымрет. Думаю, что на горизонте ближайших 5-10 лет будет преобладать такая вот клиент-серверная архитектура, где основными клиентами выступают мобильные телефоны в лице своих владельцев. Не претендуя на роль первооткрывателя посмотрим через призму этой формулировки на онлайн торговлю.

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

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

Написать Мобильное приложение это недешево. А наделить его способностями серьезного чата и подавно. Как оказаться на этой поляне раньше других?

Снижаем стоимость


Если найдем уже существующее приложение, это серьезно снизит стоимость проекта. Натянем логику чат-бота на морду существующих мессенджеров.

И знаете, выбор пока оказывается не велик Чат-боты, так или иначе, можно сделать во многих мессенджерах, но способности Telegram заметно шире. Самое важное для нас отличие, это возможность программировать кнопки (Помнить и набивать команды вручную, понравится не каждому). Если знаете аналоги напишите пожалуйста в комментарии.

Вдобавок, каналы делают Телеграмм социальной сетью. А это не лишняя плюшка в способностях онлайн магазина.
Телеграмм с чат-ботом это недорогая основа собственного онлайн магазина.
Получается достаточно запрограммировать внутреннюю логику чат-бота, об остальном позаботится мультиплатформенный Telegram.

Я предпринял попытку создать такой чат-бот. То что у меня получилось, после установки Телеграмм, можно посмотреть на https://t.me/repassBot.
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru