]> jfr.im git - irc/rizon/acid.git/blame - pyva/src/main/python/erepublik/api/feed.py
.gitignore: Ignore all pyva logs
[irc/rizon/acid.git] / pyva / src / main / python / erepublik / api / feed.py
CommitLineData
685e346e
A
1import json
2import socket
3import urllib2
4import xpath
5from BaseHTTPServer import BaseHTTPRequestHandler
6from decimal import Decimal
7from StringIO import StringIO
8from urlparse import urlparse
9from xml.dom.minidom import Element
10from xml.dom.minidom import parse
11
12class InputError(Exception):
13 def __init__(self, msg):
14 self.msg = msg
15
16 def __str__(self):
17 return str(self.msg)
18
19class FeedError(Exception):
20 def __init__(self, e):
21 if hasattr(e, 'code'):
22 c = e.code
23
24 if c == 404:
25 self.msg = 'not found.'
26 elif c == 406:
27 self.msg = 'this eRepublik API feed is unavailable.'
28 elif c == 500:
29 self.msg = 'eRepublik server has encountered an unexpected error.'
30 elif c == 502:
31 self.msg = 'invalid response from eRepublik server. Try again later.'
32 elif c == 503:
33 self.msg = 'eRepublik API feed is temporarily unavailable. Try again later.'
34 else:
35 self.msg = 'something went wrong while connecting to eRepublik API feed (%s)' % BaseHTTPRequestHandler.responses[e.code][0]
36
37 self.code = c
38 self.url = e.url
39 elif hasattr(e, 'reason'):
40 r = str(e.reason)
41
42 if r == 'timed out':
43 self.msg = 'connection to eRepublik API feed timed out. Try again later.'
44 else:
45 self.msg = r
46
47 self.code = None
48 self.url = None
49 else:
50 e = unicode(e)
51
52 if e == 'an error occured':
53 self.msg = 'this command cannot work because eRepublik admins disabled the API. If you want to complain, send a ticket: http://www.erepublik.com/en/tickets'
54 else:
55 self.msg = e
56
57 self.code = None
58 self.url = None
59
60 def __str__(self):
61 return self.msg
62
63class HtmlFeed:
64 def __init__(self, value):
65 if value == None:
66 raise InputError('Invalid feed input.')
67
68 if isinstance(value, str) or isinstance(value, unicode):
69 try:
70 opener = urllib2.build_opener()
71 opener.addheaders = [('User-Agent', 'Rizon eRepublik bot - www.rizon.net')]
72 feed = opener.open(value.replace(' ', '%20'), timeout=20)
73 self._html = feed.read()
74 feed.close()
75 except urllib2.URLError, e:
76 raise FeedError(e)
77 else:
78 raise InputError('Invalid feed input type.')
79
80 def html(self):
81 return self._html
82
83def get_json(value):
84 if value == None:
85 raise InputError('Invalid feed input.')
86
87 if isinstance(value, basestring):
88 feed = HtmlFeed(value)
89 return json.load(StringIO(feed.html()))
90 else:
91 raise InputError('Invalid feed input type.')
92
93class XmlFeed:
94 def __init__(self, value, namespaces = None):
95 if value == None:
96 raise InputError('Invalid feed input.')
97
98 self.namespaces = {} if namespaces == None else namespaces
99
100 if isinstance(value, basestring):
101 feed = HtmlFeed(value)
102 self._element = parse(StringIO(feed.html()))
103 elif isinstance(value, Element):
104 self._element = value
105 else:
106 raise InputError('Invalid feed input type.')
107
108 error = xpath.findvalue('/error/message', self._element)
109
110 if error != None:
111 raise FeedError(error)
112
113 def elements(self, query):
114 return [XmlFeed(x, self.namespaces) for x in xpath.find(query, self._element, namespaces=self.namespaces)]
115
116 def text(self, query, default=None):
117 result = xpath.findvalue(query, self._element, namespaces=self.namespaces)
118
119 if not result:
120 value = default
121 else:
122 value = result.strip()
123
124 if isinstance(value, unicode):
125 try:
126 value = value.encode('latin-1').decode('utf-8')
127 except:
128 pass
129
130 return value
131
132 def int(self, query, default = None):
133 result = self.text(query, None)
134
135 if result == None:
136 return default
137
138 try:
139 return int(result)
140 except:
141 return default
142
143 def decimal(self, query, default = None):
144 result = self.text(query, None)
145
146 if result == None:
147 return default
148
149 try:
150 return Decimal(result)
151 except:
152 return default
153
154 def bool(self, query, default = None):
155 result = self.text(query, None)
156
157 if result == None:
158 return default
159
160 if 'true' in result.lower() or result == '1':
161 return True
162 elif 'false' in result.lower() or result == '0':
163 return False
164 else:
165 try:
166 return int(result) > 0
167 except:
168 return default