1
0
Fork
You've already forked geocat
0
Bot de Mastodon que fa jugar als usuaris a endevinar les comarques catalanes. Tot el codi i la comunicació amb els usuaris és en català.
  • Python 100%
2026年07月12日 12:20:24 +02:00
app Mostra l'estat dels límits de l'API a cada resposta de partida. Destaca amb ⚠️ el límit de l'API quan queda esgotat. Corregeix falsos positius en validar respostes (Urgell/Alt Urgell/Pla d'Urgell). Normalitza variants d'apòstrof abans de comparar respostes. Permet espai opcional entre @ i el nom d'usuari en detectar mencions. Accepta un article inicial opcional en validar respostes; corregeix 'Selva' a 'la Selva' 2026年07月12日 12:20:24 +02:00
geocat.py Mostra l'estat dels límits de l'API a cada resposta de partida. Destaca amb ⚠️ el límit de l'API quan queda esgotat. Corregeix falsos positius en validar respostes (Urgell/Alt Urgell/Pla d'Urgell). Normalitza variants d'apòstrof abans de comparar respostes. Permet espai opcional entre @ i el nom d'usuari en detectar mencions. Accepta un article inicial opcional en validar respostes; corregeix 'Selva' a 'la Selva' 2026年07月12日 12:20:24 +02:00
LICENSE primera versió 2026年07月11日 19:10:50 +02:00
README.md Mostra l'estat dels límits de l'API a cada resposta de partida. Destaca amb ⚠️ el límit de l'API quan queda esgotat. Corregeix falsos positius en validar respostes (Urgell/Alt Urgell/Pla d'Urgell). Normalitza variants d'apòstrof abans de comparar respostes. Permet espai opcional entre @ i el nom d'usuari en detectar mencions. Accepta un article inicial opcional en validar respostes; corregeix 'Selva' a 'la Selva' 2026年07月12日 12:20:24 +02:00
requirements.txt primera versió 2026年07月11日 19:10:50 +02:00

geocat

Bot de Mastodon que fa jugar als usuaris a endevinar comarques catalanes. Tot el codi i la comunicació amb els usuaris és en català.

Publica el mapa de Catalunya amb una comarca destacada i demana quina és. Cada encert encadena una comarca nova; el primer error acaba la partida i en desa la puntuació. Hi ha un rànquing dels millors jugadors i un panell personal amb les millors partides de cadascú.

Com jugar

Menciona el compte del bot amb una d'aquestes paraules:

Paraula Què fa
jugar Comença una partida nova (ratxa a 0) i mostra la primera comarca a endevinar.
(resposta al fil) Escriu el nom de la comarca destacada en resposta a la pregunta oberta.
millors Mostra el top 10 de jugadors per la seva millor partida individual.
panell Mostra les teves 10 millors partides pròpies.
ajuda Torna a mostrar aquestes instruccions.

Com funciona una partida:

  • Cada encert suma un punt a la ratxa actual i, en el mateix tut, mostra en verd totes les comarques ja encertades (amb el nom escrit només a la darrera) i en vermell la comarca nova a endevinar.
  • El primer error acaba la partida: es desa la ratxa final a la base de dades, es mostra el mapa amb l'historial verd i la comarca fallada en vermell, i es publica el rànquing actualitzat.
  • Si s'encerten les 43 comarques sense cap error, la partida acaba en victòria.
  • Demanar millors o panell en resposta a una partida oberta la dona per finalitzada (es desa la ratxa que portava) abans de respondre. Demanar ajuda, en canvi, no afecta cap partida activa.

Arquitectura

  • Mastodon: client fet a mida amb aiohttp (app/libraries/mastodon_api.py) — no fa servir Mastodon.py. La seva API de streaming és síncrona i no es pot fer asíncrona sense un pont fil-bloquejant; com que aquí tot és aiohttp, el streaming (GET /api/v1/streaming/user, Server-Sent Events) és nadiament async.
  • Base de dades: PostgreSQL via asyncpg, a través del pool propi de l'aplicació (app.services.postgres.dbpool) i les consultes a app/libraries/asyncdb.py (Database.desa_partida, Database.obtenir_rankings, Database.obtenir_millors_partides).
  • Mapes: matplotlib, sense dependència de geopandas/GDAL (app/geo/mapa_comarques.py).
  • Tot el bot és asyncio de cap a cap: no hi ha fils ni bridges bloquejants.

Estructura de fitxers

geocat.py # bot principal (streaming, lògica del joc)
app/
 geo/
 mapa_comarques.py # generació de tots els mapes
 comarques.geojson # 43 comarques (juliol 2026, inclou Lluçanès i Moianès)
 libraries/
 mastodon_api.py # client Mastodon fet a mida (aiohttp)
 asyncdb.py # consultes SQL del joc (Database)
 setup.py # configuració de l'aplicació (Setup) — propi del projecte
 services/
 postgres.py # pool de connexió Postgres (dbpool) — propi del projecte
 db/
 schema.py # creació de taules (create_dbschema) — propi del projecte
 imatges/ # cache de mapes generats (es crea sola en executar-se)

Requisits

pip install aiohttp asyncpg matplotlib loguru python-dotenv

Base de dades

create_dbschema() crea, entre altres, la taula partides — una fila per cada partida jugada (no un total acumulat per usuari):

CREATETABLEIFNOTEXISTSpartides(idSERIALPRIMARYKEY,acctTEXTNOTNULL,encertsINTEGERNOTNULLDEFAULT0,creat_elTIMESTAMPTZNOTNULLDEFAULTnow());CREATEINDEXidx_partides_acctONpartides(acct);

El rànquing (millors) agrupa per acct i mostra la puntuació màxima de cadascú; el panell (panell) mostra les partides d'un usuari concret ordenades de major a menor puntuació.

Desat en temps real: en començar una partida es crea de seguida la fila corresponent a partides amb encerts=0, i es va actualitzant (no re-inserint) a cada encert. Això vol dir que, si el bot es reinicia enmig d'una partida, la ratxa que portava fins al darrer encert ja està desada — només es perd el que hi havia des de l'últim encert fins al moment de tallar-se (si n'hi havia cap en curs). Com a efecte secundari, mentre algú està jugant, la seva partida en curs ja apareix a millors/panell amb el recompte parcial, no només un cop acabada.

Hi ha també una taula encerts (una fila fixa per usuari amb un total acumulat) que ve d'una primera versió del joc. Ja no la fa servir cap part del codi actual; es manté només per no trencar res si en depèn una altra part del vostre sistema.

Configuració

Al executar geocat.py per primer cop, es demanen els parametres de configuració i es crea la base de dades

Rendiment i cache

  • Els mapes de pregunta i d'error es guarden a app/imatges/ la primera vegada que surt cada comarca, i es reutilitzen les següents.
  • Els mapes que depenen de l'estat d'una partida concreta (el de progrés durant la partida, el de resultat final, i els de millors/panell) no es guarden a cache, perquè el seu contingut canvia cada vegada.
  • El comarques.geojson d'aquest projecte ha estat netejat i simplificat (geometria original triplicada per error de conversió, ja corregit) per generar cada mapa nou en menys d'un segon.
  • Si mai canvieu com es dibuixen els mapes (colors, peu de pàgina, etc.), cal buidar app/imatges/*.png perquè els canvis es notin — la cache no es regenera sola.

Límits coneguts

  • L'estat de les partides obertes (partides_actives, ratxes, demanades, encertades) viu només en memòria del procés; si el bot es reinicia enmig d'una partida, aquella partida concreta es perd (el rànquing i les partides ja completades, no: això viu a la base de dades).
  • Si l'API de Mastodon respon amb un límit de peticions (429), el bot avisa l'usuari en català amb els segons d'espera reals, calculats a partir de la capçalera X-RateLimit-Reset que Mastodon envia de veritat (Mastodon no envia Retry-After; per defecte, POST /api/v1/media permet només 30 pujades cada 30 minuts, molt més estricte que el límit general de 300 peticions/5 min). Cap canvi d'estat (ratxa, comarques encertades, pregunta oberta) es dona per fet fins que la publicació a Mastodon no ha tingut èxit real, així que si es peta a mig torn, la pregunta original es manté oberta i n'hi ha prou de tornar-la a respondre un cop passi l'estona — no cal tornar a dir "jugar" ni es perd la ratxa.
  • Cada resposta a un encert o error inclou, al final del toot, l'últim estat conegut dels dos límits (Límit API: X/300 ... i Límit pujada d'imatges: X/30 ...), llegit de les capçaleres X-RateLimit-* de la crida més recent — no es fa cap petició extra només per consultar-ho, per això el número de "Límit API" pot anar un torn per darrere del que s'acaba de gastar en aquell mateix missatge.
  • Es dona per fet un jugador amb una partida oberta alhora; dues partides simultànies del mateix usuari no estan cobertes.