From 5617eef6c7d7cdb45890ff53a5120985c4a04131 Mon Sep 17 00:00:00 2001 From: L Maffeo Date: Sun, 12 Aug 2018 17:48:53 +0200 Subject: [PATCH 01/13] Added subsonic plugin --- beetsplug/subsonic.py | 62 +++++++++++++++++++++++++++++++++++++++ docs/changelog.rst | 1 + docs/plugins/subsonic.rst | 37 +++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 beetsplug/subsonic.py create mode 100644 docs/plugins/subsonic.rst diff --git a/beetsplug/subsonic.py b/beetsplug/subsonic.py new file mode 100644 index 0000000000..dece5a0b2f --- /dev/null +++ b/beetsplug/subsonic.py @@ -0,0 +1,62 @@ +# Subsonic plugin for Beets +# Allows to trigger a library scan on Subsonic after music has been imported with Beets +# Your Beets configuration file should contain a subsonic section like the following: +# subsonic: +# host: 192.168.x.y (the IP address where Subsonic listens on) +# port: 4040 (default) +# user: +# pass: +# Plugin wrote by Lorenzo Maffeo + +from beets.plugins import BeetsPlugin +import requests +import string +import hashlib +from random import * + +class Subsonic(BeetsPlugin): + def __init__(self): + super(Subsonic, self).__init__() + self.register_listener('import', self.loaded) + + def loaded(self): + host = self.config['host'].get() + port = self.config['port'].get() + user = self.config['user'].get() + passw = self.config['pass'].get() + url = "http://"+str(host)+":"+str(port)+"/rest/startScan" + salt = "".join([random.choice(string.ascii_letters + string.digits) for n in range(6)]) + t = passw + salt + token = hashlib.md5() + token.update(t.encode('utf-8')) + payload = { + 'u': user, + 't': token.hexdigest(), + 's': salt, + 'v': '1.15.0', + 'c': 'beets' + } + response = requests.post(url, params=payload) + if (response.status_code == 0): + self._log.error(u'Operation Failed due to a generic error, please try again later.') + print("Operation Failed due to a generic error, please try again later.") + elif (response.status_code == 30): + self._log.error(u'Your Subsonic server version is not compatible with this feature, please upgrade to at least version 6.1 (API version 1.15.0).') + print("Your Subsonic server version is not compatible with this feature, please upgrade to at least v +ersion 6.1 (API version 1.15.0).") + elif (response.status_code == 40): + self._log.error(u'Wrong username or password. Check and update the credentials in your Beets configuration file.') + print("Wrong username or password. Check and update the credentials in your Beets configuration file.") + elif (response.status_code == 50): + self._log.error(u'User %s is not allowed to perform the requested operation.', user) + print("User " + str(user) + "is not allowed to perform the requested operation.") + elif (response.status_code == 60): + self._log.error(u'This feature requires Subsonic Premium, check that your license is still valid or the trial period has not expired.') + print("This feature requires Subsonic Premium, check that your license is still valid or the trial pe +riod has not expired.") + elif (response.status_code == 200): + self._log.info('Operation completed successfully!") + print("Operation completed successfully!") + else + self._log.error(u'Unknown error code returned from server.') + print("Unknown error code returned from server.") diff --git a/docs/changelog.rst b/docs/changelog.rst index 4a8b9daf35..2f40d26ed0 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -18,6 +18,7 @@ New features: :user:`jams2` * Automatically upload to Google Play Music library on track import. :user:`shuaiscott` +* Added Subsonic automatic library update plugin Fixes: diff --git a/docs/plugins/subsonic.rst b/docs/plugins/subsonic.rst new file mode 100644 index 0000000000..0bcf0a0e97 --- /dev/null +++ b/docs/plugins/subsonic.rst @@ -0,0 +1,37 @@ +Subsonic Plugin +================ + +``Subsonic`` is a very simple plugin for beets that lets you automatically +update `Subsonic`_'s index whenever you change your beets library. + +.. _Subsonic: http://www.subsonic.org + +To use ``Subsonic`` plugin, enable it in your configuration +(see :ref:`using-plugins`). +Then, you'll probably want to configure the specifics of your Subsonic server. +You can do that using an ``subsonic:`` section in your ``config.yaml``, +which looks like this:: + + subsonic: + host: 192.168.x.x + port: 4040 + user: username + pass: password + +With that all in place, beets will send a Rest API to your Subsonic +server every time you change your beets library. + +This plugin requires the Premium version of Subsonic (or a Trial Premium version). +This plugin requires Subsonic version 6.1 or higher. + +Configuration +------------- + +The available options under the ``subsonic:`` section are: + +- **host**: The Subsonic server name/IP. +- **port**: The Subsonic server port. +- **user**: The Subsonic user. +- **pass**: The Subsonic user password. + +This plugin does not set default values for the above values. From 67568b4f4cb2f2091dc087a1ba96218cae3d618e Mon Sep 17 00:00:00 2001 From: L Maffeo Date: Sun, 12 Aug 2018 19:37:31 +0200 Subject: [PATCH 02/13] Passed tox tests --- beetsplug/subsonic.py | 113 ++++++++++++++++++++++------------------- docs/plugins/index.rst | 1 + 2 files changed, 61 insertions(+), 53 deletions(-) diff --git a/beetsplug/subsonic.py b/beetsplug/subsonic.py index dece5a0b2f..667e18bddb 100644 --- a/beetsplug/subsonic.py +++ b/beetsplug/subsonic.py @@ -1,62 +1,69 @@ +# -*- coding: utf-8 -*- # Subsonic plugin for Beets -# Allows to trigger a library scan on Subsonic after music has been imported with Beets -# Your Beets configuration file should contain a subsonic section like the following: -# subsonic: -# host: 192.168.x.y (the IP address where Subsonic listens on) -# port: 4040 (default) -# user: -# pass: -# Plugin wrote by Lorenzo Maffeo +# Allows to trigger a library scan on Subsonic +# after music has been imported with Beets +# Your Beets configuration file should contain +# a subsonic section like the following: +# subsonic: +# host: 192.168.x.y (the IP address where Subsonic listens on) +# port: 4040 (default) +# user: +# pass: +# Plugin wrote by maffo999 + +"""Updates Subsonic library on Beets import +""" +from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin import requests import string import hashlib -from random import * +import random + class Subsonic(BeetsPlugin): - def __init__(self): - super(Subsonic, self).__init__() - self.register_listener('import', self.loaded) + def __init__(self): + super(Subsonic, self).__init__() + self.register_listener('import', self.loaded) - def loaded(self): - host = self.config['host'].get() - port = self.config['port'].get() - user = self.config['user'].get() - passw = self.config['pass'].get() - url = "http://"+str(host)+":"+str(port)+"/rest/startScan" - salt = "".join([random.choice(string.ascii_letters + string.digits) for n in range(6)]) - t = passw + salt - token = hashlib.md5() - token.update(t.encode('utf-8')) - payload = { - 'u': user, - 't': token.hexdigest(), - 's': salt, - 'v': '1.15.0', - 'c': 'beets' - } - response = requests.post(url, params=payload) - if (response.status_code == 0): - self._log.error(u'Operation Failed due to a generic error, please try again later.') - print("Operation Failed due to a generic error, please try again later.") - elif (response.status_code == 30): - self._log.error(u'Your Subsonic server version is not compatible with this feature, please upgrade to at least version 6.1 (API version 1.15.0).') - print("Your Subsonic server version is not compatible with this feature, please upgrade to at least v -ersion 6.1 (API version 1.15.0).") - elif (response.status_code == 40): - self._log.error(u'Wrong username or password. Check and update the credentials in your Beets configuration file.') - print("Wrong username or password. Check and update the credentials in your Beets configuration file.") - elif (response.status_code == 50): - self._log.error(u'User %s is not allowed to perform the requested operation.', user) - print("User " + str(user) + "is not allowed to perform the requested operation.") - elif (response.status_code == 60): - self._log.error(u'This feature requires Subsonic Premium, check that your license is still valid or the trial period has not expired.') - print("This feature requires Subsonic Premium, check that your license is still valid or the trial pe -riod has not expired.") - elif (response.status_code == 200): - self._log.info('Operation completed successfully!") - print("Operation completed successfully!") - else - self._log.error(u'Unknown error code returned from server.') - print("Unknown error code returned from server.") + def loaded(self): + host = self.config['host'].get() + port = self.config['port'].get() + user = self.config['user'].get() + passw = self.config['pass'].get() + r = string.ascii_letters + string.digits + url = "http://"+str(host)+":"+str(port)+"/rest/startScan" + salt = "".join([random.choice(r) for n in range(6)]) + t = passw + salt + token = hashlib.md5() + token.update(t.encode('utf-8')) + payload = { + 'u': user, + 't': token.hexdigest(), + 's': salt, + 'v': '1.15.0', + 'c': 'beets' + } + response = requests.post(url, params=payload) + if (response.status_code == 0): + self._log.error(u'Generic error, please try again later.') + print("Generic error, please try again later.") + elif (response.status_code == 30): + self._log.error(u'Subsonic server not compatible with plugin.') + print("Subsonic server not compatible with plugin.") + elif (response.status_code == 40): + self._log.error(u'Wrong username or password.') + print("Wrong username or password.") + elif (response.status_code == 50): + self._log.error(u'User not allowed to perform the operation.') + print("User not allowed to perform the requested operation.") + elif (response.status_code == 60): + self._log.error(u'This feature requires Subsonic Premium.') + print("This feature requires Subsonic Premium.") + elif (response.status_code == 200): + self._log.info('Operation completed successfully!') + print("Operation completed successfully!") + else: + self._log.error(u'Unknown error code returned from server.') + print("Unknown error code returned from server.") diff --git a/docs/plugins/index.rst b/docs/plugins/index.rst index 50853413a3..8c23883c9e 100644 --- a/docs/plugins/index.rst +++ b/docs/plugins/index.rst @@ -89,6 +89,7 @@ like this:: smartplaylist sonosupdate spotify + subsonic the thumbnails types From fc1592adbee583bc1657606142c0ecc18fe1745f Mon Sep 17 00:00:00 2001 From: L Maffeo Date: Sat, 18 Aug 2018 14:17:00 +0200 Subject: [PATCH 03/13] Renamed plugin, added default configuration and comments --- beetsplug/subsonicupdate.py | 97 +++++++++++++++++++++++++++++++++ docs/changelog.rst | 3 +- docs/plugins/index.rst | 2 +- docs/plugins/subsonicupdate.rst | 41 ++++++++++++++ 4 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 beetsplug/subsonicupdate.py create mode 100644 docs/plugins/subsonicupdate.rst diff --git a/beetsplug/subsonicupdate.py b/beetsplug/subsonicupdate.py new file mode 100644 index 0000000000..b78f491888 --- /dev/null +++ b/beetsplug/subsonicupdate.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +# This file is part of beets. +# Copyright 2016, Adrian Sampson. +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. + +"""Updates Subsonic library on Beets import +Your Beets configuration file should contain +a "subsonic" section like the following: + subsonic: + host: 192.168.x.y (Subsonic server IP) + port: 4040 (default) + user: + pass: +""" +from __future__ import division, absolute_import, print_function + +from beets.plugins import BeetsPlugin +import requests +import string +import hashlib +import random + +__author__ = 'https://github.com/maffo999' + + +class SubsonicUpdate(BeetsPlugin): + def __init__(self): + super(SubsonicUpdate, self).__init__() + +# Set default configuration values + self.config['subsonic'].add({ + u'host': u'localhost', + u'port': 4040, + u'user': u'admin', + u'pass': u'admin', + }) + self.config['subsonic']['pass'].redact = True + self.register_listener('import', self.loaded) + + def loaded(self): + host = self.config['host'].as_str() + port = self.config['port'].as_str() + user = self.config['user'].as_str() + passw = self.config['pass'].as_str() + +# To avoid sending plaintext passwords, authentication will be performed via +# username, a token, and a 6 random letters/numbers sequence +# The token is the concatenation of your password and the 6 random +# letters/numbers (the salt) which is hashed with MD5. + +# Pick the random sequence and salt the password + r = string.ascii_letters + string.digits + salt = "".join([random.choice(r) for n in range(6)]) + t = passw + salt + +# Hash the password making sure it's UTF-8 format + token = hashlib.md5() + token.update(t.encode('utf-8')) + +# Put together the payload of the request to the server and the URL + payload = { + 'u': user, + 't': token.hexdigest(), + 's': salt, + 'v': '1.15.0', + 'c': 'beets' + } + url = "http://{}:{}/rest/startScan".format(host, port) + +# Send the request and store the response + response = requests.post(url, params=payload) + +# Log an eventual error reported by the server or success on status code 200 + if (response.status_code == 0): + self._log.error(u'Generic error, please try again later.') + elif (response.status_code == 30): + self._log.error(u'Subsonic server not compatible with plugin.') + elif (response.status_code == 40): + self._log.error(u'Wrong username or password.') + elif (response.status_code == 50): + self._log.error(u'User not allowed to perform the operation.') + elif (response.status_code == 60): + self._log.error(u'This feature requires Subsonic Premium.') + elif (response.status_code == 200): + self._log.info('Operation completed successfully!') + else: + self._log.error(u'Unknown error code returned from server.') diff --git a/docs/changelog.rst b/docs/changelog.rst index 2f40d26ed0..d18c6c690e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -18,7 +18,8 @@ New features: :user:`jams2` * Automatically upload to Google Play Music library on track import. :user:`shuaiscott` -* Added Subsonic automatic library update plugin +* Added :doc:`/plugins/subsonicupdate` that can automatically update your Subsonic library. + :user:`maffo999` Fixes: diff --git a/docs/plugins/index.rst b/docs/plugins/index.rst index 8c23883c9e..6bf50e227b 100644 --- a/docs/plugins/index.rst +++ b/docs/plugins/index.rst @@ -89,7 +89,7 @@ like this:: smartplaylist sonosupdate spotify - subsonic + subsonicupdate the thumbnails types diff --git a/docs/plugins/subsonicupdate.rst b/docs/plugins/subsonicupdate.rst new file mode 100644 index 0000000000..dd48b8381d --- /dev/null +++ b/docs/plugins/subsonicupdate.rst @@ -0,0 +1,41 @@ +Subsonic Plugin +================ + +``subsonic`` is a very simple plugin for beets that lets you automatically +update `Subsonic`_'s index whenever you change your beets library. + +.. _Subsonic: http://www.subsonic.org + +To use ``subsonic`` plugin, enable it in your configuration +(see :ref:`using-plugins`). +Then, you'll probably want to configure the specifics of your Subsonic server. +You can do that using an ``subsonic:`` section in your ``config.yaml``, +which looks like this:: + + subsonic: + host: X.X.X.X + port: 4040 + user: username + pass: password + +With that all in place, beets will send a Rest API to your Subsonic +server every time you change your beets library. + +This plugin requires Subsonic v6.1 or higher and an active Premium license (or trial). + +Configuration +------------- + +The available options under the ``subsonic:`` section are: + +- **host**: The Subsonic server name/IP. +- **port**: The Subsonic server port. +- **user**: The Subsonic user. +- **pass**: The Subsonic user password. + +This plugin sets the following default values: + +- **host**: localhost +- **port**: 4040 +- **user**: admin +- **pass**: admin \ No newline at end of file From d4cecccdace3fabf9e89736ad5ba6c05a9e351af Mon Sep 17 00:00:00 2001 From: L Maffeo Date: Sat, 18 Aug 2018 14:22:25 +0200 Subject: [PATCH 04/13] Renamed plugin, added comments and minor fixes. --- beetsplug/subsonic.py | 69 --------------------------------------- docs/plugins/subsonic.rst | 37 --------------------- 2 files changed, 106 deletions(-) delete mode 100644 beetsplug/subsonic.py delete mode 100644 docs/plugins/subsonic.rst diff --git a/beetsplug/subsonic.py b/beetsplug/subsonic.py deleted file mode 100644 index 667e18bddb..0000000000 --- a/beetsplug/subsonic.py +++ /dev/null @@ -1,69 +0,0 @@ -# -*- coding: utf-8 -*- -# Subsonic plugin for Beets -# Allows to trigger a library scan on Subsonic -# after music has been imported with Beets -# Your Beets configuration file should contain -# a subsonic section like the following: -# subsonic: -# host: 192.168.x.y (the IP address where Subsonic listens on) -# port: 4040 (default) -# user: -# pass: -# Plugin wrote by maffo999 - -"""Updates Subsonic library on Beets import -""" -from __future__ import division, absolute_import, print_function - -from beets.plugins import BeetsPlugin -import requests -import string -import hashlib -import random - - -class Subsonic(BeetsPlugin): - def __init__(self): - super(Subsonic, self).__init__() - self.register_listener('import', self.loaded) - - def loaded(self): - host = self.config['host'].get() - port = self.config['port'].get() - user = self.config['user'].get() - passw = self.config['pass'].get() - r = string.ascii_letters + string.digits - url = "http://"+str(host)+":"+str(port)+"/rest/startScan" - salt = "".join([random.choice(r) for n in range(6)]) - t = passw + salt - token = hashlib.md5() - token.update(t.encode('utf-8')) - payload = { - 'u': user, - 't': token.hexdigest(), - 's': salt, - 'v': '1.15.0', - 'c': 'beets' - } - response = requests.post(url, params=payload) - if (response.status_code == 0): - self._log.error(u'Generic error, please try again later.') - print("Generic error, please try again later.") - elif (response.status_code == 30): - self._log.error(u'Subsonic server not compatible with plugin.') - print("Subsonic server not compatible with plugin.") - elif (response.status_code == 40): - self._log.error(u'Wrong username or password.') - print("Wrong username or password.") - elif (response.status_code == 50): - self._log.error(u'User not allowed to perform the operation.') - print("User not allowed to perform the requested operation.") - elif (response.status_code == 60): - self._log.error(u'This feature requires Subsonic Premium.') - print("This feature requires Subsonic Premium.") - elif (response.status_code == 200): - self._log.info('Operation completed successfully!') - print("Operation completed successfully!") - else: - self._log.error(u'Unknown error code returned from server.') - print("Unknown error code returned from server.") diff --git a/docs/plugins/subsonic.rst b/docs/plugins/subsonic.rst deleted file mode 100644 index 0bcf0a0e97..0000000000 --- a/docs/plugins/subsonic.rst +++ /dev/null @@ -1,37 +0,0 @@ -Subsonic Plugin -================ - -``Subsonic`` is a very simple plugin for beets that lets you automatically -update `Subsonic`_'s index whenever you change your beets library. - -.. _Subsonic: http://www.subsonic.org - -To use ``Subsonic`` plugin, enable it in your configuration -(see :ref:`using-plugins`). -Then, you'll probably want to configure the specifics of your Subsonic server. -You can do that using an ``subsonic:`` section in your ``config.yaml``, -which looks like this:: - - subsonic: - host: 192.168.x.x - port: 4040 - user: username - pass: password - -With that all in place, beets will send a Rest API to your Subsonic -server every time you change your beets library. - -This plugin requires the Premium version of Subsonic (or a Trial Premium version). -This plugin requires Subsonic version 6.1 or higher. - -Configuration -------------- - -The available options under the ``subsonic:`` section are: - -- **host**: The Subsonic server name/IP. -- **port**: The Subsonic server port. -- **user**: The Subsonic user. -- **pass**: The Subsonic user password. - -This plugin does not set default values for the above values. From b179df963ab156c23c1571c95b37ac97d0fc08ee Mon Sep 17 00:00:00 2001 From: L Maffeo Date: Sat, 18 Aug 2018 14:29:34 +0200 Subject: [PATCH 05/13] Minor rewording --- docs/plugins/subsonicupdate.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/plugins/subsonicupdate.rst b/docs/plugins/subsonicupdate.rst index dd48b8381d..ca0731eca1 100644 --- a/docs/plugins/subsonicupdate.rst +++ b/docs/plugins/subsonicupdate.rst @@ -1,15 +1,15 @@ -Subsonic Plugin +SubsonicUpdate Plugin ================ -``subsonic`` is a very simple plugin for beets that lets you automatically +``subsonicupdate`` is a very simple plugin for beets that lets you automatically update `Subsonic`_'s index whenever you change your beets library. .. _Subsonic: http://www.subsonic.org -To use ``subsonic`` plugin, enable it in your configuration +To use ``subsonicupdate`` plugin, enable it in your configuration (see :ref:`using-plugins`). Then, you'll probably want to configure the specifics of your Subsonic server. -You can do that using an ``subsonic:`` section in your ``config.yaml``, +You can do that using a ``subsonic:`` section in your ``config.yaml``, which looks like this:: subsonic: From dfb5fe32764ba8467a2a242cd71d7c305af279d6 Mon Sep 17 00:00:00 2001 From: L Maffeo Date: Sat, 18 Aug 2018 16:17:14 +0200 Subject: [PATCH 06/13] Merged changes in changelog.rst --- docs/changelog.rst | 5 +++++ docs/plugins/subsonicupdate.rst | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index d18c6c690e..8e4fcb46ec 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -18,6 +18,11 @@ New features: :user:`jams2` * Automatically upload to Google Play Music library on track import. :user:`shuaiscott` +* New options for Google Play Music authentication in gmusic plugin. + :user:`thetarkus` +* The `absubmit` plugin now works in parallel (on Python 3 only). + Thanks to :user:`bemeurer`. + :bug:`2442` * Added :doc:`/plugins/subsonicupdate` that can automatically update your Subsonic library. :user:`maffo999` diff --git a/docs/plugins/subsonicupdate.rst b/docs/plugins/subsonicupdate.rst index ca0731eca1..d534201ae3 100644 --- a/docs/plugins/subsonicupdate.rst +++ b/docs/plugins/subsonicupdate.rst @@ -1,5 +1,5 @@ SubsonicUpdate Plugin -================ +===================== ``subsonicupdate`` is a very simple plugin for beets that lets you automatically update `Subsonic`_'s index whenever you change your beets library. From a981afffa3779722fe8084046398ba5a56f1b79f Mon Sep 17 00:00:00 2001 From: L Maffeo Date: Sat, 18 Aug 2018 16:21:48 +0200 Subject: [PATCH 07/13] Merged changelog --- docs/changelog.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 8e4fcb46ec..4786178cf6 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -28,6 +28,11 @@ New features: Fixes: +* Restore iTunes Store album art source, and remove the dependency on + python-itunes_, which had gone unmaintained and was not py3 compatible. + Thanks to :user:`ocelma` for creating python-itunes_ in the first place. + Thanks to :user:`nathdwek`. + :bug:`2371` :bug:`2551` :bug:`2718` * Fix compatibility Python 3.7 and its change to a name in the ``re`` module. :bug:`2978` * R128 normalization tags are now properly deleted from files when the values @@ -47,6 +52,11 @@ Fixes: with CORS enabled. Thanks to :user:`rveachkc`. :bug:`2979`: :bug:`2980` +* Improve error reporting: during startup if sqlite returns an error the + sqlite error message is attached to the beets message. + :bug:`3005` + +.. _python-itunes: https://github.com/ocelma/python-itunes 1.4.7 (May 29, 2018) From 10c40b15756152e8b7988411d306a33662507762 Mon Sep 17 00:00:00 2001 From: Io Ii Date: Sun, 26 Aug 2018 08:35:16 +0200 Subject: [PATCH 08/13] Second review by @sampsyo --- beetsplug/subsonicupdate.py | 46 ++++++++++++++++----------------- docs/plugins/subsonicupdate.rst | 15 +++-------- 2 files changed, 26 insertions(+), 35 deletions(-) diff --git a/beetsplug/subsonicupdate.py b/beetsplug/subsonicupdate.py index b78f491888..6714762c0c 100644 --- a/beetsplug/subsonicupdate.py +++ b/beetsplug/subsonicupdate.py @@ -25,6 +25,7 @@ from __future__ import division, absolute_import, print_function from beets.plugins import BeetsPlugin +from beets import config import requests import string import hashlib @@ -37,37 +38,36 @@ class SubsonicUpdate(BeetsPlugin): def __init__(self): super(SubsonicUpdate, self).__init__() -# Set default configuration values - self.config['subsonic'].add({ + # Set default configuration values + config['subsonic'].add({ u'host': u'localhost', u'port': 4040, u'user': u'admin', u'pass': u'admin', }) - self.config['subsonic']['pass'].redact = True + config['subsonic']['pass'].redact = True self.register_listener('import', self.loaded) def loaded(self): - host = self.config['host'].as_str() - port = self.config['port'].as_str() - user = self.config['user'].as_str() - passw = self.config['pass'].as_str() + host = config['host'].as_str() + port = config['port'].as_str() + user = config['user'].as_str() + passw = config['pass'].as_str() -# To avoid sending plaintext passwords, authentication will be performed via -# username, a token, and a 6 random letters/numbers sequence -# The token is the concatenation of your password and the 6 random -# letters/numbers (the salt) which is hashed with MD5. + # To avoid sending plaintext passwords, authentication will be + # performed via username, a token, and a 6 random + # letters/numbers sequence. + # The token is the concatenation of your password and the 6 random + # letters/numbers (the salt) which is hashed with MD5. -# Pick the random sequence and salt the password + # Pick the random sequence and salt the password r = string.ascii_letters + string.digits salt = "".join([random.choice(r) for n in range(6)]) t = passw + salt - -# Hash the password making sure it's UTF-8 format token = hashlib.md5() token.update(t.encode('utf-8')) -# Put together the payload of the request to the server and the URL + # Put together the payload of the request to the server and the URL payload = { 'u': user, 't': token.hexdigest(), @@ -76,22 +76,20 @@ def loaded(self): 'c': 'beets' } url = "http://{}:{}/rest/startScan".format(host, port) - -# Send the request and store the response response = requests.post(url, params=payload) -# Log an eventual error reported by the server or success on status code 200 - if (response.status_code == 0): + # Log an eventual error by the server or success on status code 200 + if response.status_code == 0: self._log.error(u'Generic error, please try again later.') - elif (response.status_code == 30): + elif response.status_code == 30: self._log.error(u'Subsonic server not compatible with plugin.') - elif (response.status_code == 40): + elif response.status_code == 40: self._log.error(u'Wrong username or password.') - elif (response.status_code == 50): + elif response.status_code == 50: self._log.error(u'User not allowed to perform the operation.') - elif (response.status_code == 60): + elif response.status_code == 60: self._log.error(u'This feature requires Subsonic Premium.') - elif (response.status_code == 200): + elif response.status_code == 200: self._log.info('Operation completed successfully!') else: self._log.error(u'Unknown error code returned from server.') diff --git a/docs/plugins/subsonicupdate.rst b/docs/plugins/subsonicupdate.rst index d534201ae3..6d469dfa74 100644 --- a/docs/plugins/subsonicupdate.rst +++ b/docs/plugins/subsonicupdate.rst @@ -28,14 +28,7 @@ Configuration The available options under the ``subsonic:`` section are: -- **host**: The Subsonic server name/IP. -- **port**: The Subsonic server port. -- **user**: The Subsonic user. -- **pass**: The Subsonic user password. - -This plugin sets the following default values: - -- **host**: localhost -- **port**: 4040 -- **user**: admin -- **pass**: admin \ No newline at end of file +- **host**: The Subsonic server name/IP. Default: ``localhost`` +- **port**: The Subsonic server port. Default: ``4040`` +- **user**: The Subsonic user. Default: ``admin`` +- **pass**: The Subsonic user password. Default: ``admin`` From 7bfb7e12e75ad6947157a59def546b07078e1a65 Mon Sep 17 00:00:00 2001 From: Io Ii Date: Sun, 26 Aug 2018 09:13:23 +0200 Subject: [PATCH 09/13] Minor fix in config --- beetsplug/subsonicupdate.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/beetsplug/subsonicupdate.py b/beetsplug/subsonicupdate.py index 6714762c0c..52ea0dba6f 100644 --- a/beetsplug/subsonicupdate.py +++ b/beetsplug/subsonicupdate.py @@ -49,10 +49,10 @@ def __init__(self): self.register_listener('import', self.loaded) def loaded(self): - host = config['host'].as_str() - port = config['port'].as_str() - user = config['user'].as_str() - passw = config['pass'].as_str() + host = config['subsonic']['host'].as_str() + port = config['subsonic']['port'].as_str() + user = config['subsonic']['user'].as_str() + passw = config['subsonic']['pass'].as_str() # To avoid sending plaintext passwords, authentication will be # performed via username, a token, and a 6 random From bd5ab43bc6276a4846642144b43595013b0ea5f6 Mon Sep 17 00:00:00 2001 From: L Maffeo Date: Sun, 26 Aug 2018 14:34:47 +0200 Subject: [PATCH 10/13] Removed logging (needs additional testing) --- beetsplug/subsonicupdate.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/beetsplug/subsonicupdate.py b/beetsplug/subsonicupdate.py index 52ea0dba6f..9b87531b8e 100644 --- a/beetsplug/subsonicupdate.py +++ b/beetsplug/subsonicupdate.py @@ -78,18 +78,18 @@ def loaded(self): url = "http://{}:{}/rest/startScan".format(host, port) response = requests.post(url, params=payload) - # Log an eventual error by the server or success on status code 200 - if response.status_code == 0: - self._log.error(u'Generic error, please try again later.') - elif response.status_code == 30: - self._log.error(u'Subsonic server not compatible with plugin.') - elif response.status_code == 40: - self._log.error(u'Wrong username or password.') - elif response.status_code == 50: - self._log.error(u'User not allowed to perform the operation.') - elif response.status_code == 60: - self._log.error(u'This feature requires Subsonic Premium.') - elif response.status_code == 200: - self._log.info('Operation completed successfully!') - else: - self._log.error(u'Unknown error code returned from server.') + # TODO: Log an eventual error by the server or success on status code 200 + #if response.status_code == 0: + # self._log.error(u'Generic error, please try again later.') + #elif response.status_code == 30: + # self._log.error(u'Subsonic server not compatible with plugin.') + #elif response.status_code == 40: + # self._log.error(u'Wrong username or password.') + #elif response.status_code == 50: + # self._log.error(u'User not allowed to perform the operation.') + #elif response.status_code == 60: + # self._log.error(u'This feature requires Subsonic Premium.') + #elif response.status_code == 200: + # self._log.info('Operation completed successfully!') + #else: + # self._log.error(u'Unknown error code returned from server.') From 1e0378d584bf26495250f9563e55d4bdf0d32e07 Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Sun, 26 Aug 2018 08:50:24 -0400 Subject: [PATCH 11/13] Refine changelog entry --- docs/changelog.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index c9920bd30d..ca04d160fe 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -30,8 +30,9 @@ New features: * :doc:`/plugins/replaygain`: albumpeak on large collections is calculated as the average, not the maximum. :bug:`3008` :bug:`3009` -* Added :doc:`/plugins/subsonicupdate` that can automatically update your Subsonic library. - :user:`maffo999` +* A new :doc:`/plugins/subsonicupdate` can automatically update your Subsonic library. + Thanks to :user:`maffo999`. + :bug:`3001` Fixes: From b747291468ef127b3b3ec9cd9d5e648b864355ac Mon Sep 17 00:00:00 2001 From: L Maffeo Date: Sun, 26 Aug 2018 15:22:22 +0200 Subject: [PATCH 12/13] Passed tox tests --- beetsplug/subsonicupdate.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/beetsplug/subsonicupdate.py b/beetsplug/subsonicupdate.py index 9b87531b8e..dc75543481 100644 --- a/beetsplug/subsonicupdate.py +++ b/beetsplug/subsonicupdate.py @@ -78,18 +78,18 @@ def loaded(self): url = "http://{}:{}/rest/startScan".format(host, port) response = requests.post(url, params=payload) - # TODO: Log an eventual error by the server or success on status code 200 - #if response.status_code == 0: - # self._log.error(u'Generic error, please try again later.') - #elif response.status_code == 30: + # TODO Log an error by the server or success on status code 200 + if response.status_code != 200: + self._log.error(u'Generic error, please try again later.') + # elif response.status_code == 30: # self._log.error(u'Subsonic server not compatible with plugin.') - #elif response.status_code == 40: + # elif response.status_code == 40: # self._log.error(u'Wrong username or password.') - #elif response.status_code == 50: + # elif response.status_code == 50: # self._log.error(u'User not allowed to perform the operation.') - #elif response.status_code == 60: + # elif response.status_code == 60: # self._log.error(u'This feature requires Subsonic Premium.') - #elif response.status_code == 200: + # elif response.status_code == 200: # self._log.info('Operation completed successfully!') - #else: + # else: # self._log.error(u'Unknown error code returned from server.') From 39e8a8389b28f647f9a49b7bf3f2f03fdf8ffce9 Mon Sep 17 00:00:00 2001 From: L Maffeo Date: Sun, 26 Aug 2018 17:38:17 +0200 Subject: [PATCH 13/13] Code cleanup --- beetsplug/subsonicupdate.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/beetsplug/subsonicupdate.py b/beetsplug/subsonicupdate.py index dc75543481..41e3ec36f1 100644 --- a/beetsplug/subsonicupdate.py +++ b/beetsplug/subsonicupdate.py @@ -78,18 +78,5 @@ def loaded(self): url = "http://{}:{}/rest/startScan".format(host, port) response = requests.post(url, params=payload) - # TODO Log an error by the server or success on status code 200 if response.status_code != 200: self._log.error(u'Generic error, please try again later.') - # elif response.status_code == 30: - # self._log.error(u'Subsonic server not compatible with plugin.') - # elif response.status_code == 40: - # self._log.error(u'Wrong username or password.') - # elif response.status_code == 50: - # self._log.error(u'User not allowed to perform the operation.') - # elif response.status_code == 60: - # self._log.error(u'This feature requires Subsonic Premium.') - # elif response.status_code == 200: - # self._log.info('Operation completed successfully!') - # else: - # self._log.error(u'Unknown error code returned from server.')