+
     hü  c                  s   ^ RI Ht ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHtH	t	H
t
Ht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 ^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- ]'       d   ^RI.H/t/ . R.Ot0 ! R R4      t1 ! R R	4      t2 ! R R
4      t3 ! R R4      t4R t5R t6 ! R R]44      t7 ! R R4      t8 ! R R4      t9 ! R  R4      t: ! R! R4      t; ! R" R4      t< ! R# R4      t= ! R$ R4      t> ! R% R&]P~                  P                  4      tA ! R' R]A4      tB ! R( R]A4      tC ! R) R4      tD]P                  ! R*R+4      tF ! R, R-4      tGR# )/i    )annotationsN)TYPE_CHECKINGAnyListTupleUnion)BeautifulSoup)AddonCategoryArticleCategoryGenreGroupCategoryHardwareCategoryLicence
MembershipPlayerStyleScopeSearchCategorySoftwareCategoryStatusTeamCategoryThemeThumbnailType)BASE_URLLOGGERgenerate_hashgetget_dateget_list_statsget_pageget_page_typeget_siteareaid	get_viewsjoin	normalizetime_mappingunroll_numberArticle
StatisticsProfileStyle	ThumbnailCommentMissingCommentMemberProfileMemberStatisticsPlatformStatisticsPartialArticleOptionMirror
ResultListCommentListc                  s,    ] tR t^CtRtR R ltR tRtR# )r&   a  The stats box, on pages that have one. This represents total stats and daily stats in one
neat package.

Attributes
----------
files : int
    The number of files this page has uploaded
articles : int
    The number of articles this page has uploaded
reviews : int
    The number of reviews this page has been given
watchers : int
    The number of people following this page
mods : int
    The number of mods this page is related too (only applies to games, members and teams)
addons : int
    The number of addons this page has uploaded
members : int
    The number of members a group has (only applies to groups and teams)
visits : int
    The total number of times this page has been viewed
today : int
    The number of times this page has been viewed today
rank : int
    The current rank of the page against all other pages of the same type
total : int
    The maximum rank number
updated : datetime.datetime
    The last time this page was updated
c                   V ^8  d   QhRR/#    htmlr    Zformat   "0/usr/lib/python3.14/site-packages/moddb/boxes.py__annotate__ZStatistics.__annotate__c   s        ]      c                	sr   VP                  R RR7      pV P                  P                  V Uu/ uFM  q3P                  P	                  4       \        \        VP                  P                  P                  4      4      bKO  	  up4       \        VP                  R RR7      P                  P                  P                  4      p\        V4      w  V n        V n        \        VP                  R RR7      P                  P                  P                  4      P                  R4      p\        V^ ,          P                  RR4      4      V n        \        V^,          P                  RR4      4      V n         \#        VP                  RRR	7      R
,          4      V n        R# u upi   \&         d    RT n         R# i ; i)h5stringZVisitsRankof, timeZdateModifiedZitempropdatetimeN)ZFilesZArticlesZReviewsWatchersModsZAddonsZMembers)find_all__dict__updater@   lowerintr!   parentafindr   visitstodaysplitreplaceranktotalr   updated	TypeError)selfr7   miscstatrR   rV   s   &&    r;   __init__ZStatistics.__init__c   sV   }}  
 	SWXSW4[[ #i0D0D&E"FFSWX	
 499T(9;BBDDKKL"+F"3TZ47>>@@GGHNNtTQR01	ab12
	 #DIIf~I$Nz$Z[DL Y  	 DL	 s   AF1(F   F65F6c                	<    R V P                    RV P                   R2# )z<Statistics rank=/>rV   rW   rZ      &r;   __repr__ZStatistics.__repr__   s    "499+Qtzzl!<<r=   )rV   rS   rW   rX   rR   N__name__
__module____qualname____firstlineno____doc__r]   rd   __static_attributes__r8   r=   r;   r&   r&   C   s    > :=r=   c                  s,    ] tR t^tRtR R ltR tRtR# )r'   a 
  The profile object is used for several models and as such attribute vary based on which model
the profile is attached too. Profiles are only present on Mod, Game, Member, Addon, Engine, Company,
Hardware, Software and Group pages.

Parameters
-----------
html : bs4.BeautifulSoup
    The html to parse. Allows for finer control.

Attributes
-----------
category : Union[AddonCategory, HardwareCategory, SoftwareCategory, TeamCategory, GroupCategory, SearchCategory]
    The category the page falls under within the context of what the page is. E.g the page is an Addon category
    will be an AddonCategory enum. If the category of the page doesn't fall under any of the above mentionned
    the attribute will be of type SearchCategory.
contact : str
    The url to contact the page owner
follow : str
    The url to click to follow the mod
share : dict
    A dictionnary of share links with the place they will be shared as the key and the url
    for sharing as the value.
private : bool
    Exclusive to Group and Team, True if the group is private, else False
membership : Membership
    Exclusive to Group and Team, represents the join procedure (invitation only, private, public)
icon : str
    Exclusive to Game, Mod and Addon pages. URL of the icon image
developers : dict
    Exclusive to Game, Mods, Engine and Addon pages. Dictionnary of member/team like thumbnails as
    values and the role of the member/team as the key (creator, publisher, developer, ect...)
release : datetime.datetime
    Exclusive to Game, Mods, Engine and Addon pages. Datetime object of when the page was
    released, can be None if the page hasn't seen a release yet.
homepage : str
    Present on all pages but Group pages. URL to the page's homepage. Can be None
engine : Thumbnail
    Exclusive to Game and Addon pages. Engine like thumbnails representing the engine the addon/game
    was built for.
game : Thumbnail
    Exclusive to Mod pages. Game like thumbnail representing the game the mod was built for.
licence : Licence
    Exclusive to Engine and Addon pages. Object representing the licence the engine operates under.
platforms : List[Thumbnail]
    Exclusive to Game, Engine and Addon pages. List of platform like thumbnails representing
    the plaftorms the software was built for.
status : Status
    Exclusive to Games, Mods, Addons, Engines, Hardware .Whether the thing is released, unreleased, ect...
download_count: int
    Total count of all downloads on the page, this adds up downloads of all files and addons. Exclusive
    to mods and games.

c               r4   r5   r8   r9   r:   r;   r<   ZProfile.__annotate__   s     M M] Mr=   c           
     	sn    VP                  R RR7      P                  p TP                  RR	R
