2018-10-03 23:24:36 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
2018-11-06 23:43:11 +01:00
|
|
|
import os
|
2018-10-03 23:24:36 +02:00
|
|
|
import requests
|
2018-11-07 00:37:24 +01:00
|
|
|
import defusedxml.ElementTree as Et
|
2018-10-03 23:24:36 +02:00
|
|
|
|
|
|
|
|
|
|
|
class XEPRequest:
|
2018-11-06 23:43:11 +01:00
|
|
|
"""
|
|
|
|
class which requests the header of the referenced xep
|
|
|
|
"""
|
|
|
|
def __init__(self):
|
|
|
|
# init all necessary variables
|
|
|
|
self.reqxep, self.opt_arg = None, None
|
2018-10-03 23:24:36 +02:00
|
|
|
|
|
|
|
self.xeplist = None
|
|
|
|
self.acceptedxeps = list()
|
|
|
|
|
|
|
|
def req_xeplist(self):
|
|
|
|
"""
|
|
|
|
query and save the current xep list to reduce network bandwidth
|
|
|
|
"""
|
2018-11-06 23:43:11 +01:00
|
|
|
# check if etag header is present if not set local_etag to ""
|
|
|
|
if os.path.isfile("./common/.etag"):
|
|
|
|
with open("./common/.etag") as file:
|
2018-10-03 23:24:36 +02:00
|
|
|
local_etag = file.read()
|
2018-11-06 23:43:11 +01:00
|
|
|
else:
|
2018-10-03 23:24:36 +02:00
|
|
|
local_etag = ""
|
|
|
|
|
|
|
|
with requests.Session() as s:
|
2018-11-06 23:43:11 +01:00
|
|
|
# head request the xeplist.xml
|
2018-10-03 23:24:36 +02:00
|
|
|
s.headers.update({'Accept': 'application/xml'})
|
|
|
|
head = s.head("https://xmpp.org/extensions/xeplist.xml")
|
|
|
|
etag = head.headers['etag']
|
|
|
|
|
2018-11-06 23:43:11 +01:00
|
|
|
# compare etag with local_etag if they match up no request is made
|
2018-10-03 23:24:36 +02:00
|
|
|
if local_etag == etag:
|
2018-10-06 13:16:27 +02:00
|
|
|
with open("./common/xeplist.xml", "r") as file:
|
2018-11-07 00:37:24 +01:00
|
|
|
self.xeplist = Et.fromstring(file.read())
|
2018-11-06 23:43:11 +01:00
|
|
|
|
|
|
|
# if the connection is not possible use cached xml if present
|
|
|
|
elif os.path.isfile("./common/xeplist.xml") and head.status_code != 200:
|
|
|
|
with open("./common/xeplist.xml", "r") as file:
|
2018-11-07 00:37:24 +01:00
|
|
|
self.xeplist = Et.fromstring(file.read())
|
2018-11-06 23:43:11 +01:00
|
|
|
|
|
|
|
# in any other case request the latest xml
|
2018-10-03 23:24:36 +02:00
|
|
|
else:
|
|
|
|
r = s.get("https://xmpp.org/extensions/xeplist.xml")
|
|
|
|
r.encoding = 'utf-8'
|
|
|
|
local_etag = head.headers['etag']
|
|
|
|
|
2018-10-06 13:16:27 +02:00
|
|
|
with open("./common/xeplist.xml", "w") as file:
|
2018-10-03 23:24:36 +02:00
|
|
|
file.write(r.content.decode())
|
2018-11-07 00:37:24 +01:00
|
|
|
self.xeplist = Et.fromstring(r.content.decode())
|
2018-10-03 23:24:36 +02:00
|
|
|
|
2018-11-06 23:43:11 +01:00
|
|
|
with open('./common/.etag', 'w') as string:
|
2018-10-03 23:24:36 +02:00
|
|
|
string.write(local_etag)
|
|
|
|
|
|
|
|
# populate xep comparison list
|
|
|
|
for xep in self.xeplist.findall(".//*[@accepted='true']/number"):
|
|
|
|
self.acceptedxeps.append(xep.text)
|
|
|
|
|
|
|
|
def get(self):
|
|
|
|
"""
|
|
|
|
function to query the xep entry if xepnumber is present in xeplist
|
2018-11-06 23:43:11 +01:00
|
|
|
:return: formatted xep header information
|
2018-10-03 23:24:36 +02:00
|
|
|
"""
|
2018-11-06 23:43:11 +01:00
|
|
|
# all possible subtags grouped by location
|
|
|
|
last_revision_tags = ["date", "version", "initials", "remark"]
|
2018-11-07 14:47:55 +01:00
|
|
|
xep_tags = ["number", "title", "abstract", "type", "status", "approver", "shortname", "sig", "lastcall", "date", "version", "initials", "remark"]
|
2018-11-06 23:43:11 +01:00
|
|
|
|
2018-10-03 23:24:36 +02:00
|
|
|
# check if xeplist is accurate
|
|
|
|
self.req_xeplist()
|
|
|
|
|
|
|
|
result = list()
|
2018-11-06 23:43:11 +01:00
|
|
|
# if requested number is member of acceptedxeps continue
|
2018-10-06 13:16:27 +02:00
|
|
|
if str(self.reqxep) in self.acceptedxeps:
|
2018-10-03 23:24:36 +02:00
|
|
|
searchstring = ".//*[@accepted='true']/[number='%s']" % self.reqxep
|
|
|
|
|
|
|
|
for item in self.xeplist.findall(searchstring):
|
2018-11-06 23:43:11 +01:00
|
|
|
# if the opt_arg references is member of xeptag return only that tag
|
|
|
|
if self.opt_arg in xep_tags:
|
|
|
|
|
2018-11-07 14:47:55 +01:00
|
|
|
# if the opt_arg references is member of last_revision_tags return only that subtag
|
|
|
|
if self.opt_arg in last_revision_tags:
|
|
|
|
query = item.find("last-revision").find(self.opt_arg)
|
|
|
|
else:
|
|
|
|
query = item.find(self.opt_arg)
|
|
|
|
|
|
|
|
# append opt_arg results to the result list
|
|
|
|
if query is not None:
|
|
|
|
result.append("%s : %s" % (query.tag, query.text))
|
|
|
|
else:
|
|
|
|
result.append("%s does not have a %s tag." % (self.reqxep, self.opt_arg))
|
2018-11-06 23:43:11 +01:00
|
|
|
|
|
|
|
# in any other case return the general answer
|
|
|
|
else:
|
|
|
|
result_opts = ["title", "type", "abstract", "status"]
|
|
|
|
for tag in result_opts:
|
|
|
|
result.append(item.find(tag).text)
|
|
|
|
|
|
|
|
# if the requested number is no member of acceptedxeps and/or not accepted return error.
|
2018-10-03 23:24:36 +02:00
|
|
|
else:
|
2018-11-06 23:43:11 +01:00
|
|
|
result.append("XEP-%s : is not available." % self.reqxep)
|
2018-10-03 23:24:36 +02:00
|
|
|
|
|
|
|
return result
|
|
|
|
|
2018-11-06 23:43:11 +01:00
|
|
|
def format(self, query, target, opt_arg):
|
|
|
|
"""
|
|
|
|
:param target: number int or str to request the xep for
|
|
|
|
:return:
|
|
|
|
"""
|
|
|
|
self.reqxep = int(target)
|
|
|
|
self.opt_arg = opt_arg
|
|
|
|
|
2018-10-03 23:24:36 +02:00
|
|
|
reply = self.get()
|
|
|
|
|
|
|
|
text = '\n'.join(reply)
|
|
|
|
return text
|