We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Site Request] 7plus add login/pass to access 720p resolution
<!--

######################################################################
  WARNING!
  IGNORING THE FOLLOWING TEMPLATE WILL RESULT IN ISSUE CLOSED AS INCOMPLETE
######################################################################

-->


## Checklist

<!--
Carefully read and work through this check list in order to prevent the most common mistakes and misuse of yt-dlp:
- First of, make sure you are using the latest version of yt-dlp. Run `yt-dlp --version` and ensure your version is 2021.09.25. If it's not, see https://github.com/yt-dlp/yt-dlp on how to update. Issues with outdated version will be REJECTED.
- Search the bugtracker for similar site feature requests: https://github.com/yt-dlp/yt-dlp. DO NOT post duplicates.
- Finally, put x into all relevant boxes like this [x] (Dont forget to delete the empty space)
-->

- [x] I'm reporting a site feature request
- [x] I've verified that I'm running yt-dlp version **2021.09.25**
- [x] I've searched the bugtracker for similar site feature requests including closed ones


## Description

<!--
Provide an explanation of your site feature request in an arbitrary form. Please make sure the description is worded well enough to be understood, see https://github.com/ytdl-org/youtube-dl#is-the-description-of-the-issue-itself-sufficient. Provide any additional information, suggested solution and as much context and examples as possible.
-->

7Plus has 720p resolution available behind a login/pass.  Current site functionality only pulls 540p.  

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `yt_dlp/extractor/sevenplus.py`
Content:
```
1 # coding: utf-8
2 from __future__ import unicode_literals
3 
4 import re
5 
6 from .brightcove import BrightcoveNewIE
7 from ..compat import (
8     compat_HTTPError,
9     compat_str,
10 )
11 from ..utils import (
12     ExtractorError,
13     try_get,
14     update_url_query,
15 )
16 
17 
18 class SevenPlusIE(BrightcoveNewIE):
19     IE_NAME = '7plus'
20     _VALID_URL = r'https?://(?:www\.)?7plus\.com\.au/(?P<path>[^?]+\?.*?\bepisode-id=(?P<id>[^&#]+))'
21     _TESTS = [{
22         'url': 'https://7plus.com.au/MTYS?episode-id=MTYS7-003',
23         'info_dict': {
24             'id': 'MTYS7-003',
25             'ext': 'mp4',
26             'title': 'S7 E3 - Wind Surf',
27             'description': 'md5:29c6a69f21accda7601278f81b46483d',
28             'uploader_id': '5303576322001',
29             'upload_date': '20171201',
30             'timestamp': 1512106377,
31             'series': 'Mighty Ships',
32             'season_number': 7,
33             'episode_number': 3,
34             'episode': 'Wind Surf',
35         },
36         'params': {
37             'format': 'bestvideo',
38             'skip_download': True,
39         }
40     }, {
41         'url': 'https://7plus.com.au/UUUU?episode-id=AUMS43-001',
42         'only_matching': True,
43     }]
44 
45     def _real_extract(self, url):
46         path, episode_id = self._match_valid_url(url).groups()
47 
48         try:
49             media = self._download_json(
50                 'https://videoservice.swm.digital/playback', episode_id, query={
51                     'appId': '7plus',
52                     'deviceType': 'web',
53                     'platformType': 'web',
54                     'accountId': 5303576322001,
55                     'referenceId': 'ref:' + episode_id,
56                     'deliveryId': 'csai',
57                     'videoType': 'vod',
58                 })['media']
59         except ExtractorError as e:
60             if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:
61                 raise ExtractorError(self._parse_json(
62                     e.cause.read().decode(), episode_id)[0]['error_code'], expected=True)
63             raise
64 
65         for source in media.get('sources', {}):
66             src = source.get('src')
67             if not src:
68                 continue
69             source['src'] = update_url_query(src, {'rule': ''})
70 
71         info = self._parse_brightcove_metadata(media, episode_id)
72 
73         content = self._download_json(
74             'https://component-cdn.swm.digital/content/' + path,
75             episode_id, headers={
76                 'market-id': 4,
77             }, fatal=False) or {}
78         for item in content.get('items', {}):
79             if item.get('componentData', {}).get('componentType') == 'infoPanel':
80                 for src_key, dst_key in [('title', 'title'), ('shortSynopsis', 'description')]:
81                     value = item.get(src_key)
82                     if value:
83                         info[dst_key] = value
84                 info['series'] = try_get(
85                     item, lambda x: x['seriesLogo']['name'], compat_str)
86                 mobj = re.search(r'^S(\d+)\s+E(\d+)\s+-\s+(.+)$', info['title'])
87                 if mobj:
88                     info.update({
89                         'season_number': int(mobj.group(1)),
90                         'episode_number': int(mobj.group(2)),
91                         'episode': mobj.group(3),
92                     })
93 
94         return info
95
```
--- 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/yt_dlp/extractor/sevenplus.py b/yt_dlp/extractor/sevenplus.py
--- a/yt_dlp/extractor/sevenplus.py
+++ b/yt_dlp/extractor/sevenplus.py
@@ -1,6 +1,7 @@
 # coding: utf-8
 from __future__ import unicode_literals
 
+import json
 import re
 
 from .brightcove import BrightcoveNewIE
@@ -42,9 +43,52 @@
         'only_matching': True,
     }]
 
+    def _real_initialize(self):
+        self.token = None
+
+        cookies = self._get_cookies('https://7plus.com.au')
+        api_key = next((x for x in cookies if x.startswith('glt_')), '')[4:]
+        if not api_key:  # Cookies are signed out, skip login
+            return
+
+        login_resp = self._download_json(
+            'https://login.7plus.com.au/accounts.getJWT', None, 'Logging in', fatal=False,
+            query={
+                'APIKey': api_key,
+                'sdk': 'js_latest',
+                'login_token': cookies[f'glt_{api_key}'].value,
+                'authMode': 'cookie',
+                'pageURL': 'https://7plus.com.au/',
+                'sdkBuild': '12471',
+                'format': 'json',
+            }) or {}
+
+        if 'errorMessage' in login_resp:
+            self.report_warning(f'Unable to login: 7plus said: {login_resp["errorMessage"]}')
+            return
+        id_token = login_resp.get('id_token')
+        if not id_token:
+            self.report_warning('Unable to login: Could not extract id token')
+            return
+
+        token_resp = self._download_json(
+            'https://7plus.com.au/auth/token', None, 'Getting auth token', fatal=False,
+            headers={'Content-Type': 'application/json'}, data=json.dumps({
+                'idToken': id_token,
+                'platformId': 'web',
+                'regSource': '7plus',
+            }).encode('utf-8')) or {}
+        self.token = token_resp.get('token')
+        if not self.token:
+            self.report_warning('Unable to log in: Could not extract auth token')
+
     def _real_extract(self, url):
         path, episode_id = self._match_valid_url(url).groups()
 
+        headers = {}
+        if self.token:
+            headers['Authorization'] = f'Bearer {self.token}'
+
         try:
             media = self._download_json(
                 'https://videoservice.swm.digital/playback', episode_id, query={
@@ -55,7 +99,7 @@
                     'referenceId': 'ref:' + episode_id,
                     'deliveryId': 'csai',
                     'videoType': 'vod',
-                })['media']
+                }, headers=headers)['media']
         except ExtractorError as e:
             if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:
                 raise ExtractorError(self._parse_json(

{"golden_diff": "diff --git a/yt_dlp/extractor/sevenplus.py b/yt_dlp/extractor/sevenplus.py\n--- a/yt_dlp/extractor/sevenplus.py\n+++ b/yt_dlp/extractor/sevenplus.py\n@@ -1,6 +1,7 @@\n # coding: utf-8\n from __future__ import unicode_literals\n \n+import json\n import re\n \n from .brightcove import BrightcoveNewIE\n@@ -42,9 +43,52 @@\n         'only_matching': True,\n     }]\n \n+    def _real_initialize(self):\n+        self.token = None\n+\n+        cookies = self._get_cookies('https://7plus.com.au')\n+        api_key = next((x for x in cookies if x.startswith('glt_')), '')[4:]\n+        if not api_key:  # Cookies are signed out, skip login\n+            return\n+\n+        login_resp = self._download_json(\n+            'https://login.7plus.com.au/accounts.getJWT', None, 'Logging in', fatal=False,\n+            query={\n+                'APIKey': api_key,\n+                'sdk': 'js_latest',\n+                'login_token': cookies[f'glt_{api_key}'].value,\n+                'authMode': 'cookie',\n+                'pageURL': 'https://7plus.com.au/',\n+                'sdkBuild': '12471',\n+                'format': 'json',\n+            }) or {}\n+\n+        if 'errorMessage' in login_resp:\n+            self.report_warning(f'Unable to login: 7plus said: {login_resp[\"errorMessage\"]}')\n+            return\n+        id_token = login_resp.get('id_token')\n+        if not id_token:\n+            self.report_warning('Unable to login: Could not extract id token')\n+            return\n+\n+        token_resp = self._download_json(\n+            'https://7plus.com.au/auth/token', None, 'Getting auth token', fatal=False,\n+            headers={'Content-Type': 'application/json'}, data=json.dumps({\n+                'idToken': id_token,\n+                'platformId': 'web',\n+                'regSource': '7plus',\n+            }).encode('utf-8')) or {}\n+        self.token = token_resp.get('token')\n+        if not self.token:\n+            self.report_warning('Unable to log in: Could not extract auth token')\n+\n     def _real_extract(self, url):\n         path, episode_id = self._match_valid_url(url).groups()\n \n+        headers = {}\n+        if self.token:\n+            headers['Authorization'] = f'Bearer {self.token}'\n+\n         try:\n             media = self._download_json(\n                 'https://videoservice.swm.digital/playback', episode_id, query={\n@@ -55,7 +99,7 @@\n                     'referenceId': 'ref:' + episode_id,\n                     'deliveryId': 'csai',\n                     'videoType': 'vod',\n-                })['media']\n+                }, headers=headers)['media']\n         except ExtractorError as e:\n             if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:\n                 raise ExtractorError(self._parse_json(\n", "issue": "[Site Request] 7plus add login/pass to access 720p resolution\n<!--\r\n\r\n######################################################################\r\n  WARNING!\r\n  IGNORING THE FOLLOWING TEMPLATE WILL RESULT IN ISSUE CLOSED AS INCOMPLETE\r\n######################################################################\r\n\r\n-->\r\n\r\n\r\n## Checklist\r\n\r\n<!--\r\nCarefully read and work through this check list in order to prevent the most common mistakes and misuse of yt-dlp:\r\n- First of, make sure you are using the latest version of yt-dlp. Run `yt-dlp --version` and ensure your version is 2021.09.25. If it's not, see https://github.com/yt-dlp/yt-dlp on how to update. Issues with outdated version will be REJECTED.\r\n- Search the bugtracker for similar site feature requests: https://github.com/yt-dlp/yt-dlp. DO NOT post duplicates.\r\n- Finally, put x into all relevant boxes like this [x] (Dont forget to delete the empty space)\r\n-->\r\n\r\n- [x] I'm reporting a site feature request\r\n- [x] I've verified that I'm running yt-dlp version **2021.09.25**\r\n- [x] I've searched the bugtracker for similar site feature requests including closed ones\r\n\r\n\r\n## Description\r\n\r\n<!--\r\nProvide an explanation of your site feature request in an arbitrary form. Please make sure the description is worded well enough to be understood, see https://github.com/ytdl-org/youtube-dl#is-the-description-of-the-issue-itself-sufficient. Provide any additional information, suggested solution and as much context and examples as possible.\r\n-->\r\n\r\n7Plus has 720p resolution available behind a login/pass.  Current site functionality only pulls 540p.  \n", "before_files": [{"content": "# coding: utf-8\nfrom __future__ import unicode_literals\n\nimport re\n\nfrom .brightcove import BrightcoveNewIE\nfrom ..compat import (\n    compat_HTTPError,\n    compat_str,\n)\nfrom ..utils import (\n    ExtractorError,\n    try_get,\n    update_url_query,\n)\n\n\nclass SevenPlusIE(BrightcoveNewIE):\n    IE_NAME = '7plus'\n    _VALID_URL = r'https?://(?:www\\.)?7plus\\.com\\.au/(?P<path>[^?]+\\?.*?\\bepisode-id=(?P<id>[^&#]+))'\n    _TESTS = [{\n        'url': 'https://7plus.com.au/MTYS?episode-id=MTYS7-003',\n        'info_dict': {\n            'id': 'MTYS7-003',\n            'ext': 'mp4',\n            'title': 'S7 E3 - Wind Surf',\n            'description': 'md5:29c6a69f21accda7601278f81b46483d',\n            'uploader_id': '5303576322001',\n            'upload_date': '20171201',\n            'timestamp': 1512106377,\n            'series': 'Mighty Ships',\n            'season_number': 7,\n            'episode_number': 3,\n            'episode': 'Wind Surf',\n        },\n        'params': {\n            'format': 'bestvideo',\n            'skip_download': True,\n        }\n    }, {\n        'url': 'https://7plus.com.au/UUUU?episode-id=AUMS43-001',\n        'only_matching': True,\n    }]\n\n    def _real_extract(self, url):\n        path, episode_id = self._match_valid_url(url).groups()\n\n        try:\n            media = self._download_json(\n                'https://videoservice.swm.digital/playback', episode_id, query={\n                    'appId': '7plus',\n                    'deviceType': 'web',\n                    'platformType': 'web',\n                    'accountId': 5303576322001,\n                    'referenceId': 'ref:' + episode_id,\n                    'deliveryId': 'csai',\n                    'videoType': 'vod',\n                })['media']\n        except ExtractorError as e:\n            if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:\n                raise ExtractorError(self._parse_json(\n                    e.cause.read().decode(), episode_id)[0]['error_code'], expected=True)\n            raise\n\n        for source in media.get('sources', {}):\n            src = source.get('src')\n            if not src:\n                continue\n            source['src'] = update_url_query(src, {'rule': ''})\n\n        info = self._parse_brightcove_metadata(media, episode_id)\n\n        content = self._download_json(\n            'https://component-cdn.swm.digital/content/' + path,\n            episode_id, headers={\n                'market-id': 4,\n            }, fatal=False) or {}\n        for item in content.get('items', {}):\n            if item.get('componentData', {}).get('componentType') == 'infoPanel':\n                for src_key, dst_key in [('title', 'title'), ('shortSynopsis', 'description')]:\n                    value = item.get(src_key)\n                    if value:\n                        info[dst_key] = value\n                info['series'] = try_get(\n                    item, lambda x: x['seriesLogo']['name'], compat_str)\n                mobj = re.search(r'^S(\\d+)\\s+E(\\d+)\\s+-\\s+(.+)$', info['title'])\n                if mobj:\n                    info.update({\n                        'season_number': int(mobj.group(1)),\n                        'episode_number': int(mobj.group(2)),\n                        'episode': mobj.group(3),\n                    })\n\n        return info\n", "path": "yt_dlp/extractor/sevenplus.py"}], "after_files": [{"content": "# coding: utf-8\nfrom __future__ import unicode_literals\n\nimport json\nimport re\n\nfrom .brightcove import BrightcoveNewIE\nfrom ..compat import (\n    compat_HTTPError,\n    compat_str,\n)\nfrom ..utils import (\n    ExtractorError,\n    try_get,\n    update_url_query,\n)\n\n\nclass SevenPlusIE(BrightcoveNewIE):\n    IE_NAME = '7plus'\n    _VALID_URL = r'https?://(?:www\\.)?7plus\\.com\\.au/(?P<path>[^?]+\\?.*?\\bepisode-id=(?P<id>[^&#]+))'\n    _TESTS = [{\n        'url': 'https://7plus.com.au/MTYS?episode-id=MTYS7-003',\n        'info_dict': {\n            'id': 'MTYS7-003',\n            'ext': 'mp4',\n            'title': 'S7 E3 - Wind Surf',\n            'description': 'md5:29c6a69f21accda7601278f81b46483d',\n            'uploader_id': '5303576322001',\n            'upload_date': '20171201',\n            'timestamp': 1512106377,\n            'series': 'Mighty Ships',\n            'season_number': 7,\n            'episode_number': 3,\n            'episode': 'Wind Surf',\n        },\n        'params': {\n            'format': 'bestvideo',\n            'skip_download': True,\n        }\n    }, {\n        'url': 'https://7plus.com.au/UUUU?episode-id=AUMS43-001',\n        'only_matching': True,\n    }]\n\n    def _real_initialize(self):\n        self.token = None\n\n        cookies = self._get_cookies('https://7plus.com.au')\n        api_key = next((x for x in cookies if x.startswith('glt_')), '')[4:]\n        if not api_key:  # Cookies are signed out, skip login\n            return\n\n        login_resp = self._download_json(\n            'https://login.7plus.com.au/accounts.getJWT', None, 'Logging in', fatal=False,\n            query={\n                'APIKey': api_key,\n                'sdk': 'js_latest',\n                'login_token': cookies[f'glt_{api_key}'].value,\n                'authMode': 'cookie',\n                'pageURL': 'https://7plus.com.au/',\n                'sdkBuild': '12471',\n                'format': 'json',\n            }) or {}\n\n        if 'errorMessage' in login_resp:\n            self.report_warning(f'Unable to login: 7plus said: {login_resp[\"errorMessage\"]}')\n            return\n        id_token = login_resp.get('id_token')\n        if not id_token:\n            self.report_warning('Unable to login: Could not extract id token')\n            return\n\n        token_resp = self._download_json(\n            'https://7plus.com.au/auth/token', None, 'Getting auth token', fatal=False,\n            headers={'Content-Type': 'application/json'}, data=json.dumps({\n                'idToken': id_token,\n                'platformId': 'web',\n                'regSource': '7plus',\n            }).encode('utf-8')) or {}\n        self.token = token_resp.get('token')\n        if not self.token:\n            self.report_warning('Unable to log in: Could not extract auth token')\n\n    def _real_extract(self, url):\n        path, episode_id = self._match_valid_url(url).groups()\n\n        headers = {}\n        if self.token:\n            headers['Authorization'] = f'Bearer {self.token}'\n\n        try:\n            media = self._download_json(\n                'https://videoservice.swm.digital/playback', episode_id, query={\n                    'appId': '7plus',\n                    'deviceType': 'web',\n                    'platformType': 'web',\n                    'accountId': 5303576322001,\n                    'referenceId': 'ref:' + episode_id,\n                    'deliveryId': 'csai',\n                    'videoType': 'vod',\n                }, headers=headers)['media']\n        except ExtractorError as e:\n            if isinstance(e.cause, compat_HTTPError) and e.cause.code == 403:\n                raise ExtractorError(self._parse_json(\n                    e.cause.read().decode(), episode_id)[0]['error_code'], expected=True)\n            raise\n\n        for source in media.get('sources', {}):\n            src = source.get('src')\n            if not src:\n                continue\n            source['src'] = update_url_query(src, {'rule': ''})\n\n        info = self._parse_brightcove_metadata(media, episode_id)\n\n        content = self._download_json(\n            'https://component-cdn.swm.digital/content/' + path,\n            episode_id, headers={\n                'market-id': 4,\n            }, fatal=False) or {}\n        for item in content.get('items', {}):\n            if item.get('componentData', {}).get('componentType') == 'infoPanel':\n                for src_key, dst_key in [('title', 'title'), ('shortSynopsis', 'description')]:\n                    value = item.get(src_key)\n                    if value:\n                        info[dst_key] = value\n                info['series'] = try_get(\n                    item, lambda x: x['seriesLogo']['name'], compat_str)\n                mobj = re.search(r'^S(\\d+)\\s+E(\\d+)\\s+-\\s+(.+)$', info['title'])\n                if mobj:\n                    info.update({\n                        'season_number': int(mobj.group(1)),\n                        'episode_number': int(mobj.group(2)),\n                        'episode': mobj.group(3),\n                    })\n\n        return info\n", "path": "yt_dlp/extractor/sevenplus.py"}]}