7      R,          pRp\        P                  ! YC4      pTP                  4        \        T^ ,          P                  R4      '       d
   T^ ,          MT^ ,          R,           ,          pY`n        TP                  RRR7      P                  P                  P                  P                  RRR7      p\        TP                  RRR7      P                  P                  P                  R,          4      T n        \        TP#                  R. R:OR7      ^ ,          P                  P                  P                  R,          4      T n         TP                  RRR7      P                  P                  P#                  R 4      pRT^ ,          R,          RT^,          R,          RT^,          R,          RT^,          R,          /T n        T\        P4                  \        P6                  39   d   TP                  RRR7      P                  P                  P                  P9                  4       R8g  T n        TP                  RRR7      P                  P                  P                  P9                  4       p	T	R8X  d   \=        ^4      T n        M(T	R 8X  d   \=        ^4      T n        M\=        ^4      T n        T\        P@                  \        PB                  \        PD                  39   d?    TP                  RR!R7      P                  P                  PF                  R",          T n$        T\        P@                  \        PB                  \        PJ                  \        PD                  \        PL                  \        PN                  39   Ed   TP#                  R. R;OR7      p
T
 Uu/ uF  pTP                  PQ                  4       \S        TP                  P                  R,          TP                  P                  P                  TP                  R$8w  d   \T        PV                  M\T        PX                  R%7      bK  	  upT n         TP                  RR&R7      P                  P                  PZ                  p\]        TR',          4      T n/        R)XP                  9   d   \b        Pd                  T n3        McR*TP                  9   d   \b        Ph                  T n3        M<R+TP                  9   d   \b        Pj                  T n3        M\b        Pl                  T n3        T\        PB                  8w  dy   TP                  RR,R7      P                  P                  P#                  R 4      pT Uu. uF0  p\S        TP                  TR,          \T        Pn                  R-7      NK2  	  upT n8        T\        P6                  8w  d?    TP                  RR.R7      P                  P                  P                  R,          T n9        T\        P@                  \        PD                  39   d   TP                  RR0R7      pTP                  P                  P                  R,          pTP                  P                  P                  P                  p\S        Y?\T        Pt                  R%7      T n:        T\        PB                  8X  d   TP                  RR1R7      pTP                  P                  P                  R,          pTP                  P                  P                  P                  p\S        Y?\T        Pv                  R%7      T n;        T\        PJ                  \        PD                  39   df   \y        \{        TP                  RR2R7      P                  P                  P                  R,          P}                  R34      R<,          4      4      T n?        T\        PL                  8X  df   \        \{        TP                  RR4R7      P                  P                  P                  R,          P}                  R34      R<,          4      4      T n        T\        PN                  8X  df   \        \{        TP                  RR4R7      P                  P                  P                  R,          P}                  R34      R<,          4      4      T n        T\        PD                  8X  df   \        \{        TP                  RR4R7      P                  P                  P                  R,          P}                  R34      R<,          4      4      T n        T\        P4                  8X  dK   TP                  R54      P                  P9                  4       PQ                  4       p \        T,          T n        T\        P6                  8X  dZ   TP                  R54      P                  P9                  4       PQ                  4       P                  R6R74      p\        T,          T n        T\        P@                  \        PB                  39   d9    \        TP                  R R8R7      P                  P                  4      T nG        R# R#   \         dg     TP                  RRR7      P                  p E
L  \         d7    TP                  RRR7      P                  P                  P                  p  E
Li ; ii ; i  \
         d2    \        TP                  R T P                  R7      R,          4      p ELi ; i  \        \(        3 dO    \*        P,                  ! RTP                  T\*        P.                  \0        P2                  8  R7       RT n         E	Li ; i  \         dE    RT n$        \*        P,                  ! R#TT\*        P.                  \0        P2                  8  R7        ELi ; iu upi   \`         dO    \*        P,                  ! R(TP                  T\*        P.                  \0        P2                  8  R7       RT n/         ELi ; iu upi   \         dO    RT n9        \*        P,                  ! R/TP                  T\*        P.                  \0        P2                  8  R7        ELi ; i  \`         d    \        ^4      T n         ELi ; i  \         dO    ^ T nG        \*        P,                  ! R9TP                  T\*        P.                  \0        P2                  8  R7        R# i ; i)=rP   mainEntityOfPagerF   spanZheadlinedivtitleclass_metaog:urlZpropertycontentr?   hrefz\/([a-z]+)\/sr'   table tablemenur>   ZContactZShareZredditZmailZtwitterZfacebookz(Something funky about share box of %s %sZexc_infoNZPrivacyZPublicZSubscriptionzOpen to all memberszMust apply to joinZIconsrcz%s '%s' does not have an iconCreatorurlnametypezRelease daterG   z%s %s has not been releasedZComingZEarlyZReleasedZ	Platformsr~   r}   r   Homepagez%s %s has no homepageZEngineZGamer   =ZCategoryZh3z & _Zdownloadautotogglez%s %s has no download count)z	Mod watchz
Game watchzGroup watchzEngine watchzHardware watchzSoftware watch)Z	DeveloperZ	PublisherzDeveloper & Publisherr{   ZCompany)HrQ   r@   AttributeErrorZh2rP   rY   r    r~   refindallZreverser   ZendswithcategoryrO   rm   contactrJ   followshare
IndexErrorr   infolevelloggingDEBUG
developersZgroupsstripprivater   
membershipZgamesZmodsZaddonsimgiconZenginesZ	hardwaresZ	softwaresrM   r)   r   ZteammemberrE   r   releaseKeyErrorr   Zcoming_soonstatusZearly_accessZreleasedZ
unreleasedZplatform	platformshomepageenginegamer   rN   rT   licencer   r   r   r   rU   r
   r#   download_count)rZ   r7   Z_namer}   ZregexZmatches	page_typeprofile_rawr   r   ZpeoplexZdr   r   r~   r   r   s   &&                r;   r]   ZProfile.__init__   sM
   	EIIc,>I?FFE	A))FX)6yAC  **U("1D1DS1I1I71:wWXz\_O_`	!iiyi9@@GGNNSS+ T 
 DIId9I=DDIIKKFST   ! 
 
 QQv
'
	$$T'$:AAFFOOPSTE%(6*a(58F+E!HV,	DJ 22N4I4IJJ  i 8??DDKKQQSW__ L %))$~)FMMRRYY__aJ22",Q-33",Q-",Q-  !!
 

	',,T&,AHHMMQQRWX	   ""!!$$$$
 
 !)) * 	F     A  )

6***/0xx9/D++-J^J^# 
  DO
$$$T.$AHHMMRR'*6 188#$00AHH$$11qxx'$oo$//N///',,T+,FMMRR[[\_`	 '"& 1886AWAWX&"
 ---	 $		$z	 B I I N N P PQW X --~/D/DEE %%d8%<F--$$&&v.C==%%''..D#]=Q=QRDK+++##D#8D++""$$V,C;;##%%,,D!c=;M;MNDI//1F1FGG"K$$T)$<CCHHJJ6RXXY\]^`abDL 000,K$$T*$=DDIIKKFSYYZ]^_abcDM 000,K$$T*$=DDIIKKFSYYZ]^_abcDM ---)K$$T*$=DDIIKKFSYYZ]^_abcDM 111yy--335;;=H0 ,X 6 ---yy--335;;=EEeSQH)(3DM--~/B/BCC&3IIc*>I?DDKK'# D}  	EE		&:	>EE! E		%	8;;==DDE	E  	AtyyTYYy7?@C	AF 
