Repository: yt-dlp/yt-dlp
File: yt_dlp/extractor/sonyliv.py (Python)

Code before:
            'episode_number': 1,
            'release_year': 2016,
        },
        'params': {
            'skip_download': True,
        },
    }, {
        'url': 'https://www.sonyliv.com/movies/tahalka-1000050121?watch=true',
        'only_matching': True,
    }, {
        'url': 'https://www.sonyliv.com/clip/jigarbaaz-1000098925',
        'only_matching': True,
    }, {
        'url': 'https://www.sonyliv.com/trailer/sandwiched-forever-1000100286?watch=true',
        'only_matching': True,
    }, {
        'url': 'https://www.sonyliv.com/sports/india-tour-of-australia-2020-21-1700000286/cricket-hls-day-3-1st-test-aus-vs-ind-19-dec-2020-1000100959?watch=true',
        'only_matching': True,
    }, {
        'url': 'https://www.sonyliv.com/music-videos/yeh-un-dinon-ki-baat-hai-1000018779',
        'only_matching': True,
    }]
    _GEO_COUNTRIES = ['IN']
    _AUTH_TOKEN = None
    _HEADERS = {}
    _LOGIN_HINT = 'Use "--username <mobile_number>" to login using otp or "--username token" and "--password <user_token>" to login using auth token.'
    _NETRC_MACHINE = 'sonyliv'

    def _get_device_id(self):
        e = int(time.time() * 1000)
        t = list('xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx')
        for i, c in enumerate(t):
            n = int((e + 16 * random.random()) % 16) | 0
            e = math.floor(e / 16)
            if c == 'x':
                t[i] = str(n)
            elif c == 'y':
                t[i] = '{:x}'.format(3 & n | 8)
        return ''.join(t) + '-' + str(int(time.time() * 1000))

    def _login(self, username, password):
        if len(username) == 10 and username.isdigit() and self._AUTH_TOKEN is None:
            self.report_login()
            data = '{"mobileNumber":"%s","channelPartnerID":"MSMIND","country":"IN","timestamp":"%s","otpSize":6,"loginType":"REGISTERORSIGNIN","isMobileMandatory":true}' % (username, datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%MZ"))
            otp_request_json = self._download_json(
                'https://apiv2.sonyliv.com/AGL/1.6/A/ENG/WEB/IN/HR/CREATEOTP-V2',
                None, note='Sending OTP', data=data.encode(), headers=self._HEADERS)
            if otp_request_json['resultCode'] == 'KO':
                raise ExtractorError(otp_request_json['message'], expected=True)
            otp_code = self._get_tfa_info('OTP')
            data = '{"channelPartnerID":"MSMIND","mobileNumber":"%s","country":"IN","otp":"%s","dmaId":"IN","ageConfirmation":true,"timestamp":"%s","isMobileMandatory":true}' % (username, otp_code, datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%MZ"))

Review comment (security):
```suggestion
    _LOGIN_HINT = 'Use "--username <mobile_number>" to login using OTP or "--username token --password <user_token>" to login using auth token'
```

Code after:
            'episode_number': 1,
            'release_year': 2016,
        },
        'params': {
            'skip_download': True,
        },
    }, {
        'url': 'https://www.sonyliv.com/movies/tahalka-1000050121?watch=true',
        'only_matching': True,
    }, {
        'url': 'https://www.sonyliv.com/clip/jigarbaaz-1000098925',
        'only_matching': True,
    }, {
        'url': 'https://www.sonyliv.com/trailer/sandwiched-forever-1000100286?watch=true',
        'only_matching': True,
    }, {
        'url': 'https://www.sonyliv.com/sports/india-tour-of-australia-2020-21-1700000286/cricket-hls-day-3-1st-test-aus-vs-ind-19-dec-2020-1000100959?watch=true',
        'only_matching': True,
    }, {
        'url': 'https://www.sonyliv.com/music-videos/yeh-un-dinon-ki-baat-hai-1000018779',
        'only_matching': True,
    }]
    _GEO_COUNTRIES = ['IN']
    _HEADERS = {}
    _LOGIN_HINT = 'Use "--username <mobile_number>" to login using OTP or "--username token --password <auth_token>" to login using auth token.'
    _NETRC_MACHINE = 'sonyliv'

    def _get_device_id(self):
        e = int(time.time() * 1000)
        t = list('xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx')
        for i, c in enumerate(t):
            n = int((e + 16 * random.random()) % 16) | 0
            e = math.floor(e / 16)
            if c == 'x':
                t[i] = str(n)
            elif c == 'y':
                t[i] = '{:x}'.format(3 & n | 8)
        return ''.join(t) + '-' + str(int(time.time() * 1000))

    def _login(self, username, password):
        if username.lower() == 'token' and len(password) > 1198:
            return password
        elif len(username) != 10 or not username.isdigit():
            raise ExtractorError(f'Invalid username/password; {self._LOGIN_HINT}')

        self.report_login()
        data = '''{"mobileNumber":"%s","channelPartnerID":"MSMIND","country":"IN","timestamp":"%s",
        "otpSize":6,"loginType":"REGISTERORSIGNIN","isMobileMandatory":true}
         ''' % (username, datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%MZ"))
        otp_request_json = self._download_json(
            'https://apiv2.sonyliv.com/AGL/1.6/A/ENG/WEB/IN/HR/CREATEOTP-V2',