Repository: Flexget/Flexget

Issue:
BUG: Unhandled error in plugin from_transmission
<!---
Before opening an issue, verify:

- Is this a feature request? Post it on https://feathub.com/Flexget/Flexget
- Is this an issue with webui? Make an issue over on https://github.com/Flexget/webui
- Did you recently upgrade? Look at the Change Log and Upgrade Actions to make sure that you don't need to make any changes to your config https://flexget.com/ChangeLog https://flexget.com/UpgradeActions
- Are you running FlexGet as a daemon? Stop it completely and then start it again https://flexget.com/CLI/daemon
- Did you search to see if the issue already exists? https://github.com/Flexget/Flexget/issues
- Did you fill out the issue template as completely as possible?

The issue template is here because it helps to ensure you submitted all the necessary information the first time, and allows us to more quickly review issues. Please fill it out correctly and do not ignore it, no matter how irrelevant you think it may be. Thanks in advance for your help with this!
--->

### Expected behaviour:

Flexget continues to connect to Transmission without crashing when username and password are provided. This is recent new crashing behaviour.

### Actual behaviour:

Crash despite passing username and password.

### Steps to reproduce:
- Step 1: Execute task with from_transmission plugin

#### Config:
```yaml
root@e64a70b996d2:/config# flexget exec --task cleanup-torrents --dump-config
There is a FlexGet process already running for this config, sending execution there.
--- config from task: cleanup-torrents
disable:
  - seen
  - seen_info_hash
from_transmission:
  host: transmission
  password: xxx
  port: 9091
  username: xxx
if:
  - transmission_progress == 100: accept
  - transmission_ratio < 1.0 and transmission_date_done > now - timedelta(days=15): reject
no_entries_ok: true
priority: 40
transmission:
  action: purge
  host: transmission
  password: xxx
  port: 9091
  username: xxx
```
  
#### Log:
<details>
 <summary>(click to expand)</summary>

```
2021-01-18 20:33:43 DEBUG    transmission  cleanup-torrents Connecting to http://transmission:9091/transmission/
2021-01-18 20:33:43 ERROR    transmission-rpc cleanup-torrents Error: Expecting value: line 1 column 1 (char 0)
2021-01-18 20:33:43 ERROR    transmission-rpc cleanup-torrents Request: "{"tag": 0, "method": "session-get", "arguments": {}}"
2021-01-18 20:33:43 ERROR    transmission-rpc cleanup-torrents HTTP data: "<h1>421: Misdirected Request</h1><p>Transmission received your request, but the hostname was unrecognized.</p><p>To fix this, choose one of the following options:<ul><li>Enable password authentication, then any hostname is allowed.</li><li>Add the hostname you want to use to the whitelist in settings.</li></ul></p><p>If you're editing settings.json, see the 'rpc-host-whitelist' and 'rpc-host-whitelist-enabled' entries.</p><p>This requirement has been added to help prevent <a href="https://en.wikipedia.org/wiki/DNS_rebinding">DNS Rebinding</a> attacks.</p>"
2021-01-18 20:33:43 CRITICAL task          cleanup-torrents BUG: Unhandled error in plugin from_transmission: 
Traceback (most recent call last):

  File "/usr/lib/python3.8/site-packages/transmission_rpc/client.py", line 221, in _request
    data: dict = json.loads(http_data)
                 │    │     └ '<h1>421: Misdirected Request</h1><p>Transmission received your request, but the hostname was unrecognized.</p><p>To fix this...
                 │    └ <function loads at 0x7fa0008aed30>
                 └ <module 'json' from '/usr/lib/python3.8/json/__init__.py'>
  File "/usr/lib/python3.8/json/__init__.py", line 357, in loads
    return _default_decoder.decode(s)
           │                │      └ '<h1>421: Misdirected Request</h1><p>Transmission received your request, but the hostname was unrecognized.</p><p>To fix this...
           │                └ <function JSONDecoder.decode at 0x7fa0008ae670>
           └ <json.decoder.JSONDecoder object at 0x7fa0008a4040>
  File "/usr/lib/python3.8/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               │    │          │      │  └ '<h1>421: Misdirected Request</h1><p>Transmission received your request, but the hostname was unrecognized.</p><p>To fix this...
               │    │          │      └ <built-in method match of re.Pattern object at 0x7fa0009b63f0>
               │    │          └ '<h1>421: Misdirected Request</h1><p>Transmission received your request, but the hostname was unrecognized.</p><p>To fix this...
               │    └ <function JSONDecoder.raw_decode at 0x7fa0008ae700>
               └ <json.decoder.JSONDecoder object at 0x7fa0008a4040>
  File "/usr/lib/python3.8/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
          │                                  └ '<h1>421: Misdirected Request</h1><p>Transmission received your request, but the hostname was unrecognized.</p><p>To fix this...
          └ <class 'json.decoder.JSONDecodeError'>

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)


The above exception was the direct cause of the following exception:


Traceback (most recent call last):

  File "/usr/lib/python3.8/threading.py", line 890, in _bootstrap
    self._bootstrap_inner()
    │    └ <function Thread._bootstrap_inner at 0x7fa00118df70>
    └ <Thread(task_queue, started daemon 140325069957944)>
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
    │    └ <function Thread.run at 0x7fa00118dca0>
    └ <Thread(task_queue, started daemon 140325069957944)>
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
    │    │        │    │        │    └ {}
    │    │        │    │        └ <Thread(task_queue, started daemon 140325069957944)>
    │    │        │    └ ()
    │    │        └ <Thread(task_queue, started daemon 140325069957944)>
    │    └ <bound method TaskQueue.run of <flexget.task_queue.TaskQueue object at 0x7f9ffb4b8f70>>
    └ <Thread(task_queue, started daemon 140325069957944)>
  File "/usr/lib/python3.8/site-packages/flexget/task_queue.py", line 46, in run
    self.current_task.execute()
    │    │            └ <function Task.execute at 0x7f9ffedcfb80>
    │    └ <flexget.task.Task object at 0x7f9ff93dce80>
    └ <flexget.task_queue.TaskQueue object at 0x7f9ffb4b8f70>
  File "/usr/lib/python3.8/site-packages/flexget/task.py", line 87, in wrapper
    return func(self, *args, **kw)
           │    │      │       └ {}
           │    │      └ ()
           │    └ <flexget.task.Task object at 0x7f9ff93dce80>
           └ <function Task.execute at 0x7f9ffedcfaf0>
  File "/usr/lib/python3.8/site-packages/flexget/task.py", line 722, in execute
    self._execute()
    │    └ <function Task._execute at 0x7f9ffedcfa60>
    └ <flexget.task.Task object at 0x7f9ff93dce80>
  File "/usr/lib/python3.8/site-packages/flexget/task.py", line 688, in _execute
    self.__run_task_phase(phase)
    │                     └ 'input'
    └ <flexget.task.Task object at 0x7f9ff93dce80>
  File "/usr/lib/python3.8/site-packages/flexget/task.py", line 514, in __run_task_phase
    response = self.__run_plugin(plugin, phase, args)
               │                 │       │      └ (<flexget.task.Task object at 0x7f9ff93dce80>, {'host': 'transmission', 'port': 9091, 'username': 'dl', 'password': 'torrents...
               │                 │       └ 'input'
               │                 └ <PluginInfo(name=from_transmission)>
               └ <flexget.task.Task object at 0x7f9ff93dce80>
> File "/usr/lib/python3.8/site-packages/flexget/task.py", line 547, in __run_plugin
    result = method(*args, **kwargs)
             │       │       └ {}
             │       └ (<flexget.task.Task object at 0x7f9ff93dce80>, {'host': 'transmission', 'port': 9091, 'username': 'dl', 'password': 'torrents...
             └ <Event(name=plugin.from_transmission.input,func=on_task_input,priority=128)>
  File "/usr/lib/python3.8/site-packages/flexget/event.py", line 20, in __call__
    return self.func(*args, **kwargs)
           │    │     │       └ {}
           │    │     └ (<flexget.task.Task object at 0x7f9ff93dce80>, {'host': 'transmission', 'port': 9091, 'username': 'dl', 'password': 'torrents...
           │    └ <bound method PluginTransmissionInput.on_task_input of <flexget.plugins.clients.transmission.PluginTransmissionInput object a...
           └ <Event(name=plugin.from_transmission.input,func=on_task_input,priority=128)>
  File "/usr/lib/python3.8/site-packages/flexget/plugins/clients/transmission.py", line 189, in on_task_input
    self.client = self.create_rpc_client(config)
    │    │        │    │                 └ {'host': 'transmission', 'port': 9091, 'username': 'dl', 'password': 'torrents', 'enabled': True, 'main_file_ratio': 0.9, 'on...
    │    │        │    └ <function TransmissionBase.create_rpc_client at 0x7f9ffebd4e50>
    │    │        └ <flexget.plugins.clients.transmission.PluginTransmissionInput object at 0x7f9ffb8fae50>
    │    └ None
    └ <flexget.plugins.clients.transmission.PluginTransmissionInput object at 0x7f9ffb8fae50>
  File "/usr/lib/python3.8/site-packages/flexget/plugins/clients/transmission.py", line 70, in create_rpc_client
    cli = transmissionrpc.Client(
          │               └ <class 'transmission_rpc.client.Client'>
          └ <module 'transmission_rpc' from '/usr/lib/python3.8/site-packages/transmission_rpc/__init__.py'>
  File "/usr/lib/python3.8/site-packages/transmission_rpc/client.py", line 112, in __init__
    self.get_session()
    │    └ <function Client.get_session at 0x7f9ffeb3e040>
    └ <transmission_rpc.client.Client object at 0x7f9ff8cbb610>
  File "/usr/lib/python3.8/site-packages/transmission_rpc/client.py", line 748, in get_session
    self._request("session-get", timeout=timeout)
    │    │                               └ None
    │    └ <function Client._request at 0x7f9ffeb39280>
    └ <transmission_rpc.client.Client object at 0x7f9ff8cbb610>
  File "/usr/lib/python3.8/site-packages/transmission_rpc/client.py", line 226, in _request
    raise ValueError from error

ValueError
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/transmission_rpc/client.py", line 221, in _request
    data: dict = json.loads(http_data)
  File "/usr/lib/python3.8/json/__init__.py", line 357, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.8/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.8/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/flexget/task.py", line 547, in __run_plugin
    result = method(*args, **kwargs)
  File "/usr/lib/python3.8/site-packages/flexget/event.py", line 20, in __call__
    return self.func(*args, **kwargs)
  File "/usr/lib/python3.8/site-packages/flexget/plugins/clients/transmission.py", line 189, in on_task_input
    self.client = self.create_rpc_client(config)
  File "/usr/lib/python3.8/site-packages/flexget/plugins/clients/transmission.py", line 70, in create_rpc_client
    cli = transmissionrpc.Client(
  File "/usr/lib/python3.8/site-packages/transmission_rpc/client.py", line 112, in __init__
    self.get_session()
  File "/usr/lib/python3.8/site-packages/transmission_rpc/client.py", line 748, in get_session
    self._request("session-get", timeout=timeout)
  File "/usr/lib/python3.8/site-packages/transmission_rpc/client.py", line 226, in _request
    raise ValueError from error
ValueError

```
</details>

