+
     ȟ  c                  s   ^ RI Ht ^ RIt^ RIt^ RIt^ RIHtHtHtH	t	H
t
 ^ RIt^ RIHt ^ RIHt ^RIHt ^RIHtHtHt ^RIHtHt ^R	IHt ^R
IHt ^RIHtHtHtHtH t H!t!H"t"H#t#H$t$H%t%H&t&H't'H(t(H)t)H*t*H+t+H,t,H-t-H.t. ]'       d   ^RIH/t/H0t0 ^RIH1t1 ^RIH2t2H3t3H4t4H5t5H6t6H7t7  ! R R4      t8 ! R R4      t9 ! R R4      t:]" ! R R]4      4       t;]" ! R R]4      4       t< ! R R4      t=R# )i    )annotationsN)TYPE_CHECKINGAnyListTupleUnion)BeautifulSoup)utils)
parse_page)
ResultList	Thumbnail_parse_results)StatusThumbnailType)ModdbException)Member)BASE_URLCOMMENT_LIMITERGLOBAL_LIMITERGLOBAL_THROTLELOGGER
SSLAdapterconcat_docsgenerate_hashgenerate_login_cookiesgetget_dateget_page_typeget_siteareaget_siteareaidjoinraise_for_status	ratelimitsoupuser_agent_list)CommentTag)	WatchType)EngineGameGroupModReviewTeamc                  s,    ] tR t^-tRtR R ltR tRtR# )Messagea  A single message within a thread.

Attributes
-----------
id : int
    The id of the message
member : Thumbnail
    A member type thumbnail representing the member
    who sent the message
timestamp : datetime.datetime
    Message send date
text : str
    The html text of the message
c                   V ^8  d   QhRR/#    htmlr    Zformat   "1/usr/lib/python3.14/site-packages/moddb/client.py__annotate__ZMessage.__annotate__=   s     < <] <    c                	sH   VP                  R RR7      p\        VR,          4      V n        \        VR,          \        P
                  VR,          R7      V n        \        VP                  R4      R,          4      V n        VP                  R	R
R7      P                  V n        R# )aZavatarZclass_idhreftitle)urltypenametimedatetimedivcommentN)	findintr9   r
   r   memberr   	timestamptext)selfr0   rE      && r4   __init__ZMessage.__init__=   sx    3x0d4j/F6N9M9MTZ[bTcd!$))F"3J"?@IIeII6;;	r6   c                	"    R V P                    R2# )z< Message member= >)rE   rH      &r4   __repr__ZMessage.__repr__E   s    "4;;-r22r6   )r9   rE   rG   rF   N__name__
__module____qualname____firstlineno____doc__rJ   rO   __static_attributes__r1   r6   r4   r,   r,   -   s    <3r6   r,   c                  s,    ] tR t^ItRtR R ltR tRtR# )Threada  A thread is a conversation between two or more members in which
one or more messages can be sent.

Sorting
--------
    * **id** - when the message was sent, asc is oldest, desc is most recent
    * **name** - order alphabetically, asc is a-z, desc is z-a
    * **hasread** - order by whether or the message has been read, asc is unread first, desc is read first
    * **hasreplied** - order by whether or not you have replied to the message, asc us unreplied first, desc is replied first

Attributes
-----------
name : str
    Name of the thread
id : int
    Id of the thread
count : int
    The number of messages in this thread
members : List[Tumbnail]
    All the members participating in the thread. Note: The
    thumbnail of the member who fetched the message will always
    be first and will have their name attribute be 'you' instead
    of the username
message : List[Message]
    The messages associated to this thread
c               r-   r.   r1   r2   r3   r4   r5   ZThread.__annotate__e   s     C C] Cr6   c           	     	sX   VP                  R RR7      pVP                  R RR7      pVP                  RRR7      P                  p\        P                  ! RV4      pVf   W@n        ^V n        M5VP                  ^4      V n        \        VP                  ^4      4      V n        VP                  R	R
R7      P                  P                  R4      pVP                  RR.R7      pVP                  R R.R7      P                  R RR7      p\        VR,          VR,          P                  R4      ^,           R 4      V n        V U	u. uF0  p	\        V	R,          V	P                  \        P                  R7      NK2  	  up	V n        V U
u. uF  p
\!        V
4      NK  	  up
V n        R# u up	i u up
i )rA   Zfirstmessager9   Znormalcornerr8   spanZheadingz(.*) \(([0-9]*) messages?\)NpZintroductionr7   Z
deleteiconZtablecommentsFZ	recursiver:   Z=)r<   r>   r=   )rC   stringreZmatchr>   countZgrouprD   Zstrongfind_allZindexr9   r
   r   rE   membersr,   messages)rH   r0   threadZheaderZheader_stringZheader_matchr`   Zoptionra   rE   messages   &&         r4   rJ   ZThread.__init__e   st   5^4U>:F9=DDxx >N%IDJ$**1-DI\//23DJ++c.+9@@II#NS,8;;uo->;?HHZ_H`fVnVF^%9%9#%>%B%DEF "
