Show retroachievements awards on a dedicated page

This commit is contained in:
theo@manjaro 2023-12-20 15:57:22 -05:00
parent 7b5b92b8f3
commit c578e5ecc1
7 changed files with 109 additions and 41 deletions

7
default_rareview.gmi Normal file
View File

@ -0,0 +1,7 @@
# $AWARDNAME
Award got on the $AWARDDATE
=> $AWARDGAMEURL View this game on RetroAchievements
No review written yet, come back later!

View File

@ -5,6 +5,11 @@
=> atom.xml Flux RSS complet => atom.xml Flux RSS complet
=> atom_fr.xml Flux RSS, en français seulement => atom_fr.xml Flux RSS, en français seulement
=> atom_en.xml RSS feed, in English only => atom_en.xml RSS feed, in English only
=> atom_rareview.xml RSS feed, only RetroAchievements reviews
## Contact
=> /contact.gmi Contact page
## En français (English at the bottom) ## En français (English at the bottom)
@ -12,22 +17,15 @@
Salut! Moi c'est Théo (il/iel), j'étudie l'informatique à l'Université de Strasbourg! Salut! Moi c'est Théo (il/iel), j'étudie l'informatique à l'Université de Strasbourg!
Affectif et fatigué, je suis un grand fan de jeux vidéos (principalement rétros). Mes favoris sont les jeux de plateforme, style Celeste, Super Meat Boy, 1001 Spikes, ou autres. J'ai eu la chance de grandir avec une GameBoy Color dans les mains, et une GameCube dans le salon. Je programme aussi quand j'en trouve la motivation, en python, en C, Lua ou en Zig. Affectif et fatigué, je suis un grand fan de jeux vidéos (principalement rétros). Mes favoris sont les jeux de plateforme. Je programme aussi quand j'en trouve la motivation.
Pendant mon temps libre, je m'intéresse aussi à la cuisine, à la philosophie, à l'éthique, et à la sociologie. À la croisée de ces intérêts se trouve mon régime végétarien. Il y a tellement de choses à découvrir, à changer, à faire. Pendant mon temps libre, je m'intéresse aussi à la cuisine, à la philosophie, à l'éthique, et à la sociologie. À la croisée de ces intérêts se trouve mon régime végétarien.
### À propos de ce site ### À propos de ce site
#### Le contenu
Ce que j'écris ici est avant tout destiné à mon moi du futur, n'implique donc que moi, et n'est pas professionnel.
Au lieu de me répéter si je dois expliquer quelque chose à des moments différents, j'écris. Formaliser mes idées m'aide beaucoup, cela me permet de me faire une mise au point, en plus de servir de mémo.
Ce site fait parti d'un webring, le fediring, rassemblant diverses sites (souvent anglophones) dont les auteur.e.s ont une présence sur le fédiverse. Ce site fait parti d'un webring, le fediring, rassemblant diverses sites (souvent anglophones) dont les auteur.e.s ont une présence sur le fédiverse.
=> https://fediring.net/ Le site du fediring => https://fediring.net/ Le site du fediring
#### D'un point de vue technique
Généré à partir du même générateur que Ploum.net (même si légèrement modifié), un grand merci à ellui pour avoir laissé ses sources en libre accès! Généré à partir du même générateur que Ploum.net (même si légèrement modifié), un grand merci à ellui pour avoir laissé ses sources en libre accès!
=> https://ploum.net/ Le site de Ploum => https://ploum.net/ Le site de Ploum
@ -42,22 +40,16 @@ Mon site est hébergé chez sourcehut, est généré statiquement, et ne comport
Hi! I'm Théo (he/they), studying computer science at Strasbourg's university (in France)! Hi! I'm Théo (he/they), studying computer science at Strasbourg's university (in France)!
I'm an always cuddly, often tired, video game fan (I mainly play retro ones these days). My favorites are platformer games, like Celeste, Super Meat Boy, 1001 Spikes, or others. I've been lucky enough to grow up with a GameBoy Color in my hand, and a GameCube in my living room. I'm also programming sometimes, in python, C, Lua and Zig. I'm an always cuddly, often tired, video game fan (I mainly play retro ones these days). My favorites are platformer games. I'm also programming sometimes.
I'm also interested in cooking, philosophy, ethics, and sociology. I try not to cause suffering, notably trough what I'm eating. I'm also interested in cooking, philosophy, ethics, and sociology. I try not to cause suffering, notably trough what I'm eating.
There's so much to discover, so much to change, so much to do, that sometimes it gets a bit scary.
### About this site ### About this site
I'm mainly writing for myself and my future self, it is a personnal blog. Having my thoughts written somewhere is helpful when I need to explain the same thing at different times.
Writting also helps me focus on my thoughts.
This site is part of a webring, the fediring, composed of other great sites. The point of this one is to link people that have a presence on the fediverse. This site is part of a webring, the fediring, composed of other great sites. The point of this one is to link people that have a presence on the fediverse.
=> https://fediring.net/ Fediring's website => https://fediring.net/ Fediring's website
#### On the technical side This site use the same generator (with some modifications) as Ploum's one. Huge thanks to them for making it!
This site use the same generator (with some minor modifications) as Ploum's one. Huge thanks to them for making it!
=> https://ploum.net/ Ploum's site => https://ploum.net/ Ploum's site
@ -65,9 +57,7 @@ My site is currently hosted at SourceHut's.
=> https://sr.ht/ SourceHut's site => https://sr.ht/ SourceHut's site
## Contact ## Misc
=> /contact.gmi Contact page
I also made a 88x31 button for this site! I also made a 88x31 button for this site!
You can integrate it in your site with the following code : You can integrate it in your site with the following code :

