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

Code before:
    @staticmethod
    def _decrypt_url_params(audio_info):
        def char_code_at(s: str, n: int) -> int:
            return ord(s[n]) if n < len(s) else 0

        def decrypt(e: str, t: list) -> str:
            r = list(range(256))
            a = 0
            s = ''

            for o in range(256):
                a = (a + r[o] + int_or_none(char_code_at(e, o % len(e)))) % 256
                r[o], r[a] = r[a], r[o]

            a, o = 0, 0
            for u in range(len(t)):
                o = (o + 1) % 256
                a = (a + r[o]) % 256
                r[o], r[a] = r[a], r[o]
                s += chr(t[u] ^ r[(r[o] + r[a]) % 256])

            return s

        def decrypt2(key: str, key2: list) -> str:
            n = []
            for r in range(len(key)):
                a = ord('a')
                if ord('a') <= ord(key[r]) <= ord('z'):
                    a = ord(key[r]) - 97
                else:
                    a = ord(key[r]) - 48 + 26

                for i in range(36):
                    if key2[i] == a:
                        a = i
                        break

                if a > 25:
                    n.append(chr(a - 26 + 48))
                else:
                    n.append(chr(a + 97))

            return ''.join(n)

        def decrypt3(s: str) -> list:
            t = 0
            n = 0
            r = 0
            s_len = len(s)
            i = []
            o = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,

Review comment (suggestion):
Can't we just iterate over the chars?
```suggestion
            for char in key:
```

Code after:

    @staticmethod
    def _decrypt_url_params(encrypted_params):
        params = VideaIE.rc4(
            base64.b64decode(encrypted_params), 'xkt3a41psizxrh9l').split('-')
        # sign, token, timestamp
        return params[1], params[2], params[3]

    def _real_extract(self, url):
        scheme = 'https' if url.startswith('https') else 'http'

        audio_id = self._match_id(url)
        audio_info = self._download_json(
            f'{scheme}://m.ximalaya.com/tracks/{audio_id}.json', audio_id,
            'Downloading info json', 'Unable to download info file')

        formats = []
        # NOTE: VIP-restricted audio
        if audio_info.get('is_paid'):
            ts = int(time.time())
            vip_info = self._download_json(
                f'{scheme}://mpay.ximalaya.com/mobile/track/pay/{audio_id}/{ts}',
                audio_id, 'Downloading VIP info json', 'Unable to download VIP info file',
                query={'device': 'pc', 'isBackend': 'true', '_': ts})
            filename = self._decrypt_filename(vip_info['fileId'], vip_info['seed'])
            sign, token, timestamp = self._decrypt_url_params(vip_info['ep'])
            vip_url = update_url_query(
                f'{vip_info["domain"]}/download/{vip_info["apiVersion"]}{filename}', {
                    'sign': sign,
                    'token': token,
                    'timestamp': timestamp,
                    'buy_key': vip_info['buyKey'],
                    'duration': vip_info['duration'],
                })
            fmt = {
                'format_id': 'vip',
                'url': vip_url,
                'vcodec': 'none',
            }
            if '_preview_' in vip_url:
                self.report_warning(
                    f'This tracks requires a VIP account. Using a sample instead. {self._login_hint()}')
                fmt.update({
                    'format_note': 'Sample',
                    'preference': -10,
                    **traverse_obj(vip_info, {
                        'filesize': ('sampleLength', {int_or_none}),
                        'duration': ('sampleDuration', {int_or_none}),
                    }),
                })
            else: