source: src/mlx/web.py@ 41:19b2001e4478

Last change on this file since 41:19b2001e4478 was 41:19b2001e4478, checked in by István Váradi <ivaradi@…>, 12 years ago

Added the code to log in to the MAVA website and download the flights.

File size: 8.2 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 return result
204
205#------------------------------------------------------------------------------
206
207class Handler(threading.Thread):
208 """The handler for the web services.
209
210 It can process one request at a time. The results are passed to a callback
211 function."""
212 def __init__(self):
213 """Construct the handler."""
214 super(Handler, self).__init__()
215
216 self._requests = []
217 self._requestCondition = threading.Condition()
218
219 self.daemon = True
220
221 def login(self, pilotID, password, callback):
222 """Enqueue a login request."""
223 self._addRequest(Login(pilotID, password, callback))
224
225 def run(self):
226 """Process the requests."""
227 while True:
228 with self._requestCondition:
229 while not self._requests:
230 self._requestCondition.wait()
231 request = self._requests[0]
232 del self._requests[0]
233
234 request.perform()
235
236 def _addRequest(self, request):
237 """Add the given request to the queue."""
238 with self._requestCondition:
239 self._requests.append(request)
240 self._requestCondition.notify()
241
242#------------------------------------------------------------------------------
243
244if __name__ == "__main__":
245 import time
246
247 def callback(returned, result):
248 print returned, unicode(result)
249
250 handler = Handler()
251 handler.start()
252
253 handler.login("P096", "V5fwj", callback)
254 time.sleep(3)
255
256#------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.