Last active
June 8, 2018 20:19
-
-
Save lukas2511/83969cb3b16a15a83a7e to your computer and use it in GitHub Desktop.
ParcelApp.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python2 | |
import re | |
import datetime | |
import urllib | |
import urllib2 | |
import cookielib | |
import os | |
import json | |
import curses | |
import sys | |
import traceback | |
import atexit | |
import time | |
SETTINGS_LOCATION = os.path.join(os.path.expanduser("~"), ".parcelapp") | |
COOKIE_LOCATION = os.path.join(SETTINGS_LOCATION, "cookies.txt") | |
IDENT_LOCATION = os.path.join(SETTINGS_LOCATION, "identifier.txt") | |
LOGIN_LOCATION = os.path.join(SETTINGS_LOCATION, "login.cfg") | |
LAST_UPDATE = None | |
MAIL = None | |
PASSWORD = None | |
def login(): | |
request = urllib2.Request('https://secure.parcelapp.net/login-webaccess.php', data=urllib.urlencode({'account_email': MAIL, 'account_password': PASSWORD})) | |
request.get_method = lambda: "POST" | |
loginret = opener.open(request).read() | |
cj.save() | |
identifier = re.search(r"""var\ identifier\ \=\ \"([0-9A-F\-]+)\"\;""", loginret).group(1) | |
identifier = open(IDENT_LOCATION, "w").write(identifier) | |
def get_data(): | |
global LAST_UPDATE | |
try: | |
cj.load() | |
except: | |
login() | |
try: | |
identifier = open(IDENT_LOCATION).read() | |
request = urllib2.Request('http://data.parcelapp.net/data-json.php?callback=yo&id=%s&caller=yes&compression=yes&version=3&_=1415036727429' % identifier) | |
data = opener.open(request).read() | |
except: | |
login() | |
try: | |
identifier = open(IDENT_LOCATION).read() | |
request = urllib2.Request('http://data.parcelapp.net/data-json.php?callback=yo&id=%s&caller=yes&compression=yes&version=3&_=1415036727429' % identifier) | |
data = opener.open(request).read() | |
except: | |
print("Uhm, error.") | |
return None | |
data = data.strip() | |
data = json.loads(data[3:-1]) | |
data = data[1] | |
menu = [] | |
for parcel in data: | |
for n in range(0,len(parcel['Data'])): | |
date = parcel['Data'][n]['Date'].strip() | |
if re.match(r"^[0-9]{2}\/[0-9]{2}\/[0-9]{4}\ [0-9]{2}:[0-9]{2}$", date): | |
date = datetime.datetime.strptime(date,"%m/%d/%Y %H:%M") | |
elif re.match(r"^[0-9]{2}\.[0-9]{2}\.[0-9]{4}\ [0-9]{2}:[0-9]{2}:[0-9]{2}$", date): | |
date = datetime.datetime.strptime(date,"%d.%m.%Y %H:%M:%S") | |
elif re.match(r"^[0-9]{2}\.[0-9]{2}\.[0-9]{4}\ [0-9]{2}:[0-9]{2}\ h$", date): | |
date = datetime.datetime.strptime(date,"%d.%m.%Y %H:%M h") | |
elif re.match(r"^[A-Z][a-z]{2},\ [0-9]{2}\.[0-9]{2}\.[0-9]{4}\ [0-9]{2}:[0-9]{2}\ h$", date): | |
date = datetime.datetime.strptime(date,"%a, %d.%m.%Y %H:%M h") | |
parcel['Data'][n]['Date'] = "%s" % date | |
if parcel['Update'] == "yes": | |
delivered = False | |
else: | |
delivered = True | |
menu.append([parcel['Label'], parcel['Number'], parcel['Type'], parcel['Data'][0]['Operation'], parcel, delivered]) | |
menu.sort(key = lambda k: k[4]['Data'][0]['Date'], reverse=True) | |
LAST_UPDATE = "%s" % datetime.datetime.now().strftime("%d.%m.%Y %H:%M:%S") | |
return menu | |
class pmenu(object): | |
menu = {} | |
ordered = [] | |
pos = 0 | |
ipos = 0 | |
def __init__(self, options, title="python curses menu"): | |
curses.initscr() | |
curses.start_color() | |
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_WHITE) | |
curses.curs_set(0) | |
curses.noecho() | |
self.screen = curses.initscr() | |
self.screen.keypad(1) | |
self.h = curses.color_pair(1) | |
self.n = curses.A_NORMAL | |
for k in range(0,len(options)): | |
self.menu[k] = options[k] | |
self.ordered.append(k) | |
self.title = title | |
atexit.register(self.cleanup) | |
def cleanup(self): | |
curses.doupdate() | |
curses.endwin() | |
def display(self): | |
screen = self.screen | |
while True: | |
screen.clear() | |
ckey = None | |
func = None | |
while ckey != ord('\n'): | |
screen.addstr(1, 1, self.title, curses.A_STANDOUT|curses.A_BOLD) | |
for n in range(0, len(self.menu)): | |
item = self.menu[n] | |
if n != self.pos: | |
color = self.n | |
else: | |
color = self.h | |
operation = item[3] | |
if len(operation) > 65: | |
operation = "%s..." % operation[:65] | |
screen.addstr(3 + n, 1, ("[%s] %s (%s - %s)" % ('x' if item[5] else ' ', item[0], operation, item[4]['Data'][0]['Date'])).encode("utf8"), color) | |
screen.addstr(3 + len(self.menu) + 1, 1, "Last Update: %s" % LAST_UPDATE, curses.A_STANDOUT) | |
screen.refresh() | |
ckey = screen.getch() | |
if ckey == 113: | |
self.cleanup() | |
sys.exit(0) | |
if ckey == 114: | |
screen.clear() | |
screen.refresh() | |
time.sleep(0.1) | |
self.menu = {} | |
self.ordered = [] | |
options = get_data() | |
for k in range(0,len(options)): | |
self.menu[k] = options[k] | |
self.ordered.append(k) | |
if ckey == 258 or ckey == 261: | |
self.pos = (self.pos + 1) % len(self.menu) | |
if ckey == 259 or ckey == 260: | |
self.pos = (self.pos - 1) % len(self.menu) | |
ckey = 0 | |
self.cleanup() | |
if self.pos >= 0 and self.pos < len(self.ordered): | |
self.ipos = 0 | |
while True: | |
item = self.menu[self.pos] | |
screen.clear() | |
screen.addstr(1, 1, item[0], curses.A_STANDOUT|curses.A_BOLD) | |
for n in range(0, len(item[4]['Data'])): | |
if n == self.ipos: | |
color = self.h | |
else: | |
color = self.n | |
screen.addstr(3 + n, 1, ("%s %s" % (item[4]['Data'][n]['Date'][:-3], item[4]['Data'][n]['Operation'])).encode("utf8"), color) | |
screen.addstr(3 + len(item[4]['Data']) + 1, 1, "Last Update: %s" % LAST_UPDATE, curses.A_STANDOUT) | |
ckey = screen.getch() | |
if ckey == 113: | |
break | |
if ckey == 114: | |
screen.clear() | |
screen.refresh() | |
time.sleep(0.1) | |
self.menu = {} | |
self.ordered = [] | |
options = get_data() | |
for k in range(0,len(options)): | |
self.menu[k] = options[k] | |
self.ordered.append(k) | |
if ckey == 258: | |
self.ipos = (self.ipos + 1) % len(item[4]['Data']) | |
if ckey == 259: | |
self.ipos = (self.ipos - 1) % len(item[4]['Data']) | |
if ckey == 260: | |
self.ipos = 0 | |
self.pos = (self.pos - 1) % len(self.menu) | |
if ckey == 261: | |
self.ipos = 0 | |
self.pos = (self.pos + 1) % len(self.menu) | |
else: | |
curses.flash() | |
cj = cookielib.LWPCookieJar(COOKIE_LOCATION) | |
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj)) | |
if not os.path.exists(SETTINGS_LOCATION): | |
os.mkdir(SETTINGS_LOCATION) | |
if not os.path.exists(LOGIN_LOCATION): | |
print("Please create the file %s with following content:" % LOGIN_LOCATION) | |
print("") | |
print("################################") | |
print("""[email protected]""") | |
print("""PASSWORD=password""") | |
print("################################") | |
print("") | |
print("Replace email address and password with your ParcelApp Premium login") | |
sys.exit(0) | |
else: | |
logindata = open(LOGIN_LOCATION).readlines() | |
for line in logindata: | |
line = line.strip() | |
if line[0:5] == "MAIL=": | |
MAIL = line[5:] | |
elif line[0:9] == "PASSWORD=": | |
PASSWORD = line[9:] | |
data = get_data() | |
if data: | |
c = pmenu(data, title="ParcelApp.py") | |
c.display() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment