Repository: streamlink/streamlink

Issue:
plugins.ustreamtv: Proxy and Socks do not work
Hi,
I noticed Proxy and Socks no longer work on Streamlink.
The channel I want to watch blocks all countries except the United States and I use US IP to see it.

```
streamlink --http-proxy xxx.xxx.xxx.xxx:xxxx https://www.ustream.tv/embed/23259921 best
```

And it doesn't work

```
[cli][info] Found matching plugin ustreamtv for URL https://www.ustream.tv/embed/23259921
[plugin.ustreamtv][error] This content is not available in your area
```

Meanwhile, I use the Proxy SwitchyOmega extension and the same IP, I can watch it on the browser.
Please help me, Thanks.


Discussion:
Try setting `--https-proxy` too, to the same thing. For legacy reasons they are different. It might be worth defaulting the `https-proxy` to the same as `http-proxy`, but for now you gotta do it yourself.
I tried it all but it didn't work.
You're right, WebSocket connections are not proxied - we'll have to update that.  

Resolving patch:
diff --git a/src/streamlink/plugins/ustreamtv.py b/src/streamlink/plugins/ustreamtv.py
--- a/src/streamlink/plugins/ustreamtv.py
+++ b/src/streamlink/plugins/ustreamtv.py
@@ -11,7 +11,7 @@
 from threading import Thread, Event
 from time import sleep
 
-from streamlink.compat import range, urljoin, urlunparse
+from streamlink.compat import range, urljoin, urlunparse, urlparse, unquote_plus
 from streamlink.exceptions import PluginError, StreamError
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
 from streamlink.plugin.api import useragents, validate
@@ -57,6 +57,7 @@ def __init__(self, media_id, application, **options):
         self._app_version = options.pop("app_version", self.APP_VERSION)
         self._cluster = options.pop("cluster", "live")
         self._password = options.pop("password")
+        self._proxy_url = options.pop("proxy")
         self._ws = None
 
     @property
@@ -79,11 +80,32 @@ def cluster(self, cluster):
         self._cluster = cluster
         self.reconnect()
 
+    @staticmethod
+    def parse_proxy_url(purl):
+        proxy_options = {}
+        if purl:
+            p = urlparse(purl)
+            proxy_options['proxy_type'] = p.scheme
+            proxy_options['http_proxy_host'] = p.hostname
+            if p.port:
+                proxy_options['http_proxy_port'] = p.port
+            if p.username:
+                proxy_options['http_proxy_auth'] = (unquote_plus(p.username), unquote_plus(p.password or ""))
+        return proxy_options
+
     def connect(self):
-        log.debug("Connecting to {0}".format(self.host))
+        proxy_options = self.parse_proxy_url(self._proxy_url)
+        if proxy_options.get('http_proxy_host'):
+            log.debug("Connecting to {0} via proxy ({1}://{2}:{3})".format(self.host,
+                                                                           proxy_options.get('proxy_type') or "http",
+                                                                           proxy_options.get('http_proxy_host'),
+                                                                           proxy_options.get('http_proxy_port') or 80))
+        else:
+            log.debug("Connecting to {0}".format(self.host))
         self._ws = websocket.create_connection(self.host,
                                                header=["User-Agent: {0}".format(useragents.CHROME)],
-                                               origin="https://www.ustream.tv")
+                                               origin="https://www.ustream.tv",
+                                               **proxy_options)
 
         args = dict(type="viewer",
                     appId=self._app_id,
@@ -304,6 +326,7 @@ def stopper(self, f):
             def _stopper(*args, **kwargs):
                 self.stop()
                 return f(*args, **kwargs)
+
             return _stopper
 
         def handle_module_info(self, args):
@@ -411,8 +434,8 @@ def handle_module_info(self, args):
                     raise PluginError("Stream format is not supported: {0}".format(
                         ", ".join(data["streamFormats"].keys())))
             elif "stream" in arg and arg["stream"]["contentAvailable"] is False:
-                    log.error("This stream is currently offline")
-                    raise ModuleInfoNoStreams
+                log.error("This stream is currently offline")
+                raise ModuleInfoNoStreams
 
         return res
 
@@ -432,7 +455,11 @@ def handle_reject(self, api, args):
     def _get_streams(self):
         media_id, application = self._get_media_app()
         if media_id:
-            api = UHSClient(media_id, application, referrer=self.url, cluster="live", password=self.get_option("password"))
+            api = UHSClient(media_id, application,
+                            referrer=self.url,
+                            cluster="live",
+                            password=self.get_option("password"),
+                            proxy=self.session.get_option("http-proxy"))
             log.debug("Connecting to UStream API: media_id={0}, application={1}, referrer={2}, cluster={3}",
                       media_id, application, self.url, "live")
             api.connect()
diff --git a/src/streamlink_cli/argparser.py b/src/streamlink_cli/argparser.py
--- a/src/streamlink_cli/argparser.py
+++ b/src/streamlink_cli/argparser.py
@@ -1070,8 +1070,8 @@ def build_parser():
         "--http-proxy",
         metavar="HTTP_PROXY",
         help="""
-        A HTTP proxy to use for all HTTP requests, by default this proxy
-        will be used for all HTTPS requests too.
+        A HTTP proxy to use for all HTTP requests, including WebSocket connections. 
+        By default this proxy will be used for all HTTPS requests too.
 
         Example: "http://hostname:port/"
         """


Test patch: