Skip to content

Commit

Permalink
chore: Update changelog for v2.3, refactor Udemy class, and modify se…
Browse files Browse the repository at this point in the history
…ttings handling
  • Loading branch information
techtanic committed Nov 2, 2024
1 parent 28c7a15 commit 4cb9800
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 36 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
# Changelog

## v2.3

- Removed getting settings from github is file not found. Default settings will be included in exe.
- Fixed `TutorialBar`
- Fixed Error for Courses that are no longer accepting new enrollments
- Refactored some code

## v2.2

- Fixed `CourseVania`
- Refactored code
- Added Course last Updated filter


## v2.1

- Fixed Scrappers
Expand Down
85 changes: 52 additions & 33 deletions base.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from colors import fb, fc, fg, flb, flg, fm, fr, fy

VERSION = "v2.2"
VERSION = "v2.3"

scraper_dict: dict = {
"Udemy Freebies": "uf",
Expand Down Expand Up @@ -203,7 +203,7 @@ def tb(self):
)
soup = self.parse_html(content)
page_items = soup.find_all(
"h3", class_="mb15 mt0 font110 mobfont100 fontnormal lineheight20"
"h2", class_="mb15 mt0 font110 mobfont100 fontnormal lineheight20"
)
all_items.extend(page_items)
self.tb_length = len(all_items)
Expand Down Expand Up @@ -437,11 +437,8 @@ def load_settings(self):
with open(f"duce-{self.interface}-settings.json") as f:
self.settings = json.load(f)
except FileNotFoundError:
self.settings = dict(
requests.get(
f"https://raw.githubusercontent.com/techtanic/Discounted-Udemy-Course-Enroller/master/duce-{self.interface}-settings.json"
).json()
)
with open(f"default-duce-{self.interface}-settings.json") as f:
self.settings = json.load(f)
if (
self.interface == "cli" and "use_browser_cookies" not in self.settings
): # v2.1
Expand Down Expand Up @@ -737,32 +734,51 @@ def normalize_link(self, link):
)

def get_course_id(self, url):
course = {
"course_id": None,
"url": url,
"is_invalid": False,
"is_free": None,
"is_excluded": None,
"retry": None,
"msg": "Report to developer",
}
url = re.sub(r"\W+$", "", unquote(url))
try:
r = self.client.get(url)
except requests.exceptions.ConnectionError:
if self.debug:
print(r.text)
return "retry", url, False

course["retry"] = True
return course
course["url"] = r.url
soup = bs(r.content, "html5lib")
if self.debug:
with open("test/soup.html", "w", encoding="utf-8") as f:
f.write(str(soup))

course_id = soup.find("body").get("data-clp-course-id", "invalid")
if course_id == "invalid":
return "invalid", url, False

if course_id == "invalid":
course["is_invalid"] = True
course["msg"] = "Course ID not found: Report to developer"
return course
course["course_id"] = course_id
dma = json.loads(soup.find("body")["data-module-args"])
if self.debug:
with open("test/dma.json", "w") as f:
with open("debug/dma.json", "w") as f:
json.dump(dma, f, indent=4)

is_free = not dma["serverSideProps"]["course"].get("isPaid", True)
if dma.get("view_restriction"):
course["is_invalid"] = True
course["msg"] = dma["serverSideProps"]["limitedAccess"]["errorMessage"][
"title"
]
return course

course["is_free"] = not dma["serverSideProps"]["course"].get("isPaid", True)
if not self.debug and self.is_course_excluded(dma):
return "excluded", r.url, False
course["is_excluded"] = True
return course

return course_id, r.url, is_free
return course

