first commit
This commit is contained in:
commit
ea264a41e7
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
*.log
|
||||
__pycache__
|
||||
*.png
|
36
config.py
Normal file
36
config.py
Normal file
|
@ -0,0 +1,36 @@
|
|||
import smtplib, ssl, options
|
||||
import keyring as kr
|
||||
from selenium.webdriver import Firefox
|
||||
from selenium.webdriver.firefox.service import Service
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.firefox.options import Options
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
|
||||
# email config
|
||||
# edit the following with your imap server configuration for your email account
|
||||
PORT = 465 # For SSL
|
||||
CONTEXT = ssl.create_default_context()
|
||||
IMAP_SERVER = ""
|
||||
SENDER_EMAIL = ""
|
||||
MAILING_LIST = ["johndoe@gmail.com","johnsmith@gmail.com"] # replace with mail addresses you want to notify
|
||||
|
||||
# credentials
|
||||
# add email and immi credentials in your keyring and edit this accordingly
|
||||
# https://pypi.org/project/keyring/
|
||||
CRED_MAIL = kr.get_credential("service", "username")
|
||||
CRED_IMMI = kr.get_credential("","")
|
||||
|
||||
# webdriver config
|
||||
options=Options()
|
||||
options.add_argument('-headless')
|
||||
options.binary_location = r'' # fill with firefox binary path
|
||||
profile_path = r"" # fill with firefox profile path
|
||||
SERVICE = Service(r"") # download and fill with geckodriver location
|
||||
URL = 'https://online.immi.gov.au/lusc/login'
|
||||
options.set_preference('profile', profile_path)
|
||||
|
||||
# general
|
||||
ini_status = "Received" # replace with your current application status
|
||||
ini_msg = 2 # replace with the current number of messages in your portal
|
||||
ERROR_PNG_FILENAME = "error.png"
|
BIN
granted.wav
Normal file
BIN
granted.wav
Normal file
Binary file not shown.
52
msg.py
Normal file
52
msg.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
# emails
|
||||
|
||||
message_status = """\
|
||||
From: baasil@riseup.net
|
||||
To: {}
|
||||
Subject: Your Australian student visa application status has changed to \"{}\"\n\n
|
||||
|
||||
https://online.immi.gov.au/lusc/login
|
||||
This is an automated message sent from a python script made by Baasil."""
|
||||
|
||||
message_new = """\
|
||||
From: baasil@riseup.net
|
||||
To: {}
|
||||
Subject: You have new message(s) in your australian visa application portal\n\n
|
||||
|
||||
{}\n
|
||||
https://online.immi.gov.au/lusc/login
|
||||
check portal to see full message, I won't do everything for you\n
|
||||
This is an automated message sent from a python script made by Baasil."""
|
||||
|
||||
message_final = """\
|
||||
From: baasil@riseup.net
|
||||
To:{}
|
||||
Subject: Your Australian visa has been {}\n\n
|
||||
|
||||
https://online.immi.gov.au/lusc/login
|
||||
check portal for details\nthis message may have been sent in error\n
|
||||
this is an automated message sent from a python script made by Baasil."""
|
||||
|
||||
error_message = """\
|
||||
From: baasil@riseup.net
|
||||
To: {}
|
||||
Subject: visa_stat.py exited due to too many consecutive errors\n\n
|
||||
|
||||
https://online.immi.gov.au/lusc/login - check what's up here
|
||||
this is an automated message"""
|
||||
|
||||
net_error_msg = """\
|
||||
From: baasil@riseup.net
|
||||
To: {}
|
||||
Subject: visa_stat.py too many consecutive net errors\n\n
|
||||
|
||||
https://online.immi.gov.au/lusc/login - check what's up here
|
||||
this is an automated message"""
|
||||
|
||||
error_in_messages = """\
|
||||
From: baasil@riseup.net
|
||||
To:{}
|
||||
Subject: too many consecutive errors in fetching messages, from visa_stat.py\n\n
|
||||
|
||||
https://online.immi.gov.au/lusc/login - check what's up here
|
||||
this is an automated message"""
|
170
oldver.py
Normal file
170
oldver.py
Normal file
|
@ -0,0 +1,170 @@
|
|||
"""script to track my visa application status"""
|
||||
from time import sleep
|
||||
from random import randrange
|
||||
from datetime import datetime
|
||||
from os import _exit
|
||||
import smtplib, ssl, threading, options
|
||||
from selenium.webdriver import Firefox
|
||||
from selenium.webdriver.firefox.service import Service
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.firefox.options import Options
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
import keyring as kr
|
||||
import simpleaudio as sa
|
||||
from plyer import notification as toast
|
||||
from msg import *
|
||||
|
||||
# email config
|
||||
port = 465 # For SSL
|
||||
context = ssl.create_default_context()
|
||||
imap_server = "mail.riseup.net"
|
||||
sender_email = "baasil@riseup.net"
|
||||
receivers = ["baasil@riseup.net","baasilsiddiqui@gmail.com","siddiqui_m_j@yahoo.com"]
|
||||
|
||||
# credentials
|
||||
cred_mail = kr.get_credential("riseup","sedentaryowl")
|
||||
cred_immi = kr.get_credential("immi","sbaasil51@gmail.com")
|
||||
|
||||
# webdriver config
|
||||
options=Options()
|
||||
options.add_argument('-headless')
|
||||
options.binary_location = r'/usr/sbin/firefox'
|
||||
profile_path = r"/home/baasil/.mozilla/firefox/z93eslik.default-release"
|
||||
service = Service(r"/home/baasil/dls/geckodriver")
|
||||
url = 'https://online.immi.gov.au/lusc/login'
|
||||
options.set_preference('profile', profile_path)
|
||||
|
||||
errors=0 # variable to track number of consecutive errors
|
||||
|
||||
def notifier(receiver_email, msg):
|
||||
"""sends mail to receiver_email with msg message"""
|
||||
global imap_server, port, context, sender_email, cred_mail
|
||||
with smtplib.SMTP_SSL(imap_server, port, context=context) as server:
|
||||
server.login(cred_mail.username, cred_mail.password)
|
||||
server.sendmail(sender_email, receiver_email, msg)
|
||||
|
||||
def music(file):
|
||||
sa.WaveObject.from_wave_file(file).play()
|
||||
|
||||
# main event loop
|
||||
while True:
|
||||
driver = Firefox(service=service, options=options)
|
||||
driver.get(url)
|
||||
print("------------------------------------------------------------------")
|
||||
try:
|
||||
driver.find_element(by=By.NAME, value="username").send_keys(cred_immi.username)
|
||||
driver.find_element(by=By.NAME, value="password").send_keys(cred_immi.password)
|
||||
driver.find_element(by=By.XPATH, value="/html/body/form/div/div[2]/button[2]").click() # login
|
||||
sleep(2)
|
||||
driver.find_element(by=By.NAME, value="continue").click()
|
||||
details_element = WebDriverWait(driver, 25).until(EC.element_to_be_clickable((By.XPATH, '//*[@id="defaultActionPanel_0_7"]'))) # view details
|
||||
sleep(5)
|
||||
try:
|
||||
details_element.click()
|
||||
except:
|
||||
pass
|
||||
status_line_element = WebDriverWait(driver, 25).until(EC.visibility_of_element_located((By.XPATH, '//*[@id="_0a1a0c1a0a0b1a0a1a0a"]/div/div/strong')))
|
||||
status_line = status_line_element.text
|
||||
trashy, status = status_line.split(": ")
|
||||
print(datetime.now().strftime("%H:%M"), end=": ")
|
||||
print(f"Application status: {status}")
|
||||
try:
|
||||
driver.find_element(by=By.ID, value="_0a1a0c1a0a0b0a1a0b0-body").click() # messages tab
|
||||
sleep(5)
|
||||
messages = driver.find_elements(by=By.XPATH, value="//table/tbody/tr") # list of messages
|
||||
latest = ''
|
||||
for i in messages:
|
||||
if '06 feb' not in i.text.lower() and '25 jan' not in i.text.lower():
|
||||
latest_element = i; latest = i.text; break
|
||||
if 'acknowledge' not in i.text.lower():
|
||||
latest_element = i; latest = i.text
|
||||
errors=0
|
||||
except:
|
||||
driver.save_screenshot('/home/baasil/learnpy/visa_stat/error.png')
|
||||
errors+=1
|
||||
latest=''
|
||||
messages=[]
|
||||
driver.close()
|
||||
|
||||
# checking status
|
||||
if status=="Received":
|
||||
pass
|
||||
elif status=="Finalised":
|
||||
print("status change detected")
|
||||
print(latest)
|
||||
print("sending mails...")
|
||||
if 'grant' in latest.lower() or 'accept' in latest.lower():
|
||||
play = threading.Thread(target=music, args=('granted.wav',)); play.start()
|
||||
toast.notify(title="your Australian visa has been granted", message='congratulations')
|
||||
for r_mail in receivers:
|
||||
notifier(r_mail, message_final.format(r_mail, 'granted'))
|
||||
print("mails sent")
|
||||
_exit(1)
|
||||
elif 'reject' in latest.lower():
|
||||
play = threading.Thread(target=music, args=('rejected.wav',)); play.start()
|
||||
toast.notify(title="your Australian visa has been rejected")
|
||||
for r_mail in receivers:
|
||||
notifier(r_mail, message_final.format(r_mail, 'rejected'))
|
||||
print("mails sent")
|
||||
_exit(1)
|
||||
else:
|
||||
toast.notify(title=f"your Australian visa application status has changed to \"{status}\"")
|
||||
for r_mail in receivers:
|
||||
notifier(r_mail, message_status.format(r_mail, status))
|
||||
print("mails sent")
|
||||
if len(messages)==2:
|
||||
_exit(1)
|
||||
else:
|
||||
print("status change detected")
|
||||
print("sending mails...")
|
||||
toast.notify(title=f"your Australian visa application status has changed to \"{status}\"")
|
||||
for r_mail in receivers:
|
||||
notifier(r_mail, message_status.format(r_mail, status))
|
||||
print("mails sent")
|
||||
if len(messages)==2:
|
||||
_exit(1)
|
||||
|
||||
# checking messages
|
||||
if len(messages)==2 and '2023' in latest:
|
||||
print("no new messages")
|
||||
elif len(messages)>2:
|
||||
print("found new message")
|
||||
print(latest)
|
||||
print("sending mails...")
|
||||
toast.notify(title="you have a new message in your Australian visa application portal", message=latest)
|
||||
for r_mail in receivers:
|
||||
notifier(r_mail, message_new.format(r_mail,latest))
|
||||
print("mails sent")
|
||||
_exit(1)
|
||||
else:
|
||||
print("can't find messages")
|
||||
sleep(5*60)
|
||||
continue
|
||||
|
||||
n = randrange(15,30)
|
||||
sleep(n*60)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
try:
|
||||
driver.close()
|
||||
except:
|
||||
pass
|
||||
_exit(1)
|
||||
|
||||
except:
|
||||
try:
|
||||
driver.save_screenshot('/home/baasil/learnpy/visa_stat/error.png')
|
||||
driver.close()
|
||||
except KeyboardInterrupt:
|
||||
_exit(1)
|
||||
except:
|
||||
pass
|
||||
print("ERROR"); errors+=1
|
||||
if errors>=5:
|
||||
notifier(receivers[0], error_message.format(receivers[0]))
|
||||
toast.notify(title="visa_stat.py",message="too many consecutive errors, exiting...")
|
||||
print("too many consecutive errors, exiting...")
|
||||
_exit(1)
|
||||
else:
|
||||
sleep(15*60)
|
BIN
rejected.wav
Normal file
BIN
rejected.wav
Normal file
Binary file not shown.
32
requirements.txt
Normal file
32
requirements.txt
Normal file
|
@ -0,0 +1,32 @@
|
|||
async-generator==1.10
|
||||
attrs==22.2.0
|
||||
certifi==2022.12.7
|
||||
cffi==1.15.1
|
||||
chainmap==1.0.3
|
||||
combomethod==1.0.12
|
||||
cryptography==40.0.1
|
||||
exceptiongroup==1.1.1
|
||||
h11==0.14.0
|
||||
idna==3.4
|
||||
importlib-metadata==6.1.0
|
||||
jaraco.classes==3.2.3
|
||||
jeepney==0.8.0
|
||||
keyring==23.13.1
|
||||
more-itertools==9.1.0
|
||||
nulltype==2.3.1
|
||||
options==1.4.10
|
||||
outcome==1.2.0
|
||||
plyer==2.1.0
|
||||
pycparser==2.21
|
||||
PySocks==1.7.1
|
||||
SecretStorage==3.3.3
|
||||
selenium==4.8.3
|
||||
simpleaudio==1.0.4
|
||||
six==1.12.0
|
||||
sniffio==1.3.0
|
||||
sortedcontainers==2.4.0
|
||||
trio==0.22.0
|
||||
trio-websocket==0.10.2
|
||||
urllib3==1.26.15
|
||||
wsproto==1.2.0
|
||||
zipp==3.15.0
|
23
utils.py
Normal file
23
utils.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
import simpleaudio as sa
|
||||
from datetime import datetime
|
||||
from config import *
|
||||
|
||||
def notifier(receivers_list, msg, *format_args):
|
||||
"""sends mail to receivers_list with msg message formated with rmail and *format_args"""
|
||||
for rmail in receivers_list:
|
||||
with smtplib.SMTP_SSL(IMAP_SERVER, PORT, context=CONTEXT) as server:
|
||||
server.login(CRED_MAIL.username, CRED_MAIL.password)
|
||||
server.sendmail(SENDER_EMAIL, rmail, msg.format(rmail, *format_args))
|
||||
|
||||
def music(file):
|
||||
"""plays music from wav file"""
|
||||
sa.WaveObject.from_wave_file(file).play()
|
||||
|
||||
def parse_date(full_message):
|
||||
"""parses date from message title"""
|
||||
|
||||
full_message_lines = full_message.split("\n")
|
||||
date_line = full_message_lines[-1]
|
||||
date_list = date_line.split(" ")
|
||||
date_string = date_list[0]+' '+date_list[1]+' '+date_list[2]
|
||||
return datetime.strptime(date_string, '%d %b %Y')
|
175
visa_stat.py
Normal file
175
visa_stat.py
Normal file
|
@ -0,0 +1,175 @@
|
|||
"""script to track my visa application status"""
|
||||
|
||||
from time import sleep
|
||||
from random import randrange
|
||||
from os import _exit
|
||||
import threading
|
||||
from plyer import notification as toast
|
||||
from msg import *
|
||||
from utils import *
|
||||
|
||||
con_errors = 0 # variable to track number of consecutive errors
|
||||
msg_errors = 0 # variable to track number of consecutive errors in fetching messages
|
||||
net_errors = 0 # variable to track number of consecutive connection errors
|
||||
|
||||
# main event loop
|
||||
while True:
|
||||
print("------------------------------------------------------------------")
|
||||
try:
|
||||
try:
|
||||
driver = Firefox(service=SERVICE, options=options)
|
||||
driver.get(URL)
|
||||
net_errors=0
|
||||
except:
|
||||
net_errors+=1
|
||||
print("net error")
|
||||
if net_errors>=5:
|
||||
notifier(MAILING_LIST[0:1], net_error_msg)
|
||||
toast.notify(title="visa_stat.py",message="too many consecutive net errors")
|
||||
net_errors = 0
|
||||
sleep(15*60)
|
||||
continue
|
||||
driver.find_element(by=By.NAME, value="username").send_keys(CRED_IMMI.username)
|
||||
driver.find_element(by=By.NAME, value="password").send_keys(CRED_IMMI.password)
|
||||
driver.find_element(by=By.XPATH, \
|
||||
value="/html/body/form/div/div[2]/button[2]").click() # login
|
||||
sleep(2)
|
||||
driver.find_element(by=By.NAME, value="continue").click()
|
||||
details_element = WebDriverWait(driver, 25).until(EC.element_to_be_clickable\
|
||||
((By.XPATH, '//*[@id="defaultActionPanel_0_7"]')))
|
||||
sleep(5)
|
||||
try:
|
||||
details_element.click()
|
||||
except:
|
||||
pass
|
||||
status_line_element = WebDriverWait(driver, 25).until(EC.visibility_of_element_located\
|
||||
((By.XPATH, '//*[@id="_0a1a0c1a0a0b1a0a1a0a"]/div/div/strong')))
|
||||
status_line = status_line_element.text
|
||||
trashy, status = status_line.split(": ")
|
||||
print(datetime.now().strftime("%H:%M"), end=": ")
|
||||
print(f"Application status: {status}")
|
||||
|
||||
try:
|
||||
msg_tab = driver.find_element(by=By.ID, value="_0a1a0c1a0a0b0a1a0b0-body")
|
||||
while_timeout = False # variable to deteremine if while loop timed out
|
||||
timeout_while = 0
|
||||
|
||||
while not driver.find_elements(by=By.XPATH, value='//*[@id="_0a1a0c1a0a0b1a0c0a0b"]/div/div[1]'):
|
||||
trashy = msg_tab.text
|
||||
timeout_while+=1
|
||||
if timeout_while>=7:
|
||||
msg_err = True
|
||||
while_timeout = True
|
||||
break
|
||||
msg_tab.click()
|
||||
sleep(10)
|
||||
|
||||
if not while_timeout:
|
||||
messages = driver.find_elements(by=By.XPATH, \
|
||||
value="//table/tbody/tr") # list of messages
|
||||
messages_string_list = []
|
||||
for i in messages:
|
||||
messages_string_list.append(i.text)
|
||||
ordered_message_list = sorted(messages_string_list, key=parse_date)
|
||||
new_message_list = ordered_message_list[ini_msg:]
|
||||
new_messages_string = "\n\n".join(new_message_list)
|
||||
msg_errors = 0
|
||||
msg_err = False
|
||||
|
||||
except:
|
||||
msg_err = True
|
||||
|
||||
finally:
|
||||
if msg_err:
|
||||
driver.save_screenshot(ERROR_PNG_FILENAME)
|
||||
msg_errors+=1
|
||||
new_messages_string = ""
|
||||
messages=[]
|
||||
|
||||
if msg_errors>=5:
|
||||
notifier(MAILING_LIST[0:1], error_in_messages)
|
||||
msg_errors = 0
|
||||
|
||||
driver.close()
|
||||
|
||||
# checking status
|
||||
if status==ini_status:
|
||||
pass
|
||||
elif status=="Finalised":
|
||||
print("status change detected")
|
||||
print(new_messages_string)
|
||||
print("sending mails...", end="")
|
||||
if 'grant' in new_messages_string.lower():
|
||||
play = threading.Thread(target=music, args=('granted.wav',))
|
||||
play.start()
|
||||
toast.notify(title="your Australian visa has been granted", \
|
||||
message='congratulations')
|
||||
notifier(MAILING_LIST, message_final, 'granted')
|
||||
print("mails sent")
|
||||
_exit(0)
|
||||
elif 'reject' in new_messages_string.lower():
|
||||
play = threading.Thread(target=music, args=('rejected.wav',))
|
||||
play.start()
|
||||
toast.notify(title="your Australian visa has been rejected")
|
||||
notifier(MAILING_LIST, message_final, 'rejected')
|
||||
print("mails sent")
|
||||
_exit(0)
|
||||
else:
|
||||
toast.notify(title=f"your Australian visa application status has changed to \"{status}\"")
|
||||
notifier(MAILING_LIST, message_status, status)
|
||||
print("mails sent")
|
||||
ini_status = status
|
||||
else:
|
||||
print("status change detected")
|
||||
print("sending mails...", end="")
|
||||
toast.notify(title=f"your Australian visa application status has changed to \"{status}\"")
|
||||
notifier(MAILING_LIST, message_status, status)
|
||||
print("mails sent")
|
||||
ini_status = status
|
||||
|
||||
# checking messages
|
||||
if len(messages)==ini_msg:
|
||||
print("no new messages")
|
||||
elif len(messages)>ini_msg:
|
||||
print("found new message(s)")
|
||||
print(new_messages_string)
|
||||
print("sending mails...", end="")
|
||||
toast.notify(title="you have new message(s) in your Australian visa application portal", \
|
||||
message=new_messages_string)
|
||||
notifier(MAILING_LIST, message_new, new_messages_string)
|
||||
print("mails sent")
|
||||
ini_msg = len(messages)
|
||||
if status=="Finalised":
|
||||
_exit(0)
|
||||
else:
|
||||
print("can't find messages")
|
||||
sleep(5*60)
|
||||
continue
|
||||
|
||||
n = randrange(15,30)
|
||||
sleep(n*60)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
try:
|
||||
driver.close()
|
||||
except:
|
||||
pass
|
||||
_exit(1)
|
||||
|
||||
except:
|
||||
try:
|
||||
driver.save_screenshot(ERROR_PNG_FILENAME)
|
||||
driver.close()
|
||||
except KeyboardInterrupt:
|
||||
_exit(1)
|
||||
except:
|
||||
pass
|
||||
print("ERROR")
|
||||
con_errors+=1
|
||||
if con_errors>=5:
|
||||
notifier(MAILING_LIST[0:1], error_message)
|
||||
toast.notify(title="visa_stat.py",message="too many consecutive errors, exiting...")
|
||||
print("too many consecutive errors, exiting...")
|
||||
_exit(1)
|
||||
else:
|
||||
sleep(15*60)
|
Loading…
Reference in a new issue