! &.v}}=CWCWX!
 :BBg)B	
 Cs   6F"F'c                	<    R V P                    RV P                   R2# )z< Thread name=z count=rL   )r>   r^   rM   rN   r4   rO   ZThread.__repr__}   s    		{'$**R@@r6   )r^   r9   r`   ra   r>   NrP   r1   r6   r4   rW   rW   I   s    6C0Ar6   rW   c                  s&    ] tR t^tRtR tR tRtR# )ThreadThumbnaila  The thumbnail of a thread, these represent partial objects that
must be parsed using a client to get the full thread.

Attributes
-----------
name : str
    The name of the thread
id : int
    The id of the thread
url : str
    The url for the thread
last_messager : Thumbnail
    A thumbnail representig the user that sent the
    last message
timestamp : datetime.datetime
    Datetime of the last message
content : str
    Content of the last message. Useful for checking
    the last message without having to parse the thread.
c                	sT   VP                  R 4      V n        \        VP                  R4      4      V n        VP                  R4      V n        VP                  R4      V n        VP                  R4      V n        \        V P                  P                  R4      R,          4      V n	        R# )r>   r<   last_messagerrF   contentZ/N)
r   r>   r   r<   rf   rF   rg   rD   Zsplitr9   )rH   kwargss   &,r4   rJ   ZThreadThumbnail.__init__   sv    JJv&	

5)*#ZZ8K0zz),dhhnnS)"-.r6   c                	rd   )z< ThreadThumbnail name=z last_messager=rL   )r>   rf   rM   rN   r4   rO   ZThreadThumbnail.__repr__   s#    (?4CUCUBVVXYYr6   )rg   r9   rf   r>   rF   r<   NrP   r1   r6   r4   re   re      s    */Zr6   re   c                  sJ   a  ] tR t^tRtV 3R ltR tR R ltR R ltRt	V ;t
# )	UpdatezAn update object. Which is basically just a fancy thumbnail with a couple extra attributes and
methods.

Attributes
-----------
updates : List[Thumbnail]
    A list of thumbnail objects of the things thave have been posted (new files, new images)
c                	s   < \         SV `  ! R/ VB  VP                  R 4      V n        \	        VP                  R4      4      V n        \	        VP                  R4      4      V n        VP                  R4      V n        R# )updatesunfollowclearclientNr1   )superrJ   r   rk   r   _unfollow_url
_clear_url_clientrH   Zattrs	__class__   &,r4   rJ   ZUpdate.__init__   s^    !5!yy+!%))J"78uyy12yy*r6   c                	s|    R V P                    RV P                  P                    R\        V P                  4       R2# )z<Update name=z type=z	 updates=>)r>   r=   Zlenrk   rM   rN   r4   rO   ZUpdate.__repr__   s5    tyyk		/?yT\\IZH[[\]]r6   c               r-   r/   returnboolr1   r2   r3   r4   r5   Update.__annotate__   s     : :t :r6   c                    V P                   P                  RV P                  RR/R7      pRVP                  4       R,          9   # )zClears all updates

Raises
-------
ModdbException
    An error has occured while trying to clear the updates for this page

Returns
--------
bool
    True if the updates were successfully cleared
POSTajaxtdatasuccessfully removedrG   )rr   _requestrq   jsonrH   r   & r4   rm   ZUpdate.clear   s=     LL!!&$//!N%&)999r6   c               r-   rw   r1   r2   r3   r4   r5   rz      s     8 8$ 8r6   c                r{   )zUnfollows the page. This will also clear the updates

Raises
-------
ModdbException
    An error has occured while trying to unfollow this page

Returns
--------
bool
    True if the page was successfully unfollowed
r|   r}   r~   r   zno longer watchingrG   )rr   r   rp   r   r   r   r4   rl   ZUpdate.unfollow   s?     LL!!&$*<*<FC=!Q#qvvx'777r6   )rq   rr   rp   rk   )rQ   rR   rS   rT   rU   rJ   rO   rm   rl   rV   __classcell__rt      @r4   rj   rj      s"    +^:"8 8r6   rj   c                  sJ   a  ] tR t^tRtV 3R ltR R ltR R ltR tRt	V ;t
# )	Requestz^A thumbnail with two extra methods used to clear and accept requests.

Attributes
-----------
c                	s   < \         SV `  ! R/ VB  \        VP                  R 4      4      V n        \        VP                  R4      4      V n        VP                  R4      V n        R# )declineacceptrn   Nr1   )ro   rJ   r   r   _decline_acceptrr   rs   ru   r4   rJ   ZRequest.__init__   sM    !5!UYYy12EIIh/0yy*r6   c               r-   rw   r1   r2   r3   r4   r5   Request.__annotate__   s     6 6 6r6   c                r{   )zAccept the friend request.

Raises
-------
ModdbException
    An error has occured while trying to accept the request

Returns
--------
bool
    True if the request was successfully accepted
r|   r}   r~   r   znow friends withrG   )rr   r   r   r   r   r   r4   r   ZRequest.accept   s=     LL!!&$,,fc]!K!QVVXf%555r6   c               r-   rw   r1   r2   r3   r4   r5   r      s     : : :r6   c                r{   )zDecline the friend request

Raises
-------
ModdbException
    An error has occured while trying to decline the request

Returns
--------
bool
    True if the page was successfully declined
