Ensimmäinen versio: Spotify-päivittäjä
This commit is contained in:
commit
00c0fd5189
4 changed files with 239 additions and 0 deletions
10
.env.example
Normal file
10
.env.example
Normal 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
13
.gitignore
vendored
Normal 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
75
README.md
Normal 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
141
levyraati.py
Normal 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()
|
||||||
|
|
||||||
Loading…
Reference in a new issue