iOS XMPPFramework - Room / chat messages history

2019-06-07 05:04发布

问题:

I am developing chat application using XMPPFramework

How can i receive history of messages after join existing room?

Now i join to room like this:

XMPPJID *roomJid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@conference.%@",systemName,xmppServer]];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:[XMPPRoomHybridStorage sharedInstance] jid:roomJid];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];
NSXMLElement *history = [NSXMLElement elementWithName:@"history"];
[history addAttributeWithName:@"maxstanzas" stringValue:@"100"];
[xmppRoom joinRoomUsingNickname:user.deviceUUID history:history];

Also i read example from documentation

According to this example I also tried to join room this way:

XMPPJID *roomJid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@conference.%@",systemName,xmppServer]];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:[XMPPRoomHybridStorage sharedInstance] jid:roomJid];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];

NSXMLElement *presence = [NSXMLElement elementWithName:@"presence"];
[presence addAttributeWithName:@"from" stringValue:[NSString stringWithFormat:@"bob@%@",xmppServer]];
[presence addAttributeWithName:@"to" stringValue:[NSString stringWithFormat:@"%@@conference.%@/%@",systemName,xmppServer,user.deviceUUID]];

NSXMLElement *x = [NSXMLElement elementWithName:@"x" xmlns:@"http://jabber.org/protocol/muc"];

NSXMLElement *history = [NSXMLElement elementWithName:@"history"];
[history addAttributeWithName:@"maxstanzas" stringValue:@"100"];

[x addChild:history];

[presence addChild:x];

[xmppRoom joinRoomUsingNickname:user.deviceUUID history:presence]; 

I join room successfully, but don't receive history of previous messages.

Btw, if at least one user in the room, i receive all previous messages, even if i join room like:

[xmppRoom joinRoomUsingNickname:user.deviceUUID history:nil];

If all users leave room and then some join again - history is empty=(

What am I doing wrong? Do i need to turn on some settings on the server side to save history (eg, logging)?

And some questions about example from documentation:

What means "from" parameter? Does it mean that I ask for the history of messages in this room only from user bob? And what if i want to receive all history (messages from any users)?

What means "id" parameter? I didn't find any description in the documentation.

回答1:

When you've created a room and you've joined, you need to configure that room to make persistent, what this means is that:

Persistent Room A room that is not destroyed if the last occupant exits; antonym: Temporary Room. (You want this room's configuration).

Temporary Room A room that is destroyed if the last occupant exits; antonym: Persistent Room.

1. So, you create and join a room.

XMPPJID *roomJid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@conference.%@",systemName,xmppServer]];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:[XMPPRoomHybridStorage sharedInstance] jid:roomJid];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];
[xmppRoom joinRoomUsingNickname:user.deviceUUID history:history];

2. Then, the delegate method xmppRoomDidJoin:sender; is called (only if all has gone right), and you have to configure your room

-(void)xmppRoomDidJoin:(XMPPRoom *)sender {
   NSLog("I did join.");
   [sender fetchConfigurationForm];
}

fetchConfigurationForm method send an IQ to request an initial room configuration form.

Example of IQ that has been sent to XMPP Server:

<iq from='crone1@shakespeare.lit/desktop'
    id='create1'
    to='coven@chat.shakespeare.lit'
    type='get'>
  <query xmlns='http://jabber.org/protocol/muc#owner'/>
</iq>

3. When XMPP server answer with the room configuration the -xmppRoom:sender didFetchConfigurationForm:configForm; method is called. And here is where you change the default values of the room to make persistent, room name, members only, etc.

Example:

-(void)xmppRoom:(XMPPRoom *)sender didFetchConfigurationForm:(NSXMLElement *)configForm {
    NSXMLElement *newConfig = [configForm copy];
    NSArray *fields = [newConfig elementsForName:@"field"];
    for (NSXMLElement *field in fields) {
        NSString *var = [field attributeStringValueForName:@"var"];
        // Make Room Persistent
       if ([var isEqualToString:@"muc#roomconfig_persistentroom"]) {
           [field removeChildAtIndex:0];
           [field addChild:[NSXMLElement elementWithName:@"value" stringValue:@"1"]];
       }
    }
    [sender configureRoomUsingOptions:newConfig];
}


回答2:

Thanks @Moral for explanation. But In my case the solution was very simple.

In the chat server in ejabberd.yml just added default options in the module muc configuration:

mod_muc: ## host: "conference.HOST" 
db_type: odbc 
access: muc
access_create: muc_create
access_persistent: muc_create
access_admin: muc_admin
min_message_interval: 1.0
min_presence_interval: 5.0
default_room_options:
logging: true
persistent: true

And in the app join room this way:

XMPPJID *roomJid = [XMPPJID jidWithString:[NSString stringWithFormat:@"%@@conference.%@",systemName,xmppServer]];
xmppRoom = [[XMPPRoom alloc] initWithRoomStorage:[XMPPRoomHybridStorage sharedInstance] jid:roomJid];
[xmppRoom addDelegate:self delegateQueue:dispatch_get_main_queue()];
[xmppRoom activate:xmppStream];
NSXMLElement *history = [NSXMLElement elementWithName:@"history"];
[history addAttributeWithName:@"maxstanzas" stringValue:@"100"];
[xmppRoom joinRoomUsingNickname:user.deviceUUID history:history];

Thats it!