Created
August 20, 2018 12:08
-
-
Save secondwtq/d614012c8f31c03c8382665bdb15738c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# START_FILE ./.gitignore #-} | |
.DS_Store | |
.idea | |
*.log | |
tmp/ | |
*.py[cod] | |
*.egg | |
build | |
htmlcov | |
{-# START_FILE ./hsca.hs #-} | |
import Hscaffold(hscaffoldFromDirectoryWith, toHsfiles) | |
import Control.Monad.Writer(writer) | |
import Data.Text(unpack) | |
doFilter :: [FilePath] -> [FilePath] | |
doFilter paths = | |
filter f paths | |
where | |
f a = | |
case a of | |
"." -> False | |
".." -> False | |
".DS_Store" -> False | |
_ -> True | |
main :: IO () | |
main = do | |
scaffold <- hscaffoldFromDirectoryWith doFilter "." | |
let hsfiles = toHsfiles $ writer ((), scaffold) | |
putStrLn $ unpack hsfiles | |
{-# START_FILE ./hsct.hs #-} | |
import Hscaffold(runHscaffold, fromHsfiles) | |
import Control.Monad.Writer(writer) | |
import Data.Text(unpack) | |
main :: IO () | |
main = do | |
hsfiles <- readFile "a.txt" | |
let scaffold = fromHsfiles hsfiles | |
runHscaffold "." (writer ((), scaffold)) | |
{-# START_FILE ./MANIFEST.in #-} | |
include MANIFEST.in | |
include mopidy_qobuz/ext.conf | |
{-# START_FILE ./mopidy_qobuz/__init__.py #-} | |
from __future__ import unicode_literals | |
from mopidy import config, ext | |
from os import path | |
__version__ = "0.0.1" | |
class Extension(ext.Extension): | |
dist_name = "Mopidy-Qobuz" | |
ext_name = "qobuz" | |
version = __version__ | |
def get_default_config(self): | |
return config.read(path.join(path.dirname(__file__), "ext.conf")) | |
def get_config_schema(self): | |
schema = super(Extension, self).get_config_schema() | |
schema["username"] = config.String() | |
schema["password"] = config.Secret() | |
schema["client_id"] = config.String() | |
schema["client_secret"] = config.Secret() | |
return schema | |
def validate_config(self, config): | |
if not config.getboolean("qobuz", "enabled"): | |
return | |
def setup(self, registry): | |
from mopidy_qobuz.backend import QobuzBackend | |
registry.add("backend", QobuzBackend) | |
{-# START_FILE ./mopidy_qobuz/backend.py #-} | |
from __future__ import unicode_literals | |
import logging | |
import os | |
from mopidy import backend, httpclient | |
import client | |
import pykka | |
class QobuzBackend(pykka.ThreadingActor, backend.Backend): | |
def __init__(self, config, audio): | |
super(QobuzBackend, self).__init__() | |
self._config = config | |
self._audio = audio | |
self.library = client.QobuzLibraryProvider(backend=self) | |
self.uri_schemes = ["qobuz"] | |
self.session = None | |
def on_start(self): | |
self.session = client.get_requests_session(self._config["qobuz"]) | |
{-# START_FILE ./mopidy_qobuz/client.py #-} | |
from __future__ import absolute_import, unicode_literals | |
import requests | |
import urlparse | |
import logging | |
import hashlib | |
from mopidy import backend, models | |
import types | |
import time | |
import re | |
# URI: | |
# qobuz:track:$id | |
API_PREFIX = "http://www.qobuz.com/api.json/0.2/" | |
REGEX_URL = "http://www\.qobuz\.com/api\.json/0\.2/(.*)" | |
USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" | |
URI_ROOT = "qobuz:directory" | |
URI_ALBUMS = "qobuz:album" | |
logger = logging.getLogger(__name__) | |
def api(p): | |
return urlparse.urljoin(API_PREFIX, p) | |
def to_album_ref(album): | |
return models.Ref.album(uri="%s:%s" % (URI_ALBUMS, album["id"]), | |
name=album["title"]) | |
class QobuzRequestsSession(requests.Session): | |
def __init__(self, app_id, app_secret, user_auth_token): | |
super(QobuzRequestsSession, self).__init__() | |
self._app_id = app_id | |
self._app_secret = app_secret | |
self._user_auth_token = user_auth_token | |
self.headers.update({ | |
"User-Agent": USER_AGENT, | |
"X-App-Id": app_id, | |
"X-User-Auth-Token": user_auth_token, | |
}) | |
def prepare_request(self, request): | |
if request.method == "GET": | |
path = re.search(REGEX_URL, request.url).groups()[0].replace('/','') | |
params = "".join([(k + v) for k, v in request.params.items()]) | |
ts = long(time.time()) | |
sigstr = "{path}{params}{ts}{secret}".format( | |
path=path, params=params, ts=ts, secret=self._app_secret) | |
sigdigest = hashlib.md5(sigstr).hexdigest() | |
logger.debug("Signing request %s %s", sigstr, sigdigest) | |
request.params["request_ts"] = ts | |
request.params["request_sig"] = sigdigest | |
p = requests.Session.prepare_request(self, request) | |
return p | |
def get_requests_session(config): | |
# TODO: proxy | |
login = requests.get(api("user/login"), params={ | |
"app_id": config["client_id"], | |
"email": config["username"], | |
"password": hashlib.md5(config["password"]).hexdigest(), | |
}, headers={ "user-agent": USER_AGENT }) | |
if login.status_code != requests.codes.ok: | |
pass | |
# TODO: add log | |
login_data = login.json() | |
logger.debug("Successful logged in %s %s", | |
login_data["user"]["credential"]["description"], | |
login_data["user"]["email"]) | |
session = QobuzRequestsSession(config["client_id"], | |
config["client_secret"], login_data["user_auth_token"]) | |
return session | |
class QobuzPlaybackProvider(backend.PlaybackProvider): | |
def translate_uri(self, uri): | |
return None | |
class QobuzLibraryProvider(backend.LibraryProvider): | |
root_directory = models.Ref.directory( | |
uri=URI_ROOT, | |
name="Qobuz", | |
) | |
def __init__(self, backend): | |
super(QobuzLibraryProvider, self).__init__(backend) | |
self._root = [ | |
models.Ref.directory(uri=URI_ALBUMS, name="Albums"), | |
] | |
def browse(self, uri): | |
logger.debug("Browsing URI %s", uri) | |
if uri == URI_ROOT: | |
return self._root | |
elif uri == URI_ALBUMS: | |
return self._browse_albums() | |
return [] | |
def lookup(self, uri): | |
logger.debug("Looking up URI %s", uri) | |
return [] | |
def _browse_albums(self): | |
# TODO: paging | |
album_list_req = self.backend.session.get(api("userLibrary/getAlbumsList")) | |
album_list = album_list_req.json()["items"] | |
return map(to_album_ref, album_list) | |
{-# START_FILE ./mopidy_qobuz/ext.conf #-} | |
[qobuz] | |
enabled = true | |
username = | |
password = | |
client_id = | |
client_secret = | |
{-# START_FILE ./Mopidy_Qobuz.egg-info/dependency_links.txt #-} | |
{-# START_FILE ./Mopidy_Qobuz.egg-info/entry_points.txt #-} | |
[mopidy.ext] | |
qobuz = mopidy_qobuz:Extension | |
{-# START_FILE ./Mopidy_Qobuz.egg-info/not-zip-safe #-} | |
{-# START_FILE ./Mopidy_Qobuz.egg-info/PKG-INFO #-} | |
Metadata-Version: 1.0 | |
Name: Mopidy-Qobuz | |
Version: 0.0.1 | |
Summary: Mopidy extension for playing music from Qobuz | |
Home-page: https://github.com/secondwtq/mopidy-qobuz | |
Author: Second Datke | |
Author-email: lovejay-lovemusic@outlook.com | |
License: UNKNOWN | |
Description: UNKNOWN | |
Platform: UNKNOWN | |
{-# START_FILE ./Mopidy_Qobuz.egg-info/requires.txt #-} | |
Mopidy>=2.0 | |
Pykka>=1.1 | |
requests>=2.0 | |
setuptools | |
{-# START_FILE ./Mopidy_Qobuz.egg-info/SOURCES.txt #-} | |
MANIFEST.in | |
setup.py | |
Mopidy_Qobuz.egg-info/PKG-INFO | |
Mopidy_Qobuz.egg-info/SOURCES.txt | |
Mopidy_Qobuz.egg-info/dependency_links.txt | |
Mopidy_Qobuz.egg-info/entry_points.txt | |
Mopidy_Qobuz.egg-info/not-zip-safe | |
Mopidy_Qobuz.egg-info/requires.txt | |
Mopidy_Qobuz.egg-info/top_level.txt | |
mopidy_qobuz/__init__.py | |
mopidy_qobuz/backend.py | |
mopidy_qobuz/client.py | |
mopidy_qobuz/ext.conf | |
{-# START_FILE ./Mopidy_Qobuz.egg-info/top_level.txt #-} | |
mopidy_qobuz | |
{-# START_FILE ./setup.py #-} | |
from __future__ import unicode_literals | |
from setuptools import find_packages, setup | |
import re | |
def get_version(filename): | |
regex = "__([a-z]+)__ = \"([^\"]+)\"" | |
return dict(re.findall(regex, open(filename).read()))["version"] | |
setup(name="Mopidy-Qobuz", | |
version=get_version("mopidy_qobuz/__init__.py"), | |
description="Mopidy extension for playing music from Qobuz", | |
url="https://github.com/secondwtq/mopidy-qobuz", | |
author="Second Datke", | |
author_email="lovejay-lovemusic@outlook.com", | |
install_requires=[ | |
"Mopidy >= 2.0", | |
"Pykka >= 1.1", | |
"requests >= 2.0", | |
"setuptools" | |
], | |
entry_points={ | |
"mopidy.ext": [ | |
"qobuz = mopidy_qobuz:Extension" | |
] | |
}, | |
packages=find_packages(), | |
zip_safe=False, | |
include_package_data=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment