33import  net .dv8tion .jda .api .JDA ;
44import  net .dv8tion .jda .api .entities .Guild ;
55import  net .dv8tion .jda .api .entities .Member ;
6+ import  net .dv8tion .jda .api .entities .Role ;
7+ import  net .dv8tion .jda .api .entities .UserSnowflake ;
68import  org .jooq .Query ;
79import  org .jooq .impl .DSL ;
810import  org .slf4j .Logger ;
2123import  java .util .Optional ;
2224import  java .util .concurrent .CompletableFuture ;
2325import  java .util .concurrent .TimeUnit ;
26+ import  java .util .function .Predicate ;
27+ import  java .util .regex .Pattern ;
2428import  java .util .stream .Collectors ;
2529
2630import  static  org .togetherjava .tjbot .db .generated .tables .CakeDays .CAKE_DAYS ;
@@ -31,12 +35,15 @@ public class CakeDayRoutine implements Routine {
3135    private  static  final  DateTimeFormatter  MONTH_DAY_FORMATTER  =
3236            DateTimeFormatter .ofPattern ("MM-dd" );
3337    private  static  final  int  BULK_INSERT_SIZE  = 500 ;
38+     private  final  Predicate <String > cakeDayRolePredicate ;
3439    private  final  CakeDayConfig  config ;
3540    private  final  Database  database ;
3641
3742    public  CakeDayRoutine (Config  config , Database  database ) {
3843        this .config  = config .getCakeDayConfig ();
3944        this .database  = database ;
45+ 
46+         this .cakeDayRolePredicate  = Pattern .compile (this .config .rolePattern ()).asPredicate ();
4047    }
4148
4249    /** 
@@ -75,7 +82,49 @@ public void runRoutine(JDA jda) {
7582
7683                    return  result ;
7784                });
85+ 
86+             return ;
7887        }
88+ 
89+         jda .getGuilds ().forEach (this ::reassignCakeDayRole );
90+     }
91+ 
92+     private  void  reassignCakeDayRole (Guild  guild ) {
93+         Role  cakeDayRole  = getCakeDayRoleFromGuild (guild ).orElse (null );
94+ 
95+         if  (cakeDayRole  == null ) {
96+             logger .warn ("Cake day role with pattern {} not found for guild: {}" ,
97+                     config .rolePattern (), guild .getName ());
98+             return ;
99+         }
100+ 
101+         removeMembersCakeDayRole (cakeDayRole , guild )
102+             .thenCompose (result  -> addTodayMembersCakeDayRole (cakeDayRole , guild ))
103+             .join ();
104+     }
105+ 
106+     private  CompletableFuture <Void > addTodayMembersCakeDayRole (Role  cakeDayRole , Guild  guild ) {
107+         return  CompletableFuture 
108+             .runAsync (() -> findCakeDaysTodayFromDatabase ().forEach (cakeDayRecord  -> {
109+                 UserSnowflake  snowflake  = UserSnowflake .fromId (cakeDayRecord .getUserId ());
110+ 
111+                 int  anniversary  = OffsetDateTime .now ().getYear () - cakeDayRecord .getJoinedYear ();
112+                 if  (anniversary  > 0 ) {
113+                     guild .addRoleToMember (snowflake , cakeDayRole ).complete ();
114+                 }
115+             }));
116+     }
117+ 
118+     private  CompletableFuture <Void > removeMembersCakeDayRole (Role  cakeDayRole , Guild  guild ) {
119+         return  CompletableFuture .runAsync (() -> guild .findMembersWithRoles (cakeDayRole )
120+             .onSuccess (members  -> removeRoleFromMembers (guild , cakeDayRole , members )));
121+     }
122+ 
123+     private  void  removeRoleFromMembers (Guild  guild , Role  role , List <Member > members ) {
124+         members .forEach (member  -> {
125+             UserSnowflake  snowflake  = UserSnowflake .fromId (member .getIdLong ());
126+             guild .removeRoleFromMember (snowflake , role ).complete ();
127+         });
79128    }
80129
81130    private  int  getCakeDayCount (Database  database ) {
@@ -121,6 +170,13 @@ private Optional<Query> createMemberCakeDayQuery(Member member, long guildId) {
121170            .set (CAKE_DAYS .USER_ID , member .getIdLong ()));
122171    }
123172
173+     private  Optional <Role > getCakeDayRoleFromGuild (Guild  guild ) {
174+         return  guild .getRoles ()
175+             .stream ()
176+             .filter (role  -> cakeDayRolePredicate .test (role .getName ()))
177+             .findFirst ();
178+     }
179+ 
124180    private  List <CakeDaysRecord > findCakeDaysTodayFromDatabase () {
125181        String  todayMonthDay  = OffsetDateTime .now ().format (MONTH_DAY_FORMATTER );
126182
0 commit comments