3 Commits

Author SHA1 Message Date
e184375897 feat: Add Posting to CLI tools
All checks were successful
Build Docker / BuildImage (push) Successful in 59s
2025-10-30 17:12:43 +11:00
844f1b52e2 feat: Update isCurl to isCLI to allow more CLI agents 2025-10-30 17:07:20 +11:00
19c51c3665 feat: Add header route for troubleshooting 2025-10-30 17:03:17 +11:00
4 changed files with 31 additions and 12 deletions

View File

@@ -40,7 +40,6 @@ def help():
"/time": "Get the current time", "/time": "Get the current time",
"/timezone": "Get the current timezone", "/timezone": "Get the current timezone",
"/message": "Get the message from the config", "/message": "Get the message from the config",
"/ip": "Get your IP address",
"/project": "Get the current project from git", "/project": "Get the current project from git",
"/version": "Get the current version of the website", "/version": "Get the current version of the website",
"/page_date?url=URL&verbose=BOOL": "Get the last modified date of a webpage (verbose is optional, default false)", "/page_date?url=URL&verbose=BOOL": "Get the last modified date of a webpage (verbose is optional, default false)",
@@ -48,6 +47,8 @@ def help():
"/playing": "Get the currently playing Spotify track", "/playing": "Get the currently playing Spotify track",
"/status": "Just check if the site is up", "/status": "Just check if the site is up",
"/ping": "Just check if the site is up", "/ping": "Just check if the site is up",
"/ip": "Get your IP address",
"/headers": "Get your request headers",
"/help": "Get this help message" "/help": "Get this help message"
}, },
"base_url": "/api/v1", "base_url": "/api/v1",
@@ -191,6 +192,17 @@ def playing():
return json_response(request, track_info, HTTP_OK) return json_response(request, track_info, HTTP_OK)
return json_response(request, {"spotify": track_info}, HTTP_OK) return json_response(request, {"spotify": track_info}, HTTP_OK)
@api_bp.route("/headers")
def headers():
"""Get the request headers."""
headers = dict(request.headers)
return jsonify({
"headers": headers,
"ip": getClientIP(request),
"status": HTTP_OK
})
@api_bp.route("/page_date") @api_bp.route("/page_date")
def page_date(): def page_date():
url = request.args.get("url") url = request.args.get("url")

View File

@@ -3,7 +3,7 @@ from flask import Blueprint, render_template, request, jsonify
import markdown import markdown
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
import re import re
from tools import isCurl, getClientIP, getHandshakeScript from tools import isCLI, getClientIP, getHandshakeScript
blog_bp = Blueprint('blog', __name__) blog_bp = Blueprint('blog', __name__)
@@ -110,7 +110,7 @@ def render_home(handshake_scripts: str | None = None):
@blog_bp.route("/") @blog_bp.route("/")
def index(): def index():
if not isCurl(request): if not isCLI(request):
return render_home(handshake_scripts=getHandshakeScript(request.host)) return render_home(handshake_scripts=getHandshakeScript(request.host))
# Get a list of pages # Get a list of pages
@@ -131,7 +131,7 @@ def index():
@blog_bp.route("/<path:path>") @blog_bp.route("/<path:path>")
def path(path): def path(path):
if not isCurl(request): if not isCLI(request):
return render_page(path, handshake_scripts=getHandshakeScript(request.host)) return render_page(path, handshake_scripts=getHandshakeScript(request.host))
# Convert md to html # Convert md to html

View File

@@ -26,7 +26,7 @@ from blueprints.api import api_bp
from blueprints.podcast import podcast_bp from blueprints.podcast import podcast_bp
from blueprints.acme import acme_bp from blueprints.acme import acme_bp
from blueprints.spotify import spotify_bp from blueprints.spotify import spotify_bp
from tools import isCurl, isCrawler, getAddress, getFilePath, error_response, getClientIP, json_response, getHandshakeScript, get_tools_data from tools import isCLI, isCrawler, getAddress, getFilePath, error_response, getClientIP, json_response, getHandshakeScript, get_tools_data
from curl import curl_response from curl import curl_response
app = Flask(__name__) app = Flask(__name__)
@@ -244,7 +244,7 @@ def index():
# Always load if load is in the query string # Always load if load is in the query string
if request.args.get("load"): if request.args.get("load"):
loaded = False loaded = False
if isCurl(request): if isCLI(request):
return curl_response(request) return curl_response(request)
if not loaded and not isCrawler(request): if not loaded and not isCrawler(request):
@@ -397,7 +397,7 @@ def index():
# region Donate # region Donate
@app.route("/donate") @app.route("/donate")
def donate(): def donate():
if isCurl(request): if isCLI(request):
return curl_response(request) return curl_response(request)
coinList = os.listdir(".well-known/wallets") coinList = os.listdir(".well-known/wallets")
@@ -687,7 +687,7 @@ def resume_pdf():
@app.route("/tools") @app.route("/tools")
def tools(): def tools():
if isCurl(request): if isCLI(request):
return curl_response(request) return curl_response(request)
return render_template("tools.html", tools=get_tools_data()) return render_template("tools.html", tools=get_tools_data())
@@ -704,7 +704,7 @@ def catch_all(path: str):
return error_response(request, message="Restricted route", code=403) return error_response(request, message="Restricted route", code=403)
# If curl request, return curl response # If curl request, return curl response
if isCurl(request): if isCLI(request):
return curl_response(request) return curl_response(request)
if path in REDIRECT_ROUTES: if path in REDIRECT_ROUTES:

View File

@@ -27,6 +27,13 @@ CRAWLERS = [
"Twitterbot" "Twitterbot"
] ]
CLI_AGENTS = [
"curl",
"hurl",
"xh",
"Posting"
]
def getClientIP(request: Request) -> str: def getClientIP(request: Request) -> str:
""" """
@@ -75,7 +82,7 @@ def getGitCommit() -> str:
return "failed to get version" return "failed to get version"
def isCurl(request: Request) -> bool: def isCLI(request: Request) -> bool:
""" """
Check if the request is from curl or hurl. Check if the request is from curl or hurl.
@@ -87,7 +94,7 @@ def isCurl(request: Request) -> bool:
""" """
if request.headers and request.headers.get("User-Agent"): if request.headers and request.headers.get("User-Agent"):
user_agent = request.headers.get("User-Agent", "") user_agent = request.headers.get("User-Agent", "")
return "curl" in user_agent or "hurl" in user_agent return any(agent in user_agent for agent in CLI_AGENTS)
return False return False
@@ -221,7 +228,7 @@ def error_response(
Returns: Returns:
Union[Tuple[Dict, int], object]: The JSON or HTML response Union[Tuple[Dict, int], object]: The JSON or HTML response
""" """
if force_json or isCurl(request): if force_json or isCLI(request):
return json_response(request, message, code) return json_response(request, message, code)
# Check if <error code>.html exists in templates # Check if <error code>.html exists in templates