mirror of
https://github.com/pyro2927/SouthwestCheckin.git
synced 2025-12-06 01:13:19 +00:00
Working on basic support for GMail
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*.swp
|
*.swp
|
||||||
|
client_secret.json
|
||||||
110
checkin.py
110
checkin.py
@@ -12,63 +12,63 @@ from math import trunc
|
|||||||
# Pulled from proxying the Southwest iOS App
|
# Pulled from proxying the Southwest iOS App
|
||||||
headers = {'Host': 'mobile.southwest.com', 'Content-Type': 'application/vnd.swacorp.com.mobile.reservations-v1.0+json', 'X-API-Key': 'l7xxab4b3533b8d54bad9df230deb96a6f90', 'Accept': '*/*'}
|
headers = {'Host': 'mobile.southwest.com', 'Content-Type': 'application/vnd.swacorp.com.mobile.reservations-v1.0+json', 'X-API-Key': 'l7xxab4b3533b8d54bad9df230deb96a6f90', 'Accept': '*/*'}
|
||||||
|
|
||||||
reservation_number = sys.argv[1]
|
def checkin(first_name, last_name, reservation_number):
|
||||||
first_name = sys.argv[2]
|
# Find our existing record
|
||||||
last_name = sys.argv[3]
|
url = "https://mobile.southwest.com/api/extensions/v1/mobile/reservations/record-locator/{}?first-name={}&last-name={}".format(reservation_number, first_name, last_name)
|
||||||
|
|
||||||
# Find our existing record
|
|
||||||
url = "https://mobile.southwest.com/api/extensions/v1/mobile/reservations/record-locator/{}?first-name={}&last-name={}".format(reservation_number, first_name, last_name)
|
|
||||||
|
|
||||||
r = requests.get(url, headers=headers)
|
|
||||||
body = r.json()
|
|
||||||
|
|
||||||
# Confirm this reservation is found
|
|
||||||
if 'httpStatusCode' in body and body['httpStatusCode'] == 'NOT_FOUND':
|
|
||||||
print(body['message'])
|
|
||||||
else:
|
|
||||||
now = datetime.now(pytz.utc).astimezone(get_localzone())
|
|
||||||
tomorrow = now + timedelta(days=1)
|
|
||||||
date = now
|
|
||||||
|
|
||||||
airport = ""
|
|
||||||
|
|
||||||
# Get the correct flight information
|
|
||||||
for leg in body['itinerary']['originationDestinations']:
|
|
||||||
departure_time = leg['segments'][0]['departureDateTime']
|
|
||||||
airport = leg['segments'][0]['originationAirportCode']
|
|
||||||
date = parse(departure_time)
|
|
||||||
# Stop when we reach a future flight
|
|
||||||
if date > now:
|
|
||||||
break
|
|
||||||
|
|
||||||
print("Flight information found, departing {} at {}".format(airport, date.strftime('%b %d %I:%M%p')))
|
|
||||||
|
|
||||||
# Wait until checkin time
|
|
||||||
if date > tomorrow:
|
|
||||||
delta = (date-tomorrow).total_seconds()
|
|
||||||
m, s = divmod(delta, 60)
|
|
||||||
h, m = divmod(m, 60)
|
|
||||||
print("Too early to check in. Waiting {} hours, {} minutes, {} seconds".format(trunc(h), trunc(m), s))
|
|
||||||
time.sleep(delta)
|
|
||||||
|
|
||||||
print("Attempting check-in...")
|
|
||||||
|
|
||||||
# Get our passengers to get boarding passes for
|
|
||||||
passengers = []
|
|
||||||
for passenger in body['passengers']:
|
|
||||||
passengers.append({'firstName': passenger['secureFlightName']['firstName'], 'lastName': passenger['secureFlightName']['lastName']})
|
|
||||||
|
|
||||||
# Check in
|
|
||||||
headers['Content-Type'] = 'application/vnd.swacorp.com.mobile.boarding-passes-v1.0+json'
|
|
||||||
url = "https://mobile.southwest.com/api/extensions/v1/mobile/reservations/record-locator/{}/boarding-passes".format(reservation_number)
|
|
||||||
r = requests.post(url, headers=headers, json={'names': passengers})
|
|
||||||
|
|
||||||
|
r = requests.get(url, headers=headers)
|
||||||
body = r.json()
|
body = r.json()
|
||||||
|
|
||||||
if 'httpStatusCode' in body and body['httpStatusCode'] == 'FORBIDDEN':
|
# Confirm this reservation is found
|
||||||
|
if 'httpStatusCode' in body and body['httpStatusCode'] == 'NOT_FOUND':
|
||||||
print(body['message'])
|
print(body['message'])
|
||||||
else:
|
else:
|
||||||
# Spit out info about boarding number
|
now = datetime.now(pytz.utc).astimezone(get_localzone())
|
||||||
for checkinDocument in body['passengerCheckInDocuments']:
|
tomorrow = now + timedelta(days=1)
|
||||||
for doc in checkinDocument['checkinDocuments']:
|
date = now
|
||||||
print("You got {}{}!".format(doc['boardingGroup'], doc['boardingGroupNumber']))
|
|
||||||
|
airport = ""
|
||||||
|
|
||||||
|
# Get the correct flight information
|
||||||
|
for leg in body['itinerary']['originationDestinations']:
|
||||||
|
departure_time = leg['segments'][0]['departureDateTime']
|
||||||
|
airport = leg['segments'][0]['originationAirportCode']
|
||||||
|
date = parse(departure_time)
|
||||||
|
# Stop when we reach a future flight
|
||||||
|
if date > now:
|
||||||
|
break
|
||||||
|
|
||||||
|
print("Flight information found, departing {} at {}".format(airport, date.strftime('%b %d %I:%M%p')))
|
||||||
|
|
||||||
|
# Wait until checkin time
|
||||||
|
if date > tomorrow:
|
||||||
|
delta = (date-tomorrow).total_seconds()
|
||||||
|
m, s = divmod(delta, 60)
|
||||||
|
h, m = divmod(m, 60)
|
||||||
|
print("Too early to check in. Waiting {} hours, {} minutes, {} seconds".format(trunc(h), trunc(m), s))
|
||||||
|
time.sleep(delta)
|
||||||
|
|
||||||
|
print("Attempting check-in...")
|
||||||
|
|
||||||
|
# Get our passengers to get boarding passes for
|
||||||
|
passengers = []
|
||||||
|
for passenger in body['passengers']:
|
||||||
|
passengers.append({'firstName': passenger['secureFlightName']['firstName'], 'lastName': passenger['secureFlightName']['lastName']})
|
||||||
|
|
||||||
|
# Check in
|
||||||
|
headers['Content-Type'] = 'application/vnd.swacorp.com.mobile.boarding-passes-v1.0+json'
|
||||||
|
url = "https://mobile.southwest.com/api/extensions/v1/mobile/reservations/record-locator/{}/boarding-passes".format(reservation_number)
|
||||||
|
r = requests.post(url, headers=headers, json={'names': passengers})
|
||||||
|
|
||||||
|
body = r.json()
|
||||||
|
|
||||||
|
if 'httpStatusCode' in body and body['httpStatusCode'] == 'FORBIDDEN':
|
||||||
|
print(body['message'])
|
||||||
|
else:
|
||||||
|
# Spit out info about boarding number
|
||||||
|
for checkinDocument in body['passengerCheckInDocuments']:
|
||||||
|
for doc in checkinDocument['checkinDocuments']:
|
||||||
|
print("You got {}{}!".format(doc['boardingGroup'], doc['boardingGroupNumber']))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main(sys.argv[1], sys.argv[2], sys.argv[3])
|
||||||
|
|||||||
79
gmail.py
Normal file
79
gmail.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
from __future__ import print_function
|
||||||
|
import base64
|
||||||
|
import httplib2
|
||||||
|
import os
|
||||||
|
|
||||||
|
from apiclient import discovery
|
||||||
|
from oauth2client import client
|
||||||
|
from oauth2client import tools
|
||||||
|
from oauth2client.file import Storage
|
||||||
|
|
||||||
|
from scrapy.selector import Selector
|
||||||
|
from scrapy.http import HtmlResponse
|
||||||
|
|
||||||
|
import checkin
|
||||||
|
|
||||||
|
try:
|
||||||
|
import argparse
|
||||||
|
flags = argparse.ArgumentParser(parents=[tools.argparser]).parse_args()
|
||||||
|
except ImportError:
|
||||||
|
flags = None
|
||||||
|
|
||||||
|
SCOPES = 'https://www.googleapis.com/auth/gmail.readonly'
|
||||||
|
CLIENT_SECRET_FILE = 'client_secret.json'
|
||||||
|
APPLICATION_NAME = 'SW Checking App'
|
||||||
|
|
||||||
|
def get_credentials():
|
||||||
|
"""Gets valid user credentials from storage.
|
||||||
|
|
||||||
|
If nothing has been stored, or if the stored credentials are invalid,
|
||||||
|
the OAuth2 flow is completed to obtain the new credentials.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Credentials, the obtained credential.
|
||||||
|
"""
|
||||||
|
home_dir = os.path.expanduser('~')
|
||||||
|
credential_dir = os.path.join(home_dir, '.credentials')
|
||||||
|
if not os.path.exists(credential_dir):
|
||||||
|
os.makedirs(credential_dir)
|
||||||
|
credential_path = os.path.join(credential_dir,
|
||||||
|
'sw-checkin.json')
|
||||||
|
|
||||||
|
store = Storage(credential_path)
|
||||||
|
credentials = store.get()
|
||||||
|
if not credentials or credentials.invalid:
|
||||||
|
flow = client.flow_from_clientsecrets(CLIENT_SECRET_FILE, SCOPES)
|
||||||
|
flow.user_agent = APPLICATION_NAME
|
||||||
|
if flags:
|
||||||
|
credentials = tools.run_flow(flow, store, flags)
|
||||||
|
else: # Needed only for compatibility with Python 2.6
|
||||||
|
credentials = tools.run(flow, store)
|
||||||
|
print('Storing credentials to ' + credential_path)
|
||||||
|
return credentials
|
||||||
|
|
||||||
|
def main():
|
||||||
|
""" Pulling Southwest emails from GMail """
|
||||||
|
credentials = get_credentials()
|
||||||
|
http = credentials.authorize(httplib2.Http())
|
||||||
|
service = discovery.build('gmail', 'v1', http=http)
|
||||||
|
|
||||||
|
results = service.users().messages().list(userId='me').execute()
|
||||||
|
messages = results.get('messages', [])
|
||||||
|
|
||||||
|
if not messages:
|
||||||
|
print('No emails found.')
|
||||||
|
else:
|
||||||
|
for message in messages:
|
||||||
|
r = service.users().messages().get(userId='me',id=message['id'],format='full').execute()
|
||||||
|
if "Southwest" in r['snippet'] and r['payload']['body'].has_key('data'):
|
||||||
|
body = base64.urlsafe_b64decode(r['payload']['body']['data'].encode('UTF-8'))
|
||||||
|
selector = Selector(text=body)
|
||||||
|
divs = selector.css('span[style*="23972a"]::text').extract()
|
||||||
|
if len(divs) > 0:
|
||||||
|
conf = divs[0].replace("\r", "").replace("\n", "").strip()
|
||||||
|
name = selector.css('div[style*="13px"]::text').extract()[13]
|
||||||
|
last_name, first_name = name.strip().split('/')
|
||||||
|
checkin.checkin(first_name, last_name, conf)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -3,3 +3,5 @@ python-dateutil
|
|||||||
pytz
|
pytz
|
||||||
requests
|
requests
|
||||||
tzlocal
|
tzlocal
|
||||||
|
google-api-python-client
|
||||||
|
scrapy
|
||||||
|
|||||||
Reference in New Issue
Block a user