Skip to content

Instantly share code, notes, and snippets.

@NivenT
Created December 1, 2020 02:10
Show Gist options
  • Save NivenT/e56c6301350e7eac3646d084fbfa16df to your computer and use it in GitHub Desktop.
Save NivenT/e56c6301350e7eac3646d084fbfa16df to your computer and use it in GitHub Desktop.
Don't you hate not owning a ps5? This might help (but probably won't). Periodically checks for in-stock ps5s and then launches firefox when one is found. If you want, you can make a free trial [Twilio account](www.twilio.com/referral/DNJ8MN) and then provide a file containing your account sid, account auth token, account phone number, and person…
#!/usr/bin/python3
import requests
import sys
from html.parser import HTMLParser
from validators import url as is_url
from os import system as cmdline
from time import sleep
from twilio.rest import Client
def print_usage(prog_name):
print('Usage:')
print(f' {prog_name} (-h | --help)')
print(f' {prog_name} TWILIO_INFO_FILE')
print(f' {prog_name}')
def format_alert(stock):
return f'PS5s are \'{stock.status}\' ({stock.name}) at \n{stock.url}'
class Twilio:
def __init__(self, path):
self.sid = ''
self.auth = ''
self.from_num = ''
self.to_num = ''
try:
with open(path, 'r') as info:
lines = info.readlines()
self.sid = lines[0]
self.auth = lines[1]
self.from_num = lines[2]
self.to_num = lines[3]
except:
pass
def send_sms(self, stock):
if '' in [self.sid, self.auth, self.from_num, self.to_num]: return
client = Client(self.sid, self.auth)
msg = format_alert(stock)
client.api.account.messages.create(to=self.to_num, from_=self.from_num, body=msg)
class Stock:
def __init__(self):
self.count = 0
self.name = 'N/A'
self.status = 'N/A'
self.url = 'N/A'
def __repr__(self):
return f'{{\n name: {self.name}\n status: {self.status}\n url: {self.url}\n}}'
def update(self, data):
if self.count == 0: self.url = data
elif self.count == 1: self.name = data
elif self.count == 2: self.status = data
self.count += 1
class StockParser(HTMLParser):
def __init__(self):
super().__init__()
self.stocks = []
self.curr = Stock()
self.in_tr = False
self.in_td = False
def handle_starttag(self, tag, attr):
if tag == 'tr':
self.in_tr = True
elif self.in_tr:
if tag == 'a':
#print(f'{tag}: {attr}')
self.curr.update(attr[0][1])
elif tag == 'td':
self.in_td = True
def handle_endtag(self, tag):
if tag == 'tr':
self.in_tr = False
self.stocks += [self.curr]
self.curr = Stock()
elif tag == 'td':
self.in_td = False
def handle_data(self, data):
if self.in_tr and self.in_td:
self.curr.update(data)
self.in_td = False
def is_well_formed(stock):
if 'N/A' in [stock.name, stock.status, stock.url]:
return False
if 'Ebay' in stock.name:
return False
magic_number = len('Out of Stock') + len('Stock Available')
if len(stock.status) > magic_number:
return False
if not is_url(stock.url):
return False
return True
def extract_table(resp):
if resp.status_code/100 != 2:
print(f'response ({r.status_code}) error message:\n{r.text}')
return ''
table_start = resp.text.find('<table')
if table_start == -1:
print('Could not find table')
return ''
table_end = resp.text.find('</table', table_start)
if table_end == -1:
print('Could not find end of table')
return ''
table_str = resp.text[table_start:table_end+len('</table>')]
return table_str
def open_url(url):
cmdline(f'firefox {url}')
def alert(twil, stock):
print(f'\a{format_alert(stock)}\a')
twil.send_sms(stock)
open_url(stock.url)
def check_stock(twil):
r = requests.get('https://www.nowinstock.net/videogaming/consoles/sonyps5/')
table_str = extract_table(r)
if table_str == '': return
parser = StockParser()
parser.feed(table_str)
stocks = filter(is_well_formed, parser.stocks)
#stocks = list(stocks)
for s in stocks:
#print(s)
if 'Out' not in s.status and 'out' not in s.status:
alert(twil, s)
#alert(twil, stocks[8])
def main():
if len(sys.argv) > 2 or len([x for x in ['-h', '--help'] if x in sys.argv]) > 0:
print_usage(sys.argv[0])
else:
CHECKS_PER_PRINT = 20
SECS_PER_CHECK = 30
twil = Twilio(sys.argv[1] if len(sys.argv) > 1 else '')
counter = 0
while True:
if counter%CHECKS_PER_PRINT == 0: print(f'Check number {counter}...')
check_stock(twil)
sleep(SECS_PER_CHECK)
counter += 1
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment