From f871619d7fedbf973c249ad6e16c0fcf7e819cf8 Mon Sep 17 00:00:00 2001 From: Mitja Felicijan Date: Sat, 2 Aug 2025 20:28:26 +0200 Subject: Update --- Makefile | 22 +- content/pages/projects.fossil.md.part | 4 + content/pages/projects.github.md.part | 392 ++++++++++++++++++++++++++++++++++ content/pages/projects.md | 8 + static/projects/pats.fossil | Bin 0 -> 225280 bytes static/projects/xmagnify.fossil | Bin 0 -> 225280 bytes tools/fossil-projects.sh | 17 ++ tools/github-projects.py | 138 ++++++++++++ tools/projects.py | 149 ------------- 9 files changed, 579 insertions(+), 151 deletions(-) create mode 100644 content/pages/projects.fossil.md.part create mode 100644 content/pages/projects.github.md.part create mode 100644 static/projects/pats.fossil create mode 100644 static/projects/xmagnify.fossil create mode 100644 tools/fossil-projects.sh create mode 100644 tools/github-projects.py delete mode 100644 tools/projects.py diff --git a/Makefile b/Makefile index 0c183ca..d0add7d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ MAKEFLAGS+=-j2 +PROJECTS_FILENAME = content/pages/projects.md dev: watch server @@ -8,5 +9,22 @@ watch: server: jbmafp -s -fetch-projects: - cd tools && python projects.py +update-projects: projects-header + cat content/pages/projects.fossil.md.part \ + content/pages/projects.github.md.part >> \ + content/pages/projects.md + +projects-header: + echo "---" > $(PROJECTS_FILENAME) + echo "title: Personal projects" >> $(PROJECTS_FILENAME) + echo "date: 2024-10-21T12:00:00+02:00" >> $(PROJECTS_FILENAME) + echo "url: projects.html" >> $(PROJECTS_FILENAME) + echo "type: page" >> $(PROJECTS_FILENAME) + echo "draft: false" >> $(PROJECTS_FILENAME) + echo "---\n" >> $(PROJECTS_FILENAME) + +update-fossil: + cd tools && bash fossil-projects.sh + +update-github: + cd tools && python github-projects.py diff --git a/content/pages/projects.fossil.md.part b/content/pages/projects.fossil.md.part new file mode 100644 index 0000000..796af87 --- /dev/null +++ b/content/pages/projects.fossil.md.part @@ -0,0 +1,4 @@ +## Fossil repositories + +- [pats.fossil](/projects/pats.fossil)
Size: 220K, Modified: 2025-08-02 20:24:05 +- [xmagnify.fossil](/projects/xmagnify.fossil)
Size: 220K, Modified: 2025-08-02 20:24:05 diff --git a/content/pages/projects.github.md.part b/content/pages/projects.github.md.part new file mode 100644 index 0000000..92a8c74 --- /dev/null +++ b/content/pages/projects.github.md.part @@ -0,0 +1,392 @@ + + +## GitHub repositories + +
+ +- [abtts](#abtts) +- [blpconvert](#blpconvert) +- [ClassicEnhanced](#classicenhanced) +- [clutch](#clutch) +- [jbmafp](#jbmafp) +- [lazycommit](#lazycommit) +- [makext](#makext) +- [mprogress](#mprogress) +- [newsbarge](#newsbarge) +- [oberon](#oberon) +- [p9tree](#p9tree) +- [pats](#pats) +- [rssperado](#rssperado) +- [sm](#sm) +- [sparklines](#sparklines) +- [ttdaw](#ttdaw) +- [TurtleTweaks](#turtletweaks) +- [xmagnify](#xmagnify) + + +
+ +## abtts +Convert text like ebooks into audiobooks with UnrealSpeech. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2023-07-05|Added introduction audio option| [abtts-v0.3.tar.gz](/projects/abtts-v0.3.tar.gz) | +|2023-07-03|Moved to OGG as default format| [abtts-v0.2.tar.gz](/projects/abtts-v0.2.tar.gz) | +|2023-07-03|First release| [abtts-v0.1.tar.gz](/projects/abtts-v0.1.tar.gz) | + + +
+ + + +## blpconvert +This tool converts BLP texture files used in many games such as World of Warcraft into PNG files. With support for DXT1, DXT3 and DXT5 compression. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2025-02-04|First version| [blpconvert-v1.0.tar.gz](/projects/blpconvert-v1.0.tar.gz) | + + +
+ + + +## ClassicEnhanced +Quality of life improvements and general enhancements for WoW Classic Client. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2024-04-13|Fixed Druid initial state of mana bar| [ClassicEnhanced-v1.0.1.tar.gz](/projects/ClassicEnhanced-v1.0.1.tar.gz) | +|2024-04-13|First release| [ClassicEnhanced-v1.0.0.tar.gz](/projects/ClassicEnhanced-v1.0.0.tar.gz) | + + +
+ + + +## clutch +Clutch allows you to run nested dwm session inside your existing X or Wayland session. This comes in handy when you already have a desktop environment running (like Gnome) but you want to have a tiling window manager as well. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2024-06-19|First release| [clutch-v1.0.tar.gz](/projects/clutch-v1.0.tar.gz) | + + +
+ + + +## jbmafp +A simple static site generator that is semi compatible with Hugo and aims to be a simpler version of it, getting out of your way when it comes to taxonomies. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2024-06-21|Added better filtering| [jbmafp-v0.3.tar.gz](/projects/jbmafp-v0.3.tar.gz) | +|2024-06-18|Added filters first, last, random| [jbmafp-v0.2.tar.gz](/projects/jbmafp-v0.2.tar.gz) | +|2024-03-10|First release| [jbmafp-v0.1.tar.gz](/projects/jbmafp-v0.1.tar.gz) | + + +
+ + + +## lazycommit +Git commit messages for lazy people that use AI in the backend. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2025-03-17|First release| [lazycommit-v1.0.tar.gz](/projects/lazycommit-v1.0.tar.gz) | + + +
+ + + +## makext +Makext is a collection of useful extensions for Makefiles, aimed at simplifying and enhancing the functionality of Make-based projects. These extensions provide additional features and convenience functions to improve the overall usage of GNU Make as a task runner. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2024-05-15|First release| [makext-v1.0.tar.gz](/projects/makext-v1.0.tar.gz) | + + +
+ + + +## mprogress +Displays progress bar in terminal. It can be used as a standalone program so you can put it in /usr/bin. The name is stupid like that because of the potential name conflicts. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2022-12-31|First release| [mprogress-v1.0.tar.gz](/projects/mprogress-v1.0.tar.gz) | + + +
+ + + +## newsbarge +Converts RSS feeds into single HTMLpage containing all the feed stories. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2025-03-01|First release| [newsbarge-v0.1.tar.gz](/projects/newsbarge-v0.1.tar.gz) | + + +
+ + + +## oberon +This is a tiny project boilerplate for OpenResty and Lua website that includes basic router, memcached, Redis and MySQL with accompanying examples how to use all this. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2025-03-29|First release| [oberon-v1.0.tar.gz](/projects/oberon-v1.0.tar.gz) | + + +
+ + + +## p9tree +tree is written with Plan9 Operating System in mind so it may not work with other systems. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2023-11-11|First release| [p9tree-v1.0.tar.gz](/projects/p9tree-v1.0.tar.gz) | + + +
+ + + +## pats +Pats is a command-line tool for managing PulseAudio audio sinks that allows you to list available audio outputs and cycles between them seamlessly. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2025-07-19|First release| [pats-v1.0.tar.gz](/projects/pats-v1.0.tar.gz) | + + +
+ + + +## rssperado +The RSS parser is a command-line utility that simplifies the process of parsing RSS feeds, enriching the extracted data, exporting it to JSON files, enabling content classification, and providing English translation. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2023-06-07|First release| [rssperado-v1.0.tar.gz](/projects/rssperado-v1.0.tar.gz) | + + +
+ + + +## sm +Simple snapshot utility that uses TAR to compress current directory into a .tar file while ignoring some of the directories. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2024-10-21|First release| [sm-v1.0.tar.gz](/projects/sm-v1.0.tar.gz) | + + +
+ + + +## sparklines +Self-contained tiny SVG sparkline chart library written in vanilla JS with zero dependencies. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2023-12-09|First release| [sparklines-v1.0.tar.gz](/projects/sparklines-v1.0.tar.gz) | + + +
+ + + +## ttdaw +ttdaw is a tiny terminal based digital audio workstation made for fun, experimentation and learning more about audio, MIDI and terminal applications in general. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2024-12-22|First release| [ttdaw-v0.1.tar.gz](/projects/ttdaw-v0.1.tar.gz) | + + +
+ + + +## TurtleTweaks +World of Warcraft 1.12 client Tweaks and Enhancements Addon. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2023-05-14|Added cooldown timers to actionbars| [TurtleTweaks-v0.7.tar.gz](/projects/TurtleTweaks-v0.7.tar.gz) | +|2023-05-12|Rested bar now has a proper progress bar| [TurtleTweaks-v0.6.tar.gz](/projects/TurtleTweaks-v0.6.tar.gz) | +|2023-05-09|Removed debug messages| [TurtleTweaks-v0.5.1.tar.gz](/projects/TurtleTweaks-v0.5.1.tar.gz) | +|2023-05-09|Added option to open world map in a window| [TurtleTweaks-v0.5.tar.gz](/projects/TurtleTweaks-v0.5.tar.gz) | +|2023-05-09|Added nameplate scaling option| [TurtleTweaks-v0.4.tar.gz](/projects/TurtleTweaks-v0.4.tar.gz) | +|2023-05-08|Fixed progress bar to reflect the value in rested bar| [TurtleTweaks-v0.3.tar.gz](/projects/TurtleTweaks-v0.3.tar.gz) | +|2023-05-08|Added align grid slashcommand| [TurtleTweaks-v0.2.tar.gz](/projects/TurtleTweaks-v0.2.tar.gz) | +|2023-05-08|First release| [TurtleTweaks-v0.1.tar.gz](/projects/TurtleTweaks-v0.1.tar.gz) | + + +
+ + + +## xmagnify +Xmagnify is a real-time screen magnification tool for X11 systems that provides a zoomed view of the area around your mouse cursor. + + +
+ +|Released|Description|Download| +|--------|-----------|--------| +|2025-07-18|First release| [xmagnify-v1.0.tar.gz](/projects/xmagnify-v1.0.tar.gz) | + + +
+ + + + + + + diff --git a/content/pages/projects.md b/content/pages/projects.md index 8c341b6..cc10185 100644 --- a/content/pages/projects.md +++ b/content/pages/projects.md @@ -6,6 +6,14 @@ type: page draft: false --- +## Fossil repositories + +- [pats.fossil](/projects/pats.fossil)
Size: 220K, Modified: 2025-08-02 20:21:40 +- [xmagnify.fossil](/projects/xmagnify.fossil)
Size: 220K, Modified: 2025-08-02 20:21:40 + + +## GitHub repositories +
- [abtts](#abtts) diff --git a/static/projects/pats.fossil b/static/projects/pats.fossil new file mode 100644 index 0000000..ad91737 Binary files /dev/null and b/static/projects/pats.fossil differ diff --git a/static/projects/xmagnify.fossil b/static/projects/xmagnify.fossil new file mode 100644 index 0000000..258d27d Binary files /dev/null and b/static/projects/xmagnify.fossil differ diff --git a/tools/fossil-projects.sh b/tools/fossil-projects.sh new file mode 100644 index 0000000..bb6e673 --- /dev/null +++ b/tools/fossil-projects.sh @@ -0,0 +1,17 @@ +set -xe + +OUT=../content/pages/projects.fossil.md.part + +echo -e "## Fossil repositories\n" > $OUT + +find ~/Projects/ -type f -name "*.fossil" -not -path "*/website/*" | while read -r file; do + cp $file ../static/projects/ +done + +find ../static/projects/ -type f -name "*.fossil" | while read -r file; do + base=$(basename "$file") + size=$(stat -c %s "$file" | numfmt --to=iec) + modified_date=$(stat -c %Y "$file") + formatted_date=$(date -d @"$modified_date" +"%Y-%m-%d %H:%M:%S") + echo -e "- [$base](/projects/$base)
Size: $size, Modified: $formatted_date" >> $OUT +done diff --git a/tools/github-projects.py b/tools/github-projects.py new file mode 100644 index 0000000..e2afe95 --- /dev/null +++ b/tools/github-projects.py @@ -0,0 +1,138 @@ +"""Fetches my public repositories and downloads tagged versions.""" +from datetime import datetime +import sys +import json +import requests + +USERNAME = "mitjafelicijan" +CACHE_BUSTER = int(datetime.now().timestamp()) +DOUBLE_NL = "\n\n" + +headers = { + "Accept": "application/vnd.github.v3+json" +} + +def generate_markdown_file(include_repositories): + file = open("../content/pages/projects.github.md.part", "w") + + file.write(DOUBLE_NL) + file.write("## GitHub repositories") + file.write(DOUBLE_NL) + + file.write("
") + file.write(DOUBLE_NL) + + for repo in include_repositories: + file.write(f"- [{repo['name']}](#{repo['name'].lower()}) \n") + + file.write(DOUBLE_NL) + file.write("
") + file.write(DOUBLE_NL) + + for repo in include_repositories: + print(f"> {repo['name']}") + + file.write(f"## {repo['name']}\n") + file.write(f"{repo['description']}\n") + + file.write(DOUBLE_NL) + file.write("
") + file.write(DOUBLE_NL) + file.write("|Released|Description|Download|\n") + file.write("|--------|-----------|--------|\n") + + for release in repo['releases']: + print(f" - {release['name']} - {release['created_at']}") + dt = datetime.strptime(release["created_at"], "%Y-%m-%dT%H:%M:%SZ") + file.write(f"|{dt.strftime('%Y-%m-%d')}|{release['name']}| [{release['filename']}](/projects/{release['filename']}) |\n") + + file.write(DOUBLE_NL) + file.write("
") + file.write(DOUBLE_NL) + + file.write("") + file.write(DOUBLE_NL) + + file.write(DOUBLE_NL) + file.write("") + file.write(DOUBLE_NL) + + file.close() + +def download_tarball(url, filepath): + with requests.get(url, stream=True, timeout=30) as response: + response.raise_for_status() + + with open(filepath, "wb") as file: + for chunk in response.iter_content(chunk_size=8192): + file.write(chunk) + +def assert_rate_limit(response): + rate_limit_limit = int(response.headers.get("x-ratelimit-limit")) + rate_limit_remaining = int(response.headers.get("x-ratelimit-remaining")) + rate_limit_reset = int(response.headers.get("x-ratelimit-reset")) + print(f"Rate limit: {rate_limit_remaining}/{rate_limit_limit}") + print(f"Reset time: {datetime.fromtimestamp(rate_limit_reset)}") + + if rate_limit_remaining == 0: + sys.exit(1) + +def fetch_github_data(): + include_repositories = [] + print(headers) + response = requests.get(f"https://api.github.com/users/{USERNAME}/repos?ts={CACHE_BUSTER}&per_page=100", + headers=headers, + timeout=10) + + assert_rate_limit(response) + + if response.status_code == 200: + repos = response.json() + for repo in repos: + # Check if repository has "winc" topic. This means I want to include + # this repository on this page. + if "winc" in repo["topics"]: + include_repositories.append(repo) + else: + print(f"Failed to retrieve repositories: {response.status_code}") + sys.exit(1) + + for repo in include_repositories: + print(f"Name: {repo['name']}, URL: {repo['html_url']}") + + response = requests.get(f"https://api.github.com/repos/{USERNAME}/{repo['name']}/releases?ts={CACHE_BUSTER}", + headers=headers, + timeout=10) + + assert_rate_limit(response) + + if response.status_code == 200: + repo["releases"] = response.json() + for release in repo["releases"]: + release["filename"] = f"{repo['name']}-{release['tag_name']}.tar.gz" + print(f" > {release['tag_name']}, {release['name']}, {release['filename']}") + download_tarball(release["tarball_url"], f"../static/projects/{release['filename']}") + + return include_repositories + +include_repositories = fetch_github_data() + +# with open("out.json", "w") as json_file: +# json.dump(include_repositories, json_file, indent=4) + +generate_markdown_file(include_repositories) + +# with open("out.json", "r") as fp: +# include_repositories = json.load(fp) +# generate_markdown_file(include_repositories) diff --git a/tools/projects.py b/tools/projects.py deleted file mode 100644 index 65cea8d..0000000 --- a/tools/projects.py +++ /dev/null @@ -1,149 +0,0 @@ -"""Fetches my public repositories and downloads tagged versions.""" -from datetime import datetime -import sys -import json -import requests - -USERNAME = "mitjafelicijan" -CACHE_BUSTER = int(datetime.now().timestamp()) -DOUBLE_NL = "\n\n" - -headers = { - "Accept": "application/vnd.github.v3+json" -} - - -def generate_markdown_file(include_repositories): - file = open("../content/pages/projects.md", "w") - - file.write("---\n") - file.write("title: Personal projects\n") - file.write("date: 2024-10-21T12:00:00+02:00\n") - file.write("url: projects.html\n") - file.write("type: page\n") - file.write("draft: false\n") - file.write("---") - file.write(DOUBLE_NL) - - file.write("
") - file.write(DOUBLE_NL) - - for repo in include_repositories: - file.write(f"- [{repo['name']}](#{repo['name'].lower()}) \n") - - file.write(DOUBLE_NL) - file.write("
") - file.write(DOUBLE_NL) - - for repo in include_repositories: - print(f"> {repo['name']}") - - file.write(f"## {repo['name']}\n") - file.write(f"{repo['description']}\n") - - file.write(DOUBLE_NL) - file.write("
") - file.write(DOUBLE_NL) - file.write("|Released|Description|Download|\n") - file.write("|--------|-----------|--------|\n") - - for release in repo['releases']: - print(f" - {release['name']} - {release['created_at']}") - dt = datetime.strptime(release["created_at"], "%Y-%m-%dT%H:%M:%SZ") - file.write(f"|{dt.strftime('%Y-%m-%d')}|{release['name']}| [{release['filename']}](/projects/{release['filename']}) |\n") - - file.write(DOUBLE_NL) - file.write("
") - file.write(DOUBLE_NL) - - file.write("") - file.write(DOUBLE_NL) - - file.write(DOUBLE_NL) - file.write("") - file.write(DOUBLE_NL) - - file.close() - - - -def download_tarball(url, filepath): - with requests.get(url, stream=True, timeout=30) as response: - response.raise_for_status() - - with open(filepath, "wb") as file: - for chunk in response.iter_content(chunk_size=8192): - file.write(chunk) - - -def assert_rate_limit(response): - rate_limit_limit = int(response.headers.get("x-ratelimit-limit")) - rate_limit_remaining = int(response.headers.get("x-ratelimit-remaining")) - rate_limit_reset = int(response.headers.get("x-ratelimit-reset")) - print(f"Rate limit: {rate_limit_remaining}/{rate_limit_limit}") - print(f"Reset time: {datetime.fromtimestamp(rate_limit_reset)}") - - if rate_limit_remaining == 0: - sys.exit(1) - - -def fetch_github_data(): - include_repositories = [] - print(headers) - response = requests.get(f"https://api.github.com/users/{USERNAME}/repos?ts={CACHE_BUSTER}&per_page=100", - headers=headers, - timeout=10) - - assert_rate_limit(response) - - if response.status_code == 200: - repos = response.json() - for repo in repos: - # Check if repository has "winc" topic. This means I want to include - # this repository on this page. - if "winc" in repo["topics"]: - include_repositories.append(repo) - else: - print(f"Failed to retrieve repositories: {response.status_code}") - sys.exit(1) - - for repo in include_repositories: - print(f"Name: {repo['name']}, URL: {repo['html_url']}") - - response = requests.get(f"https://api.github.com/repos/{USERNAME}/{repo['name']}/releases?ts={CACHE_BUSTER}", - headers=headers, - timeout=10) - - assert_rate_limit(response) - - if response.status_code == 200: - repo["releases"] = response.json() - for release in repo["releases"]: - release["filename"] = f"{repo['name']}-{release['tag_name']}.tar.gz" - print(f" > {release['tag_name']}, {release['name']}, {release['filename']}") - download_tarball(release["tarball_url"], f"../static/projects/{release['filename']}") - - return include_repositories - - -include_repositories = fetch_github_data() - -# with open("out.json", "w") as json_file: -# json.dump(include_repositories, json_file, indent=4) - -generate_markdown_file(include_repositories) - -# with open("out.json", "r") as fp: -# include_repositories = json.load(fp) -# generate_markdown_file(include_repositories) -- cgit v1.2.3