+ 	KK:6	 DJ	: "  	3#\\W]]:	 6  $1NN#\\W]]:	  $$(" "  $+NN#\\W]]:	 Z  0 ,Q0 " &'#1NN#\\W]]:	 s   j l A=m =n% Bo78Ao< 6q-=q 1r9 5s lj<<<k=8l<k==l8m ?m An"!n"%Ao43o4<AqqAr65r69ssAt43t4c                	s6    R V P                   P                   R2# )z<Profile category=r`   )r   r~   rb   rc   r;   rd   ZProfile.__repr__  s    #DMM$6$6#7q99r=   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   Nre   r8   r=   r;   r'   r'      s    4lM^:r=   c                  ,    ] tR tRtRtR R ltR tRtR# )r(   i  a  Represents semantic information on the page's theme.

Parameters
-----------
html : bs4.BeautifulSoup
    The html to parse. Allows for finer control.

Attributes
----------
theme : Theme
    fantasy, sci-fi, ect...
genre : Genre
    fps, rpg, moba, ect...
players : PlayerStyle
    Singplayer, multiplayer, ect...
scope : Scope
    Triple A games or indie
boxart : str
    URL of the boxart for the page.
c               r4   r5   r8   r9   r:   r;   r<   ZStyle.__annotate__  s     Q Q] Qr=   c           	     	s   VP                  R RR7      pV Uu/ uFT  q3P                  P                  4       \        P                  ! RVP
                  P                  R,          4      ^ ,          bKV  	  pp\        \        VR,          4      4      V n	        \        \        VR,          4      4      V n        \        \        VR,          4      4      V n         \        \        VP                  R RR7      P
                  P                  R,          R,          4      4      V n         VP                  R R	R7      P
                  P.                  P                  P0                  R
,          V n        R# u upi   \"         d;    \$        P&                  ! R\$        P(                  \*        P,                  8  R7        Li ; i  \"         d<    \$        P&                  ! R\$        P(                  \*        P,                  8  R7        R# i ; i)r>   r?   z(\d*)$rv   themegenreZProjectzHas no scopery   ZBoxartrz   zHas no boxartN)r   r	   ZPlayersr   )rJ   r@   rM   r   r   rO   rP   r   rN   r   r	   r   r   playersr   rQ   scoper   r   r   r   r   r   rm   r   boxart)rZ   r7   r[   ZstyleZstyles   &&   r;   r]   ZStyle.__init__  sw   }}T*G}H`d
`dW\LL "**Yv8N"OPQ"RR`d 	 
 3vg/0
3vg/0
"3vg#78	Ps499T)9#D#K#K#M#Mf#UVX#YZ[DJ	Q))D):AAFFHHLLUSDK
  	PKK1NO	P
  	QKK&,,'--2OPP	Qs.   AE+AE0 "AF8 0AF54F58AG>=G>c                	s    R V P                   P                   RV P                  P                   R\        V P                  4       R2# )z<Style genre=z theme=z	 players=r`   )r   r~   r   strr   rb   rc   r;   rd   ZStyle.__repr__  s?    DJJOO,GDJJOO3DIcRVR^R^N_M``ab	
r=   )r   r   r   r   r   Nre   r8   r=   r;   r(   r(     s    *Q(
r=   c                  s2    ] tR tRtRtR tR tR R ltRtR# )	r)   i  a  Thumbnail objects are minature version of ModDB models. They can be parsed to return the full
version of the model.

Attributes
-----------
url : str
    The url to the full model, mandatory attribute.
name : str
    The name of the model
image : str
    The optional thumbnail image of the model
summary : str
    Optional bit of fluff
date : datetime.datetime
    A date related to this timestamp if it exists. Can be None
type : ThumbnailType
    The type of the resource, mandatory attribute

c                	s(   \        VP                  R 4      4      V n        VP                  RR4      V n        VP                  RR4      V n        VP                  RR4      V n        VP                  RR4      V n        VP                  R4      V n        R# )r}   r~   Nimagesummarydater   )r    r   r}   r~   r   r   r   r   )rZ   attrs   &,r;   r]   ZThumbnail.__init__  so    UYYu-. %		&$ 7	!&7D!9
#(99Y#=.3ii.E	#(99V#4	r=   c                	sP    R V P                    RV P                  P                    R2# )<Thumbnail name= type=r`   )r~   r   rb   rc   r;   rd   ZThumbnail.__repr__  s$    !$))F499>>2B!DDr=   c               r4   )r6   returnr   r8   r9   r:   r;   r<   ZThumbnail.__annotate__  s     
Y 
Ys 
Yr=   c                s    \        \        P                  R,          V P                  P                  P                  4       4      ! \        V P                  4      4      # )zUses the Thumbnail's mandatory attributes to get the full html of the
model and parse them with the appropriate object.

Returns
--------
Any
    The model that was parsed, can be any model from the list of the ThumbnailType
    enum.
Zmoddb)ZgetattrsysZmodulesr   r~   ro   r   r}   rb   rc   r;   parseZThumbnail.parse  s9     s{{7+TYY^^-A-A-CDXdhhEWXXr=   )r   r   r~   r   r   r}   N)	rf   rg   rh   ri   rj   r]   rd   r   rk   r8   r=   r;   r)   r)     s    (5E
Y 
Yr=   c                s   V P                  R RR7      p VP                  R RR7      P                  R RR7      P                  R R.R7      p. p T F  pTP                  R4      pTP                  R4      pTP                  \	        TP
                  R,          TP
                  R	,          TP
                  P                  R
,          \        \        TP
                  R	,          4      4      T'       d   TP                  MRT'       d$   TP                  R8w  d   \        TR,          4      MRR7      4       K  	  \)        T4      w  rpTf   \+        T4      pY:Y3#   \         d
    . ^^^ 3u # i ; i  \        \        3 Ed
    \        P                  ! R\        P                  \         P"                  8  R7       \%        TR,          TR,          4       F  w  rxTP                  R4      pTP                  R4      P
                  p	TP                  \	        T	P&                  T	R	,          R\        \        T	R	,          4      4      TP&                  T'       d$   TP                  R8w  d   \        TR,          4      MRR7      4       K  	   ELRi ; i)rn   znormalbox browseboxrp   ZinnerZtableZ
rowcontentrE   Zpro   rv   rz   NZTBDrG   )r~   r}   r   r   r   r   z'Parsing articles as key-value pair listry   :NNr6   :i   Nr6   h4)rQ   rJ   r   appendr)   rP   r   r   r    r@   r   rY   r   r   r   r   r   r   Zziptextr   len)r7   Z
result_boxZsearch_rawsresultsZobjr   r   ro   ru   r}   current_page
total_pagetotal_resultss   &            r;   _parse_resultsr     s   5)>?JOOE'O2T%T(Xe\NX3 	 GC88F#DhhsmGNNwf%%))E*&tCEE&M':;.5GNN47;u@T$z"23Z^	 @ /=Z.H+LmG*;;S  1a{$ x  5PWP]P]@]	
 "+c"2K4EFNE::f%D**T"$$CNNF&tCK'89#LL7;u@T$z"23Z^	 Gs+   6E B7E0 2E0 E-,E-0DJ
