Repository: yt-dlp/yt-dlp

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.  


Discussion:
1. Provide example URL of the video webpage, not manifest.
2. Confirm whether passing logged in cookies resolves your issue (show output with `-vUF`)
3. Are you willing to provide account details?
1. https://7plus.com.au/seven-news-gold-coast?episode-id=7ANG21-192
2. Passing cookies does not present the higher resolution.
3. Accounts are free, but can provide account if needed.
It seems the authorization header is the only thing needed to make it work. Now just need to figure out how to generate it

```
➤ yt-dlp -F http://7plus.com.au/seven-news-gold-coast?episode-id=7ANG21-192  --add-header "authorization: Bearer A_LONG_PRIVATE_TOKEN"
[7plus] 7ANG21-192: Downloading JSON metadata
[7plus] 7ANG21-192: Downloading m3u8 information
[7plus] 7ANG21-192: Downloading MPD manifest
[7plus] 7ANG21-192: Downloading MPD manifest
[7plus] 7ANG21-192: Downloading JSON metadata
[info] Available formats for 7ANG21-192:
ID                                          EXT RESOLUTION |   TBR PROTO  | VCODEC        VBR ACODEC     ABR  ASR    MORE INFO
------------------------------------------- --- ---------- - ----- ------ - ----------- ----- --------- ---- ------- --------------------------
hls-audio-0-en__Main_                       mp4 audio only |       m3u8_n |                   unknown                [en], en (Main)
dash-6dff20c3-383a-422a-88f3-fe299561bab0-0 m4a audio only |  127k dash   |                   mp4a.40.2 127k 48000Hz [en], DASH audio, m4a_dash
dash-6dff20c3-383a-422a-88f3-fe299561bab0-1 m4a audio only |  127k dash   |                   mp4a.40.2 127k 48000Hz [en], DASH audio, m4a_dash
dash-a3f3a68a-eec8-4517-8912-c20151542d20-0 mp4 320x180    |  234k dash   | avc1.4d000c  234k                        DASH video, mp4_dash
dash-a3f3a68a-eec8-4517-8912-c20151542d20-1 mp4 320x180    |  234k dash   | avc1.4d000c  234k                        DASH video, mp4_dash
hls-397                                     mp4 320x180    |  397k m3u8_n | avc1.4d000c  397k
dash-6c6ca7a6-c380-432d-a532-9a5dca7dbb9b-0 mp4 320x180    |  439k dash   | avc1.4d000d  439k                        DASH video, mp4_dash
dash-6c6ca7a6-c380-432d-a532-9a5dca7dbb9b-1 mp4 320x180    |  439k dash   | avc1.4d000d  439k                        DASH video, mp4_dash
hls-622                                     mp4 320x180    |  622k m3u8_n | avc1.4d000d  622k
dash-fe0e5200-c20e-4ace-84da-51a8acc5dcb7-0 mp4 640x360    |  836k dash   | avc1.4d001e  836k                        DASH video, mp4_dash
dash-fe0e5200-c20e-4ace-84da-51a8acc5dcb7-1 mp4 640x360    |  836k dash   | avc1.4d001e  836k                        DASH video, mp4_dash
hls-1059                                    mp4 640x360    | 1059k m3u8_n | avc1.4d001e 1059k
dash-700e2f17-961e-42ac-ad52-a5df26ae8a9e-0 mp4 896x504    | 1589k dash   | avc1.64001f 1589k                        DASH video, mp4_dash
dash-700e2f17-961e-42ac-ad52-a5df26ae8a9e-1 mp4 896x504    | 1589k dash   | avc1.64001f 1589k                        DASH video, mp4_dash
hls-1887                                    mp4 896x504    | 1887k m3u8_n | avc1.64001f 1887k
dash-e9616205-af97-4a9f-a729-1506fc63af32-0 mp4 1280x720   | 3015k dash   | avc1.64001f 3015k                        DASH video, mp4_dash
dash-e9616205-af97-4a9f-a729-1506fc63af32-1 mp4 1280x720   | 3015k dash   | avc1.64001f 3015k                        DASH video, mp4_dash
hls-3456                                    mp4 1280x720   | 3456k m3u8_n | avc1.64001f 3456k
```

Resolving patch:
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 @@ class SevenPlusIE(BrightcoveNewIE):
         '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 @@ def _real_extract(self, url):
                     '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(


Test patch: