@@ -673,6 +673,60 @@ export class MessagesRaw extends BaseRaw<IMessage> implements IMessagesModel {
673673 setReactions ( messageId : string , reactions : IMessage [ 'reactions' ] ) : Promise < UpdateResult > {
674674 return this . updateOne ( { _id : messageId } , { $set : { reactions } } ) ;
675675 }
676+ public async removeReactionsByUsername ( username : string ) {
677+ const query = {
678+ reactions : { $exists : true } ,
679+ $expr : {
680+ $gt : [
681+ {
682+ $size : {
683+ $filter : {
684+ input : { $objectToArray : '$reactions' } ,
685+ as : 'reaction' ,
686+ cond : {
687+ $in : [ username , '$$reaction.v.usernames' ] ,
688+ } ,
689+ } ,
690+ } ,
691+ } ,
692+ 0 ,
693+ ] ,
694+ } ,
695+ } ;
696+
697+ const pointer = this . find ( query , {
698+ projection : { reactions : 1 } ,
699+ } ) ;
700+
701+ while ( await pointer . hasNext ( ) ) {
702+ const message = await pointer . next ( ) ;
703+ if ( ! message . reactions ) continue ;
704+
705+ let updated = false ;
706+ for ( const [ emoji , data ] of Object . entries ( message . reactions as Record < string , { usernames ?: string [ ] } > ) ) {
707+ if ( ! data . usernames ) continue ;
708+
709+ const filtered = data . usernames . filter ( ( u ) => u !== username ) ;
710+
711+ if ( filtered . length !== data . usernames . length ) {
712+ updated = true ;
713+
714+ if ( filtered . length === 0 ) {
715+ delete message . reactions [ emoji ] ;
716+ } else {
717+ message . reactions [ emoji ] . usernames = filtered ;
718+ }
719+ }
720+ }
721+
722+ if ( updated ) {
723+ await this . updateOne (
724+ { _id : message . _id } ,
725+ Object . keys ( message . reactions ) . length ? { $set : { reactions : message . reactions } } : { $unset : { reactions : 1 } } ,
726+ ) ;
727+ }
728+ }
729+ }
676730
677731 keepHistoryForToken ( token : string ) : Promise < UpdateResult | Document > {
678732 return this . updateMany (
0 commit comments