Tee scriptistä modulaarisempi
This commit is contained in:
parent
00c0fd5189
commit
6f77e4580c
1 changed files with 160 additions and 115 deletions
257
levyraati.py
257
levyraati.py
|
|
@ -1,141 +1,186 @@
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import datetime
|
||||||
|
import requests
|
||||||
import spotipy
|
import spotipy
|
||||||
from spotipy.oauth2 import SpotifyOAuth
|
from spotipy.oauth2 import SpotifyOAuth
|
||||||
import requests
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
import datetime
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
load_dotenv()
|
# --- KONFIGURAATIO ---
|
||||||
|
|
||||||
CLIENT_ID = os.getenv("SPOTIPY_CLIENT_ID")
|
def lataa_asetukset():
|
||||||
CLIENT_SECRET = os.getenv("SPOTIPY_CLIENT_SECRET")
|
"""Lataa ympäristömuuttujat .env-tiedostosta."""
|
||||||
REDIRECT_URI = os.getenv("SPOTIPY_REDIRECT_URI")
|
load_dotenv()
|
||||||
PLAYLIST_ID = os.getenv("PLAYLIST_ID")
|
return {
|
||||||
|
"SPOTIPY_CLIENT_ID": os.getenv("SPOTIPY_CLIENT_ID"),
|
||||||
WIKI_API_URL = os.getenv("WIKI_API_URL")
|
"SPOTIPY_CLIENT_SECRET": os.getenv("SPOTIPY_CLIENT_SECRET"),
|
||||||
WIKI_PAGE_TITLE = os.getenv("WIKI_PAGE_TITLE")
|
"SPOTIPY_REDIRECT_URI": os.getenv("SPOTIPY_REDIRECT_URI"),
|
||||||
WIKI_USERNAME = os.getenv("WIKI_USERNAME")
|
"PLAYLIST_ID": os.getenv("PLAYLIST_ID"),
|
||||||
WIKI_PASSWORD = os.getenv("WIKI_PASSWORD")
|
"WIKI_API_URL": os.getenv("WIKI_API_URL"),
|
||||||
|
"WIKI_PAGE_TITLE": os.getenv("WIKI_PAGE_TITLE"),
|
||||||
def hae_wiki_sisalto():
|
"WIKI_USERNAME": os.getenv("WIKI_USERNAME"),
|
||||||
"""Hakee MediaWiki-sivun raakatekstin APIn kautta."""
|
"WIKI_PASSWORD": os.getenv("WIKI_PASSWORD"),
|
||||||
|
|
||||||
# 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:
|
# --- WIKI-YHTEYS ---
|
||||||
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ö)
|
class WikiClient:
|
||||||
login_params = {
|
"""Luokka MediaWiki-rajapinnan kanssa toimimiseen."""
|
||||||
"action": "login",
|
|
||||||
"lgname": WIKI_USERNAME,
|
def __init__(self, api_url, username, password):
|
||||||
"lgpassword": WIKI_PASSWORD,
|
self.api_url = api_url
|
||||||
"lgtoken": login_token,
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
self.session = requests.Session()
|
||||||
|
|
||||||
|
def kirjaudu(self):
|
||||||
|
"""Kirjautuu Wikiin ja palauttaa True jos onnistuu."""
|
||||||
|
token_params = {
|
||||||
|
"action": "query",
|
||||||
|
"meta": "tokens",
|
||||||
|
"type": "login",
|
||||||
"format": "json"
|
"format": "json"
|
||||||
}
|
}
|
||||||
|
|
||||||
login_response = session.post(url=WIKI_API_URL, data=login_params)
|
try:
|
||||||
login_data = login_response.json()
|
# Vaihe 1: Haetaan kirjautumistoken
|
||||||
|
response = self.session.get(url=self.api_url, params=token_params)
|
||||||
|
response.raise_for_status()
|
||||||
|
login_token = response.json()['query']['tokens']['logintoken']
|
||||||
|
|
||||||
if login_data.get("login", {}).get("result") != "Success":
|
# Vaihe 2: Kirjaudutaan sisään
|
||||||
print(f"Wikin kirjautuminen epäonnistui: {login_data}")
|
login_params = {
|
||||||
return ""
|
"action": "login",
|
||||||
|
"lgname": self.username,
|
||||||
|
"lgpassword": self.password,
|
||||||
|
"lgtoken": login_token,
|
||||||
|
"format": "json"
|
||||||
|
}
|
||||||
|
|
||||||
print("Kirjauduttu Wikiin onnistuneesti!")
|
login_response = self.session.post(url=self.api_url, data=login_params)
|
||||||
|
login_response.raise_for_status()
|
||||||
|
|
||||||
# Vaihe 3: Haetaan vihdoin itse sivun sisältö
|
if login_response.json().get("login", {}).get("result") == "Success":
|
||||||
page_params = {
|
print("Kirjauduttu Wikiin onnistuneesti!")
|
||||||
|
return True
|
||||||
|
|
||||||
|
print(f"Wikin kirjautuminen epäonnistui: {login_response.json()}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Virhe Wiki-kirjautumisessa: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def hae_sivun_sisalto(self, otsikko):
|
||||||
|
"""Hakee annetun sivun raakatekstin."""
|
||||||
|
params = {
|
||||||
"action": "query",
|
"action": "query",
|
||||||
"prop": "revisions",
|
"prop": "revisions",
|
||||||
"rvprop": "content",
|
"rvprop": "content",
|
||||||
"rvslots": "main",
|
"rvslots": "main",
|
||||||
"titles": WIKI_PAGE_TITLE,
|
"titles": otsikko,
|
||||||
"format": "json"
|
"format": "json"
|
||||||
}
|
}
|
||||||
|
|
||||||
page_response = session.get(url=WIKI_API_URL, params=page_params)
|
try:
|
||||||
page_data = page_response.json()
|
response = self.session.get(url=self.api_url, params=params)
|
||||||
|
response.raise_for_status()
|
||||||
|
pages = response.json()["query"]["pages"]
|
||||||
|
page_id = list(pages.keys())[0]
|
||||||
|
|
||||||
pages = page_data["query"]["pages"]
|
if page_id == "-1":
|
||||||
page_id = list(pages.keys())[0]
|
print(f"Virhe: Wiki-sivua '{otsikko}' ei löytynyt!")
|
||||||
|
return ""
|
||||||
|
|
||||||
if page_id == "-1":
|
return pages[page_id]["revisions"][0]["slots"]["main"]["*"]
|
||||||
print("Virhe: Wiki-sivua ei löytynyt!")
|
except Exception as e:
|
||||||
|
print(f"Virhe sivun noudossa: {e}")
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
return pages[page_id]["revisions"][0]["slots"]["main"]["*"]
|
# --- TEKSTINKÄSITTELY ---
|
||||||
|
|
||||||
|
def erista_viikon_osio(teksti, viikko_numero):
|
||||||
|
"""Eristää tietyn viikon osion koko sivun tekstistä (== Viikko X ==)."""
|
||||||
|
viikko_str = f"{viikko_numero:02d}"
|
||||||
|
pattern = rf"==\s*Viikko {viikko_str}\s*==(.*?(?===|\Z))"
|
||||||
|
match = re.search(pattern, teksti, re.IGNORECASE | re.DOTALL)
|
||||||
|
|
||||||
|
if match:
|
||||||
|
return match.group(1).strip()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def poimi_spotify_linkit(teksti):
|
||||||
|
"""Etsii tekstistä Spotify-kappaleiden linkit hakasulkeiden sisältä."""
|
||||||
|
linkit = []
|
||||||
|
for rivi in teksti.split('\n'):
|
||||||
|
# Etsitään [http...] muotoisia linkkejä
|
||||||
|
match = re.search(r'\[(https?://[^\s\]]+)', rivi)
|
||||||
|
if match:
|
||||||
|
url = match.group(1)
|
||||||
|
if "spotify.com" in url.lower():
|
||||||
|
linkit.append(url)
|
||||||
|
print(f"Löydetty Spotify-linkki: {url}")
|
||||||
|
else:
|
||||||
|
print(f"Ohitettu muu linkki: {url}")
|
||||||
|
return linkit
|
||||||
|
|
||||||
|
# --- SPOTIFY-PÄIVITYS ---
|
||||||
|
|
||||||
|
def paivita_spotify_soittolista(linkit, asetukset):
|
||||||
|
"""Päivittää Spotify-soittolistan annetuilla linkeillä."""
|
||||||
|
if not linkit:
|
||||||
|
print("\nEi päivitettäviä linkkejä. Soittolistaa ei muutettu.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
scope = "playlist-modify-private playlist-modify-public"
|
||||||
|
try:
|
||||||
|
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(
|
||||||
|
client_id=asetukset["SPOTIPY_CLIENT_ID"],
|
||||||
|
client_secret=asetukset["SPOTIPY_CLIENT_SECRET"],
|
||||||
|
redirect_uri=asetukset["SPOTIPY_REDIRECT_URI"],
|
||||||
|
scope=scope,
|
||||||
|
open_browser=False
|
||||||
|
))
|
||||||
|
|
||||||
|
# Spotify sallii enintään 100 kappaletta per kutsu
|
||||||
|
sp.playlist_replace_items(asetukset["PLAYLIST_ID"], linkit[:100])
|
||||||
|
print(f"Soittolista päivitetty onnistuneesti ({len(linkit[:100])} kappaletta).")
|
||||||
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Virhe Wiki-yhteydessä: {e}")
|
print(f"Virhe Spotifyn päivityksessä: {e}")
|
||||||
return ""
|
return False
|
||||||
|
|
||||||
def paivita_soittolista():
|
# --- PÄÄOHJELMA ---
|
||||||
# 1. Haetaan teksti Wikistä
|
|
||||||
nykyinen_viikko_int = datetime.date.today().isocalendar()[1]
|
def aja_paivitys():
|
||||||
nykyinen_viikko = f"{nykyinen_viikko_int:02d}"
|
"""Suorittaa koko päivitysprosessin vaihe kerrallaan."""
|
||||||
print(f"Kuluva viikko on {nykyinen_viikko}")
|
asetukset = lataa_asetukset()
|
||||||
wiki_teksti = hae_wiki_sisalto()
|
nykyinen_viikko = datetime.date.today().isocalendar()[1]
|
||||||
|
print(f"--- Aloitetaan päivitys (Viikko {nykyinen_viikko:02d}) ---")
|
||||||
|
|
||||||
|
# 1. Wiki-yhteys ja sisällön haku
|
||||||
|
wiki = WikiClient(
|
||||||
|
asetukset["WIKI_API_URL"],
|
||||||
|
asetukset["WIKI_USERNAME"],
|
||||||
|
asetukset["WIKI_PASSWORD"]
|
||||||
|
)
|
||||||
|
|
||||||
|
if not wiki.kirjaudu():
|
||||||
|
return
|
||||||
|
|
||||||
|
wiki_teksti = wiki.hae_sivun_sisalto(asetukset["WIKI_PAGE_TITLE"])
|
||||||
if not wiki_teksti:
|
if not wiki_teksti:
|
||||||
return
|
return
|
||||||
|
|
||||||
# 3. Eristetään kuluvan viikon osio tekstistä säännöllisellä lausekkeella (regex)
|
# 2. Oikean viikon osion eristäminen
|
||||||
# Etsii esim. "== Viikko 10 ==" ja nappaa kaiken tekstin sen jälkeen
|
viikko_teksti = erista_viikon_osio(wiki_teksti, nykyinen_viikko)
|
||||||
# aina seuraavaan "==" merkkiin asti tai sivun loppuun.
|
if not viikko_teksti:
|
||||||
viikko_pattern = rf"==\s*Viikko {nykyinen_viikko}\s*==(.*?(?===|\Z))"
|
print(f"Huom: Viikon {nykyinen_viikko:02d} osiota ei löytynyt sivulta.")
|
||||||
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
|
return
|
||||||
|
|
||||||
kuluvan_viikon_teksti = match.group(1)
|
# 3. Linkkien kerääminen ja Spotifyn päivittäminen
|
||||||
|
spotify_linkit = poimi_spotify_linkit(viikko_teksti)
|
||||||
# 4. Poimitaan suorat Spotify-linkit koodista
|
paivita_spotify_soittolista(spotify_linkit, asetukset)
|
||||||
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__':
|
if __name__ == '__main__':
|
||||||
paivita_soittolista()
|
aja_paivitys()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue