Compare commits
4 Commits
copilot/im
...
50596fc4ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
50596fc4ba
|
|||
|
83436352e7
|
|||
|
779f895ef8
|
|||
|
d53c48ba85
|
@@ -6,6 +6,7 @@
|
|||||||
"BTC": "Bitcoin (BTC)",
|
"BTC": "Bitcoin (BTC)",
|
||||||
"CRO": "Crypto.com (CRO)",
|
"CRO": "Crypto.com (CRO)",
|
||||||
"DOT": "Polkadot (DOT)",
|
"DOT": "Polkadot (DOT)",
|
||||||
|
"ERG": "ERGO (ERG)",
|
||||||
"ETH": "Ethereum (ETH)",
|
"ETH": "Ethereum (ETH)",
|
||||||
"HNS": "Handshake (HNS)",
|
"HNS": "Handshake (HNS)",
|
||||||
"MATIC": "Polygon (MATIC)",
|
"MATIC": "Polygon (MATIC)",
|
||||||
|
|||||||
1
.well-known/wallets/ERG
Normal file
1
.well-known/wallets/ERG
Normal file
@@ -0,0 +1 @@
|
|||||||
|
9gfxbmYdeVGr4PPRbsBHhsJJSHyacJRNr61LhxudHc8PtQPCUsM
|
||||||
Binary file not shown.
@@ -7,7 +7,7 @@ from mail import sendEmail
|
|||||||
from tools import getClientIP, getGitCommit, json_response, parse_date, get_tools_data
|
from tools import getClientIP, getGitCommit, json_response, parse_date, get_tools_data
|
||||||
from blueprints import sol
|
from blueprints import sol
|
||||||
from dateutil import parser as date_parser
|
from dateutil import parser as date_parser
|
||||||
from blueprints.spotify import get_spotify_track
|
from blueprints.spotify import get_playing_spotify_track
|
||||||
from cache_helper import get_nc_config, get_git_latest_activity
|
from cache_helper import get_nc_config, get_git_latest_activity
|
||||||
|
|
||||||
# Constants
|
# Constants
|
||||||
@@ -176,7 +176,7 @@ def tools():
|
|||||||
@app.route("/playing")
|
@app.route("/playing")
|
||||||
def playing():
|
def playing():
|
||||||
"""Get the currently playing Spotify track."""
|
"""Get the currently playing Spotify track."""
|
||||||
track_info = get_spotify_track()
|
track_info = get_playing_spotify_track()
|
||||||
if "error" in track_info:
|
if "error" in track_info:
|
||||||
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)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from bs4 import BeautifulSoup
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
# Create blueprint
|
# Create blueprint
|
||||||
app = Blueprint("now", __name__, url_prefix="/now")
|
app = Blueprint("now", __name__, url_prefix="/")
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=16)
|
@lru_cache(maxsize=16)
|
||||||
@@ -136,14 +136,14 @@ def render_curl(date=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/", strict_slashes=False)
|
@app.route("/now", strict_slashes=False)
|
||||||
def index():
|
def index():
|
||||||
if isCLI(request):
|
if isCLI(request):
|
||||||
return render_curl()
|
return render_curl()
|
||||||
return render_latest(handshake_scripts=getHandshakeScript(request.host))
|
return render_latest(handshake_scripts=getHandshakeScript(request.host))
|
||||||
|
|
||||||
|
|
||||||
@app.route("/<path:path>")
|
@app.route("/now/<path:path>")
|
||||||
def path(path):
|
def path(path):
|
||||||
if isCLI(request):
|
if isCLI(request):
|
||||||
return render_curl(path)
|
return render_curl(path)
|
||||||
@@ -151,6 +151,7 @@ def path(path):
|
|||||||
return render(path, handshake_scripts=getHandshakeScript(request.host))
|
return render(path, handshake_scripts=getHandshakeScript(request.host))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/now/old", strict_slashes=False)
|
||||||
@app.route("/old", strict_slashes=False)
|
@app.route("/old", strict_slashes=False)
|
||||||
def old():
|
def old():
|
||||||
now_dates = list_dates()[1:]
|
now_dates = list_dates()[1:]
|
||||||
@@ -187,16 +188,26 @@ def old():
|
|||||||
@app.route("/rss.xml")
|
@app.route("/rss.xml")
|
||||||
def rss():
|
def rss():
|
||||||
host = "https://" + request.host
|
host = "https://" + request.host
|
||||||
|
path = request.path
|
||||||
if ":" in request.host:
|
if ":" in request.host:
|
||||||
host = "http://" + request.host
|
host = "http://" + request.host
|
||||||
# Generate RSS feed
|
# Generate RSS feed
|
||||||
now_pages = list_page_files()
|
now_pages = list_page_files()
|
||||||
rss = f'<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Nathan.Woodburn/</title><link>{host}</link><description>See what I\'ve been up to</description><language>en-us</language><lastBuildDate>{datetime.datetime.now(tz=datetime.timezone.utc).strftime("%a, %d %b %Y %H:%M:%S %z")}</lastBuildDate><atom:link href="{host}/now.rss" rel="self" type="application/rss+xml" />'
|
rss = f'<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Nathan.Woodburn/</title><link>{host}</link><description>See what I\'ve been up to</description><language>en-us</language><lastBuildDate>{datetime.datetime.now(tz=datetime.timezone.utc).strftime("%a, %d %b %Y %H:%M:%S %z")}</lastBuildDate><atom:link href="{host}{path}" rel="self" type="application/rss+xml" />'
|
||||||
for page in now_pages:
|
for page in now_pages:
|
||||||
link = page.strip(".html")
|
link = page.strip(".html")
|
||||||
date = datetime.datetime.strptime(link, "%y_%m_%d")
|
date = datetime.datetime.strptime(link, "%y_%m_%d")
|
||||||
|
pubdate = date.strftime("%a, %d %b %Y 00:00:00 +0000")
|
||||||
date = date.strftime("%A, %B %d, %Y")
|
date = date.strftime("%A, %B %d, %Y")
|
||||||
rss += f"<item><title>What's Happening {date}</title><link>{host}/now/{link}</link><description>Latest updates for {date}</description><guid>{host}/now/{link}</guid></item>"
|
rss += f"""
|
||||||
|
<item>
|
||||||
|
<title>What's Happening {date}</title>
|
||||||
|
<link>{host}/now/{link}</link>
|
||||||
|
<description>Latest updates for {date}</description>
|
||||||
|
<pubDate>{pubdate}</pubDate>
|
||||||
|
<guid isPermaLink="true">{host}/now/{link}</guid>
|
||||||
|
</item>
|
||||||
|
"""
|
||||||
rss += "</channel></rss>"
|
rss += "</channel></rss>"
|
||||||
return make_response(rss, 200, {"Content-Type": "application/rss+xml"})
|
return make_response(rss, 200, {"Content-Type": "application/rss+xml"})
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ SPOTIFY_AUTH_URL = "https://accounts.spotify.com/authorize"
|
|||||||
SPOTIFY_TOKEN_URL = "https://accounts.spotify.com/api/token"
|
SPOTIFY_TOKEN_URL = "https://accounts.spotify.com/api/token"
|
||||||
SPOTIFY_CURRENTLY_PLAYING_URL = "https://api.spotify.com/v1/me/player/currently-playing"
|
SPOTIFY_CURRENTLY_PLAYING_URL = "https://api.spotify.com/v1/me/player/currently-playing"
|
||||||
|
|
||||||
SCOPE = "user-read-currently-playing user-read-playback-state"
|
|
||||||
|
SCOPE = "user-read-currently-playing user-read-playback-state user-read-recently-played"
|
||||||
|
|
||||||
ACCESS_TOKEN = None
|
ACCESS_TOKEN = None
|
||||||
REFRESH_TOKEN = os.getenv("SPOTIFY_REFRESH_TOKEN")
|
REFRESH_TOKEN = os.getenv("SPOTIFY_REFRESH_TOKEN")
|
||||||
@@ -103,11 +104,11 @@ def callback():
|
|||||||
@app.route("/playing")
|
@app.route("/playing")
|
||||||
def currently_playing():
|
def currently_playing():
|
||||||
"""Public endpoint showing your current track."""
|
"""Public endpoint showing your current track."""
|
||||||
track = get_spotify_track()
|
track = get_playing_spotify_track()
|
||||||
return json_response(request, {"spotify": track}, 200)
|
return json_response(request, {"spotify": track}, 200)
|
||||||
|
|
||||||
|
|
||||||
def get_spotify_track():
|
def get_playing_spotify_track():
|
||||||
"""Internal function to get current playing track without HTTP context."""
|
"""Internal function to get current playing track without HTTP context."""
|
||||||
token = refresh_access_token()
|
token = refresh_access_token()
|
||||||
if not token:
|
if not token:
|
||||||
@@ -115,9 +116,9 @@ def get_spotify_track():
|
|||||||
|
|
||||||
headers = {"Authorization": f"Bearer {token}"}
|
headers = {"Authorization": f"Bearer {token}"}
|
||||||
response = requests.get(SPOTIFY_CURRENTLY_PLAYING_URL, headers=headers)
|
response = requests.get(SPOTIFY_CURRENTLY_PLAYING_URL, headers=headers)
|
||||||
|
|
||||||
if response.status_code == 204:
|
if response.status_code == 204:
|
||||||
return {"error": "Nothing is currently playing."}
|
# return {"error": "Nothing is currently playing."}
|
||||||
|
return get_last_spotify_track()
|
||||||
elif response.status_code != 200:
|
elif response.status_code != 200:
|
||||||
return {"error": "Spotify API error", "status": response.status_code}
|
return {"error": "Spotify API error", "status": response.status_code}
|
||||||
|
|
||||||
@@ -135,3 +136,30 @@ def get_spotify_track():
|
|||||||
"duration_ms": data["item"].get("duration_ms", 1),
|
"duration_ms": data["item"].get("duration_ms", 1),
|
||||||
}
|
}
|
||||||
return track
|
return track
|
||||||
|
|
||||||
|
|
||||||
|
def get_last_spotify_track():
|
||||||
|
"""Internal function to get last played track without HTTP context."""
|
||||||
|
token = refresh_access_token()
|
||||||
|
if not token:
|
||||||
|
return {"error": "Failed to refresh access token"}
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}"}
|
||||||
|
response = requests.get(
|
||||||
|
"https://api.spotify.com/v1/me/player/recently-played", headers=headers
|
||||||
|
)
|
||||||
|
if response.status_code != 200:
|
||||||
|
print("Spotify API error:", response.text)
|
||||||
|
return {"error": "Spotify API error", "status": response.status_code}
|
||||||
|
data = response.json()
|
||||||
|
if not data.get("items"):
|
||||||
|
return {"error": "No recently played tracks found."}
|
||||||
|
last_track_info = data["items"][0]["track"]
|
||||||
|
track = {
|
||||||
|
"song_name": last_track_info["name"],
|
||||||
|
"artist": ", ".join([artist["name"] for artist in last_track_info["artists"]]),
|
||||||
|
"album_name": last_track_info["album"]["name"],
|
||||||
|
"album_art": last_track_info["album"]["images"][0]["url"],
|
||||||
|
"played_at": data["items"][0]["played_at"],
|
||||||
|
}
|
||||||
|
return track
|
||||||
|
|||||||
4
curl.py
4
curl.py
@@ -2,7 +2,7 @@ from flask import render_template
|
|||||||
from tools import getAddress, get_tools_data, getClientIP
|
from tools import getAddress, get_tools_data, getClientIP
|
||||||
import os
|
import os
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
from blueprints.spotify import get_spotify_track
|
from blueprints.spotify import get_playing_spotify_track
|
||||||
from cache_helper import get_git_latest_activity, get_projects as get_projects_cached
|
from cache_helper import get_git_latest_activity, get_projects as get_projects_cached
|
||||||
|
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ def curl_response(request):
|
|||||||
"index.ascii",
|
"index.ascii",
|
||||||
repo=get_current_project(),
|
repo=get_current_project(),
|
||||||
ip=getClientIP(request),
|
ip=getClientIP(request),
|
||||||
spotify=get_spotify_track(),
|
spotify=get_playing_spotify_track(),
|
||||||
),
|
),
|
||||||
200,
|
200,
|
||||||
{"Content-Type": "text/plain; charset=utf-8"},
|
{"Content-Type": "text/plain; charset=utf-8"},
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ RATE_LIMIT_WINDOW = 3600 # 1 hour in seconds
|
|||||||
RESTRICTED_ROUTES = ["ascii"]
|
RESTRICTED_ROUTES = ["ascii"]
|
||||||
REDIRECT_ROUTES = {
|
REDIRECT_ROUTES = {
|
||||||
"contact": "/#contact",
|
"contact": "/#contact",
|
||||||
"old": "/now/old",
|
|
||||||
"/meet": "https://cloud.woodburn.au/apps/calendar/appointment/PamrmmspWJZr",
|
"/meet": "https://cloud.woodburn.au/apps/calendar/appointment/PamrmmspWJZr",
|
||||||
"/meeting": "https://cloud.woodburn.au/apps/calendar/appointment/PamrmmspWJZr",
|
"/meeting": "https://cloud.woodburn.au/apps/calendar/appointment/PamrmmspWJZr",
|
||||||
"/appointment": "https://cloud.woodburn.au/apps/calendar/appointment/PamrmmspWJZr",
|
"/appointment": "https://cloud.woodburn.au/apps/calendar/appointment/PamrmmspWJZr",
|
||||||
|
|||||||
@@ -70,8 +70,6 @@
|
|||||||
<li class="list-inline-item" style="margin-top: 15px;"> <a class="btn btn-primary btn-lg btn-default" role="button" href="https://paypal.me/nathanwoodburn" target="_blank" style="width: auto;"><i class="fab fa-paypal fa-fw"></i><span class="network-name"> Paypal</span></a></li>
|
<li class="list-inline-item" style="margin-top: 15px;"> <a class="btn btn-primary btn-lg btn-default" role="button" href="https://paypal.me/nathanwoodburn" target="_blank" style="width: auto;"><i class="fab fa-paypal fa-fw"></i><span class="network-name"> Paypal</span></a></li>
|
||||||
<li class="list-inline-item" style="margin-top: 15px;"> <a class="btn btn-primary btn-lg btn-default" role="button" href="https://github.com/sponsors/Nathanwoodburn" target="_blank" style="width: auto;"><i class="fab fa-github fa-fw"></i><span class="network-name"> Github</span></a></li>
|
<li class="list-inline-item" style="margin-top: 15px;"> <a class="btn btn-primary btn-lg btn-default" role="button" href="https://github.com/sponsors/Nathanwoodburn" target="_blank" style="width: auto;"><i class="fab fa-github fa-fw"></i><span class="network-name"> Github</span></a></li>
|
||||||
<li class="list-inline-item" style="margin-top: 15px;"> <a class="btn btn-primary btn-lg btn-default" role="button" href="https://donate.stripe.com/8wM6pv0VD08Xe408ww" target="_blank" style="width: auto;"><i class="fab fa-stripe-s fa-fw"></i><span class="network-name"> Stripe</span></a></li>
|
<li class="list-inline-item" style="margin-top: 15px;"> <a class="btn btn-primary btn-lg btn-default" role="button" href="https://donate.stripe.com/8wM6pv0VD08Xe408ww" target="_blank" style="width: auto;"><i class="fab fa-stripe-s fa-fw"></i><span class="network-name"> Stripe</span></a></li>
|
||||||
<li class="list-inline-item" style="margin-top: 15px;"> <a class="btn btn-primary btn-lg btn-default" role="button" href="https://wise.com/pay/me/nathanjoelw6" target="_blank" style="width: auto;"><span class="network-name"> Wise</span></a></li>
|
|
||||||
<li class="list-inline-item" style="margin-top: 15px;"> <a class="btn btn-primary btn-lg btn-default" role="button" href="https://revolut.me/nwoodburn" target="_blank" style="width: auto;"><span class="network-name"> Revolut</span></a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<h4>Crypto Options</h4><div class="dropdown">
|
<h4>Crypto Options</h4><div class="dropdown">
|
||||||
<button class="btn btn-primary btn-lg btn-default" aria-expanded="false" data-bs-toggle="dropdown" type="button" id="dropdownButton">Select Crypto</button>
|
<button class="btn btn-primary btn-lg btn-default" aria-expanded="false" data-bs-toggle="dropdown" type="button" id="dropdownButton">Select Crypto</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user