-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8400370
commit c1b4de2
Showing
6 changed files
with
351 additions
and
138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,12 @@ | ||
configuration.json | ||
__pycache__ | ||
test_canvas_upload.py | ||
.DS_Store | ||
|
||
# Folder to ignore | ||
.idea | ||
__pycache__ | ||
venv | ||
build | ||
dist | ||
resources | ||
|
||
*.spec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
## 以下是面向用户文档 | ||
|
||
### 下载链接 | ||
1. Window 下载链接,下载exe | ||
2. Mac 下载链接,下载dmg | ||
|
||
### 教程 | ||
1. 去[Canvas设置](https://oc.sjtu.edu.cn/profile/settings),滑倒下方找到**允许融入使用的外部软件**,点击创建新访问许可证,用途随便写,过期可以留空白 | ||
2. 生成后把你的Canvas令牌保存起来放到一旁 | ||
3. 去找你要下载的课程页面,看网址上方最后的号码,抄下来,格式如下:https://oc.sjtu.edu.cn/courses/93214 | ||
4. 点击exe程序(应该需要权限),点击set,把你的访问许可证填进去然后点击ok。点击change更改你的目标文件夹。class code填写课程网址代码。 | ||
5. **同步模式** : 推荐On因为On只会下载新的文件,他会先检查你的目标文件夹下有没有重名的文件,没有的话才会下载(也会查看目标文件夹的子文件夹所以不要担心) | ||
6. **Canvas文件结构**: 下载的文件要不要依据canvas上的文件夹形式 | ||
7. 点击保存并运行 | ||
8. 注意Canvas令牌只需要生成,填写一次,以后想要下载其他课程就换课程号码参数就可以了 | ||
|
||
|
||
## 以下是面向开发者文档 | ||
|
||
## How to build and run this project locally | ||
|
||
```bash | ||
# Create new virtual environment and install dependencies | ||
$ python3 -m venv venv | ||
$ source venv/bin/activate | ||
$ pip install -r requirement.txt | ||
|
||
# Run | ||
$ python canvas_downloader.py | ||
|
||
# Build executable and disk (mac) | ||
$ pyinstaller -n "SJTU Canvas下载器" -w --icon=resources/canvas.icns canvas_downloader.py | ||
$ mkdir -p dist/dmg | ||
$ cp -r dist/SJTU\ Canvas下载器.app dist/dmg | ||
$ create-dmg \ | ||
--volname "SJTU Canvas下载器" \ | ||
--volicon "resources/canvas.icns" \ | ||
--window-pos 200 120 \ | ||
--window-size 600 300 \ | ||
--icon-size 100 \ | ||
--icon "SJTU Canvas下载器.app" 175 120 \ | ||
--hide-extension "SJTU Canvas下载器.app" \ | ||
--app-drop-link 425 120 \ | ||
"dist/SJTU Canvas下载器.dmg" \ | ||
"dist/dmg/" | ||
|
||
# Build executable (window) | ||
$ pyinstaller -n "SJTU Canvas下载器" -w --icon=resources/canvas.ico canvas_downloader.py | ||
``` | ||
|
||
## Change Log | ||
- v1.0 | ||
- Initial build | ||
- v1.1 | ||
- Added sync & ability to choose download structure | ||
- v1.2 (Next release) | ||
- Update to QT6 | ||
- restructure project for maintainability | ||
- Add docs and code refactoring | ||
- Remove dependency for `configuration.json` file | ||
- Use pathlib for path manipulation instead of os | ||
- Unit testing | ||
- 更改应用语言为中文 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,75 @@ | ||
from canvasapi import Canvas, exceptions | ||
from typing import Callable | ||
import os | ||
from pathlib import Path | ||
from utils import get_application_setting, ConfigKey | ||
|
||
app_setting = get_application_setting() | ||
|
||
def download_canvas(secret_token: str, course_num: int, save_to_path: str, | ||
print_output: Callable[[str], None], sync_on: bool, canvas_struct: bool) -> None: | ||
def download_canvas(print_output: Callable[[str], None]) -> None: | ||
""" | ||
Download files from canvas | ||
Args: | ||
secret_token: token to access canvas api | ||
course_num: course number to download from | ||
save_to_path: which folder to save to | ||
print_output: output function (eg: terminal or qt output) | ||
sync_on: | ||
canvas_struct: | ||
""" | ||
canvas_struct = app_setting.value(ConfigKey.CANVAS_STRUCT) | ||
sync_on = app_setting.value(ConfigKey.SYNC_ON) | ||
download_to_folder = app_setting.value(ConfigKey.FOLDER_PATH_ABS) | ||
|
||
try: | ||
canvas = Canvas("https://oc.sjtu.edu.cn/", secret_token) # Init | ||
course = canvas.get_course(course_num) | ||
canvas = Canvas("https://oc.sjtu.edu.cn/", app_setting.value(ConfigKey.SECRET_TOKEN)) | ||
course = canvas.get_course(app_setting.value(ConfigKey.CLASS_CODE)) | ||
except exceptions.InvalidAccessToken: | ||
print_output("下载失败,请检查你的口令牌") | ||
print_output("下载失败:请检查你的口令牌") | ||
return | ||
except ValueError: | ||
print_output("下载失败:请确保课程号码已经设置") | ||
return | ||
except exceptions.ResourceDoesNotExist: | ||
print_output("FAILED. Check your course number!") | ||
print_output("下载失败:课程号码不存在,请检查") | ||
return | ||
except exceptions.CanvasException: | ||
print_output("下载失败:Canvas状态异常") | ||
return | ||
except: | ||
print_output("FAILED. Unknown error occur while trying to connect with canvas!") | ||
except Exception: | ||
print_output("下载失败:遇到未知错误") | ||
return | ||
|
||
# variables to get all the files in the current save path first for a LOOKUP table | ||
current_files = set() # print this to debug | ||
new_files_idx = 0 | ||
for dir_path, dir_names, filenames in os.walk(save_to_path): | ||
for dir_path, dir_names, filenames in os.walk(download_to_folder): | ||
current_files.update(filenames) | ||
|
||
for folder in course.get_folders(): # Get all folders in a course, it contains all sub-folders as well ! | ||
# Extract the top folder path | ||
folder_top = "" if str(folder) == 'course files' else str(folder).split('/', 1)[1] | ||
print_output(f"Currently at: {folder_top if folder_top else 'Canvas Home'}") | ||
print_output(f"正在爬取: {folder_top if folder_top else 'Canvas Home'}") | ||
folder_top = "" if not canvas_struct else folder_top # Check download directory structure | ||
|
||
# Download files | ||
for file in folder.get_files(): | ||
if not sync_on or str(file) not in current_files: # Download checking condition | ||
try: | ||
print_output(f"Downloading file {new_files_idx + 1} inside {folder_top if folder_top else 'Canvas Home'}... -> {file}") | ||
print_output(f"位于{folder_top if folder_top else 'Canvas Home'},正在下载文件:{file}") | ||
|
||
# Create folder to replicate canvas structure | ||
os.makedirs(os.path.join(save_to_path, folder_top), exist_ok=True) | ||
file.download(os.path.join(save_to_path, folder_top, str(file))) | ||
Path(download_to_folder, folder_top).mkdir(parents=True, exist_ok=True) | ||
file.download(Path(app_setting.value(ConfigKey.FOLDER_PATH_ABS), folder_top, str(file)).as_posix()) | ||
new_files_idx += 1 # only increment after download because it might have error during download | ||
except exceptions.ResourceDoesNotExist: | ||
print_output(f"Download error: You might not have permission to access this file.") | ||
print_output(f"下载失败:资源不存在") | ||
except exceptions.Unauthorized: | ||
print_output(f"下载失败:没有权限") | ||
|
||
# Status report | ||
print_output(f"Finished, there's {new_files_idx} newly added files.") | ||
print_output(f"下载结束,总共下载了{new_files_idx}个文件。") | ||
|
||
|
||
if __name__ == '__main__': | ||
# FOR DEBUGGING | ||
API_KEY = os.getenv("SJTU_CANVAS_KEY") | ||
COURSE_NUMBER = 28295 | ||
SAVE_FOLDER_LOC = "/Users/lunafreya/Downloads/untitled" | ||
download_canvas(API_KEY, COURSE_NUMBER, SAVE_FOLDER_LOC, print, True, True) | ||
# COURSE_NUMBER = 28295 | ||
# SAVE_FOLDER_LOC = "/Users/lunafreya/Downloads/untitled" | ||
# download_canvas(API_KEY, COURSE_NUMBER, SAVE_FOLDER_LOC, print, True, True) |
Oops, something went wrong.