@ -12,6 +12,7 @@ use crate::error::GroupError; 
			
		
	
		
		
			
				
					
					use   crate ::group_handler ::GroupHandle ; use   crate ::group_handler ::GroupHandle ;  
			
		
	
		
		
			
				
					
					use   crate ::store ::group_config ::GroupConfig ; use   crate ::store ::group_config ::GroupConfig ;  
			
		
	
		
		
			
				
					
					use   crate ::store ::CommonConfig ; use   crate ::store ::CommonConfig ;  
			
		
	
		
		
			
				
					
					use   crate ::tr ::TranslationTable ;  
			
		
	
		
		
			
				
					
					use   crate ::utils ; use   crate ::utils ;  
			
		
	
		
		
			
				
					
					use   crate ::utils ::{ normalize_acct ,   LogError } ; use   crate ::utils ::{ normalize_acct ,   LogError } ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -26,13 +27,17 @@ pub struct ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					     status_user_id : String ,      status_user_id : String ,  
			
		
	
		
		
			
				
					
					     can_write : bool ,      can_write : bool ,  
			
		
	
		
		
			
				
					
					     is_admin : bool ,      is_admin : bool ,  
			
		
	
		
		
			
				
					
					     replies : Vec < String > ,      replies : String ,  
			
				
				
			
		
	
		
		
			
				
					
					     announcements : Vec < String > ,      announcements : String ,  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					     do_boost_prev_post : bool ,      do_boost_prev_post : bool ,  
			
		
	
		
		
			
				
					
					     want_markdown : bool ,      want_markdown : bool ,  
			
		
	
		
		
			
				
					
					} }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					impl < ' a >   ProcessMention < ' a >   { impl < ' a >   ProcessMention < ' a >   {  
			
		
	
		
		
			
				
					
					     fn  tr ( & self )   -> & TranslationTable   {  
			
		
	
		
		
			
				
					
					         self . cc . tr ( self . config . get_locale ( ) )  
			
		
	
		
		
			
				
					
					     }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  lookup_acct_id ( & self ,   acct : & str ,   followed : bool )   -> Result < Option < String > ,   GroupError >   {      async   fn  lookup_acct_id ( & self ,   acct : & str ,   followed : bool )   -> Result < Option < String > ,   GroupError >   {  
			
		
	
		
		
			
				
					
					         debug ! ( "Looking up user ID by acct: {}" ,   acct ) ;          debug ! ( "Looking up user ID by acct: {}" ,   acct ) ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -41,7 +46,7 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					             self . client              self . client  
			
		
	
		
		
			
				
					
					                 . search_v2 ( acct ,   ! followed ,   Some ( SearchType ::Accounts ) ,   Some ( 1 ) ,   followed ) ,                  . search_v2 ( acct ,   ! followed ,   Some ( SearchType ::Accounts ) ,   Some ( 1 ) ,   followed ) ,  
			
		
	
		
		
			
				
					
					         )          )  
			
		
	
		
		
			
				
					
					         . await               . await  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         {          {  
			
		
	
		
		
			
				
					
					             Err ( _ )   = >   {              Err ( _ )   = >   {  
			
		
	
		
		
			
				
					
					                 warn ! ( "Account lookup timeout!" ) ;                  warn ! ( "Account lookup timeout!" ) ;  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -72,9 +77,11 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					     fn  append_admin_list_to_reply ( & mut   self )   {      fn  append_admin_list_to_reply ( & mut   self )   {  
			
		
	
		
		
			
				
					
					         let   mut   admins   =   self . config . get_admins ( ) . collect ::< Vec < _ > > ( ) ;          let   mut   admins   =   self . config . get_admins ( ) . collect ::< Vec < _ > > ( ) ;  
			
		
	
		
		
			
				
					
					         admins . sort ( ) ;          admins . sort ( ) ;  
			
		
	
		
		
			
				
					
					         let   mut   to_add   =   String ::new ( ) ;  
			
		
	
		
		
			
				
					
					         for   a   in   admins   {          for   a   in   admins   {  
			
		
	
		
		
			
				
					
					             self . replies . push ( format! ( "- {}" ,   a ) ) ;              to_add . push_str ( & crate ::tr ! ( self ,   "user_list_entry" ,   user   =   a ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					         self . add_reply ( & to_add ) ;  
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     fn  append_member_list_to_reply ( & mut   self )   {      fn  append_member_list_to_reply ( & mut   self )   {  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -83,13 +90,15 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					         members . extend ( admins . iter ( ) ) ;          members . extend ( admins . iter ( ) ) ;  
			
		
	
		
		
			
				
					
					         members . sort ( ) ;          members . sort ( ) ;  
			
		
	
		
		
			
				
					
					         members . dedup ( ) ;          members . dedup ( ) ;  
			
		
	
		
		
			
				
					
					         let   mut   to_add   =   String ::new ( ) ;  
			
		
	
		
		
			
				
					
					         for   m   in   members   {          for   m   in   members   {  
			
		
	
		
		
			
				
					
					             self . replies . push ( if   admins . contains ( & m )   {              to_add . push_str ( & if   admins . contains ( & m )   {  
			
				
				
			
		
	
		
		
			
				
					
					                 format! ( "- {} [admin] ",   m )                  crate ::tr ! ( self ,   "user_list_entry_admin ",   user = m )  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 format! ( "- {} ",   m )                  crate ::tr ! ( self ,   "user_list_entry ",   user = m )  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             } ) ;              } ) ;  
			
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					         self . add_reply ( & to_add ) ;  
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  follow_user_by_id ( & self ,   id : & str )   -> Result < ( ) ,   GroupError >   {      async   fn  follow_user_by_id ( & self ,   id : & str )   -> Result < ( ) ,   GroupError >   {  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -122,8 +131,8 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					             cc : & gh . cc ,              cc : & gh . cc ,  
			
		
	
		
		
			
				
					
					             can_write : gh . config . can_write ( & status_acct ) ,              can_write : gh . config . can_write ( & status_acct ) ,  
			
		
	
		
		
			
				
					
					             is_admin : gh . config . is_admin ( & status_acct ) ,              is_admin : gh . config . is_admin ( & status_acct ) ,  
			
		
	
		
		
			
				
					
					             replies : vec ! [ ] ,              replies : String ::new ( ) ,  
			
				
				
			
		
	
		
		
			
				
					
					             announcements : vec ! [ ] ,              announcements : String ::new ( ) ,  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					             do_boost_prev_post : false ,              do_boost_prev_post : false ,  
			
		
	
		
		
			
				
					
					             want_markdown : false ,              want_markdown : false ,  
			
		
	
		
		
			
				
					
					             group_acct ,              group_acct ,  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -136,16 +145,17 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  reblog_status ( & self )   {      async   fn  reblog_status ( & self )   {  
			
		
	
		
		
			
				
					
					         self . client . reblog ( & self . status . id ) . await . log_error ( "Failed to reblog status" ) ;          self . client . reblog ( & self . status . id )  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             . await . log_error ( "Failed to reblog status" ) ;  
			
		
	
		
		
			
				
					
					         self . delay_after_post ( ) . await ;          self . delay_after_post ( ) . await ;  
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     fn  add_reply ( & mut   self ,   line : impl   AsRef < str > )   {      fn  add_reply ( & mut   self ,   line : impl   AsRef < str > )   {  
			
		
	
		
		
			
				
					
					         self . replies . push ( line . as_ref ( ) . trim_matches ( ' ' ) . to_string ( ) )          self . replies . push_str  ( line . as_ref ( ) )  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     fn  add_announcement ( & mut   self ,   line : impl   AsRef < str > )   {      fn  add_announcement ( & mut   self ,   line : impl   AsRef < str > )   {  
			
		
	
		
		
			
				
					
					         self . announcements . push ( line . as_ref ( ) . trim_matches ( ' ' ) . to_string ( ) )          self . announcements . push_str  ( line . as_ref ( ) )  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  handle ( mut   self )   -> Result < ( ) ,   GroupError >   {      async   fn  handle ( mut   self )   -> Result < ( ) ,   GroupError >   {  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -160,6 +170,9 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					             for   cmd   in   commands   {              for   cmd   in   commands   {  
			
		
	
		
		
			
				
					
					                 if   ! self . replies . is_empty ( )   {  
			
		
	
		
		
			
				
					
					                     self . replies . push ( '\n' ) ;   // make sure there's a newline between batched commands.
  
			
		
	
		
		
			
				
					
					                 }  
			
		
	
		
		
			
				
					
					                 match   cmd   {                  match   cmd   {  
			
		
	
		
		
			
				
					
					                     StatusCommand ::Undo   = >   {                      StatusCommand ::Undo   = >   {  
			
		
	
		
		
			
				
					
					                         self . cmd_undo ( ) . await . log_error ( "Error handling undo cmd" ) ;                          self . cmd_undo ( ) . await . log_error ( "Error handling undo cmd" ) ;  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -207,7 +220,7 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					                         self . cmd_grant_admin ( & u ) . await . log_error ( "Error handling grant-admin cmd" ) ;                          self . cmd_grant_admin ( & u ) . await . log_error ( "Error handling grant-admin cmd" ) ;  
			
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                     StatusCommand ::RemoveAdmin ( u )   = >   {                      StatusCommand ::RemoveAdmin ( u )   = >   {  
			
		
	
		
		
			
				
					
					                         self . cmd_revoke_member  ( & u ) . await . log_error ( "Error handling grant-admin cmd" ) ;                          self . cmd_revoke_admin  ( & u ) . await . log_error ( "Error handling grant-admin cmd" ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                     StatusCommand ::OpenGroup   = >   {                      StatusCommand ::OpenGroup   = >   {  
			
		
	
		
		
			
				
					
					                         self . cmd_open_group ( ) . await ;                          self . cmd_open_group ( ) . await ;  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -255,26 +268,26 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         if   ! self . replies . is_empty ( )   {          if   ! self . replies . is_empty ( )   {  
			
		
	
		
		
			
				
					
					             let   mut   msg   =   self . replies . join ( "\n" ) ;              let   mut   msg   =   std ::mem ::take ( & mut   self . replies ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             debug ! ( "r={}" ,   msg ) ;              debug ! ( "r={}" ,   msg ) ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					             if   self . want_markdown   {              if   self . want_markdown   {  
			
		
	
		
		
			
				
					
					                 apply_trailing_hashtag_pleroma_bug_workaround ( & mut   msg ) ;                  apply_trailing_hashtag_pleroma_bug_workaround ( & mut   msg ) ;  
			
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					             let   mention   =   format! ( "@{user}  ",   user   =   self . status_acct ) ;              let   mention   =   crate ::tr ! ( self ,   "mention_prefix ",   user   =   & self . status_acct ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             self . send_reply_multipart ( mention ,   msg ) . await ? ;              self . send_reply_multipart ( mention ,   msg ) . await ? ;  
			
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         if   ! self . announcements . is_empty ( )   {          if   ! self . announcements . is_empty ( )   {  
			
		
	
		
		
			
				
					
					             let   mut   msg   =   self . announcements . join ( "\n" ) ;              let   mut   msg   =   std ::mem ::take ( & mut   self . announcements ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             debug ! ( "a={}" ,   msg ) ;              debug ! ( "a={}" ,   msg ) ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					             if   self . want_markdown   {              if   self . want_markdown   {  
			
		
	
		
		
			
				
					
					                 apply_trailing_hashtag_pleroma_bug_workaround ( & mut   msg ) ;                  apply_trailing_hashtag_pleroma_bug_workaround ( & mut   msg ) ;  
			
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					             let   msg   =   format! ( "**📢 Group announcement**\n{msg} ",   msg   =   msg ) ;              let   msg   =   crate ::tr ! ( self ,   "group_announcement ",   mes sa ge    =   & msg ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             self . send_announcement_multipart ( & msg ) . await ? ;              self . send_announcement_multipart ( & msg ) . await ? ;  
			
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					
 
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -367,29 +380,29 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  cmd_optout ( & mut   self )   {      async   fn  cmd_optout ( & mut   self )   {  
			
		
	
		
		
			
				
					
					         if   self . is_admin   {          if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             self . add_reply ( "Group admins can't opt-out." ) ;              self . add_reply ( crate ::tr ! ( self ,   "cmd_optout_fail_admin_cant" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         }   else   if   self . config . is_member ( & self . status_acct )   {          }   else   if   self . config . is_member ( & self . status_acct )   {  
			
		
	
		
		
			
				
					
					             self . add_reply ( "Group members can't opt-out. You have to leave first." ) ;              self . add_reply ( crate ::tr ! ( self ,   "cmd_optout_fail_member_cant" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             self . config . set_optout ( & self . status_acct ,   true ) ;              self . config . set_optout ( & self . status_acct ,   true ) ;  
			
		
	
		
		
			
				
					
					             self . add_reply ( "Your posts will no longer be shared to the group." ) ;              self . add_reply ( crate ::tr ! ( self ,   "cmd_optout_ok" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  cmd_optin ( & mut   self )   {      async   fn  cmd_optin ( & mut   self )   {  
			
		
	
		
		
			
				
					
					         if   self . is_admin   {          if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             self . add_reply ( "Opt-in has no effect for admins." ) ;              self . add_reply ( crate ::tr ! ( self ,   "cmd_optin_fail_admin_cant" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         }   else   if   self . config . is_member ( & self . status_acct )   {          }   else   if   self . config . is_member ( & self . status_acct )   {  
			
		
	
		
		
			
				
					
					             self . add_reply ( "Opt-in has no effect for members." ) ;              self . add_reply ( crate ::tr ! ( self ,   "cmd_optin_fail_member_cant" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             self . config . set_optout ( & self . status_acct ,   false ) ;              self . config . set_optout ( & self . status_acct ,   false ) ;  
			
		
	
		
		
			
				
					
					             self . add_reply ( "Your posts can now be shared to the group." ) ;              self . add_reply ( crate ::tr ! ( self ,   "cmd_optin_ok" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  cmd_undo ( & mut   self )   -> Result < ( ) ,   GroupError >   {      async   fn  cmd_undo ( & mut   self )   -> Result < ( ) ,   GroupError >   {  
			
		
	
		
		
			
				
					
					         if   let   ( Some ( ref   parent_account_id ) ,   Some ( ref   parent_status_id ) )   =          if   let   ( Some ( ref   parent_account_id ) ,   Some ( ref   parent_status_id ) )   =  
			
		
	
		
		
			
				
					
					              ( & self . status . in_reply_to_account_id ,   & self . status . in_reply_to_id )          ( & self . status . in_reply_to_account_id ,   & self . status . in_reply_to_id )  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         {          {  
			
		
	
		
		
			
				
					
					             if   parent_account_id   = =   & self . group_account . id   {              if   parent_account_id   = =   & self . group_account . id   {  
			
		
	
		
		
			
				
					
					                 // This is a post sent by the group user, likely an announcement.
                  // This is a post sent by the group user, likely an announcement.
  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -422,15 +435,15 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					             if   ! self . config . is_banned ( & u )   {              if   ! self . config . is_banned ( & u )   {  
			
		
	
		
		
			
				
					
					                 match   self . config . ban_user ( & u ,   true )   {                  match   self . config . ban_user ( & u ,   true )   {  
			
		
	
		
		
			
				
					
					                     Ok ( _ )   = >   {                      Ok ( _ )   = >   {  
			
		
	
		
		
			
				
					
					                         self . add_reply ( format! ( "User {} banned from group! ",   u ) ) ;                          self . add_reply ( crate ::tr ! ( self ,   "cmd_ban_user_ok ",   user   =   & u ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                         self . unfollow_by_acct ( & u ) . await . log_error ( "Failed to unfollow banned user" ) ;                          self . unfollow_by_acct ( & u ) . await . log_error ( "Failed to unfollow banned user" ) ;  
			
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                     Err ( e )   = >   {                      Err ( e )   = >   {  
			
		
	
		
		
			
				
					
					                         self . add_reply ( format! ( "Failed to ban user {}: {}" ,   u ,   e ) ) ;                          self . add_reply ( crate ::tr ! ( self ,   "cmd_error" ,   cause   =   & e . to_string ( ) ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                 }                  }  
			
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 self . add_reply ( format! ( "No action, user {} is already banned ",   u ) ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_ban_user_fail_already ",   user   =   & u ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             warn ! ( "Ignore cmd, user not admin" ) ;              warn ! ( "Ignore cmd, user not admin" ) ;  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -444,15 +457,15 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					             if   self . config . is_banned ( & u )   {              if   self . config . is_banned ( & u )   {  
			
		
	
		
		
			
				
					
					                 match   self . config . ban_user ( & u ,   false )   {                  match   self . config . ban_user ( & u ,   false )   {  
			
		
	
		
		
			
				
					
					                     Ok ( _ )   = >   {                      Ok ( _ )   = >   {  
			
		
	
		
		
			
				
					
					                         self . add_reply ( format! ( "User {} un-banned! ",   u ) ) ;                          self . add_reply ( crate ::tr ! ( self ,   "cmd_unban_user_ok ",   user   =   & u ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                         // no announcement here
                          // no announcement here
  
			
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                     Err ( _ )   = >   {                      Err ( e )   = >   {  
			
				
				
			
		
	
		
		
			
				
					
					                         unreachable! ( )                          self . add_reply ( crate ::tr ! ( self ,   "cmd_error" ,   cause   =   & e . to_string ( ) ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                 }                  }  
			
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 self . add_reply ( format! ( "No action, user {} is not banned ",   u ) ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_unban_user_fail_already ",   user   =   & u ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             warn ! ( "Ignore cmd, user not admin" ) ;              warn ! ( "Ignore cmd, user not admin" ) ;  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -465,14 +478,14 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					             if   ! self . config . is_server_banned ( s )   {              if   ! self . config . is_server_banned ( s )   {  
			
		
	
		
		
			
				
					
					                 match   self . config . ban_server ( s ,   true )   {                  match   self . config . ban_server ( s ,   true )   {  
			
		
	
		
		
			
				
					
					                     Ok ( _ )   = >   {                      Ok ( _ )   = >   {  
			
		
	
		
		
			
				
					
					                         self . add_reply ( format! ( "Server {} banned from group!" ,   s ) ) ;                          self . add_reply ( crate ::tr ! ( self ,   "cmd_ban_server_ok" ,   server   =   s ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                     Err ( e )   = >   {                      Err ( e )   = >   {  
			
		
	
		
		
			
				
					
					                         self . add_reply ( format! ( "Failed to ban server {}: {}" ,   s ,   e ) ) ;                          self . add_reply ( crate ::tr ! ( self ,   "cmd_error" ,   cause   =   & e . to_string ( ) ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                 }                  }  
			
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 self . add_reply ( format! ( "No action, server {} already banned" ,   s ) ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_ban_server_fail_already" ,   server   =   s ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             warn ! ( "Ignore cmd, user not admin" ) ;              warn ! ( "Ignore cmd, user not admin" ) ;  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -484,14 +497,14 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					             if   self . config . is_server_banned ( s )   {              if   self . config . is_server_banned ( s )   {  
			
		
	
		
		
			
				
					
					                 match   self . config . ban_server ( s ,   false )   {                  match   self . config . ban_server ( s ,   false )   {  
			
		
	
		
		
			
				
					
					                     Ok ( _ )   = >   {                      Ok ( _ )   = >   {  
			
		
	
		
		
			
				
					
					                         self . add_reply ( format! ( "Server {} un-banned!" ,   s ) ) ;                          self . add_reply ( crate ::tr ! ( self ,   "cmd_unban_server_ok" ,   server   =   s ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                     Err ( e )   = >   {                      Err ( e )   = >   {  
			
		
	
		
		
			
				
					
					                         self . add_reply ( format! ( "Unexpected error occured: {} ",   e ) ) ;                          self . add_reply ( crate ::tr ! ( self ,   "cmd_error ",   caus e  =   & e . to_string ( ) ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                 }                  }  
			
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 self . add_reply ( format! ( "No action, server {} is not banned" ,   s ) ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_unban_server_fail_already" ,   server   =   s ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             warn ! ( "Ignore cmd, user not admin" ) ;              warn ! ( "Ignore cmd, user not admin" ) ;  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -504,11 +517,12 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					             // Allow even if the user is already a member - that will trigger re-follow
              // Allow even if the user is already a member - that will trigger re-follow
  
			
		
	
		
		
			
				
					
					             match   self . config . set_member ( & u ,   true )   {              match   self . config . set_member ( & u ,   true )   {  
			
		
	
		
		
			
				
					
					                 Ok ( _ )   = >   {                  Ok ( _ )   = >   {  
			
		
	
		
		
			
				
					
					                     self . add_reply ( format! ( "User {} added to the group!" ,   u ) ) ;                      self . add_reply ( crate ::tr ! ( self ,   "cmd_add_user_ok" ,   user   =   & u ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     // marked as member, now also follow the user
  
			
		
	
		
		
			
				
					
					                     self . follow_by_acct ( & u ) . await . log_error ( "Failed to follow" ) ;                      self . follow_by_acct ( & u ) . await . log_error ( "Failed to follow" ) ;  
			
		
	
		
		
			
				
					
					                 }                  }  
			
		
	
		
		
			
				
					
					                 Err ( e )   = >   {                  Err ( e )   = >   {  
			
		
	
		
		
			
				
					
					                     self . add_reply ( format! ( "Failed to add user {} to group: {}" ,   u ,   e ) ) ;                      self . add_reply ( crate ::tr ! ( self ,   "cmd_error" ,   cause   =   & e . to_string ( ) ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                 }                  }  
			
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -522,11 +536,11 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					         if   self . is_admin   {          if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             match   self . config . set_member ( & u ,   false )   {              match   self . config . set_member ( & u ,   false )   {  
			
		
	
		
		
			
				
					
					                 Ok ( _ )   = >   {                  Ok ( _ )   = >   {  
			
		
	
		
		
			
				
					
					                     self . add_reply ( format! ( "User {} removed from the group. ",   u ) ) ;                      self . add_reply ( crate ::tr ! ( self ,   "cmd_remove_user_ok ",   user   =   & u ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     self . unfollow_by_acct ( & u ) . await . log_error ( "Failed to unfollow removed user" ) ;                      self . unfollow_by_acct ( & u ) . await . log_error ( "Failed to unfollow removed user" ) ;  
			
		
	
		
		
			
				
					
					                 }                  }  
			
		
	
		
		
			
				
					
					                 Err ( e )   = >   {                  Err ( e )   = >   {  
			
		
	
		
		
			
				
					
					                     self . add_reply ( format! ( "Unexpected error occured: {} ",   e ) ) ;                      self . add_reply ( crate ::tr ! ( self ,   "cmd_error ",   caus e  =   & e . to_string ( ) ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                 }                  }  
			
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -539,9 +553,9 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					         if   self . is_admin   {          if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             if   ! self . config . is_tag_followed ( & tag )   {              if   ! self . config . is_tag_followed ( & tag )   {  
			
		
	
		
		
			
				
					
					                 self . config . add_tag ( & tag ) ;                  self . config . add_tag ( & tag ) ;  
			
		
	
		
		
			
				
					
					                 self . add_reply ( format! ( "Tag \"{}\" added to the group! ",   tag ) ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_add_tag_ok ",   tag   =   & tag ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 self . add_reply ( format! ( "No action, \"{}\" is already a group tag" ,   tag ) ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_add_tag_fail_already" ,   tag   =   & tag ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             warn ! ( "Ignore cmd, user not admin" ) ;              warn ! ( "Ignore cmd, user not admin" ) ;  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -552,9 +566,9 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					         if   self . is_admin   {          if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             if   self . config . is_tag_followed ( & tag )   {              if   self . config . is_tag_followed ( & tag )   {  
			
		
	
		
		
			
				
					
					                 self . config . remove_tag ( & tag ) ;                  self . config . remove_tag ( & tag ) ;  
			
		
	
		
		
			
				
					
					                 self . add_reply ( format! ( "Tag \"{}\" removed from the group! ",   tag ) ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_remove_tag_ok ",   tag   =   & tag ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 self . add_reply ( format! ( "No action, \"{}\" is not a group tag" ,   tag ) ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_remove_tag_fail_already" ,   tag   =   & tag ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             warn ! ( "Ignore cmd, user not admin" ) ;              warn ! ( "Ignore cmd, user not admin" ) ;  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -570,14 +584,14 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					                         // try to make the config a little more sane, admins should be members
                          // try to make the config a little more sane, admins should be members
  
			
		
	
		
		
			
				
					
					                         let   _   =   self . config . set_member ( & u ,   true ) ;                          let   _   =   self . config . set_member ( & u ,   true ) ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					                         self . add_reply ( format! ( "User {} is now a group admin! ",   u ) ) ;                          self . add_reply ( crate ::tr ! ( self ,   "cmd_admin_ok ",   user   =   & u ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                     Err ( e )   = >   {                      Err ( e )   = >   {  
			
		
	
		
		
			
				
					
					                         self . add_reply ( format! ( "Failed to make user {} a group admin: {}" ,   u ,   e ) ) ;                          self . add_reply ( crate ::tr ! ( self ,   "cmd_error" ,   cause   =   & e . to_string ( ) ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                 }                  }  
			
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 self . add_reply ( format! ( "No action, \"{}\" is admin  already",   u ) ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_admin_fail_ already",   user   =   & u ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             warn ! ( "Ignore cmd, user not admin" ) ;              warn ! ( "Ignore cmd, user not admin" ) ;  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -585,20 +599,20 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					         Ok ( ( ) )          Ok ( ( ) )  
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  cmd_revoke_member  ( & mut   self ,   user : & str )   -> Result < ( ) ,   GroupError >   {      async   fn  cmd_revoke_admin  ( & mut   self ,   user : & str )   -> Result < ( ) ,   GroupError >   {  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         let   u   =   normalize_acct ( user ,   & self . group_acct ) ? ;          let   u   =   normalize_acct ( user ,   & self . group_acct ) ? ;  
			
		
	
		
		
			
				
					
					         if   self . is_admin   {          if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             if   self . config . is_admin ( & u )   {              if   self . config . is_admin ( & u )   {  
			
		
	
		
		
			
				
					
					                 match   self . config . set_admin ( & u ,   false )   {                  match   self . config . set_admin ( & u ,   false )   {  
			
		
	
		
		
			
				
					
					                     Ok ( _ )   = >   {                      Ok ( _ )   = >   {  
			
		
	
		
		
			
				
					
					                         self . add_reply ( format! ( "User {} is no longer a group admin! ",   u ) ) ;                          self . add_reply ( crate ::tr ! ( self ,   "cmd_unadmin_ok ",   user   =   & u ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                     Err ( e )   = >   {                      Err ( e )   = >   {  
			
		
	
		
		
			
				
					
					                         self . add_reply ( format! ( "Failed to revoke {}'s group admin: {}" ,   u ,   e ) ) ;                          self . add_reply ( crate ::tr ! ( self ,   "cmd_error" ,   cause   =   & e . to_string ( ) ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					                     }                      }  
			
		
	
		
		
			
				
					
					                 }                  }  
			
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 self . add_reply ( format! ( "No action, user {} is not admin ",   u ) ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_unadmin_fail_already ",   user   =   & u ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             warn ! ( "Ignore cmd, user not admin" ) ;              warn ! ( "Ignore cmd, user not admin" ) ;  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -610,9 +624,9 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					         if   self . is_admin   {          if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             if   self . config . is_member_only ( )   {              if   self . config . is_member_only ( )   {  
			
		
	
		
		
			
				
					
					                 self . config . set_member_only ( false ) ;                  self . config . set_member_only ( false ) ;  
			
		
	
		
		
			
				
					
					                 self . add_reply ( "Group changed to open-access" ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_open_resp" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 self . add_reply ( "No action, group is open-access already" ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_open_resp_already" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             warn ! ( "Ignore cmd, user not admin" ) ;              warn ! ( "Ignore cmd, user not admin" ) ;  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -623,9 +637,9 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					         if   self . is_admin   {          if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             if   ! self . config . is_member_only ( )   {              if   ! self . config . is_member_only ( )   {  
			
		
	
		
		
			
				
					
					                 self . config . set_member_only ( true ) ;                  self . config . set_member_only ( true ) ;  
			
		
	
		
		
			
				
					
					                 self . add_reply ( "Group changed to member-only" ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_close_resp" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 self . add_reply ( "No action, group is member-only already" ) ;                  self . add_reply ( crate ::tr ! ( self ,   "cmd_close_resp_already" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             warn ! ( "Ignore cmd, user not admin" ) ;              warn ! ( "Ignore cmd, user not admin" ) ;  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -636,93 +650,62 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					         self . want_markdown   =   true ;          self . want_markdown   =   true ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         let   membership_line   =   if   self . is_admin   {          let   membership_line   =   if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             "*You are an admin.*"              crate ::tr ! ( self ,   "help_membership_admin" )  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         }   else   if   self . config . is_member ( & self . status_acct )   {          }   else   if   self . config . is_member ( & self . status_acct )   {  
			
		
	
		
		
			
				
					
					             "*You are a member.*"              crate ::tr ! ( self ,   "help_membership_member" )  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         }   else   if   self . config . is_member_only ( )   {          }   else   if   self . config . is_member_only ( )   {  
			
		
	
		
		
			
				
					
					             "*You are not a member, ask one of the admins to add you.*"              crate ::tr ! ( self ,   "help_membership_guest_closed" )  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             "*You are not a member, follow or use /join to join the group.*"              crate ::tr ! ( self ,   "help_membership_guest_open" )  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         } ;          } ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         if   self . config . is_member_only ( )   {          if   self . config . is_member_only ( )   {  
			
		
	
		
		
			
				
					
					             self . add_reply ( format! ( "This is a member-only group. {}" ,   membership_line ) ) ;              self . add_reply ( crate ::tr ! ( self ,   "help_group_info_closed" ,   membership   =   & membership_line ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					         }   else   {  
			
		
	
		
		
			
				
					
					             self . add_reply ( format! ( "This is a public-access group. {}" ,   membership_line ) ) ;  
			
		
	
		
		
			
				
					
					         }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         self . add_reply (  
			
		
	
		
		
			
				
					
					             " \  
			
		
	
		
		
			
				
					
					             To   share   a   post ,   @   the   group   user   or   use   a   group   hashtag . \ n \  
			
		
	
		
		
			
				
					
					             \ n \  
			
		
	
		
		
			
				
					
					             * * Supported   commands :* * \ n \  
			
		
	
		
		
			
				
					
					             ` / boost ` ,   ` / b `   -   boost   the   replied - to   post   into   the   group \ n \  
			
		
	
		
		
			
				
					
					             ` / ignore ` ,   ` / i `   -   make   the   group   ignore   the   post \ n \  
			
		
	
		
		
			
				
					
					             ` / tags `   -   show   group   hashtags \ n \  
			
		
	
		
		
			
				
					
					             ` / join `   -   ( re - ) join   the   group \ n \  
			
		
	
		
		
			
				
					
					             ` / leave `   -   leave   the   group \ n \  
			
		
	
		
		
			
				
					
					             ` / optout `   -   forbid   sharing   of   your   posts " ,  
			
		
	
		
		
			
				
					
					         ) ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             self . add_reply ( "`/members`, `/who` - show group members / admins" ) ;  
			
		
	
		
		
			
				
					
					             // undo is listed as an admin command
  
			
		
	
		
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             self . add_reply ( "`/admins` - show group admins" ) ;              self . add_reply ( crate ::tr ! ( self ,   "help_group_info_open" ,   membership   =   & membership_line ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					             self . add_reply ( "`/undo` - un-boost your post (use in a reply)" ) ;  
			
		
	
		
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         // XXX when used on instance with small character limit, this won't fit!
          self . add_reply ( crate ::tr ! ( self ,   "help_basic_commands" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         if   ! self . is_admin   {  
			
		
	
		
		
			
				
					
					             self . add_reply ( crate ::tr ! ( self ,   "help_member_commands" ) ) ;  
			
		
	
		
		
			
				
					
					         }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         if   self . is_admin   {          if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             self . add_reply (              self . add_reply ( crate ::tr ! ( self ,   "help_admin_commands" ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					                 " \ n \  
			
		
	
		
		
			
				
					
					                 * * Admin   commands :* * \ n \  
			
		
	
		
		
			
				
					
					                 ` / ping `   -   check   the   group   works \ n \  
			
		
	
		
		
			
				
					
					                 ` / add   user `   -   add   a   member   ( user @ domain ) \ n \  
			
		
	
		
		
			
				
					
					                 ` / remove   user `   -   remove   a   member \ n \  
			
		
	
		
		
			
				
					
					                 ` / add   #hashtag `   -   add   a   group   hashtag \ n \  
			
		
	
		
		
			
				
					
					                 ` / remove   #hashtag `   -   remove   a   group   hashtag \ n \  
			
		
	
		
		
			
				
					
					                 ` / undo `   -   un - boost   a   replied - to   post ,   delete   an   announcement \ n \  
			
		
	
		
		
			
				
					
					                 ` / ban   x `   -   ban   a   user   or   server \ n \  
			
		
	
		
		
			
				
					
					                 ` / unban   x `   -   lift   a   ban \ n \  
			
		
	
		
		
			
				
					
					                 ` / admin   user `   -   grant   admin   rights \ n \  
			
		
	
		
		
			
				
					
					                 ` / deadmin   user `   -   revoke   admin   rights \ n \  
			
		
	
		
		
			
				
					
					                 ` / closegroup `   -   make   member - only \ n \  
			
		
	
		
		
			
				
					
					                 ` / opengroup `   -   make   public - access \ n \  
			
		
	
		
		
			
				
					
					                 ` / announce   x `   -   make   a   public   announcement " ,  
			
		
	
		
		
			
				
					
					             ) ;  
			
		
	
		
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  cmd_list_members ( & mut   self )   {      async   fn  cmd_list_members ( & mut   self )   {  
			
		
	
		
		
			
				
					
					         self . want_markdown   =   true ;          self . want_markdown   =   true ;  
			
		
	
		
		
			
				
					
					         if   self . is_admin   {          if   self . is_admin   {  
			
		
	
		
		
			
				
					
					             self . add_reply ( "Group members:" ) ;              self . add_reply ( crate ::tr ! ( self ,   "member_list_heading" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             self . append_member_list_to_reply ( ) ;              self . append_member_list_to_reply ( ) ;  
			
		
	
		
		
			
				
					
					         }   else   {          }   else   {  
			
		
	
		
		
			
				
					
					             self . add_reply ( "Group admins:" ) ;              self . add_reply ( crate ::tr ! ( self ,   "admin_list_heading" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             self . append_admin_list_to_reply ( ) ;              self . append_admin_list_to_reply ( ) ;  
			
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  cmd_list_tags ( & mut   self )   {      async   fn  cmd_list_tags ( & mut   self )   {  
			
		
	
		
		
			
				
					
					         self . add_reply ( "Group tags:" ) ;          self . add_reply ( crate ::tr ! ( self ,   "tag_list_heading" ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         self . want_markdown   =   true ;          self . want_markdown   =   true ;  
			
		
	
		
		
			
				
					
					         let   mut   tags   =   self . config . get_tags ( ) . collect ::< Vec < _ > > ( ) ;          let   mut   tags   =   self . config . get_tags ( ) . collect ::< Vec < _ > > ( ) ;  
			
		
	
		
		
			
				
					
					         tags . sort ( ) ;          tags . sort ( ) ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         let   mut   to_add   =   String ::new ( ) ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         for   t   in   tags   {          for   t   in   tags   {  
			
		
	
		
		
			
				
					
					             self . replies . push ( format! ( "- {}" ,   t ) . to_string ( ) ) ;              to_add . push_str ( & crate ::tr ! ( self ,   "tag_list_entry" ,   tag = t ) ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					         self . add_reply ( to_add ) ;  
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  cmd_leave ( & mut   self )   {      async   fn  cmd_leave ( & mut   self )   {  
			
		
	
		
		
			
				
					
					         if   self . config . is_member_or_admin ( & self . status_acct )   {          if   self . config . is_member_or_admin ( & self . status_acct )   {  
			
		
	
		
		
			
				
					
					             // admin can leave but that's a bad idea
              // admin can leave but that's a bad idea
  
			
		
	
		
		
			
				
					
					             let   _   =   self . config . set_member ( & self . status_acct ,   false ) ;              let   _   =   self . config . set_member ( & self . status_acct ,   false ) ;  
			
		
	
		
		
			
				
					
					             self . add_reply (              self . add_reply ( crate ::tr ! ( self ,   "cmd_leave_resp" ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					                 "You're no longer a group member. Unfollow the group user to stop receiving group messages." ,  
			
		
	
		
		
			
				
					
					             ) ;  
			
		
	
		
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         self . unfollow_user_by_id ( & self . status_user_id )          self . unfollow_user_by_id ( & self . status_user_id )  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -740,12 +723,7 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					             // Not a member yet
              // Not a member yet
  
			
		
	
		
		
			
				
					
					             if   self . config . is_member_only ( )   {              if   self . config . is_member_only ( )   {  
			
		
	
		
		
			
				
					
					                 // No you can't
                  // No you can't
  
			
		
	
		
		
			
				
					
					                 self . add_reply (                  self . add_reply ( crate ::tr ! ( self ,   "welcome_closed" ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					                     " \  
			
		
	
		
		
			
				
					
					                     Sorry ,   this   group   is   closed   to   new   sign - ups . \ n \  
			
		
	
		
		
			
				
					
					                     Please   ask   one   of   the   group   admins   to   add   you :" ,  
			
		
	
		
		
			
				
					
					                 ) ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
	
		
		
			
				
					
					                 self . append_admin_list_to_reply ( ) ;                  self . append_admin_list_to_reply ( ) ;  
			
		
	
		
		
			
				
					
					             }   else   {              }   else   {  
			
		
	
		
		
			
				
					
					                 // Open access, try to follow back
                  // Open access, try to follow back
  
			
		
	
	
		
		
			
				
					
						
						
						
							
								 
						
					 
					@ -753,21 +731,13 @@ impl<'a> ProcessMention<'a> { 
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					                 // This only fails if the user is banned, but that is filtered above
                  // This only fails if the user is banned, but that is filtered above
  
			
		
	
		
		
			
				
					
					                 let   _   =   self . config . set_member ( & self . status_acct ,   true ) ;                  let   _   =   self . config . set_member ( & self . status_acct ,   true ) ;  
			
		
	
		
		
			
				
					
					                 self . add_reply (                  self . add_reply ( crate ::tr ! ( self ,   "welcome_join_cmd" ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					                     " \  
			
		
	
		
		
			
				
					
					                     Welcome   to   the   group !   The   group   user   will   now   follow   you   to   complete   the   sign - up .   \  
			
		
	
		
		
			
				
					
					                     Make   sure   you   follow   back   to   receive   shared   posts ! \ n \ n \  
			
		
	
		
		
			
				
					
					                     Use   / help   for   more   info . " ,  
			
		
	
		
		
			
				
					
					                 ) ;  
			
		
	
		
		
	
		
		
			
				
					
					             }              }  
			
		
	
		
		
			
				
					
					         }          }  
			
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  cmd_ping ( & mut   self )   {      async   fn  cmd_ping ( & mut   self )   {  
			
		
	
		
		
			
				
					
					         self . add_reply ( format! (          self . add_reply ( crate ::tr ! ( self ,   "ping_response" ,   version   =   env! ( "CARGO_PKG_VERSION" ) ) ) ;  
			
				
				
			
		
	
		
		
			
				
					
					             "pong, this is fedigroups service v{}" ,  
			
		
	
		
		
			
				
					
					             env! ( "CARGO_PKG_VERSION" )  
			
		
	
		
		
			
				
					
					         ) ) ;  
			
		
	
		
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     async   fn  unfollow_by_acct ( & self ,   acct : & str )   -> Result < ( ) ,   GroupError >   {      async   fn  unfollow_by_acct ( & self ,   acct : & str )   -> Result < ( ) ,   GroupError >   {  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -917,21 +887,21 @@ mod test { 
			
		
	
		
		
			
				
					
					         let   to_split   =   "foo\nbar\nbaz" ;          let   to_split   =   "foo\nbar\nbaz" ;  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					         let   parts   =   super ::smart_split ( to_split ,   None ,   1000 ) ;          let   parts   =   super ::smart_split ( to_split ,   None ,   1000 ) ;  
			
		
	
		
		
			
				
					
					         assert_eq! ( vec! [ "foo\nbar\nbaz" . to_string ( ) , ] ,   parts ) ;          assert_eq! ( vec! [ "foo\nbar\nbaz" . to_string ( ) ] ,   parts ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     #[ test ]      #[ test ]  
			
		
	
		
		
			
				
					
					     fn  test_smart_split_nosplit_prefix ( )   {      fn  test_smart_split_nosplit_prefix ( )   {  
			
		
	
		
		
			
				
					
					         let   to_split   =   "foo\nbar\nbaz" ;          let   to_split   =   "foo\nbar\nbaz" ;  
			
		
	
		
		
			
				
					
					         let   parts   =   super ::smart_split ( to_split ,   Some ( "PREFIX" . to_string ( ) ) ,   1000 ) ;          let   parts   =   super ::smart_split ( to_split ,   Some ( "PREFIX" . to_string ( ) ) ,   1000 ) ;  
			
		
	
		
		
			
				
					
					         assert_eq! ( vec! [ "PREFIXfoo\nbar\nbaz" . to_string ( ) , ] ,   parts ) ;          assert_eq! ( vec! [ "PREFIXfoo\nbar\nbaz" . to_string ( ) ] ,   parts ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     #[ test ]      #[ test ]  
			
		
	
		
		
			
				
					
					     fn  test_smart_split_prefix_each ( )   {      fn  test_smart_split_prefix_each ( )   {  
			
		
	
		
		
			
				
					
					         let   to_split   =   "1234\n56\n7" ;          let   to_split   =   "1234\n56\n7" ;  
			
		
	
		
		
			
				
					
					         let   parts   =   super ::smart_split ( to_split ,   Some ( "PREFIX" . to_string ( ) ) ,   10 ) ;          let   parts   =   super ::smart_split ( to_split ,   Some ( "PREFIX" . to_string ( ) ) ,   10 ) ;  
			
		
	
		
		
			
				
					
					         assert_eq! ( vec! [ "PREFIX1234" . to_string ( ) ,   "PREFIX56\n7" . to_string ( ) , ] ,   parts ) ;          assert_eq! ( vec! [ "PREFIX1234" . to_string ( ) ,   "PREFIX56\n7" . to_string ( ) ] ,   parts ) ;  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					     }      }  
			
		
	
		
		
			
				
					
					
 
			
		
	
		
		
			
				
					
					     #[ test ]      #[ test ]  
			
		
	
	
		
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
					@ -973,7 +943,7 @@ mod test { 
			
		
	
		
		
			
				
					
					         let   to_split   =   "one two threefourfive six" ;          let   to_split   =   "one two threefourfive six" ;  
			
		
	
		
		
			
				
					
					         let   parts   =   super ::smart_split ( to_split ,   None ,   10 ) ;          let   parts   =   super ::smart_split ( to_split ,   None ,   10 ) ;  
			
		
	
		
		
			
				
					
					         assert_eq! (          assert_eq! (  
			
		
	
		
		
			
				
					
					             vec! [ "one two" . to_string ( ) ,   "threefourf" . to_string ( ) ,   "ive six" . to_string ( ) , ] ,              vec! [ "one two" . to_string ( ) ,   "threefourf" . to_string ( ) ,   "ive six" . to_string ( ) ] ,  
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					             parts              parts  
			
		
	
		
		
			
				
					
					         ) ;          ) ;  
			
		
	
		
		
			
				
					
					     }      }