XMPPFramework - 获取Openfire消息存档

5

我花了好几个小时都无法解决这个问题,感到很困惑!

我正在尝试获取我OpenFire服务器上2个用户之间的聊天记录, 我读到需要一个插件来实现。

于是,我在我的OpenFire服务器上安装了"Open Archive"插件,并按照XMPP-0136协议文档发送了以下XML:

<iq type="get" id="page1">
   <retrieve xmlns="urn:xmpp:archive" with="username@server.com" start="1469-07-21T02:56:15Z">
      <set xmlns="http://jabber.org/protocol/rsm">
         <max>100</max>
      </set>
   </retrieve>
</iq>

在代码中,可以通过以下方式实现:

NSXMLElement *iQ = [NSXMLElement elementWithName:@"iq"];
[iQ addAttributeWithName:@"type" stringValue:@"get"];
[iQ addAttributeWithName:@"id" stringValue:@"page1"];

NSXMLElement *retrieve = [NSXMLElement elementWithName:@"retrieve"];
[retrieve addAttributeWithName:@"xmlns" stringValue:@"urn:xmpp:archive"];
[retrieve addAttributeWithName:@"with" stringValue:@"username@server.com"];
[retrieve addAttributeWithName:@"start" stringValue:@"1469-07-21T02:56:15Z"];

NSXMLElement *set = [NSXMLElement elementWithName:@"set"];
[set addAttributeWithName:@"xmlns" stringValue:@"http://jabber.org/protocol/rsm"];
NSXMLElement *max = [NSXMLElement elementWithName:@"max"];
max.stringValue = @"100";
[set addChild:max];

[retrieve addChild:set];
[iQ addChild:retrieve];

[[[self appDelegate] xmppStream] sendElement:iQ];

会返回以下错误:

<iq xmlns="jabber:client" type="error" id="page1" to="username@server.com">
   <error code="404" type="cancel">
      <item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
   </error>
</iq>

我的Xcode项目可以成功地向我试图接收聊天历史记录的用户发送/接收消息,所以我真的不知道我做错了什么。此外,该插件使我能够通过OpenFire管理搜索聊天消息,并获得成功的结果,因此它似乎正在工作并存储消息。
如果有任何帮助,将不胜感激。谢谢!

这里是解决方案。https://dev59.com/b2gu5IYBdhLWcg3wWVuF - Karun
4个回答

7
如果您正在寻找聊天历史记录,我认为您必须将消息保存到核心数据中,并从那里检索它们。要使用XMPPFramework内置功能保存数据,您需要使用以下代码:
XMPPMessageArchivingCoreDataStorage *storage = [XMPPMessageArchivingCoreDataStorage   sharedInstance];
NSManagedObjectContext *moc = [storage mainThreadManagedObjectContext];

xmppMessageArchivingStorage = [XMPPMessageArchivingCoreDataStorage sharedInstance];
xmppMessageArchivingModule = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:xmppMessageArchivingStorage];
[xmppMessageArchivingModule activate:xmppStream];
[xmppMessageArchivingModule  addDelegate:self delegateQueue:dispatch_get_main_queue()];

现在您需要通过以下方式从核心数据中检索这些消息:
-(void)loadarchivemsg
{  
    XMPPMessageArchivingCoreDataStorage *storage = [XMPPMessageArchivingCoreDataStorage sharedInstance];
    NSManagedObjectContext *moc = [storage mainThreadManagedObjectContext];
    NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"XMPPMessageArchiving_Message_CoreDataObject"
                                                      inManagedObjectContext:moc];
    NSFetchRequest *request = [[NSFetchRequest alloc]init];

    NSString *predicateFrmt = @"bareJidStr like %@ ";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateFrmt, chatWithUser];
    request.predicate = predicate;
    NSLog(@"%@",[[NSUserDefaults standardUserDefaults] stringForKey:@"kXMPPmyJID"]);
    [request setEntity:entityDescription];
    NSError *error;
    NSArray *messages_arc = [moc executeFetchRequest:request error:&error];

    [self print:[[NSMutableArray alloc]initWithArray:messages_arc]];
}

-(void)print:(NSMutableArray*)messages_arc{
    @autoreleasepool {
        for (XMPPMessageArchiving_Message_CoreDataObject *message in messages_arc) {
            NSXMLElement *element = [[NSXMLElement alloc] initWithXMLString:message.messageStr error:nil];
            NSLog(@"to param is %@",[element attributeStringValueForName:@"to"]);

            NSMutableDictionary *m = [[NSMutableDictionary alloc] init];
            [m setObject:message.body forKey:@"msg"];

            if ([[element attributeStringValueForName:@"to"] isEqualToString:chatWithUser]) {               
                [m setObject:@"you" forKey:@"sender"];
            }
            else {
                [m setObject:chatWithUser forKey:@"sender"];
            }

            [messages addObject:m];

            NSLog(@"bareJid param is %@",message.bareJid);
            NSLog(@"bareJidStr param is %@",message.bareJidStr);
            NSLog(@"body param is %@",message.body);
            NSLog(@"timestamp param is %@",message.timestamp);
            NSLog(@"outgoing param is %d",[message.outgoing intValue]);
            NSLog(@"***************************************************");
        }
    }
}

