推送器一对一聊天结构

9

我在Pusher平台上的presence-channels方面有点困惑,因为我正在从头构建聊天应用程序。现在,我知道你们中的一些人已经看到了大量的“实时聊天应用程序”主题,但是,我正在寻找一对一的点对点聊天,而不是站点范围的全球性聊天。更像Facebook聊天,您可以一对一聊天。

现在,我在PubNub的演示(名为Babel)中看到了一个例子,但是那个东西远非我要找的,因为我在控制台中检查了请求,即使未显示,其他用户之间发送的消息也会显示在我的网络请求日志中,因为它在JS中过滤而不是服务器端,并且这绝对不是我想要的。

因此,回到主题, 我知道频道/私有频道/存在频道功能,所以我决定这样做:

  • 打开应用程序时,每个用户都订阅其private-user_id频道(如果不存在,将创建它)。

  • 同时(在打开应用程序时),user1订阅presence-global频道,其他人可以跟踪朋友是否在线。

  • 当其他人想给他发送消息时,例如user2到user1,那么他随后订阅private-1,然后javascript将处理事件。

现在,我知道这里有些问题,因为..如果user3向user1发送消息,则他会订阅private-user1,因此我想他也会看到user2向user1发送消息时触发的事件,对吗?还是我理解错了?

我在他们的文档中读到,存在频道实际上是私有频道扩展,所以现在我在思考..为什么还要使用私人频道,然后,我如何通知所有朋友我在线。

但是,然后他们的文档中出现了其他问题,告诉我频道提供了两个重要的东西(其中之一),第一个是过滤数据的方法,第二个是控制访问的方法

既然没有文档中的链接,我该如何“过滤数据”,或者更好地说,您对一对一聊天有什么想法。如果我把他们的文档都搞错了,我很抱歉,我查看了他们的样本应用程序,但他们没有使用我正在寻找的一对一技术。

我对Pusher和socket连接等领域不太熟悉,但我已经学会了如何进行身份验证,如何在频道中创建、检测和处理事件,并且可以创建一个简单的全局聊天室来显示在线成员。然而,在涉及到私有频道时,我很困惑如何为两个用户创建单独的频道。

提前感谢您的帮助!

1个回答

21
私有频道的目的是限制可以订阅该频道的用户。因此,您可以选择以下两种方式之一:
  1. 使用它来确保只有用户的朋友可以订阅更新
  2. 仅为该用户使用通知
在一对一聊天中,我建议您选择后者(第2种)。
考虑到这一点,我会按照以下方式实现一对一聊天:

论坛

当用户加入聊天应用程序时,他们都会订阅两个频道:
  1. private-notifications-<user_id>,其中user_id是他们的唯一用户ID,例如我的情况下是leggetter。该频道用于特定于用户的通知。
  2. presence-forum适用于该论坛中的所有用户。问题称其为presence-global
实现方法如下:
var notifications = pusher.subscribe( 'private-notifications-user_one' );
var forum = pusher.subscribe( 'presence-forum' );

在订阅每个频道时,将进行频道身份验证过程。
在论坛中,您可以通过发送和接收消息,在presence-forum/presence-globalpresence channel上进行公共聊天。

开始一对一聊天

当一个用户(user_one)想要与另一个用户(user_two)私聊时,您需要在UI中触发此操作。例如,user_one点击user_two旁边的某些内容,表示他们想要一对一聊天。当这种情况发生时,应向服务器(权威机构)发出请求,指示user_one希望与user_two启动私人聊天†。
注意:†如果您选择了一对一聊天的频道命名约定,则私人频道身份验证实际上可以用作私人一对一聊天初始化。
当服务器收到此请求时,它可以为此一对一聊天生成唯一的私人频道名称。一种非常简单的方法是通过连接用户ID,例如private-chat-<initiating_user>-<receiving_user>(还有其他考虑因素,例如您可能希望确保频道名称在两个用户之间始终相同)。在我们的简单场景中,频道名称将是private-chat-user_one-user_two
然后,服务器可以在每个用户的私人通知频道上触发one-to-one-chat-request事件,在负载中提供一对一私人聊天频道名称。
// Trigger event on both user channels with one call
var channels = [ 'private-notifications-user_one', 'private-notifications-user_two' ];
// Additional event data could also be sent
// e.g. more info on the initiating user
var eventData = {
                  'channel_name': 'private-chat-user_one-user_two',
                  'initiated_by': 'user_one'
                  'chat_with'   : 'user_two'
                };
pusher.trigger( channels, 'one-to-one-chat-request', eventData );

user_one收到one-to-one-chat-request时,他们将订阅eventData.channel_name频道,并且该频道的身份验证过程将会进行。
// A lookup of private chats
// where the key is the user ID of the current user is chatting with
var privateChats = {};
notifications.bind( 'one-to-one-chat-request', function( data ) {

  // MY_USER_ID would need to be stored somewhere
  // and in this case the value would be 'user_one'.
  // expectingChatWith should make sure user_one is waiting for
  // a private chat response with the given user
  if( data.initiated_by === MY_USER_ID &&
      expectingChatWith( data.chat_with ) ) {
    startPrivateChat( data.chat_with, data.channel_name );
  }

} );

function startPrivateChat( withUserId, channelName ) {
  privateChats[ withUserId ] = pusher.subscribe( channelName );
}

user_two收到one-to-one-chat-request时,用户需要被通知请求并选择接受或拒绝。如果用户接受,则客户端代码简单地订阅该频道。如果用户拒绝,则应向服务器发送一个请求,并在private-notifications-user_one上触发事件,告诉其他们的一对一聊天请求已被拒绝。这将允许user_one取消订阅私人聊天频道。
var privateChats = {};
notifications.bind( 'one-to-one-chat-request', function( data ) {

  if( ... ) { ... }
  // has somebody request to chat with this user?
  else if( data.chatWith === MY_USER_ID ) {
    // Prompt the user
    // Note: more user info required
    displayChatPrompt( data );
  }

} );

// callback when the user accepts the chat request
function accepted( chatUserId, channelName ) {
  startPrivateChat( chatUserId, channelName );
}

// the user doesn't want to chat
function declined( chatUserId ) {
  // send info to the server indicating declined request
}

私人一对一聊天成功

user_oneuser_two都订阅了private-chat-user_one-user_two频道后,他们可以在频道上触发事件并参与他们的私人一对一聊天


1
我必须说,我为想出这种方法感到骄傲,但我在想是否会在这个主题上让自己变得复杂。我很高兴你花时间回复我,我愿意立即动手写代码!谢谢! - Eduard
写得非常好!我有点难以理解 if ( ... ) { ... } 是否有人请求与此用户聊天?我们应该在那里填什么.. 谢谢! - Miguel Stevens
1
@Notflip,之前的代码更像是伪代码,因为它在现实生活中无法运行。它的目的是让你了解事情的运作方式。与此同时,我已经制作了自己的聊天系统,可以在这里检查:http://socialjs.eduardd.eu(http://socialjs.eduardd.eu/static/js/chat.js)。请检查一下,也许可以帮助你理解这个系统的工作原理。请注意,我没有采用“userid_userid”命名约定,因为我正在创建用户组,所以频道名称不能是user1_user2_user3...user37。 - Eduard
1
非常感谢!我会看一下的! :) 这有点难以理解。正在尝试构建一种具有私人选项的聊天室。编辑:你的网站看起来真的很不错! - Miguel Stevens
我已经接近了,但是想知道(在上面的例子中)StartPrivateChat()方法会是什么样子?谢谢大家! - Miguel Stevens
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接