我正在使用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>
请帮我得到想要的结果
感谢
您必须使用<retrieve>
执行请求(请参阅http://xmpp.org/extensions/xep-0136.html)则可以从接收到的CCD_ 2结果中提取特定的时间。例如:
发送:
<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,body=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>
检索聊天的具体时间
发送以获取时间:
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];
首先,要从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];
在这里,这将以XML响应的形式返回用户Rahul和当前登录的用户之间的整个聊天历史
有关更多详细信息,请参阅此博客http://question.ikende.com/question/363439343236313430
从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
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