
    iQ                         d Z ddlmZmZmZmZ ddl ddlmZ ddl	Z	ddl
mZ ddlmZ ddlZddlZddlmZ dd	lmZmZ dd
lmZ  G d de      Zy)z
    podgen.episode
    ~~~~~~~~~~~~~~

    :copyright: 2013, Lars Kiesow <lkiesow@uos.de> and 2016, Thorben Dahl
        <thorben@sjostrom.no>

    :license: FreeBSD and LGPL, see license.* for more details.
    )absolute_importdivisionprint_functionunicode_literals)*)	iteritemsN)etree)datetime)NotSupportedByItunesWarning)formatRFC2822listToHumanreadableStr)string_typesc                      e Zd ZdZd Zd Zed        Zej                  d        Zed        Z	e	j                  d        Z	ed        Z
e
j                  d	        Z
ed
        Zej                  d        Zed        Zej                  d        Zed        Zej                  d        Zed        Zej                  d        Zy)Episodea  Class representing an episode in a podcast. Corresponds to an RSS Item.

    When creating a new Episode, you can populate any attribute
    using keyword arguments. Use the attribute's name on the left side of
    the equals sign and its value on the right side. Here's an example::

        >>> # This...
        >>> ep = Episode()
        >>> ep.title = "Exploring the RTS genre"
        >>> ep.summary = "Tory and I talk about a genre of games we've " + \
        ...              "never dared try out before now..."
        >>> # ...is equal to this:
        >>> ep = Episode(
        ...    title="Exploring the RTS genre",
        ...    summary="Tory and I talk about a genre of games we've "
        ...            "never dared try out before now..."
        ... )

    :raises: TypeError if you try to set an attribute which doesn't exist,
             ValueError if you set an attribute to an invalid value.

    You must have filled in either :attr:`.title` or :attr:`.summary` before
    the RSS can be generated.

    To add an episode to a podcast::

        >>> import podgen
        >>> p = podgen.Podcast()
        >>> episode = podgen.Episode()
        >>> p.episodes.append(episode)

    You may also replace the last two lines with a shortcut::

        >>> episode = p.add_episode(podgen.Episode())


    .. seealso::

       :doc:`/usage_guide/episodes`
          A friendlier introduction to episodes.
    c                 `   g | _         d | _        	 d | _        	 d | _        d | _        	 d | _        	 d | _        d | _        	 d| _        d | _	        d | _
        d | _        d| _        	 d | _        d | _        	 t        |      D ]0  \  }}t!        | |      rt#        | ||        t%        d|d|d       y )NFzKeyword argument z (with value z) not recognized!)_Episode__authorssummarylong_summary_Episode__mediaidlink_Episode__publication_datetitle_Episode__withhold_from_itunes_Episode__image_Episode__itunes_duration_Episode__explicitis_closed_captioned_Episode__positionsubtitler   hasattrsetattr	TypeError)selfkwargs	attributevalues       G/root/podcast_feed/.venv/lib/python3.12/site-packages/podgen/episode.py__init__zEpisode.__init__G   s    	( !	 	2 		 #'
	 ',#!%#( 	 	 !*& 1IutY'i/1:E!C D D	 !2    c                    d}d}t        j                  d      }| j                  s| j                  st	        d      | j                  r't        j
                  |d      }| j                  |_        | j                  r't        j
                  |d      }| j                  |_        | j                  s| j                  r| j                  r| j                  rxt        j
                  |d      }t        j                  | j                        |_        t        j
                  |dd	z        }t        j                  | j                        |_        nHt        j
                  |d      }t        j                  | j                  xs | j                        |_        | j                  rW| j                  D cg c]  }|j                  s|j                   }	}|	r)t        j
                  |d
|z        }
t        |	      |
_        t        | j                        dkD  s| j                  d   j                  s| j                  xs g D ]  }t        j
                  |d|z        }|j                  r.|j                  r"|j                  d|j                  d|_        V|j                  r|j                  |_        t|j                  |_         n3t        j
                  |d      }t        | j                  d         |_        | j                   r| j                   }n1| j"                  r#| j                   | j"                  j$                  }nd}|r,t        j
                  |d      }||_        d|j&                  d<   | j"                  rt        j
                  |d      }| j"                  j$                  |j&                  d<   t        | j"                  j(                        |j&                  d<   | j"                  j*                  |j&                  d<   | j"                  j,                  r4t        j
                  |d|z        }| j"                  j.                  |_        | j0                  r0t        j
                  |d      }t3        | j0                        |_        | j4                  r t        j
                  |d|z        }d|_        | j6                  r2t        j
                  |d|z        }| j6                  |j&                  d<   | j8                  .t        j
                  |d|z        }| j8                  rdnd |_        | j:                  r t        j
                  |d!|z        }d|_        | j<                  B| j<                  dk\  r3t        j
                  |d"|z        }t        | j<                        |_        | j>                  r*t        j
                  |d#|z        }| j>                  |_        |S c c}w )$zCreate an RSS item using lxml's etree and return it.

        This is primarily used by :class:`podgen.Podcast` when generating the
        podcast's RSS feed.

        :returns: etree.Element('item')
        z*http://www.itunes.com/dtds/podcast-1.0.dtdz http://purl.org/dc/elements/1.1/itemzBRequired fields not set, make sure either title or summary is set!r   r   descriptionz{%s}encodedz(http://purl.org/rss/1.0/modules/content/z
{%s}author   r   z{%s}creatorz <>authorNguidfalseisPermaLink	enclosureurllengthtypez{%s}durationpubDatez	{%s}blockYesz	{%s}imagehrefz{%s}explicitNoz{%s}isClosedCaptionedz	{%s}orderz{%s}subtitle) r	   Elementr   r   
ValueError
SubElementtextr   r   CDATAr   namer   lenemailstrr   r   r5   attribsizer7   durationduration_strr   r   r   r   r   r   r   r    )r$   	ITUNES_NS	DUBLIN_NSentryr   r   r-   contentaauthors_with_nameitunes_authorr0   rss_guidr1   r4   rG   r8   blockimageexplicitr   orderr    s                          r(   	rss_entryzEpisode.rss_entry   s    A	6	f%

dll 8 9 9 ::$$UG4EEJ99##E62D		DI<<4,,|| 1 1#..umD#(;;t||#< **5-%O3P Q${{4+<+<= $..umDKK A0A0AB   >>15 JA166 J  $$UL9,DE %;<M%N"4>>"Q&dnnQ.?.E.E -2-A"--e]Y5NOFvv!''3466177&C&'ff&'gg . ))%:!$.."3477wwH\\dggo||''H H##E62D DI)0DKK&<<((<I&*ll&6&6IU#),T\\->->)?IX&'+||'8'8IV$||$$ ++E>I3MN $ 9 9""&&ui8G()@)@AGL&&$$UK),CDEEJ<<$$UK),CDE#'<<ELL ??&''~	/IJH%)__E$HM##"'"2"25,Ci,O#Q',$??&4??a+?$$UK),CDET__-EJ==''~	/IJH MMHMW !Ks   .W Wc                     | j                   S )a  List of :class:`~podgen.Person` that contributed to this
        episode.

        The authors don't need to have both name and email set. They're usually
        not displayed anywhere.

        .. note::

            You do not need to provide any authors for an episode if
            they're identical to the podcast's authors.

        Any value you assign to authors will be automatically converted to a
        list, but only if it's iterable (like tuple, set and so on). It is an
        error to assign a single :class:`~podgen.Person` object to this
        attribute::

            >>> # This results in an error
            >>> ep.authors = Person("John Doe", "johndoe@example.org")
            TypeError: Only iterable types can be assigned to authors, ...
            >>> # This is the correct way:
            >>> ep.authors = [Person("John Doe", "johndoe@example.org")]

        The initial value is an empty list, so you can use the list methods
        right away.

        Example::

            >>> # This attribute is just a list - you can for example append:
            >>> ep.authors.append(Person("John Doe", "johndoe@example.org"))
            >>> # Or assign a new list (discarding earlier authors)
            >>> ep.authors = [Person("John Doe", "johndoe@example.org"),
            ...               Person("Mary Sue", "marysue@example.org")]

        :type: :obj:`list` of :class:`podgen.Person`
        :RSS: author or dc:creator, and itunes:author
        )r   r$   s    r(   authorszEpisode.authors9  s    L ~~r*   c                 \    	 t        |      | _        y # t        $ r t        d|z        w xY w)Nz~Only iterable types can be assigned to authors, %s given. You must put your object in a list, even if there's only one author.)listr   r#   )r$   rX   s     r(   rX   zEpisode.authorsa  sA    	J!']DN 	J ?AHI J J	Js    +c                     | j                   S )a  The time and date this episode was first published.

        The value can be a :obj:`str`, which will be parsed and
        made into a :class:`datetime.datetime` object when assigned. You may
        also assign a :class:`datetime.datetime` object directly. In both cases,
        you must ensure that the value includes timezone information.

        :type: :obj:`str` (will be converted to and stored as
            :class:`datetime.datetime`) or :class:`datetime.datetime`.
        :RSS: pubDate

        .. note::

           Don't use the media file's modification date as the publication
           date, unless they're the same. It looks very odd when an episode
           suddenly pops up in the feed, but it claims to be several hours old!
        )r   rW   s    r(   publication_datezEpisode.publication_datej  s    & &&&r*   c                     |it        |t              rt        j                  j	                  |      }t        |t
              st        d      |j                  t        d      || _        y d | _        y )NzInvalid datetime formatz$Datetime object has no timezone info)	
isinstancer   dateutilparserparser
   r=   tzinfor   )r$   r\   s     r(   r\   zEpisode.publication_date  sh    '*L9#+??#8#89I#J .9 !:;;&&. !GHH&6D#&*D#r*   c                     | j                   S )a  Get or set the :class:`~podgen.Media` object that is attached
        to this episode.

        Note that if :py:attr:`.id` is not set, the media's URL is used as
        the id. If you rely on this, you should make sure the URL never changes,
        since changing the id messes up with clients (they will think this
        episode is new again, even if the user has listened to it already).
        Therefore, you should only rely on this behaviour if you own the domain
        which the episodes reside on. If you don't, then you must set
        :py:attr:`.id` to an appropriate value manually.

        :type: :class:`podgen.Media`
        :RSS: enclosure and itunes:duration
        )r   rW   s    r(   mediazEpisode.media  s      ||r*   c                     |7t        |d      r t        |d      rt        |d      r|| _        y t        d      d | _        y )Nr5   rF   r7   z@The parameter media must have the attributes url, size and type.)r!   r   r#   )r$   rd   s     r(   rd   zEpisode.media  sG    ue$)?uf%$ !6 7 7  DLr*   c                     | j                   S )az  Prevent this episode from appearing in the iTunes podcast directory.
        Note that the episode can still be found by inspecting the XML, so it is
        still public.

        One use case would be if you knew that this episode would get you kicked
        out from iTunes, should it make it there. In such cases, you can set
        withhold_from_itunes to ``True`` so this episode isn't published on
        iTunes, allowing you to publish it to everyone else while keeping your
        podcast on iTunes.

        This attribute defaults to ``False``, of course.

        :type: :obj:`bool`
        :RSS: itunes:block
        )r   rW   s    r(   withhold_from_ituneszEpisode.withhold_from_itunes  s    " ***r*   c                 R    ||du s|du r|| _         y t        d|z        d | _         y )NTFz1withhold_from_itunes expects bool or None, got %s)r   r#   )r$   rg   s     r(   rg   zEpisode.withhold_from_itunes  sG    +#t+/Cu/L.B+ !)+?!@ A A +/D'r*   c                     | j                   S )u  The podcast episode's image, overriding the podcast's
        :attr:`~.Podcast.image`.

        This attribute specifies the absolute URL to the artwork for your
        podcast. iTunes prefers square images that are at least ``1400x1400``
        pixels.

        iTunes supports images in JPEG and PNG formats with an RGB color space
        (CMYK is not supported). The URL must end in ".jpg" or ".png"; a
        :class:`.NotSupportedByItunesWarning` will be issued if it doesn't.

        :type: :obj:`str`
        :RSS: itunes:image

        .. note::

           If you change an episode’s image, you should also change the file’s
           name; iTunes doesn't check the actual file to see if it's changed.

           Additionally, the server hosting your cover art image must allow HTTP
           HEAD requests.

        .. warning::

            Almost no podcatchers support this. iTunes supports it only if you
            embed the cover in the media file (the same way you would embed
            an album cover), and recommends that you use Garageband's Enhanced
            Podcast feature.

            The podcast's image is used if this isn't supported.
        )r   rW   s    r(   rR   zEpisode.image  s    B ||r*   c                     |ct        |      j                         }|j                  d      s1t        j                  d|j                  d      d   z  t        d       || _        y d | _        y )N)z.jpgz.jpegz.pngz/Image filename must end with png or jpg, not %s.   )
stacklevel)rD   lowerendswithwarningswarnsplitr   r   )r$   rR   lowercase_images      r(   rR   zEpisode.image  sf    !%j..0O#,,-FG "[[-b123N!"$ !DLDLr*   c                     | j                   S )aq  Whether this podcast episode contains material which may be
        inappropriate for children.

        The value of the podcast's explicit attribute is used by default, if
        this is kept as ``None``.

        If you set this to ``True``, an "explicit" parental advisory
        graphic will appear in the Name column in iTunes. If the value is
        ``False``, the parental advisory type is considered Clean, meaning that
        no explicit language or adult content is included anywhere in this
        episode, and a "clean" graphic will appear.

        :type: :obj:`bool`
        :RSS: itunes:explicit
        )r   rW   s    r(   rS   zEpisode.explicit  s    " r*   c                 J    ||dvrt        d|z        || _        y d | _        y )N)TFz#Invalid value "%s" for explicit tag)r=   r   )r$   rS   s     r(   rS   zEpisode.explicit  s6    }, !F#+", - -&DO"DOr*   c                     | j                   S )a  A custom position for this episode on the iTunes store page.

        If you would like this episode to appear first, set it to ``1``.
        If you want it second, set it to ``2``, and so on. If multiple episodes
        share the same position, they will be sorted by their
        :attr:`publication date <.Episode.publication_date>`.

        To remove the order from the episode, set the position back to
        :obj:`None`.

        :type: :obj:`int`
        :RSS: itunes:order
        )r   rW   s    r(   positionzEpisode.position  s     r*   c                 8    |t        |      | _        y d | _        y )N)intr   )r$   rx   s     r(   rx   zEpisode.position(  s    !(mDO"DOr*   N)__name__
__module____qualname____doc__r)   rU   propertyrX   setterr\   rd   rg   rR   rS   rx    r*   r(   r   r      sS   (TzDxtl % %N ^^J J ' '( 
+ 
+  " \\    + +$   / !/    D \\	  	   $ __# #    __# #r*   r   )r~   
__future__r   r   r   r   builtinsfuture.utilsr   rq   lxmlr	   r
   dateutil.parserr_   dateutil.tzpodgen.warningsr   podgen.utilr   r   podgen.compatr   objectr   r   r*   r(   <module>r      s?    S R  "      7 = &Q#f Q#r*   