@@ -252,7 +252,7 @@ async function hasIcebreakerLinkedAccount({ user: member, rule }: CheckFunctionA
252252 } ;
253253}
254254
255- async function hasGreaterThanVerifiedTwitterFollowers ( { user : member , rule } : CheckFunctionArgs ) {
255+ async function hasVerifiedTwitterFollowersGreaterThan ( { user : member , rule } : CheckFunctionArgs ) {
256256 const { threshold } = rule . args as { threshold : string } ;
257257
258258 if ( ! threshold || isNaN ( + threshold ) ) {
@@ -271,14 +271,14 @@ async function hasGreaterThanVerifiedTwitterFollowers({ user: member, rule }: Ch
271271 message : `@${ member . username } not found in Icebreaker` ,
272272 } ;
273273 }
274- // get twitter followers for user verified twitter account
274+
275275 const verifiedTwitterAccount = user . channels ?. find (
276276 ( channel ) => channel . type === "twitter" && channel . isVerified
277277 ) ?. value ;
278278
279279 const metadata = verifiedTwitterAccount ? await getTwitterMetadata ( verifiedTwitterAccount ) : undefined ;
280280
281- const followerCount = metadata && extractTwitterFollowerCount ( metadata ) ;
281+ const followerCount = extractTwitterFollowerCount ( metadata ) ;
282282
283283 const userHasGreaterThanThreshold = ! ! followerCount && followerCount > thresholdNumber ;
284284
@@ -292,6 +292,56 @@ async function hasGreaterThanVerifiedTwitterFollowers({ user: member, rule }: Ch
292292 } ;
293293}
294294
295+ async function hasVerifiedTwitterCreatedBefore ( { user : member , rule } : CheckFunctionArgs ) {
296+ const { threshold } = rule . args as { threshold : string } ;
297+
298+ const isValidDateFormat = ( dateString : string ) => {
299+ const regex = / ^ \d { 4 } - \d { 2 } - \d { 2 } $ / ;
300+ if ( ! regex . test ( dateString ) ) return false ;
301+
302+ const date = new Date ( dateString ) ;
303+ return dateString === date . toISOString ( ) . split ( "T" ) [ 0 ] ;
304+ } ;
305+
306+ // Check if threshold can be parsed as a valid date
307+ if ( ! threshold || ! isValidDateFormat ( threshold ) ) {
308+ return {
309+ result : false ,
310+ message : "Invalid threshold value. Please provide a valid date." ,
311+ } ;
312+ }
313+
314+ const thresholdDate = new Date ( threshold ) ;
315+
316+ const user = await getIcebreakerbyFid ( member . fid ) ;
317+
318+ if ( ! user ) {
319+ return {
320+ result : false ,
321+ message : `@${ member . username } not found in Icebreaker` ,
322+ } ;
323+ }
324+
325+ const verifiedTwitterAccount = user . channels ?. find (
326+ ( channel ) => channel . type === "twitter" && channel . isVerified
327+ ) ?. value ;
328+
329+ const metadata = verifiedTwitterAccount ? await getTwitterMetadata ( verifiedTwitterAccount ) : undefined ;
330+
331+ const createdAt = extractTwitterCreatedAt ( metadata ) ;
332+
333+ const userHasGreaterThanThreshold = ! ! createdAt && createdAt < thresholdDate ;
334+
335+ return {
336+ result : userHasGreaterThanThreshold ,
337+ message : createdAt
338+ ? `@${ member . username } created Twitter account on ${ createdAt . toDateString ( ) } `
339+ : metadata
340+ ? `Unable to retrieve created date for @${ member . username } `
341+ : `Unable to find a verified Twitter account for @${ member . username } ` ,
342+ } ;
343+ }
344+
295345async function hasPOAP ( { user : member , rule } : CheckFunctionArgs ) {
296346 const { eventId } = rule . args as { eventId : string } ;
297347
@@ -344,9 +394,10 @@ type RuleName =
344394 | "hasIcebreakerQBuilder"
345395 | "hasIcebreakerVerified"
346396 | "hasIcebreakerLinkedAccount"
347- | "hasPOAP"
348397 | "hasGuildRole"
349- | "hasGreaterThanVerifiedTwitterFollowers" ;
398+ | "hasPOAP"
399+ | "hasVerifiedTwitterCreatedBefore"
400+ | "hasVerifiedTwitterFollowersGreaterThan" ;
350401
351402const author = "Icebreaker" ;
352403const authorUrl = "https://icebreaker.xyz" ;
@@ -458,29 +509,56 @@ export const iceBreakerRulesDefinitions: Record<RuleName, RuleDefinition> = {
458509 } ,
459510 } ,
460511
461- hasGreaterThanVerifiedTwitterFollowers : {
462- name : "hasGreaterThanVerifiedTwitterFollowers " ,
463- allowMultiple : true ,
512+ hasVerifiedTwitterFollowersGreaterThan : {
513+ name : "hasVerifiedTwitterFollowersGreaterThan " ,
514+ allowMultiple : false ,
464515 author,
465516 authorUrl,
466517 authorIcon,
467518 category : "all" ,
468- friendlyName : "Icebreaker: Has Greater Than X Verified Twitter Followers " ,
519+ friendlyName : "Icebreaker: Has verified Twitter account with greater than X followers " ,
469520 checkType : "user" ,
470521 description : "Check if the user has more than a certain number of followers on their verified Twitter account" ,
471522 hidden : false ,
472523 invertable : true ,
473524 args : {
474525 threshold : {
475526 type : "string" ,
476- friendlyName : "Follower Threshold" ,
527+ pattern : "^[0-9]*$" ,
528+ defaultValue : "1000" ,
529+ friendlyName : "Follower minimum" ,
477530 description : "The minimum number of followers required" ,
478531 placeholder : "Enter a number..." ,
479532 required : true ,
480533 } ,
481534 } ,
482535 } ,
483536
537+ hasVerifiedTwitterCreatedBefore : {
538+ name : "hasVerifiedTwitterCreatedBefore" ,
539+ allowMultiple : false ,
540+ author,
541+ authorUrl,
542+ authorIcon,
543+ category : "all" ,
544+ friendlyName : "Icebreaker: Has verified Twitter account created before a date" ,
545+ checkType : "user" ,
546+ description : "Check if the user has a verified Twitter account created before a given date" ,
547+ hidden : false ,
548+ invertable : true ,
549+ args : {
550+ threshold : {
551+ type : "string" ,
552+ pattern : "^d{4}-d{2}-d{2}$" ,
553+ defaultValue : "2021-01-01" ,
554+ friendlyName : "Created before" ,
555+ description : "The latest creation date of the Twitter account" ,
556+ placeholder : "Enter a date in YYYY-MM-DD format..." ,
557+ required : true ,
558+ } ,
559+ } ,
560+ } ,
561+
484562 hasPOAP : {
485563 name : "hasPOAP" ,
486564 allowMultiple : true ,
@@ -543,7 +621,8 @@ export const iceBreakerRulesFunction: Record<RuleName, CheckFunction> = {
543621 hasIcebreakerVerified : hasIcebreakerVerified ,
544622 hasIcebreakerCredential : hasIcebreakerCredential ,
545623 hasIcebreakerLinkedAccount : hasIcebreakerLinkedAccount ,
546- hasPOAP : hasPOAP ,
547624 hasGuildRole : hasGuildRole ,
548- hasGreaterThanVerifiedTwitterFollowers : hasGreaterThanVerifiedTwitterFollowers ,
625+ hasPOAP : hasPOAP ,
626+ hasVerifiedTwitterCreatedBefore : hasVerifiedTwitterCreatedBefore ,
627+ hasVerifiedTwitterFollowersGreaterThan : hasVerifiedTwitterFollowersGreaterThan ,
549628} as const ;
0 commit comments