r|   r}   r~   r   r   rG   )rr   r   r   r   r   r   r4   r   ZRequest.decline   s=     LL!!&$--vsm!L%&)999r6   c                	rK   )z<Request from=rv   r>   rM   rN   r4   rO   ZRequest.__repr__  s    		{!,,r6   )r   rr   r   )rQ   rR   rS   rT   rU   rJ   r   r   rO   rV   r   r   r   r4   r   r      s!    +6":"- -r6   r   c                  s   ] tR tRtRtR R ltR tR tR t]	! ]
]4      R 4       tR	 R
 ltR R ltR R ltRFR R lltR R ltR R ltR R ltR R ltR R ltR R ltR R lt]	! ]4      RR /R! R" ll4       tR# tR$ R% ltR& R' ltR( R) ltR*R R+R,/R- R. lltR/ R0 ltRGR1 R2 llt R3 R4 lt!R5 R6 lt"R7 R8 lt#R9 R: lt$R; R< lt%R= R> lt&R? R@ lt'RA RB lt(RC RD lt)REt*R # )HClienti  a  Login the user to moddb through the library, this allows user to see guest comments and see
private groups they are part of. In addition, this can be used for a lot of the operation

Parameters
-----------
username : str
    The username of the user

password : str
    The password associated to that username

Raises
-------
ValueError
    The password or username was incorrect

Attributes
----------
member : Member
    The member objects this client instance represents
c               s     V ^8  d   QhRRRR/# )r/   usernamestrpasswordr1   r2   r3   r4   r5   Client.__annotate__(  s     	
 	
 	
 	
r6   c                	sZ   \         P                  ! 4       pVP                  R \        4       4       \	        WVR7      Vn        W0n        \        P                  ! RV4       \        \        V P                  R\         RVP                  RR4       24      P                  4      4      V n        R# )zhttps://)sessionzLogin successful for %sGETz	/members/Z_-N)requestsZSessionZmountr   r   cookies_sessionr   infor   r!   r   r   ZreplacerG   rE   )rH   r   r   r      &&& r4   rJ   ZClient.__init__(  s    ""$j*,/0WU-x8u
)H<L<LSRU<V;W&XY^^_
r6   c                	sx    R V P                   P                   RV P                   P                  P                   R2# )z<Client username=z level=rv   )rE   r>   profileZlevelrM   rN   r4   rO   ZClient.__repr__3  s4    "4;;#3#3"4GDKK<O<O<U<U;VVWXXr6   c                	s    \         P                  R ,          P                  V n        V P                  \         P                  R ,          n        R# )moddbN)sysmodulesSESSION_fake_sessionr   rM   rN   r4   	__enter__ZClient.__enter__6  s.     [[199'+}}G$r6   c                	sj    V P                   \        P                  R ,          n        \	        V R4       R# )r   r   N)r   r   r   r   Zdelattr)rH   Zexc_typeZexc_valZexc_tbs   &&&&r4   __exit__ZClient.__exit__:  s#    '+'9'9G$o&r6   c           
     s   \         P                  ! V P                  P                  4      p/ VP	                  R/ 4      CR\
        P                  ! \        4      /Cp\        P                  ! WWTVP	                  R/ 4      R7      pV P                  P                  V4      p\        P                  ! RVP                  4       V P                  P                  WsP	                  RR4      R7      p\        V4       V# )	zgMaking sure we do our request with the cookies from this client rather than the cookies
of the library.headersz
User-Agentr   )r   r   r   zRequest: %sallow_redirectsT)r   )r   Zdict_from_cookiejarr   r   ZpoprandomZchoicer"   r   r   Zprepare_requestr   r   r<   Zsendr   )	rH   Zmethodr<   ri   r   r   ZreqZpreppedr   s	   &&&,     r4   r   ZClient._request>  s     ++DMM,A,AB
jjB'
&--8

 

6SU@V
 --//4M7;;/MMw

CTVZ8[\r6   c               r-   )r/   rx   zList[Update]r1   r2   r3   r4   r5   r   S  s     1 1\ 1r6   c                s   V P                  R\         R24      p\        VP                  4      p. pRpVP	                  RVR7      pV Uu. uFE  pVP
                  P
                  P
                  P                  RRR7      P	                  RRR	7      NKG  	  ppV UU	u. uF  qR
R  F  qNK  	  K  	  p
pp	V
 EF  pVP                  R4      pVP                  RRR7      R,          pVP                  RRR7      R,          pVP                  R4      P	                  R4      pTP                  \        VR,          VR,          \        VR,          4      VP                  R,          T TTV Uu. uF2  p\        VP                  VR,          \        VR,          4      R7      NK4  	  up\        VP                  R4      R,          4      R7	      4       EK  	  V# u upi u up	pi u upi )zGet the current updates the user has for models they are subscribed to.

Returns
--------
List[Update]
    List of updates (thumbnail like objects with extra methods and an extra attribute)