### Additional information:

- FlexGet version: 3.1.98
- Python version:
- Installation method:
- Using daemon (yes/no):
- OS and version:
- Link to crash log:

<!---
In config and debug/crash logs, remember to redact any personal or sensitive information such as passwords, API keys, private URLs and so on.

Please verify that the following data is present before submitting your issue:

- Link to a paste service or paste above the relevant config (preferably full config, including templates if present). Please make sure the paste does not expire, if possible.
- Link to a paste service or paste above debug-level logs of the relevant task/s (use `flexget -L debug execute --tasks <Task_name>`).
- FlexGet version (use `flexget -V` to get it).
- Full Python version, for example `2.7.11` (use `python -V` to get it). 
- Installation method (pip, git install, etc).
- Whether or not you're running FlexGet as a daemon.
- OS and version.
- Attach crash log if one was generated, in addition to the debug-level log. It can be found in the directory with your config file.
--->



Discussion:
Just wanted to point out here, if it was not clear, the plugin **from_transmission** no longer works at all with the new transmission-rpc library :)

It seems like it is not passing login credentials to transmission?
> <h5>421: Misdirected Request</h5><p>Transmission received your request, but the hostname was unrecognized.</p><p>To fix this, choose one of the following options:<ul><li>Enable password authentication, then any hostname is allowed.</li><li>Add the hostname you want to use to the whitelist in settings.</li></ul></p><p>If you're editing settings.json, see the 'rpc-host-whitelist' and 'rpc-host-whitelist-enabled' entries.</p><p>This requirement has been added to help prevent <a href="https://en.wikipedia.org/wiki/DNS_rebinding">DNS Rebinding</a> attacks.</p>
Just to be clear, you have one of these enabled in transmission? It looks like it's sending the username and password, and I thought other people had reported from_transmission working on the new library...
After some investigation, it appears my config was overwritten by some automated update, my apologies.

Please feel free to close if you feel the unhandled error is not a priority. Thanks again @gazpachoking 
Catching that error and giving a better message would definitely be good. Just wanted to make sure the problem wasn't deeper first.

Resolving patch:
diff --git a/flexget/plugins/clients/transmission.py b/flexget/plugins/clients/transmission.py
--- a/flexget/plugins/clients/transmission.py
+++ b/flexget/plugins/clients/transmission.py
@@ -86,6 +86,8 @@ def create_rpc_client(self, config):
             raise plugin.PluginError("Cannot connect to transmission: Connection timed out.")
         except requests.exceptions.ConnectionError as e:
             raise plugin.PluginError("Error connecting to transmission: %s" % e.args[0].reason)
+        except ValueError as e:
+            raise plugin.PluginError("Error connecting to transmission")
         return cli
 
     def torrent_info(self, torrent, config):


Test patch: