# -*- coding: utf-8 -*-
from xml.dom.minidom import parseString
import xml.sax
def _urllib_fetch(url, action, body):
import urllib2
"""
A wrapper around default urllib2 library.
"""
headers = {'Content-Type': 'text/xml',
'SOAPAction':'"http://gamespy.net/sake/%s"' % action}
try:
req = urllib2.Request(url, body, headers)
return urllib2.urlopen(req).read()
except urllib2.HTTPError, e:
return e.read()
class WebServiceError(Exception):
def __init__(self, msg):
Exception.__init__(self, msg)
def _CreateSOAPRequest(action, *args, **kwargs):
soap_doc = '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://gamespy.net/sake"><SOAP-ENV:Body/></SOAP-ENV:Envelope>'
doc = parseString(soap_doc)
body = doc.createElement(action)
doc.documentElement.firstChild.appendChild(body)
for (a, b) in kwargs.iteritems():
if b is None:
continue
i = doc.createElement(a)
if isinstance(b, tuple) or isinstance (b, list):
for z in b:
if isinstance(z, int):
tp = 'int'
elif isinstance(z, str):
tp = 'string'
x = doc.createElement(tp)
x.appendChild(doc.createTextNode(str(z)))
i.appendChild(x)
else:
i.appendChild(doc.createTextNode(str(b)))
body.appendChild(i)
return doc.toxml('utf-8')
class Result:
def __init__(self, doc, fields):
self._data = []
self.cached = False
self._count = 0
xml.sax.parseString(doc, _SFRParser(fields, self._data))
def next(self):
if self._count >= len(self._data):
self._count = 0
raise StopIteration
else:
c = self._count
self._count = c + 1
return self._data[c]
def __getitem__(self, n):
return self._data[n]
def __iter__(self):
return self
class _SFRParser(xml.sax.handler.ContentHandler):
def __init__(self, fields, result):
xml.sax.handler.ContentHandler.__init__(self)
self._fields = fields
self.result = result
#initializing flags
self._SFRResult = False
self._faultstring = False
self._AORV = False
self._RV = False
self._val = False
self._arrayCount = 0
self._fieldCount = 0
def startElement (self, name, attrs):
if name == 'value' and self._RV:
self._val = True
self._valText = u''
elif name == 'RecordValue':
self._RV = True
elif name == 'ArrayOfRecordValue':
self._array = []
self._AORV = True
elif name == 'SearchForRecordsResult':
self._SFRResult = True
self._SFRRtext = u''
elif name == 'faultstring':
self._faultstring = True
self._fsText = u''
def endElement(self, name):
if name == 'value' and self._RV: #ячейка кончилась
self._val = False
self._array.append((self._fields[self._fieldCount], self._valText))
elif name == 'RecordValue': #столбец кончился
self._RV = False
self._fieldCount += 1 #следующий столбец
elif name == 'ArrayOfRecordValue': #строка кончилась
self._arrayCount += 1 #следующая строка
self._fieldCount = 0 #сбрасываем показатель столбца
self._AORV = False
self.result.append(self._array)
elif name == 'SearchForRecordsResult':
if self._SFRRtext != 'Success':
raise WebServiceError(self._SFRRtext)
self._SFRResult = False
elif name == 'faultstring':
self._faultstring = False
raise WebServiceError(self._fsText)
def characters(self, content):
if self._val:
self._valText += content
elif self._SFRResult:
self._SFRRtext += content
elif self._faultstring:
self._fsText += content
class SakeStorage:
def __init__(self, url, gameid, tableid, ticket, cacheFlag=0, opener=_urllib_fetch):
self.url = url
self.gameid = gameid
self.tableid = tableid
self.ticket = ticket
self.cacheFlag = cacheFlag
self.opener = opener
def CreateRecord(self, *args, **kwargs):
raise NotImplementedError
def DeleteRecord(self, *args, **kwargs):
raise NotImplementedError
def GetMyRecords(self, *args, **kwargs):
raise NotImplementedError
def GetRandomRecords(self, *args, **kwargs):
raise NotImplementedError
def GetRecordCount(self, *args, **kwargs):
raise NotImplementedError
def GetRecordLimit(self, *args, **kwargs):
raise NotImplementedError
def GetSpecificRecords(self, *args, **kwargs):
raise NotImplementedError
def RateRecords(self, *args, **kwargs):
raise NotImplementedError
def UpdateRecords(self, *args, **kwargs):
raise NotImplementedError
# everything above actually isn't needed to be implemented
def SearchForRecords(self, fields, filter, sort, offset, ownerids, max):
action = 'SearchForRecords'
payload = _CreateSOAPRequest(action, gameid=self.gameid,
tableid=self.tableid, cacheFlag=self.cacheFlag,
loginTicket=self.ticket, fields=fields,
filter=filter, sort=sort,
offset=offset, max=max,
ownerids=ownerids)
res = _urllib_fetch(self.url, action, payload)
return Result(res, fields)