Skip to content

Commit

Permalink
tons of update, v1.2
Browse files Browse the repository at this point in the history
  • Loading branch information
LeeTeng2001 committed Nov 29, 2022
1 parent 8400370 commit c1b4de2
Show file tree
Hide file tree
Showing 6 changed files with 351 additions and 138 deletions.
12 changes: 10 additions & 2 deletions .gitignore
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
64 changes: 64 additions & 0 deletions README.md
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
- 更改应用语言为中文

58 changes: 34 additions & 24 deletions canvas_api.py
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)
Loading

0 comments on commit c1b4de2

Please sign in to comment.