luisignaciocc / youtube-music-scrobbler

a python script to scrobble your YouTube Music history to Last.fm
MIT License
29 stars 5 forks source link

Skipping songs if scrobbling multiple times per day #9

Closed roos-robert closed 2 months ago

roos-robert commented 2 months ago

Hi and thank you for this great scrobbler!

It's almost working perfectly, got it all set up to run a few times a day (to get streamed-times kind of correct), but just noticed that the way the code is set up right now (I think at least this is the issue) songs I listen to several times in one day are skipped (not scrobbled to Last.FM).

To reproduce issue

  1. Listen to a couple of songs
  2. Run the scrobbler to send it to Last.fm
  3. Listen to the same songs again
  4. Run the scrobbler and the songs are not sent to Last.fm

I suspect this is the bit of code causing the issue: 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

Since the way the code works is to empty the DB on a daily basis, if a song is not here it has not been scrobbled. But a song will exist in the database if you have already run the scrobbler a few times that day.

So bugfix should be to look for the time the song was added to the database and set as scrobbled?

Instead of making a pull request for this I'm asking here to make sure haha, Python is not my main language so not 100% certain I've understood the code fully.

Thanks in advance!

luisignaciocc commented 2 months ago

Hi there! Yes, that's a known issue. The thing is, the response we get from the YouTube API doesn't have a timestamp, so we can't link a play to a specific time.

For example, if you run the script at 2:00 PM, it detects that you listened to a certain song and saves it in the database with a timestamp. If you then run the script at 2:10 PM, since the data from YouTube doesn't have a timestamp, there's no way to know which of the songs from the YouTube API have already been saved. YouTube only tells us if the song was played today or not, hence that limitation.

luisignaciocc commented 2 months ago

Btw I'm working on version 2.0 of this project on this repo

It will be a web app, so you can log in with Google and authorize the Lastfm API, and a worker will be scrobbling the songs in the background. If you're interested, I can let you know when it is ready to accept users

roos-robert commented 2 months ago

Thank you for the quick response and for explaining the issue in detail!

I get the issue now, wow that's a really bad solution on Googles side, just saving a song once to history regardless of if it's played more than once.

I thought of a possible solution though, would've loved to help out with it myself but again- I've never really learned Python. How about when you save the song to the local database you also save the location in the array returned from the API?

As I'm writing this though it hits me that this would also introduce the need to run the scrobbler often, maybe once a minute and it also won't add a song that's on repeat...

Hard nut to crack, can't believe they've implemented their "history" this way.

Yes I would love to try it out once it's available!

luisignaciocc commented 2 months ago

Yes, that could actually work. In my case, I run the script every 5 minutes, so I could test how it goes. I will keep it in mind, I'm not sure if I should implement it in this repo or take advantage of the fact that I'm building version 2 and implement it there.

YouTube doesn't have an API that gives us the history, this is a workaround that simulates navigation in a certain way, hence the limitations. That's why it's hard to come up with a solution that works for 100% of the cases, but with what you suggested, I think we can fix one of the biggest pain point of this script.

I'll let you know when I've made some progress with that.

roos-robert commented 2 months ago

I just made a pull request #10 that enables this kind of functionality, running it right now and everything seems to be working as intended with the two caveats listed before:

And also a huge disclaimer 😁 you better check the Python code haha, it's actually not that different from C# but screaming internally at the lack of { } haha.