Skip to content

Commit a4579c5

Browse files
committed
reimplemented simyo script in python
1 parent 16b2a10 commit a4579c5

File tree

1 file changed

+327
-0
lines changed

1 file changed

+327
-0
lines changed

simyo/simyo.py

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
#
4+
# quick-n-dirty simyo.es consumption checker v3
5+
# (c) 2013 Pau Oliva - pof [at] eslack (.) org
6+
#
7+
# license: WTFPL (Do What The Fuck You Want To Public License)
8+
#
9+
# api functions reverse engineered from the com.simyo android app
10+
#
11+
# enter your simyo.es username and password below
12+
13+
import sys
14+
import argparse
15+
import pyDes
16+
import base64
17+
import urllib
18+
import urllib2
19+
import hmac
20+
import hashlib
21+
import json
22+
import datetime
23+
24+
__author__ = 'Pau Oliva Fora'
25+
26+
USERNAME = ""
27+
PASSWORD = ""
28+
29+
def getApiSig(url):
30+
dig = hmac.new(b'f25a2s1m10', msg='f25a2s1m10' + url.lower(), digestmod=hashlib.sha256).digest()
31+
return url + "&apiSig=" + dig.encode('hex')
32+
33+
def simyopass():
34+
k = pyDes.triple_des("25d1d4cb0a08403e2acbcbe0", pyDes.ECB, "\0\0\0\0\0\0\0\0", pad=None, padmode=pyDes.PAD_PKCS5)
35+
d = urllib.quote(base64.b64encode(k.encrypt(PASSWORD)) + '\n')
36+
#print "Encrypted: %r" % d
37+
#print "Decrypted: %r" % k.decrypt(base64.b64decode(urllib.unquote(d)))
38+
return d
39+
40+
def writeFile(filename, content):
41+
in_file = open(filename,"wb")
42+
in_file.write(content)
43+
in_file.close()
44+
45+
def api_request(url, data=""):
46+
kPublicKey="a654fb77dc654a17f65f979ba8794c34"
47+
48+
if url[-1:] == "?":
49+
url=url + "publicKey=" + kPublicKey
50+
else:
51+
url=url + "&publicKey=" + kPublicKey
52+
53+
url=getApiSig(url)
54+
55+
if VERBOSE:
56+
print "URL: " + url
57+
58+
if data=="":
59+
req = urllib2.Request(url)
60+
else:
61+
req = urllib2.Request(url,data)
62+
63+
try:
64+
result = urllib2.urlopen(req).read()
65+
except urllib2.HTTPError as e:
66+
print e
67+
sys.exit(1)
68+
except urllib2.URLError as e:
69+
print e
70+
sys.exit(1)
71+
except:
72+
print "Unexpected error :("
73+
raise
74+
75+
return result
76+
77+
def api_logout():
78+
URL="https://www.simyo.es/api/logout?sessionId=" + str(sessionId)
79+
result = api_request(URL)
80+
if VERBOSE: print result + "\n"
81+
82+
def api_login():
83+
global sessionId, customerId
84+
85+
SIMYOPASS = simyopass()
86+
URL="https://www.simyo.es/api/login?"
87+
data = "user=" + USERNAME + "&password=" + SIMYOPASS + "&apiSig=null"
88+
result = api_request(URL,data)
89+
if VERBOSE: print result + "\n"
90+
91+
sessionId = json.loads(result)['response']['sessionId']
92+
customerId = json.loads(result)['response']['customerId']
93+
94+
def subscriptions():
95+
global registerDate, mainProductId, billCycleType, msisdn, subscriberId, payType
96+
97+
URL="https://www.simyo.es/api/subscriptions/" + str(customerId) + "?sessionId=" + str(sessionId)
98+
result = api_request(URL)
99+
if VERBOSE: print result + "\n"
100+
101+
data = json.loads(result)
102+
for subscription in reversed(data['response']['subcriptions']):
103+
registerDate = subscription['registerDate']
104+
mainProductId = subscription['mainProductId']
105+
billCycleType = subscription['billCycleType']
106+
msisdn = subscription['msisdn']
107+
subscriberId = subscription['subscriberId']
108+
payType = subscription['subscriberId']
109+
if SHOWMSISDN:
110+
print "MSISDN: " + msisdn + " (product=" + mainProductId +")"
111+
else:
112+
if msisdn == MSISDN:
113+
break
114+
115+
if SHOWMSISDN:
116+
api_logout()
117+
sys.exit(0)
118+
119+
def consumptionByCycle():
120+
billCycleCount=""
121+
URL="https://www.simyo.es/api/consumptionByCycle/" + str(customerId) + "?sessionId=" + str(sessionId) + "&msisdn=" + str(msisdn) + "&billCycleType=" + str(billCycleType) + "&registerDate=" + str(registerDate) + "&billCycle=" + str(billCycle) + "&billCycleCount=" + str(billCycleCount) + "&payType=" + str(payType)
122+
result = api_request(URL)
123+
if VERBOSE: print result + "\n"
124+
125+
data = json.loads(result)
126+
127+
startDate=data['response']['consumptionsByCycle'][0]['startDate']
128+
endDate=data['response']['consumptionsByCycle'][0]['endDate']
129+
startDate = str(startDate)[0:10]
130+
endDate = str(endDate)[0:10]
131+
start = datetime.datetime.fromtimestamp(int(startDate)).strftime('%d/%m/%Y')
132+
end = datetime.datetime.fromtimestamp(int(endDate)).strftime('%d/%m/%Y')
133+
print "\nPeriodo de " + start + " a " + end + "\n"
134+
135+
count = data['response']['consumptionsByCycle'][0]['voice']['count']
136+
chargeTotal = float(data['response']['consumptionsByCycle'][0]['voice']['chargeTotal'])
137+
hms = datetime.timedelta(seconds=count)
138+
print "Llamadas: " + str(hms) + " (" + str(chargeTotal) + ") EUR"
139+
140+
count = data['response']['consumptionsByCycle'][0]['sms']['count']
141+
chargeTotal = float(data['response']['consumptionsByCycle'][0]['sms']['chargeTotal'])
142+
print "SMS: " + str(count) + " (" + str(chargeTotal) + " EUR)"
143+
144+
count = data['response']['consumptionsByCycle'][0]['mms']['count']
145+
if count > 0:
146+
chargeTotal = data['response']['consumptionsByCycle'][0]['mms']['chargeTotal']
147+
print "MMS: " + str(count) + " (" + str(chargeTotal) + " EUR)"
148+
149+
count = data['response']['consumptionsByCycle'][0]['data']['count']
150+
chargeTotal = float(data['response']['consumptionsByCycle'][0]['data']['chargeTotal'])
151+
count = count/1024.0/1024.0
152+
print "Datos: {0:.2f} MB (".format(count) + str(chargeTotal) + " EUR)"
153+
154+
PRINT=1
155+
156+
count = data['response']['consumptionsByCycle'][0]['voicePremium']['count']
157+
if count > 0:
158+
chargeTotal = float(data['response']['consumptionsByCycle'][0]['voicePremium']['chargeTotal'])
159+
hms = datetime.timedelta(seconds=count)
160+
if PRINT: print ; PRINT=0
161+
print "Llamadas Premium: " + str(hms) + " (" + str(chargeTotal) + ") EUR"
162+
163+
count = data['response']['consumptionsByCycle'][0]['smsPremium']['count']
164+
if count > 0:
165+
chargeTotal = data['response']['consumptionsByCycle'][0]['smsPremium']['chargeTotal']
166+
if PRINT: print ; PRINT=0
167+
print "SMS Premium: " + str(count) + " (" + str(chargeTotal) + " EUR)"
168+
169+
PRINT=1
170+
171+
count = data['response']['consumptionsByCycle'][0]['voiceOutgoingRoaming']['count']
172+
if count > 0:
173+
chargeTotal = float(data['response']['consumptionsByCycle'][0]['voiceOutgoingRoaming']['chargeTotal'])
174+
hms = datetime.timedelta(seconds=count)
175+
if PRINT: print ; PRINT=0
176+
print "Llamadas Salientes Roaming: " + str(hms) + " (" + str(chargeTotal) + ") EUR"
177+
178+
count = data['response']['consumptionsByCycle'][0]['voiceIngoingRoaming']['count']
179+
if count > 0:
180+
chargeTotal = float(data['response']['consumptionsByCycle'][0]['voiceIngoingRoaming']['chargeTotal'])
181+
hms = datetime.timedelta(seconds=count)
182+
if PRINT: print ; PRINT=0
183+
print "Llamadas Entrantes Roaming: " + str(hms) + " (" + str(chargeTotal) + ") EUR"
184+
185+
count = data['response']['consumptionsByCycle'][0]['smsRoaming']['count']
186+
if count > 0:
187+
chargeTotal = data['response']['consumptionsByCycle'][0]['smsRoaming']['chargeTotal']
188+
if PRINT: print ; PRINT=0
189+
print "SMS Roaming: " + str(count) + " (" + str(chargeTotal) + " EUR)"
190+
191+
count = data['response']['consumptionsByCycle'][0]['mmsRoaming']['count']
192+
if count > 0:
193+
chargeTotal = data['response']['consumptionsByCycle'][0]['mmsRoaming']['chargeTotal']
194+
if PRINT: print ; PRINT=0
195+
print "MMS Roaming: " + str(count) + " (" + str(chargeTotal) + " EUR)"
196+
197+
count = data['response']['consumptionsByCycle'][0]['dataRoaming']['count']
198+
if count > 0:
199+
chargeTotal = float(data['response']['consumptionsByCycle'][0]['dataRoaming']['chargeTotal'])
200+
count = count/1024.0/1024.0
201+
if PRINT: print ; PRINT=0
202+
print "Datos Roaming: {0:.2f} MB (".format(count) + str(chargeTotal) + " EUR)"
203+
204+
chargeTotal = float(data['response']['consumptionsByCycle'][0]['chargeTotal'])
205+
print "\nConsumo total: " + str(chargeTotal) + " EUR\n"
206+
207+
def mgmHistory():
208+
URL="https://www.simyo.es/api/mgmHistory/" + str(customerId) + "?sessionId=" + str(sessionId)
209+
result = api_request(URL)
210+
if VERBOSE: print result + "\n"
211+
212+
data = json.loads(result)
213+
receivedPoints=data['response']['mgmHistoryList']['receivedPoints']
214+
usedPoints=data['response']['mgmHistoryList']['usedPoints']
215+
totalAvailablePoints=data['response']['mgmHistoryList']['totalAvailablePoints']
216+
217+
print "EUROS GANADOS: " + str(receivedPoints)
218+
print "EUROS GASTADOS: " + str(usedPoints)
219+
print "TOTAL DISPONIBLE: " + str(totalAvailablePoints)
220+
221+
def invoiceList():
222+
URL="https://www.simyo.es/api/invoiceList/" + str(customerId) + "?msisdn=" + str(msisdn) + "&sessionId=" + str(sessionId) + "&billCycleType=" + str(billCycleType) + "&registerDate=" + str(registerDate)
223+
result = api_request(URL)
224+
if VERBOSE: print result + "\n"
225+
226+
data = json.loads(result)
227+
return data
228+
229+
def printInvoiceList():
230+
data = invoiceList()
231+
for invoice in data['response']['invoiceList']:
232+
startDate=invoice['startDate']
233+
startDate = str(startDate)[0:10]
234+
endDate=invoice['endDate']
235+
endDate = str(endDate)[0:10]
236+
invoiceNO=invoice['invoiceNO']
237+
invoiceId=invoice['invoiceId']
238+
start = datetime.datetime.fromtimestamp(int(startDate)).strftime('%d/%m/%Y')
239+
end = datetime.datetime.fromtimestamp(int(endDate)).strftime('%d/%m/%Y')
240+
print "Factura " + str(invoiceNO) + " (id=" + str(invoiceId) + ") del " + str(start) + " al " + str(end)
241+
242+
def downloadInvoice():
243+
data = invoiceList()
244+
for invoice in data['response']['invoiceList']:
245+
invoiceId=invoice['invoiceId']
246+
if invoiceId == reqInvoiceId:
247+
invoiceNO=invoice['invoiceNO']
248+
break
249+
if invoiceNO=="":
250+
print "Can't find invoice with id = " + str(reqInvoiceId)
251+
sys.exit(1)
252+
253+
URL="https://www.simyo.es/api/downloadInvoice?sessionId=" + str (sessionId) + "&invoiceNO=" + str(invoiceNO) + "&invoiceId=" + str(invoiceId)
254+
result = api_request(URL)
255+
if VERBOSE: print result + "\n"
256+
257+
data = json.loads(result)
258+
filename = data['response']['invoice']['filename']
259+
print "File: " + str(filename)
260+
content=base64.b64decode(data['response']['invoice']['content'])
261+
writeFile(filename, content)
262+
263+
def parse_cmd():
264+
global VERBOSE, INVOICELIST, MSISDN, SHOWMSISDN, SHOWMGM, INVOICEDOWNLOAD
265+
global billCycle, reqInvoiceId
266+
267+
parser = argparse.ArgumentParser()
268+
parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='verbose mode')
269+
parser.add_argument('-b', '--billcycle', dest='billCycle', help='bill cycle (from 1 to 6), default=1')
270+
parser.add_argument('-l', '--listinvoice', dest='invoicelist', action='store_true', help='list invoices')
271+
parser.add_argument('-d', '--downloadinvoice', dest='invoice_id', help='download invoice')
272+
parser.add_argument('-m', '--msisdn', dest='msisdn', help='msisdn if you have more than 1 line')
273+
parser.add_argument('-s', '--showmsisdn', dest='showmsisdn', action='store_true', help='show user\'s msisdn')
274+
parser.add_argument('-g', '--mgm', dest='showmgm', action='store_true', help='show member-get-member history')
275+
args = parser.parse_args()
276+
277+
if USERNAME=="":
278+
print "Edit the script to enter your username/password"
279+
sys.exit(1)
280+
281+
VERBOSE = args.verbose
282+
MSISDN = args.msisdn
283+
SHOWMSISDN = args.showmsisdn
284+
SHOWMGM = args.showmgm
285+
INVOICELIST = args.invoicelist
286+
287+
if args.invoice_id == None:
288+
INVOICEDOWNLOAD=0
289+
else:
290+
reqInvoiceId = args.invoice_id
291+
INVOICEDOWNLOAD=1
292+
293+
if args.billCycle == None:
294+
billCycle = int(1)
295+
else:
296+
billCycle = int(args.billCycle)
297+
298+
if (billCycle > 6) or (billCycle < 1):
299+
sys.stderr.write('Billing Cycle must be an integer from 1 (current month) to 6\n');
300+
sys.exit(1)
301+
302+
if __name__ == '__main__':
303+
parse_cmd()
304+
api_login()
305+
subscriptions()
306+
if SHOWMGM:
307+
mgmHistory()
308+
api_logout()
309+
sys.exit(0)
310+
if INVOICELIST:
311+
printInvoiceList()
312+
api_logout()
313+
sys.exit(0)
314+
if INVOICEDOWNLOAD:
315+
downloadInvoice()
316+
api_logout()
317+
sys.exit(0)
318+
consumptionByCycle()
319+
api_logout()
320+
321+
#TODO:
322+
#consumptionDetailByCycle
323+
#frequentNumbers
324+
#messages
325+
#voiceCalls
326+
#rechargeHistory
327+
#https://www.simyo.es/api/contact

0 commit comments

Comments
 (0)