async def upload_media(
        self,
        source: str | bytes,
        wait_for_completion: bool = False,
        status_check_interval: float | None = None,
        media_type: str | None = None,
        media_category: str | None = None,
        is_long_video: bool = False
    ) -> str:
        """
        Uploads media to twitter.

        Parameters
        ----------
        source : :class:`str` | :class:`bytes`
            The source of the media to be uploaded.
            It can be either a file path or bytes of the media content.
        wait_for_completion : :class:`bool`, default=False
            Whether to wait for the completion of the media upload process.
        status_check_interval : :class:`float`, default=1.0
            The interval (in seconds) to check the status of the
            media upload process.
        media_type : :class:`str`, default=None
            The MIME type of the media.
            If not specified, it will be guessed from the source.
        media_category : :class:`str`, default=None
            The media category.
        is_long_video : :class:`bool`, default=False
            If this is True, videos longer than 2:20 can be uploaded.
            (Twitter Premium only)

        Returns
        -------
        :class:`str`
            The media ID of the uploaded media.

        Examples
        --------
        Videos, images and gifs can be uploaded.

        >>> media_id_1 = await client.upload_media(
        ...     'media1.jpg',
        ... )

        >>> media_id_2 = await client.upload_media(
        ...     'media2.mp4',
        ...     wait_for_completion=True
        ... )

        >>> media_id_3 = await client.upload_media(
        ...     'media3.gif',
        ...     wait_for_completion=True,
        ...     media_category='tweet_gif'  # media_category must be specified
        ... )
        """
        if not isinstance(wait_for_completion, bool):
            raise TypeError(
                'wait_for_completion must be bool,'
                f' not {wait_for_completion.__class__.__name__}'
            )

        if isinstance(source, str):
            # If the source is a path
            with open(source, 'rb') as file:
                binary = file.read()
        elif isinstance(source, bytes):
            # If the source is bytes
            binary = source

        if media_type is None:
            # Guess mimetype if not specified
            media_type = filetype.guess(binary).mime

        if wait_for_completion:
            if media_type == 'image/gif':
                if media_category is None:
                    raise TwitterException(
                        "`media_category` must be specified to check the "
                        "upload status of gif images ('dm_gif' or 'tweet_gif')"
                    )
            elif media_type.startswith('image'):
                # Checking the upload status of an image is impossible.
                wait_for_completion = False

        total_bytes = len(binary)

        # ============ INIT =============
        response, _ = await self.v11.upload_media_init(
            media_type, total_bytes, media_category, is_long_video
        )
        media_id = response['media_id']
        # =========== APPEND ============
        segment_index = 0
        bytes_sent = 0
        MAX_SEGMENT_SIZE = 8 * 1024 * 1024  # The maximum segment size is 8 MB
        append_tasks = []
        chunk_streams: list[io.BytesIO] = []

        while bytes_sent < total_bytes:
            chunk = binary[bytes_sent:bytes_sent + MAX_SEGMENT_SIZE]
            chunk_stream = io.BytesIO(chunk)
            coro = self.v11.upload_media_append(is_long_video, media_id, segment_index, chunk_stream)
            append_tasks.append(asyncio.create_task(coro))
            chunk_streams.append(chunk_stream)

            segment_index += 1
            bytes_sent += len(chunk)

        append_gather = asyncio.gather(*append_tasks)
        await append_gather

        # Close chunk streams
        for chunk_stream in chunk_streams:
            chunk_stream.close()

        # ========== FINALIZE ===========
        await self.v11.upload_media_finelize(is_long_video, media_id)
        # ===============================

        if wait_for_completion:
            while True:
                state = await self.check_media_status(media_id, is_long_video)
                processing_info = state['processing_info']
                if 'error' in processing_info:
                    raise InvalidMedia(processing_info['error'].get('message'))
                if processing_info['state'] == 'succeeded':
                    break
                await asyncio.sleep(status_check_interval or processing_info['check_after_secs'])

        return media_id

        Uploads media to twitter.

        Parameters
        ----------
        source : :class:`str` | :class:`bytes`
            The source of the media to be uploaded.
            It can be either a file path or bytes of the media content.
        wait_for_completion : :class:`bool`, default=False
            Whether to wait for the completion of the media upload process.
        status_check_interval : :class:`float`, default=1.0
            The interval (in seconds) to check the status of the
            media upload process.
        media_type : :class:`str`, default=None
            The MIME type of the media.
            If not specified, it will be guessed from the source.
        media_category : :class:`str`, default=None
            The media category.
        is_long_video : :class:`bool`, default=False
            If this is True, videos longer than 2:20 can be uploaded.
            (Twitter Premium only)

        Returns
        -------
        :class:`str`
            The media ID of the uploaded media.

        Examples
        --------
        Videos, images and gifs can be uploaded.

        >>> media_id_1 = await client.upload_media(
        ...     'media1.jpg',
        ... )

        >>> media_id_2 = await client.upload_media(
        ...     'media2.mp4',
        ...     wait_for_completion=True
        ... )

        >>> media_id_3 = await client.upload_media(
        ...     'media3.gif',
        ...     wait_for_completion=True,
        ...     media_category='tweet_gif'  # media_category must be specified
        ... )
        
twikit/client/client.py