Jc                sd   . pV P                  R RR7      pVf   . ^^^ 3# \        V4      w  r4p V P                  RRR7      R,          pVP                  R R.R7      P	                  R RRR7      pVf   \        V4      pV F  p\        V4      p	V RV 2V	n        V	P                  ^8X  d&    VR,          P                  P                  V	4       KP  V	P                  ^8X  d7    VR,          P                  R,          P                  P                  V	4       K  VP                  V	4       K  	  WWE3#   \         d(    \        T P                  RRR	7      R
,          4      p ELi ; i  \         dB    TP                  \        ^ 4      4       TR,          P                  P                  T	4        EK0  i ; i  \         d     TR,          P                  P                  \        ^4      4       TR,          P                  R,          P                  P                  T	4        EK    \         d    TP                  \        ^ 4      4       TR,          P                  P                  \        ^4      4       TR,          P                  R,          P                  P                  T	4         EK*  i ; ii ; i)rn   comments)idrr   rs   rt   ru   rP   rl   rF   rv   Ztablecommentsrp   ZrowF)rq   Z	recursive/page/r   )rQ   r   rY   r    rJ   r   r*   _urlpositionchildrenr   r   r+   )
r7   r   Zcomment_boxr   r   r   r}   Zcomments_rawZrawcomments
   &         r;   _parse_commentsr     sn   H))Ej)1K1a{.<[.I+LmHiii29= ##E?2C#DMMeu N L L)#,f\N3q 6%%,,W5 "	G%%b)2299'B OOG$+ . :<<A  H499S+=9>vFGH  6q 12%%,,W556  GGRL))001BCRL))"-66==gFF! GOON1$56RL))001BCRL))"-66==gFFG	GsP   D0 ,"E%"3F40.E"!E"%AF10F14J/ AH""BJ+%J/*J++J/c                  s2   a  ] tR tRtRtV 3R ltR tRtV ;t# )CommentAuthoriL  zRepresents the thumbnail of a user having left a comment on a page. Functions the same as a
thumbnail but with an extra attribute.

Attributes
-----------
comment_count : int
    Number of comments the user has posted
c                	sV   < \         SV `  ! R/ VB  VP                  R ^ 4      V n        R# )comment_countNr8   )Zsuperr]   r   r   )rZ   r   	__class__s   &,r;   r]   ZCommentAuthor.__init__V  s&    !5!"'))OQ"?r=   c                	sj    R V P                    RV P                  P                    RV P                   R2# )r   r   z comment_count=r`   )r~   r   r   rb   rc   r;   rd   ZCommentAuthor.__repr__[  s4    tyyk		/?tOaOaNbbcd	
r=   )r   )	rf   rg   rh   ri   rj   r]   rd   rk   Z__classcell__)r   s   @r;   r   r   L  s    @

 
r=   r   c                  s2    ] tR tRtRtR R ltR tR tRtR# )	r*   ia  a6  A moddb comment object.

Parameters
-----------
html : bs4.Tag
    The html to parse into the object. Must be the exact div of the comment.

Attributes
-----------
id : int
    The ID of the comment
author : Thumbnail
    A member like thumbnail of the member who posted the comment
date : datetime.datetime
    Date and time of the comment creation
position : int
    Ranging from 0-2 represents the nested level of the comment.
children : int
    Comment object replying directly to this one. If the comment is
    parsed on its own it will be null. It is only populated if originating
    from a CommentList
content : str
    Text of the comment can be none if the comment only contains embeds
embeds : list
    List of urls that have been embeded
karma : int
    The current karma count
upvote : str
    Link to upvote the comment
downvote : str
    Link to downvote the comment
approved : bool
    Whether or not the comment is still waiting for admin approval and is visible to the guest members
developer : bool
    Whether or not the comment was posted one of the page creators
staff : bool
    Wether or not the comment was posted by one of moddb's staff members
subscriber : bool
    Whether or not the comment was posted by a moddb subscriber
guest : bool
    Whether or not the comment was posted by a guest user
location : Thumbnail
    Thumbnail of the place the comment is, only available when getting comments from get_member_comments. This
    thumbnail does not guarantee that you will find the comment if you parse it, since the url does not
    contain the page number.
c               r4   r5   r8   r9   r:   r;   r<   ZComment.__annotate__  s     K K] Kr=   c                	sj	   VP                  R RR7      p\        VR,          4      V n        \        VP                  RRR7      P                  P	                  4       P                  R4      R%,          P                  RR4      P                  R	R4      4      p\        VR
,          VR,          VP                  R,          \        P                  VR7      V n        \        VP                  R4      R,          4      V n        VP                  RRR7      p\        P                  P                  4       V n        VR,          pRV9   d	   ^V n        MRV9   d	   ^V n        M^ V n        . V n         VP                  RRR7      P'                  R 4      pV F  pVR,          Vn        K  	  VP                  RRR7      P                  V n         VP:                  P(                  p\        \<        P>                  ! RV4      ^ ,          P                  R	R4      4      V n         \C        VP'                  R 4      ^,          R,          4      V n"        \C        VP'                  R 4      ^,          R,          4      V n#        RV n$        \M        VP                  RRR7      4      V n'        \M        VP                  RRR7      4      V n(        \M        VP                  RRR7      4      V n)        V P                  P2                  PU                  4       R8H  V n+        VP'                  R 4       U	u. uF  qR,          NK  	  up	V n,        VP                  R R!R7      V n-        V PZ                  eN   \C        V PZ                  R,          4      p
\]        V
4      p\_        V PZ                  P(                  WR"7      V n-         VP                  R R&R#7      R,          P                  R$4      R%,          V n0        R#   \,         dc    \.        P0                  ! RT P                  T P                  P2                  \.        P4                  \6        P8                  8  R7       RT n         ELi ; i  \,         d!    ^ T n         RT n"        RT n#        RT n$         EL \J         d    RT n#        RT n$         ELi ; iu up	i   \b         d    RT n0         R# i ; i)'rP   avatarrp   r   rm   Zheading-r   rD   rC   ro   rv   rz   )r~   r}   r   r   r   rE   rG   actionsZclassZreply1Zreply2rn   r   z-Comment %s by %s has no content, likely embedry   Nz[+-]?\dTF	developerstaff
subscriberguestZiframeZrelatedr   )ro   r   r   )ZDeleteZUndelete)2rQ   rN   r   r   r   rT   rU   r   r   r   r   authorr   r   rG   utcnow_fetch_timer   r   rJ   r@   ru   r   r   r   r~   r   r   r   rm   r   r   karmar    upvotedownvoteapprovedr   boolr   r   r   rM   r   embedslocationr   r)   _hashrY   )rZ   r7   r   r   r   r   ZlinksZlinkr   r   r}   r   s   &&          r;   r]   ZComment.__init__  s   3x0d4j/IIfYI/T%%'U3Z WZ$WS"
 $v**U#%%'
 TYYv.z:;	))F9)5#,,335=xDM!DMDM	 IIeII6??DE"6l 99U99=BBDL	!LL''ERZZ
