Ensimmäinen versio: Spotify-päivittäjä

This commit is contained in:
Toni Fadjukoff 2026-03-08 14:16:17 +00:00
commit 00c0fd5189
4 changed files with 239 additions and 0 deletions

10
.env.example Normal file
View file

@ -0,0 +1,10 @@
SPOTIPY_CLIENT_ID="From Spotify Developer"
SPOTIPY_CLIENT_SECRET="Acquire from Spotify Developer Console"
SPOTIPY_REDIRECT_URI="http://localhost:8888/callback"
PLAYLIST_ID="Spotify playlist ID"
WIKI_API_URL="https://example.com/wiki/api.php"
WIKI_PAGE_TITLE="Levyraati"
WIKI_USERNAME="wiki user"
WIKI_PASSWORD="correct horse battery staple"

13
.gitignore vendored Normal file
View file

@ -0,0 +1,13 @@
# Salaisuudet ja keksit
.env
.cache
# Pythonin virtuaaliympäristö ja välimuisti
.venv/
__pycache__/
# Vimin tiedostot
*.swp
# Mahdolliset lokitiedostot
skripti_loki.log

75
README.md Normal file
View file

@ -0,0 +1,75 @@
# Wiki-to-Spotify Soittolistan Päivittäjä 🎵
Tämä Python-skripti hakee automaattisesti kuluvan viikon biisivalinnat MediaWiki-sivulta ja päivittää ne haluttuun Spotifyn soittolistaan. Skripti on suunniteltu ajettavaksi automaattisesti taustalla (esim. Cronilla).
## Ominaisuudet
* Kirjautuu MediaWiki-rajapintaan ja lukee kuluvan viikon (esim. `== Viikko 10 ==`) sisällön.
* Etsii tekstistä suorat Spotify-linkit.
* Jättää huomiotta muiden palveluiden (esim. YouTube) linkit.
* Korvaa valitun Spotify-soittolistan sisällön löydetyillä kappaleilla.
## Vaatimukset
* Python 3
* [uv](https://github.com/astral-sh/uv) (suositeltu) tai perinteinen `pip` paketinhallintaan.
* Spotify Developer -sovelluksen tunnukset (Client ID & Client Secret).
* Tunnukset kohde-MediaWikiin.
## Asennus ja käyttöönotto
**1. Lataa koodi ja luo virtuaaliympäristö**
```bash
# Luo virtuaaliympäristö uv:lla
uv venv
# Aktivoi ympäristö (Mac/Linux)
source .venv/bin/activate
# TAI (Windows)
.venv\Scripts\activate
# Asenna riippuvuudet
uv pip install spotipy requests python-dotenv
```
**2. Asetukset**
Luo projektin juureen tiedosto nimeltä `.env` (voit kopioida `.env.example` -tiedoston pohjaksi) ja täytä sinne omat tietosi:
```env
SPOTIPY_CLIENT_ID="sinun_spotify_client_id"
SPOTIPY_CLIENT_SECRET="sinun_spotify_client_secret"
SPOTIPY_REDIRECT_URI="http://localhost:8888/callback"
PLAYLIST_ID="soittolistan_id_jota_paivitetaan"
WIKI_USERNAME="wiki_tunnuksesi"
WIKI_PASSWORD="wiki_salasanasi"
WIKI_API_URL="https://sinun-wikisi.fi/api.php"
WIKI_PAGE_TITLE="Sivun_Nimi"
```
**3. Ensimmäinen käynnistys ja Spotifyn luvitus**
Ensimmäisellä ajokerralla skriptin täytyy saada sinulta lupa muokata soittolistaasi.
Aja skripti terminaalissa:
```bash
python skripti.py
```
* Skripti tulostaa terminaaliin pitkän Spotify-linkin.
* Kopioi linkki ja avaa se selaimessasi.
* Kirjaudu sisään Spotifyhin ja hyväksy luvat.
* Selaimesi ohjautuu tyhjälle sivulle (localhost). Kopioi tuon sivun osoiterivillä oleva koko URL ja liitä se takaisin terminaaliin.
* Projektikansioosi syntyy `.cache` -tiedosto, joka pitää sinut jatkossa kirjautuneena. **Älä jaa tätä tiedostoa eteenpäin!**
## Automatisointi (Linux/Mac)
Voit asettaa skriptin pyörimään automaattisesti esimerkiksi kerran päivässä Cron-työkalulla:
```bash
crontab -e
```
Lisää tiedoston loppuun (muista muuttaa oikea polku):
```bash
0 4 * * * cd /polku/projektiin && .venv/bin/python skripti.py >> skripti_loki.log 2>&1
```
Tämä ajaa päivityksen joka aamu klo 04:00 ja tallentaa tulosteet `skripti_loki.log` -tiedostoon.

141
levyraati.py Normal file
View file

@ -0,0 +1,141 @@
import spotipy
from spotipy.oauth2 import SpotifyOAuth
import requests
import re
import os
import datetime
from dotenv import load_dotenv
load_dotenv()
CLIENT_ID = os.getenv("SPOTIPY_CLIENT_ID")
CLIENT_SECRET = os.getenv("SPOTIPY_CLIENT_SECRET")
REDIRECT_URI = os.getenv("SPOTIPY_REDIRECT_URI")
PLAYLIST_ID = os.getenv("PLAYLIST_ID")
WIKI_API_URL = os.getenv("WIKI_API_URL")
WIKI_PAGE_TITLE = os.getenv("WIKI_PAGE_TITLE")
WIKI_USERNAME = os.getenv("WIKI_USERNAME")
WIKI_PASSWORD = os.getenv("WIKI_PASSWORD")
def hae_wiki_sisalto():
"""Hakee MediaWiki-sivun raakatekstin APIn kautta."""
# Käytetään Session-oliota, jotta kirjautumiskeksit (cookies) pysyvät tallessa
session = requests.Session()
# Vaihe 1: Haetaan kirjautumistoken (login token)
token_params = {
"action": "query",
"meta": "tokens",
"type": "login",
"format": "json"
}
try:
response = session.get(url=WIKI_API_URL, params=token_params)
data = response.json()
login_token = data['query']['tokens']['logintoken']
# Vaihe 2: Kirjaudutaan sisään tunnuksilla ja tokenilla (POST-pyyntö)
login_params = {
"action": "login",
"lgname": WIKI_USERNAME,
"lgpassword": WIKI_PASSWORD,
"lgtoken": login_token,
"format": "json"
}
login_response = session.post(url=WIKI_API_URL, data=login_params)
login_data = login_response.json()
if login_data.get("login", {}).get("result") != "Success":
print(f"Wikin kirjautuminen epäonnistui: {login_data}")
return ""
print("Kirjauduttu Wikiin onnistuneesti!")
# Vaihe 3: Haetaan vihdoin itse sivun sisältö
page_params = {
"action": "query",
"prop": "revisions",
"rvprop": "content",
"rvslots": "main",
"titles": WIKI_PAGE_TITLE,
"format": "json"
}
page_response = session.get(url=WIKI_API_URL, params=page_params)
page_data = page_response.json()
pages = page_data["query"]["pages"]
page_id = list(pages.keys())[0]
if page_id == "-1":
print("Virhe: Wiki-sivua ei löytynyt!")
return ""
return pages[page_id]["revisions"][0]["slots"]["main"]["*"]
except Exception as e:
print(f"Virhe Wiki-yhteydessä: {e}")
return ""
def paivita_soittolista():
# 1. Haetaan teksti Wikistä
nykyinen_viikko_int = datetime.date.today().isocalendar()[1]
nykyinen_viikko = f"{nykyinen_viikko_int:02d}"
print(f"Kuluva viikko on {nykyinen_viikko}")
wiki_teksti = hae_wiki_sisalto()
if not wiki_teksti:
return
# 3. Eristetään kuluvan viikon osio tekstistä säännöllisellä lausekkeella (regex)
# Etsii esim. "== Viikko 10 ==" ja nappaa kaiken tekstin sen jälkeen
# aina seuraavaan "==" merkkiin asti tai sivun loppuun.
viikko_pattern = rf"==\s*Viikko {nykyinen_viikko}\s*==(.*?(?===|\Z))"
match = re.search(viikko_pattern, wiki_teksti, re.IGNORECASE | re.DOTALL)
if not match:
print(f"\nWiki-sivulta ei löytynyt otsikkoa '== Viikko {nykyinen_viikko} =='. Soittolistaa ei päivitetty.")
return
kuluvan_viikon_teksti = match.group(1)
# 4. Poimitaan suorat Spotify-linkit koodista
track_urls = []
# Käydään wiki-teksti läpi rivi riviltä
for rivi in kuluvan_viikon_teksti.split('\n'):
# Etsitään vain rivit, joissa lukee if '' in rivi:
# Säännöllinen lauseke (regex), joka etsii http- tai https-alkuisen
# linkin heti avaavan hakasulkeen [ jälkeen
match = re.search(r'\[(https?://[^\s\]]+)', rivi)
if match:
url = match.group(1) # Napataan pelkkä linkki
if "spotify.com" in url.lower():
track_urls.append(url)
print(f"Löydettiin linkki: {url}")
else:
print(f"Ohitettiin muun palvelun linkki: {url}")
# 5. Tarkistetaan löytyikö mitään
if not track_urls:
print("\nYhtään Spotify-linkkiä ei löytynyt Wiki-sivulta. Soittolistaa ei päivitetty.")
return
# 6. Kirjaudutaan sisään
scope = "playlist-modify-private playlist-modify-public"
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
redirect_uri=REDIRECT_URI,
scope=scope, open_browser=False))
# 7. Päivitetään soittolista
sp.playlist_replace_items(PLAYLIST_ID, track_urls[:100])
print("Soittolista päivitetty onnistuneesti!")
if __name__ == '__main__':
paivita_soittolista()