Skip to content

Instantly share code, notes, and snippets.

@romuald
Created October 1, 2019 12:26
Show Gist options
  • Save romuald/ab96abecaa9891970f80e1b08ba6e8d0 to your computer and use it in GitHub Desktop.
Save romuald/ab96abecaa9891970f80e1b08ba6e8d0 to your computer and use it in GitHub Desktop.
Pilot a Chrome tab with deezer, need to have remote debugging enabled
#!/usr/bin/env python
from __future__ import print_function
import sys
import socket
import json
import optparse
import requests
import websocket # websocket-client
try:
from urlparse import urlparse
except ImportError:
from urllib.parse import urlparse
from pprint import pprint
class JavascriptError(Exception):
pass
class DeezerRemote(object):
def __init__(self, target):
url = 'http://%s:%d/json/list' % target
self._rfile = None
self.socket = None
self.connect(url)
self._id = 0
@property
def id(self):
self._id += 1
return self._id
def connect(self, url):
tabs = requests.get(url).json()
for tab in tabs:
host = urlparse(tab['url']).netloc
if ('.%s' % host).endswith('.deezer.com'):
break
else:
raise RuntimeError('Deezer tab not found')
self.socket = websocket.WebSocket()
self.socket.connect(tab['webSocketDebuggerUrl'])
@property
def rfile(self):
if self._rfile:
return self._rfile
self._rfile = self.socket.makefile()
return self._rfile
def do(self, command):
"""Execute a javascript statement"""
# (may actually
jcommand = {'id': self.id,
'method': 'Runtime.evaluate',
'params': {'expression': command}}
self.socket.send(json.dumps(jcommand))
result = json.loads(self.socket.recv())
print(result)
return
if 'result' in result:
return result['result']
if 'error' in result:
raise JavascriptError(result['error'])
def dof(self, function):
"""Same as do, wrapped in a javascript function"""
command = '(function() {%s})()' % function
return self.do(command)
def pause(self):
self.do('dzPlayer.control.pause()')
def playpause(self):
func = """
var playing = dzPlayer.playing;
dzPlayer.control[playing ? "pause" : "play"]();
return !playing;
"""
return self.dof(func)
def nextsong(self):
self.do('dzPlayer.control.nextSong()')
def info(self):
func = """
return {
artist: dzPlayer.getArtistName(),
title: dzPlayer.getSongTitle(),
album: dzPlayer.getAlbumTitle()
}
"""
return self.dof(func)
def main(args=sys.argv):
parser = optparse.OptionParser()
parser.add_option('-H', '--host', dest='host', default=':9222',
help='connect to specific'
' [host]:port (default: "%default")')
options, args = parser.parse_args()
# try to parse host
host = options.host
if ':' not in host:
raise ValueError('Invalid host definition')
host, port = host.rsplit(':', 1)
if not port.isdigit():
raise ValueError('Invalid host definition')
port = int(port)
if not host:
host = 'localhost'
if not args:
args = ('info', )
command = args.pop(0)
if command.startswith('_'):
raise ValueError('Invalid comamnd: %r' % command)
remote = DeezerRemote((host, port))
method = getattr(remote, command, None)
if method is None or not callable(method):
raise ValueError('Unknown comamnd: %r' % command)
ret = method(*args)
if ret is not None:
print(json.dumps(ret))
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment