Skip to content

Commit 0409bb4

Browse files
committed
note generator v0.3.0
1 parent a26d02e commit 0409bb4

7 files changed

Lines changed: 727 additions & 127 deletions

File tree

‎.github/workflows/release.yml‎

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
name: Build & Release
2+
3+
# Triggered by pushing a version tag: git tag v1.0.0 && git push --tags
4+
on:
5+
push:
6+
tags:
7+
- "v*.*.*"
8+
workflow_dispatch: # allow manual runs from the Actions tab
9+
10+
permissions:
11+
contents: write # needed to create/upload release assets
12+
13+
jobs:
14+
build:
15+
strategy:
16+
fail-fast: false
17+
matrix:
18+
include:
19+
- os: ubuntu-22.04
20+
platform: linux
21+
artifact_name: AutoNote-linux-x86_64.AppImage
22+
23+
- os: windows-latest
24+
platform: windows
25+
artifact_name: AutoNote-windows-x86_64.zip
26+
27+
- os: macos-13 # Intel (x86_64)
28+
platform: macos-intel
29+
artifact_name: AutoNote-macos-x86_64.zip
30+
31+
- os: macos-latest # Apple Silicon (arm64)
32+
platform: macos-arm
33+
artifact_name: AutoNote-macos-arm64.zip
34+
35+
runs-on: ${{ matrix.os }}
36+
name: Build (${{ matrix.platform }})
37+
38+
steps:
39+
# ── Checkout ────────────────────────────────────────────────────────────
40+
- uses: actions/checkout@v4
41+
42+
# ── Python ──────────────────────────────────────────────────────────────
43+
- name: Set up Python 3.11
44+
uses: actions/setup-python@v5
45+
with:
46+
python-version: "3.11"
47+
cache: pip
48+
49+
# ── Install build-time dependencies ─────────────────────────────────────
50+
# GUI + OpenAI client are bundled. The heavy ML stack (torch, faster-whisper,
51+
# etc.) is NOT bundled; users run it in a separate Python environment.
52+
# The app auto-falls back to OpenAI Whisper API when faster-whisper is absent.
53+
- name: Install dependencies
54+
run: |
55+
pip install --upgrade pip
56+
pip install flet pyinstaller openai httpx
57+
58+
# ── Linux: install system libs required by flet/webkit ──────────────────
59+
- name: Install Linux system deps
60+
if: matrix.platform == 'linux'
61+
run: |
62+
sudo apt-get update -qq
63+
sudo apt-get install -y --no-install-recommends \
64+
libgtk-3-dev libwebkit2gtk-4.0-dev \
65+
libglib2.0-dev libgstreamer1.0-dev \
66+
libgstreamer-plugins-base1.0-dev \
67+
fuse libfuse2
68+
69+
# ── Build with PyInstaller ───────────────────────────────────────────────
70+
- name: Build (Linux / macOS)
71+
if: matrix.platform != 'windows'
72+
run: pyinstaller build.spec --noconfirm
73+
74+
- name: Build (Windows)
75+
if: matrix.platform == 'windows'
76+
run: pyinstaller build.spec --noconfirm
77+
shell: pwsh
78+
79+
# ── Linux: wrap dist/AutoNote directory into an AppImage ─────────────────
80+
- name: Create AppImage (Linux)
81+
if: matrix.platform == 'linux'
82+
run: |
83+
# Download appimagetool
84+
wget -q -O appimagetool \
85+
"https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
86+
chmod +x appimagetool
87+
88+
# Build AppDir layout
89+
mkdir -p AppDir/usr/bin AppDir/usr/share/applications AppDir/usr/share/icons/hicolor/256x256/apps
90+
91+
# Copy the PyInstaller output
92+
cp -r dist/AutoNote/* AppDir/usr/bin/
93+
94+
# Desktop entry
95+
cat > AppDir/AutoNote.desktop << 'EOF'
96+
[Desktop Entry]
97+
Name=AutoNote
98+
Comment=AI lecture note pipeline
99+
Exec=AutoNote
100+
Icon=AutoNote
101+
Type=Application
102+
Categories=Education;Science;
103+
Terminal=false
104+
EOF
105+
106+
cp AppDir/AutoNote.desktop AppDir/usr/share/applications/
107+
108+
# Placeholder icon (replace with real icon if available)
109+
if [ -f assets/icon.png ]; then
110+
cp assets/icon.png AppDir/usr/share/icons/hicolor/256x256/apps/AutoNote.png
111+
cp assets/icon.png AppDir/AutoNote.png
112+
else
113+
# Generate a minimal valid PNG so appimagetool doesn't fail
114+
python3 -c "
115+
import struct, zlib, base64
116+
# 1x1 cyan PNG
117+
png = base64.b64decode(
118+
'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==')
119+
open('AppDir/AutoNote.png','wb').write(png)
120+
open('AppDir/usr/share/icons/hicolor/256x256/apps/AutoNote.png','wb').write(png)
121+
"
122+
fi
123+
124+
# AppStream symlink expected by some tools
125+
ln -sf usr/bin/AutoNote AppDir/AppRun
126+
127+
# Package
128+
ARCH=x86_64 ./appimagetool AppDir AutoNote-linux-x86_64.AppImage
129+
130+
# ── Windows: zip the dist directory ─────────────────────────────────────
131+
- name: Package (Windows)
132+
if: matrix.platform == 'windows'
133+
run: Compress-Archive -Path dist\AutoNote -DestinationPath AutoNote-windows-x86_64.zip
134+
shell: pwsh
135+
136+
# ── macOS Intel: zip the .app bundle ─────────────────────────────────────
137+
- name: Package (macOS Intel)
138+
if: matrix.platform == 'macos-intel'
139+
run: |
140+
cd dist
141+
zip -r ../AutoNote-macos-x86_64.zip AutoNote.app
142+
143+
# ── macOS ARM: zip the .app bundle ───────────────────────────────────────
144+
- name: Package (macOS ARM)
145+
if: matrix.platform == 'macos-arm'
146+
run: |
147+
cd dist
148+
zip -r ../AutoNote-macos-arm64.zip AutoNote.app
149+
150+
# ── Upload artifact for debugging (optional) ─────────────────────────────
151+
- name: Upload build artifact
152+
uses: actions/upload-artifact@v4
153+
with:
154+
name: ${{ matrix.artifact_name }}
155+
path: ${{ matrix.artifact_name }}
156+
retention-days: 7
157+
158+
# ── Attach to GitHub Release ─────────────────────────────────────────────
159+
- name: Upload to Release
160+
uses: softprops/action-gh-release@v2
161+
with:
162+
files: ${{ matrix.artifact_name }}
163+
generate_release_notes: true
164+
draft: false
165+
prerelease: ${{ contains(github.ref_name, '-') }} # v1.0.0-beta → prerelease
166+
env:
167+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

‎.gitignore‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# ── API keys & credentials (never commit these) ───────────────────────────────
2+
canvas_token.txt
3+
canvas_credentials.txt
4+
openai_api.txt
5+
anthropic_key.txt
6+
*_api.txt
7+
*_key.txt
8+
*_token.txt
9+
*_secret.txt
10+
.env
11+
12+
# ── Downloaded course data ────────────────────────────────────────────────────
13+
85367/
14+
85377/
15+
85397/
16+
85427/
17+
manifest.json
18+
19+
# ── Python ────────────────────────────────────────────────────────────────────
20+
__pycache__/
21+
*.pyc
22+
*.pyo
23+
.pytest_cache/
24+
25+
# ── PyInstaller build output ─────────────────────────────────────────────────
26+
dist/
27+
build/
28+
*.spec.bak
29+
30+
# ── Misc ──────────────────────────────────────────────────────────────────────
31+
*.egg-info/
32+
.DS_Store

‎build.spec‎

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# build.spec — PyInstaller spec for AutoNote GUI
2+
#
3+
# Bundles gui.py with flet and all pipeline scripts as data files.
4+
# The heavy ML stack (torch, whisper, etc.) is NOT bundled; users must
5+
# set up a Python environment separately and configure it in Settings.
6+
7+
import sys
8+
from pathlib import Path
9+
10+
block_cipher = None
11+
HERE = Path(SPECPATH) # noqa: F821 — injected by PyInstaller
12+
13+
# All pipeline scripts shipped alongside the GUI
14+
pipeline_scripts = [
15+
(str(p), ".")
16+
for p in HERE.glob("*.py")
17+
if p.name not in ("gui.py", "build.spec")
18+
]
19+
20+
a = Analysis(
21+
[str(HERE / "gui.py")],
22+
pathex=[str(HERE)],
23+
binaries=[],
24+
datas=pipeline_scripts,
25+
hiddenimports=[
26+
"flet",
27+
"flet.fastapi",
28+
"flet_core",
29+
"flet_runtime",
30+
],
31+
hookspath=[],
32+
hooksconfig={},
33+
runtime_hooks=[],
34+
excludes=[
35+
# Exclude heavy ML libs — not needed in the GUI process
36+
"torch", "torchvision", "torchaudio",
37+
"faster_whisper", "transformers", "sentence_transformers",
38+
"faiss", "sklearn", "scipy", "numpy",
39+
"playwright",
40+
"canvasapi",
41+
],
42+
win_no_prefer_redirects=False,
43+
win_private_assemblies=False,
44+
cipher=block_cipher,
45+
noarchive=False,
46+
)
47+
48+
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) # noqa: F821
49+
50+
exe = EXE( # noqa: F821
51+
pyz,
52+
a.scripts,
53+
[],
54+
exclude_binaries=True,
55+
name="AutoNote",
56+
debug=False,
57+
bootloader_ignore_signals=False,
58+
strip=False,
59+
upx=True,
60+
console=False, # no terminal window
61+
disable_windowed_traceback=False,
62+
argv_emulation=False,
63+
target_arch=None,
64+
codesign_identity=None,
65+
entitlements_file=None,
66+
icon=None, # add icon path here if available
67+
)
68+
69+
coll = COLLECT( # noqa: F821
70+
exe,
71+
a.binaries,
72+
a.zipfiles,
73+
a.datas,
74+
strip=False,
75+
upx=True,
76+
upx_exclude=[],
77+
name="AutoNote",
78+
)
79+
80+
# macOS: wrap directory into a .app bundle
81+
if sys.platform == "darwin":
82+
app = BUNDLE( # noqa: F821
83+
coll,
84+
name="AutoNote.app",
85+
bundle_identifier="com.autonote.app",
86+
info_plist={
87+
"NSHighResolutionCapable": True,
88+
"LSMinimumSystemVersion": "12.0",
89+
},
90+
)

‎downloader.py‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,15 @@
3535

3636
# ── Configuration ──────────────────────────────────────────────────────────────
3737

38+
PROJECT_DIR = Path(__file__).parent
3839
CANVAS_URL = "https://canvas.nus.edu.sg"
39-
CANVAS_TOKEN = "21450~VhMGPzTKzT9wABF3VF76k8YE9LKUwfL93nU2LMc3xcfKPMhTkHJYaG3vZ34mfUke"
40+
_canvas_token_file = PROJECT_DIR / "canvas_token.txt"
41+
CANVAS_TOKEN = (
42+
_canvas_token_file.read_text().strip()
43+
if _canvas_token_file.exists() else
44+
os.environ.get("CANVAS_TOKEN", "")
45+
)
4046
PANOPTO_HOST = "mediaweb.ap.panopto.com"
41-
PROJECT_DIR = Path(__file__).parent
4247
MANIFEST_FILE = PROJECT_DIR / "manifest.json"
4348
SIZE_LIMIT = 1 * 1024 ** 3 # 1 GB
4449

0 commit comments

Comments
 (0)