Closed pablorusso closed 7 years ago
This is fantastic! I'll give this a try locally and make sure it works in OSX as well.
It works nice. Thank you :)
I'm getting this error on PMS v0.9.12.11 and Ubuntu Server 15.04.
2015-08-31 13:20:33,367 (7f18e622f700) : CRITICAL (core:613) - Exception starting plug-in (most recent call last):
File "bundles-release/Framework.bundle-dist/Contents/Resources/Versions/2/Python/Framework/core.py", line 606, in start
File "bundles-release/Framework.bundle-dist/Contents/Resources/Versions/2/Python/Framework/code/sandbox.py", line 256, in execute
File "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Code/__init__.py", line 4, in <module>
from gmusic import GMusic, CallFailure, API
File "bundles-release/Framework.bundle-dist/Contents/Resources/Versions/2/Python/Framework/code/sandbox.py", line 345, in __import__
ImportError: cannot import name _counter
The fix includes the binaries only for windows.
For all on Linux: You have to download Crypto from https://pypi.python.org/pypi/pycrypto, and then build it: python setup.py build.
Then copy the Crypto from the "build" directory to replace the Crypto directory.
The entire path to the folder you need to copy is 'build/lib.linux-x86_64-2.7/Crypto'. It needs to go into '/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared'.
Make sure you copy the 'Crypto' folder and not just the contents of it. Also make sure plex has proper access to it by doing 'sudo chown -R plex:plex Crypto' (or whatever user runs your Plex server).
Would be nice if someone on linux send a PR with this binaries to help others in linux.
Exact steps on Ubuntu
1) sudo apt-get install gcc python python-dev 2) wget https://pypi.python.org/packages/source/p/pycrypto/pycrypto-2.6.1.tar.gz 3) tar -xf pycrypto-2.6.1.tar.gz 4) cd pycrypto-2.6.1/ 5) python setup.py build 6) sudo cp -R build/lib.linux-x86_64-2.7/Crypto /var/lib/plexmediaserver/Library/Application\ Support/Plex\ Media\ Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/ 7) sudo chown -R plex:plex /var/lib/plexmediaserver/Library/Application\ Support/Plex\ Media\ Server/Plug-ins/
After doing this I can get the plugin to load when I don't have a username/password set. I get into it and I get a refresh Library button. After I set login credentials. (I use an a google App password since I have two-factor authentication enabled.) I get the same "This channel is not responding" error.
Log with no credentials set:
2015-09-16 12:33:10,203 (7fec53bde700) : DEBUG (runtime:717) - Handling request GET /music/googlemusic 2015-09-16 12:33:10,204 (7fec53bde700) : DEBUG (runtime:814) - Found route matching /music/googlemusic 2015-09-16 12:33:10,205 (7fec53bde700) : DEBUG (base:117) - Checking if com.plexapp.plugins.googlemusic is broken 2015-09-16 12:33:10,205 (7fec53bde700) : DEBUG (networking:166) - Requesting 'http://127.0.0.1:32400/:/plugins/com.plexapp.system/messaging/function/X1N0b3JlU2VydmljZTpJc0NoYW5uZWxCcm9rZW4_/Y2VyZWFsMQoxCmxpc3QKMApyMAo_/Y2VyZWFsMQoxCmRpY3QKMQpzMzEKY29tLnBsZXhhcHAucGx1Z2lucy5nb29nbGVtdXNpY3MxMAppZGVudGlmaWVycjAK' 2015-09-16 12:33:10,211 (7fec53bde700) : DEBUG (runtime:106) - Sending packed state data (112 bytes) 2015-09-16 12:33:10,211 (7fec53bde700) : DEBUG (runtime:918) - Response: [200] MediaContainer, 751 bytes
Setting credentials and trying to open plugin
2015-09-16 12:34:31,135 (7fec53bde700) : DEBUG (runtime:717) - Handling request GET /music/googlemusic/:/prefs 2015-09-16 12:34:31,136 (7fec53bde700) : DEBUG (runtime:814) - Found route matching /music/googlemusic/:/prefs 2015-09-16 12:34:31,138 (7fec53bde700) : DEBUG (runtime:106) - Sending packed state data (112 bytes) 2015-09-16 12:34:31,138 (7fec53bde700) : DEBUG (runtime:918) - Response: [200] MediaContainer, 363 bytes 2015-09-16 12:34:44,528 (7fec53bde700) : DEBUG (runtime:717) - Handling request GET /music/googlemusic/:/prefs/set?email=EMAILADDRESS&password=THISSHOULDNTBEPLAINTEXT 2015-09-16 12:34:44,529 (7fec53bde700) : DEBUG (runtime:814) - Found route matching /music/googlemusic/:/prefs/set 2015-09-16 12:34:44,530 (7fec53bde700) : DEBUG (preferences:198) - Saved the user preferences 2015-09-16 12:34:44,530 (7fec53bde700) : DEBUG (runtime:106) - Sending packed state data (112 bytes) 2015-09-16 12:34:44,530 (7fec53bde700) : DEBUG (runtime:918) - Response: [200] bool, 0 bytes 2015-09-16 12:34:48,294 (7fec53bde700) : DEBUG (runtime:717) - Handling request GET /music/googlemusic 2015-09-16 12:34:48,296 (7fec53bde700) : DEBUG (runtime:814) - Found route matching /music/googlemusic 2015-09-16 12:34:48,634 (7fec53bde700) : CRITICAL (runtime:883) - Exception (most recent call last): File "bundles-release/Framework.bundle-dist/Contents/Resources/Versions/2/Python/Framework/components/runtime.py", line 843, in handle_request File "bundles-release/Framework.bundle-dist/Contents/Resources/Versions/2/Python/Framework/handlers/base.py", line 111, in call File "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Code/init.py", line 47, in MainMenu API.authenticate(Prefs['email'], Prefs['password']) File "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/gmusic.py", line 66, in authenticate self._set_all_access() File "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/gmusic.py", line 38, in _set_all_access settings = self._webclient._make_call(webclient.GetSettings, '') File "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/gmusicapi/clients/shared.py", line 80, in _make_call return protocol.perform(self.session, self.validate, _args, *_kwargs) File "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/gmusicapi/protocol/shared.py", line 208, in perform response = session.send(req_kwargs, cls.required_auth) File "/var/lib/plexmediaserver/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/gmusicapi/session.py", line 81, in send raise NotLoggedIn NotLoggedIn
2015-09-16 12:34:48,636 (7fec53bde700) : DEBUG (runtime:106) - Sending packed state data (112 bytes) 2015-09-16 12:34:48,636 (7fec53bde700) : DEBUG (runtime:918) - Response: [500] 1795 bytes
@r0n0c Were you able to get it to work with those steps?
@imthenachoman nope. Kept getting errors.
Then I realized everything I play plex on is either a nexus player or chromecast enabled so I don't need it. And once All Access Family plan is up and running girlfriend won't need it either.
@r0n0c Oh. Thanks!
This fix works nicely! Now I'm just having an issue on my Roku 3. Any chance we could get this fix merged into master?
Hi all! Thanks Pablo for your efforts! I really appreciate it! Anyway, I had this plugin up and running till past week. I decided to enable 2way authentication with Google and In spite of generating and using app password the plugin stopped working and I got "Channel not responding" error. I disabled 2way authentication, but it didn't help. Plugin log is here http://pastebin.com/nk2qWyRk Running it on Win 10 //========================= UPD: Sorry, guys. My bad! It appeared to be a local problem. Works fine with fresh windows install - had to test it on VM.
I can confirm, it does not work on OSX with Crypto installed:
2016-01-18 10:54:59,967 (7000024af000) : DEBUG (runtime:717) - Handling request GET /music/googlemusic
2016-01-18 10:54:59,968 (7000024af000) : DEBUG (runtime:814) - Found route matching /music/googlemusic
2016-01-18 10:54:59,971 (7000024af000) : CRITICAL (runtime:889) - Exception (most recent call last):
File "bundles-release/Framework.bundle-dist-ninja/Contents/Resources/Versions/2/Python/Framework/components/runtime.py", line 843, in handle_request
File "bundles-release/Framework.bundle-dist-ninja/Contents/Resources/Versions/2/Python/Framework/handlers/base.py", line 111, in call
File "/Users/asamorukov/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Code/__init__.py", line 47, in MainMenu
API.authenticate(Prefs['email'], Prefs['password'])
File "/Users/asamorukov/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/gmusic.py", line 56, in authenticate
mcauthenticated = self._mobileclient.login(email, password, Mobileclient.FROM_MAC_ADDRESS)
File "/Users/asamorukov/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/gmusicapi/clients/mobileclient.py", line 63, in login
if not self.session.login(email, password, android_id):
File "/Users/asamorukov/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/gmusicapi/session.py", line 163, in login
res = gpsoauth.perform_master_login(email, password, android_id)
File "/Users/asamorukov/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/gpsoauth/__init__.py", line 56, in perform_master_login
'EncryptedPasswd': google.signature(email, password, android_key_7_3_29),
File "/Users/asamorukov/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/gpsoauth/google.py", line 51, in signature
encrypted_login = cipher.encrypt((email + u'\x00' + password).encode('utf-8'))
File "/Users/asamorukov/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/Crypto/Cipher/PKCS1_OAEP.py", line 164, in encrypt
m = self._key.encrypt(em, 0)[0]
File "/Users/asamorukov/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/Crypto/PublicKey/RSA.py", line 150, in encrypt
return pubkey.pubkey.encrypt(self, plaintext, K)
File "/Users/asamorukov/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/Crypto/PublicKey/pubkey.py", line 75, in encrypt
ciphertext=self._encrypt(plaintext, K)
File "/Users/asamorukov/Library/Application Support/Plex Media Server/Plug-ins/GoogleMusic.bundle/Contents/Libraries/Shared/Crypto/PublicKey/RSA.py", line 224, in _encrypt
return (self.key._encrypt(c),)
ValueError: Plaintext too large
Update: it works when pycrypto compiled for the py-27
For some reasons I started getting the error I mentioned above - https://github.com/jwdempsey/GoogleMusic.bundle/pull/13#issuecomment-169540547 Only fix I could find is using my actual device Android ID in gmusic.py file. So, changing the line _mcauthenticated = self._mobileclient.login(email, password, Mobileclient.FROM_MACADDRESS) to _mcauthenticated = self._mobileclient.login(email, password, "myadroiddeviceid")_ did the trick. Could anyone please look into it?
I finally been able to get it running, thank you! When testing i found one very easy to fix error - for the artists in non-ASCII it wont work correctly. I patches this issue and now it works fine. Patch provided below:
diff --git a/Contents/Libraries/Shared/gmusic.py b/Contents/Libraries/Shared/gmusic.py
index 94417ad..7aa3b5a 100644
--- a/Contents/Libraries/Shared/gmusic.py
+++ b/Contents/Libraries/Shared/gmusic.py
@@ -133,13 +133,13 @@ class GMusic(object):
def get_tracks_for_type(self, type, name):
type = type.lower()
if type == 'artists':
- return self.tracks_by_artist[name]
+ return self.tracks_by_artist[name.decode('utf_8')]
elif type == 'albums':
- return self.tracks_by_album[name]
+ return self.tracks_by_album[name.decode('utf_8')]
elif type == 'genres':
- return self.tracks_by_genre[name]
+ return self.tracks_by_genre[name.decode('utf_8')]
elif type == 'songs by letter':
- return self.tracks_by_letter[name]
+ return self.tracks_by_letter[name.decode('utf_8')]
else:
return {}
And one more unicode related fix: display title2 for non-ASCII songs/artists:
diff --git a/Contents/Code/__init__.py b/Contents/Code/__init__.py
index 1a9b51b..a4f2998 100644
--- a/Contents/Code/__init__.py
+++ b/Contents/Code/__init__.py
@@ -288,7 +288,7 @@ def ShowSongs(title, shuffle=False, page=1):
################################################################################
@route(PREFIX + '/getalbumsinlibrary')
def GetAlbumsInLibrary(name):
- oc = ObjectContainer(title2=name)
+ oc = ObjectContainer(title2=unicode(name))
albums = API.get_albums_in_library(name)
for album in sorted(albums['albums'], key = lambda x: x.get('year')):
@@ -307,7 +307,7 @@ def GetAlbumsInLibrary(name):
################################################################################
@route(PREFIX + '/gettracklist')
def GetTrackList(name, type):
- oc = ObjectContainer(title2=name)
+ oc = ObjectContainer(title2=unicode(name))
tracks = API.get_tracks_for_type(type, name)
sort = 'title' if type == 'Songs By Letter' else 'trackType'
for track in sorted(tracks, key = lambda x: x['track'].get(sort)):
@@ -318,7 +318,7 @@ def GetTrackList(name, type):
################################################################################
@route(PREFIX + '/getplaylistcontents')
def GetPlaylistContents(name, id):
- oc = ObjectContainer(title2=name)
+ oc = ObjectContainer(title2=unicode(name))
tracks = API.get_all_user_playlist_contents(id)
for track in tracks:
@@ -334,7 +334,7 @@ def GetPlaylistContents(name, id):
################################################################################
@route(PREFIX + '/getsharedplaylist')
def GetSharedPlaylist(name, token):
- oc = ObjectContainer(title2=name)
+ oc = ObjectContainer(title2=unicode(name))
tracks = API.get_shared_playlist_contents(token)
for track in tracks:
@@ -345,7 +345,7 @@ def GetSharedPlaylist(name, token):
################################################################################
@route(PREFIX + '/getstationtracks')
def GetStationTracks(name, id):
- oc = ObjectContainer(title2=name)
+ oc = ObjectContainer(title2=unicode(name))
tracks = API.get_station_tracks(id)
for track in tracks:
@@ -363,7 +363,7 @@ def GetStationTracks(name, id):
################################################################################
@route(PREFIX + '/genressubmenu', children=list)
def GenresSubMenu(name, id, children=None):
- oc = ObjectContainer(title2=name)
+ oc = ObjectContainer(title2=unicode(name))
oc.add(DirectoryObject(key=Callback(CreateStation, id=id), title='Play ' + name))
if children != None:
@@ -381,7 +381,7 @@ def CreateStation(id):
################################################################################
@route(PREFIX + '/getartistinfo')
def GetArtistInfo(name, id, inLibrary=False):
- oc = ObjectContainer(title2=name)
+ oc = ObjectContainer(title2=unicode(name))
artist = API.get_artist_info(id)
for album in sorted(artist['albums'], key = lambda x: x.get('year')):
@@ -400,7 +400,7 @@ def GetArtistInfo(name, id, inLibrary=False):
################################################################################
@route(PREFIX + '/getalbuminfo')
def GetAlbumInfo(name, id):
- oc = ObjectContainer(title2=name)
+ oc = ObjectContainer(title2=unicode(name))
album = API.get_album_info(id)
for track in album['tracks']:
new version here => https://github.com/jwdempsey/GoogleMusic.bundle/pull/20
Web protocol was deprecated by google, so I have updated the gmusicapi and changes gmusic to use only mobileclient.
The new gmusicapi depends on pycrypto which was a PITA to build and use inside a windows plex, but its is working. I had tested it only in a windows server.
The trick is to compile it with plex python and vs2013 as plex uses a custom python 2.7 build (plexsripthost) that depednds on msvcrt120 instead of msvcrt90 (like regular python 2.7 does)