e3cli 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- e3cli-0.3.1/.github/workflows/ci.yml +34 -0
- e3cli-0.3.1/.github/workflows/release.yml +117 -0
- e3cli-0.3.1/.gitignore +19 -0
- e3cli-0.3.1/Formula/e3cli.rb +35 -0
- e3cli-0.3.1/LICENSE +21 -0
- e3cli-0.3.1/Makefile +26 -0
- e3cli-0.3.1/PKG-INFO +370 -0
- e3cli-0.3.1/README.md +336 -0
- e3cli-0.3.1/e3cli/__init__.py +3 -0
- e3cli-0.3.1/e3cli/__main__.py +5 -0
- e3cli-0.3.1/e3cli/ai/__init__.py +1 -0
- e3cli-0.3.1/e3cli/api/__init__.py +0 -0
- e3cli-0.3.1/e3cli/api/assignments.py +38 -0
- e3cli-0.3.1/e3cli/api/client.py +77 -0
- e3cli-0.3.1/e3cli/api/courses.py +27 -0
- e3cli-0.3.1/e3cli/api/files.py +25 -0
- e3cli-0.3.1/e3cli/api/site.py +10 -0
- e3cli-0.3.1/e3cli/auth.py +33 -0
- e3cli-0.3.1/e3cli/cli.py +61 -0
- e3cli-0.3.1/e3cli/commands/__init__.py +0 -0
- e3cli-0.3.1/e3cli/commands/_common.py +29 -0
- e3cli-0.3.1/e3cli/commands/assignments.py +91 -0
- e3cli-0.3.1/e3cli/commands/courses.py +39 -0
- e3cli-0.3.1/e3cli/commands/download.py +105 -0
- e3cli-0.3.1/e3cli/commands/login.py +68 -0
- e3cli-0.3.1/e3cli/commands/logout.py +19 -0
- e3cli-0.3.1/e3cli/commands/schedule.py +42 -0
- e3cli-0.3.1/e3cli/commands/setup.py +142 -0
- e3cli-0.3.1/e3cli/commands/submit.py +77 -0
- e3cli-0.3.1/e3cli/commands/sync.py +115 -0
- e3cli-0.3.1/e3cli/config.py +98 -0
- e3cli-0.3.1/e3cli/credential.py +116 -0
- e3cli-0.3.1/e3cli/i18n.py +233 -0
- e3cli-0.3.1/e3cli/scheduler/__init__.py +0 -0
- e3cli-0.3.1/e3cli/scheduler/cron.py +54 -0
- e3cli-0.3.1/e3cli/storage/__init__.py +0 -0
- e3cli-0.3.1/e3cli/storage/db.py +124 -0
- e3cli-0.3.1/e3cli/storage/models.py +32 -0
- e3cli-0.3.1/e3cli/storage/tracking.py +11 -0
- e3cli-0.3.1/pyproject.toml +57 -0
- e3cli-0.3.1/tests/__init__.py +0 -0
- e3cli-0.3.1/tests/test_basic.py +32 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
os: [ubuntu-latest, macos-latest]
|
|
15
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- uses: actions/setup-python@v5
|
|
20
|
+
with:
|
|
21
|
+
python-version: ${{ matrix.python-version }}
|
|
22
|
+
|
|
23
|
+
- name: Install dependencies
|
|
24
|
+
run: |
|
|
25
|
+
pip install -e ".[dev]"
|
|
26
|
+
|
|
27
|
+
- name: Lint
|
|
28
|
+
run: ruff check e3cli/
|
|
29
|
+
|
|
30
|
+
- name: Test
|
|
31
|
+
run: pytest --tb=short -q
|
|
32
|
+
|
|
33
|
+
- name: Verify CLI loads
|
|
34
|
+
run: e3cli version
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: write
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
release:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
|
|
20
|
+
- name: Install build tools
|
|
21
|
+
run: pip install build
|
|
22
|
+
|
|
23
|
+
- name: Build package
|
|
24
|
+
run: python -m build
|
|
25
|
+
|
|
26
|
+
- name: Create GitHub Release
|
|
27
|
+
uses: softprops/action-gh-release@v2
|
|
28
|
+
with:
|
|
29
|
+
files: dist/*
|
|
30
|
+
generate_release_notes: true
|
|
31
|
+
|
|
32
|
+
- name: Publish to PyPI
|
|
33
|
+
env:
|
|
34
|
+
TWINE_USERNAME: __token__
|
|
35
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
36
|
+
run: pip install twine && twine upload dist/*
|
|
37
|
+
|
|
38
|
+
update-homebrew:
|
|
39
|
+
needs: release
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
|
|
44
|
+
- name: Calculate tarball sha256
|
|
45
|
+
id: sha
|
|
46
|
+
run: |
|
|
47
|
+
TARBALL_URL="https://github.com/${{ github.repository }}/archive/refs/tags/${{ github.ref_name }}.tar.gz"
|
|
48
|
+
echo "url=${TARBALL_URL}" >> "$GITHUB_OUTPUT"
|
|
49
|
+
SHA=$(curl -sL "${TARBALL_URL}" | sha256sum | cut -d' ' -f1)
|
|
50
|
+
echo "sha256=${SHA}" >> "$GITHUB_OUTPUT"
|
|
51
|
+
echo "Tarball: ${TARBALL_URL}"
|
|
52
|
+
echo "SHA256: ${SHA}"
|
|
53
|
+
|
|
54
|
+
- name: Clone homebrew tap
|
|
55
|
+
uses: actions/checkout@v4
|
|
56
|
+
with:
|
|
57
|
+
repository: ${{ github.repository_owner }}/homebrew-e3cli
|
|
58
|
+
token: ${{ secrets.TAP_GITHUB_TOKEN }}
|
|
59
|
+
path: homebrew-tap
|
|
60
|
+
|
|
61
|
+
- name: Update formula
|
|
62
|
+
run: |
|
|
63
|
+
cat > homebrew-tap/Formula/e3cli.rb << 'FORMULA_EOF'
|
|
64
|
+
class E3cli < Formula
|
|
65
|
+
include Language::Python::Virtualenv
|
|
66
|
+
|
|
67
|
+
desc "NYCU E3 Moodle automation CLI — sync courses, download materials, submit assignments"
|
|
68
|
+
homepage "https://github.com/${{ github.repository }}"
|
|
69
|
+
url "${{ steps.sha.outputs.url }}"
|
|
70
|
+
sha256 "${{ steps.sha.outputs.sha256 }}"
|
|
71
|
+
license "MIT"
|
|
72
|
+
|
|
73
|
+
depends_on "python@3.12"
|
|
74
|
+
FORMULA_EOF
|
|
75
|
+
|
|
76
|
+
# Append dependency resources from PyPI
|
|
77
|
+
python3 -c "
|
|
78
|
+
import json, urllib.request
|
|
79
|
+
deps = ['typer', 'requests', 'rich']
|
|
80
|
+
for pkg in deps:
|
|
81
|
+
info = json.loads(urllib.request.urlopen(f'https://pypi.org/pypi/{pkg}/json').read())
|
|
82
|
+
ver = info['info']['version']
|
|
83
|
+
for f in info['releases'][ver]:
|
|
84
|
+
if f['packagetype'] == 'sdist':
|
|
85
|
+
print(f'')
|
|
86
|
+
print(f' resource \"{pkg}\" do')
|
|
87
|
+
print(f' url \"{f[\"url\"]}\"')
|
|
88
|
+
print(f' sha256 \"{f[\"digests\"][\"sha256\"]}\"')
|
|
89
|
+
print(f' end')
|
|
90
|
+
break
|
|
91
|
+
" >> homebrew-tap/Formula/e3cli.rb
|
|
92
|
+
|
|
93
|
+
# Append install and test blocks
|
|
94
|
+
cat >> homebrew-tap/Formula/e3cli.rb << 'TAIL_EOF'
|
|
95
|
+
|
|
96
|
+
def install
|
|
97
|
+
virtualenv_install_with_resources
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
test do
|
|
101
|
+
assert_match "e3cli", shell_output("#{bin}/e3cli version")
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
TAIL_EOF
|
|
105
|
+
|
|
106
|
+
echo "=== Generated formula ==="
|
|
107
|
+
cat homebrew-tap/Formula/e3cli.rb
|
|
108
|
+
|
|
109
|
+
- name: Push updated formula
|
|
110
|
+
run: |
|
|
111
|
+
cd homebrew-tap
|
|
112
|
+
git config user.name "github-actions[bot]"
|
|
113
|
+
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
114
|
+
git add Formula/e3cli.rb
|
|
115
|
+
git diff --cached --quiet && echo "No changes" && exit 0
|
|
116
|
+
git commit -m "Update e3cli to ${{ github.ref_name }}"
|
|
117
|
+
git push
|
e3cli-0.3.1/.gitignore
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
class E3cli < Formula
|
|
2
|
+
include Language::Python::Virtualenv
|
|
3
|
+
|
|
4
|
+
desc "NYCU E3 Moodle automation CLI — sync courses, download materials, submit assignments"
|
|
5
|
+
homepage "https://github.com/junlinwk/e3cli"
|
|
6
|
+
url "https://github.com/junlinwk/e3cli/archive/refs/tags/v0.1.0.tar.gz"
|
|
7
|
+
sha256 "7aa0147a0301b7fcd69502689cece3d648dc19f2ce6025b131b325b31300367a"
|
|
8
|
+
license "MIT"
|
|
9
|
+
|
|
10
|
+
depends_on "python@3.12"
|
|
11
|
+
|
|
12
|
+
resource "typer" do
|
|
13
|
+
url "https://files.pythonhosted.org/packages/f5/24/cb09efec5cc954f7f9b930bf8279447d24618bb6758d4f6adf2574c41780/typer-0.24.1.tar.gz"
|
|
14
|
+
sha256 "e39b4732d65fbdcde189ae76cf7cd48aeae72919dea1fdfc16593be016256b45"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
resource "requests" do
|
|
18
|
+
url "https://files.pythonhosted.org/packages/34/64/8860370b167a9721e8956ae116825caff829224fbca0ca6e7bf8ddef8430/requests-2.33.0.tar.gz"
|
|
19
|
+
sha256 "c7ebc5e8b0f21837386ad0e1c8fe8b829fa5f544d8df3b2253bff14ef29d7652"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
resource "rich" do
|
|
23
|
+
url "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz"
|
|
24
|
+
sha256 "b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def install
|
|
28
|
+
virtualenv_install_with_resources
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
test do
|
|
32
|
+
assert_match "e3cli", shell_output("#{bin}/e3cli version")
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
ㄍ
|
e3cli-0.3.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 E3CLI Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
e3cli-0.3.1/Makefile
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
.PHONY: install dev lint test build clean
|
|
2
|
+
|
|
3
|
+
install: ## Install e3cli
|
|
4
|
+
pip install .
|
|
5
|
+
|
|
6
|
+
dev: ## Install in development mode with dev dependencies
|
|
7
|
+
pip install -e ".[dev]"
|
|
8
|
+
|
|
9
|
+
lint: ## Run linter
|
|
10
|
+
ruff check e3cli/
|
|
11
|
+
|
|
12
|
+
test: ## Run tests
|
|
13
|
+
pytest --tb=short -q
|
|
14
|
+
|
|
15
|
+
build: ## Build distribution packages
|
|
16
|
+
python -m build
|
|
17
|
+
|
|
18
|
+
clean: ## Remove build artifacts
|
|
19
|
+
rm -rf dist/ build/ *.egg-info/
|
|
20
|
+
find . -type d -name __pycache__ -exec rm -rf {} +
|
|
21
|
+
|
|
22
|
+
formula: ## Generate Homebrew formula (requires version tag, e.g. make formula TAG=v0.1.0)
|
|
23
|
+
python scripts/generate-formula.py $(TAG)
|
|
24
|
+
|
|
25
|
+
help: ## Show this help
|
|
26
|
+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-12s\033[0m %s\n", $$1, $$2}'
|
e3cli-0.3.1/PKG-INFO
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: e3cli
|
|
3
|
+
Version: 0.3.1
|
|
4
|
+
Summary: NYCU E3 Moodle automation CLI — sync courses, download materials, submit assignments.
|
|
5
|
+
Project-URL: Homepage, https://github.com/junlinwk/e3cli
|
|
6
|
+
Project-URL: Repository, https://github.com/junlinwk/e3cli
|
|
7
|
+
Project-URL: Issues, https://github.com/junlinwk/e3cli/issues
|
|
8
|
+
Author: E3CLI Contributors
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: automation,cli,e3,moodle,nycu
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Education
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: MacOS
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Education
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: requests>=2.31
|
|
24
|
+
Requires-Dist: rich>=13.0
|
|
25
|
+
Requires-Dist: typer>=0.9
|
|
26
|
+
Provides-Extra: ai
|
|
27
|
+
Requires-Dist: anthropic>=0.18; extra == 'ai'
|
|
28
|
+
Requires-Dist: pymupdf>=1.23; extra == 'ai'
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.4; extra == 'dev'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# e3cli
|
|
36
|
+
|
|
37
|
+
NYCU E3 Moodle automation CLI -- sync courses, download materials, submit assignments from your terminal.
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- **Login** -- authenticate via Moodle Web Service API, encrypted credential storage
|
|
42
|
+
- **Courses** -- list all enrolled courses
|
|
43
|
+
- **Assignments** -- view assignments, deadlines, submission status
|
|
44
|
+
- **Download** -- batch download course materials, skip already-downloaded files
|
|
45
|
+
- **Submit** -- upload and submit assignments from CLI
|
|
46
|
+
- **Sync** -- one command to pull everything new (materials + assignment status)
|
|
47
|
+
- **Schedule** -- cron-based automatic sync
|
|
48
|
+
|
|
49
|
+
## Supported Platforms
|
|
50
|
+
|
|
51
|
+
| Platform | Architecture | Status |
|
|
52
|
+
|----------|-------------|--------|
|
|
53
|
+
| macOS | Apple Silicon (ARM64) | Supported |
|
|
54
|
+
| macOS | Intel (x86_64) | Supported |
|
|
55
|
+
| Linux | x86_64 | Supported |
|
|
56
|
+
| Linux | ARM64 | Supported |
|
|
57
|
+
|
|
58
|
+
Requires **Python 3.11+**.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Installation
|
|
63
|
+
|
|
64
|
+
### Option 1: Homebrew (recommended for macOS/Linux)
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Add the tap
|
|
68
|
+
brew tap junlinwk/e3cli
|
|
69
|
+
|
|
70
|
+
# Install
|
|
71
|
+
brew install e3cli
|
|
72
|
+
|
|
73
|
+
# Verify
|
|
74
|
+
e3cli version
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Option 2: pipx (isolated install, recommended for Linux)
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Install pipx if you don't have it
|
|
81
|
+
brew install pipx # or: apt install pipx
|
|
82
|
+
pipx ensurepath
|
|
83
|
+
|
|
84
|
+
# Install e3cli
|
|
85
|
+
pipx install e3cli
|
|
86
|
+
|
|
87
|
+
# Verify
|
|
88
|
+
e3cli version
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Option 3: pip
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install e3cli
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Option 4: From source (development)
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git clone https://github.com/junlinwk/e3cli.git
|
|
101
|
+
cd e3cli
|
|
102
|
+
pip install -e ".[dev]"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Update
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Quick Start
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
# 1. Login (first time)
|
|
112
|
+
e3cli login --save # --save encrypts and stores your credentials locally
|
|
113
|
+
|
|
114
|
+
# 2. List your courses
|
|
115
|
+
e3cli courses
|
|
116
|
+
|
|
117
|
+
# 3. Download all course materials
|
|
118
|
+
e3cli download --all
|
|
119
|
+
|
|
120
|
+
# 4. Check assignments and deadlines
|
|
121
|
+
e3cli assignments
|
|
122
|
+
|
|
123
|
+
# 5. Submit an assignment
|
|
124
|
+
e3cli submit <assignment-id> homework.pdf
|
|
125
|
+
|
|
126
|
+
# 6. Enable automatic sync (every hour)
|
|
127
|
+
e3cli schedule enable
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Commands
|
|
133
|
+
|
|
134
|
+
### `e3cli login`
|
|
135
|
+
|
|
136
|
+
Authenticate with your Moodle account and store the API token.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
e3cli login # Interactive prompt
|
|
140
|
+
e3cli login -u <student-id> # Specify username
|
|
141
|
+
e3cli login --save # Save credentials (encrypted) for auto-refresh
|
|
142
|
+
e3cli login --refresh # Re-authenticate using saved credentials
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### `e3cli logout`
|
|
146
|
+
|
|
147
|
+
Securely erase all stored credentials and tokens.
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
e3cli logout
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### `e3cli courses`
|
|
154
|
+
|
|
155
|
+
List all enrolled courses in a formatted table.
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
e3cli courses
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### `e3cli assignments`
|
|
162
|
+
|
|
163
|
+
View assignments with deadlines and submission status.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
e3cli assignments # All assignments
|
|
167
|
+
e3cli assignments --due-soon 7 # Due within 7 days
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### `e3cli download`
|
|
171
|
+
|
|
172
|
+
Download course materials to local disk.
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
e3cli download --all # All courses
|
|
176
|
+
e3cli download --course "OS" # Filter by course name/code
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Files are saved to `~/e3-downloads/<course>/<section>/` by default. Already-downloaded files are skipped automatically (tracked via SQLite).
|
|
180
|
+
|
|
181
|
+
### `e3cli submit`
|
|
182
|
+
|
|
183
|
+
Upload and submit an assignment.
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
e3cli submit <assignment-id> file1.pdf file2.zip
|
|
187
|
+
e3cli submit <assignment-id> report.pdf --text "Some notes"
|
|
188
|
+
e3cli submit <assignment-id> late-hw.pdf --force # Submit past deadline
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### `e3cli sync`
|
|
192
|
+
|
|
193
|
+
Pull all new materials and update assignment status in one command.
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
e3cli sync # Interactive output
|
|
197
|
+
e3cli sync --quiet # Silent mode (for cron)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### `e3cli schedule`
|
|
201
|
+
|
|
202
|
+
Manage automatic sync via system crontab.
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
e3cli schedule enable # Default: every 60 minutes
|
|
206
|
+
e3cli schedule enable --interval 30 # Every 30 minutes
|
|
207
|
+
e3cli schedule disable # Remove cron job
|
|
208
|
+
e3cli schedule status # Show current schedule
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### `e3cli version`
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
e3cli version
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Configuration
|
|
220
|
+
|
|
221
|
+
Config file: `~/.e3cli/config.toml`
|
|
222
|
+
|
|
223
|
+
```toml
|
|
224
|
+
[moodle]
|
|
225
|
+
url = "https://e3p.nycu.edu.tw" # Your Moodle instance URL
|
|
226
|
+
service = "moodle_mobile_app" # Web service name (usually don't change)
|
|
227
|
+
|
|
228
|
+
[storage]
|
|
229
|
+
download_dir = "~/e3-downloads" # Where to save course materials
|
|
230
|
+
db_path = "~/.e3cli/data/e3cli.db" # Tracking database
|
|
231
|
+
|
|
232
|
+
[schedule]
|
|
233
|
+
interval_minutes = 60 # Sync interval for cron job
|
|
234
|
+
notify = true # Desktop notifications (future)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The config file is auto-created with defaults on first run. Edit it to customize behavior.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Security
|
|
242
|
+
|
|
243
|
+
### Credential Storage
|
|
244
|
+
|
|
245
|
+
e3cli uses **Fernet symmetric encryption** (from the `cryptography` library) to protect stored credentials:
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
~/.e3cli/
|
|
249
|
+
key # Random 256-bit encryption key (chmod 600)
|
|
250
|
+
credentials.enc # Encrypted username + password (chmod 600)
|
|
251
|
+
token # Moodle API token (chmod 600)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
- Encryption key is randomly generated per machine and stored separately from credentials
|
|
255
|
+
- All sensitive files are created with `chmod 600` (owner-only read/write)
|
|
256
|
+
- Passwords are **never** stored in plaintext or passed as CLI arguments (uses `getpass`)
|
|
257
|
+
- `e3cli logout` securely overwrites files with zeros before deletion
|
|
258
|
+
|
|
259
|
+
### What's NOT stored
|
|
260
|
+
|
|
261
|
+
- Your password is never written to shell history (interactive `getpass` prompt)
|
|
262
|
+
- No credentials in `config.toml`
|
|
263
|
+
- No credentials in environment variables
|
|
264
|
+
|
|
265
|
+
### Recommendations
|
|
266
|
+
|
|
267
|
+
- Use `e3cli login --save` only on machines you trust
|
|
268
|
+
- Run `e3cli logout` when done on shared machines
|
|
269
|
+
- The `~/.e3cli/` directory is in `.gitignore` -- never commit it
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Local Data
|
|
274
|
+
|
|
275
|
+
| Path | Purpose |
|
|
276
|
+
|------|---------|
|
|
277
|
+
| `~/.e3cli/config.toml` | User configuration |
|
|
278
|
+
| `~/.e3cli/token` | Moodle API token (encrypted-equivalent, chmod 600) |
|
|
279
|
+
| `~/.e3cli/key` | Encryption key (chmod 600) |
|
|
280
|
+
| `~/.e3cli/credentials.enc` | Encrypted credentials (chmod 600) |
|
|
281
|
+
| `~/.e3cli/data/e3cli.db` | SQLite tracking DB (downloaded files, assignment status) |
|
|
282
|
+
| `~/e3-downloads/` | Downloaded course materials |
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Project Structure
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
e3cli/
|
|
291
|
+
├── pyproject.toml # Package metadata and dependencies
|
|
292
|
+
├── Makefile # Dev shortcuts (make dev, make test, etc.)
|
|
293
|
+
├── LICENSE # MIT License
|
|
294
|
+
├── Formula/e3cli.rb # Homebrew formula template
|
|
295
|
+
├── scripts/
|
|
296
|
+
│ ├── generate-formula.py # Auto-generate formula from PyPI
|
|
297
|
+
│ └── setup-homebrew-tap.sh # Bootstrap Homebrew tap repo
|
|
298
|
+
├── .github/workflows/
|
|
299
|
+
│ ├── ci.yml # Test on push/PR (Linux + macOS, Py 3.11-3.13)
|
|
300
|
+
│ └── release.yml # Build + publish on tag push
|
|
301
|
+
├── e3cli/
|
|
302
|
+
│ ├── __init__.py
|
|
303
|
+
│ ├── __main__.py # python -m e3cli
|
|
304
|
+
│ ├── cli.py # Typer CLI entry point
|
|
305
|
+
│ ├── config.py # ~/.e3cli/config.toml management
|
|
306
|
+
│ ├── auth.py # Moodle token authentication
|
|
307
|
+
│ ├── credential.py # Encrypted credential storage
|
|
308
|
+
│ ├── api/
|
|
309
|
+
│ │ ├── client.py # Moodle REST API client
|
|
310
|
+
│ │ ├── site.py # Site info
|
|
311
|
+
│ │ ├── courses.py # Course listing and contents
|
|
312
|
+
│ │ ├── assignments.py # Assignment queries and submission
|
|
313
|
+
│ │ └── files.py # File download
|
|
314
|
+
│ ├── storage/
|
|
315
|
+
│ │ ├── db.py # SQLite schema and operations
|
|
316
|
+
│ │ ├── models.py # Data models
|
|
317
|
+
│ │ └── tracking.py # Download/assignment tracking
|
|
318
|
+
│ ├── commands/
|
|
319
|
+
│ │ ├── _common.py # Shared utilities (get_client, get_db)
|
|
320
|
+
│ │ ├── login.py # e3cli login
|
|
321
|
+
│ │ ├── logout.py # e3cli logout
|
|
322
|
+
│ │ ├── courses.py # e3cli courses
|
|
323
|
+
│ │ ├── assignments.py # e3cli assignments
|
|
324
|
+
│ │ ├── download.py # e3cli download
|
|
325
|
+
│ │ ├── submit.py # e3cli submit
|
|
326
|
+
│ │ ├── sync.py # e3cli sync
|
|
327
|
+
│ │ └── schedule.py # e3cli schedule
|
|
328
|
+
│ ├── scheduler/
|
|
329
|
+
│ │ └── cron.py # Crontab management
|
|
330
|
+
│ └── ai/ # Future: AI integration
|
|
331
|
+
│ └── __init__.py
|
|
332
|
+
└── tests/
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Development
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
# Clone and install in dev mode
|
|
341
|
+
git clone https://github.com/<your-user>/e3cli.git
|
|
342
|
+
cd e3cli
|
|
343
|
+
make dev # pip install -e ".[dev]"
|
|
344
|
+
|
|
345
|
+
# Run linter
|
|
346
|
+
make lint
|
|
347
|
+
|
|
348
|
+
# Run tests
|
|
349
|
+
make test
|
|
350
|
+
|
|
351
|
+
# Build distribution
|
|
352
|
+
make build
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Roadmap
|
|
358
|
+
|
|
359
|
+
- [ ] AI-powered material summarization (`e3cli ai summarize`)
|
|
360
|
+
- [ ] AI-assisted assignment drafting (`e3cli ai draft`)
|
|
361
|
+
- [ ] Smart deadline notifications with priority scoring
|
|
362
|
+
- [ ] Desktop notification integration (Linux `notify-send`, macOS `osascript`)
|
|
363
|
+
- [ ] Course filtering by semester
|
|
364
|
+
- [ ] Parallel downloads for faster sync
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## License
|
|
369
|
+
|
|
370
|
+
MIT
|