Block, unblock, mute, and unmute functionality added. I never needed to block, mute, etc anyone so these are untested but they do follow the spec as best as I understand it, so they should theoretically work.

This commit is contained in:
Storm Dragon
2025-08-06 19:28:16 -04:00
parent d58e5045bd
commit 9f2bf588e1
+120 -38
View File
@@ -150,7 +150,7 @@ BEGIN {
# notificationpause=0 # Notification refresh rate (0=use main pause)
# === INTERACTION ===
# mentions=0 # Show mentions in timeline
# mentions=0 # Legacy flag (mentions included automatically)
# synch=0 # Synchronous mode (blocks on requests)
# maxhist=19 # Command history size
# hold=0 # Hold mode for piped input
@@ -253,7 +253,7 @@ EOF
apibase fediverseserver queryurl idurl delurl dmdelurl favsurl
notificationurl markersurl
favurl favdelurl followurl leaveurl
dmupdate credurl blockurl blockdelurl friendsurl
dmupdate credurl blockurl blockdelurl muteurl mutedelurl friendsurl
modifyliurl adduliurl delliurl getliurl getlisurl getfliurl
creliurl delliurl deluliurl crefliurl delfliurl
getuliurl getufliurl dmsenturl reblogurl boostsbyurl dmidurl
@@ -278,7 +278,7 @@ EOF
urlopen cli_browser gui_browser delurl notrack dmdelurl favsurl
favurl favdelurl slowpost notifies filter colourdefault
followurl leaveurl dmupdate mentions backload
lat long location searchhits blockurl blockdelurl woeid
lat long location searchhits blockurl blockdelurl muteurl mutedelurl woeid
nocounter linelength friendsurl followersurl lists
modifyliurl adduliurl delliurl getliurl getlisurl getfliurl
creliurl delliurl deluliurl crefliurl delfliurl atrendurl
@@ -393,6 +393,8 @@ EOF
$leaveurl = "${apibase}/accounts/%I/unfollow";
$blockurl = "${apibase}/accounts/%I/block";
$blockdelurl = "${apibase}/accounts/%I/unblock";
$muteurl = "${apibase}/accounts/%I/mute";
$mutedelurl = "${apibase}/accounts/%I/unmute";
$favurl = "${apibase}/statuses/%I/favourite";
$favdelurl = "${apibase}/statuses/%I/unfavourite";
$blockingurl = "${apibase}/accounts/relationships?id[]=%I";
@@ -1337,6 +1339,8 @@ $followurl ||= "${apibase}/accounts/%I/follow";
$leaveurl ||= "${apibase}/accounts/%I/unfollow";
$blockurl ||= "${apibase}/accounts/%I/block";
$blockdelurl ||= "${apibase}/accounts/%I/unblock";
$muteurl ||= "${apibase}/accounts/%I/mute";
$mutedelurl ||= "${apibase}/accounts/%I/unmute";
$friendsurl ||= "${apibase}/accounts/%I/following";
$followersurl ||= "${apibase}/accounts/%I/followers";
# Twitter friendships/update removed - fediverse uses individual follow/unfollow endpoints
@@ -1495,17 +1499,8 @@ if (!$dostream || $authtype eq 'basic' || !$ssl || $script || $anonymous || $syn
} else {
print $stdout "-- Streaming API enabled\n";
# streams change mentions behaviour; we get them automatically.
# warn the user if the current settings are suboptimal.
if ($mentions) {
if ($nostreamreplies) {
print $stdout
"** warning: -mentions and -nostreamreplies are very inefficient together\n";
} else {
print $stdout
"** warning: -mentions not generally needed in Streaming mode\n";
}
}
# In fediverse, mentions are included automatically in home timeline
# and handled via background notifications - no separate flag needed
}
} else { $dostream = 0; } # -status suppresses streaming
if (!$dostream && $streamallreplies) {
@@ -3175,6 +3170,12 @@ USER COMMANDS:
/wagain username - combines them all
/follow username - follow a username
/leave username - stop following a username
/block username - block a username
/block d4 - block author of post d4
/unblock username - unblock a username
/mute username - mute a username (also mutes notifications)
/mute d4 - mute author of post d4
/unmute username - unmute a username
/followers [username] - show who follows you (or username)
/following [username] - show who you follow (or username follows)
/dm username message - send a username a DM
@@ -4469,24 +4470,91 @@ EOF
return 0;
}
# block and unblock users
if (m#^/(block|unblock) \@?([^\s/]+)$#) {
# block and unblock users (with menu code support)
if (m#^/(block|unblock)(?:\s+([a-z]+\d+)|\s+\@?([^\s/]+))$#) {
my $m = $1;
my $u = lc($2);
my $code = $2; # menu code like 'd4'
my $username = $3; # username like '@user'
my $target_user;
my $post_ref;
if ($code) {
# Menu code provided - get username from timeline
$post_ref = $tl{$code};
if (!$post_ref) {
print $stdout "-- sorry, I don't know that code.\n";
return 0;
}
$target_user = lc($post_ref->{'user'}->{'acct'} || $post_ref->{'user'}->{'username'});
if (!$target_user) {
print $stdout "-- sorry, couldn't get user from that post.\n";
return 0;
}
} else {
# Username provided directly
$target_user = lc($username);
}
if ($m eq 'block') {
$answer = lc(&linein(
"-- sure you want to block $u? (only y or Y is affirmative):"));
my $confirm_msg = $code ?
"-- sure you want to block $target_user (author of $code)? (only y or Y is affirmative):" :
"-- sure you want to block $target_user? (only y or Y is affirmative):";
$answer = lc(&linein($confirm_msg));
if ($answer ne 'y') {
print $stdout "-- ok, $u is NOT blocked.\n";
print $stdout "-- ok, $target_user is NOT blocked.\n";
return 0;
}
}
&boruuser($u, 1,
&boruuser($target_user, 1,
(($m eq 'block') ? $blockurl : $blockdelurl),
(($m eq 'block') ? 'started' : 'stopped'));
return 0;
}
# mute and unmute users (with menu code support)
if (m#^/(mute|unmute)(?:\s+([a-z]+\d+)|\s+\@?([^\s/]+))$#) {
my $m = $1;
my $code = $2; # menu code like 'd4'
my $username = $3; # username like '@user'
my $target_user;
my $post_ref;
if ($code) {
# Menu code provided - get username from timeline
$post_ref = $tl{$code};
if (!$post_ref) {
print $stdout "-- sorry, I don't know that code.\n";
return 0;
}
$target_user = lc($post_ref->{'user'}->{'acct'} || $post_ref->{'user'}->{'username'});
if (!$target_user) {
print $stdout "-- sorry, couldn't get user from that post.\n";
return 0;
}
} else {
# Username provided directly
$target_user = lc($username);
}
if ($m eq 'mute') {
my $confirm_msg = $code ?
"-- sure you want to mute $target_user (author of $code)? (only y or Y is affirmative):" :
"-- sure you want to mute $target_user? (only y or Y is affirmative):";
$answer = lc(&linein($confirm_msg));
if ($answer ne 'y') {
print $stdout "-- ok, $target_user is NOT muted.\n";
return 0;
}
}
&muteuser($target_user, 1,
(($m eq 'mute') ? $muteurl : $mutedelurl),
(($m eq 'mute') ? 'started' : 'stopped'));
return 0;
}
# list support
# /withlist (/withlis, /with, /wl)
if (s#^/(withlist|withlis|withl|with|wl)\s+([^/\s]+)\s+## &&
@@ -6260,22 +6328,8 @@ sub refresh {
}
}
# add stream for replies, if requested
if ($mentions) {
# same thing
my $r = &grabjson($rurl,
($dostream && !$nostreamreplies) ? $last_id : $fetch_id,
0,
(($last_id) ? 250
: $fetchwanted || $backload), {
"type" => "reply",
"payload" => ""
}, 1);
push(@streams, $r)
if (defined($r) &&
ref($r) eq 'ARRAY' &&
scalar(@{ $r }));
}
# Mentions are included in home timeline and handled via background notifications
# No separate mentions fetch needed in fediverse (unlike Twitter)
# next handle hashtags and tracktags
# failure here does not abort, because search may be down independently
@@ -7420,6 +7474,34 @@ sub boruuser {
return 0;
}
# mute or unmute a user
sub muteuser {
my $uname = shift;
my $interactive = shift;
my $basef = shift;
my $verb = shift;
# Look up account ID for the username
my $account_id = &lookup_account_id($uname);
if (!$account_id) {
&report_account_not_found($uname, $interactive);
return 1;
}
# Substitute account ID into URL template
my $api_url = $basef;
$api_url =~ s/%I/$account_id/g;
# For mute, include notifications=true parameter (mute notifications too)
my $post_data = ($verb eq 'started') ? "notifications=true&id=$account_id" : "id=$account_id";
my ($en, $em) = &central_cd_dispatch($post_data,
$interactive, $api_url);
print $stdout "-- ok, you have $verb muting user $uname.\n"
if ($interactive && !$en);
return 0;
}
# enable or disable reposts for a user
sub rtsonoffuser {
my $uname = shift;
@@ -8551,7 +8633,7 @@ sub defaultautocompletion {
'/unset', '/verbose', '/short', '/follow', '/unfollow',
'/doesfollow', '/search', '/tron', '/troff',
'/delete', '/deletelast', '/dump',
'/track', '/trends', '/block', '/unblock',
'/track', '/trends', '/block', '/unblock', '/mute', '/unmute',
'/fave', '/faves', '/unfave', '/eval');
}
@rlkeys = keys(%readline_completion);