2828
2929from .enums import HubType , try_enum
3030from .metadata import Metadata
31- from .utils import SequenceProxy , SnowflakeList , murmurhash32
31+ from .utils import SequenceProxy , SnowflakeList , murmurhash32 , utcnow
3232
3333if TYPE_CHECKING :
3434 from .abc import Snowflake
@@ -126,6 +126,7 @@ class ExperimentFilters:
126126 FILTER_KEYS : Final [Dict [int , str ]] = {
127127 1604612045 : 'guild_has_feature' ,
128128 2404720969 : 'guild_id_range' ,
129+ 3730341874 : 'guild_age_range_days' ,
129130 2918402255 : 'guild_member_count_range' ,
130131 3013771838 : 'guild_ids' ,
131132 4148745523 : 'guild_hub_types' ,
@@ -143,7 +144,16 @@ def __init__(self, population: ExperimentPopulation, data: FiltersPayload):
143144 self .options : Metadata = self .array_object (data )
144145
145146 def __repr__ (self ) -> str :
146- keys = ('features' , 'id_range' , 'member_count_range' , 'ids' , 'range_by_hash' , 'has_vanity_url' )
147+ keys = (
148+ 'features' ,
149+ 'id_range' ,
150+ 'age_range' ,
151+ 'member_count_range' ,
152+ 'ids' ,
153+ 'hub_types' ,
154+ 'range_by_hash' ,
155+ 'has_vanity_url' ,
156+ )
147157 attrs = [f'{ attr } ={ getattr (self , attr )!r} ' for attr in keys if getattr (self , attr ) is not None ]
148158 if attrs :
149159 return f'<ExperimentFilters { " " .join (attrs )} >'
@@ -168,7 +178,7 @@ def array_object(cls, array: list) -> Metadata:
168178 return metadata
169179
170180 @staticmethod
171- def in_range (num : int , start : Optional [int ], end : Optional [int ], / ) -> bool :
181+ def in_range (num : float , start : Optional [float ], end : Optional [float ], / ) -> bool :
172182 if start is not None and num < start :
173183 return False
174184 if end is not None and num > end :
@@ -189,6 +199,13 @@ def id_range(self) -> Optional[Tuple[Optional[int], Optional[int]]]:
189199 if id_range_filter is not None :
190200 return id_range_filter .min_id , id_range_filter .max_id
191201
202+ @property
203+ def age_range (self ) -> Optional [Tuple [Optional [int ], Optional [int ]]]:
204+ """Optional[Tuple[Optional[:class:`int`], Optional[:class:`int`]]]: The range of guild ages that are eligible for the population."""
205+ age_range_filter = self .options .guild_age_range_days
206+ if age_range_filter is not None :
207+ return age_range_filter .min_id , age_range_filter .max_id
208+
192209 @property
193210 def member_count_range (self ) -> Optional [Tuple [Optional [int ], Optional [int ]]]:
194211 """Optional[Tuple[Optional[:class:`int`], Optional[:class:`int`]]]: The range of guild member counts that are eligible for the population."""
@@ -253,6 +270,12 @@ def is_eligible(self, guild: Guild, /) -> bool:
253270 if not self .in_range (guild .id , * id_range ):
254271 return False
255272
273+ age_range = self .age_range
274+ if age_range is not None :
275+ # Guild must be within the range of ages (in days)
276+ if not self .in_range ((utcnow () - guild .created_at ).days , * age_range ):
277+ return False
278+
256279 member_count_range = self .member_count_range
257280 if member_count_range is not None and guild .member_count is not None :
258281 # Guild must be within the range of member counts
0 commit comments