Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sqlite3.OperationalError: row value misused #17

Open
Flavien06 opened this issue Dec 8, 2024 · 0 comments
Open

sqlite3.OperationalError: row value misused #17

Flavien06 opened this issue Dec 8, 2024 · 0 comments

Comments

@Flavien06
Copy link

Flavien06 commented Dec 8, 2024

Hello,
I have this error:

Getting history...
Traceback (most recent call last):
File "/home/pi/git/youtube-music-scrobbler/start.py", line 204, in
Process().execute()
File "/home/pi/git/youtube-music-scrobbler/start.py", line 123, in execute
cursor.execute(f'''
sqlite3.OperationalError: row value misused

I use venv

pip install -r requirements.txt
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Requirement already satisfied: certifi==2024.7.4 in /home/pi/python_env/pylast/lib/python3.9/site-packages (from -r requirements.txt (line 1)) (2024.7.4)
Requirement already satisfied: charset-normalizer==3.2.0 in /home/pi/python_env/pylast/lib/python3.9/site-packages (from -r requirements.txt (line 2)) (3.2.0)
Requirement already satisfied: idna==3.7 in /home/pi/python_env/pylast/lib/python3.9/site-packages (from -r requirements.txt (line 3)) (3.7)
Requirement already satisfied: pysqlite3==0.5.1 in /home/pi/python_env/pylast/lib/python3.9/site-packages (from -r requirements.txt (line 4)) (0.5.1)
Requirement already satisfied: python-dotenv==1.0.0 in /home/pi/python_env/pylast/lib/python3.9/site-packages (from -r requirements.txt (line 5)) (1.0.0)
Requirement already satisfied: requests==2.32.0 in /home/pi/python_env/pylast/lib/python3.9/site-packages (from -r requirements.txt (line 6)) (2.32.0)
Requirement already satisfied: urllib3==2.2.2 in /home/pi/python_env/pylast/lib/python3.9/site-packages (from -r requirements.txt (line 7)) (2.2.2)
Requirement already satisfied: ytmusicapi==1.2.1 in /home/pi/python_env/pylast/lib/python3.9/site-packages (from -r requirements.txt (line 8)) (1.2.1)


edit:
So far I've modified the old version without sql using the new login method, and it works.

#!/usr/bin/env python3
import os
import time
import lastpy
import sqlite3
import webbrowser
import threading
import http.server
import socketserver
from ytmusicapi import YTMusic
import xml.etree.ElementTree as ET
from dotenv import load_dotenv, set_key
from datetime import datetime, timedelta

load_dotenv()

# Changer de répertoire au répertoire contenant le script
script_dir = os.path.dirname(os.path.realpath(__file__))
os.chdir(script_dir)

class TokenHandler(http.server.SimpleHTTPRequestHandler):
    def do_get_token(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b'<html><head><title>Token Received</title></head>')
        self.wfile.write(
            b'<body><p>Authentication successful! You can now close this window.</p></body></html>')
        self.server.token = self.path.split('?token=')[1]

    def do_GET(self):
        if self.path.startswith('/?token='):
            self.do_get_token()
        else:
            http.server.SimpleHTTPRequestHandler.do_GET(self)

class TokenServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    token = None

class Process:
    def __init__(self):
        self.api_key = os.environ['LAST_FM_API']
        try:
            self.session = os.environ['LASTFM_SESSION']
        except:
            self.session = None

        self.formatted_date = datetime.now().strftime(
            "%Y-%m-%dT%H:%M:%S.%fZ")
        self.conn = sqlite3.connect('./data.db')
        cursor = self.conn.cursor()
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS scrobbles (
                id INTEGER PRIMARY KEY,
                track_name TEXT,
                artist_name TEXT,
                album_name TEXT,
                scrobbled_at TEXT DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        self.conn.commit()
        yesterday = (datetime.now() - timedelta(days=1)
                     ).strftime('%Y-%m-%d %H:%M:%S')
        cursor.execute('''
            DELETE FROM scrobbles WHERE scrobbled_at < :yesterday
        ''', {"yesterday": yesterday})
        self.conn.commit()
        cursor.close()

    def get_token(self):
        print("Waiting for authentication...")
        auth_url = "https://www.last.fm/api/auth/?api_key=" + \
            self.api_key + "&cb=http://localhost:5588"
        with TokenServer(('localhost', 5588), TokenHandler) as httpd:
            webbrowser.open(auth_url)
            thread = threading.Thread(target=httpd.serve_forever)
            thread.start()
            while True:
                if httpd.token:
                    token = httpd.token
                    httpd.shutdown()
                    break
                time.sleep(0.1)
        return token

    def get_session(self, token):
        print("Getting session...")
        xml_response = lastpy.authorize(token)
        try:
            root = ET.fromstring(xml_response)
            token = root.find('session/key').text
            set_key('.env', 'LASTFM_SESSION', token)
            return token
        except Exception as e:
            print(xml_response)
            raise Exception(e)

    def execute(self):
        # Utiliser le nouveau fichier d'authentification "browser.json"
        ytmusic = YTMusic("browser.json")

        if not self.session:
            token = self.get_token()
            self.session = self.get_session(token)
        print("Getting history...")
        history = ytmusic.get_history()
        i = 0
        cursor = self.conn.cursor()
        for item in history:
            if item["played"] == "Today":
                record = {
                    "artistName": item["artists"][0]["name"],
                    "trackName": item["title"],
                    "ts": self.formatted_date,
                    "albumName": item["album"]["name"] if "album" in item and item["album"] is not None else None,
                }
                if record["artistName"].endswith(" - Topic"):
                    continue
                if record["albumName"] is None:
                    record["albumName"] = record["trackName"]
                scroble = cursor.execute(
                    'SELECT * FROM scrobbles WHERE track_name = :trackName AND artist_name = :artistName AND album_name = :albumName', {
                        "trackName": record["trackName"],
                        "artistName": record["artistName"],
                        "albumName": record["albumName"]
                    }).fetchone()
                if scroble:
                    continue
                xml_response = lastpy.scrobble(
                    record["trackName"],
                    record["artistName"],
                    record["albumName"],
                    self.session,
                    str(int(time.time() - 30 - (i * 90)))
                )
                root = ET.fromstring(xml_response)
                scrobbles = root.find('scrobbles')
                accepted = scrobbles.get('accepted')
                ignored = scrobbles.get('ignored')
                if accepted == '0' and ignored == '1':
                    print("Error scrobbling " + record["trackName"] +
                          " by " + record["artistName"] + ".")
                    print(xml_response)
                else:
                    cursor.execute('''
                        INSERT INTO scrobbles (track_name, artist_name, album_name, scrobbled_at)
                        VALUES (:trackName, :artistName, :albumName, :ts)
                    ''', record)
                    self.conn.commit()
                    i += 1
        print("Scrobbled " + str(i) + " songs")

        cursor.close()
        self.conn.close()

if __name__ == '__main__':
    Process().execute()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant