From bcc7e5d8c2326fe50fdb51a3ea314f1a6d80559f Mon Sep 17 00:00:00 2001 From: Lord Lumineer <56554075+LordLumineer@users.noreply.github.com> Date: Fri, 7 Feb 2025 22:24:31 -0500 Subject: [PATCH 01/15] V1.0.5 BETA (#15) * :sparkles: v1.0.5 - Try It Out * Removed the bridge to the titles and cleaned so of the code * feat: :test_tube: Better CI/CD to include the pre-release branch Invalid version on purpose to test the version validation Invalid version on purpose to test the version validation * run version check on pre-release PR * Now with valid version --- .github/workflows/ci-cd.yml | 45 ++++++++++++++++++++++++++++++++----- app/main.py | 2 +- static/index.html | 14 +++++------- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 1db671c..42e3842 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -2,9 +2,9 @@ name: CI/CD on: push: - branches: [ master ] + branches: [ master, pre-release ] pull_request: - branches: [ master ] + branches: [ master, pre-release ] jobs: test: @@ -15,6 +15,14 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 0 + - name: Check version for pre-release + if: github.base_ref == 'pre-release' + run: | + validState=$(grep -oP 'version=\"\K[0-9.]+-\K['-']+' app/main.py || echo "valid") + if [ "$validState" != "valid" ]; then + echo "Fail: invalid development state (missing)" + exit 1 + fi - name: Set up Python uses: actions/setup-python@v5 @@ -43,7 +51,7 @@ jobs: deploy: needs: test - if: github.ref == 'refs/heads/master' + if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/pre-release' runs-on: ubuntu-latest steps: - name: Checkout @@ -55,7 +63,11 @@ jobs: id: get_version run: | version=$(grep -oP "version=\"\K[0-9.]+" app/main.py || echo "0.0.0") + versionState=$(grep -oP 'version=\"\K[0-9.]+-\K[a-zA-Z]+' app/main.py || echo "dev") + versionSub=$(grep -oP 'version=\"\K[0-9.]+-\K[a-zA-Z]+-\K[a-zA-Z0-9.]+' app/main.py || echo "missing") echo "version=$version" >> $GITHUB_OUTPUT + echo "versionState=$versionState" >> $GITHUB_OUTPUT + echo "versionSub=$versionSub" >> $GITHUB_OUTPUT - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -69,10 +81,33 @@ jobs: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - - name: Build and push Docker images + - name: Build and push Docker images (master) + if: github.ref == 'refs/heads/master' uses: docker/build-push-action@v6 with: push: true tags: | ${{ secrets.DOCKER_USERNAME }}/kofi-websocket:latest - ${{ secrets.DOCKER_USERNAME }}/kofi-websocket:${{ steps.get_version.outputs.version }} \ No newline at end of file + ${{ secrets.DOCKER_USERNAME }}/kofi-websocket:${{ steps.get_version.outputs.version }} + + - name: Build and push Docker images (pre-release with subversion) + if: github.ref == 'refs/heads/pre-release' && steps.get_version.outputs.versionSub != 'missing' + uses: docker/build-push-action@v6 + with: + push: true + tags: | + ${{ secrets.DOCKER_USERNAME }}/kofi-websocket:dev-latest + ${{ secrets.DOCKER_USERNAME }}/kofi-websocket:latest-${{ steps.get_version.outputs.versionState }}-latest + ${{ secrets.DOCKER_USERNAME }}/kofi-websocket:latest-${{ steps.get_version.outputs.versionState }}-${{ steps.get_version.outputs.versionSub }} + ${{ secrets.DOCKER_USERNAME }}/kofi-websocket:${{ steps.get_version.outputs.version }}-${{ steps.get_version.outputs.versionState }}-latest + ${{ secrets.DOCKER_USERNAME }}/kofi-websocket:${{ steps.get_version.outputs.version }}-${{ steps.get_version.outputs.versionState }}-${{ steps.get_version.outputs.versionSub }} + + - name: Build and push Docker images (pre-release without subversion) + if: github.ref == 'refs/heads/pre-release' && steps.get_version.outputs.versionSub == 'missing' + uses: docker/build-push-action@v6 + with: + push: true + tags: | + ${{ secrets.DOCKER_USERNAME }}/kofi-websocket:dev-latest + ${{ secrets.DOCKER_USERNAME }}/kofi-websocket:latest-${{ steps.get_version.outputs.versionState }} + ${{ secrets.DOCKER_USERNAME }}/kofi-websocket:${{ steps.get_version.outputs.version }}-${{ steps.get_version.outputs.versionState }} \ No newline at end of file diff --git a/app/main.py b/app/main.py index f9553ed..b51fbda 100644 --- a/app/main.py +++ b/app/main.py @@ -29,7 +29,7 @@ active_connections: dict[str, WebSocket] = {} app = FastAPI( - version="1.0.5-beta_1", + version="1.0.5-beta-v1", docs_url=None, # Disable Swagger UI redoc_url=None # Disable ReDoc ) diff --git a/static/index.html b/static/index.html index 7f9cb71..b5974a8 100644 --- a/static/index.html +++ b/static/index.html @@ -4,14 +4,14 @@
-Example code to handle Ko-fi notifications:
-ws.onmessage = (event) => {
+ ws.onmessage = (event) => {
const data = JSON.parse(event.data);
switch(data.type) {
case "Donation":
@@ -689,8 +688,7 @@ 4. Handle Events
Example Implementation
Here's a complete, fully functional, example that connects on page load:
-
-<!-- Add this to your HTML -->
+ <!-- Add this to your HTML -->
<div id="kofi-notifications"></div>
<!-- Add this to your JavaScript file or <script> tag -->
From c3014a3467b8284324127ece8951b9652918d1f6 Mon Sep 17 00:00:00 2001
From: Lord Lumineer <56554075+LordLumineer@users.noreply.github.com>
Date: Fri, 7 Feb 2025 22:47:18 -0500
Subject: [PATCH 02/15] beta v2 (#16)
---
app/main.py | 12 ++++++++----
static/index.html | 8 ++++----
static/kofi-websocket-icon.png | Bin 0 -> 9979 bytes
...ocket-preview.png => kofi-websocket-logo.png} | Bin
tests/test_main.py | 12 +++---------
5 files changed, 15 insertions(+), 17 deletions(-)
create mode 100644 static/kofi-websocket-icon.png
rename static/{kofi-websocket-preview.png => kofi-websocket-logo.png} (100%)
diff --git a/app/main.py b/app/main.py
index b51fbda..6cff7bc 100644
--- a/app/main.py
+++ b/app/main.py
@@ -29,7 +29,7 @@
active_connections: dict[str, WebSocket] = {}
app = FastAPI(
- version="1.0.5-beta-v1",
+ version="1.0.5-beta-v2",
docs_url=None, # Disable Swagger UI
redoc_url=None # Disable ReDoc
)
@@ -55,9 +55,13 @@ async def root():
async def _favicon():
return FileResponse("static/favicon.ico")
-@app.get("/kofi-websocket-preview.png")
-async def _favicon():
- return FileResponse("static/kofi-websocket-preview.png")
+@app.get("/logo.png")
+async def _logo():
+ return FileResponse("static/kofi-websocket-logo.png")
+
+@app.get("/icon.png")
+async def _icon():
+ return FileResponse("static/kofi-websocket-icon.png")
@app.get("/ping")
async def _ping():
diff --git a/static/index.html b/static/index.html
index b5974a8..f255812 100644
--- a/static/index.html
+++ b/static/index.html
@@ -14,20 +14,20 @@
-
+
-
+
-
+
-
+
diff --git a/static/kofi-websocket-icon.png b/static/kofi-websocket-icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..830e04003aea709f84ac00ed87c688e1b6e4b379
GIT binary patch
literal 9979
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
YHD4(i{M8yfxCT*>Rh9W6W%A$u07bAS" in response.content
-
-def test_favicon_endpoint(client):
- """Test the favicon endpoint."""
- response = client.get("/favicon.ico")
- assert response.status_code == 200
- assert "image/" in response.headers["content-type"]
-
-def test_SEO_image(client):
+@pytest.mark.parametrize("endpoint", ["/favicon.ico", "/logo.png", "/icon.png"])
+def test_image_endpoint(client, endpoint):
"""Test the favicon endpoint."""
- response = client.get("/kofi-websocket-preview.png")
+ response = client.get(endpoint)
assert response.status_code == 200
assert "image/" in response.headers["content-type"]
From 323ed54a9fb816057821a5b784371eaa9a7583cc Mon Sep 17 00:00:00 2001
From: Lord Lumineer <56554075+LordLumineer@users.noreply.github.com>
Date: Sat, 8 Feb 2025 00:43:44 -0500
Subject: [PATCH 03/15] V1.0.5 try it out (#17)
* feat: :sparkles: v1.0.5 - Try It Out
Added a box to try out the service directly in the home page
* v1.0.5 - BETA
* beta 1
* removed the bridge to the titles and cleaned so of the code
* feat: :test_tube: Better CI/CD to include the pre-release branch
Invalid version on purpose to test the version validation
Invalid version on purpose to test the version validation
* run version check on pre-release PR
* Now with valid version
* beta v2 fixed homepage tags
* fix: :bug: Fixed wrong endpoint for SEO
---
app/main.py | 2 +-
static/index.html | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/main.py b/app/main.py
index 6cff7bc..b51cc26 100644
--- a/app/main.py
+++ b/app/main.py
@@ -29,7 +29,7 @@
active_connections: dict[str, WebSocket] = {}
app = FastAPI(
- version="1.0.5-beta-v2",
+ version="1.0.5-beta-v3",
docs_url=None, # Disable Swagger UI
redoc_url=None # Disable ReDoc
)
diff --git a/static/index.html b/static/index.html
index f255812..71a7ca0 100644
--- a/static/index.html
+++ b/static/index.html
@@ -20,14 +20,14 @@
-
+
-
+
From c91ef0ed8a5f3a7882d67c4ec58b76d4cbee8490 Mon Sep 17 00:00:00 2001
From: Lord Lumineer <56554075+LordLumineer@users.noreply.github.com>
Date: Mon, 10 Feb 2025 21:51:47 -0500
Subject: [PATCH 04/15] :sparkles: Refactoring of the homepage to use libraries
(#18)
---
CHANGES.md | 17 +
app/main.py | 40 +-
static/{kofi-websocket-icon.png => icon.png} | Bin
static/index.html | 1098 +++++-------------
static/{kofi-websocket-logo.png => logo.png} | Bin
static/script.js | 300 +++++
tests/test_main.py | 23 -
7 files changed, 642 insertions(+), 836 deletions(-)
rename static/{kofi-websocket-icon.png => icon.png} (100%)
rename static/{kofi-websocket-logo.png => logo.png} (100%)
create mode 100644 static/script.js
diff --git a/CHANGES.md b/CHANGES.md
index 66c0c6c..adac01f 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -6,6 +6,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [1.1.0 - UNRELEASED] - 2025-02-10
+
+### Changes in 1.1.0
+
+- You can try the service directly from the homepage now
+ - The button to display the try it out section is located at the bottom right of the page (and is always visible)
+- Addition of a navigation panel to quickly jump to the different sections of the homepage
+- Theme switcher to change between light and dark mode
+
+- Now using libraries for the UI of the homepage
+ - TailwindCSS
+ - DaisyUI
+ - Json Formatter (to format the json in the try it out section)
+- General refactoring of the homepage
+
+- Reduced the endpoints by directly mounting the static files in the server
+
## [1.0.4] - 2025-02-02
### Changes in 1.0.4
diff --git a/app/main.py b/app/main.py
index b51cc26..4b41ef3 100644
--- a/app/main.py
+++ b/app/main.py
@@ -22,14 +22,15 @@
import asyncio
import json
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Form
-from fastapi.responses import FileResponse, HTMLResponse
+# from fastapi.responses import FileResponse, HTMLResponse
from fastapi.exceptions import HTTPException
+from fastapi.staticfiles import StaticFiles
from starlette.middleware.cors import CORSMiddleware
active_connections: dict[str, WebSocket] = {}
app = FastAPI(
- version="1.0.5-beta-v3",
+ version="1.1.0-beta-v1",
docs_url=None, # Disable Swagger UI
redoc_url=None # Disable ReDoc
)
@@ -43,25 +44,25 @@
)
-@app.get("/", response_class=HTMLResponse)
-async def root():
- """
- Returns the home page of the application, which explains the purpose
- and functionalities of the Ko-fi WebSocket bridge.
- """
- return FileResponse("static/index.html")
+# @app.get("/", response_class=HTMLResponse)
+# async def root():
+# """
+# Returns the home page of the application, which explains the purpose
+# and functionalities of the Ko-fi WebSocket bridge.
+# """
+# return FileResponse("static/index.html")
-@app.get("/favicon.ico")
-async def _favicon():
- return FileResponse("static/favicon.ico")
+# @app.get("/favicon.ico")
+# async def _favicon():
+# return FileResponse("static/favicon.ico")
-@app.get("/logo.png")
-async def _logo():
- return FileResponse("static/kofi-websocket-logo.png")
+# @app.get("/logo.png")
+# async def _logo():
+# return FileResponse("static/kofi-websocket-logo.png")
-@app.get("/icon.png")
-async def _icon():
- return FileResponse("static/kofi-websocket-icon.png")
+# @app.get("/icon.png")
+# async def _icon():
+# return FileResponse("static/kofi-websocket-icon.png")
@app.get("/ping")
async def _ping():
@@ -135,3 +136,6 @@ async def websocket_endpoint(websocket: WebSocket, verification_token: str):
except WebSocketDisconnect:
if verification_token in active_connections:
del active_connections[verification_token]
+
+# Keep it at the end to prevent routing issues
+app.mount("/", StaticFiles(directory="static",html = True), name="static")
diff --git a/static/kofi-websocket-icon.png b/static/icon.png
similarity index 100%
rename from static/kofi-websocket-icon.png
rename to static/icon.png
diff --git a/static/index.html b/static/index.html
index 71a7ca0..2501809 100644
--- a/static/index.html
+++ b/static/index.html
@@ -1,5 +1,5 @@
-
+
@@ -20,656 +20,296 @@
-
+
-
+
+
+
+
+
+
+ id="prism-light">
-
-
-
-
-
-
- Ko-fi WebSocket
-
- Loading version...
-
-
- A modern, real-time bridge between Ko-fi webhooks and WebSocket connections, enabling instant
- notifications for your Ko-fi events.
-
-
- View on GitHub
+
+
+
+
+
+
+
+
+
+ Ko-fi WebSocket
+
+
+
+ Loading...
+
+
+
+ A modern, real-time bridge between Ko-fi webhooks and WebSocket connections, enabling instant
+ notifications for your Ko-fi events.
+
+
+ View on
+ GitHub
+
-
-
- Real-time Updates
- Instant notification delivery via WebSocket connections
-
-
- Secure
- Token-based authentication for secure communications
-
-
- Universal Support
- Compatible with all Ko-fi event types
+
+
+
+ Real-time Updates
+ Instant notification delivery via WebSocket connections
+
-
- Easy Integration
- Simple to integrate with any WebSocket client
+
+
+ Secure
+ Token-based authentication for secure communications
+
-
-
-
- Try It Out
-
-
-
-
-
-
+
+
+ Universal Support
+ Compatible with all Ko-fi event types
-
-
- WebSocket Terminal
-
-
-
+
+
+
+ Easy Integration
+ Simple to integrate with any WebSocket client
-
- Quick Start
- Connect to the WebSocket endpoint using your verification token:
-
- {{ WSprotocol }}//{{ HOSTNAME }}/ws/{verification_token}
+
+
+
+
+ Quick Start
+ Connect to the WebSocket endpoint using your verification token:
+
+ {{ WSprotocol }}//{{ HOSTNAME }}/ws/{verification_token}
+
-
- Getting Started
- 1. Get Your Verification Token
- To find your Ko-fi verification token:
-
- - Go to your Ko-fi
- Dashboard
- - Click on "API" in the left menu (under "More")
- - Find your verification token in the "Advanced" section
- - Copy the token, you'll need it for the WebSocket setup
-
-
- 2. Set Up Ko-fi Webhook
- In your Ko-fi settings, set your Webhook URL to:
-
- {{ HTTPprotocol }}//{{ HOSTNAME }}/webhook
-
+
+
+ Getting Started
+ 1. Get Your Verification Token
+ To find your Ko-fi verification token:
+
+ - Go to your Ko-fi
+ Dashboard
+ - Click on "API" in the left menu (under "More")
+ - Find your verification token in the "Advanced" section
+ - Copy the token, you'll need it for the WebSocket setup
+
+
+ 2. Set Up Ko-fi Webhook
+ In your Ko-fi settings, set your Webhook URL to:
+
+ {{ HTTPprotocol }}//{{ HOSTNAME }}/webhook
+
- 3. Connect to WebSocket
- Connect to the WebSocket using your verification token:
-
- const ws = new WebSocket('{{ WSprotocol }}//{{ HOSTNAME }}/ws/YOUR_VERIFICATION_TOKEN');
-
+ 3. Connect to WebSocket
+ Connect to the WebSocket using your verification token:
+
+ const ws = new WebSocket('{{ WSprotocol }}//{{ HOSTNAME }}/ws/YOUR_VERIFICATION_TOKEN');
+
- 4. Handle Events
- Example code to handle Ko-fi notifications:
-
- ws.onmessage = (event) => {
+ 4. Handle Events
+ Example code to handle Ko-fi notifications:
+
+ ws.onmessage = (event) => {
const data = JSON.parse(event.data);
switch(data.type) {
case "Donation":
@@ -682,13 +322,14 @@ 4. Handle Events
console.log(`New shop order from ${data.from_name}`);
break;
}
-};
-
+};
+
+
- Example Implementation
- Here's a complete, fully functional, example that connects on page load:
-
- <!-- Add this to your HTML -->
+ Example Implementation
+ Here's a complete, fully functional, example that connects on page load:
+
+ <!-- Add this to your HTML -->
<div id="kofi-notifications"></div>
<!-- Add this to your JavaScript file or <script> tag -->
@@ -788,257 +429,124 @@ Example Implementation
});
</script>
+
-
-