E:1=EEc2NODJw//4Q7?@DK !1!1#!6q!9&!ABDM DM dii{iCD$))F7);<
tyyyEF[[%%++-8
)-x)@A)@Axx)@A		#i	8==$t}}V,-C%c*I%4==+?+?SYDM	3.DEfMSSTWXY[\DJM  	 KK?  6	  DL	   	"DJDK DM!DM 	! DM DM	! B  	DJ	sK   )AO B3Q R'5R A)Q
Q'R8RRRR21R2c                s    V P                   \        P                  ! ^R7      ,           \        P                  P                  4       8  # )a  Comments are very volatile. If they are pushed onto another page by other comments
it becomes impossible to use objects with the previous page number. In addition,
calculating the new page number is not possible. Pages do not have a defined size but
rather grow and shrink based on sizes of individual comments. Finally, comments
also have token that can be used to modify them. These tokens have a hard life of
30 minutes from the time of the request. This function puts in place several mechanism
to verify wether or not the object can still be trusted.


Returns
--------
bool
    True, the comment is stale and you should fetch a new version, False you **should**
    be good to continue using it.
)Zminute)r   rG   Z	timedeltar   rb   rc   r;   is_staleZComment.is_stale  s4    " ("4"4B"??(BSBSBZBZB\\\r=   c                	sj    R V P                   P                   RV P                   RV P                   R2# )z<Comment author=z
 position=z
 approved=r`   )r   r~   r   r   rb   rc   r;   rd   ZComment.__repr__  s7    t{{//0
4==/TXTaTaSbbcd	
r=   )r   r   r   r   r   ru   r   r   r   r   r   r   r   r   r   r   r   r   N)	rf   rg   rh   ri   rj   r]   r   rd   rk   r8   r=   r;   r*   r*   a  s    -^KZ]&
r=   c                  s,    ] tR tRtRtR tR tR tRtR# )r+   i  a  An object to represent a missing comment. This is used in the cases where a parent comment with
children is deleted so that the children may still be accessible, missing comment will have the
same attributes as a :class:`.Comment` but they will all be equal to None or False apart from children
and the comment position, which will have the children of the comment that was deleted attached to it.
c                	s    R V n         R V n        R V n        Wn        R V n        ^ V n        R V n        R V n        RV n        . V n	        RV n
        RV n        RV n        RV n        . V n        R V n        R # )NF)r   r   r   r   ru   r   r   r   r   r   r   r   r   r   r   r   )rZ   r      &&r;   r]   ZMissingComment.__init__  sp    	 


r=   c                	"    R V P                    R2# )z<MissingComment position=r`   )r   rb   rc   r;   rd   ZMissingComment.__repr__  s    *4==/;;r=   c                	    R # )Tr8   rb   rc   r;   r   ZMissingComment.is_stale  s    r=   )r   r   r   ru   r   r   r   r   r   r   r   r   r   r   r   r   N)	rf   rg   rh   ri   rj   r]   rd   r   rk   r8   r=   r;   r+   r+     s    &<r=   c                  r   )r,   i  aY  Member profiles are separate entities because they share nothing with the other profile boxes. Where as all
other profile boxes share at least 4 attributes, a member shares none.

Parameters
-----------
html : bs4.BeautifulSoup
    The html to parse. Allows for finer control.

Attributes
-----------
name : str
    Name of the member
level : int
    Current level
progress : float
    Percentage progress to next level
title : str
    Member title
avatar : str
    Url of the member avatar
online : bool
    Whether or not the member is currently online
last_online :  datetime.datetime
    None if the member is currently online, datetime the user was last seen online
gender : str
    Gender of the member, can be None
homepage : str
    URL of the member's homepage
country : str
    The member's chosen country
follow : str
    Link to follow a member
c               r4   r5   r8   r9   r:   r;   r<   ZMemberProfile.__annotate__;  s     6 6] 6r=   c                	s   VP                  R RR7      P                  P                  P                  P                  RRR7      pVP                  RRR7      P                  P                  P                  pVP                  RR	R
7      R,          V n        \        VP                  R RR7      P                  4      V n        \        RVP                  R RR7      P                  P                  P                  RR4      ,           4      V n        VP                  R RR7      P                  P                  V n        VP                  RRR7      P                  R,          V n        \!        VP                  RRR7      4      V n        VP                  RRR7      pV'       d1   \%        VP                  P                  P&                  R,          4      MRV n         VP                  RRR7      P                  P                  P                  P+                  4       V n         VP                  RRR7      P                  P                  P                  R,          V n         VP                  RRR7      P                  P                  P                  P+                  4       V n         \=        VP                  RRR7      P                  P                  P                  R,          4      V n        R#   \.         dN    \0        P2                  ! RT P                  \0        P                  \4        P6                  8  R7       RT n         EL#i ; i  \.         dN    RT n        \0        P2                  ! RT P                  \0        P                  \4        P6                  8  R7        EL@i ; i  \.         dN    RT n        \0        P2                  ! RT P                  \0        P                  \4        P6                  8  R7        ELVi ; i  \.         dC    \0        P2                  ! R \0        P                  \4        P6                  8  R7       RT n         R# i ; i)!rm   r'   r?   rn   rx   rp   r>   ZLevelrr   og:titlert   ru   r   z0.r   Z%rD   Z
avatarinforz   r   zLast OnlinerG   NZGenderz)Member %s has not publicized their genderry   r   rv   zMember %s has no homepageZCountryz=Member %s country is not visible (happens when not logged in)zMember watchz#Can't watch yourself, narcissist...) rQ   rO   rm   rn   r~   rN   r@   r   ZfloatZstrongrU   progressrP   ro   r   r   r   onliner   rE   last_onliner   genderr   r   r   r   r   r   countryr    r   )rZ   r7   r   Z	level_rawr   r   r;   r]   ZMemberProfile.__init__;  sP   iiyi9@@GGNNSS+ T 
  $$T'$:AAFFJJ	IIfzI:9E	w?FFG
9>>&>8??FFNNsTVWW
 ^^F6^:<<CC
!&&u\&BFFuM;++D+BC!&&tM&BBMH['',,11*=>SW 		%**4*AHHMMTTZZ\DK	 IId:I>EEJJLLVTDM	&++D+CJJOOVV\\^DL	{//^/LSSXXZZ[abcDK7  	KK;		6
 DK	  	 DMKK+TYYQXQ^Q^A^ 	  	DLKKO		6 	  	KK5PWP]P]@] DK		sO   AK# =L> AN AO4 #AL;:L;>ANNAO10O14A	Q Qc                	r   )z<MemberProfile name=r`   r~   rb   rc   r;   rd   ZMemberProfile.__repr__s  s    %dii[22r=   )r   r   r   r   r   r   r   r~   r   r   ro   Nre   r8   r=   r;   r,   r,     s     D6p3r=   c                  r   )r-   iw  a$  Similarly, a member statistics shared no common ground with other stats and therefore there was a
need for a separate object.

Parameters
-----------
html : bs4.BeautifulSoup
    The html to parse. Allows for finer control.

Attributes
-----------
watchers : int
    How many members are following this member
acivity_points : int
    Activity points
comments : int
    How many comments the member has made
tags : int
    How many tags the member has created
visits : int
    How many people have viewed this page
site_visits : int
    How many time this user has visited the site
