XMPPFramework - 从Openfire服务器检索归档消息

14
我正在使用XMPP和Openfire服务器为iPhone开发聊天应用程序,OpenFire服务器存储了用户之间的所有聊天记录,但是当我尝试检索特定用户的聊天历史记录时,我只能获得日期和聊天消息数量,而不是实际的文本消息。 我已经在openfire上安装了开放式归档插件。 这是我传递给Openfire服务器的数据包:
    <iq type='get' id='pk1'>
    <list xmlns='urn:xmpp:archive'
    with='piyush@openfire'>
    <set xmlns='http://jabber.org/protocol/rsm'>
    <max>30</max>
    </set>
    </list>
    </iq>

这是我从服务器收到的结果

  <iq type="result" id="pk1" to="vivek@openfire/iphone">
  <list xmlns="urn:xmpp:archive">
  <chat with="piyush@openfire" start="2012-07-04T13:16:12.291Z"/>
  <chat with="piyush@openfire" start="2012-07-05T08:25:31.555Z"/>
  <chat with="piyush@openfire" start="2012-07-05T12:38:24.098Z"/>
  <set xmlns="http://jabber.org/protocol/rsm">
  <first index="0">15</first>
  <last>25</last>
  <count>3</count>
  </set>
  </list>
  </iq>

这就是我想要的结果,也是我期望的结果

 <iq type='result' to='vivek@openfire/iphone' id='page1'>
 <chat xmlns='urn:xmpp:archive'
    with='piyush@openfire'
    start='2012-07-04T13:16:12.291Z'
    subject='She speaks!'
    version='4'>
<from secs='0'><body>Art thou not Romeo, and a Montague?</body></from>
<to secs='11'><body>Neither, fair saint, if either thee dislike.</body></to>
.
[98 more messages]
.
<from secs='9'><body>How cam'st thou hither, tell me, and wherefore?</body></from>
<set xmlns='http://jabber.org/protocol/rsm'>
  <first index='0'>0</first>
  <last>99</last>
  <count>217</count>
</set>

请帮我得到所需的结果

谢谢


1
我认为这更多是一个OpenFire API的问题,而不是iOS的问题。 - Pfitz
嗨,Piyush,我也在尝试实现同样的事情。但是(请原谅我的无知),我不知道如何将这个段发送到Openfire服务器。是否有API调用可用?您介绍一下吗? - Anidhya Ahuja
@Piyush Kashyap,你是如何启用聊天记录的?因为我已经安装了“监控”插件,但当我执行上述标准时,它返回未实现的功能。 - Hunt
希望这能有所帮助。请看:https://dev59.com/qILba4cB1Zd3GeqPcksQ#29097289 - Mrug
@KeithOYS,兄弟,你能帮我解决这个问题吗?https://stackoverflow.com/questions/44172852/how-to-parse-xmppmessage-element-attribute-and-node-in-xmppframework-with-swif ? - May Phyu
5个回答

