# Path: pytube/exceptions.py
# class RegexMatchError(ExtractError):
#     """Regex pattern did not return any matches."""
# 
#     def __init__(self, caller: str, pattern: Union[str, Pattern]):
#         """
#         :param str caller:
#             Calling function
#         :param str pattern:
#             Pattern that failed to match
#         """
#         super().__init__(f"{caller}: could not find match for {pattern}")
#         self.caller = caller
#         self.pattern = pattern
# 
# class MaxRetriesExceeded(PytubeError):
#     """Maximum number of retries exceeded."""
# 
# Path: pytube/helpers.py
# def regex_search(pattern: str, string: str, group: int) -> str:
#     """Shortcut method to search a string for a given pattern.
# 
#     :param str pattern:
#         A regular expression pattern.
#     :param str string:
#         A target string to search.
#     :param int group:
#         Index of group to return.
#     :rtype:
#         str or tuple
#     :returns:
#         Substring pattern matches.
#     """
#     regex = re.compile(pattern)
#     results = regex.search(string)
#     if not results:
#         raise RegexMatchError(caller="regex_search", pattern=pattern)
# 
#     logger.debug("matched regex search: %s", pattern)
# 
#     return results.group(group)


import http.client
import json
import logging
import re
import socket
from functools import lru_cache
from urllib import parse
from urllib.error import URLError
from urllib.request import Request, urlopen
from pytube.exceptions import RegexMatchError, MaxRetriesExceeded
from pytube.helpers import regex_search
    :param str url: The URL to get the size of
    :returns: int: size in bytes of remote file
    """
    total_filesize = 0
    # YouTube expects a request sequence number as part of the parameters.
    split_url = parse.urlsplit(url)
    base_url = '%s://%s/%s?' % (split_url.scheme, split_url.netloc, split_url.path)
    querys = dict(parse.parse_qsl(split_url.query))

    # The 0th sequential request provides the file headers, which tell us
    #  information about how the file is segmented.
    querys['sq'] = 0
    url = base_url + parse.urlencode(querys)
    response = _execute_request(
        url, method="GET"
    )

    response_value = response.read()
    # The file header must be added to the total filesize
    total_filesize += len(response_value)

    # We can then parse the header to find the number of segments
    segment_count = 0
    stream_info = response_value.split(b'\r\n')
    segment_regex = b'Segment-Count: (\\d+)'
    for line in stream_info:
        # One of the lines should contain the segment count, but we don't know
        #  which, so we need to iterate through the lines to find it
        try:
            segment_count = int(regex_search(segment_regex, line, 1))

# Path: pytube/exceptions.py
# class RegexMatchError(ExtractError):
#     """Regex pattern did not return any matches."""
# 
#     def __init__(self, caller: str, pattern: Union[str, Pattern]):
#         """
#         :param str caller:
#             Calling function
#         :param str pattern:
#             Pattern that failed to match
#         """
#         super().__init__(f"{caller}: could not find match for {pattern}")
#         self.caller = caller
#         self.pattern = pattern
# 
# class MaxRetriesExceeded(PytubeError):
#     """Maximum number of retries exceeded."""
# 
# Path: pytube/helpers.py
# def regex_search(pattern: str, string: str, group: int) -> str:
#     """Shortcut method to search a string for a given pattern.
# 
#     :param str pattern:
#         A regular expression pattern.
#     :param str string:
#         A target string to search.
#     :param int group:
#         Index of group to return.
#     :rtype:
#         str or tuple
#     :returns:
#         Substring pattern matches.
#     """
#     regex = re.compile(pattern)
#     results = regex.search(string)
#     if not results:
#         raise RegexMatchError(caller="regex_search", pattern=pattern)
# 
#     logger.debug("matched regex search: %s", pattern)
# 
#     return results.group(group)


# Path: pytube/request.py
import http.client
import json
import logging
import re
import socket
from functools import lru_cache
from urllib import parse
from urllib.error import URLError
from urllib.request import Request, urlopen
from pytube.exceptions import RegexMatchError, MaxRetriesExceeded
from pytube.helpers import regex_search

    :param str url: The URL to get the size of
    :returns: int: size in bytes of remote file
    """
    total_filesize = 0
    # YouTube expects a request sequence number as part of the parameters.
    split_url = parse.urlsplit(url)
    base_url = '%s://%s/%s?' % (split_url.scheme, split_url.netloc, split_url.path)
    querys = dict(parse.parse_qsl(split_url.query))

    # The 0th sequential request provides the file headers, which tell us
    #  information about how the file is segmented.
    querys['sq'] = 0
    url = base_url + parse.urlencode(querys)
    response = _execute_request(
        url, method="GET"
    )

    response_value = response.read()
    # The file header must be added to the total filesize
    total_filesize += len(response_value)

    # We can then parse the header to find the number of segments
    segment_count = 0
    stream_info = response_value.split(b'\r\n')
    segment_regex = b'Segment-Count: (\\d+)'
    for line in stream_info:
        # One of the lines should contain the segment count, but we don't know
        #  which, so we need to iterate through the lines to find it
        try:
            segment_count = int(regex_search(segment_regex, line, 1))

        except RegexMatchError: