docs: async def prepare_decrypter(client, cdn_client, cdn_redirect):
          """
          Prepares a new CDN decrypter.
  
          :param client: a TelegramClient connected to the main servers.
          :param cdn_client: a new client connected to the CDN.
          :param cdn_redirect: the redirect file object that caused this call.
          :return: (CdnDecrypter, first chunk file data)
          """
          cdn_aes = AESModeCTR(
              key=cdn_redirect.encryption_key,
              # 12 first bytes of the IV..4 bytes of the offset (0, big endian)
              iv=cdn_redirect.encryption_iv[:12] + bytes(4)
          )
  
          # We assume that cdn_redirect.cdn_file_hashes are ordered by offset,
          # and that there will be enough of these to retrieve the whole file.
          decrypter = CdnDecrypter(
              cdn_client, cdn_redirect.file_token,
              cdn_aes, cdn_redirect.cdn_file_hashes
          )
  
          cdn_file = await cdn_client(GetCdnFileRequest(
              file_token=cdn_redirect.file_token,
              offset=cdn_redirect.cdn_file_hashes[0].offset,
              limit=cdn_redirect.cdn_file_hashes[0].limit
          ))
          if isinstance(cdn_file, CdnFileReuploadNeeded):
              # We need to use the original client here
              await client(ReuploadCdnFileRequest(
                  file_token=cdn_redirect.file_token,
                  request_token=cdn_file.request_token
              ))
  
              # We want to always return a valid upload.CdnFile
              cdn_file = decrypter.get_file()
          else:
              cdn_file.bytes = decrypter.cdn_aes.encrypt(cdn_file.bytes)
              cdn_hash = decrypter.cdn_file_hashes.pop(0)
              decrypter.check(cdn_file.bytes, cdn_hash)
  
          return decrypter, cdn_file