We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Vaughnlive changed IP's to break Streamlink
This will be a very brief bug report... As of tonight the head vaughnlive.py references IPs which were disconnected by vaughn to thwart streamlinking. I've observed vaughn serving video now from "66.90.93.44","66.90.93.35" and have personally gotten it to work overwriting the IP's in rtmp_server_map with those two alternating. I would submit the commit but I think some more testing is needed as I only use streamlink with one occasional stream and don't know how far those IPs will get more frequent SL users.

 #1187 contains lengthy discussion on the history of the war vaughn has waged against streamlink, this is probably not the last time the IPs will change.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/streamlink/plugins/vaughnlive.py`
Content:
```
1 import random
2 import re
3 import itertools
4 import ssl
5 import websocket
6 
7 from streamlink.plugin import Plugin
8 from streamlink.plugin.api import useragents, http
9 from streamlink.stream import RTMPStream
10 
11 _url_re = re.compile(r"""
12     http(s)?://(\w+\.)?
13     (?P<domain>vaughnlive|breakers|instagib|vapers|pearltime).tv
14     (/embed/video)?
15     /(?P<channel>[^/&?]+)
16 """, re.VERBOSE)
17 
18 
19 class VLWebSocket(websocket.WebSocket):
20     def __init__(self, **_):
21         self.session = _.pop("session")
22         self.logger = self.session.logger.new_module("plugins.vaughnlive.websocket")
23         sslopt = _.pop("sslopt", {})
24         sslopt["cert_reqs"] = ssl.CERT_NONE
25         super(VLWebSocket, self).__init__(sslopt=sslopt, **_)
26 
27     def send(self, payload, opcode=websocket.ABNF.OPCODE_TEXT):
28         self.logger.debug("Sending message: {0}", payload)
29         return super(VLWebSocket, self).send(payload + "\n\x00", opcode)
30 
31     def recv(self):
32         d = super(VLWebSocket, self).recv().replace("\n", "").replace("\x00", "")
33         return d.split(" ", 1)
34 
35 
36 class VaughnLive(Plugin):
37     servers = ["wss://sapi-ws-{0}x{1:02}.vaughnlive.tv".format(x, y) for x, y in itertools.product(range(1, 3),
38                                                                                                    range(1, 6))]
39     origin = "https://vaughnlive.tv"
40     rtmp_server_map = {
41         "594140c69edad": "66.90.93.42",
42         "585c4cab1bef1": "66.90.93.34",
43         "5940d648b3929": "66.90.93.42",
44         "5941854b39bc4": "198.255.0.10"
45     }
46     name_remap = {"#vl": "live", "#btv": "btv", "#pt": "pt", "#igb": "instagib", "#vtv": "vtv"}
47     domain_map = {"vaughnlive": "#vl", "breakers": "#btv", "instagib": "#igb", "vapers": "#vtv", "pearltime": "#pt"}
48 
49     @classmethod
50     def can_handle_url(cls, url):
51         return _url_re.match(url)
52 
53     def api_url(self):
54         return random.choice(self.servers)
55 
56     def parse_ack(self, action, message):
57         if action.endswith("3"):
58             channel, _, viewers, token, server, choked, is_live, chls, trns, ingest = message.split(";")
59             is_live = is_live == "1"
60             viewers = int(viewers)
61             self.logger.debug("Viewers: {0}, isLive={1}", viewers, is_live)
62             domain, channel = channel.split("-", 1)
63             return is_live, server, domain, channel, token, ingest
64         else:
65             self.logger.error("Unhandled action format: {0}", action)
66 
67     def _get_info(self, stream_name):
68         server = self.api_url()
69         self.logger.debug("Connecting to API: {0}", server)
70         ws = websocket.create_connection(server,
71                                          header=["User-Agent: {0}".format(useragents.CHROME)],
72                                          origin=self.origin,
73                                          class_=VLWebSocket,
74                                          session=self.session)
75         ws.send("MVN LOAD3 {0}".format(stream_name))
76         action, message = ws.recv()
77         return self.parse_ack(action, message)
78 
79     def _get_rtmp_streams(self, server, domain, channel, token):
80         rtmp_server = self.rtmp_server_map.get(server, server)
81 
82         url = "rtmp://{0}/live?{1}".format(rtmp_server, token)
83 
84         yield "live", RTMPStream(self.session, params={
85             "rtmp": url,
86             "pageUrl": self.url,
87             "playpath": "{0}_{1}".format(self.name_remap.get(domain, "live"), channel),
88             "live": True
89         })
90 
91     def _get_streams(self):
92         m = _url_re.match(self.url)
93         if m:
94             stream_name = "{0}-{1}".format(self.domain_map[(m.group("domain").lower())],
95                                            m.group("channel"))
96 
97             is_live, server, domain, channel, token, ingest = self._get_info(stream_name)
98 
99             if not is_live:
100                 self.logger.info("Stream is currently off air")
101             else:
102                 for s in self._get_rtmp_streams(server, domain, channel, token):
103                     yield s
104 
105 
106 __plugin__ = VaughnLive
107
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/streamlink/plugins/vaughnlive.py b/src/streamlink/plugins/vaughnlive.py
--- a/src/streamlink/plugins/vaughnlive.py
+++ b/src/streamlink/plugins/vaughnlive.py
@@ -38,10 +38,10 @@
                                                                                                    range(1, 6))]
     origin = "https://vaughnlive.tv"
     rtmp_server_map = {
-        "594140c69edad": "66.90.93.42",
-        "585c4cab1bef1": "66.90.93.34",
-        "5940d648b3929": "66.90.93.42",
-        "5941854b39bc4": "198.255.0.10"
+        "594140c69edad": "192.240.105.171:1935",
+        "585c4cab1bef1": "192.240.105.171:1935",
+        "5940d648b3929": "192.240.105.171:1935",
+        "5941854b39bc4": "192.240.105.171:1935"
     }
     name_remap = {"#vl": "live", "#btv": "btv", "#pt": "pt", "#igb": "instagib", "#vtv": "vtv"}
     domain_map = {"vaughnlive": "#vl", "breakers": "#btv", "instagib": "#igb", "vapers": "#vtv", "pearltime": "#pt"}
@@ -99,6 +99,7 @@
             if not is_live:
                 self.logger.info("Stream is currently off air")
             else:
+                self.logger.info("Stream powered by VaughnSoft - remember to support them.")
                 for s in self._get_rtmp_streams(server, domain, channel, token):
                     yield s

{"golden_diff": "diff --git a/src/streamlink/plugins/vaughnlive.py b/src/streamlink/plugins/vaughnlive.py\n--- a/src/streamlink/plugins/vaughnlive.py\n+++ b/src/streamlink/plugins/vaughnlive.py\n@@ -38,10 +38,10 @@\n                                                                                                    range(1, 6))]\n     origin = \"https://vaughnlive.tv\"\n     rtmp_server_map = {\n-        \"594140c69edad\": \"66.90.93.42\",\n-        \"585c4cab1bef1\": \"66.90.93.34\",\n-        \"5940d648b3929\": \"66.90.93.42\",\n-        \"5941854b39bc4\": \"198.255.0.10\"\n+        \"594140c69edad\": \"192.240.105.171:1935\",\n+        \"585c4cab1bef1\": \"192.240.105.171:1935\",\n+        \"5940d648b3929\": \"192.240.105.171:1935\",\n+        \"5941854b39bc4\": \"192.240.105.171:1935\"\n     }\n     name_remap = {\"#vl\": \"live\", \"#btv\": \"btv\", \"#pt\": \"pt\", \"#igb\": \"instagib\", \"#vtv\": \"vtv\"}\n     domain_map = {\"vaughnlive\": \"#vl\", \"breakers\": \"#btv\", \"instagib\": \"#igb\", \"vapers\": \"#vtv\", \"pearltime\": \"#pt\"}\n@@ -99,6 +99,7 @@\n             if not is_live:\n                 self.logger.info(\"Stream is currently off air\")\n             else:\n+                self.logger.info(\"Stream powered by VaughnSoft - remember to support them.\")\n                 for s in self._get_rtmp_streams(server, domain, channel, token):\n                     yield s\n", "issue": "Vaughnlive changed IP's to break Streamlink\nThis will be a very brief bug report... As of tonight the head vaughnlive.py references IPs which were disconnected by vaughn to thwart streamlinking. I've observed vaughn serving video now from \"66.90.93.44\",\"66.90.93.35\" and have personally gotten it to work overwriting the IP's in rtmp_server_map with those two alternating. I would submit the commit but I think some more testing is needed as I only use streamlink with one occasional stream and don't know how far those IPs will get more frequent SL users.\r\n\r\n #1187 contains lengthy discussion on the history of the war vaughn has waged against streamlink, this is probably not the last time the IPs will change.\n", "before_files": [{"content": "import random\nimport re\nimport itertools\nimport ssl\nimport websocket\n\nfrom streamlink.plugin import Plugin\nfrom streamlink.plugin.api import useragents, http\nfrom streamlink.stream import RTMPStream\n\n_url_re = re.compile(r\"\"\"\n    http(s)?://(\\w+\\.)?\n    (?P<domain>vaughnlive|breakers|instagib|vapers|pearltime).tv\n    (/embed/video)?\n    /(?P<channel>[^/&?]+)\n\"\"\", re.VERBOSE)\n\n\nclass VLWebSocket(websocket.WebSocket):\n    def __init__(self, **_):\n        self.session = _.pop(\"session\")\n        self.logger = self.session.logger.new_module(\"plugins.vaughnlive.websocket\")\n        sslopt = _.pop(\"sslopt\", {})\n        sslopt[\"cert_reqs\"] = ssl.CERT_NONE\n        super(VLWebSocket, self).__init__(sslopt=sslopt, **_)\n\n    def send(self, payload, opcode=websocket.ABNF.OPCODE_TEXT):\n        self.logger.debug(\"Sending message: {0}\", payload)\n        return super(VLWebSocket, self).send(payload + \"\\n\\x00\", opcode)\n\n    def recv(self):\n        d = super(VLWebSocket, self).recv().replace(\"\\n\", \"\").replace(\"\\x00\", \"\")\n        return d.split(\" \", 1)\n\n\nclass VaughnLive(Plugin):\n    servers = [\"wss://sapi-ws-{0}x{1:02}.vaughnlive.tv\".format(x, y) for x, y in itertools.product(range(1, 3),\n                                                                                                   range(1, 6))]\n    origin = \"https://vaughnlive.tv\"\n    rtmp_server_map = {\n        \"594140c69edad\": \"66.90.93.42\",\n        \"585c4cab1bef1\": \"66.90.93.34\",\n        \"5940d648b3929\": \"66.90.93.42\",\n        \"5941854b39bc4\": \"198.255.0.10\"\n    }\n    name_remap = {\"#vl\": \"live\", \"#btv\": \"btv\", \"#pt\": \"pt\", \"#igb\": \"instagib\", \"#vtv\": \"vtv\"}\n    domain_map = {\"vaughnlive\": \"#vl\", \"breakers\": \"#btv\", \"instagib\": \"#igb\", \"vapers\": \"#vtv\", \"pearltime\": \"#pt\"}\n\n    @classmethod\n    def can_handle_url(cls, url):\n        return _url_re.match(url)\n\n    def api_url(self):\n        return random.choice(self.servers)\n\n    def parse_ack(self, action, message):\n        if action.endswith(\"3\"):\n            channel, _, viewers, token, server, choked, is_live, chls, trns, ingest = message.split(\";\")\n            is_live = is_live == \"1\"\n            viewers = int(viewers)\n            self.logger.debug(\"Viewers: {0}, isLive={1}\", viewers, is_live)\n            domain, channel = channel.split(\"-\", 1)\n            return is_live, server, domain, channel, token, ingest\n        else:\n            self.logger.error(\"Unhandled action format: {0}\", action)\n\n    def _get_info(self, stream_name):\n        server = self.api_url()\n        self.logger.debug(\"Connecting to API: {0}\", server)\n        ws = websocket.create_connection(server,\n                                         header=[\"User-Agent: {0}\".format(useragents.CHROME)],\n                                         origin=self.origin,\n                                         class_=VLWebSocket,\n                                         session=self.session)\n        ws.send(\"MVN LOAD3 {0}\".format(stream_name))\n        action, message = ws.recv()\n        return self.parse_ack(action, message)\n\n    def _get_rtmp_streams(self, server, domain, channel, token):\n        rtmp_server = self.rtmp_server_map.get(server, server)\n\n        url = \"rtmp://{0}/live?{1}\".format(rtmp_server, token)\n\n        yield \"live\", RTMPStream(self.session, params={\n            \"rtmp\": url,\n            \"pageUrl\": self.url,\n            \"playpath\": \"{0}_{1}\".format(self.name_remap.get(domain, \"live\"), channel),\n            \"live\": True\n        })\n\n    def _get_streams(self):\n        m = _url_re.match(self.url)\n        if m:\n            stream_name = \"{0}-{1}\".format(self.domain_map[(m.group(\"domain\").lower())],\n                                           m.group(\"channel\"))\n\n            is_live, server, domain, channel, token, ingest = self._get_info(stream_name)\n\n            if not is_live:\n                self.logger.info(\"Stream is currently off air\")\n            else:\n                for s in self._get_rtmp_streams(server, domain, channel, token):\n                    yield s\n\n\n__plugin__ = VaughnLive\n", "path": "src/streamlink/plugins/vaughnlive.py"}], "after_files": [{"content": "import random\nimport re\nimport itertools\nimport ssl\nimport websocket\n\nfrom streamlink.plugin import Plugin\nfrom streamlink.plugin.api import useragents, http\nfrom streamlink.stream import RTMPStream\n\n_url_re = re.compile(r\"\"\"\n    http(s)?://(\\w+\\.)?\n    (?P<domain>vaughnlive|breakers|instagib|vapers|pearltime).tv\n    (/embed/video)?\n    /(?P<channel>[^/&?]+)\n\"\"\", re.VERBOSE)\n\n\nclass VLWebSocket(websocket.WebSocket):\n    def __init__(self, **_):\n        self.session = _.pop(\"session\")\n        self.logger = self.session.logger.new_module(\"plugins.vaughnlive.websocket\")\n        sslopt = _.pop(\"sslopt\", {})\n        sslopt[\"cert_reqs\"] = ssl.CERT_NONE\n        super(VLWebSocket, self).__init__(sslopt=sslopt, **_)\n\n    def send(self, payload, opcode=websocket.ABNF.OPCODE_TEXT):\n        self.logger.debug(\"Sending message: {0}\", payload)\n        return super(VLWebSocket, self).send(payload + \"\\n\\x00\", opcode)\n\n    def recv(self):\n        d = super(VLWebSocket, self).recv().replace(\"\\n\", \"\").replace(\"\\x00\", \"\")\n        return d.split(\" \", 1)\n\n\nclass VaughnLive(Plugin):\n    servers = [\"wss://sapi-ws-{0}x{1:02}.vaughnlive.tv\".format(x, y) for x, y in itertools.product(range(1, 3),\n                                                                                                   range(1, 6))]\n    origin = \"https://vaughnlive.tv\"\n    rtmp_server_map = {\n        \"594140c69edad\": \"192.240.105.171:1935\",\n        \"585c4cab1bef1\": \"192.240.105.171:1935\",\n        \"5940d648b3929\": \"192.240.105.171:1935\",\n        \"5941854b39bc4\": \"192.240.105.171:1935\"\n    }\n    name_remap = {\"#vl\": \"live\", \"#btv\": \"btv\", \"#pt\": \"pt\", \"#igb\": \"instagib\", \"#vtv\": \"vtv\"}\n    domain_map = {\"vaughnlive\": \"#vl\", \"breakers\": \"#btv\", \"instagib\": \"#igb\", \"vapers\": \"#vtv\", \"pearltime\": \"#pt\"}\n\n    @classmethod\n    def can_handle_url(cls, url):\n        return _url_re.match(url)\n\n    def api_url(self):\n        return random.choice(self.servers)\n\n    def parse_ack(self, action, message):\n        if action.endswith(\"3\"):\n            channel, _, viewers, token, server, choked, is_live, chls, trns, ingest = message.split(\";\")\n            is_live = is_live == \"1\"\n            viewers = int(viewers)\n            self.logger.debug(\"Viewers: {0}, isLive={1}\", viewers, is_live)\n            domain, channel = channel.split(\"-\", 1)\n            return is_live, server, domain, channel, token, ingest\n        else:\n            self.logger.error(\"Unhandled action format: {0}\", action)\n\n    def _get_info(self, stream_name):\n        server = self.api_url()\n        self.logger.debug(\"Connecting to API: {0}\", server)\n        ws = websocket.create_connection(server,\n                                         header=[\"User-Agent: {0}\".format(useragents.CHROME)],\n                                         origin=self.origin,\n                                         class_=VLWebSocket,\n                                         session=self.session)\n        ws.send(\"MVN LOAD3 {0}\".format(stream_name))\n        action, message = ws.recv()\n        return self.parse_ack(action, message)\n\n    def _get_rtmp_streams(self, server, domain, channel, token):\n        rtmp_server = self.rtmp_server_map.get(server, server)\n\n        url = \"rtmp://{0}/live?{1}\".format(rtmp_server, token)\n\n        yield \"live\", RTMPStream(self.session, params={\n            \"rtmp\": url,\n            \"pageUrl\": self.url,\n            \"playpath\": \"{0}_{1}\".format(self.name_remap.get(domain, \"live\"), channel),\n            \"live\": True\n        })\n\n    def _get_streams(self):\n        m = _url_re.match(self.url)\n        if m:\n            stream_name = \"{0}-{1}\".format(self.domain_map[(m.group(\"domain\").lower())],\n                                           m.group(\"channel\"))\n\n            is_live, server, domain, channel, token, ingest = self._get_info(stream_name)\n\n            if not is_live:\n                self.logger.info(\"Stream is currently off air\")\n            else:\n                self.logger.info(\"Stream powered by VaughnSoft - remember to support them.\")\n                for s in self._get_rtmp_streams(server, domain, channel, token):\n                    yield s\n\n\n__plugin__ = VaughnLive\n", "path": "src/streamlink/plugins/vaughnlive.py"}]}