source: src/mlx/web.py@ 48:53b2648cfb30

Last change on this file since 48:53b2648cfb30 was 48:53b2648cfb30, checked in by István Váradi <locvais@…>, 12 years ago

Flight selection works

File size: 8.4 KB
Line 
1# Interface towards the websites used
2
3#------------------------------------------------------------------------------
4
5import const
6
7import threading
8import sys
9import urllib2
10import hashlib
11import datetime
12import codecs
13
14#---------------------------------------------------------------------------------------
15
16def readline(f):
17 """Read a line from the given file.
18
19 The line is stripped and empty lines are discarded."""
20 while True:
21 line = f.readline()
22 if not line: return ""
23 line = line.strip()
24 if line:
25 return line
26
27#---------------------------------------------------------------------------------------
28
29class BookedFlight(object):
30 """A flight that was booked."""
31 TYPECODE2TYPE = { "736" : const.AIRCRAFT_B736,
32 "73G" : const.AIRCRAFT_B737,
33 "738" : const.AIRCRAFT_B738,
34 "733" : const.AIRCRAFT_B733,
35 "734" : const.AIRCRAFT_B734,
36 "735" : const.AIRCRAFT_B735,
37 "DH4" : const.AIRCRAFT_DH8D,
38 "762" : const.AIRCRAFT_B762,
39 "763" : const.AIRCRAFT_B763,
40 "CR2" : const.AIRCRAFT_CRJ2,
41 "F70" : const.AIRCRAFT_F70,
42 "LI2" : const.AIRCRAFT_DC3,
43 "TU3" : const.AIRCRAFT_T134,
44 "TU5" : const.AIRCRAFT_T154,
45 "YK4" : const.AIRCRAFT_YK40 }
46
47 def __init__(self, id, f):
48 """Construct a booked flight with the given ID.
49
50 The rest of the data is read from the given file."""
51
52 self.id = id
53 self.callsign = readline(f)
54
55 date = readline(f)
56
57 self.departureICAO = readline(f)
58 self.arrivalICAO = readline(f)
59
60 self._readAircraftType(f)
61 self.tailNumber = readline(f)
62 self.numPassengers = int(readline(f))
63 self.numCrew = int(readline(f))
64 self.bagWeight = int(readline(f))
65 self.cargoWeight = int(readline(f))
66 self.mailWeight = int(readline(f))
67 self.route = readline(f)
68
69 departureTime = readline(f)
70 self.departureTime = datetime.datetime.strptime(date + " " + departureTime,
71 "%Y-%m-%d %H:%M:%S")
72
73 arrivalTime = readline(f)
74 self.arrivalTime = datetime.datetime.strptime(date + " " + arrivalTime,
75 "%Y-%m-%d %H:%M:%S")
76
77 if not readline(f)==".NEXT.":
78 raise Exception("Invalid line in flight data")
79
80 def _readAircraftType(self, f):
81 """Read the aircraft type from the given file."""
82 line = readline(f)
83 typeCode = line[:3]
84 if typeCode in self.TYPECODE2TYPE:
85 self.aircraftType = self.TYPECODE2TYPE[typeCode]
86 else:
87 raise Exception("Invalid aircraft type code: '" + typeCode + "'")
88
89 def __repr__(self):
90 """Get a representation of the flight."""
91 s = "<Flight: %s-%s, %s, %s-%s," % (self.departureICAO,
92 self.arrivalICAO,
93 self.route,
94 self.departureTime, self.arrivalTime)
95 s += " %d %s," % (self.aircraftType, self.tailNumber)
96 s += " pax=%d, crew=%d, bag=%d, cargo=%d, mail=%d" % \
97 (self.numPassengers, self.numCrew,
98 self.bagWeight, self.cargoWeight, self.mailWeight)
99 s += ">"
100 return s
101
102#------------------------------------------------------------------------------
103
104class Result(object):
105 """A result object.
106
107 An instance of this filled with the appropriate data is passed to the
108 callback function on each request."""
109
110 def __repr__(self):
111 """Get a representation of the result."""
112 s = "<Result:"
113 for (key, value) in self.__dict__.iteritems():
114 s += " " + key + "=" + unicode(value)
115 s += ">"
116 return s
117
118#------------------------------------------------------------------------------
119
120class Request(object):
121 """Base class for requests.
122
123 It handles any exceptions and the calling of the callback.
124
125 If an exception occurs during processing, the callback is called with
126 the two parameters: a boolean value of False, and the exception object.
127
128 If no exception occurs, the callback is called with True and the return
129 value of the run() function.
130
131 If the callback function throws an exception, that is caught and logged
132 to the debug log."""
133 def __init__(self, callback):
134 """Construct the request."""
135 self._callback = callback
136
137 def perform(self):
138 """Perform the request.
139
140 The object's run() function is called. If it throws an exception,
141 the callback is called with False, and the exception. Otherwise the
142 callback is called with True and the return value of the run()
143 function. Any exceptions thrown by the callback are caught and
144 reported."""
145 try:
146 result = self.run()
147 returned = True
148 except Exception, e:
149 result = e
150 returned = False
151
152 try:
153 self._callback(returned, result)
154 except Exception, e:
155 print >> sys.stderr, "web.Handler.Request.perform: callback throwed an exception: " + str(e)
156
157#------------------------------------------------------------------------------
158
159class Login(Request):
160 """A login request."""
161 iso88592decoder = codecs.getdecoder("iso-8859-2")
162
163 def __init__(self, pilotID, password, callback):
164 """Construct the login request with the given pilot ID and
165 password."""
166 super(Login, self).__init__(callback)
167
168 self._pilotID = pilotID
169 self._password = password
170
171 def run(self):
172 """Perform the login request."""
173 md5 = hashlib.md5()
174 md5.update(self._pilotID)
175 pilotID = md5.hexdigest()
176
177 md5 = hashlib.md5()
178 md5.update(self._password)
179 password = md5.hexdigest()
180
181 url = "http://www.virtualairlines.hu/leker2.php?pid=%s&psw=%s" % \
182 (pilotID, password)
183
184 result = Result()
185
186 f = urllib2.urlopen(url)
187
188 status = readline(f)
189 result.loggedIn = status == ".OK."
190
191 if result.loggedIn:
192 result.pilotName = self.iso88592decoder(readline(f))[0]
193 result.exams = readline(f)
194 result.flights = []
195
196 while True:
197 line = readline(f)
198 if not line or line == "#ENDPIREP": break
199
200 flight = BookedFlight(line, f)
201 result.flights.append(flight)
202
203 result.flights.sort(cmp = lambda flight1, flight2:
204 cmp(flight1.departureTime,
205 flight2.departureTime))
206
207 return result
208
209#------------------------------------------------------------------------------
210
211class Handler(threading.Thread):
212 """The handler for the web services.
213
214 It can process one request at a time. The results are passed to a callback
215 function."""
216 def __init__(self):
217 """Construct the handler."""
218 super(Handler, self).__init__()
219
220 self._requests = []
221 self._requestCondition = threading.Condition()
222
223 self.daemon = True
224
225 def login(self, pilotID, password, callback):
226 """Enqueue a login request."""
227 self._addRequest(Login(pilotID, password, callback))
228
229 def run(self):
230 """Process the requests."""
231 while True:
232 with self._requestCondition:
233 while not self._requests:
234 self._requestCondition.wait()
235 request = self._requests[0]
236 del self._requests[0]
237
238 request.perform()
239
240 def _addRequest(self, request):
241 """Add the given request to the queue."""
242 with self._requestCondition:
243 self._requests.append(request)
244 self._requestCondition.notify()
245
246#------------------------------------------------------------------------------
247
248if __name__ == "__main__":
249 import time
250
251 def callback(returned, result):
252 print returned, unicode(result)
253
254 handler = Handler()
255 handler.start()
256
257 handler.login("P096", "V5fwj", callback)
258 time.sleep(3)
259
260#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.