Last active
December 11, 2021 21:41
-
-
Save gene1wood/236f1dcc082950afb4851a382951820c to your computer and use it in GitHub Desktop.
Tool to fetch a Redpocket account's balance of minutes, texts and data and write that in JSON to a file
This file contains hidden or 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
import logging | |
from bs4 import BeautifulSoup | |
import requests | |
import yaml | |
import json | |
import os.path | |
import datetime | |
import re | |
import sys | |
# https://gist.github.com/gene1wood/236f1dcc082950afb4851a382951820c | |
logging.basicConfig() | |
logger = logging.getLogger() | |
loglevel = logging.DEBUG if '-v' in sys.argv else logging.ERROR | |
logger.setLevel(loglevel) | |
WARN_VOICE = 15 | |
WARN_MESSAGING = 10 | |
WARN_DATA = 50 | |
MIN_VOICE = 15 | |
MIN_MESSAGING = 10 | |
MIN_DATA = 50 | |
DATA_UNIT_MULTIPLIER = { | |
'MB': 1, | |
'GB': 1024 | |
} | |
def buy_addon(user, jar): | |
# TODO : Finish developing this auto buy thing | |
page = requests.post( | |
'https://www.redpocket.com/refill/refill-addons', | |
cookies=jar) | |
# get sku | |
page = requests.get( | |
'https://www.redpocket.com/refill/refill-plan-new/%s' % sku, | |
cookies=jar) | |
page = requests.post( | |
'https://www.redpocket.com/refill/setup-payment/%s' % sku, | |
cookies=jar) | |
# get securityNumber | |
data = user['billing'] | |
data['term_check'] = 1 | |
data['securityNumber'] = 'foo' | |
data['autorenew'] = 0 | |
page = requests.post( | |
'https://www.redpocket.com/refill/charge', | |
data=data, | |
cookies=jar) | |
# { | |
# "name": "fname", | |
# "value": "First" | |
# }, | |
# { | |
# "name": "lname", | |
# "value": "Last" | |
# }, | |
# { | |
# "name": "phone", | |
# "value": "2125555555" | |
# }, | |
# { | |
# "name": "email", | |
# "value": "[email protected]" | |
# }, | |
# { | |
# "name": "address1", | |
# "value": "123+First+St." | |
# }, | |
# { | |
# "name": "address2", | |
# "value": "" | |
# }, | |
# { | |
# "name": "country", | |
# "value": "US" | |
# }, | |
# { | |
# "name": "state", | |
# "value": "NY" | |
# }, | |
# { | |
# "name": "city", | |
# "value": "New York" | |
# }, | |
# { | |
# "name": "zip", | |
# "value": "10002" | |
# }, | |
# { | |
# "name": "term_check", | |
# "value": "1" | |
# }, | |
# { | |
# "name": "securityNumber", | |
# "value": "6a39762c8441da30f52a7138999688c26a39762c8441da30f52a7138999688c2" | |
# }, | |
# { | |
# "name": "autorenew", | |
# "value": "0" | |
# }, | |
# { | |
# "name": "stripeSource", | |
# "value": "src_JVxUnuf208q3dNkuJVxUnuf2" | |
# } | |
def process_user(user): | |
jar = requests.cookies.RequestsCookieJar() | |
page = requests.get('https://www.redpocket.com/login', cookies=jar) | |
soup = BeautifulSoup(page.text, 'html.parser') | |
csrf = soup.select( | |
'body div.content div.container div form.form-signin input[name=csrf]' | |
)[0]['value'] | |
logger.debug('CSRF is {}'.format(csrf)) | |
data = { | |
'mdn': user['username'], | |
'password': user['password'], | |
'remember_me': 1, | |
'redirect_url': '', | |
'csrf': csrf | |
} | |
requests.post( | |
'https://www.redpocket.com/login', | |
data=data, | |
cookies=jar) | |
logger.debug('Cookies are {}'.format(jar)) | |
data = {'refill_mdn': user['mdn']} | |
page = requests.post( | |
'https://www.redpocket.com/refill/get-account-info', | |
data=data, | |
cookies=jar | |
) | |
result = page.json() | |
logger.debug('get-account-info : {}'.format(result)) | |
total = {} | |
# 30 Day- Unlimited Everything (10GB@4G LTE) | |
# 30 Day- Unlimited Everything (3GB@4G LTE) | |
# 30 Day- Unlimited Everything (5GB@4G LTE) | |
# 30 Day- Unlimited Everything (3GB@ 4G LTE) | |
# 30 Day- Unlimited Everything (1GB@4G LTE) | |
# 30 Day- Unlimited Minutes, Unlimited Texts, 3GB@ 4G LTE | |
# 30 Day- Unlimited Minutes, Unlimited Texts, 1.5GB@4G LTE | |
# 30 Day- Unlimited Minutes, Unlimited Texts, 1GB@ 4G LTE | |
# 30 Day- Unlimited Minutes, Unlimited Texts, 500MB@4G LTE | |
# 30 Day- Unlimited Minutes, Unlimited Texts, 500MB@ 4G LTE | |
# 30 Day- 300 Minutes, Unlimited Texts & Data (2GB@4G LTE) | |
# 90 Day- 1000 Minutes, 1000 Texts & 1GB@4G LTE | |
# 30 Day- 1000 Minutes, 1000 Texts & 1GB@4G LTE | |
# 30 Day- 500 Minutes, 500 Texts & 500MB@4G LTE | |
# 180 Day- PayGo Plan | |
# 90 Day- PayGo Plan | |
# 30 Day- PayGo Plan | |
# $60- Annual 100 MOU/100 SMS/500MB Plan | |
user_output = { | |
'datetime': "%s" % datetime.datetime.now(), | |
'plan_name': result['plan'], | |
'expiration_date': result['aed']} | |
logger.debug('Plan : {}'.format(result['plan'])) | |
if 'PayGo' in result['plan']: | |
pass | |
elif 'Annual' in result['plan']: | |
match = re.search( | |
r'(\d+) MOU/(\d+) SMS/([.\d]+)([MG]B)', result['plan']) | |
if match: | |
total['minutes'] = match.group(1) | |
total['messaging'] = match.group(2) | |
total['data'] = ( | |
int(match.group(3)) * DATA_UNIT_MULTIPLIER[match.group(4)]) | |
else: | |
match = re.search( | |
r'(\d+|Unlimited) (Minutes|Everything)', result['plan']) | |
if match: | |
total['minutes'] = ( | |
0 if match.group(1) == 'Unlimited' | |
else int(match.group(1))) | |
match = re.search( | |
r'(\d+|Unlimited) (Texts|Everything)', result['plan']) | |
if match: | |
total['messaging'] = ( | |
0 if match.group(1) == 'Unlimited' | |
else int(match.group(1))) | |
if ('Unlimited Everything' in result['plan'] | |
or 'Unlimited Texts & Data' in result['plan']): | |
finite_data_type = '4g_data' | |
total['data'] = 0 | |
else: | |
finite_data_type = 'data' | |
match = re.search(r'([.\d]+)([MG]B)', result['plan']) | |
if match: | |
total[finite_data_type] = ( | |
int(match.group(1)) * DATA_UNIT_MULTIPLIER[match.group(2)]) | |
if '4g_data' not in total: | |
total['4g_data'] = total['data'] | |
user_output['voice_balance'] = result.get('voice_balance') | |
user_output['total_voice'] = total.get('minutes') | |
user_output['messaging_balance'] = result.get('messaging_balance') | |
user_output['total_messaging'] = total.get('messaging') | |
user_output['data_balance'] = result.get('data_balance') | |
user_output['status'] = True | |
user_output['description'] = '' | |
if result['voice_balance'] < WARN_VOICE: | |
user_output['status'] = False | |
user_output['description'] += ( | |
'Remaining voice balance is only %s minutes. ' % | |
result['voice_balance']) | |
if result['messaging_balance'] < WARN_MESSAGING: | |
user_output['status'] = False | |
user_output['description'] += ( | |
'Remaining SMS balance is only %s texts. ' % | |
result['messaging_balance']) | |
if result['data_balance'] < WARN_DATA: | |
user_output['status'] = False | |
user_output['description'] += ( | |
'Remaining data balance is only %s MB' % | |
result['data_balance']) | |
if user.get('buy_addons') and result['data_balance'] < MIN_DATA: | |
result = buy_addon(user, jar) | |
return user_output | |
def main(): | |
with open(os.path.expanduser('~/.redpocket.conf')) as f: | |
config = yaml.load(f) | |
output = {} | |
status = True | |
description = '' | |
for user in config['users']: | |
output[user['username']] = process_user(user) | |
status = status and output[user['username']]['status'] | |
description += output[user['username']]['description'] | |
if not description: | |
description = ( | |
'All pocket accounts have enough data minutes and messages ' | |
'remaining') | |
output['status'] = status | |
output['description'] = description | |
logger.debug('Result : {}'.format(output)) | |
with open('/var/www/html/redpocket-balance.json', 'w') as f: | |
json.dump(output, f, indent=4, sort_keys=True) | |
with open('/var/www/html/redpocket-balance.csv', 'a') as f: | |
for user in config['users']: | |
record = output[user['username']] | |
f.write("{},{},{},{},{}\n".format( | |
record['datetime'], user['username'], record['data_balance'], | |
record['messaging_balance'], record['voice_balance'])) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment