# Path: pytube/request.py
# def _execute_request(
#     url,
#     method=None,
#     headers=None,
#     data=None,
#     timeout=socket._GLOBAL_DEFAULT_TIMEOUT
# ):
# def get(url, extra_headers=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
# def post(url, extra_headers=None, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
# def seq_stream(
#     url,
#     timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
#     max_retries=0
# ):
# def stream(
#     url,
#     timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
#     max_retries=0
# ):
# def filesize(url):
# def seq_filesize(url):
# def head(url):
# 
# Path: pytube/helpers.py
# def safe_filename(s: str, max_length: int = 255) -> str:
#     """Sanitize a string making it safe to use as a filename.
# 
#     This function was based off the limitations outlined here:
#     https://en.wikipedia.org/wiki/Filename.
# 
#     :param str s:
#         A string to make safe for use as a file name.
#     :param int max_length:
#         The maximum filename character length.
#     :rtype: str
#     :returns:
#         A sanitized string.
#     """
#     # Characters in range 0-31 (0x00-0x1F) are not allowed in ntfs filenames.
#     ntfs_characters = [chr(i) for i in range(0, 31)]
#     characters = [
#         r'"',
#         r"\#",
#         r"\$",
#         r"\%",
#         r"'",
#         r"\*",
#         r"\,",
#         r"\.",
#         r"\/",
#         r"\:",
#         r'"',
#         r"\;",
#         r"\<",
#         r"\>",
#         r"\?",
#         r"\\",
#         r"\^",
#         r"\|",
#         r"\~",
#         r"\\\\",
#     ]
#     pattern = "|".join(ntfs_characters + characters)
#     regex = re.compile(pattern, re.UNICODE)
#     filename = regex.sub("", s)
#     return filename[:max_length].rsplit(" ", 0)[0]
# 
# def target_directory(output_path: Optional[str] = None) -> str:
#     """
#     Function for determining target directory of a download.
#     Returns an absolute path (if relative one given) or the current
#     path (if none given). Makes directory if it does not exist.
# 
#     :type output_path: str
#         :rtype: str
#     :returns:
#         An absolute directory path as a string.
#     """
#     if output_path:
#         if not os.path.isabs(output_path):
#             output_path = os.path.join(os.getcwd(), output_path)
#     else:
#         output_path = os.getcwd()
#     os.makedirs(output_path, exist_ok=True)
#     return output_path


import math
import os
import time
import xml.etree.ElementTree as ElementTree
from html import unescape
from typing import Dict, Optional
from pytube import request
from pytube.helpers import safe_filename, target_directory
    """Container for caption tracks."""

    def __init__(self, caption_track: Dict):
        """Construct a :class:`Caption <Caption>`.

        :param dict caption_track:
            Caption track data extracted from ``watch_html``.
        """
        self.url = caption_track.get("baseUrl")

        # Certain videos have runs instead of simpleText
        #  this handles that edge case
        name_dict = caption_track['name']
        if 'simpleText' in name_dict:
            self.name = name_dict['simpleText']
        else:
            for el in name_dict['runs']:
                if 'text' in el:
                    self.name = el['text']

        # Use "vssId" instead of "languageCode", fix issue #779
        self.code = caption_track["vssId"]
        # Remove preceding '.' for backwards compatibility, e.g.:
        # English -> vssId: .en, languageCode: en
        # English (auto-generated) -> vssId: a.en, languageCode: en
        self.code = self.code.strip('.')

    @property
    def xml_captions(self) -> str:
        """Download the xml caption tracks."""

# Path: pytube/request.py
# def _execute_request(
#     url,
#     method=None,
#     headers=None,
#     data=None,
#     timeout=socket._GLOBAL_DEFAULT_TIMEOUT
# ):
# def get(url, extra_headers=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
# def post(url, extra_headers=None, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
# def seq_stream(
#     url,
#     timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
#     max_retries=0
# ):
# def stream(
#     url,
#     timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
#     max_retries=0
# ):
# def filesize(url):
# def seq_filesize(url):
# def head(url):
# 
# Path: pytube/helpers.py
# def safe_filename(s: str, max_length: int = 255) -> str:
#     """Sanitize a string making it safe to use as a filename.
# 
#     This function was based off the limitations outlined here:
#     https://en.wikipedia.org/wiki/Filename.
# 
#     :param str s:
#         A string to make safe for use as a file name.
#     :param int max_length:
#         The maximum filename character length.
#     :rtype: str
#     :returns:
#         A sanitized string.
#     """
#     # Characters in range 0-31 (0x00-0x1F) are not allowed in ntfs filenames.
#     ntfs_characters = [chr(i) for i in range(0, 31)]
#     characters = [
#         r'"',
#         r"\#",
#         r"\$",
#         r"\%",
#         r"'",
#         r"\*",
#         r"\,",
#         r"\.",
#         r"\/",
#         r"\:",
#         r'"',
#         r"\;",
#         r"\<",
#         r"\>",
#         r"\?",
#         r"\\",
#         r"\^",
#         r"\|",
#         r"\~",
#         r"\\\\",
#     ]
#     pattern = "|".join(ntfs_characters + characters)
#     regex = re.compile(pattern, re.UNICODE)
#     filename = regex.sub("", s)
#     return filename[:max_length].rsplit(" ", 0)[0]
# 
# def target_directory(output_path: Optional[str] = None) -> str:
#     """
#     Function for determining target directory of a download.
#     Returns an absolute path (if relative one given) or the current
#     path (if none given). Makes directory if it does not exist.
# 
#     :type output_path: str
#         :rtype: str
#     :returns:
#         An absolute directory path as a string.
#     """
#     if output_path:
#         if not os.path.isabs(output_path):
#             output_path = os.path.join(os.getcwd(), output_path)
#     else:
#         output_path = os.getcwd()
#     os.makedirs(output_path, exist_ok=True)
#     return output_path


# Path: pytube/captions.py
import math
import os
import time
import xml.etree.ElementTree as ElementTree
from html import unescape
from typing import Dict, Optional
from pytube import request
from pytube.helpers import safe_filename, target_directory

    """Container for caption tracks."""

    def __init__(self, caption_track: Dict):
        """Construct a :class:`Caption <Caption>`.

        :param dict caption_track:
            Caption track data extracted from ``watch_html``.
        """
        self.url = caption_track.get("baseUrl")

        # Certain videos have runs instead of simpleText
        #  this handles that edge case
        name_dict = caption_track['name']
        if 'simpleText' in name_dict:
            self.name = name_dict['simpleText']
        else:
            for el in name_dict['runs']:
                if 'text' in el:
                    self.name = el['text']

        # Use "vssId" instead of "languageCode", fix issue #779
        self.code = caption_track["vssId"]
        # Remove preceding '.' for backwards compatibility, e.g.:
        # English -> vssId: .en, languageCode: en
        # English (auto-generated) -> vssId: a.en, languageCode: en
        self.code = self.code.strip('.')

    @property
    def xml_captions(self) -> str:
        """Download the xml caption tracks."""

        return request.get(self.url)