diff --git a/README.md b/README.md
index 1c8043b..a72ecae 100644
--- a/README.md
+++ b/README.md
@@ -13,22 +13,21 @@
- **This tool will not work without decryption keys, and there currently no public way to get those keys. Do not bother installing unless you already have keys!**
- This program is WIP, the code is provided as-is and I am not held resposible for any legal issues resulting from the use of this program.
-# Support
-
-if you want help using the program, join [my discord server](https://discord.gg/5B3XVb4RRX) or use [github issues](https://github.com/Puyodead1/udemy-downloader/issues)
-
-# License
-
-All code is licensed under the MIT license
-
# Description
Utility script to download Udemy courses, has support for DRM videos but requires the user to aquire the decryption key (for legal reasons).
-Windows is the primary development OS, but I've made an effort to support Linux also.
+Windows is the primary development OS, but I've made an effort to support Linux also (Mac untested).
# Requirements
-1. You will need to download `ffmpeg`, `aria2c`, `mp4decrypt` (from Bento4 SDK) and `yt-dlp` (`pip install yt-dlp`). Ensure they are in the system path (typing their name in cmd should invoke them).
+The following are a list of required third-party tools, you will need to ensure they are in your systems path and that typing their name in a terminal invokes them.
+
+_**Note**:_ _These are seperate requirements that are not installed with the pip command! You will need to download and install these manually!_
+
+- [ffmpeg](https://www.ffmpeg.org/) - This tool is available in Linux package repositories
+- [aria2/aria2c](https://github.com/aria2/aria2/) - This tool is available in Linux package repositories
+- [mp4decrypt](https://www.bento4.com/)
+- [yt-dlp](https://github.com/yt-dlp/yt-dlp/) - This tool is available in Linux package repositories, but can also be installed using pip if desired (`pip install yt-dlp`)
# Usage
@@ -40,27 +39,28 @@ You will need to get a few things before you can use this program:
- Decryption Key
- Udemy Course URL
- Udemy Bearer Token (aka acccess token for udemy-dl users)
+- Udemy cookies (only required for subscription plans - see [Udemy Subscription Plans](#udemy-subscription-plans))
-### Setting up
+## Setting up
- rename `.env.sample` to `.env` _(you only need to do this if you plan to use the .env file to store your bearer token)_
- rename `keyfile.example.json` to `keyfile.json`
-### Aquire Bearer Token
+## Aquire Bearer Token
- Firefox: [Udemy-DL Guide](https://github.com/r0oth3x49/udemy-dl/issues/389#issuecomment-491903900)
- Chrome: [Udemy-DL Guide](https://github.com/r0oth3x49/udemy-dl/issues/389#issuecomment-492569372)
- If you want to use the .env file to store your Bearer Token, edit the .env and add your token.
-### Key ID and Key
+## Key ID and Key
-It is up to you to aquire the key and key ID. Please **DO NOT** ask me for help acquiring these, decrypting DRM protected content can be considered piracy.
+It is up to you to aquire the key and key ID. Please **DO NOT** ask me for help acquiring these, decrypting DRM protected content can be considered piracy. The tool required for this has already been discused in a GitHub issue.
- Enter the key and key id in the `keyfile.json`
- 
- 
-### Start Downloading
+## Start Downloading
You can now run the program, see the examples below. The course will download to `out_dir`.
@@ -68,6 +68,8 @@ You can now run the program, see the examples below. The course will download to
To download a course included in a subscription plan that you did not purchase individually, you will need to follow a few more steps to get setup.
+_**NOTE**:_ _You do **NOT** need to follow this section if you don't have a **Udemy Pro** or **Udemy Personal** subscription plan! This section is not for individually purchased courses._
+
## Getting your cookies
- Go to the page of the course you want to download
@@ -82,6 +84,10 @@ To download a course included in a subscription plan that you did not purchase i
- Paste the cookie into the file
- save and close the file
+You will also need to ensure the link is in the following format: `https://www.udemy.com/course//learn/`.
+
+Note the link is `/course` not `/program-taking`. It is also important that the link has `/learn`, otherwise you will see an error when trying to fetch the course information.
+
# Advanced Usage
```
@@ -142,6 +148,10 @@ optional arguments:
- `python main.py -c --concurrent-downloads 20`
- `python main.py -c -cd 20`
+# Support
+
+if you want help using the program, join my [Discord](https://discord.gg/5B3XVb4RRX) server or use [GitHub Issues](https://github.com/Puyodead1/udemy-downloader/issues)
+
# Credits
- https://github.com/Jayapraveen/Drm-Dash-stream-downloader - For the original code which this is based on
@@ -149,3 +159,13 @@ optional arguments:
- https://github.com/alastairmccormack/pymp4parse - For code related to mp4 box parsing (used by pywvpssh)
- https://github.com/lbrayner/vtt-to-srt - For code related to converting subtitles from vtt to srt format
- https://github.com/r0oth3x49/udemy-dl - For some of the informaton related to using the udemy api
+
+## License
+
+All code is licensed under the MIT license
+
+## and finally, donations!
+
+Woo, you made it this far!
+
+I spend a lot of time coding things, and almost all of them are for nothing in return. When theres a lot of use of a program I make, I try to keep it updated, fix bugs, and even implement new features! But after a while, I do run out of motivation to keep doing it. If you like my work, and can help me out even a little, it would really help me out. If you are interested, you can find all the available options [here](https://github.com/Puyodead1/#supporting-me). Even if you don't, thank you anyways!
diff --git a/main.py b/main.py
index c18c269..a9b1ab8 100644
--- a/main.py
+++ b/main.py
@@ -92,7 +92,7 @@ class Udemy:
})
print("Login Success")
else:
- print("Login Failure!")
+ print("Login Failure! You are probably missing an access token!")
sys.exit(1)
def _extract_supplementary_assets(self, supp_assets):
@@ -400,11 +400,11 @@ class Udemy:
except conn_error as error:
print(f"Udemy Says: Connection error, {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
except (ValueError, Exception) as error:
print(f"Udemy Says: {error} on {url}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
else:
results = webpage.get("results", [])
return results
@@ -418,7 +418,7 @@ class Udemy:
except conn_error as error:
print(f"Udemy Says: Connection error, {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
else:
return resp
@@ -437,7 +437,7 @@ class Udemy:
except conn_error as error:
print(f"Udemy Says: Connection error, {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
except (ValueError, Exception):
resp = self._extract_large_course_content(url=url)
return resp
@@ -451,7 +451,7 @@ class Udemy:
except conn_error as error:
print(f"Udemy Says: Connection error, {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
else:
_next = data.get("next")
while _next:
@@ -461,7 +461,7 @@ class Udemy:
except conn_error as error:
print(f"Udemy Says: Connection error, {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
else:
_next = resp.get("next")
results = resp.get("results")
@@ -489,11 +489,11 @@ class Udemy:
except conn_error as error:
print(f"Udemy Says: Connection error, {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
except (ValueError, Exception) as error:
print(f"Udemy Says: {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
else:
results = webpage.get("results", [])
return results
@@ -506,11 +506,11 @@ class Udemy:
except conn_error as error:
print(f"Udemy Says: Connection error, {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
except (ValueError, Exception) as error:
print(f"Udemy Says: {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
else:
results = webpage.get("results", [])
if results:
@@ -529,11 +529,11 @@ class Udemy:
except conn_error as error:
print(f"Udemy Says: Connection error, {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
except (ValueError, Exception) as error:
print(f"Udemy Says: {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
else:
results = webpage.get("results", [])
return results
@@ -546,11 +546,11 @@ class Udemy:
except conn_error as error:
print(f"Udemy Says: Connection error, {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
except (ValueError, Exception) as error:
print(f"Udemy Says: {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
else:
results = webpage.get("results", [])
return results
@@ -563,11 +563,11 @@ class Udemy:
except conn_error as error:
print(f"Udemy Says: Connection error, {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
except (ValueError, Exception) as error:
print(f"Udemy Says: {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
else:
results = webpage.get("results", [])
if results:
@@ -586,11 +586,11 @@ class Udemy:
except conn_error as error:
print(f"Udemy Says: Connection error, {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
except (ValueError, Exception) as error:
print(f"Udemy Says: {error}")
time.sleep(0.8)
- sys.exit(0)
+ sys.exit(1)
else:
results = webpage.get("results", [])
return results
@@ -619,8 +619,14 @@ class Udemy:
if not course:
course_html = self.session._get(url).text
soup = BeautifulSoup(course_html, "lxml")
- data_args = soup.find(
- "div", {"class": "ud-component--course-taking--app"}).attrs["data-module-args"]
+ data = soup.find(
+ "div", {"class": "ud-component--course-taking--app"})
+ if not data:
+ print(
+ "Unable to extract arguments from course page! Make sure you have a cookies.txt file!")
+ self.session.terminate()
+ sys.exit(1)
+ data_args = data.attrs["data-module-args"]
data_json = json.loads(data_args)
course_id = data_json.get("courseId", None)
portal_name = self.extract_portal_name(url)
@@ -638,7 +644,7 @@ class Udemy:
print("Trying to logout now...", )
self.session.terminate()
print("Logged out successfully.", )
- sys.exit(0)
+ sys.exit(1)
class Session(object):