我不明白一个问题,我们应该在哪里提供其他用户的JID。您能否在注释中指出特定位置。 - Romance
[NSPredicate predicateWithFormat:predicateFrmt, chatWithUser]; 这里的chatWithUser是另一个用户的JID,您可以在这里设置其他用户的JID。 - Mitul Bhadeshiya
@MitsBhadeshiya 如果我不在线时收到消息,我们该如何检索离线消息? - AMohan
2
@Mohan 如果用户离线,所有消息都会存储在服务器上,当用户在线时,所有消息都会作为延迟消息发送给用户。因此,您必须处理这些消息...我希望你能理解。 - Mitul Bhadeshiya
这是客户端归档的过程。您能分享一下从Openfire服务器检索消息的方法吗? - Karun
显示剩余10条评论

4
请详细查看 Stanza 的细节:https://dev59.com/qILba4cB1Zd3GeqPcksQ#29097289 它是平台无关的,只需了解 Stanza 的结构并根据您正在使用的库创建即可。
这是您需要发送的 Stanza 系列以获取存档消息。有关详细信息,请查看 XEP 0136(http://xmpp.org/extensions/xep-0136.html#manual)。
REQ
<iq type='get' id='mrug_sender@staging.openfire.com'>
       <list xmlns='urn:xmpp:archive'
               with='mrug_target_155@staging.openfire.com'>
        <set xmlns='http://jabber.org/protocol/rsm'>
            <max>6900</max>
        </set>
      </list>
   </iq>

RES

<iq type="result" id="mrug_sender@staging.openfire.com" to="mrug_sender@staging.openfire.com/Psi">
<list xmlns="urn:xmpp:archive">
<chat with="mrug_target_155@staging.openfire.com" start="2014-06-07T06:52:26.041Z"/>
<chat with="mrug_target_155@staging.openfire.com" start="2014-06-07T07:06:53.372Z"/>
<set xmlns="http://jabber.org/protocol/rsm">
<first index="0">866</first>
<last>867</last>
<count>2</count>
</set>
</list>
</iq>

请求

<iq type='get' id='mrug_sender@staging.openfire.com'>
    <retrieve xmlns='urn:xmpp:archive'  with='mrug_target_155@staging.openfire.com'  start='2014-06-07T06:52:26.041Z'>
     <set xmlns='http://jabber.org/protocol/rsm'>
       <max>8000</max>
     </set>
    </retrieve>
 </iq>

RES

<iq type="result" id="mrug_sender@staging.openfire.com" to="mrug_sender@staging.openfire.com/Psi">
<chat xmlns="urn:xmpp:archive" with="mrug_target_155@staging.openfire.com" start="2014-06-07T06:52:26.041Z">
<from secs="0" jid="mrug_target_155@staging.openfire.com">
<body>Hello This is Cool</body>
</from>
<set xmlns="http://jabber.org/protocol/rsm">
<first index="0">0</first>
<last>0</last>
<count>1</count>
</set>
</chat>
</iq>

获取所有对话列表。
<iq type='get' id='mrug_sender@staging.openfire.com'>
       <list xmlns='urn:xmpp:archive'>
        <set xmlns='http://jabber.org/protocol/rsm'>
            <max>6900</max>
        </set>
      </list>
</iq>

1
当您在请求中提到起始标签时,它将与具有完全时间戳的聊天匹配,因此会返回错误代码“404”或“500”。我从我的请求中省略了起始标签,并编写了以下代码,它将返回与用户的整个聊天历史记录。
NSXMLElement *iq1 = [NSXMLElement elementWithName:@"iq"];
[iq1 addAttributeWithName:@"type" stringValue:@"get"];
[iq1 addAttributeWithName:@"id" stringValue:@"pk1"];

NSXMLElement *retrieve = [NSXMLElement elementWithName:@"retrieve" xmlns:@"urn:xmpp:archive"];

[retrieve addAttributeWithName:@"with" stringValue:@"rahul@vishals-mac-pro.local"];
NSXMLElement *set = [NSXMLElement elementWithName:@"set" xmlns:@"http://jabber.org/protocol/rsm"];
NSXMLElement *max = [NSXMLElement elementWithName:@"max" stringValue:@"100"];

[iq1 addChild:retrieve];
[retrieve addChild:set];
[set addChild:max];
[[[self appDelegate] xmppStream] sendElement:iq1]; 

这里将返回用户Rahul和当前登录用户之间的整个聊天记录XML响应。
要获取更详细的信息,请参考此博客 http://question.ikende.com/question/363439343236313430

0

XMPPFramework 实现了 XEP-0136 。您尝试使用 XMPPMessageArchiving设置偏好或将服务器档案与客户端同步了吗?


1
嗨@noa!你能否分享一下如何设置偏好,以便将服务器的归档同步到客户端的示例? - Karun

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