r   /messages/updatesrY   r\   rA   tabler8   Fr[   Nr7   zStop Watchingr;   r:   ZClearrZ   r;   src)r>   r<   r=   r?   r@   )	r>   r<   r=   imagern   rl   rm   rk   date)z
Mods WatchzMembers WatchzEngines WatchzGroups WatchzGames Watchrh   )r   r   r!   rG   r_   parentrC   appendrj   r   imgr
   r\   r   )rH   r   r0   rk   ZstringsrawZeZobjectsZsublistZitemZobjects_rawZupdate	thumbnailrl   rm   Zupdates_rawZxs   &                r4   get_updatesZClient.get_updatesS  s    MM%H:->!?@AFF|
 mmF7m3 
 HHOO""''g'>GGY^G_ 	 

 ,3L7s|tt|t7L!FC(I{{3o{>vFHKK7K3F;E ++c*33C8KNN"7+!&)&y'89#--.% "-!,A "qxxQvY]STU[S\E]^!, "&++f"5j"AB ". ;

 M s   
AGG)8Gc                    V ^8  d   QhRRRR/# )r/   categoryr%   rx   ry   r1   r2   r3   r4   r5   r     s     : :i :D :r6   c                sV   V P                  R\         R24      p\        VP                  4      p\        P
                  ! RVP                   R24      pVP                  RVR7      pVf   R# V P                  R\         VR	,           2R
R/R7      pRVP                  4       R,          9   # )a5  Clear all updates for a specific category of
watched. This method will conduct two requests because
the clear update request requires a hash generated by
moddb.

Parameters
-----------
category: WatchType
    The category of watched to clear

Returns
--------
bool
    Whether or not the clear was successful
r   r   z.*\/clearall\/(.*)\/1\/sr7   )r:   Tr|   r:   r}   r~   r   zupdates were clearedrG   )	r   r   r!   rG   r]   Zcompiler>   rC   r   )rH   r   Z	hash_pager0   ZpatternZlinkr   s   &&     r4   clear_updatesZClient.clear_updates  s      MM%H:5F)GH	INN#** 7aHIyy7y+<MM&XJtF|n"=VSMMR%&)999r6   c               r-   )r/   rx   zList[Request]r1   r2   r3   r4   r5   r     s     " "] "r6   c                s   V P                  R\         R24      p\        VP                  4      p. pVP	                  RRR7      pVP
                  P
                  P
                  P	                  RRR7      P                  RR	R
7      pVRR  F  pVP	                  R4      pVP	                  RRR7      R,          pVP	                  RRR7      R,          p	VP                  ! \        VR,          VR,          \        VR,          4      VP                  R,          V VV	\        VP	                  R4      R,          4      R7      4       K  	  V# )zGet the current friend requests the user has.

Returns
--------
List[Request]
    List of requests (thumbnail like objects with extra methods)
r   r   rY   zFriend Requestsr   rA   r   r8   Fr[   Nr7   ZAcceptr   r:   ZDecliner;   r   r?   r@   )r>   r<   r=   r   rn   r   r   r   rh   )r   r   r!   rG   rC   r   r_   r   r   r   r   r   )
rH   r   r0   r   r   Zraw_requestsZrequestr   r   r   s
   &         r4   get_friend_requestsZClient.get_friend_requests  s.    MM%H:->!?@AFF|ii'8i9zz((//44U74KTTU U 
 $CR(GS)I\\#X\6v>Fll3il8@GOO"7+!&)&y'89#--.!#!',,v"6z"BC	 )$ r6   c               $    V ^8  d   QhRRRRRR/# )r/   r   r%   pagerD   rx   r	   r1   r2   r3   r4   r5   r     s!     
 
I 
S 
 
r6   c                s    \          RVP                   R2p\        V P                  RV RV 24      P                  4      p\        V4      w  rVrx\        VVVVVR7      # )aa  Get a list of thumbnails of watched items based on the type parameters. Eventually, you'll also be
able to paginate your mods.

Parameters
-----------
category : WatchType
    The type of watched thing you wanna get (mod, games, engines)
page : int
    The page number you want to get

Returns
--------
ResultList[Thumbnail]
    List of watched things

z/messages/watching/r   r   z/page/)resultsr<   current_pagetotal_pagestotal_results)r   r>   r!   r   rG   r   r	   )	rH   r   r   r<   r0   r   r   r   r   s	   &&&      r4   get_watchedZClient.get_watched  sl    " 
-hmm_A>DMM%C5tf)=>CCD<J4<P9{%#'
 	
r6   c               r   )r/   r   z'Union[Mod, Game, Engine, Group, Member]rx   ry   r1   r2   r3   r4   r5   r     s     1 1D 1 1r6   c                s    V P                  R\         R2RRRRR\        VP                  4      RVP                  /R	R
7      pRVP                  4       R,          9   # )ac  Follow/unfollow this page.

Parameters
-----------
page : Union[Mod, Game, Engine, Group, Member]
    The page you wish to watch/unwatch

Raises
-------
ModdbException
    An error has occured while trying to follow/unfollow the page

Returns
--------
bool
    True if the page has been successfully followed, False if it has been successfully unfollowed
r|   /messages/ajax/action/r}   r~   actionZwatchsitearea
siteareaidFr   r   zbe notifiedrG   r   r   r   r<   r9   r   rH   r   r   rI   r4   trackingZClient.tracking  sh    $ MMj./'L2dgg	 "  

  000r6   c               r   r/   rB   r#   rx   ry   r1   r2   r3   r4   r5   r     s     9 9G 9 9r6   c                s    V P                  R\         R2RRRRRRR	VP                  /R
