Get spotify currently playing track - python

EDIT : Let's try to clarify all this.
I'm writing a python script, and I want it to tell me the song that Spotify is currently playing.
I've tried looking for libraries that could help me but didn't find any that are still maintained and working.
I've also looked through Spotify's web API, but it does not provide any way to get that information.
The only potential solution I found would be to grab the title of my Spotify (desktop app) window. But I didn't manage to do that so far.
So basically, what I'm asking is whether anyone knows :
How to apply the method I'm already trying to use (get the window's title from a program), either in pure python or using an intermediary shell script.
OR
Any other way to extract that information from Spotify's desktop app or web client.
Original post :
I'm fiddling with the idea of a python status bar for a linux environment, nothing fancy, just a script tailored to my own usage. What I'm trying to do right now is to display the currently playing track from spotify (namely, the artist and title).
There does not seem to be anything like that in their official web API. I haven't found any third party library that would do that either. Most libraries I found are either deprecated since spotify released their current API, or they are based on said API which does not do what I want.
I've also read a bunch of similar question in here, most of which had no answers, or a deprecated solution.
I thought about grabbing the window title, since it does diplay the information I need. But not only does that seem really convoluted, I also have difficulties making this happen. I was trying to get it by running a combination of the linux commands xdotools and xprop inside my script.
It's worth mentionning that since I'm already using the psutil lib for other informations, I already have access to spotify's PID.
Any idea how I could do that ?
And in case my method was the only one you can think of, any idea how to actually make it work ?
Your help will be appreciated.

The Spotify client on Linux implements a D-Bus interface called MPRIS - Media Player Remote Interfacing Specification.
http://specifications.freedesktop.org/mpris-spec/latest/index.html
You could access the title (and other metadata) from python like this:
import dbus
session_bus = dbus.SessionBus()
spotify_bus = session_bus.get_object("org.mpris.MediaPlayer2.spotify",
"/org/mpris/MediaPlayer2")
spotify_properties = dbus.Interface(spotify_bus,
"org.freedesktop.DBus.Properties")
metadata = spotify_properties.Get("org.mpris.MediaPlayer2.Player", "Metadata")
# The property Metadata behaves like a python dict
for key, value in metadata.items():
print(key, value)
# To just print the title
print(metadata['xesam:title'])

For windows:
The library can be found at github: https://github.com/XanderMJ/spotilib. Keep in mind that this is still work in progress.
Just copy the file and place it in your Python/Lib directory.
import spotilib
spotilib.artist() #returns the artist of the current playing song
spotilib.song() #returns the song title of the current playing song
spotilib.artist() returns only the first artist. I started working on an other library spotimeta.py to solve this issue. However, this is not working at 100% yet.
import spotimeta
spotimeta.artists() #returns a list of all the collaborating artists of the track
If an error occurs, spotimeta.artists() will return only the first artist (found with spotilib.artist())

Related

Web Scraping with an Incrementing ID and Login

I’m trying to create a web scraper in python for a website called Canvas LMS to find a course link. The course link is formatted like this: [schoolname].instructure.com/courses/[id] I need to figure out how to have a bot log in with my api key and check all IDs from 1 to 10,000 for courses that does not contain the phrase “Unauthorized” or “Page Not Found” in the title so I can check them manually. However, I cannot figure out how to do any of this, as there is no guide (to my knowledge) that says how to do any of this. Tips would be appreciated.
I was working with a similar problem a few weeks back and found a solution.
Firstly, there is extensive Canvas LMS documentation available here
Secondly, find the relevant tags which can be identified and then copied to a download set. I forked a repository here and ran as a Docker container on my local machine.
I would also recommend viewing the data in a Jupyter Notebook. As a starter (and I do not advocate nested 'for loops' but you get the idea) try these:
from canvasapi import Canvas
canvas = Canvas("your-course-url", "api-token")
#Get courses and print
courses = canvas.get_courses()
for course in courses:
print(f"{course}")
#Get modules and print
modules = course.get_modules()
for module in modules:
print(f"{module}")
#Get modules items and print
module_items = course.get_module_items()
for item in module_items:
print(f"{item}")
Good luck

Remove Video From Plex's "Recently Added" Section

Is it possible to remove videos from Plex's "Recently Added" section? I'd like to add some old videos to my server for posterity but not have them appears as newly added.
When I initially sought an answer to this question, I looked on support forums, including Plex's own and Reddit. All answers said it was either not possible or suggested editing the metadata_items table of the SQLite database directly (yuck). I have since found a better way to do this, but those support threads are now locked, so I'm unable to share this solution there. Hopefully answering this question here helps others find it.
This actually is possible and quite easy via the REST API. First, pip install plexapi. Then use the following script to update the addedAt field of your video of choice.
import os
import sys
from plexapi.myplex import MyPlexAccount
USERNAME = os.environ.get("PLEX_USERNAME")
PASSWORD = os.environ.get("PLEX_PASSWORD")
account = MyPlexAccount(USERNAME, PASSWORD)
plex = account.resource("<YOUR_PLEX_HOSTNAME>").connect()
library = plex.library.section("<YOUR_PLEX_LIBRARY_NAME>")
video = library.get(title="<YOUR MOVIE TITLE>")
updates = {"addedAt.value": "2018-08-21 11:19:43"}
video.edit(**updates)
That's it! What we're doing here is changing the addedAt value to be something that is older, since "Recently Added" is sorted by this date, so we're moving the video to the back of the line.
alexdlaird suggestion worked very well for me! I had to make one change, and I believe that's because I have 2FA on my Plex account:
import os
import sys
import plexapi
from plexapi.server import PlexServer
baseurl = 'http://plexserver:32400'
token = 'YOUR PLEX TOKEN'
plex = PlexServer(baseurl, token)
library = plex.library.section("Movies")
video = library.get(title="MOVIE NAME")
updates = {"addedAt.value": "2018-08-21 11:19:43"}
video.edit(**updates)
I was faced to this situation and while gathering documentations to modify the SQL db, I thought about another solution and it did the trick for me. As previously said, all support threads regarding this issue are closed elsewhere so I'm posting it here for others to eventually find it :
Stopped Plex Server
Disabled the server (computer) internal clock automatic sync
Set the internal clock manually to a year before
Started Plex Server
Added the movies
Scanned the library
Movie got added to the library without showing into recently added BUT the metadata from moviedb where not able to be loaded (probably caused by the difference in time and date between my server and moviedb server)
Stopped Plex Server
Restored the internal clock automatic sync
Started Plex server
Updated all metadata of the library (actually I did it manually for each as I didn't know if I had some custom metadata somewhere else in the library)
Enjoyed !

Download latest version from Github, unzip to folder and overwrite contents?

I have a Node project that's bundled and added to Github as releases. At the moment, it checks my Github for a new release via the API and lets the user download it. The user must then stop the Node server, unzip the release.zip to the folder and overwrite everything to update the project.
What I'm trying to do is write a Python script that I can execute in Node by spawning a new process. This will then kill the Node server using PM2, and then Python script will then check the Github API, grab the download url, downloads it, unzips the contents to the current folder, deletes the zip and then starts up the Node server again.
What I'm struggling with though is checking the Github API and downloading the latest release file. Can anyone point me in the right direction? I've read that wget shouldn't be used in Python, and instead use urlopen
If you are asking for ways to get data from a web server, the two main libraries are:
Requests
Urllib
Personally, I prefer requests. They both have good documentation.
With requests, getting JSON data is as simple as:
r = requests.get("example.com")
r = r.json()
You can add headers and other information easily, though keep in mind that while it supports HTTP, it doesn't support HTTPS.
You need to map out your workflow and dataflow better. You can do it in words or pictures. If you can express your problem clearly and completely in words step by step in list format in words, then translate it to pseudocode. Python is great because you can go almost immediately from a good written description, to pseudocode, to a working implementation. Then at least you have something that works, and you can optimize performance, simplify functionality or usability from there. This is the process of translating a problem into a solution.
When asking questions on SO, you need to show your current thinking, what you've already tried, preferably with your code that doesn't yet work, or work the way you need it to work. People can vote you down and give you negative reputation points if you ask a question with just a vague description, a question that is an obvious cry for help with homework (yours is not that), or a muse or a vague question with not even an attempt at a solution, because it does not contribute back to the community in any way.
Do you have any code or detailed pseudocode steps for checking the GitHub API and checking for the "latest release" of file(s) you are trying to update?

Create a 'single-serving site' with python

I want to make a Python script available as a service on the net. The script, which is my first 'proper' Python program, takes a txt file as argument and writes an image into the work directory. So:
How difficult is it for somebody who is new to Python and web development?
How much work is it?
Do I need a framework (Django, cherryPy, web2py)?
Are there good tutorials?
How do I avoid the server to be compromised?
What are my next steps?
==> What is the easiest way?
In the end it is enough, if it is a white page, with some text, and a button, which when clicked, opens a file dialog. After the txt is processed, the server should just return the image, which was written on the hard drive. Already I have access to a server which has Ubuntu installed through a friend.
[update]
Thanks for all your answers. After reading them I want to stress again, that I want to have it as minimal as possible. Srikar's suggestion sounds like the easiest one:
Put it in executable directory of your OS (commonly known as CGI
path). Provide a simple HTML form & upon form submission hit this
script which executes & returns back the image you want to display.
Any objections or comments? Do you know any tutorials for that?
[udpate2]
I found this SO answer: File Sharing Site in Python Is this a sensible approach?
It's not too difficult. Actually, it sounds like a good first project.
That too subjective to answer. An hour to days.
No, you don't need one, but I'd use one if I were you. They abstract away some of the stuff you really don't care about, and you'll learn a tool you can use again in the future.
Plenty. If you want a real rundown of how Python works for the web, read the HOWTO from Python.org. If you just want to learn how to do this one project, pick a framework and do their tutorial.
This question is so broad and complex that I'm not going to try to answer it. Search this site, or Google, for questions like that.
Your next step should be to pick a framework; I've used Django successfully. Just download it, follow the installation instructions, and work your way through their tutorial; it should tell you everything you need to know to do what you want. If you still have questions once you've learned how to do the basics, come back and ask again!
Edit: The answer to that other question will certainly work for you. There, they just receive a GET request and respond with data from a Python file. You need to receive a GET request, respond with an HTML page (easy enough), then respond to a POST request that includes an uploaded file (slightly more complicated) and run your python routine on the uploaded file and then respond with the created image (or a link to it).
Take a look at this page which includes a simple Python script to do file uploads. You should easily be able to modify it to do what you want.
How difficult is it for somebody who is new to Python and web development?
Depends on your level of knowledge.
How much work is it?
Depends on which method you choose to solve the problem.
Do I need a framework (Django, cherryPy, web2py)?
Not necessarily - you could get started by using the CGI (http://docs.python.org/library/cgi.html)
Are there good tutorials?
Yes, there are plenty. The Python docs are an excellent place to start.
How do I avoid the server to be compromised?
Again, depends on the method you choose to solve the problem, although there are commonalities.
What are my next steps?
Dare I say it again, choose a method, read the docs, have a play!
If its just as simple as you have described it. Then you might not even need Django. You could simply use CGI scripting. All of these design decisions, depend on whether
You need (or foresee) a SQL storage?
or a Content-Management-System?
Will you need multiple-user support?
Do you need tight security?
Do you need different privileges for different users?
Do you need an Admin to manage your site?
If the answer to above questions is atleast 60% correct, then you might consider Django. otherwise, just write a python script. Put it in executable directory of your OS (commonly known as CGI path). Provide a simple HTML form & upon form submission hit this script which executes & returns back the image you want to display. So, it all depends on the features you need...
In the end, I created what I needed with Flask.
They have a well documented pattern / tutorial on Uploading Files. The tutorial is understandable even for people with little python and web expericence.
To get a first working version it took me 2h and the resulting code was only 50 lines. This includes, starting the webserver, having a html file/form with file upload and serving a file back to the user.

Media Kind in iTunes COM for Windows SDK

I recently found out about the awesomeness of the iTunes COM for Windows SDK. I am using Python with win32com to talk to my iTunes library. Needless to say, my head is in the process of exploding. This API rocks.
I have one issue though, how do I access the Media Kind attribute of the track? I looked through the help file provided in the SDK and saw no sign of it. If you go into iTunes, you can modify the track's media kind. This way if you have an audiobook that is showing up in your music library, you can set the Media Kind to Audiobook and it will appear in the Books section in iTunes. Pretty nifty.
The reason I ask is because I have a whole crap load of audiobooks that are showing up in my LibraryPlaylist.
Here is my code thus far.
import win32com.client
iTunes = win32com.client.gencache.EnsureDispatch('iTunes.Application')
track = win32com.client.CastTo(iTunes.LibraryPlaylist.Tracks.Item(1), 'IITFileOrCDTrack')
print track.Artist, '-', track.Name
print
print 'Is this track an audiobook?'
print 'How the hell should I know?'
Thanks in advance.
One reason why you may not be able to find it is that the atom structure the com object references may be out of date. The most popular list of atoms from the MP4 structure is here: http://atomicparsley.sourceforge.net/mpeg-4files.html I don't see a media kind atom. I suppose you could try to parse the structure through atomicparsley but to my knowledge it only finds atoms that it knows about.
Short Answer: The COM object may not know about the MediaKind Attribute.
The only reference I can find to that "Media Kind" attribute is the ITUserPlaylistSpecialKind enum. The only place that is used is a getter method IITUserPlaylist::SpecialKind. So it seems that is a read-only playlist-level attribute. I would guess that in order to read it you need to get the playlist of the track and then get the playlists's SpecialKind attribute. In order to write it, you probably have to move the track to the appropriate playlist.
Well, the Media Kind is in interface IITTrack.Kind, but that probably isn't what you want - the answer will be one of:
public enum ITTrackKind
{
ITTrackKindUnknown = 0,
ITTrackKindFile = 1,
ITTrackKindCD = 2,
ITTrackKindURL = 3,
ITTrackKindDevice = 4,
ITTrackKindSharedLibrary = 5,
}
Probably you need to look at IITTrack.Genre, which gives the string form of the ID3 tag
Genre, so you can find "Audiobook" or Apple's "Books & Spoken". (Some genres are treated specially by iTunes/iPods).
Tip: the compiled help file in the ITunes SDK I downloaded seemed to be broken - I had to convert it back to HTML files and use Firefox/grep to find the information I needed.
It is actually quite easy, use the IITFileOrCDTrack.Podcast :
yourTrack.Podcast
If it is a podcast, it will return True, otherwise it will return False.
You can of course set it through
yourTrack.Podcast(bool)
Glad I could help.

Categories

Resources