|
|
|
@ -91,9 +91,7 @@ impl GroupHandle { |
|
|
|
|
|
|
|
|
|
loop { |
|
|
|
|
if next_save < Instant::now() { |
|
|
|
|
self.save_if_needed() |
|
|
|
|
.await |
|
|
|
|
.log_error("Failed to save group"); |
|
|
|
|
self.save_if_needed().await.log_error("Failed to save group"); |
|
|
|
|
next_save = Instant::now() + PERIODIC_SAVE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -104,27 +102,18 @@ impl GroupHandle { |
|
|
|
|
|
|
|
|
|
match tokio::time::timeout(timeout, events.next()).await { |
|
|
|
|
Ok(Some(event)) => { |
|
|
|
|
debug!( |
|
|
|
|
"(@{}) Event: {}", |
|
|
|
|
self.config.get_acct(), |
|
|
|
|
EventDisplay(&event) |
|
|
|
|
); |
|
|
|
|
debug!("(@{}) Event: {}", self.config.get_acct(), EventDisplay(&event)); |
|
|
|
|
match event { |
|
|
|
|
Event::Update(_status) => {} |
|
|
|
|
Event::Notification(n) => { |
|
|
|
|
self.handle_notification(n) |
|
|
|
|
.await |
|
|
|
|
.log_error("Error handling a notification"); |
|
|
|
|
self.handle_notification(n).await.log_error("Error handling a notification"); |
|
|
|
|
} |
|
|
|
|
Event::Delete(_id) => {} |
|
|
|
|
Event::FiltersChanged => {} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Ok(None) => { |
|
|
|
|
warn!( |
|
|
|
|
"Group @{} socket closed, restarting...", |
|
|
|
|
self.config.get_acct() |
|
|
|
|
); |
|
|
|
|
warn!("Group @{} socket closed, restarting...", self.config.get_acct()); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
Err(_) => { |
|
|
|
@ -181,13 +170,9 @@ impl GroupHandle { |
|
|
|
|
// Someone tagged the group in OP, boost it.
|
|
|
|
|
info!("Boosting OP mention"); |
|
|
|
|
tokio::time::sleep(DELAY_BEFORE_ACTION).await; |
|
|
|
|
self.client |
|
|
|
|
.reblog(&status.id) |
|
|
|
|
.await |
|
|
|
|
.log_error("Failed to boost"); |
|
|
|
|
self.client.reblog(&status.id).await.log_error("Failed to boost"); |
|
|
|
|
} else { |
|
|
|
|
replies |
|
|
|
|
.push("You are not allowed to post to this group".to_string()); |
|
|
|
|
replies.push("You are not allowed to post to this group".to_string()); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
debug!("Not OP, ignore mention"); |
|
|
|
@ -208,10 +193,7 @@ impl GroupHandle { |
|
|
|
|
if can_write { |
|
|
|
|
do_boost_prev_post = status.in_reply_to_id.is_some(); |
|
|
|
|
} else { |
|
|
|
|
replies.push( |
|
|
|
|
"You are not allowed to share to this group" |
|
|
|
|
.to_string(), |
|
|
|
|
); |
|
|
|
|
replies.push("You are not allowed to share to this group".to_string()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
StatusCommand::BanUser(u) => { |
|
|
|
@ -221,24 +203,17 @@ impl GroupHandle { |
|
|
|
|
match self.config.ban_user(&u, true) { |
|
|
|
|
Ok(_) => { |
|
|
|
|
any_admin_cmd = true; |
|
|
|
|
replies.push(format!( |
|
|
|
|
"User {} banned from group!", |
|
|
|
|
u |
|
|
|
|
)); |
|
|
|
|
replies.push(format!("User {} banned from group!", u)); |
|
|
|
|
|
|
|
|
|
// no announcement here
|
|
|
|
|
} |
|
|
|
|
Err(e) => { |
|
|
|
|
replies.push(format!( |
|
|
|
|
"Failed to ban user {}: {}", |
|
|
|
|
u, e |
|
|
|
|
)); |
|
|
|
|
replies.push(format!("Failed to ban user {}: {}", u, e)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
replies |
|
|
|
|
.push("Only admins can manage user bans".to_string()); |
|
|
|
|
replies.push("Only admins can manage user bans".to_string()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
StatusCommand::UnbanUser(u) => { |
|
|
|
@ -258,8 +233,7 @@ impl GroupHandle { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
replies |
|
|
|
|
.push("Only admins can manage user bans".to_string()); |
|
|
|
|
replies.push("Only admins can manage user bans".to_string()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
StatusCommand::BanServer(s) => { |
|
|
|
@ -268,26 +242,16 @@ impl GroupHandle { |
|
|
|
|
match self.config.ban_server(&s, true) { |
|
|
|
|
Ok(_) => { |
|
|
|
|
any_admin_cmd = true; |
|
|
|
|
announcements.push(format!( |
|
|
|
|
"Server \"{}\" has been banned.", |
|
|
|
|
s |
|
|
|
|
)); |
|
|
|
|
replies.push(format!( |
|
|
|
|
"Server {} banned from group!", |
|
|
|
|
s |
|
|
|
|
)); |
|
|
|
|
announcements.push(format!("Server \"{}\" has been banned.", s)); |
|
|
|
|
replies.push(format!("Server {} banned from group!", s)); |
|
|
|
|
} |
|
|
|
|
Err(e) => { |
|
|
|
|
replies.push(format!( |
|
|
|
|
"Failed to ban server {}: {}", |
|
|
|
|
s, e |
|
|
|
|
)); |
|
|
|
|
replies.push(format!("Failed to ban server {}: {}", s, e)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
replies |
|
|
|
|
.push("Only admins can manage server bans".to_string()); |
|
|
|
|
replies.push("Only admins can manage server bans".to_string()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
StatusCommand::UnbanServer(s) => { |
|
|
|
@ -296,12 +260,8 @@ impl GroupHandle { |
|
|
|
|
match self.config.ban_server(&s, false) { |
|
|
|
|
Ok(_) => { |
|
|
|
|
any_admin_cmd = true; |
|
|
|
|
announcements.push(format!( |
|
|
|
|
"Server \"{}\" has been un-banned.", |
|
|
|
|
s |
|
|
|
|
)); |
|
|
|
|
replies |
|
|
|
|
.push(format!("Server {} un-banned!", s)); |
|
|
|
|
announcements.push(format!("Server \"{}\" has been un-banned.", s)); |
|
|
|
|
replies.push(format!("Server {} un-banned!", s)); |
|
|
|
|
} |
|
|
|
|
Err(_) => { |
|
|
|
|
unreachable!() |
|
|
|
@ -309,8 +269,7 @@ impl GroupHandle { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
replies |
|
|
|
|
.push("Only admins can manage server bans".to_string()); |
|
|
|
|
replies.push("Only admins can manage server bans".to_string()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
StatusCommand::AddMember(u) => { |
|
|
|
@ -320,23 +279,15 @@ impl GroupHandle { |
|
|
|
|
match self.config.set_member(&u, true) { |
|
|
|
|
Ok(_) => { |
|
|
|
|
any_admin_cmd = true; |
|
|
|
|
replies.push(format!( |
|
|
|
|
"User {} added to the group!", |
|
|
|
|
u |
|
|
|
|
)); |
|
|
|
|
replies.push(format!("User {} added to the group!", u)); |
|
|
|
|
|
|
|
|
|
if self.config.is_member_only() { |
|
|
|
|
announcements.push(format!( |
|
|
|
|
"Welcome new member @{} to the group!", |
|
|
|
|
u |
|
|
|
|
)); |
|
|
|
|
announcements |
|
|
|
|
.push(format!("Welcome new member @{} to the group!", u)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Err(e) => { |
|
|
|
|
replies.push(format!( |
|
|
|
|
"Failed to add user {} to group: {}", |
|
|
|
|
u, e |
|
|
|
|
)); |
|
|
|
|
replies.push(format!("Failed to add user {} to group: {}", u, e)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -351,10 +302,7 @@ impl GroupHandle { |
|
|
|
|
match self.config.set_member(&u, false) { |
|
|
|
|
Ok(_) => { |
|
|
|
|
any_admin_cmd = true; |
|
|
|
|
replies.push(format!( |
|
|
|
|
"User {} removed from the group.", |
|
|
|
|
u |
|
|
|
|
)); |
|
|
|
|
replies.push(format!("User {} removed from the group.", u)); |
|
|
|
|
} |
|
|
|
|
Err(_) => { |
|
|
|
|
unreachable!() |
|
|
|
@ -372,14 +320,9 @@ impl GroupHandle { |
|
|
|
|
match self.config.set_admin(&u, true) { |
|
|
|
|
Ok(_) => { |
|
|
|
|
any_admin_cmd = true; |
|
|
|
|
replies.push(format!( |
|
|
|
|
"User {} is now a group admin!", |
|
|
|
|
u |
|
|
|
|
)); |
|
|
|
|
announcements.push(format!( |
|
|
|
|
"User @{} can now manage this group!", |
|
|
|
|
u |
|
|
|
|
)); |
|
|
|
|
replies.push(format!("User {} is now a group admin!", u)); |
|
|
|
|
announcements |
|
|
|
|
.push(format!("User @{} can now manage this group!", u)); |
|
|
|
|
} |
|
|
|
|
Err(e) => { |
|
|
|
|
replies.push(format!( |
|
|
|
@ -400,20 +343,13 @@ impl GroupHandle { |
|
|
|
|
match self.config.set_admin(&u, false) { |
|
|
|
|
Ok(_) => { |
|
|
|
|
any_admin_cmd = true; |
|
|
|
|
replies.push(format!( |
|
|
|
|
"User {} is no longer a group admin!", |
|
|
|
|
u |
|
|
|
|
)); |
|
|
|
|
announcements.push(format!( |
|
|
|
|
"User @{} no longer manages this group.", |
|
|
|
|
u |
|
|
|
|
)); |
|
|
|
|
replies.push(format!("User {} is no longer a group admin!", u)); |
|
|
|
|
announcements |
|
|
|
|
.push(format!("User @{} no longer manages this group.", u)); |
|
|
|
|
} |
|
|
|
|
Err(e) => { |
|
|
|
|
replies.push(format!( |
|
|
|
|
"Failed to revoke {}'s group admin: {}", |
|
|
|
|
u, e |
|
|
|
|
)); |
|
|
|
|
replies |
|
|
|
|
.push(format!("Failed to revoke {}'s group admin: {}", u, e)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -426,14 +362,11 @@ impl GroupHandle { |
|
|
|
|
if self.config.is_member_only() { |
|
|
|
|
any_admin_cmd = true; |
|
|
|
|
self.config.set_member_only(false); |
|
|
|
|
replies |
|
|
|
|
.push("Group changed to open-access".to_string()); |
|
|
|
|
announcements |
|
|
|
|
.push("This group is now open-access!".to_string()); |
|
|
|
|
replies.push("Group changed to open-access".to_string()); |
|
|
|
|
announcements.push("This group is now open-access!".to_string()); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
replies |
|
|
|
|
.push("Only admins can set group options".to_string()); |
|
|
|
|
replies.push("Only admins can set group options".to_string()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
StatusCommand::CloseGroup => { |
|
|
|
@ -441,14 +374,11 @@ impl GroupHandle { |
|
|
|
|
if !self.config.is_member_only() { |
|
|
|
|
any_admin_cmd = true; |
|
|
|
|
self.config.set_member_only(true); |
|
|
|
|
replies |
|
|
|
|
.push("Group changed to member-only".to_string()); |
|
|
|
|
announcements |
|
|
|
|
.push("This group is now member-only!".to_string()); |
|
|
|
|
replies.push("Group changed to member-only".to_string()); |
|
|
|
|
announcements.push("This group is now member-only!".to_string()); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
replies |
|
|
|
|
.push("Only admins can set group options".to_string()); |
|
|
|
|
replies.push("Only admins can set group options".to_string()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
StatusCommand::Help => { |
|
|
|
@ -474,12 +404,13 @@ impl GroupHandle { |
|
|
|
|
|
|
|
|
|
replies.push( |
|
|
|
|
"\nTo share an original post, mention the group user.\n\ |
|
|
|
|
Posts with commands, and replies, won't be shared.\n\ |
|
|
|
|
Replies and mentions with commands won't be shared.\n\ |
|
|
|
|
\n\ |
|
|
|
|
**Supported commands:**\n\ |
|
|
|
|
`/ignore, /i` - make the group completely ignore the post\n\ |
|
|
|
|
`/members, /who` - show group members / admins\n\ |
|
|
|
|
`/boost, /b` - boost the replied-to post into the group" |
|
|
|
|
`/boost, /b` - boost the replied-to post into the group\n\ |
|
|
|
|
`/ping - check that the service is alive" |
|
|
|
|
.to_string(), |
|
|
|
|
); |
|
|
|
|
|
|
|
|
@ -497,7 +428,9 @@ impl GroupHandle { |
|
|
|
|
`/deop, /deadmin user` - revoke admin rights\n\ |
|
|
|
|
`/opengroup` - make member-only\n\ |
|
|
|
|
`/closegroup` - make public-access\n\ |
|
|
|
|
`/announce x` - make a public announcement from the rest of the status".to_string()); |
|
|
|
|
`/announce x` - make a public announcement from the rest of the status" |
|
|
|
|
.to_string(), |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
StatusCommand::ListMembers => { |
|
|
|
@ -505,10 +438,8 @@ impl GroupHandle { |
|
|
|
|
if is_admin { |
|
|
|
|
if self.config.is_member_only() { |
|
|
|
|
replies.push("Group members:".to_string()); |
|
|
|
|
let admins = |
|
|
|
|
self.config.get_admins().collect::<HashSet<_>>(); |
|
|
|
|
let mut members = |
|
|
|
|
self.config.get_members().collect::<Vec<_>>(); |
|
|
|
|
let admins = self.config.get_admins().collect::<HashSet<_>>(); |
|
|
|
|
let mut members = self.config.get_members().collect::<Vec<_>>(); |
|
|
|
|
members.extend(admins.iter()); |
|
|
|
|
members.sort(); |
|
|
|
|
members.dedup(); |
|
|
|
@ -528,8 +459,7 @@ impl GroupHandle { |
|
|
|
|
|
|
|
|
|
if show_admins { |
|
|
|
|
replies.push("Group admins:".to_string()); |
|
|
|
|
let mut admins = |
|
|
|
|
self.config.get_admins().collect::<Vec<_>>(); |
|
|
|
|
let mut admins = self.config.get_admins().collect::<Vec<_>>(); |
|
|
|
|
admins.sort(); |
|
|
|
|
for a in admins { |
|
|
|
|
replies.push(a.to_string()); |
|
|
|
@ -543,6 +473,9 @@ impl GroupHandle { |
|
|
|
|
replies.push("You left the group.".to_string()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
StatusCommand::Ping => { |
|
|
|
|
replies.push("Pong".to_string()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -566,11 +499,7 @@ impl GroupHandle { |
|
|
|
|
.build() |
|
|
|
|
.expect("error build status"); |
|
|
|
|
|
|
|
|
|
let _ = self |
|
|
|
|
.client |
|
|
|
|
.new_status(post) |
|
|
|
|
.await |
|
|
|
|
.log_error("Failed to post"); |
|
|
|
|
let _ = self.client.new_status(post).await.log_error("Failed to post"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if !announcements.is_empty() { |
|
|
|
@ -578,15 +507,11 @@ impl GroupHandle { |
|
|
|
|
let post = StatusBuilder::new() |
|
|
|
|
.status(format!("**📢 Group announcement**\n{msg}", msg = msg)) |
|
|
|
|
.content_type("text/markdown") |
|
|
|
|
.visibility(Visibility::Unlisted) |
|
|
|
|
.visibility(Visibility::Public) |
|
|
|
|
.build() |
|
|
|
|
.expect("error build status"); |
|
|
|
|
|
|
|
|
|
let _ = self |
|
|
|
|
.client |
|
|
|
|
.new_status(post) |
|
|
|
|
.await |
|
|
|
|
.log_error("Failed to post"); |
|
|
|
|
let _ = self.client.new_status(post).await.log_error("Failed to post"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if any_admin_cmd { |
|
|
|
@ -598,8 +523,7 @@ impl GroupHandle { |
|
|
|
|
info!("New follower!"); |
|
|
|
|
tokio::time::sleep(Duration::from_millis(500)).await; |
|
|
|
|
|
|
|
|
|
let text = |
|
|
|
|
if self.config.is_member_only() { |
|
|
|
|
let text = if self.config.is_member_only() { |
|
|
|
|
// Admins are listed without @, so they won't become handles here.
|
|
|
|
|
// Tagging all admins would be annoying.
|
|
|
|
|
let mut admins = self.config.get_admins().cloned().collect::<Vec<_>>(); |
|
|
|
@ -607,7 +531,10 @@ impl GroupHandle { |
|
|
|
|
format!( |
|
|
|
|
"@{user} welcome to the group! This is a member-only group, you won't be \ |
|
|
|
|
able to post. Ask the group admins if you wish to join!\n\n\ |
|
|
|
|
Admins: {admins}", user = notif_acct, admins = admins.join(", ")) |
|
|
|
|
Admins: {admins}", |
|
|
|
|
user = notif_acct, |
|
|
|
|
admins = admins.join(", ") |
|
|
|
|
) |
|
|
|
|
} else { |
|
|
|
|
format!( |
|
|
|
|
"@{user} welcome to the group! \ |
|
|
|
@ -623,11 +550,7 @@ impl GroupHandle { |
|
|
|
|
.build() |
|
|
|
|
.expect("error build status"); |
|
|
|
|
|
|
|
|
|
let _ = self |
|
|
|
|
.client |
|
|
|
|
.new_status(post) |
|
|
|
|
.await |
|
|
|
|
.log_error("Failed to post"); |
|
|
|
|
let _ = self.client.new_status(post).await.log_error("Failed to post"); |
|
|
|
|
} |
|
|
|
|
_ => {} |
|
|
|
|
} |
|
|
|
@ -670,9 +593,7 @@ impl GroupHandle { |
|
|
|
|
|
|
|
|
|
for n in notifs_to_handle { |
|
|
|
|
debug!("Handling missed notification: {}", NotificationDisplay(&n)); |
|
|
|
|
self.handle_notification(n) |
|
|
|
|
.await |
|
|
|
|
.log_error("Error handling a notification"); |
|
|
|
|
self.handle_notification(n).await.log_error("Error handling a notification"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(true) |
|
|
|
|