def is_course_excluded(self, dma):
instructors = [
Expand Down Expand Up @@ -835,7 +851,7 @@ def start_enrolling(self):
self.title = title
self.link = link
self.print_course_info(previous_courses_count + index, total_courses)
self.handle_course_enrollment(index)
self.handle_course_enrollment()
previous_courses_count += len(courses)

def initialize_counters(self):
Expand All @@ -857,27 +873,30 @@ def print_course_info(self, index, total_courses):
self.print(self.title, color="yellow", end=" ")
self.print(self.link, color="blue")

def handle_course_enrollment(self, index):
course_id, self.link, is_free = self.get_course_id(self.link)

if course_id == "invalid":
self.print("Invalid Course", color="red")
def handle_course_enrollment(self):
course = self.get_course_id(self.link)
if course["is_invalid"]:
self.print(course["msg"], color="red")
self.excluded_c += 1
elif course_id == "excluded":
elif course["retry"]:
self.print("Retrying...", color="red")
time.sleep(1)
self.handle_course_enrollment()
elif course["is_excluded"]:
self.excluded_c += 1
elif not course_id:
self.print("X Course Expired", color="red")
self.expired_c += 1
elif course_id in self.enrolled_courses:
elif course["course_id"] in self.enrolled_courses:
self.print(
f"You purchased this course on {self.get_date_from_utc(self.enrolled_courses[course_id])}",
f"You purchased this course on {self.get_date_from_utc(self.enrolled_courses[course['course_id']])}",
color="light blue",
)
self.already_enrolled_c += 1
elif is_free:
self.handle_free_course(course_id)
elif course["is_free"]:
self.handle_free_course(course["course_id"])
elif not course["is_free"]:
self.handle_discounted_course(course["course_id"])
else:
self.handle_discounted_course(course_id)
self.print("Unknown Error: Report this link to the developer", color="red")
self.excluded_c += 1

def handle_free_course(self, course_id):
if self.settings["discounted_only"]:
Expand Down
64 changes: 64 additions & 0 deletions default-duce-cli-settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"categories": {
"Business": true,
"Design": true,
"Development": true,
"Finance & Accounting": true,
"Health & Fitness": true,
"IT & Software": true,
"Lifestyle": true,
"Marketing": true,
"Music": true,
"Office Productivity": true,
"Personal Development": true,
"Photography & Video": true,
"Teaching & Academics": true
},
"languages": {
"Arabic": true,
"Chinese": true,
"Dutch": true,
"English": true,
"French": true,
"German": true,
"Hindi": true,
"Indonesian": true,
"Italian": true,
"Japanese": true,
"Korean": true,
"Nepali": true,
"Polish": true,
"Portuguese": true,
"Romanian": true,
"Russian": true,
"Spanish": true,
"Thai": true,
"Turkish": true,
"Urdu": true
},
"sites": {
"Real Discount": true,
"Discudemy": true,
"IDownloadCoupons": true,
"Tutorial Bar": true,
"E-next": true,
"Course Vania": true,
"Udemy Freebies": true
},
"min_rating": 0.0,
"instructor_exclude": [
"instructor-1",
"instructor-2",
"more-bad-instructor"
],
"title_exclude": [
"keyword One",
"noT_cAse SenSItiVe"
],
"email": "",
"password": "",
"save_txt": true,
"discounted_only": false,
"use_browser_cookies": false,
"course_update_threshold_months": 24
}
60 changes: 60 additions & 0 deletions default-duce-gui-settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"stay_logged_in": {
"auto": false,
"manual": false
},
"min_rating": 0.0,
"title_exclude": [],
"instructor_exclude": [],
"languages": {
"Arabic": true,
"Chinese": true,
"Dutch": true,
"English": true,
"French": true,
"German": true,
"Hindi": true,
"Indonesian": true,
"Italian": true,
"Japanese": true,
"Korean": true,
"Nepali": true,
"Polish": true,
"Portuguese": true,
"Romanian": true,
"Russian": true,
"Spanish": true,
"Thai": true,
"Turkish": true,
"Urdu": true
},
"categories": {
"Business": true,
"Design": true,
"Development": true,
"Finance & Accounting": true,
"Health & Fitness": true,
"IT & Software": true,
"Lifestyle": true,
"Marketing": true,
"Music": true,
"Office Productivity": true,
"Personal Development": true,
"Photography & Video": true,
"Teaching & Academics": true
},
"sites": {
"Real Discount": true,
"Discudemy": true,
"IDownloadCoupons": true,
"Tutorial Bar": true,
"E-next": true,
"Course Vania": true,
"Udemy Freebies": true
},
"email": "",
"password": "",
"save_txt": false,
"discounted_only": false,
"course_update_threshold_months": 24
}
2 changes: 1 addition & 1 deletion duce-cli-settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@
"password": "",
"save_txt": true,
"discounted_only": false,
"use_browser_cookies": false,
"use_browser_cookies": true,
"course_update_threshold_months": 24
}
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FreeSimpleGUI
rookiepy == 0.5.3b0
rookiepy
cloudscraper
bs4
requests
Expand Down

0 comments on commit 4cb9800

Please sign in to comment.