在 Firebase 中管理聊天频道的最佳方式

IT技术 javascript arrays firebase chat
2021-02-02 10:06:47

在我的主页中,我有一个用户列表,我想选择并打开一个频道与其中一个人聊天。

我在想是否使用 id 是最好的方法并控制对像 USERID1-USERID2 这样的通道的访问。

但是当然,用户 2 也可以打开相同的频道,所以我想找到更容易控制的东西。

如果你想帮助我,请给我一个使用 firebase url/array 的 javascript 示例。

谢谢!

4个回答

处理这种 1:1 聊天室的常用方法是根据用户 ID 生成聊天室 URL。正如您已经提到的,一个问题是任何一个用户都可以发起聊天,在这两种情况下,他们都应该在同一个房间里结束。

您可以通过在复合键中按字典顺序对用户 ID 进行排序来解决此问题。例如使用用户名而不是 id:

var user1 = "Frank"; // UID of user 1
var user2 = "Eusthace"; // UID of user 2

var roomName = 'chat_'+(user1<user2 ? user1+'_'+user2 : user2+'_'+user1);

console.log(user1+', '+user2+' => '+ roomName);
            
user1 = "Eusthace";
user2 = "Frank";

var roomName = 'chat_'+(user1<user2 ? user1+'_'+user2 : user2+'_'+user1);

console.log(user1+', '+user2+' => '+ roomName);
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>

一个常见的后续问题似乎是如何显示当前用户的聊天室列表。上面的代码没有解决这个问题。正如在 NoSQL 数据库中常见的那样,您需要扩充数据模型以支持此用例。如果您想显示当前用户的聊天室列表,您应该对数据进行建模以允许这样做。最简单的方法是将每个用户的聊天室列表添加到数据模型中:

"userChatrooms" : {
  "Frank" : {
    "Eusthace_Frank": true
  },
  "Eusthace" : {
    "Eusthace_Frank": true
  }
}

如果您担心键的长度,您可以考虑使用组合 UID 的哈希码而不是完整 UID。

我知道这很旧,但是,只是在寻找一些想法。您可以通过将用户放在一个数组中并对其进行排序来使其灵活。然后,为了便于使用并防止其他人轻易猜到房间名称,只需从中制作一个 MD5,或者以某种方式对其进行散列。通过这种方式,您可以扩大房间中的用户数量。我已经使用了一段时间,它非常好。
2021-03-12 10:06:47
这是一个很好的答案,谢谢。但我想知道如何确保这个聊天室名称是唯一的。特别是对于更常见的名称。即使我将聊天内容存储在两个用户节点中,我也可以与 2 个 Franks 聊天。现在我正在考虑只使用 FB 键进行聊天,在每个用户的 /conversations 中存储一个对它的引用,其中有 withUser:recipientUid 然后当其中一个用户发起聊天时,只需检查以确保一个人还没有与其他用户存在。看起来这可能不是最好的设计。有什么想法吗?谢谢!
2021-03-12 10:06:47
@Frank van Puffelen 如果有人离开小组怎么办?房间名称更改?如果是这样,其他人将失去之前对话的链接。将room推送到房间的集合,并将生成的id添加到所有成员中,生成room-id有什么害处?
2021-03-22 10:06:47
如果您还想为每个用户聊天室(在每个用户的上下文中)保留未读计数,您是否会在每个聊天室对象中保留 lastRead 和 lastUpdated 时间戳?
2021-03-27 10:06:47
谢谢你的积分。使用 js-sha256 module进行散列对我有用。'让 chatHash = SHA256('agent:' + agentId + '_user:' + userId)'
2021-03-28 10:06:47

在典型的数据库模式中,每个频道/聊天组都有自己的节点,带有唯一的 $key(由 Firebase 创建)。哪个用户首先打开频道无关紧要,但是一旦创建了节点(和相应的 $key),您就可以将其用作频道 ID。

散列/ MD5 策略当然是另一种方法,但是您还必须将“路由”信息以及 $key 存储在同一节点上 - 这是重复的 IMO(除非我遗漏了一些东西)。

我认为他们这样做是为了保留用户开始聊天的信息。
2021-03-23 10:06:47
虽然创建散列是对用户名进行排序的,但最终你真的不知道是谁启动了该频道。如果你真的需要这些信息,你可以在你的聊天频道节点下创建属性。通常,如果频道有多个用户,您应该让某个人成为该频道的“管理员”并赋予一些特殊的“权力”,但这取决于您的应用程序的需求。
2021-04-04 10:06:47

我们决定散列用户的 uid,这意味着你可以查找任何现有的对话,如果你知道其他人的 uid。

每个对话还存储了其安全规则的 uid 列表,因此即使您能猜出哈希值,您也会受到保护。

在 Frank van Puffelen 和 Eduard 的指导下,使用 js-sha256 module进行散列对我有用。

import SHA256 from 'crypto-js/sha256'
let agentId = 312
let userId = 567
let chatHash = SHA256('agent:' + agentId + '_user:' + userId)
这里的要点是创建一个带有 id 的发送者和接收者字符串。因此,在我的示例中,我们创建了一个字符串:“agent:142_user:5346”,这意味着代理 ID 为 142,用户 ID 为 5346。您也可以在字符串中使用两个用户,例如“user:123_user:312”。然后为了使其难以阅读,我们使用哈希算法。它会转换诸如“e769925f0d2068d6280e3a61b6”之类的东西。我在这里使用 SHA256,但您可以使用不同的算法,如 MD5 等。
2021-03-13 10:06:47
你能提供更多关于你如何做到这一点的信息吗?我一直在尝试不同的东西并且无法理解它。
2021-03-21 10:06:47
这是生成长度为 64 的字符串。所有聊天室都维护一个参与者数组,以便我们可以轻松查询是否存在任意数量的用户进行过聊天的聊天,这不是很好吗?在一般情况下,它也可以适合任何数量的用户。在这个散列用例中,您必须记住放置字符串的模式,如果您与 100 多个用户进行群聊,这也不会很好。那么你会循环并且肯定会使代码更复杂??
2021-04-07 10:06:47