R7      pRVP                  4       R,          9   # )a1  Like a comment, if the comment has already been liked nothing will happen.

Parameters
-----------
comment : Comment
    The comment to like

Raises
-------
ModdbException
    An error has occured while trying to like the comment

Returns
--------
bool
    True if the comment has been successfully liked
r|   r   r}   r~   r   Z	karmagoodr   rB   r   Fr   successfully issuedrG   r   r   r9   r   rH   rB   r   rI   r4   like_commentZClient.like_comment  s_    $ MMj./+Igjj	 "  

 %(888r6   c               r   r   r1   r2   r3   r4   r5   r   "  s     !9 !9w !94 !9r6   c                s    \        VR4      '       g   \        R4      hV P                  R\         R2RRRRR	R
RVP                  /RR7      pRVP                  4       R,          9   # )a=  Dislike a comment, if the comment has already been disliked nothing will happen.

Parameters
-----------
comment : Comment
    The comment to dislike

Raises
-------
ModdbException
    An error has occured while trying to dislike the comment

Returns
--------
bool
    True if comment has been successfully disliked.
Zdownvotez&Argument must be a Comment-like objectr|   r   r}   r~   r   Zkarmabadr   rB   r   Fr   r   rG   )ZhasattrZ	TypeErrorr   r   r9   r   r   rI   r4   dislike_commentZClient.dislike_comment"  sx    $ w
++DEEMMj./*Igjj	 "  

 %(888r6   c               r   )r/   r   zUnion[Group, Team]rx   ry   r1   r2   r3   r4   r5   r   E  s     9 91 9d 9r6   c                    V P                  R\         RVP                   2RR/RR7      pRVP                  4       R,          9   # )	a  Join/leave a team

Parameters
-----------
page : Union[Group, Team]
    The team/group you want to join. Will not work if you don't have permissions

Raises
-------
ModdbException
    An error has occured while trying to join/leave the group/team

Returns
--------
bool
    True if the group/team has been successfully joined, False if the group/team has been
    successfully left.

r|   z/groups/ajax/members/change/r}   r~   Fr   zsuccessfully joinedrG   r   r   rI   r4   
membershipZClient.membershipE  sO    ( MMj4TWWI>#!	  
 %(888r6   c               r   )r/   r   r   rx   ry   r1   r2   r3   r4   r5   r   b  s     G G3 G4 Gr6   c                s    V P                  R\         R2RRRRR\        VP                  4      RVP                  /R	R
7      pRVP                  4       R,          9  # )a'  Report a page. This can take any object that has an id and url attribute.

Parameters
-----------
page : Any
    The page to report

Raises
-------
ModdbException
    An error has occured while trying to report the page

Returns
--------
bool
    True if the page has been successfully reported
r|   r   r}   r~   r   reportr   r   Fr   zalready reported this contentrG   r   r   rI   r4   r   ZClient.reportb  sh    $ MMj./(L2dgg	 "  

 /affhv6FFFr6   c               r   r/   rE   r   rx   ry   r1   r2   r3   r4   r5   r     s     H Hv H$ Hr6   c                r   )	a  Unfriend this member if you are friends with them.

Parameters
-----------
member : Member
    The member you wish to unfriend

Raises
-------
ModdbException
    An error has occured trying to unfriend this user

Returns
--------
bool
    True if the user was succesfully unfriended
r|   z/members/ajax/friends/delete/r}   r~   Fr   z"no longer friends with this memberrG   r   rH   rE   r   rI   r4   unfriendZClient.unfriend  sO    $ MMj5fii[A#!	  
 4qvvx7GGGr6   c               r   r   r1   r2   r3   r4   r5   r     s     B B6 Bd Br6   c                r   )	a  Send a friend request to a user. You will not instantly become friends with them,
they will have to accept the friend request you sent them first.

Parameters
-----------
member : Member
    The member you wish to send a friend request to

Raises
-------
ModdbException
    An error has occured trying to send a friend request to that user

Returns
--------
bool
    True if the user was succesfully sent a friend request
r|   z/members/ajax/friends/add/r}   r~   Fr   zfriend request has been sentrG   r   r   rI   r4   send_requestZClient.send_request  sO    & MMj2699+>#!	  
 .&1AAAr6   rB   Nc               s(    V ^8  d   QhRRRRRRRR/# )r/   r   r   rG   r   rB   r#   rx   r1   r2   r3   r4   r5   r     s(     , , ,3 ,G ,s ,r6   c               s    T P                  RVP                  R\        4       RV'       d   VP                  M^ R^RVRR/R7      pVP	                  \        VP                  4      4      # )	a  Add a comment to a page.

Parameters
-----------
page : Any
    Must be a moddb.page, the page you wish to add the comment to.
test : str
    The content of the comment you wish to post
comment : Optional[Comment]
    If you wish to reply to another comment you must provide the comment
    object for it there.

Returns
--------
Any
    The page's updated object containing the new comment and any other new data that
    has been posted since then
r|   formhashZreplyidr   summaryrB   zSave commentr   )r   r<   r   r9   rt   r!   rG   )rH   r   rG   rB   r   s   &&&$ r4   add_commentZClient.add_comment  sb    ( MMHHMO7::a4>  

 ~~d166l++r6   c                	s    Vf   \        R4      hV P                  R\         R2RRRRRR	R
VP                  RVP                  /RR7      pV# )NzZThis comment no longer exists or is no longer on the page it was initially retrieved from.r|   r   r}   r~   r   deleter   rB   r   hashFr   )r   r   r   r9   _hashr   rI   r4   _comment_state_updateZClient._comment_state_update  sl    ? l  MMj./(Igjj "  
 r6   c               r   r   r1   r2   r3   r4   r5   r     s     J Jg J$ Jr6   c                s   V ;_uu_ 4        \        VP                  4      p\        VP                  VP                  R7      pRRR4       V P                  X4      pRVP                  4       R,          9   #   + '       g   i     L;; i)a  This will delete the supplied comment provided you have the correct permissions.
This is an expensive request because if how moddb works. It needs to make two requests
in order to get the correct hash to delete the comment. In addition, it may fail if the
comment has changed location (page number) from what the object says. It is recommended
to use a newly created comment object that is less than 30 minutes old.

Parameters
-----------
comment : Comment
    The comment to delete

Raises
-------
ModdbException
    An error occured while trying to delete the comment

Returns
--------
bool
    True if the comment was successfully deleted
rX   Nz$You have <u>deleted</u> this commentrG   )r   _urlr   Zcommentsr9   r   r   rH   rB   r   Zupdated_commentr      &&   r4   delete_commentZClient.delete_comment  s`    , Tgll+D!$--GJJ?O  &&75&9III Ts   7A55B	c               r   r   r1   r2   r3   r4   r5   r     s     M M MD Mr6   c           	     s2   V ;_uu_ 4        \        VP                  4      p\        VP                  VP                  RR7      VP                  R7      pRRR4       V P                  X4      pRVP                  4       R,          9   #   + '       g   i     L;; i)a  This will undelete the supplied comment provided you have the correct permissions.
This is an expensive request because of how moddb works. It needs to make three requests
in order to get the correct hash to undelete the comment. In addition, it may fail if the
comment has changed location (page number) from what the object says. It is recommended
to use a newly created comment object that is less than 30 minutes old.

Parameters
-----------
comment : Comment
    The comment to undelete

Raises
-------
ModdbException
    An error occured while trying to undelete the comment

Returns
--------
bool
    True if the comment was successfully undeleted
T)Zshow_deletedrX   Nz'You have <u>authorized</u> this commentrG   )r   r   r   Z_get_comments_from_urlr9   r   r   r   r   r4   undelete_commentZClient.undelete_comment  st    , Tgll+D!++GLLt+L::O  &&78AFFHV<LLL Ts   ABB	c               r   )r/   rB   r#   new_textr   rx   ry   r1   r2   r3   r4   r5   r   /  s&     A AG As At Ar6   c           
     s    V P                  R\         R2RRRVP                  RV/R7      pRVP                  4       R	,          9   # )
ar  Edit the contents of a comment. You can only edit your comment 120 minutes after it has
been posted

Parameters
-----------
comment : Comment
    The comment to edit
new_text : str
    The new content of the comment

Raises
-------
ModdbException
    An error has occured trying to edit the comment

Returns
--------
bool
    True if the comment was successfully edited
r|   z/comment/ajax/postr}   r~   r9   r   r   zYour comment has been savedrG   r   )rH   rB   r   r   r   r4   edit_commentZClient.edit_comment/  sQ    * MMj*+#tWZZHE  
 -0@@@r6   rG   has_spoilersFc          
     s,    V ^8  d   QhRRRRRRRRR	R/# )
r/   r   r   ratingrD   rG   r   r   ry   rx   r1   r2   r3   r4   r5   r   L  s;     3@ 3@3@!$3@/23@IM3@	3@r6   c               s    ^Tu;8  d   ^	8  g   M Vf   \        R4      hV ;_uu_ 4        \        VP                  4      pRRR4       V P                  R\         R2RRR\        VP                  4      RVP                  R	VP                  R
\        VP                  P                  \        P                  8H  4      RVRVR\        V4      /RR7      pRVP                  4       R,          9   #   + '       g   i     L; i)ar  Rate and review a page. If you rating is below 3 or above 8 you will be asked
to also provide a review or else the request will not be made. This is also
used to edit existing reviews.

Parameters
-----------
page : Union[Mod, Game, Engine, Hardware, Software, Platform]
    The page you wish to review
rating : int
    The rating from 1 to 10
text : str
    The text review you are giving of this page
has_spoilers : bool
    Whether or not this review contains spoilers.

Raises
-------
ModdbException
    An error occured trying to review the page.

Returns
--------
bool
    True of the review was successfuly submitted.

Nz:Please include a review to justify such a low/high rating.r|   z/reviews/ajaxr}   r~   r   r   r   Zearlyaccessr   r   ZspoilerFr   zYour rating has been savedrG   )r   r   r<   r   r   r   r9   Z_review_hashrD   r   Zstatusr   Zearly_accessr   )rH   r   r   rG   r   r   s   &&&$$ r4   
add_reviewZClient.add_reviewL  s    : FQDL !]^^Tdhh'D  MMj&L2dgg))s4<<#6#6&:M:M#MN&43|,	 "  
  ,qvvx/???' Ts   C--C=	c               r   )r/   reviewr*   rx   ry   r1   r2   r3   r4   r5   r     s     $J $JF $Jt $Jr6   c                s<   V ;_uu_ 4        V P                   P                  4       ^ ,          pRRR4       V P                  R\         R2RRRRRR	R
VP                  RXP
                  R^/RR7      pRVP                  4       R,          9   #   + '       g   i     Lf; i)aP  Delete your review on the given page. This function will do two requests in order
to delete your review.

Parameters
-----------
review : Review
    The review you wish to delete

Raises
-------
ModdbException
    An error occured while trying to delete the review

Returns
--------
bool
    True if the review was successfully deleted
Nr|   r   r}   r~   r   r   r   Zreviewsr   r   ZispdFr   z$You have <u>deleted</u> this review.rG   )rE   Zget_reviewsr   r   r9   r   r   )rH   r   Zhash_reviewr   s   &&  r4   delete_reviewZClient.delete_review  s    & T++113A6K  MMj./(Ifii)) "  
 6&9III# Ts   "BB	c               s0    V ^8  d   QhRRRRRRRRRRR	R
/# )r/   queryr   readry   replied
sent_itemssortzTuple[str, str]rx   zList[ThreadThumbnail]r1   r2   r3   r4   r5   r     sN     B BB B 	B
 B B 
Br6   c                s<   V'       d   \          R2pM	\          R2pT P                  RTRRRTRVe   \        V4      MTRVe   \        V4      MTR	Ve   V^ ,           R
V^,           2MT/R7      p\        VP                  4      pVP                  RR.R7      R,          P                  RR.R7      p	. p
V	 F  pVP                  RRR7      P                  R4      ^ ,          pV
P                  \        VP                  R,          VP                  R,          \        \        P                  VP                  VR,          R7      \        VP                  R4      R,          4      VP                  RRR7      P                  R4      P                  R7      4       K  	  V
# )ay  Get all the messages this user has sent or received. This does not return threads you
have left.

Parameters
-----------
query : Optional[str]
    Optional query to filter messages
read : Optional[bool]
    True to filter only read message, false to filter unread, None to allow both
replied : Optional[bool]
    True to filter messages where you are the last message, False for messages
    where another user is the last message, None for both.
sent_items:
    Get only the threads you have started
sort : Tuple[str, str]
    Optional sort tuple to order threads

Returns
--------
List[ThreadThumbnail]
    Thread typed thumbnails
z/messages/sentitemsz/messages/inboxr   Zfilterr~   ZkwZhasreadZ
hasrepliedr   r   )paramsrA   Ztabinboxr8   Z
rowcontentrY   Z
subheadingr7   r:   r;   )r=   r>   r<   r?   r@   rg   rZ   )r<   r>   rf   rF   rg   rh   )r   r   rD   r!   rG   r_   rC   r   re   r7   r
   r   rE   r\   r   )rH   r   r   r   r   r   r<   r   r0   Zthreads_rawZthreadsrb   rE   s   &&&&&&       r4   get_threadsZClient.get_threads  s   < J12CJo.CMM#e(83t9dg.Ac'lw$2B47)1T!WI.  

 AFF|mmE:,m?CLL<. M 
 !F[[[=FFsKANFNN('*"+*116RX># 'v{{6'::'FG"KKiK@EEcJQQ
 " r6   c               r   )r/   rb   re   rx   rW   r1   r2   r3   r4   r5   r     s     $ $? $v $r6   c                sv    V P                  RVP                  4      p\        \        VP                  4      4      # )zParse a thread thumbnail into a full thread object.

Parameters
----------
thread : ThreadThumbnail
    The thumbnail to parse

Returns
--------
Thread
    The parsed thread and its messages
r   )r   r<   rW   r!   rG   rH   rb   r   rI   r4   parse_threadZClient.parse_thread  s+     MM%,d166l##r6   c               s(    V ^8  d   QhRRRRRRRR/# )r/   r`   zList[Member]r>   r   rc   rx   rW   r1   r2   r3   r4   r5   r     s(     $ $L $ $c $f $r6   c                s    V P                  R\         R2R\        4       RRP                  R V 4       4      RVRVR	R
/R7      p\	        \        VP                  4      4      # )aG  Send a message and start a thread with one or more members

Parameters
----------
member : List[Member]
    The members to send the message to and start the
    thread with
name : str
    The subject of the message
message : str
    The message to send

Returns
--------
Thread
    The thread started from sending this message
r|   z/messages/compose/r   Z	memberstoZ,c              3  s8   "   T F  qP                   x  K  	  R # 5i)Nr   )Z.0rE   r   r4   Z	<genexpr>Z&Client.send_message.<locals>.<genexpr>  s     %Hfkks   r>   descriptionra   Send+messager   )r   r   r   r   rW   r!   rG   )rH   r`   r>   rc   r   s   &&&& r4   send_messageZClient.send_message  si    $ MMj*+MOSXX%H%HHwN  

 d166l##r6   c               r   )r/   rb   Union[Thread, ThreadThumbnail]rG   r   rx   rW   r1   r2   r3   r4   r5   r     s#     $ $&D $C $TZ $r6   c           
     s    V P                  R\         RVP                   2R\        4       RVRR/R7      p\	        \        VP                  4      4      # )ah  Add an additional message to an exiting thread

Parameters
-----------
thread : Union[Thread, ThreadThumbnail]
    The thread to add the message to
text : str
    The text to send

Returns
--------
Thread
    The updated thread containing the new message. It is
    recommended to use this object as it also contains
    a new hash for sending another message
r|   z/messages/inbox/r   r   ra   r   r   )r   r   r9   r   rW   r!   rG   )rH   rb   rG   r   r   r4   reply_to_threadZClient.reply_to_thread  sU    " MMj(4mo}dJP^_  
 d166l##r6   c               r   )r/   rb   r   rE   r   rx   ry   r1   r2   r3   r4   r5   r   5  s)     A A+I ASY A^b Ar6   c           
     s    V P                  R\         RVP                   2RRRVP                  RR/RR	7      pR
VP	                  4       R,          9   # )a  Add a member to a conversation

Parameters
-----------
thread : Union[Thread, ThreadThumbnail]
    The thread to add add a member to
member : Member
    The member to add

Returns
--------
bool
    Whether adding the member was succesful. This
    will not update the thread.
r|   z/messages/ajax/members/invite/r}   r~   r   rE   Z0Fr   zhas been successfully addedrG   )r   r   r9   r>   r   )rH   rb   rE   r   r   r4   add_member_to_threadZClient.add_member_to_thread5  s\      MMj6vyykB#z6;;#F!	  
 -0@@@r6   c               r   )r/   rb   r   rx   ry   r1   r2   r3   r4   r5   r   N  s     X X#A Xd Xr6   c                s    V P                  R\         R2RRRVP                  /RR7      pRVP                  4       R	,          9   # )
zLeave a thread, you will not get any more notifications on this thread.

Parameters
----------
thread : Union[Thread, ThreadThumbnail]
    The thread to leave

Returns
--------
bool
    Whether leaving the thread was successful
r|   z/messages/ajax/delete/r}   r~   rb   Fr   z2You have successfully deleted the requested threadrG   r   r   rI   r4   leave_threadZClient.leave_threadN  sR     MMj./#x3!	  
 DqvvxPVGWWWr6   c               r-   rw   r1   r2   r3   r4   r5   r   d  s     
A 
At 
Ar6   c                sp    V P                  R\         R2RR/R7      pRVP                  4       R,          9   # )zbMark all threads as read.

Returns
--------
bool
    True if all threads have been marked as read
r|   z/messages/ajax/markallreadr}   r~   r   zAll messages marked as readrG   )r   r   r   r   r   r4   mark_all_readZClient.mark_all_readd  s=     MM&XJ.H"IQWY\P]M^,0@@@r6   c               r   )r/   tagr$   negativerD   r1   r2   r3   r4   r5   r   p  s     & &S &C &r6   c                	s    R RRVP                   R\        VP                  4      RVP                  R\	        4       R\        V4      /pV P                  R\         R2VR	7      pVP                  4       R
,          # )r}   r~   r   r   Zsiteareadidr   r   r|   z/tags/ajax/addr   Zsuccess)	Zname_idr   r   r   r   r   r   r   r   )rH   r   r   r   Zresps   &&&  r4   	_vote_tagZClient._vote_tagp  sl    C3;;s||43>>MOH
 }}Vz%@v}Nyy{9%%r6   c               r   r/   r   r$   rx   ry   r1   r2   r3   r4   r5   r   }  s     & &c &d &r6   c                s&    V P                  V^ 4      # )zUpvote a tag

Parameters
-----------
tag : Tag
    The tag to upvote

Returns
--------
bool
    Whether the upvote was successful
r   rH   r      &&r4   
upvote_tagZClient.upvote_tag}       ~~c1%%r6   c               r   r   r1   r2   r3   r4   r5   r     s     & & & &r6   c                s&    V P                  V^4      # )zDownvote a tag

Parameters
-----------
tag : Tag
    The tag to downvote

Returns
--------
bool
    Whether the downvote was successful
r   r   r  r4   downvote_tagZClient.downvote_tag  r  r6   )r   r   rE   )i   )NNNFN)+rQ   rR   rS   rT   rU   rJ   rO   r   r   r    r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  rV   r1   r6   r4   r   r     s   ,	
Y5' ~~. /(1f:6"H
:1@9@!9F9:G@H6B8 ,d ,  ,B*J<MBA:3@593@PU3@j$JLBH$"$@$2A2X,
A&&& &r6   r   )>Z
__future__r    r   r]   r   Ztypingr   r   r   r   r   r   Zbs4r   r   Zbaser   Zboxesr	   r
   r   Zenumsr   r   Zerrorsr   Zpagesr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   rW   re   rj   r   r   r1   r6   r4   <module>r     s    "  	 
 9 9     8 8 ( "      , # ==3 385A 5ApZ ZD 58Y 58 58p 1-i 1- 1-hH& H&r6   