17
你需要使用<retrieve>请求(参见http://xmpp.org/extensions/xep-0136.html),然后可以从收到的<list>结果中取出特定时间。例如:

发送:

    <iq type='get' id='pk1'>
       <list xmlns='urn:xmpp:archive'
               with='piyush@openfire'>
        <set xmlns='http://jabber.org/protocol/rsm'>
            <max>30</max>
        </set>
      </list>
   </iq>

收到:

 <iq type="result" id="pk1" to="vivek@openfire/iphone">
     <list xmlns="urn:xmpp:archive">
      <chat with="piyush@openfire" start="2012-07-04T13:16:12.291Z"/>
      <chat with="piyush@openfire" start="2012-07-05T08:25:31.555Z"/>
      <chat with="piyush@openfire" start="2012-07-05T12:38:24.098Z"/>
      <set xmlns="http://jabber.org/protocol/rsm">
          <first index="0">15</first>
           <last>25</last>
           <count>3</count>
      </set>
    </list>
 </iq>            

现在您可以选择其中一个 start 并发送(日期和小时必须精确):

  <iq type='get' id='pk1'>
    <retrieve xmlns='urn:xmpp:archive'
        with='piyush@openfire''
        start='2012-07-04T13:16:12.291Z'>
     <set xmlns='http://jabber.org/protocol/rsm'>
       <max>100</max>
     </set>
    </retrieve>
 </iq>
你将会收到类似于这样的内容(取决于最大值 -> max=30,bodies=30):
   <iq type='result' to='vivek@openfire/iphone' id='page1'>
      <chat xmlns='urn:xmpp:archive'
             with='piyush@openfire'
              start='2012-07-04T13:16:12.291Z'
            subject='She speaks!'
       version='4'>
         <from secs='0'><body>Art thou not Romeo, and a Montague?</body></from>
         <to secs='11'><body>Neither, fair saint, if either thee dislike.</body></to>
          .
          [28 more messages]
          .
         <from secs='9'><body>How cam'st thou hither, tell me, and therefore?           </body>   
         </from>
      <set xmlns='http://jabber.org/protocol/rsm'>
       <first index='0'>0</first>
       <last>29</last>
       <count></count>
     </set>
  <iq>

这是用户ID(JabberID) - Mrug
不,这里的pk1是发送iq数据包的唯一标识符。如果您正在使用某种xmpp客户端API,则可以忽略它,因为该API(如果支持)将处理设置ID的操作。 - Uluk Biy
我们能否在XMPP服务器端存储聊天记录? - ios developer
它支持MUC吗?(即)获取MUC归档消息 - iPhone Guy
@DRMA,你能帮我解决这个问题吗?https://stackoverflow.com/questions/44172852/how-to-parse-xmppmessage-element-attribute-and-node-in-xmppframework-with-swif? - May Phyu

10

获取聊天具体时间

发送以下内容以获取时间:

 NSXMLElement *iq1 = [NSXMLElement elementWithName:@"iq"];
 [iq1 addAttributeWithName:@"type" stringValue:@"get"];
 [iq1 addAttributeWithName:@"id" stringValue:@"pk1"];
 NSXMLElement *retrieve = [NSXMLElement elementWithName:@"list" xmlns:@"urn:xmpp:archive"];
 [retrieve addAttributeWithName:@"with" stringValue:@"amit@openfire"];
 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];


 [xmppStream sendElement:iq1];

检索聊天记录

使用开始日期和发送来进行查询:

 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:@"amit@openfire"];
 [retrieve addAttributeWithName:@"start" stringValue:@"2013-11-18T05:11:53.460Z"];
 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];
 [xmppStream sendElement:iq1];

1
@Amit Gupta 是的,我也卡在这里了。请问在这里 pk1 是什么? - Sam
如果我执行上述代码,则xmppstream委托方法即didReceiveMessage将被调用,但我没有得到任何结果,我正在使用Openfire,所以我能在我的服务器上做任何技巧吗?请帮帮我。 - Sri..
1
我遇到了500错误和未实现的功能错误,该怎么办? - Mrug
1
Pk1是自定义的ID名称。您可以使用任何ID名称,没有问题。 - Karun
我遇到了503服务不可用的错误。我正在使用OpenFire。你能告诉我它的原因吗?详情请查看:http://stackoverflow.com/questions/35935397/get-xmpp-chat-history-openfire - Hassan Aftab

2
首先,要从Openfire中检索聊天记录,您需要安装Open Archive插件,因为Monitering插件仅用于在管理面板上监视和记录聊天历史记录,因此一旦安装了Open Archive,您将不会收到任何带有“500”代码的错误。
您可以从以下链接下载并学习安装Open Archive。

https://nexus.reucon.com/content/repositories/opensource-snapshots/com/reucon/openfire/plugins/archive/

https://maven.reucon.com/projects/public/archive/

上述代码中的另一个问题是,当你在请求中提到起始标记时,它会与具有完全时间戳匹配的聊天相匹配,因此会返回错误代码“404”。我从我的请求中省略了起始标记并编写了以下代码,它将返回与用户的整个聊天记录。
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

1

从Openfire服务器获取存档消息的Swift版本 请求:

func getArchieveMessages(){
        let iQ = DDXMLElement.elementWithName("iq")
        iQ.addAttributeWithName("type", stringValue: "get")
        iQ.addAttributeWithName("id", stringValue: "page1")
        let list = DDXMLElement.elementWithName("retrieve")
        list.addAttributeWithName("xmlns", stringValue: "urn:xmpp:archive")
        list.addAttributeWithName("with", stringValue: "partner@domain")
        let set = DDXMLElement.elementWithName("set")
        set.addAttributeWithName("xmlns", stringValue: "http://jabber.org/protocol/rsm")
        let max = DDXMLElement.elementWithName("max")
        max.addAttributeWithName("xmlns", stringValue: "http://jabber.org/protocol/rsm")
        //(max as! DDXMLElement).setStringValue("30")
        (set as! DDXMLElement).addChild(max as! DDXMLNode)
        list.addChild(set as! DDXMLNode)
        iQ.addChild(list as! DDXMLNode)
        xmppStream.sendElement(iQ as! DDXMLElement)
    }

回应:
func xmppStream(sender: XMPPStream!, didReceiveIQ iq: XMPPIQ!) -> Bool {
        let chat = iq.elementForName("chat")
        let chats = (chat as DDXMLElement).children()
        for chat in chats{
            let msg = chat
            let body = (msg as! DDXMLElement).elementForName("body")
            if body != nil{
                if body.stringValue() != nil{
                    //print(body.stringValue()!)
                    chatMessages.append(body.stringValue()!)
                    if msg.attributeForName("jid") == nil{
                        type.append("Send")
                    }
                    else{
                        type.append("Receive")
                    }
                }
            }
        }
        print("Did receive IQ")
        return false
    }

*with是您想获取存档消息的人的JID


1

一个获取Swift 4中归档消息的示例

声明并初始化变量XMPPMessageArchivingCoreDataStorage,其中我初始化了XMPPStream

var xmppMessageStorage: XMPPMessageArchivingCoreDataStorage?
var xmppMessageArchiving: XMPPMessageArchiving?

xmppMessageStorage = XMPPMessageArchivingCoreDataStorage.sharedInstance()
    xmppMessageArchiving = XMPPMessageArchiving(messageArchivingStorage: xmppMessageStorage)

    xmppMessageArchiving?.clientSideMessageArchivingOnly = true
    xmppMessageArchiving?.activate(stream)
    xmppMessageArchiving?.addDelegate(self, delegateQueue: DispatchQueue.main)

在这样做的情况下,每当有一条消息到达时,它将被归档而无需进行其他操作。
然后,要检索已归档的消息。
func RecibedMessageArchiving(idFriend: String) {

        let JabberIDFriend = idFriend   //id friend chat, example test1@example.com


        let moc = xmppMessageStorage?.mainThreadManagedObjectContext
        let entityDescription = NSEntityDescription.entity(forEntityName: "XMPPMessageArchiving_Message_CoreDataObject", in: moc!)
        let request = NSFetchRequest<NSFetchRequestResult>()
        let predicateFormat = "bareJidStr like %@ "
        let predicate = NSPredicate(format: predicateFormat, JabberIDFriend)

        request.predicate = predicate
        request.entity = entityDescription

        //jabberID id del usuario, cliente
        var jabberIDCliente = ""
        if let jabberj = globalChat.value(forKey: "jabberID"){
            jabberIDCliente = jabberj as! String
        }


        do {
            let results = try moc?.fetch(request)

            for message: XMPPMessageArchiving_Message_CoreDataObject? in results as? [XMPPMessageArchiving_Message_CoreDataObject?] ?? [] {

                var element: DDXMLElement!
                do {
                    element = try DDXMLElement(xmlString: (message as AnyObject).messageStr)
                } catch _ {
                    element = nil
                }

                let body: String
                let sender: String
                let date: NSDate
                let isIncomings: Bool

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