e3cli 0.3.1__py3-none-any.whl

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.
@@ -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
@@ -0,0 +1,36 @@
1
+ e3cli/__init__.py,sha256=MBBBeDGindYTULoCuSMy0v9AoYhZjyJw4vQLWd_8VoA,74
2
+ e3cli/__main__.py,sha256=urCBVMSA_KghtUSCjG5OUYVgW0i9fW3PuTfAP1y0Ouo,76
3
+ e3cli/auth.py,sha256=JJldnoOZcDH12F3EZvMk1hZp5cdVN6yigN5-A4n-I_c,909
4
+ e3cli/cli.py,sha256=7-rbq8dCHp7HCmysXaH3oaxaZ2XBc887mn533TWjHRg,1963
5
+ e3cli/config.py,sha256=JFUV8B8F9W2-Tk5ZuWtcaWUw8aOqjVjq0cQdkJGl2ic,2787
6
+ e3cli/credential.py,sha256=I650l7qfi0Z7srI03Cyus07qecdraUu0K0bxwuSuSz8,3746
7
+ e3cli/i18n.py,sha256=b9BFIZVJ7_dTGRq9LBK7WT_fcFUmi3GWP06yWXH_9KI,11204
8
+ e3cli/ai/__init__.py,sha256=L89yntHdvz1zBpUV6Hkye3ES1_hAl2jNEsHqqaQZmVg,40
9
+ e3cli/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ e3cli/api/assignments.py,sha256=gTtWvmwC0xm-1NZG3FcFFb0A0PEg1Pd_WsT6QSrGSMk,1283
11
+ e3cli/api/client.py,sha256=TUrV01RNY5HDVsyM-4h9r0jvbFPNkmCIrdCYhAtid1Q,2573
12
+ e3cli/api/courses.py,sha256=qyuqQA13wW2f-__SONDPuaUONfJkltQ9goDC2c_FQUM,813
13
+ e3cli/api/files.py,sha256=woNe7nKnVfd_2VEyRixvfr-HHWdqwsu3nsLVgdYFxD0,642
14
+ e3cli/api/site.py,sha256=Kl60NBNR4I959FCDqeSTJp3YVnwZoUKuebt8AeW5Uv4,286
15
+ e3cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ e3cli/commands/_common.py,sha256=NOmf4TS9Eni98nKcu2nGVObVbO-HU-_g-2gnxkeNPLs,747
17
+ e3cli/commands/assignments.py,sha256=ciQvucc3WG9RA0O0A1f033GC48LQ-g-l6b3dbNSZDA8,2820
18
+ e3cli/commands/courses.py,sha256=J5-nHsyC1ONx1hid21lCMaDuVtHWeGsD9KQZj7REG2E,1071
19
+ e3cli/commands/download.py,sha256=Q01j8VGmdA8yjpdgA5j7aX6mdD4pNkW1rQlwoBOqPOI,3542
20
+ e3cli/commands/login.py,sha256=z3WnzQqcwOL94odoqK1q9Bj4fzZkVG9IqAaEZ0_vA2I,2379
21
+ e3cli/commands/logout.py,sha256=a3y0wvWuNazEJRApn-s72Lv3Gz8cJAYF-MO5FXMfGmY,406
22
+ e3cli/commands/schedule.py,sha256=lFMjbmeDAY3GxuL07qbyia_DqdQKpLv1iIwMWmyDi2c,1080
23
+ e3cli/commands/setup.py,sha256=M_8p70z-veagzsDz9D_q80X-VUfgyOmcDYt9dpZXr7s,4202
24
+ e3cli/commands/submit.py,sha256=CpOBU0J3Rr-XkZGHY_XzSR7Y7CggoRFCo_ig5OmZijE,2588
25
+ e3cli/commands/sync.py,sha256=Fjuba1bUDcn0Vml8WnD-Ys6bmsl052UGF0SxhQsKidc,3930
26
+ e3cli/scheduler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ e3cli/scheduler/cron.py,sha256=8O3ULg33hEYr_riqoSVA4ORYksD8Q_YrAFUrVS07j48,1631
28
+ e3cli/storage/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
+ e3cli/storage/db.py,sha256=XnlWzZ41gZWFw7Qyq48JdTsZlec_2t84yvd8-THsQY4,4535
30
+ e3cli/storage/models.py,sha256=lwe7ZosnZ7VSqH8zloiwfujAjNilGoL4GZ7GRSdevUg,513
31
+ e3cli/storage/tracking.py,sha256=k1_SiZTFu5cbNppVh6Q4pRNkoUI_N_xsVqB_nFiIGkM,326
32
+ e3cli-0.3.1.dist-info/METADATA,sha256=HliG1tPyk2bcJJ6LD6cFgS7v7GRGD5u-Z8n7v1Pv9Xc,10202
33
+ e3cli-0.3.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
34
+ e3cli-0.3.1.dist-info/entry_points.txt,sha256=WKOiVUme-Hc-JrXxnzEp7rwu7HWINvUXh3uk5ucg4ew,40
35
+ e3cli-0.3.1.dist-info/licenses/LICENSE,sha256=leNmCknvWNK9BAJr9lrNvGT0d9IiTwaDWdCUN1pKDvM,1075
36
+ e3cli-0.3.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ e3cli = e3cli.cli:app
@@ -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.