udemyBot / gui.py
imseldrith's picture
Upload folder using huggingface_hub (#1)
a004773 verified
import sys
import threading
import time
import traceback
from webbrowser import open as web
import FreeSimpleGUI as sg
from base import LINKS, VERSION, LoginException, Scraper, Udemy, scraper_dict
from images import (
auto_login,
back,
check_mark,
exit_,
icon,
login,
logout,
manual_login_,
start,
)
sg.set_global_icon(icon)
sg.change_look_and_feel("dark")
sg.theme_background_color
sg.set_options(
button_color=(sg.theme_background_color(), sg.theme_background_color()),
border_width=0,
font=10,
)
def update_enrolled_courses():
while True:
new_menu = [
["Help", ["Support", "Github", "Discord"]],
[f"Total Courses: {len(udemy.enrolled_courses)}"],
]
main_window.write_event_value("Update-Menu", new_menu)
time.sleep(10)
def create_scraping_thread(site: str):
code_name = scraper_dict[site]
main_window[f"i{site}"].update(visible=False)
main_window[f"p{site}"].update(0, visible=True)
try:
threading.Thread(target=getattr(scraper, code_name), daemon=True).start()
while getattr(scraper, f"{code_name}_length") == 0:
time.sleep(0.1) # Avoid busy waiting
if getattr(scraper, f"{code_name}_length") == -1:
raise Exception(f"Error in: {site}")
main_window[f"p{site}"].update(0, max=getattr(scraper, f"{code_name}_length"))
while not getattr(scraper, f"{code_name}_done") and not getattr(
scraper, f"{code_name}_error"
):
main_window[f"p{site}"].update(
getattr(scraper, f"{code_name}_progress") + 1
)
time.sleep(0.1) # Update every 0.1 seconds
if getattr(scraper, f"{code_name}_error"):
raise Exception(f"Error in: {site}")
except Exception:
error_message = getattr(scraper, f"{code_name}_error", "Unknown Error")
main_window.write_event_value(
"Error", f"{error_message}|:|Unknown Error in: {site} {VERSION}"
)
finally:
main_window[f"p{site}"].update(0, visible=False)
main_window[f"i{site}"].update(visible=True)
##########################################
def scrape():
try:
for site in udemy.sites:
main_window[f"pcol{site}"].update(visible=True)
main_window["main_col"].update(visible=False)
main_window["scrape_col"].update(visible=True)
udemy.scraped_data = scraper.get_scraped_courses(create_scraping_thread)
main_window["scrape_col"].update(visible=False)
main_window["output_col"].update(visible=True)
# ------------------------------------------
udemy.start_enrolling()
main_window["output_col"].Update(visible=False)
main_window["done_col"].update(visible=True)
main_window["se_c"].update(
value=f"Successfully Enrolled: {udemy.successfully_enrolled_c}"
)
main_window["as_c"].update(
value=f"Amount Saved: {round(udemy.amount_saved_c,2)} {udemy.currency.upper()}"
)
main_window["ae_c"].update(
value=f"Already Enrolled: {udemy.already_enrolled_c}"
)
main_window["e_c"].update(value=f"Expired Courses: {udemy.expired_c}")
main_window["ex_c"].update(value=f"Excluded Courses: {udemy.excluded_c}")
except Exception:
e = traceback.format_exc()
main_window.write_event_value(
"Error",
f"{e}\n\nVersion:{VERSION}\nLink:{getattr(udemy, 'link', 'None')}\nTitle:{getattr(udemy, 'title','None')}|:|Error g100",
)
#################################
udemy = Udemy("gui")
udemy.load_settings()
login_title, main_title = udemy.check_for_update()
menu = [["Help", ["Support", "Github", "Discord"]]]
login_error = False
try:
if udemy.settings["stay_logged_in"]["auto"]:
udemy.fetch_cookies()
elif udemy.settings["stay_logged_in"]["manual"]:
udemy.manual_login(udemy.settings["email"], udemy.settings["password"])
else:
raise LoginException("No Saved Login Found")
udemy.get_session_info()
except LoginException:
login_error = True
# if (
# not udemy.settings["stay_logged_in"]["auto"]
# and not udemy.settings["stay_logged_in"]["manual"]
# ) or login_error:
if login_error:
c1 = [
[
sg.Button(key="a_login", image_data=auto_login),
sg.T(""),
sg.B(key="m_login", image_data=manual_login_),
],
[
sg.Checkbox(
"Stay logged-in",
default=udemy.settings["stay_logged_in"]["auto"],
key="sli_a",
)
],
]
c2 = [
[
sg.T("Email"),
sg.InputText(
default_text=udemy.settings["email"],
key="email",
size=(20, 1),
pad=(5, 5),
),
],
[
sg.T("Password"),
sg.InputText(
default_text=udemy.settings["password"],
key="password",
size=(20, 1),
pad=(5, 5),
password_char="*",
),
],
[
sg.Checkbox(
"Stay logged-in",
default=udemy.settings["stay_logged_in"]["manual"],
key="sli_m",
)
],
[
sg.B(key="Back", image_data=back),
sg.T(" "),
sg.B(key="Login", image_data=login),
],
]
login_layout = [
[sg.Menu(menu)],
[sg.Column(c1, key="col1"), sg.Column(c2, visible=False, key="col2")],
]
login_window = sg.Window(login_title, login_layout, finalize=True)
login_window.bind("a", "a_login")
login_window.bind("m", "m_login")
while True:
event, values = login_window.read()
if event in (None,):
login_window.close()
sys.exit()
elif event == "a_login" and not login_window["a_login"].Disabled:
login_window["a_login"].update(disabled=True)
login_window.refresh()
try:
udemy.fetch_cookies()
try:
udemy.get_session_info()
udemy.settings["stay_logged_in"]["auto"] = values["sli_a"]
udemy.save_settings()
login_window.close()
break
except Exception:
e = traceback.format_exc()
print(e)
sg.popup_auto_close(
"Make sure you are logged in to udemy.com in chrome browser",
title="Error",
auto_close_duration=3,
no_titlebar=True,
)
except Exception:
e = traceback.format_exc()
sg.popup_scrolled(e, title=f"Unknown Error {VERSION}")
login_window["a_login"].update(disabled=False)
elif event == "m_login":
login_window["col1"].update(visible=False)
login_window["col2"].update(visible=True)
login_window["email"].update(value=udemy.settings["email"])
login_window["password"].update(value=udemy.settings["password"])
elif event == "Github":
web(LINKS["github"])
elif event == "Support":
web(LINKS["support"])
elif event == "Discord":
web(LINKS["discord"])
elif event == "Back":
login_window["col1"].update(visible=True)
login_window["col2"].update(visible=False)
elif event == "Login":
udemy.settings["email"] = values["email"]
udemy.settings["password"] = values["password"]
try:
try:
udemy.manual_login(
udemy.settings["email"], udemy.settings["password"]
)
udemy.get_session_info()
udemy.settings["stay_logged_in"]["manual"] = values["sli_m"]
udemy.save_settings()
login_window.close()
break
except LoginException as e:
sg.popup_auto_close(
e,
title="Error",
auto_close_duration=3,
no_titlebar=True,
)
except Exception:
e = traceback.format_exc()
sg.popup_scrolled(e, title=f"Unknown Error {VERSION}")
checkbox_lo = []
for key in udemy.settings["sites"]:
checkbox_lo.append(
[sg.Checkbox(key, key=key, default=udemy.settings["sites"][key], size=(18, 1))]
)
categories_lo = []
categories_k = list(udemy.settings["categories"].keys())
categories_v = list(udemy.settings["categories"].values())
for index, _ in enumerate(udemy.settings["categories"]):
if index % 3 == 0:
try:
categories_lo.append(
[
sg.Checkbox(
categories_k[index],
default=categories_v[index],
key=categories_k[index],
size=(18, 1),
),
sg.Checkbox(
categories_k[index + 1],
default=categories_v[index + 1],
key=categories_k[index + 1],
size=(18, 1),
),
sg.Checkbox(
categories_k[index + 2],
default=categories_v[index + 2],
key=categories_k[index + 2],
size=(18, 1),
),
]
)
except IndexError:
categories_lo.append(
[
sg.Checkbox(
categories_k[index],
default=categories_v[index],
key=categories_k[index],
size=(18, 1),
)
]
)
languages_lo = []
languages_k = list(udemy.settings["languages"].keys())
languages_v = list(udemy.settings["languages"].values())
for index, _ in enumerate(udemy.settings["languages"]):
if index % 3 == 0:
try:
languages_lo.append(
[
sg.Checkbox(
languages_k[index],
default=languages_v[index],
key=languages_k[index],
size=(10, 1),
),
sg.Checkbox(
languages_k[index + 1],
default=languages_v[index + 1],
key=languages_k[index + 1],
size=(10, 1),
),
sg.Checkbox(
languages_k[index + 2],
default=languages_v[index + 2],
key=languages_k[index + 2],
size=(10, 1),
),
]
)
except IndexError:
languages_lo.append(
[
sg.Checkbox(
languages_k[index],
default=languages_v[index],
key=languages_k[index],
size=(10, 1),
),
sg.Checkbox(
languages_k[index + 1],
default=languages_v[index + 1],
key=languages_k[index + 1],
size=(10, 1),
),
]
)
main_tab = [
[
sg.Frame(
"Websites",
checkbox_lo,
"#4deeea",
border_width=4,
title_location="n",
key="fcb",
),
sg.Frame(
"Language",
languages_lo,
"#4deeea",
border_width=4,
title_location="n",
key="fl",
),
],
[
sg.Frame(
"Category",
categories_lo,
"#4deeea",
border_width=4,
title_location="n",
key="fc",
)
],
]
instructor_ex_lo = [
[
sg.Multiline(
default_text=udemy.instructor_exclude,
key="instructor_exclude",
size=(15, 10),
)
],
[sg.Text("Paste instructor(s)\nusername in new lines")],
]
title_ex_lo = [
[
sg.Multiline(
default_text=udemy.title_exclude, key="title_exclude", size=(20, 10)
)
],
[sg.Text("Keywords in new lines\nNot cAsE sensitive")],
]
rating_lo = [
[
sg.Spin(
[i * 0.5 for i in range(11)],
initial_value=udemy.settings["min_rating"],
key="min_rating",
),
sg.Text("0.0 <-> 5.0"),
]
]
courses_last_updated_lo = [
[
sg.Text("Past"),
sg.Spin(
[i for i in range(1, 48)],
initial_value=udemy.settings["course_update_threshold_months"],
key="course_update_threshold_months",
),
sg.Text("Month(s)"),
]
]
advanced_tab = [
[
sg.Frame(
"Exclude Instructor",
instructor_ex_lo,
"#4deeea",
border_width=4,
title_location="n",
),
sg.Frame(
"Title Keyword Exclusion",
title_ex_lo,
"#4deeea",
border_width=4,
title_location="n",
),
],
[
sg.Frame(
"Minimum Rating",
rating_lo,
"#4deeea",
border_width=4,
title_location="n",
key="f_min_rating",
font=25,
),
sg.Frame(
"Course Last Updated",
courses_last_updated_lo,
"#4deeea",
border_width=4,
title_location="n",
key="f_course_last_updated",
font=25,
),
],
[
sg.Checkbox(
"Save enrolled courses in txt",
key="save_txt",
default=udemy.settings["save_txt"],
)
],
[
sg.Checkbox(
"Enrol in Discounted courses only",
key="discounted_only",
default=udemy.settings["discounted_only"],
)
],
]
scrape_col = []
for key in udemy.settings["sites"]:
scrape_col.append(
[
sg.pin(
sg.Column(
[
[
sg.Text(key, size=(12, 1)),
sg.ProgressBar(
3,
orientation="h",
key=f"p{key}",
bar_color=("#1c6fba", "#000000"),
border_width=1,
size=(20, 20),
),
sg.Image(data=check_mark, visible=False, key=f"i{key}"),
]
],
key=f"pcol{key}",
visible=False,
)
)
]
)
output_col = [
[sg.Text("Output")],
[sg.Multiline(size=(69, 12), key="out", autoscroll=False, disabled=True)],
# [
# sg.ProgressBar(
# 3,
# orientation="h",
# key="pout",
# bar_color=("#1c6fba", "#000000"),
# border_width=1,
# size=(46, 20),
# )
# ],
]
done_col = [
[sg.Text(" Stats", text_color="#FFD700")],
[
sg.Text(
"Successfully Enrolled: ",
key="se_c",
text_color="#7CFC00",
)
],
[
sg.Text(
"Amount Saved: $ ",
key="as_c",
text_color="#00FA9A",
)
],
[sg.Text("Already Enrolled: ", key="ae_c", text_color="#00FFFF")],
[sg.Text("Expired Courses: ", key="e_c", text_color="#FF0000")],
[sg.Text("Excluded Courses: ", key="ex_c", text_color="#FF4500")],
]
main_col = [
[
sg.TabGroup(
[[sg.Tab("Main", main_tab), sg.Tab("Advanced", advanced_tab)]],
border_width=2,
)
],
[
sg.Button(
key="Start",
tooltip="Once started will not stop until completed",
image_data=start,
)
],
]
if (
udemy.settings["stay_logged_in"]["auto"]
or udemy.settings["stay_logged_in"]["manual"]
):
logout_btn_lo = sg.Button(key="Logout", image_data=logout)
else:
logout_btn_lo = sg.Button(key="Logout", image_data=logout, visible=False)
main_lo = [
[
sg.Menu(
menu,
key="mn",
)
],
[sg.Text(f"Logged in as: {udemy.display_name}", key="user_t"), logout_btn_lo],
[
sg.pin(sg.Column(main_col, key="main_col")),
sg.pin(sg.Column(output_col, key="output_col", visible=False)),
sg.pin(sg.Column(scrape_col, key="scrape_col", visible=False)),
sg.pin(sg.Column(done_col, key="done_col", visible=False)),
],
[sg.Button(key="Exit", image_data=exit_)],
]
# ,sg.Button(key='Dummy',image_data=back)
global main_window
# position windows in center
main_window = sg.Window(
main_title,
main_lo,
finalize=True,
)
threading.Thread(target=update_enrolled_courses, daemon=True).start()
while True:
event, values = main_window.read()
if event == "Dummy":
print(values)
if event in (None, "Exit"):
break
elif event == "Logout":
(
udemy.settings["stay_logged_in"]["auto"],
udemy.settings["stay_logged_in"]["manual"],
) = (
False,
False,
)
udemy.save_settings()
break
elif event == "Support":
web(LINKS["support"])
elif event == "Github":
web(LINKS["github"])
elif event == "Discord":
web(LINKS["discord"])
elif event == "Start" and main_window["main_col"].visible:
# for key in udemy.settings["languages"]:
# udemy.settings["languages"][key] = values[key]
# for key in udemy.settings["categories"]:
# udemy.settings["categories"][key] = values[key]
# for key in udemy.settings["sites"]:
# udemy.settings["sites"][key] = values[key]
for setting in ["languages", "categories", "sites"]:
for key in udemy.settings[setting]:
udemy.settings[setting][key] = values[key]
udemy.settings["instructor_exclude"] = str(values["instructor_exclude"]).split()
udemy.settings["title_exclude"] = list(
filter(None, values["title_exclude"].split("\n"))
)
udemy.settings["min_rating"] = float(values["min_rating"])
udemy.settings["course_update_threshold_months"] = int(
values["course_update_threshold_months"]
)
udemy.settings["save_txt"] = values["save_txt"]
udemy.settings["discounted_only"] = values["discounted_only"]
udemy.save_settings()
user_dumb = udemy.is_user_dumb()
if user_dumb:
sg.popup_auto_close(
"What do you even expect to happen!",
auto_close_duration=5,
no_titlebar=True,
)
continue
scraper = Scraper(udemy.sites)
udemy.window = main_window
threading.Thread(target=scrape, daemon=True).start()
elif event == "Error":
msg = values["Error"].split("|:|")
e = msg[0]
title = msg[1]
sg.popup_scrolled(e, title=title)
elif event == "Update-Menu":
menu = values["Update-Menu"]
main_window["mn"].update(menu)
main_window.close()