today : int
    How many people have viewed this page today
time : int
    How many seconds the member has spent online
rank : int
    The member's current rank (compared to other members)
total : int
    the maximum rank
c               r4   r5   r8   r9   r:   r;   r<   ZMemberStatistics.__annotate__  s     _ _] _r=   c                	s   R  pVP                  RRR7      R,          pVP                  RRR7      pV P                  P                  V Uu/ uFP  pVP                  P                  4       P                  RR4      \        \        V! VP                  4      4      4      bKR  	  up4       \        VP                  RR	R7      P                  P                  P                  4      p\        V4      w  V n        V n        VP                  RR
R7      P                  P                  P                  P                  4       P!                  R4      w  rx\"        VP                  RR4      ,          \        V4      ,          V n         \        VP                  RRR7      P                  P                  P                  4      P!                  R4      p	\        V	^ ,          P                  RR4      4      V n        \        V	^,          P                  RR4      4      V n        R# u upi   \*         dK    ^ T n        ^ T n        \,        P.                  ! RT\,        P0                  \2        P4                  8  R7        R# i ; i)c                s    V P                   '       d%   V P                   P                  P                  4       # V P                  P                  P                  4       # N)rP   r@   r   rm   )rO   rc   r;   r   Z&MemberStatistics.__init__.<locals>.get  s9    .4hhh688??((*VFKK<N<N<T<T<VVr=   rr   r   rt   ru   r>   r?    r   ZVisitorszTime Onlinerw   rD   rA   rB   rC   zMember %s has no rankry   N)rH   zActivity PointsZCommentsZTagszSite visits)rQ   rJ   rK   rL   r@   rM   rU   rN   r!   rO   rP   r   rR   rS   rm   r   rT   r"   rE   rV   rW   r   r   r   r   r   r   )
rZ   r7   r   r~   r[   r\   rR   rE   ZmappingrV   s
   &&        r;   r]   ZMemberStatistics.__init__  s   	W yy*y5i@}}U  
 	 ! D !!#++C5s9SEU;V7WW 	
 499T*9=DDFFMMN"+F"3TZ		$}	=DDIIPPVVX^^_bc b!9:SYF		_TYYtFY;BBGGNNOUUVZ[DDGOOC45DIT!W__S"56DJ   	_DIDJKK/PWP]P]@]^^	_s   
AH<BH AI/.I/c                	r^   )z<MemberStatistics rank=r_   r`   ra   rb   rc   r;   rd   ZMemberStatistics.__repr__  s    (1TZZLBBr=   )rV   rE   rS   rW   rR   Nre   r8   r=   r;   r-   r-   w  s    @_>Cr=   c                  r   )r.   i  a  Stats for platform pages.

Parameters
-----------
html : bs4.BeautifulSoup
    The html to parse. Allows for finer control.

Attributes
-----------
hardware : int
    Number of harware created for this platform
software : int
    Number of software created for this platform
engines : int
    Number of engines created for this platform
games : int
    Number of games created for this platform
mods : int
    Number of mods created for this platform
c               r4   r5   r8   r9   r:   r;   r<   ZPlatformStatistics.__annotate__  s     
 
] 
r=   c                	sL   RpVP                  RVR7      pV P                  P                  V Uu/ uFc  pW#P                  V4      ,          P	                  4       \        \        VP                  P                  P                  P                  4      4      bKe  	  up4       R# u upi )Hardwarer>   r?   N)r   ZSoftwareZEnginesZGamesrI   )rJ   rK   rL   indexrM   rN   r!   rO   rm   rP   r@   )rZ   r7   ZheadingsZhtml_headingsr   r   r;   r]   ZPlatformStatistics.__init__  s    Gd8< '&A ,,Q/0668#iH^H^>_:``&	
s   A)B!c                	r   )z<PlatformStatistics>r8   rb   rc   r;   rd   ZPlatformStatistics.__repr__  s    %r=   r8   Nre   r8   r=   r;   r.   r.     s    *
&r=   c                  8    ] tR tRtRtR R ltR tR R ltRtR	# )
r/   i  a  A partial article is an article object missing attributes due to being parsed from the front page
intead of from the article page itself. In general, it' is simple enough for previewing the article
but if you need a full article with comments, profile, ect... Then parse it with the method

Parameters
-----------
html : bs4.BeautifulSoup
    The html to parse. Allows for finer control.

Attributes
-----------
name : str
    Name of the articles
url : str
    Link to the article
date : datetime.datetime
    Date the article was published
type : ArticleCategory
    Type of the article
content : str
    html of the article content
plaintext : str
    plaintext of the article content (without html)
c               r4   r5   r8   r9   r:   r;   r<   PartialArticle.__annotate__  s     & &] &r=   c                	s   VP                  R RR7      pVP                  P                  P                  V n        \        VP                  P                  R,          4      V n        \        VP                  R4      R,          4      V n         \        VP                  RRR7      P                  P                  4       P                  R4      ^ ,          P                  4       ,          V n        VP                  R R	R7      p\#        V4      V n        VP                  V n        R
#   \         d    \        P                   T n         LXi ; i)rn   zrow rowcontent rownoimage clearrp   rv   rE   rG   rm   Z
subheadingr   z#row rowcontent rowcontentnext clearN)rQ   r   rP   r@   r~   r    r}   r   r   r   r   r   rT   rM   r   r   Znewsr   ru   	plaintext)rZ   r7   Zmeta_rawru   s   &&  r;   r]   ZPartialArticle.__init__  s    99U+L9MKKMM((	f-.X]]62:>?		-'f\:??EEGMMcRSTU[[]DI ))E*O)P7|   	-',,DI	-s   AD    EEc                	r   )z<PartialArticle title=r`   r   rb   rc   r;   rd   ZPartialArticle.__repr__
  s    '		{!44r=   c               r4   )r6   r   r%   r8   r9   r:   r;   r<   r     s     
+ 
+W 
+r=   c                sD    ^RI Hp V! \        V P                  4      4      # )zkReturns the full article object of this article.

Returns
--------
Article
    The complete article object
r$   )pages.articler%   r   r}   )rZ   r%   s   & r;   get_articleZPartialArticle.get_article  s     	+x)**r=   )ru   r   r~   r   r   r}   N)	rf   rg   rh   ri   rj   r]   rd   r   rk   r8   r=   r;   r/   r/     s    2&"5
+ 
+r=   c                  &    ] tR tRtRtR tR tRtR# )r0   i  a  Represents one of the choice from the poll they are attached to, should not be created
manually, prefer relying on the Poll.

Attributes
-----------
id : int
    The id of the option, can be None and will be None in most cases.
text : str
    The option's text
votes : int
    The number of votes that have been cast on this option
percent : int
    The percent of all votes that have been cast on this option
c                	s    VP                  R R4      V n        VP                  R4      V n        VP                  R4      V n        VP                  R4      V n        R# )r   Nr   votespercent)r   r   r   r   r   rZ   kwargsr   r;   r]   ZOption.__init__*  sD    **T4(JJv&	ZZ(
zz),r=   c                	r   )z<Option text=r`   )r   rb   rc   r;   rd   ZOption.__repr__0  s    tyyk++r=   )r   r   r   r   Nre   r8   r=   r;   r0   r0     s    -,r=   c                  s    ] tR tRtRtR tR R ltR tR R ltR	 R
 lt	R R lt
R tR tR tR tR tR tR tRtR# )	ModDBListi4  zBase List type for the lib

Attributes
-----------
current_page : int
    The page of results this objects represents
total_pages : int
    The total amount of result pages available
total_results : int
    The total amount of results available
c                	s   VP                  R 4      V n        VP                  R/ 4      V n        VP                  R4      V n        VP                  R4      V n        VP                  R4      V n        VP                  R4      V n        R# )r   paramsr}   total_pagesr   r   N)pop_results_paramsr   r   r   r   r   r   r;   r]   ZModDBList.__init__A  sg    

9-zz(B/JJu%	!::m4"JJ~6#ZZ8r=   c               r4   r5   r8   r9   r:   r;   r<   ModDBList.__annotate__I  s     " "- "r=   c                	s    \         hr   )ZNotImplementedErrorrZ   r7   r   r;   _parse_methodZModDBList._parse_methodI  s    !!r=   c           	     	s    VP                  R V P                  4      p/ V P                  CVCp\        V P                   RV 2VR7      pV P                  V4      w  rVrxV P                  VVV P                  VVVR7      # )pager   r   )r   r   r}   r   r   r   )r   r   r   r   r   r   r   )	rZ   r   r   r   r7   r   r   r   r   s	   &,       r;   _do_requestZModDBList._do_requestL  s    zz&$"3"34+DLL+F+499+VD626B<@<N<Nt<T9{~~		#%'  
 	
r=   c               r4   r6   r   "Union['ResultList', 'CommentList']r8   r9   r:   r;   r<   r   \  s     3 3= 3r=   c                s    V P                   V P                  8X  d   \        R4      hV P                  V P                   ^,           4      # )a-  Returns the next page of results as either a CommentList if you are retriving comments or
as a ResultList if it's literally anything else.

Returns
--------
Union[ResultList, CommentList]
    The new search objects containing a new set of results.

Raises
-------
ValueError
    There is no next page
zReached last page already)r   r   
ValueErrorto_pagerb   rc   r;   	next_pageZModDBList.next_page\  s>      0 00899||D--122r=   c               r4   r  r8   r9   r:   r;   r<   r   o  s     3 3A 3r=   c                s~    V P                   ^8X  d   \        R4      hV P                  V P                   ^,
          4      # )a"  Returns the previous page of results as either a CommentList if you are retriving comments or
as a ResultList if it's literally anything else.

Returns
--------
Union[ResultList, CommentList]
    The new list-like object of results.

Raises
-------
ValueError
    There is no previous page
zReached first page already)r   r  r  rb   rc   r;   previous_pageZModDBList.previous_pageo  s8     !9::||D--122r=   c                    V ^8  d   QhRRRR/# )r6   r   rN   r   r  r8   r9   r:   r;   r<   r     s     + +C +$F +r=   c                s    V^8  g   WP                   8  d   \        RV P                    24      hV P                  VR7      # )a}  Returns the desired page of results as either a CommentList if you are retriving comments or
as a ResultList if it's literally anything else.

Parameters
-----------
page : int
    A page number within the range 1 - max_page inclusive

Returns
--------
Union[ResultList, CommentList]
    The new list-like object of results.

Raises
-------
ValueError
    This page does not exist
z!Please pick a page between 1 and )r   )r   r  r   )rZ   r   r   r;   r  ZModDBList.to_page  sD    & !8t...@AQAQ@RSTTT**r=   c                s|   V P                  ^4      p\        V4      p  VP                  4       pVP                  V4       \        P
                  ! RVP                  VP                  4       KQ    \         d     Mi ; iR p\        T Uu/ uF  qC! T4      TbK  	  Mu upi upP                  4       4      Tn
        T# )a/  An expensive methods that iterates over every page of the result query and returns all
the results. This may return more results than you expected if new page have fit the criteria
while iterating.

Returns
--------
Union[CommentList[Any], ResultList[Any]]
    The list of things you were searching for
zParsed page %s/%sc                s^    \        V \        4      '       d   V P                  # V P                  # r   )Z
isinstancer*   r   r~   )elementrc   r;   keyZ&ModDBList.get_all_results.<locals>.key  s#    '7++zz!||#r=   )r  Zlistr  extendr   r   r   r   r  Zvaluesr   )rZ   Zsearchr   r	  Zes   &    r;   get_all_resultsZModDBList.get_all_results  s     av,Z))+ v&/1D1DfFXFXY	  	$ 7;7aA	7;BBDEs   A. .A<;A<Bc           	     	s    R V P                   P                   RV P                   RV P                   RV P                   R2	# )Z<z pages=r_   z
, results=r`   )r   rf   r   r   r   rb   rc   r;   rd   ZModDBList.__repr__  sF    4>>**+743D3D2EQtGWGWFXXbcgcpcpbqqrssr=   c                	s8    V P                   P                  V4      # r   )r   __getitem__rZ   r  r   r;   r  ZModDBList.__getitem__  s    }}((11r=   c                	s<    V P                   P                  V4       R # r   )r   __delitem__r  r   r;   r  ZModDBList.__delitem__  s    !!'*r=   c                	s6    V P                   P                  4       # r   )r   __len__rb   rc   r;   r  ZModDBList.__len__  s    }}$$&&r=   c                	<    V P                   P                  W4       R # r   )r   __setitem__)rZ   r	  value   &&&r;   r  ZModDBList.__setitem__  s    !!#-r=   c                	r  r   )r   insert)rZ   r   r  r  r;   r  ZModDBList.insert  s    U*r=   )r   r   r   r   r   r   N)rf   rg   rh   ri   rj   r]   r   r   r  r  r  r  rd   r  r  r  r  r  rk   r8   r=   r;   r   r   4  sI    
9"
 3&3&+0>t2+'.+r=   r   c                  s8    ] tR tRtRtR R ltR R ltR tRtR	# )
r2   i  a.  Represents a list of result gotten from one of the many get methods the library uses. This is returned
over a regular list because it has additional methods that allow for easily go through all the results. In
the same way that the moddb site works, you don't have to re-run the query manually to get the next page,
you simply click a button, same here, you don't have to recall the base get method, simply use on of the
methods here to traverse the results. This emulates a list and will behave like one, so you
can use any of the regular list operators in addition to the methods defined below

Attributes
-----------
current_page : int
    The page of results this objects represents
total_pages : int
    The total amount of result pages available
total_results : int
    The total amount of results available
c               r4   r5   r8   r9   r:   r;   r<   ResultList.__annotate__  s     $ $- $r=   c                	    \        V4      # r   )r   r   r   r;   r   ZResultList._parse_method  s    d##r=   c               r  )r6   new_sortzTuple[str, str]r   z'ResultList'r8   r9   r:   r;   r<   r    s     E E E< Er=   c                sL    V P                  V^ ,           RV^,           2R7      # )a
  Allows you to sort the whole search by a new sorting parameters. Returns a new search object.

