mirror of
https://github.com/AquaMorph/dotfiles.git
synced 2026-10-22 04:45:34 +00:00
Compare commits
107
Commits
master
..
05da23ca10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05da23ca10 | ||
|
|
67c81eea85 | ||
|
|
ed99088c87 | ||
|
|
891ba27000 | ||
|
|
8d80823b37 | ||
|
|
021dcf7010 | ||
|
|
8fb6eb5f82 | ||
|
|
585818041a | ||
|
|
525f55487f | ||
|
|
f47e69f438 | ||
|
|
cbbcf06c30 | ||
|
|
5c13c8c3e7 | ||
|
|
3f6473ce17 | ||
|
|
04cf13ae99 | ||
|
|
4fdb6d90d8 | ||
|
|
73f74fe05f | ||
|
|
1a9d6a6a78 | ||
|
|
c31b2486e3 | ||
|
|
56581c54a7 | ||
|
|
67764b4618 | ||
|
|
c3778e57ad | ||
|
|
2b8a529878 | ||
|
|
f64ac274db | ||
|
|
3689a537d5 | ||
|
|
f2daba6dc2 | ||
|
|
84a52f1223 | ||
|
|
36c7ebb6b7 | ||
|
|
9d0a5e779a | ||
|
|
229e96127c | ||
|
|
a1a9081a2a | ||
|
|
d4663ad9cd | ||
|
|
3e41472454 | ||
|
|
0bb66b057d | ||
|
|
4f45baccc3 | ||
|
|
b1f2623edb | ||
|
|
27897b86b4 | ||
|
|
2ae891ebab | ||
|
|
1960e0ed57 | ||
|
|
ae8c52e486 | ||
|
|
a6cf4cda6f | ||
|
|
56eaf33632 | ||
|
|
3f1947edc7 | ||
|
|
fd0752043a | ||
|
|
1ff0c9b1a8 | ||
|
|
02c86e53e9 | ||
|
|
719ccb83a2 | ||
|
|
09f26252f3 | ||
|
|
d19c28941d | ||
|
|
c887881732 | ||
|
|
6cb9cc1489 | ||
|
|
5a219ab7df | ||
|
|
09bb4a172d | ||
|
|
81fd52a8f7 | ||
|
|
7f684f98f1 | ||
|
|
f5f8cda9f6 | ||
|
|
542f97f865 | ||
|
|
757b6a4b13 | ||
|
|
8612259d65 | ||
|
|
69dee58e8b | ||
|
|
2ebcd74c56 | ||
|
|
67f43a8916 | ||
|
|
fb976708d5 | ||
|
|
6d94e57f6b | ||
|
|
55f99a40d7 | ||
|
|
e0be3d5684 | ||
|
|
07e96633cc | ||
|
|
c9c93f30fb | ||
|
|
bf34de3dc6 | ||
|
|
d624a55769 | ||
|
|
3081b00255 | ||
|
|
3e712774d7 | ||
|
|
e151c2e7c3 | ||
|
|
9ec8007f55 | ||
|
|
9f5802f51a | ||
|
|
86359dcba6 | ||
|
|
0d4c49a6d3 | ||
|
|
3f4809b16a | ||
|
|
0c55be8e71 | ||
|
|
faef8da677 | ||
|
|
7a59efb6b0 | ||
|
|
b23d347e26 | ||
|
|
2649688ef4 | ||
|
|
97e7ed3e53 | ||
|
|
9d821052d5 | ||
|
|
5bb978bd20 | ||
|
|
ab6a2dd0a3 | ||
|
|
03fe12a280 | ||
|
|
0ab0cc9827 | ||
|
|
96f2fde330 | ||
|
|
f5fb2a8c51 | ||
|
|
2f9ecf7571 | ||
|
|
32ff6cb136 | ||
|
|
5ba6a04786 | ||
|
|
a5bc31398f | ||
|
|
d9be0f4e18 | ||
|
|
a7319f7d7f | ||
|
|
c5a369985b | ||
|
|
64111551bd | ||
|
|
2d44c01586 | ||
|
|
a4a0596b5e | ||
|
|
80a25470b3 | ||
|
|
11b9d48c24 | ||
|
|
c66b1209a8 | ||
|
|
2b00d85cfb | ||
|
|
126504d5f9 | ||
|
|
d9c5dcbea4 | ||
|
|
932a969e97 |
@@ -0,0 +1,8 @@
|
|||||||
|
Commits
|
||||||
|
## Commit Message Format
|
||||||
|
Follow conventional commits style (all lowercase).
|
||||||
|
- `feat(scope): description` - New feature
|
||||||
|
- `fix(scope): description` - Bug fix
|
||||||
|
- `refactor(scope): description` - Code refactoring
|
||||||
|
- `docs(scope): description` - Documentation changes
|
||||||
|
- Example: `feat(zsh): update dotfiles` or `fix(scripts): use correct pass entry`
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
home
|
||||||
-142
@@ -1,142 +0,0 @@
|
|||||||
i3/.config/i3/config
|
|
||||||
settings.conf
|
|
||||||
systemd/user/*/*
|
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
|
||||||
__pycache__/
|
|
||||||
*.py[cod]
|
|
||||||
*$py.class
|
|
||||||
|
|
||||||
# C extensions
|
|
||||||
*.so
|
|
||||||
|
|
||||||
# Distribution / packaging
|
|
||||||
.Python
|
|
||||||
build/
|
|
||||||
develop-eggs/
|
|
||||||
dist/
|
|
||||||
downloads/
|
|
||||||
eggs/
|
|
||||||
.eggs/
|
|
||||||
lib/
|
|
||||||
lib64/
|
|
||||||
parts/
|
|
||||||
sdist/
|
|
||||||
var/
|
|
||||||
wheels/
|
|
||||||
share/python-wheels/
|
|
||||||
*.egg-info/
|
|
||||||
.installed.cfg
|
|
||||||
*.egg
|
|
||||||
MANIFEST
|
|
||||||
|
|
||||||
# PyInstaller
|
|
||||||
# Usually these files are written by a python script from a template
|
|
||||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
||||||
*.manifest
|
|
||||||
*.spec
|
|
||||||
|
|
||||||
# Installer logs
|
|
||||||
pip-log.txt
|
|
||||||
pip-delete-this-directory.txt
|
|
||||||
|
|
||||||
# Unit test / coverage reports
|
|
||||||
htmlcov/
|
|
||||||
.tox/
|
|
||||||
.nox/
|
|
||||||
.coverage
|
|
||||||
.coverage.*
|
|
||||||
.cache
|
|
||||||
nosetests.xml
|
|
||||||
coverage.xml
|
|
||||||
*.cover
|
|
||||||
*.py,cover
|
|
||||||
.hypothesis/
|
|
||||||
.pytest_cache/
|
|
||||||
cover/
|
|
||||||
|
|
||||||
# Translations
|
|
||||||
*.mo
|
|
||||||
*.pot
|
|
||||||
|
|
||||||
# Django stuff:
|
|
||||||
*.log
|
|
||||||
local_settings.py
|
|
||||||
db.sqlite3
|
|
||||||
db.sqlite3-journal
|
|
||||||
|
|
||||||
# Flask stuff:
|
|
||||||
instance/
|
|
||||||
.webassets-cache
|
|
||||||
|
|
||||||
# Scrapy stuff:
|
|
||||||
.scrapy
|
|
||||||
|
|
||||||
# Sphinx documentation
|
|
||||||
docs/_build/
|
|
||||||
|
|
||||||
# PyBuilder
|
|
||||||
.pybuilder/
|
|
||||||
target/
|
|
||||||
|
|
||||||
# Jupyter Notebook
|
|
||||||
.ipynb_checkpoints
|
|
||||||
|
|
||||||
# IPython
|
|
||||||
profile_default/
|
|
||||||
ipython_config.py
|
|
||||||
|
|
||||||
# pyenv
|
|
||||||
# For a library or package, you might want to ignore these files since the code is
|
|
||||||
# intended to run in multiple environments; otherwise, check them in:
|
|
||||||
# .python-version
|
|
||||||
|
|
||||||
# pipenv
|
|
||||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
||||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
||||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
||||||
# install all needed dependencies.
|
|
||||||
#Pipfile.lock
|
|
||||||
|
|
||||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
||||||
__pypackages__/
|
|
||||||
|
|
||||||
# Celery stuff
|
|
||||||
celerybeat-schedule
|
|
||||||
celerybeat.pid
|
|
||||||
|
|
||||||
# SageMath parsed files
|
|
||||||
*.sage.py
|
|
||||||
|
|
||||||
# Environments
|
|
||||||
.env
|
|
||||||
.venv
|
|
||||||
env/
|
|
||||||
venv/
|
|
||||||
ENV/
|
|
||||||
env.bak/
|
|
||||||
venv.bak/
|
|
||||||
|
|
||||||
# Spyder project settings
|
|
||||||
.spyderproject
|
|
||||||
.spyproject
|
|
||||||
|
|
||||||
# Rope project settings
|
|
||||||
.ropeproject
|
|
||||||
|
|
||||||
# mkdocs documentation
|
|
||||||
/site
|
|
||||||
|
|
||||||
# mypy
|
|
||||||
.mypy_cache/
|
|
||||||
.dmypy.json
|
|
||||||
dmypy.json
|
|
||||||
|
|
||||||
# Pyre type checker
|
|
||||||
.pyre/
|
|
||||||
|
|
||||||
# pytype static type analyzer
|
|
||||||
.pytype/
|
|
||||||
|
|
||||||
# Cython debug symbols
|
|
||||||
cython_debug/
|
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
# AGENTS.md - Coding Guidelines for Agentic Operations
|
||||||
|
|
||||||
|
This repository is a personal dotfiles collection managed with [chezmoi](https://www.chezmoi.io). It contains configuration files, shell scripts, and Python utilities for system management.
|
||||||
|
|
||||||
|
## Build, Lint & Test Commands
|
||||||
|
|
||||||
|
### Running Scripts
|
||||||
|
- **Shell scripts**: `bash ./home/bin/executable_<script_name>.sh` or run directly if executable
|
||||||
|
- **Python scripts**: `python3 ./home/bin/<script_name>.py`
|
||||||
|
- **Install dependencies**: `pip install -r requirements.txt`
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
No formal test framework is present. Validation is done by:
|
||||||
|
- Running scripts manually with test inputs
|
||||||
|
- Checking for runtime errors (e.g., `python3 -m py_compile <file>` for syntax)
|
||||||
|
- Verifying command outputs match expected behavior
|
||||||
|
|
||||||
|
### Single Test/Script Execution
|
||||||
|
```bash
|
||||||
|
# Run a single Python script
|
||||||
|
python3 ./home/bin/i3-mouse.py
|
||||||
|
|
||||||
|
# Run a single shell script
|
||||||
|
bash ./home/bin/executable_update.sh
|
||||||
|
|
||||||
|
# Check Python syntax without running
|
||||||
|
python3 -m py_compile ./home/bin/homeassistant.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code Style Guidelines
|
||||||
|
|
||||||
|
### Python
|
||||||
|
|
||||||
|
#### Imports
|
||||||
|
- Use standard library imports first, then third-party imports, then local imports
|
||||||
|
- Import order: `os`, `sys`, `time` → `requests`, `i3ipc`, `pyautogui` → local modules
|
||||||
|
- Each import on its own line (avoid `import x, y, z`)
|
||||||
|
- Example:
|
||||||
|
```python
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import datetime
|
||||||
|
from requests import get, post
|
||||||
|
import json
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Naming Conventions
|
||||||
|
- **Functions**: `snake_case` (e.g., `getPoints()`, `pointsToDirection()`)
|
||||||
|
- **Classes**: `PascalCase` (e.g., `HomeAssistant`, `Direction`)
|
||||||
|
- **Constants**: `UPPER_SNAKE_CASE`
|
||||||
|
- **Private members**: prefix with underscore `_privateVar`
|
||||||
|
- Enums use `PascalCase` for class and `UPPER_SNAKE_CASE` for members
|
||||||
|
|
||||||
|
#### Formatting
|
||||||
|
- Use 4-space indentation (not tabs)
|
||||||
|
- Line length: Keep to reasonable length (~80-100 chars) where practical
|
||||||
|
- Shebang for executable scripts: `#!/usr/bin/env python3`
|
||||||
|
- Blank lines: 2 between top-level definitions, 1 between method definitions
|
||||||
|
|
||||||
|
#### Types & Documentation
|
||||||
|
- No type hints required (not present in codebase)
|
||||||
|
- Add docstring comments for classes and non-obvious functions
|
||||||
|
- Comment format: `# description` (no colons at end unless explaining)
|
||||||
|
- Example: `# Enum for mouse direction`
|
||||||
|
|
||||||
|
#### Error Handling
|
||||||
|
- Use `raise` for exceptions in API wrappers (e.g., `response.raise_for_status()`)
|
||||||
|
- Return `None` for optional/conditional operations
|
||||||
|
- Handle command availability checks: `if command -v <cmd> &> /dev/null`
|
||||||
|
|
||||||
|
### Shell Scripts
|
||||||
|
|
||||||
|
#### Shebang & Headers
|
||||||
|
- Start with: `#!/bin/bash`
|
||||||
|
- Add brief comment: `# Script purpose description`
|
||||||
|
|
||||||
|
#### Formatting
|
||||||
|
- Use 2-space indentation
|
||||||
|
- Quote variables: `"${variable}"` or `"$variable"`
|
||||||
|
- Use `function name { ... }` syntax for functions
|
||||||
|
|
||||||
|
#### Naming & Structure
|
||||||
|
- Function names: `snake_case`
|
||||||
|
- Variables: lowercase with underscores for clarity
|
||||||
|
- Check for command availability before use:
|
||||||
|
```bash
|
||||||
|
if command -v <cmd> &> /dev/null; then
|
||||||
|
<cmd> <args>
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Error Handling
|
||||||
|
- Use `set -e` to exit on error when appropriate
|
||||||
|
- Check command exit status: `if <command>; then ... fi`
|
||||||
|
- Redirect stderr appropriately: `2>/dev/null` or `2>&1`
|
||||||
|
|
||||||
|
#### chezmoi Templates
|
||||||
|
- Dotfiles use chezmoi's templating system
|
||||||
|
- Template syntax: `{{ }}` for variables (Chezmoi specific)
|
||||||
|
- File naming: `dot_` prefix for dotfiles (e.g., `dot_zshrc`)
|
||||||
|
- Executable scripts: `executable_` prefix
|
||||||
|
|
||||||
|
#### Comments
|
||||||
|
- Use `#` for all config file comments
|
||||||
|
- Keep comments concise and descriptive
|
||||||
|
|
||||||
|
## Repository Patterns
|
||||||
|
|
||||||
|
### Commit Message Format
|
||||||
|
- Before generating a commit, always consult @.agents/COMMITS.md for the required style.
|
||||||
|
|
||||||
|
#### Pushing Remotes
|
||||||
|
- **Do not push git repositories to remote unless explicitly instructed.**
|
||||||
|
|
||||||
|
### File Organization
|
||||||
|
- Shell scripts: `home/bin/executable_<name>.sh`
|
||||||
|
- Python scripts: `home/bin/<name>.py`
|
||||||
|
- Config files: `home/dot_config/<app>/` (following XDG spec)
|
||||||
|
- Dependencies: List in `requirements.txt`
|
||||||
|
|
||||||
|
## Key Dependencies
|
||||||
|
|
||||||
|
- **configparser** - Config file parsing
|
||||||
|
- **todoist-python** - Todoist API
|
||||||
|
- **tbapy** - TBA API for robotics
|
||||||
|
- **holidays** - Holiday detection
|
||||||
|
- **i3ipc** - i3 window manager control
|
||||||
|
- **pyautogui** - Mouse control
|
||||||
|
- **requests** - HTTP library
|
||||||
|
- **dateutil** - Date utilities
|
||||||
|
|
||||||
|
## Development Notes
|
||||||
|
|
||||||
|
- This is a personal configuration repository, not a library
|
||||||
|
- Scripts are system-level utilities and automation scripts
|
||||||
|
- No CI/CD pipeline present (manual validation)
|
||||||
|
- Target OS: Linux (Ubuntu/Fedora compatible)
|
||||||
|
- Python version: Python 3.x minimum
|
||||||
@@ -1,21 +1,65 @@
|
|||||||
# Dotfiles
|
# Dotfiles
|
||||||
|
|
||||||
A collection of config files and scripts for Fedora GNU/Linux.
|
A collection of config files and scripts for Fedora GNU/Linux and macOS.
|
||||||
|
|
||||||
## Install
|
## Linux installation
|
||||||
|
|
||||||
Run the following command to install
|
```bash
|
||||||
|
chezmoi init --apply git@github.com:AquaMorph/dotfiles.git
|
||||||
```sh
|
|
||||||
cd ~ && git clone git@github.com:AquaMorph/dotfiles.git && sh ~/dotfiles/install.sh
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Scripts
|
## macOS installation
|
||||||
|
|
||||||
### frc-photo-checklist.py
|
1. Install the Xcode Command Line Tools with `xcode-select --install`, then
|
||||||
|
install [Homebrew](https://brew.sh/) and follow its `brew shellenv`
|
||||||
|
instructions. Its default prefix is `/opt/homebrew` on Apple Silicon and
|
||||||
|
`/usr/local` on Intel Macs.
|
||||||
|
|
||||||
Python script to generate a Todoist checklist for taking photos at an FRC event.
|
2. Download the dotfiles without applying them, then install dependencies:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
python frc-photo-checklist.py [Event Key]
|
brew install chezmoi
|
||||||
|
chezmoi init git@github.com:AquaMorph/dotfiles.git
|
||||||
|
brew bundle --file="$(chezmoi source-path ~/.brewfile)"
|
||||||
|
```
|
||||||
|
|
||||||
|
The Brewfile includes chezmoi, Git, Emacs, Python, jq, pass, GnuPG, Brave Browser,
|
||||||
|
Alacritty, and Inconsolata. FFmpeg and Ollama are optional; install them separately
|
||||||
|
if needed.
|
||||||
|
|
||||||
|
3. Restore your password store to `~/.password-store` and import its GPG private
|
||||||
|
key from a secure backup before applying the dotfiles:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
gpg --import /path/to/private-key-backup.asc
|
||||||
|
```
|
||||||
|
|
||||||
|
If the store is kept in Git, clone it to `~/.password-store` using your
|
||||||
|
password-store repository URL. Verify that all required secrets can be
|
||||||
|
decrypted without printing their values:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pass show self-host/token/audible-activation-bytes >/dev/null
|
||||||
|
pass show self-host/token/aquaai >/dev/null
|
||||||
|
pass show self-host/token/todoist >/dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
`settings.conf` is rendered using `pass`, so applying it requires these
|
||||||
|
entries and the matching private key. Never commit keys or plaintext tokens.
|
||||||
|
|
||||||
|
4. Review and apply the dotfiles, then open a new terminal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
chezmoi diff
|
||||||
|
chezmoi apply
|
||||||
|
```
|
||||||
|
|
||||||
|
The generated `~/.config/settings.conf` is private (mode `0600`) and its
|
||||||
|
values are shell-quoted. Linux-only configuration and scripts are ignored on
|
||||||
|
macOS; shared shell, Git, and terminal configuration remains managed.
|
||||||
|
|
||||||
|
To install newly added macOS dependencies later:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
brew bundle --file="$(chezmoi source-path ~/.brewfile)"
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
|||||||
|
{{ if eq .chezmoi.os "darwin" -}}
|
||||||
|
# Linux desktop configuration
|
||||||
|
.config/g13
|
||||||
|
.config/gtk-3.0
|
||||||
|
.config/gtk-4.0
|
||||||
|
.config/hypr
|
||||||
|
.config/i3
|
||||||
|
.config/mako
|
||||||
|
.config/polybar
|
||||||
|
.config/quickshell
|
||||||
|
.config/rofi
|
||||||
|
.config/waybar
|
||||||
|
|
||||||
|
# Linux services and PipeWire configuration
|
||||||
|
.config/systemd
|
||||||
|
.config/wireplumber
|
||||||
|
.local/share/wireplumber
|
||||||
|
user/*.service
|
||||||
|
|
||||||
|
# Linux package installers and desktop startup scripts
|
||||||
|
bin/installers
|
||||||
|
bin/desktop
|
||||||
|
bin/system
|
||||||
|
bin/i3-mouse.py
|
||||||
|
bin/i3wm-config-gen.sh
|
||||||
|
bin/i3wm-for-window-gen.sh
|
||||||
|
bin/launch-stocks-tracker.py
|
||||||
|
bin/start-firefox.py
|
||||||
|
bin/start-brave.sh
|
||||||
|
|
||||||
|
# Linux hardware, screen locking, and NAS mounting
|
||||||
|
bin/get-mouse-battery.sh
|
||||||
|
bin/lock.sh
|
||||||
|
bin/toggle-graphics.sh
|
||||||
|
bin/trackpad-toggle.sh
|
||||||
|
bin/connect-nas.sh
|
||||||
|
|
||||||
|
# ALSA/PipeWire routing and Rofi prompts; keep portable audio utilities
|
||||||
|
bin/audio/audio-lib.sh
|
||||||
|
bin/audio/aquamix.sh
|
||||||
|
bin/audio/es8start.sh
|
||||||
|
bin/audio/es9start.sh
|
||||||
|
bin/audio/es9stop.sh
|
||||||
|
bin/audio/system-start-audio.sh
|
||||||
|
bin/audio/synth-power-prompt.sh
|
||||||
|
|
||||||
|
# Wine-based Adobe DNG conversion with GNU date
|
||||||
|
bin/video/cr3todng.sh
|
||||||
|
{{ else -}}
|
||||||
|
# Homebrew dependencies are only managed on macOS.
|
||||||
|
.brewfile
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
|
{{ if ne .chezmoi.os "darwin" -}}
|
||||||
|
.config/karabiner
|
||||||
|
{{ end -}}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
AquaAI/glm-4.7-flash
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
openai/gpt-5.6-luna
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
AquaAI
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
Be as concise as possible.
|
||||||
|
Be extremely accurate.
|
||||||
|
Recommend things I would not realize I would benefit from.
|
||||||
|
Call out my misconceptions and tell me when I am wrong.
|
||||||
|
For personal matters {{ template "prompts/agent-name" . }} is encouraging but brutally honest.
|
||||||
|
Never sycophantic.
|
||||||
|
Do not use em dashes. If an em dash would normally appear, use a comma for continuing thoughts or a period if it should be a separate sentence.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
You are an AI assistant named {{ template "prompts/agent-name" . }}.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Scripts
|
||||||
|
|
||||||
|
## AquaAI
|
||||||
|
|
||||||
|
AquaAI is bash script that interacts with OpenAI and Ollama APIs to enable terminal based interaction with LLMs.
|
||||||
|
|
||||||
|
## connect-nas.sh
|
||||||
|
|
||||||
|
Connect to long storage NAS.
|
||||||
|
|
||||||
|
## convert-mp4-to-resolve.sh
|
||||||
|
|
||||||
|
Converts mp4 video files to a video format where the audio works with the linux version of Davinci Resolve.
|
||||||
|
|
||||||
|
## frc-photo-checklist.py
|
||||||
|
|
||||||
|
Python script to generate a Todoist checklist for taking photos at an FRC event.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
python frc-photo-checklist.py [Event Key]
|
||||||
|
```
|
||||||
|
|
||||||
|
## get-mouse-battery.sh
|
||||||
|
|
||||||
|
Prints out the battery percentage of a mouse and if it is charging.
|
||||||
|
|
||||||
|
## openai-usage.sh
|
||||||
|
|
||||||
|
Shows the remaining 5-hour and weekly ChatGPT Codex allowances using the current
|
||||||
|
OpenCode or Codex CLI login. Run `openai-usage --watch` to refresh every minute,
|
||||||
|
or `openai-usage --json` for machine-readable output.
|
||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
-20
@@ -22,15 +22,6 @@ function fixPulse() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Start up programs that use audio.
|
|
||||||
function launchi3() {
|
|
||||||
if [ -z "$skipi3" ]; then
|
|
||||||
echo Opening i3wm sound workspaces
|
|
||||||
sleep .1 && i3-msg 'workspace 5; exec brave-browser'
|
|
||||||
#sleep 5.1 && python ~/bin/start-firefox.py
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Set up sinks.
|
# Set up sinks.
|
||||||
function setupSinks() {
|
function setupSinks() {
|
||||||
pactl set-default-sink speakers
|
pactl set-default-sink speakers
|
||||||
@@ -66,23 +57,12 @@ function restartWireplumber() {
|
|||||||
systemctl --user restart wireplumber
|
systemctl --user restart wireplumber
|
||||||
}
|
}
|
||||||
|
|
||||||
# arg parser
|
|
||||||
for arg in "$@"
|
|
||||||
do
|
|
||||||
# Skip commands for i3wm
|
|
||||||
if [[ $arg == *"-s"* ]]; then
|
|
||||||
skipi3=true
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Wire sinks
|
# Wire sinks
|
||||||
setupSinks
|
setupSinks
|
||||||
|
|
||||||
# Eurorack audio interface
|
# Eurorack audio interface
|
||||||
sh ~/bin/audio/es9start.sh
|
sh ~/bin/audio/es9start.sh
|
||||||
|
|
||||||
launchi3
|
|
||||||
systemctl --user restart polybar
|
systemctl --user restart polybar
|
||||||
sleep 5
|
sleep 5
|
||||||
restartWireplumber
|
restartWireplumber
|
||||||
|
|
||||||
Executable → Regular
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Start the systemd-managed Quickshell bar in the current graphical session.
|
||||||
|
|
||||||
|
if ! command -v qs &> /dev/null; then
|
||||||
|
if [ "${XDG_SESSION_TYPE}" = "x11" ]; then
|
||||||
|
~/bin/desktop/polybar-start.sh
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${XDG_SESSION_TYPE}" = "x11" ]; then
|
||||||
|
systemctl --user unset-environment WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE
|
||||||
|
systemctl --user set-environment QT_QPA_PLATFORM=xcb
|
||||||
|
else
|
||||||
|
systemctl --user set-environment QT_QPA_PLATFORM=wayland
|
||||||
|
fi
|
||||||
|
systemctl --user import-environment DISPLAY XAUTHORITY WAYLAND_DISPLAY XDG_SESSION_TYPE XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE I3SOCK
|
||||||
|
if [ "$(hostname)" = "desktop" ]; then
|
||||||
|
systemctl --user set-environment QUICKSHELL_BAR_SCREEN=DP-2
|
||||||
|
else
|
||||||
|
systemctl --user unset-environment QUICKSHELL_BAR_SCREEN
|
||||||
|
fi
|
||||||
|
systemctl --user restart quickshell-bar.service
|
||||||
Executable → Regular
Executable → Regular
+7
-4
@@ -74,7 +74,7 @@
|
|||||||
#
|
#
|
||||||
# export AQUAAI_OLLAMA_URL='192.168.1.156:11434'
|
# export AQUAAI_OLLAMA_URL='192.168.1.156:11434'
|
||||||
#
|
#
|
||||||
ollama_url=${AQUAAI_OLLAMA_URL:='https://ai.aquamorph.com'}
|
ollama_url=${AQUAAI_OLLAMA_URL:='https://ai.aquamorph.com/api'}
|
||||||
#
|
#
|
||||||
# Set the default model.
|
# Set the default model.
|
||||||
#
|
#
|
||||||
@@ -178,6 +178,9 @@ function set_better_conversions() {
|
|||||||
system_prompt+=" For personal matters ${AGENT_NAME} is encouraging"
|
system_prompt+=" For personal matters ${AGENT_NAME} is encouraging"
|
||||||
system_prompt+=' but brutally honest.'
|
system_prompt+=' but brutally honest.'
|
||||||
system_prompt+=' Never sycophantic.'
|
system_prompt+=' Never sycophantic.'
|
||||||
|
system_prompt+=' Do not use em dashes. If an em dash would normally appear,'
|
||||||
|
system_prompt+=' use a comma for continuing thoughts or a period if it'
|
||||||
|
system_prompt+=' should be a separate sentence.'
|
||||||
}
|
}
|
||||||
|
|
||||||
# Set the formatting for all reponses.
|
# Set the formatting for all reponses.
|
||||||
@@ -369,9 +372,9 @@ function check_requirements() {
|
|||||||
function get_models() {
|
function get_models() {
|
||||||
local model_path=''
|
local model_path=''
|
||||||
if [ "${openai_api}" == true ]; then
|
if [ "${openai_api}" == true ]; then
|
||||||
model_path='/api/models'
|
model_path='/models'
|
||||||
else
|
else
|
||||||
model_path='/api/tags'
|
model_path='/tags'
|
||||||
fi
|
fi
|
||||||
curl "${CURL_FLAGS[@]}" "${OLLAMA_URL}${model_path}"
|
curl "${CURL_FLAGS[@]}" "${OLLAMA_URL}${model_path}"
|
||||||
}
|
}
|
||||||
@@ -801,7 +804,7 @@ function chat() {
|
|||||||
local filter=''
|
local filter=''
|
||||||
if [ "${openai_api}" == true ]; then
|
if [ "${openai_api}" == true ]; then
|
||||||
flags+=(-H "Content-Type: application/json")
|
flags+=(-H "Content-Type: application/json")
|
||||||
chat_path='/api/chat/completions'
|
chat_path='/chat/completions'
|
||||||
filter='.choices[].delta.content // empty'
|
filter='.choices[].delta.content // empty'
|
||||||
else
|
else
|
||||||
chat_path='/api/chat'
|
chat_path='/api/chat'
|
||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
@@ -0,0 +1,196 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Show the remaining ChatGPT Codex rate limits for the current OpenAI login.
|
||||||
|
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
usage_url="${OPENAI_USAGE_URL:-https://chatgpt.com/backend-api/wham/usage}"
|
||||||
|
auth_file="${OPENAI_AUTH_FILE:-}"
|
||||||
|
output_format="text"
|
||||||
|
watch_interval=""
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: openai-usage [--json] [--watch [SECONDS]]
|
||||||
|
|
||||||
|
Show the remaining Codex allowance for the OpenAI account logged into OpenCode
|
||||||
|
or the Codex CLI. The default watch interval is 60 seconds.
|
||||||
|
|
||||||
|
Environment:
|
||||||
|
OPENAI_AUTH_FILE Override the OAuth credential file
|
||||||
|
OPENAI_USAGE_URL Override the ChatGPT usage endpoint
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail {
|
||||||
|
printf 'openai-usage: %s\n' "$1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function require_command {
|
||||||
|
command -v "$1" &>/dev/null || fail "required command not found: $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
function find_auth_file {
|
||||||
|
local opencode_auth
|
||||||
|
local codex_auth
|
||||||
|
|
||||||
|
if [[ -n "$auth_file" ]]; then
|
||||||
|
[[ -r "$auth_file" ]] || fail "cannot read auth file: $auth_file"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
opencode_auth="${XDG_DATA_HOME:-$HOME/.local/share}/opencode/auth.json"
|
||||||
|
codex_auth="${CODEX_HOME:-$HOME/.codex}/auth.json"
|
||||||
|
|
||||||
|
if [[ -r "$opencode_auth" ]]; then
|
||||||
|
auth_file="$opencode_auth"
|
||||||
|
elif [[ -r "$codex_auth" ]]; then
|
||||||
|
auth_file="$codex_auth"
|
||||||
|
else
|
||||||
|
fail "no OpenCode or Codex login found; run 'opencode auth login' first"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function human_duration {
|
||||||
|
local total_seconds=$1
|
||||||
|
local days hours minutes
|
||||||
|
|
||||||
|
(( total_seconds < 0 )) && total_seconds=0
|
||||||
|
days=$((total_seconds / 86400))
|
||||||
|
hours=$(((total_seconds % 86400) / 3600))
|
||||||
|
minutes=$(((total_seconds % 3600) / 60))
|
||||||
|
|
||||||
|
if (( days > 0 )); then
|
||||||
|
printf '%dd %dh' "$days" "$hours"
|
||||||
|
elif (( hours > 0 )); then
|
||||||
|
printf '%dh %dm' "$hours" "$minutes"
|
||||||
|
else
|
||||||
|
printf '%dm' "$minutes"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function format_reset_time {
|
||||||
|
local reset_at=$1
|
||||||
|
|
||||||
|
if date --date="@$reset_at" '+%a %b %-d, %-I:%M %p' 2>/dev/null; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# BSD date fallback.
|
||||||
|
date -r "$reset_at" '+%a %b %e, %l:%M %p' 2>/dev/null || printf '%s' "$reset_at"
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_window {
|
||||||
|
local label=$1
|
||||||
|
local window=$2
|
||||||
|
local used_percent reset_after reset_at remaining
|
||||||
|
|
||||||
|
used_percent=$(jq -r '.used_percent // 0' <<<"$window")
|
||||||
|
reset_after=$(jq -r '.reset_after_seconds // 0 | floor' <<<"$window")
|
||||||
|
reset_at=$(jq -r '.reset_at // 0 | floor' <<<"$window")
|
||||||
|
remaining=$(jq -nr --argjson used "$used_percent" '100 - $used | if . < 0 then 0 else . end')
|
||||||
|
|
||||||
|
printf '%-8s %6g%% left resets in %-8s (%s)\n' \
|
||||||
|
"$label:" "$remaining" "$(human_duration "$reset_after")" "$(format_reset_time "$reset_at")"
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetch_usage {
|
||||||
|
local access_token account_id raw_response status body
|
||||||
|
|
||||||
|
access_token=$(jq -r \
|
||||||
|
'.openai.access // .tokens.access_token // .access_token // empty' \
|
||||||
|
"$auth_file") || fail "invalid JSON in auth file: $auth_file"
|
||||||
|
account_id=$(jq -r \
|
||||||
|
'.openai.accountId // .tokens.account_id // .account_id // empty' \
|
||||||
|
"$auth_file") || fail "invalid JSON in auth file: $auth_file"
|
||||||
|
|
||||||
|
[[ -n "$access_token" ]] || fail "no OpenAI OAuth token found in $auth_file"
|
||||||
|
|
||||||
|
raw_response=$(curl --silent --show-error \
|
||||||
|
--header "Authorization: Bearer $access_token" \
|
||||||
|
--header "ChatGPT-Account-Id: $account_id" \
|
||||||
|
--header 'Accept: application/json' \
|
||||||
|
--write-out $'\n%{http_code}' \
|
||||||
|
"$usage_url") || fail "could not contact OpenAI"
|
||||||
|
|
||||||
|
status=${raw_response##*$'\n'}
|
||||||
|
body=${raw_response%$'\n'*}
|
||||||
|
|
||||||
|
case "$status" in
|
||||||
|
200) ;;
|
||||||
|
401|403) fail "OpenAI login expired; run 'opencode auth login' again" ;;
|
||||||
|
*) fail "OpenAI returned HTTP $status" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
jq -e '.rate_limit' <<<"$body" >/dev/null || fail "unexpected response from OpenAI"
|
||||||
|
printf '%s\n' "$body"
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_usage {
|
||||||
|
local response=$1
|
||||||
|
local plan primary secondary
|
||||||
|
|
||||||
|
if [[ "$output_format" == "json" ]]; then
|
||||||
|
jq '{
|
||||||
|
plan: .plan_type,
|
||||||
|
allowed: .rate_limit.allowed,
|
||||||
|
limit_reached: .rate_limit.limit_reached,
|
||||||
|
five_hour: (.rate_limit.primary_window | . + {
|
||||||
|
remaining_percent: ([100 - .used_percent, 0] | max)
|
||||||
|
}),
|
||||||
|
weekly: (.rate_limit.secondary_window | . + {
|
||||||
|
remaining_percent: ([100 - .used_percent, 0] | max)
|
||||||
|
})
|
||||||
|
}' <<<"$response"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
plan=$(jq -r '.plan_type // "unknown"' <<<"$response")
|
||||||
|
primary=$(jq -c '.rate_limit.primary_window' <<<"$response")
|
||||||
|
secondary=$(jq -c '.rate_limit.secondary_window' <<<"$response")
|
||||||
|
|
||||||
|
printf 'OpenAI Codex usage (%s)\n' "$plan"
|
||||||
|
print_window '5-hour' "$primary"
|
||||||
|
print_window 'Weekly' "$secondary"
|
||||||
|
}
|
||||||
|
|
||||||
|
while (( $# > 0 )); do
|
||||||
|
case "$1" in
|
||||||
|
--json)
|
||||||
|
output_format="json"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--watch)
|
||||||
|
watch_interval=60
|
||||||
|
if [[ ${2:-} =~ ^[1-9][0-9]*$ ]]; then
|
||||||
|
watch_interval=$2
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage >&2
|
||||||
|
fail "unknown argument: $1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
require_command curl
|
||||||
|
require_command jq
|
||||||
|
find_auth_file
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
if ! response=$(fetch_usage); then
|
||||||
|
[[ -n "$watch_interval" ]] || exit 1
|
||||||
|
sleep "$watch_interval"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
print_usage "$response"
|
||||||
|
|
||||||
|
[[ -n "$watch_interval" ]] || break
|
||||||
|
sleep "$watch_interval"
|
||||||
|
done
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Restore Brave and place its windows after they finish opening.
|
||||||
|
|
||||||
|
preferences="$HOME/.config/BraveSoftware/Brave-Browser/Default/Preferences"
|
||||||
|
|
||||||
|
function enable_session_restore {
|
||||||
|
if [ ! -f "$preferences" ] || ! command -v jq &> /dev/null; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
temp_file="$(mktemp "${preferences}.XXXXXX")"
|
||||||
|
if jq '.session.restore_on_startup = 1 | .profile.exit_type = "Normal"' \
|
||||||
|
"$preferences" > "$temp_file"; then
|
||||||
|
mv "$temp_file" "$preferences"
|
||||||
|
else
|
||||||
|
rm -f "$temp_file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_session_restore
|
||||||
|
|
||||||
|
if [ -n "$HYPRLAND_INSTANCE_SIGNATURE" ]; then
|
||||||
|
brave-browser --restore-last-session &
|
||||||
|
|
||||||
|
# Signal starts after Brave and can steal focus while its window is mapping.
|
||||||
|
# Wait for both startup windows, then make Brave the final focused window.
|
||||||
|
for _ in {1..80}; do
|
||||||
|
sleep 0.25
|
||||||
|
if hyprctl clients -j | jq -e '
|
||||||
|
any(.[]; .class == "brave-browser") and
|
||||||
|
any(.[]; .class == "org.signal.Signal")
|
||||||
|
' > /dev/null; then
|
||||||
|
sleep 0.5
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
hyprctl eval \
|
||||||
|
'hl.dispatch(hl.dsp.focus({ workspace = "1" }))' > /dev/null
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
i3-msg 'workspace 9; append_layout ~/.config/i3/brave-workspace-9.json; workspace 5'
|
||||||
|
brave-browser --restore-last-session &
|
||||||
|
|
||||||
|
# Brave creates restored windows asynchronously and after startup focus has moved.
|
||||||
|
for _ in {1..20}; do
|
||||||
|
sleep 0.5
|
||||||
|
i3-msg '[class="^Brave-browser$" workspace="^(?!9$).*"] move to workspace 5' \
|
||||||
|
> /dev/null
|
||||||
|
done
|
||||||
Executable → Regular
Executable → Regular
Executable → Regular
+53
-12
@@ -2,6 +2,14 @@
|
|||||||
|
|
||||||
# This script is a catch all program updater.
|
# This script is a catch all program updater.
|
||||||
|
|
||||||
|
# Chezmoi Updater
|
||||||
|
function chezmoiUpdate {
|
||||||
|
if command -v chezmoi &> /dev/null; then
|
||||||
|
echo Updating chezmoi dotfiles...
|
||||||
|
chezmoi update
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# DNF Updater
|
# DNF Updater
|
||||||
function dnfUpdate {
|
function dnfUpdate {
|
||||||
if command -v dnf &> /dev/null; then
|
if command -v dnf &> /dev/null; then
|
||||||
@@ -14,8 +22,7 @@ function dnfUpdate {
|
|||||||
function aptUpdate {
|
function aptUpdate {
|
||||||
if command -v apt &> /dev/null; then
|
if command -v apt &> /dev/null; then
|
||||||
echo Updating APT...
|
echo Updating APT...
|
||||||
sudo apt update
|
sudo apt update && sudo apt upgrade
|
||||||
sudo apt upgrade
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,14 +30,32 @@ function aptUpdate {
|
|||||||
function flatpakUpdate {
|
function flatpakUpdate {
|
||||||
if command -v flatpak &> /dev/null; then
|
if command -v flatpak &> /dev/null; then
|
||||||
echo Updating Flatpak...
|
echo Updating Flatpak...
|
||||||
flatpak uninstall --unused
|
flatpak uninstall --unused && flatpak update
|
||||||
flatpak update
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Appimage Updater
|
# Appimage Updater
|
||||||
function appimageUpdate {
|
function appimageUpdate {
|
||||||
|
if command -v am &> /dev/null; then
|
||||||
|
echo Updating AppImages...
|
||||||
am update
|
am update
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Homebrew Updater
|
||||||
|
function brewUpdate {
|
||||||
|
if command -v brew &> /dev/null; then
|
||||||
|
echo Updating Homebrew...
|
||||||
|
brew update && brew upgrade
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Pass Repository Updater
|
||||||
|
function passUpdate {
|
||||||
|
if [ -d "$HOME/.password-store/.git" ] && [ -d "$HOME/.password-store" ]; then
|
||||||
|
echo Updating pass repository...
|
||||||
|
git -C "$HOME/.password-store" pull
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Checks if a program is installed and if it is runs an updater script
|
# Checks if a program is installed and if it is runs an updater script
|
||||||
@@ -55,12 +80,28 @@ function manualUpdate {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
dnfUpdate
|
update_failed=0
|
||||||
aptUpdate
|
|
||||||
echo ''
|
|
||||||
flatpakUpdate
|
|
||||||
echo ''
|
|
||||||
appimageUpdate
|
|
||||||
echo ''
|
|
||||||
manualUpdate
|
|
||||||
|
|
||||||
|
# Report failures while allowing the remaining updaters to run.
|
||||||
|
function run_updater {
|
||||||
|
if ! "$1"; then
|
||||||
|
echo "Updater failed: $1" >&2
|
||||||
|
update_failed=1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
run_updater chezmoiUpdate
|
||||||
|
echo ''
|
||||||
|
run_updater brewUpdate
|
||||||
|
run_updater dnfUpdate
|
||||||
|
run_updater aptUpdate
|
||||||
|
echo ''
|
||||||
|
run_updater flatpakUpdate
|
||||||
|
echo ''
|
||||||
|
run_updater appimageUpdate
|
||||||
|
echo ''
|
||||||
|
run_updater manualUpdate
|
||||||
|
echo ''
|
||||||
|
run_updater passUpdate
|
||||||
|
|
||||||
|
exit "$update_failed"
|
||||||
@@ -7,15 +7,18 @@ import datetime as dt
|
|||||||
import re
|
import re
|
||||||
import operator
|
import operator
|
||||||
import os
|
import os
|
||||||
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
import tbapy
|
import tbapy
|
||||||
import todoist
|
from todoist_api_python.api import TodoistAPI
|
||||||
|
|
||||||
# getProjectID() returns the project id that matches the name given.
|
# getProjectID() returns the project id that matches the name given.
|
||||||
def getProjectID(api, name):
|
def getProjectID(api, name):
|
||||||
for project in api.state['projects']:
|
projectPages = api.get_projects()
|
||||||
if project['name'] == name:
|
for projectList in projectPages:
|
||||||
return project['id']
|
for project in projectList:
|
||||||
|
if project.name == name:
|
||||||
|
return project.id
|
||||||
print('Error: No project with the name {} found'.format(name))
|
print('Error: No project with the name {} found'.format(name))
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
@@ -25,10 +28,12 @@ def getChecklistName(evemt):
|
|||||||
|
|
||||||
# getEventListID() returns the id of the checklist for the event and if there is none
|
# getEventListID() returns the id of the checklist for the event and if there is none
|
||||||
# returns -1.
|
# returns -1.
|
||||||
def getEventListID(items, event):
|
def getEventListID(api, projectID, event):
|
||||||
for item in items:
|
taskPages = api.get_tasks(project_id=projectID)
|
||||||
if item['content'] == getChecklistName(event):
|
for taskLists in taskPages:
|
||||||
return item['id']
|
for task in taskLists:
|
||||||
|
if task.content == getChecklistName(event):
|
||||||
|
return task.id
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
# matchToTeamList() converts a match to two lists of teams
|
# matchToTeamList() converts a match to two lists of teams
|
||||||
@@ -37,10 +42,10 @@ def matchToTeamList(match):
|
|||||||
|
|
||||||
# createChecklistItem() creates a checklist item of the highest priority.
|
# createChecklistItem() creates a checklist item of the highest priority.
|
||||||
def createChecklistItem(name, api, projectID, item, date):
|
def createChecklistItem(name, api, projectID, item, date):
|
||||||
return api.items.add(name,
|
return api.add_task(name,
|
||||||
project_id=projectID,
|
project_id=projectID,
|
||||||
parent_id=item['id'],
|
parent_id=item.id,
|
||||||
date_string=date,
|
due_string=date,
|
||||||
priority=4)
|
priority=4)
|
||||||
|
|
||||||
# createPhotoChecklistItem() creates a checklist item that requires a photo.
|
# createPhotoChecklistItem() creates a checklist item that requires a photo.
|
||||||
@@ -50,10 +55,10 @@ def createPhotoChecklistItem(name, api, projectID, item, date):
|
|||||||
|
|
||||||
# createPitList() creates a checklist for taking photos of a teams pit.
|
# createPitList() creates a checklist for taking photos of a teams pit.
|
||||||
def createPitList(api, teams, projectID, checklist, date):
|
def createPitList(api, teams, projectID, checklist, date):
|
||||||
item = api.items.add('**Take** Pit Photos',
|
item = api.add_task('**Take** Pit Photos',
|
||||||
project_id=projectID,
|
project_id=projectID,
|
||||||
parent_id=checklist['id'],
|
parent_id=checklist.id,
|
||||||
date_string=date,
|
due_string=date,
|
||||||
priority=3)
|
priority=3)
|
||||||
for team in teams:
|
for team in teams:
|
||||||
createChecklistItem('Pit photo of **{}** {}'.format(team['team_number'], team['nickname']),
|
createChecklistItem('Pit photo of **{}** {}'.format(team['team_number'], team['nickname']),
|
||||||
@@ -61,10 +66,10 @@ def createPitList(api, teams, projectID, checklist, date):
|
|||||||
|
|
||||||
# createGroupsList() creates a checklist of the different groups of volenteers.
|
# createGroupsList() creates a checklist of the different groups of volenteers.
|
||||||
def createGroupsList(api, projectID, checklist, date):
|
def createGroupsList(api, projectID, checklist, date):
|
||||||
item = api.items.add('Groups',
|
item = api.add_task('Groups',
|
||||||
project_id=projectID,
|
project_id=projectID,
|
||||||
parent_id=checklist['id'],
|
parent_id=checklist.id,
|
||||||
date_string=date,
|
due_string=date,
|
||||||
priority=3)
|
priority=3)
|
||||||
groups = ['Judges', 'Robot Inspectors', 'Referees', 'Safety Inspectors',
|
groups = ['Judges', 'Robot Inspectors', 'Referees', 'Safety Inspectors',
|
||||||
'Field Reset', 'Queuers', 'CSAs', 'VC and Pit Admin']
|
'Field Reset', 'Queuers', 'CSAs', 'VC and Pit Admin']
|
||||||
@@ -73,41 +78,39 @@ def createGroupsList(api, projectID, checklist, date):
|
|||||||
|
|
||||||
# createWinnersList() creates a checklist of the winners of an event.
|
# createWinnersList() creates a checklist of the winners of an event.
|
||||||
def createWinnersList(api, projectID, checklist, date):
|
def createWinnersList(api, projectID, checklist, date):
|
||||||
item = api.items.add('Winners',
|
item = api.add_task('Winners',
|
||||||
project_id=projectID,
|
project_id=projectID,
|
||||||
parent_id=checklist['id'],
|
parent_id=checklist.id,
|
||||||
date_string=date,
|
due_string=date,
|
||||||
priority=3)
|
priority=3)
|
||||||
groups = ['Chairman\'s award', 'Engineering Inspiration', 'Rookie All-Star', 'Winning Alliance',
|
groups = ['Impact', 'Engineering Inspiration', 'Rookie All-Star', 'Winning Alliance',
|
||||||
'Winning Team 1', 'Winning Team 2', 'Winning Team 3']
|
'Winning Team 1', 'Winning Team 2', 'Winning Team 3']
|
||||||
for group in groups:
|
for group in groups:
|
||||||
createPhotoChecklistItem(group, api, projectID, item, date)
|
createPhotoChecklistItem(group, api, projectID, item, date)
|
||||||
|
|
||||||
# createRobotList() creates a checklist for taking photos of a team's robot.
|
# createRobotList() creates a checklist for taking photos of a team's robot.
|
||||||
def createRobotList(api, teams, projectID, checklist, date):
|
def createRobotList(api, teams, projectID, checklist, date):
|
||||||
item = api.items.add('**Take** Robot Photos',
|
item = api.add_task('**Take** Robot Photos',
|
||||||
project_id=projectID,
|
project_id=projectID,
|
||||||
parent_id=checklist['id'],
|
parent_id=checklist.id,
|
||||||
date_string=date,
|
due_string=date,
|
||||||
priority=3)
|
priority=3)
|
||||||
for team in teams:
|
for team in teams:
|
||||||
createChecklistItem('Robot photo of **{}** {}'.format(team['team_number'], team['nickname']),
|
createChecklistItem('Robot photo of **{}** {}'.format(team['team_number'], team['nickname']),
|
||||||
api, projectID, item, date)
|
api, projectID, item, date)
|
||||||
|
|
||||||
# Parse settings config
|
# Parse settings config
|
||||||
configString = '[Settings]\n' + open('../settings.conf').read()
|
configString = '[Settings]\n' + open('./.config/settings.conf').read()
|
||||||
configParser = configparser.RawConfigParser()
|
configParser = configparser.RawConfigParser()
|
||||||
configParser.read_string(configString)
|
configParser.read_string(configString)
|
||||||
|
|
||||||
# Load needed credentials
|
# Load needed credentials
|
||||||
tbaKey = configParser.get('Settings', 'TBAKey')
|
tbaKey = configParser.get('Settings', 'TBAKey')
|
||||||
todoistToken = configParser.get('Settings', 'TodoistToken')
|
todoistToken = shlex.split(configParser.get('Settings', 'TodoistToken'))[0]
|
||||||
|
|
||||||
# Setup Todoist
|
# Setup Todoist
|
||||||
api = todoist.TodoistAPI(todoistToken)
|
api = TodoistAPI(todoistToken)
|
||||||
api.sync()
|
|
||||||
projectID = getProjectID(api, '🤖 Robotics')
|
projectID = getProjectID(api, '🤖 Robotics')
|
||||||
items = api.state['items']
|
|
||||||
|
|
||||||
# Setup the Blue Alliance
|
# Setup the Blue Alliance
|
||||||
tba = tbapy.TBA(tbaKey)
|
tba = tbapy.TBA(tbaKey)
|
||||||
@@ -128,12 +131,12 @@ def firstMatch(team, matches):
|
|||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
# Check if list already exists
|
# Check if list already exists
|
||||||
eventListID = getEventListID(items, event)
|
eventListID = getEventListID(api, projectID, event)
|
||||||
if eventListID == -1:
|
if eventListID == -1:
|
||||||
# Create checklist
|
# Create checklist
|
||||||
checklist = api.items.add(getChecklistName(event),
|
checklist = api.add_task(getChecklistName(event),
|
||||||
project_id=projectID,
|
project_id=projectID,
|
||||||
date_string=day2,
|
due_string=day2,
|
||||||
priority=2)
|
priority=2)
|
||||||
# Setup
|
# Setup
|
||||||
createPitList(api, teams, projectID, checklist, setupDay)
|
createPitList(api, teams, projectID, checklist, setupDay)
|
||||||
@@ -170,4 +173,3 @@ else:
|
|||||||
matchNumber = match['match_number']
|
matchNumber = match['match_number']
|
||||||
matchTime = dt.datetime.fromtimestamp(match['time']).strftime('%Y-%m-%d %I:%M %p')
|
matchTime = dt.datetime.fromtimestamp(match['time']).strftime('%Y-%m-%d %I:%M %p')
|
||||||
robot.update(date_string=matchTime, content='{} match {} {}'.format(robot['content'], matchNumber, side))
|
robot.update(date_string=matchTime, content='{} match {} {}'.format(robot['content'], matchNumber, side))
|
||||||
api.commit()
|
|
||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+1
-1
@@ -3,4 +3,4 @@
|
|||||||
# Import library
|
# Import library
|
||||||
source $(dirname ${BASH_SOURCE[0]})/install-lib.sh
|
source $(dirname ${BASH_SOURCE[0]})/install-lib.sh
|
||||||
|
|
||||||
sudo $(packageManager) install sway waybar rofi mako alacritty
|
sudo $(packageManager) install sway waybar quickshell rofi mako alacritty brightnessctl
|
||||||
Executable → Regular
Executable → Regular
Executable → Regular
Executable → Regular
+1
-2
@@ -5,9 +5,8 @@ pass git pull
|
|||||||
|
|
||||||
# Desktop
|
# Desktop
|
||||||
~/bin/connect-nas.sh
|
~/bin/connect-nas.sh
|
||||||
systemctl --user start polybar
|
~/bin/desktop/quickshell-start.sh
|
||||||
systemctl --user restart streamdeck
|
systemctl --user restart streamdeck
|
||||||
waybar &
|
|
||||||
/usr/libexec/polkit-gnome-authentication-agent-1 &
|
/usr/libexec/polkit-gnome-authentication-agent-1 &
|
||||||
|
|
||||||
# Keyring
|
# Keyring
|
||||||
Executable → Regular
@@ -0,0 +1,21 @@
|
|||||||
|
# Shared command-line tools
|
||||||
|
brew "chezmoi"
|
||||||
|
brew "git"
|
||||||
|
brew "emacs"
|
||||||
|
brew "python"
|
||||||
|
brew "jq"
|
||||||
|
|
||||||
|
# Password-store secrets used by chezmoi templates
|
||||||
|
brew "pass"
|
||||||
|
brew "gnupg"
|
||||||
|
|
||||||
|
# Web browser
|
||||||
|
cask "brave-browser"
|
||||||
|
|
||||||
|
# Terminal and font used by the shared Alacritty configuration
|
||||||
|
cask "alacritty"
|
||||||
|
cask "font-inconsolata"
|
||||||
|
|
||||||
|
# Optional tools for audio conversion and local AI
|
||||||
|
# brew "ffmpeg"
|
||||||
|
# brew "ollama"
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user