We want to create threads for messages within a chat channel on Pubnub. For example, someone could respond to a specific message in a channel by 'creating a thread' and starting to chat. Is there a prescribed way to model this behavior? If so, can you please reference documentation?
This is the behavior you see in slack, for reference.
There's no ready-made solution documented for threaded messaging. However, building a hierarchical relationship between messages could be achieved by tagging them with metadata (using PN Objects and/or MessageActions) and then some coding on your end to maintain and handle their relationship.
You could use the time token of the thread's first message as the key, group messages based on it, and use the messages' own time tokens to generate the order for the UI.
https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe#methods
Here's the high-level design for doing this:
A message is published to a channel with the name chat_11223344 (channel name uses chat_ as a prefix for all chat channels and a generated id - keeping it short here but you can use a uuid generator for this). That publish returns a publish timetoken, something like this: 16183330926487763.
Using PN Objects, your display name for the channel can be set along with a description.
In your chat UI, you allow a person to create a thread on that message. The message gets published to a channel named chat_11223344.16183330926487763 , using the publish timetoken of the top-level message as the "sub-channel" name.
So that you can easily identify top-level messages that are threaded, you would add a MessageAction to that message when the first "threaded" message is published. You may also want to add custom Channel Metadata (PN Objects, again) to add a "isThreaded":true key/value.
So with PubNub you can append meta data to either the message itself or PubNub has a section called meta (https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe#methods).
An example payload could be:
{
"type":"message",
"payload":"What do people want for lunch? Pizza?",
"sender":"me",
"sent":1618336638,
"messageActive":true,
"channel":"main",
"messageID":"main.abc123"
}
where abc123 is a uuid that references that message.
When someone wants to thread a message you can append "threaded":true variable to the object.
{
...
"messageID":"main.abc123",
"threaded":true,
...
}
Now your UI knows that there is a breakout thread, using main.abc123.thread as the channelID for that specific thread.
Your app then subscribes to the new channel main.abc123.thread and you can use fetchMessages(); to get history messages as well as new real time messages.
Related
I have a function of automatized channels,
All changes are triggered with voiceStateUpdate event.
All work very good but when a user disconnect from server, voiceStateUpdate is not called...
So how can i know if user leave with disconnection from server ?
UPDATE :
I finally got it in voiceStateUpdate, I just dont check if newMember or oldMember, I make my channels update directly by Client and not by the user.
There is currently no voiceStateUpdate event emitted when a Member disconnects from a voicechannel by leaving the Guild. This is a limitation with Discord itself, not the library.
I'd suggest using the guildMemberRemove event, which emits a GuildMember object. You can use that Object to loop through all the voicechannels in the Guild and check which one the Member disconnected from when leaving.
You can save users who are in the voice channel and then checking if the user who left the guild is in the list.
Upon testing, voiceStatusUpdate does not fire when a user has exit. This seems to be an issue with Discord itself. The guildMemberRemove event does fire, though. So to work around this, you must create an array that holds the user's ID, and if a member leaves, check if they were in a voice channel. If you want to monitor multiple channels, you can put all of the channels in an object with the channel ID as a key, and the array of participants (using their IDs, to preserve memory) as the value.
Depending on what method you choose, the resulting object might look like this.
{
"channel1ID": ["member1ID", "member2ID"],
"channel2ID": ["member3ID", "member4ID"]
}
Now when a member disconnects, simply remove their name from the array of the voice channel they were in. When a member leaves, check every array for their ID. Using this, you'll also be able to get the ID of the channel the member was originally part of.
If I'm building something like a real time stock update page and want to send the updates via SSE - is the best practice to embed any parameters you need for the service (the stock symbol) as part of the channel name? Something like
var msgSrc = new EventSource('http://localhost/dvsvc/event-stream?channels=stockupdates-MSFT');
Yeah that's fine, although I'd make the name shorter as if a user wants to subscribe to multiple stocks they'd need to all be included so i'd be inclined to just use the stock ticker, e.g:
/event-stream?channels=MSFT,GOOG,AMZN,FB,AAPL,IBM,INTC
I'm creating a bot in DirectLine. I'm trying to use SuggestedActions to display a suggested action and I don't want to include the text attribute for that. When I try to run my code without the text attribute, I see a blank message being displayed. How can I avoid that?
My code
var msg = new builder.Message(session)
.suggestedActions(
builder.SuggestedActions.create(
session, [
builder.CardAction.imBack(session, "disconnect", "Disconnect"),
]
));
session.send(msg);
The Output i'm getting:
Per my understanding, you want a button which is shown absoluted at bottom and always display to remind your agent that he can disconnect conversation any time.
However, per me testing and understanding, in my opinion, there 2 points that it's maybe not a good idea to achieve this feature:
SuggestedAction is based on Messasge in Bot framework. And basically Bot application is for conversation. So every message between user and bot renderred in different channels should always be contained in a textbox, shown like in your capture. We cannot bypass this feature.
Per your requirements, I think you want this button should be always display unless the agent click it. But I didn't find any feature like this in Bot framework, and you may need to send this meesage additionally beside every message from bot, which is not graceful and will raise unpredictable risk.
My suggestion is that you can create a triggerAction to handle global disconnect requests. Refer https://learn.microsoft.com/en-us/bot-framework/nodejs/bot-builder-nodejs-dialog-actions for more info.
I am curious to find out how you guys are incorporating meta data about command/event messages in a cqrs solution. For example, I want to know who, when, which host, etc. generated the command. I don't want to put these into message itself.
Say in a web app, user created a shopping cart CreateShoppingCart { CartID, UserID }. Then added items to it, AddItem { CartID, ItemID, Amount, etc }. I want to record exacty when the used clicked the "Add To Cart" button.
I can add this into some Dictionary<string, object> Headers { get;
set; } property. That property could be in a BaseMessage class.
I can rely on the messaging framework (something like NServiceBus) and add this data into the message header in the message context.
Send seperate command for this info. Something like LogCommandDetails { CommandID: 'id of AddItem command', DateTime, Some other meta data }. When this comamnd is handled, I can update the projection of ItemAdded event and add this data into the projection.
What are your thoughts?
Thanks
Typically this information is stored in message headers, which is option 2. This is exactly what message headers are for. Note, there is a subtle difference between a message from perspective of a messaging framework and a message in your domain which is the body of the message in a messaging framework.
However, it can be difficult to discern what is data and what is metadata. I run into this issue with dates, among other things. For example, is a timestamp associated with an event metadata or proper domain data? What if the timestamp is required for execution of certain business logic? In your example, do you need to record the date for reporting or audit purposes, or is the date needed for the domain to function? In the former case, use headers, in the latter, place the date in the message body.
I'm building an open-source clone of iPhone's native Messages app called AcaniChat on GitHub.
I have a Conversation entity and a Message entity with a sentDate attribute. Each Conversation can have many Messages. How do I fetch Conversations sorted by the sentDate of it's oldest Message?
The best way I can think of doing this is by adding an attribute to the Conversation entity called lastMessageSentDate and, every time a Message comes in and gets added to a Conversation, setting that conversation's lastMessageSentDate to that message's sentDate. I'll also probably want to add an attribute called lastMessageText to the Conversation entity as well because I want to show the text of the last message for a conversation on the ConversationsViewController (just like the native iPhone Messages app does), and doing so will save me from having to do another Core Data fetch for the Message.
Actually, I just had an idea! Maybe I can sort Conversations by messages.#max.sortedDate, according to Xcode Documentation: Key-Value Coding Programming Guide: Collection Operators.