Parameters
-----------
new_sort : Tuple[str, str]
    The new sorting tuple to check by

Returns
-------
ResultList
    The new set of results with the updated sort order
r   )Zsort)r   )rZ   r  r   r;   resortZResultList.resort  s+     }Ahqk]%CDDr=   c                	H    \        V P                  VP                  R 7      RJ# r   Nr   r   r~   r  r   r;   __contains__ZResultList.__contains__      4==w||4D@@r=   r8   N)	rf   rg   rh   ri   rj   r   r  r  rk   r8   r=   r;   r2   r2     s    "$EAr=   c                  r   )
r3   i  a  Represents a list of comments. This emulates a list and will behave like one, so you
can use any of the regular list operators in addition to the methods defined below.

Attributes
-----------
current_page : int
    The page of results this objects represents
total_pages : int
    The total amount of result pages available
total_results : int
    The total amount of results available
c               r4   r5   r8   r9   r:   r;   r<   CommentList.__annotate__  s     % %- %r=   c                	r  r   )r   r   r   r;   r   ZCommentList._parse_method  s    t$$r=   c                	r  r  r  r  r   r;   r  ZCommentList.__contains__  r  r=   c               r4   )r6   r   zList[Comment]r8   r9   r:   r;   r<   r    s       r=   c                s    . pV P                    FS  pVP                  V4       VP                   F/  pVP                  V4       VP                  VP                  4       K1  	  KU  	  V# )uj  Returns a 'flattened' list of comments where children of comments are added right
after the parent comment so:

[ Comment1 ]
    ├── Comment2

    |   ├── Comment3

    |   └── Comment4

    └── Comment5

would become:

[Comment1, Comment2, Comment3, Comment4, Comment5]

Returns
--------
List[Comment]
    The flattened list of comments
)r   r   r   r
  )rZ   Ztop_listr   Zchild   &   r;   flattenZCommentList.flatten  sV    & }}GOOG$ ))&/ * % r=   r8   N)	rf   rg   rh   ri   rj   r   r  r   rk   r8   r=   r;   r3   r3     s    %A r=   c                  r   )r1   i%  a  Represents a download mirror from which the user can download a file

Attributes
-----------
name : str
    The name of the mirror
index : int
    The index of the mirror, as multiple mirrors
    have the same name. Index starts at 1
city : str
    Alpha 2 code, or full name, of the city the server is located
    in. Sometimes represents a country.
country : str
    Alpha 2 code for the country the server is
    located in. Sometimes represents a continent.
served : int
    How many downloads of this file this mirror has
    served
capacity : float
    The current capacity of this server as a percentage.
    E.g. 35.5 -> 35.5%. Lower is better for speed.
c                	s:   VP                  R 4      V n        VP                  R4      V n        VP                  R4      V n        VP                  R4      V n        VP                  R4      V n        VP                  R4      V n        VP                  R4      V n        R# )r~   r   cityr   servedcapacityr}   N)r   r~   r   r!  r   r"  r#  r   r   r   r;   r]   ZMirror.__init__=  sr    JJv&	ZZ(
JJv&	zz),jj*

:.JJu%	r=   c                	r^   )z<Mirror name=z index= >)r~   r   rb   rc   r;   rd   ZMirror.__repr__F  s    tyykB??r=   )r   r#  r!  r   r   r~   r"  Nre   r8   r=   r;   r1   r1   %  s    .&@r=   
PartialTagzname name_id urlc                  s2    ] tR tRtRtR tR R ltR tRtR# )	TagiM  a  Represents a tag, useful to vote on stuff

Parameters
-----------
id : Optional[int]
    ID of the tag. None if obtained from parsing a page
name_id : str
    Name id of the tag
name : str
    Name of the tag
date : Optional[datetime.datetime]
    Creation date of the tag. None if obtained from parsing a page
official : Optional[bool]
    Whether the tag is official or user created. None if obtained from parsing a page
sitearea : int
    Site area
siteareaid : int
    Site area id
positive : int
    Number of positive votes
negative : int
    Number of negative votes
rank : Optiona[int]
    Rank of the tag in trending. None if obtained from parsing a page
url : str
    Url to the tag
c                	s   \        VP                  R 4      4      V n        \        P                  P	                  \        VP                  R4      4      4      V n        VP                  R4      R8H  V n        \        VP                  R4      4      V n        \        VP                  R4      4      V n        \        VP                  R4      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      4      V n        \         RV P                   2V n        R# )r   r   officialZ1sitearea
siteareaidpositivenegativeZtagidtagZtrendingz/tags/N)rN   r   r   rG   Zfromtimestampr   r'  r(  r)  r*  r+  name_idr~   rV   r   r}   r   r   r;   r]   ZTag.__init__j  s    fjj&'%%33C

68J4KL	

:.#5FJJz23fjj67FJJz23FJJz23zz'*JJu%	

:./	Zvdll^4r=   c               r4   )r6   r   r   r8   r9   r:   r;   r<   ZTag.__annotate__y  s     > ># >r=   c                	r^   )z	< Tag id=z	 name_id=r$  )r   r-  rb   rc   r;   rd   ZTag.__repr__y  s    477)9T\\N"==r=   c                s   \         P                  ! R4       RRRV P                  R\        V P                  4      RV P
                  R\        4       /p\        \         R2VR	7      pVP                  R
RR7      P                  R4       Uu. uF9  p\        \        VR,          4      VP                  \        P                  R7      NK;  	  up# u upi )z}Get a list of the members that have voted for this tag

Returns
---------
List[Thumbnail]
    List of member typed thumbnail
z>_get_members is undocumented and unreliable for the time beingZajaxZtr,  r(  r)  Zhashz/tags/ajax/whor   rn   Zsuccessboxachtungrp   rP   rv   r|   )r   Zwarningr-  r   r(  r)  r   r   r   rQ   rJ   r)   r    r@   r   r   )rZ   r   ZrespZthumbr  r;   _get_membersZTag._get_members|  s     	WXC4<<t}}5$//MO
 8*N3FC 51DENNsS
S $uV}-ELL}G[G[\S
 	
 
s   
?C)r   r   r~   r-  r+  r'  r*  rV   r(  r)  r}   N)	rf   rg   rh   ri   rj   r]   rd   r.  rk   r8   r=   r;   r&  r&  M  s    85>
r=   r&  )r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   )HZ
__future__r    ZcollectionsrG   r   r   r   Ztypingr   r   r   r   r   Zbs4r   Zenumsr   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   Zutilsr   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r   r%   Z__all__r&   r'   r(   r)   r   r   r   r*   r+   r,   r-   r.   r/   r0   ZabcZMutableSequencer   r2   r3   r1   Z
namedtupler%  r&  r8   r=   r;   <module>r/     s[   "    	 
 9 9     "   " &$>= >=BG: G:T-
 -
`*Y *YZ1<h*=Z
I 
*S
 S
l B\3 \3~AC ACH!& !&H8+ 8+v, ,4U+// U+p%A %AP.) .b"@ "@J ##L2DE
E
 E
r=   