View File

@ -8,6 +8,7 @@
<link href="atom.xml" type="application/atom+xml" rel="alternate" title="$GLOBAL_TITLE (all posts)" > <link href="atom.xml" type="application/atom+xml" rel="alternate" title="$GLOBAL_TITLE (all posts)" >
<link href="atom_en.xml" type="application/atom+xml" rel="alternate" title="$GLOBAL_TITLE (EN only)" > <link href="atom_en.xml" type="application/atom+xml" rel="alternate" title="$GLOBAL_TITLE (EN only)" >
<link href="atom_fr.xml" type="application/atom+xml" rel="alternate" title="$GLOBAL_TITLE (en français)" > <link href="atom_fr.xml" type="application/atom+xml" rel="alternate" title="$GLOBAL_TITLE (en français)" >
<link href="atom_rareview.xml" type="application/atom+xml" rel="alternate" title="$GLOBAL_TITLE (RetroAchievements Reviews)" >
<link rel="shortcut icon" href="img/favicon.png" > <link rel="shortcut icon" href="img/favicon.png" >
<link rel="me" href="https://soc.webair.xyz/@theo"> <link rel="me" href="https://soc.webair.xyz/@theo">
<link rel="canonical" href="$HTMLLINK"> <link rel="canonical" href="$HTMLLINK">
@ -54,7 +55,7 @@
a { a {
color:var(--fg-alt); color:var(--fg-alt);
text-decoration:none; text-decoration:none;
padding:1em 0; border:1em 0;
} }
a:hover { a:hover {
text-decoration:underline; text-decoration:underline;
@ -80,6 +81,7 @@
text-align: center; text-align: center;
font-variant: small-caps; font-variant: small-caps;
font-weight: bold; font-weight: bold;
padding: 1em;
} }
.horizontal { .horizontal {
text-align: center; text-align: center;
@ -102,7 +104,8 @@
<div class="navbar"> <div class="navbar">
<a href="/index.html">Blog</a> <a href="/index.html">Blog</a>
<a href="/software.html">Software</a> <a href="/software.html">Software</a>
<a href="/about.html">À Propos</a> <a href="/retroachievements.html">RetroAchievements</a>
<a href="/about.html">About</a>
<a href="/contact.html">Contact</a> <a href="/contact.html">Contact</a>
</div> </div>
<article> <article>

View File

@ -9,6 +9,8 @@ import html
from datetime import datetime from datetime import datetime
import textwrap import textwrap
import unicodedata import unicodedata
import ra
import racredentials
global_title = "webair.xyz" global_title = "webair.xyz"
global_subtitle = "Theo's web corner" global_subtitle = "Theo's web corner"
@ -33,6 +35,8 @@ old_post_url = ["2005-01-25","2013-05-17","2011-02-07","2012-03-19","2012-01-18"
html_page_template = "page_template.html" html_page_template = "page_template.html"
email_template = "email_template.html" email_template = "email_template.html"
gemini_page_template = "page_template.gmi" gemini_page_template = "page_template.gmi"
raindex_template = "raindex_template.gmi"
raindex_destination = "rareview/retroachievements.gmi"
image_extensions = [".png", ".jpg", ".jpeg"] image_extensions = [".png", ".jpg", ".jpeg"]
@ -263,7 +267,7 @@ def build_list(allposts,folder,local=False):
allposts = build_list(allposts,ff,local=local) allposts = build_list(allposts,ff,local=local)
elif f.endswith(".gmi") and "index" not in f and "template" not in f: elif f.endswith(".gmi") and "index" not in f and "template" not in f:
if len(folder) > 2: if len(folder) > 2:
lang = folder[:2] lang = folder
else: else:
lang = "fr" lang = "fr"
post = build_post(p,lang=lang,local=local) post = build_post(p,lang=lang,local=local)
@ -340,7 +344,7 @@ def build_index(allposts,folder,short=False):
index = {} index = {}
if folder: if folder:
indexname = "index_" + folder.strip("/").replace("/","_") indexname = "index_" + folder.strip("/").replace("/","_")
lang = folder[:2] lang = folder
else: else:
if short: if short:
indexname = "index" indexname = "index"
@ -505,6 +509,43 @@ def copy_static_files(source, dest):
os.popen(f"cp -r {source}/* {dest}/") os.popen(f"cp -r {source}/* {dest}/")
def generate_raindex(awards, dest):
content = ""
with open(raindex_template) as f:
content = f.read()
content += "\n"
for award in reversed(awards):
content += f"=> {award.url} {award.type} {award.name}\n"
with open(dest, "w") as f:
f.write(content)
def generate_default_rareviews(awards):
for award in awards:
default_page = ""
with open("default_rareview.gmi", "r") as f:
default_page = f.read()
filepath = Path(award.url)
# Check if a file with same name doesn't exists in current folder
if not os.path.exists(filepath):
# Check if a review was not already written
if not os.path.exists(os.path.join("rareview", filepath)):
# Write a default page
with open(filepath, "w") as f:
f.write(
default_page.replace("$AWARDNAME", award.name)
.replace("$AWARDDATE", award.date)
.replace("$AWARDGAMEURL", award.gameurl)
)
# Build a post with it
post = build_post(filepath, lang="rareview")
writehtml(post)
writegmi(post)
os.remove(filepath)
else:
print(f"Warning, file {filepath} exists in root folder, skipping.")
# Main call # Main call
if __name__ == "__main__": if __name__ == "__main__":
# Check for the destination folders # Check for the destination folders
@ -513,10 +554,14 @@ if __name__ == "__main__":
os.mkdir(dir) os.mkdir(dir)
all_posts = [] all_posts = []
local = False local = False
# Generate the RetroAchievements index page
awards = ra.getAwards(racredentials.user, racredentials.key)
generate_raindex(awards, raindex_destination)
# Normal generation
if len(sys.argv) > 1: if len(sys.argv) > 1:
local = sys.argv[1] == "local" local = sys.argv[1] == "local"
print("building locally") print("building locally")
for folder in ["", "fr", "en"]: for folder in ["", "fr", "en", "rareview"]:
all_posts = build_list(all_posts, folder, local=local) all_posts = build_list(all_posts, folder, local=local)
all_posts = build_index(all_posts, folder) all_posts = build_index(all_posts, folder)
write_atom_index(all_posts, folder) write_atom_index(all_posts, folder)
@ -527,4 +572,8 @@ if __name__ == "__main__":
for p in all_posts: for p in all_posts:
writehtml(p) writehtml(p)
writegmi(p) writegmi(p)
# Generate default RaReview pages
generate_default_rareviews(awards)
# Delete the generated raindex
os.remove(raindex_destination)
copy_static_files("static", htmldir) copy_static_files("static", htmldir)

37
ra.py
View File

@ -23,9 +23,11 @@ class Award:
# Only keep letters, and replace spaces # Only keep letters, and replace spaces
stripped = "" stripped = ""
for c in name.strip(): for c in name.strip():
if ord("a") <= ord(c) <= ord("z") or ord("0") <= ord(c) <= ord("9"): if ord("a") <= ord(c) <= ord("z"):
stripped += c stripped += c
elif c == " ": elif ord("0") <= ord(c) <= ord("9"):
stripped += c
else:
stripped += "-" stripped += "-"
# delete multiple following dashes # delete multiple following dashes
splitted = stripped.split("-") splitted = stripped.split("-")
@ -42,21 +44,24 @@ def request(path):
def getAwards(user, key): def getAwards(user, key):
response = request(f"API_GetUserAwards.php?z={user}&y={key}&u={user}")[ response = request(f"API_GetUserAwards.php?z={user}&y={key}&u={user}")
"VisibleUserAwards" if "VisibleUserAwards" in response.keys():
] response = response["VisibleUserAwards"]
indexed = {} indexed = {}
# Returns only the mastered award # Returns only the mastered award
# in case there's both a completed and master award # in case there's both a completed and master award
for award in [Award(x) for x in response]: for award in [Award(x) for x in response]:
if award.name in indexed.keys(): if award.name in indexed.keys():
if indexed[award.name].type == "Game Beaten": if indexed[award.name].type == "Game Beaten":
indexed[award.name] = award
else:
indexed[award.name] = award indexed[award.name] = award
else: sorted = list(indexed.values())
indexed[award.name] = award sorted.sort(key=lambda x: x.date)
sorted = list(indexed.values()) return sorted
sorted.sort(key=lambda x: x.date) else:
return sorted print(response)
return []
if __name__ == "__main__": if __name__ == "__main__":

11
raindex_template.gmi Normal file
View File

@ -0,0 +1,11 @@
# RetroAchievements Awards
Here's a list of my most recently mastered/completed games on RetroAchievements.
=> https://retroachievements.org/user/ayte/ My profile
I wrote reviews for some of them.
=> /index_rareview.gmi All the reviews I wrote
## The full list of awards

3
rareview/signature.html Normal file
View File

@ -0,0 +1,3 @@
<p>If you can read this, then maybe you're interested in subscribing to my reviews <a href="/atom_rareview.xml">by RSS</a>.</p>
<p>You can see the full list of my RetroAchievements Awards <a href="/retroachievements.html">here</a>.</p>
<p>Thanks for your time ❤</p>