From 4379660dfd17091d09945de18966cd4e4fdff7b2 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Sun, 27 Jul 2025 22:53:05 -0400 Subject: [PATCH] Next huge chunk of refactoring completed. --- ttyverse.pl | 153 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 98 insertions(+), 55 deletions(-) diff --git a/ttyverse.pl b/ttyverse.pl index 3e2e06f..d17f0b6 100755 --- a/ttyverse.pl +++ b/ttyverse.pl @@ -252,7 +252,7 @@ EOF getuliurl getufliurl dmsenturl reblogurl boostsbyurl dmidurl statusliurl followliurl leaveliurl followersurl oauthurl oauthauthurl oauthaccurl oauthbase wtrendurl - atrendurl frupdurl lookupidurl boostsofmeurl + atrendurl lookupidurl ); %opts_secret = map { $_ => 1} qw( superverbose ttytteristas ); %opts_comma_delimit = map { $_ => 1 } qw( @@ -278,7 +278,7 @@ EOF getuliurl getufliurl dmsenturl reblogurl boostsbyurl wtrendurl statusliurl followliurl leaveliurl dmidurl nostreamreplies frupdurl filterusers filterats filterrts filterflags - filteratonly nofilter boostsofmeurl + filteratonly nofilter ); %opts_others = map { $_ => 1 } qw( lynx curl seven silent maxhist noansi hold status daemon timestamp twarg user anonymous script readline @@ -1025,19 +1025,20 @@ $idurl ||= "${apibase}/statuses/%I"; $delurl ||= "${apibase}/statuses/%I"; $reblogurl ||= "${apibase}/statuses/%I/reblog"; -$boostsbyurl ||= "${apibase}/statuses/reposts/%I.json"; -$boostsofmeurl ||= "${apibase}/statuses/reposts_of_me.json"; +# Twitter endpoints removed - not available in fediverse +# $boostsbyurl: Use /api/v1/statuses/%I/reblogged_by instead +# $boostsofmeurl: No direct equivalent in fediverse (privacy feature) $wurl ||= "${apibase}/accounts/%I"; -$frurl ||= "${apibase}/friendships/show.json"; +# Twitter friendships API removed - use /api/v1/accounts/relationships instead $followurl ||= "${apibase}/accounts/%I/follow"; $leaveurl ||= "${apibase}/accounts/%I/unfollow"; $blockurl ||= "${apibase}/accounts/%I/block"; $blockdelurl ||= "${apibase}/accounts/%I/unblock"; $friendsurl ||= "${apibase}/accounts/%I/following"; $followersurl ||= "${apibase}/accounts/%I/followers"; -$frupdurl ||= "${apibase}/friendships/update.json"; +# Twitter friendships/update removed - fediverse uses individual follow/unfollow endpoints $lookupidurl ||= "${apibase}/accounts/lookup"; $rlurl ||= "${apibase}/instance"; # Mastodon instance info instead of rate limits @@ -1052,19 +1053,16 @@ $favsurl ||= "${apibase}/favourites"; $favurl ||= "${apibase}/statuses/%I/favourite"; $favdelurl ||= "${apibase}/statuses/%I/unfavourite"; -$getlisurl ||= "${apibase}/lists/list.json"; -$creliurl ||= "${apibase}/lists/create.json"; -$delliurl ||= "${apibase}/lists/destroy.json"; -$modifyliurl ||= "${apibase}/lists/update.json"; -$deluliurl ||= "${apibase}/lists/members/destroy_all.json"; -$adduliurl ||= "${apibase}/lists/members/create_all.json"; -$getuliurl ||= "${apibase}/lists/memberships.json"; -$getufliurl ||= "${apibase}/lists/subscriptions.json"; -$delfliurl ||= "${apibase}/lists/subscribers/destroy.json"; -$crefliurl ||= "${apibase}/lists/subscribers/create.json"; -$getfliurl ||= "${apibase}/lists/subscribers.json"; -$getliurl ||= "${apibase}/lists/members.json"; -$statusliurl ||= "${apibase}/lists/statuses.json"; +# Fediverse list APIs (simplified compared to Twitter) +$getlisurl ||= "${apibase}/lists"; # GET lists +$creliurl ||= "${apibase}/lists"; # POST create list +$delliurl ||= "${apibase}/lists/%I"; # DELETE list +$modifyliurl ||= "${apibase}/lists/%I"; # PUT update list +$getliurl ||= "${apibase}/lists/%I/accounts"; # GET list members +$adduliurl ||= "${apibase}/lists/%I/accounts"; # POST add members +$deluliurl ||= "${apibase}/lists/%I/accounts"; # DELETE remove members +$statusliurl ||= "${apibase}/lists/%I"; # GET list timeline +# Note: Fediverse doesn't have list subscriptions/followers like Twitter $streamurl ||= "${http_proto}://${fediverseserver}/api/v1/streaming"; $dostream ||= 0; @@ -2619,13 +2617,16 @@ print $stdout "*** invalid UTF-8: partial delete of a wide character?\n"; } $uname ||= $whoami; - # check the list validity - my $my_json_ref = &grabjson( - "${statusliurl}?owner_screen_name=${uname}&slug=${lname}", - 0, 0, 0, undef, 1); - if (!$my_json_ref || ref($my_json_ref) ne 'ARRAY') { - print $stdout - "*** list $uname/$lname seems bogus; not added\n"; + # In fediverse, can only access your own lists (privacy feature) + if ($uname ne $whoami) { + print $stdout "-- Sorry, fediverse only allows access to your own lists (privacy feature)\n"; + return 0; + } + + # Look up list ID by title + my $list_id = &lookup_list_id($lname); + if (!$list_id) { + print $stdout "*** list '$lname' not found; use /lists to see available lists\n"; return 0; } @@ -3086,12 +3087,30 @@ EOF $mode = ($mode eq 'frs' || $mode eq 'friends') ? $friendsurl : $followersurl; } else { - $what = ($mode eq 'frs' || $mode eq 'friends') - ? "friends/members" : "followers/subscribers"; - $mode = ($mode eq 'frs' || $mode eq 'friends') - ? $getliurl : $getfliurl; - $user = "&owner_screen_name=${who}&slug=${lname}"; - $who = "list $who/$lname"; + # List members/followers - fediverse only supports list members, not subscribers + if ($mode eq 'fos' || $mode eq 'followers') { + print $stdout "-- Sorry, fediverse lists don't have followers/subscribers (privacy feature)\n"; + return 0; + } + + # Check list ownership (fediverse privacy) + if ($who ne $whoami) { + print $stdout "-- Sorry, fediverse only allows access to your own list members (privacy feature)\n"; + return 0; + } + + # Look up list ID + my $list_id = &lookup_list_id($lname); + if (!$list_id) { + print $stdout "*** list '$lname' not found; use /lists to see available lists\n"; + return 0; + } + + $what = "list members"; + $mode = $getliurl; + $mode =~ s/%I/$list_id/g; + $user = ""; # No additional parameters needed + $who = "list $lname"; } $countmaybe =~ s/[^\d]//g if (length($countmaybe)); $countmaybe += 0; @@ -3533,13 +3552,9 @@ m#^/(un)?f(boost|a|av|ave|avorite|avourite)? ([zZ]?[a-zA-Z]?[0-9]+)$#) { $countmaybe =~ s/[^\d]//g if (length($countmaybe)); $countmaybe += 0; - my $my_json_ref = &grabjson($boostsofmeurl, 0, 0, $countmaybe); - &dt_tdisplay($my_json_ref, "rtsofme"); - if ($mode eq 're') { - $_ = '/re'; # and fall through ... - } else { - return 0; - } + # "Reposts of me" not available in fediverse (privacy feature) + print $stdout "-- Sorry, fediverse doesn't provide 'reposts of me' (privacy feature)\n"; + return 0; } if (m#^/rts?of\s+([zZ]?[a-zA-Z]?[0-9]+)$# && !$noreblogs) { my $code = lc($1); @@ -3946,18 +3961,9 @@ EOF return 0; } - my $r = &postjson( - ($m ne 'lfollow') ? $delfliurl : $crefliurl, - "owner_screen_name=$uname&slug=$lname"); - if ($r) { - my $t = ($m eq 'lfollow') ? "" : "un"; - print $stdout &wwrap( -"*** ok, you are now ${t}marked as a follower of $uname/${lname}.\n"); - my $c = ($t eq 'un') ? "off" : "on"; - $t = ($t eq 'un') ? "remove from" : "add to"; - print $stdout &wwrap( -"--- to also $t your timeline, use /list${c}\n"); - } + # List subscriptions not available in fediverse (privacy feature) + print $stdout "-- Sorry, fediverse doesn't support list subscriptions (privacy feature)\n"; + print $stdout "-- You can only access your own lists, not follow others' lists\n"; return 0; } @@ -4099,9 +4105,23 @@ EOF $countmaybe += 0; $uname ||= $whoami; - my $my_json_ref = &grabjson( - "${statusliurl}?owner_screen_name=${uname}&slug=${lname}", - 0, 0, $countmaybe, undef, 1); + # In fediverse, can only access your own lists (privacy feature) + if ($uname ne $whoami) { + print $stdout "-- Sorry, fediverse only allows access to your own lists (privacy feature)\n"; + return 0; + } + + # Look up list ID by title + my $list_id = &lookup_list_id($lname); + if (!$list_id) { + print $stdout "*** list '$lname' not found; use /lists to see available lists\n"; + return 0; + } + + # Get list timeline using proper fediverse endpoint + my $list_timeline_url = $statusliurl; + $list_timeline_url =~ s/%I/$list_id/g; + my $my_json_ref = &grabjson($list_timeline_url, 0, 0, $countmaybe, undef, 1); &dt_tdisplay($my_json_ref, "again"); return 0; } @@ -6186,7 +6206,7 @@ sub updatest { } } my $return = &backticks($baseagent, '/dev/null', undef, - ($rt_id) ? "$reblogurl/${rt_id}.json" : $update, + ($rt_id) ? ($reblogurl =~ s/%I/$rt_id/gr) : $update, $i, 0, @wend); print $stdout "-- return --\n$return\n-- return --\n" if ($superverbose); @@ -7244,6 +7264,29 @@ sub lookup_account_id { return undef; } +sub lookup_list_id { + my $list_title = shift; + return unless ($list_title); + + print $stdout "-- DEBUG: Looking up list ID for title: $list_title\n" if ($verbose); + + # Get all lists for current user + my $lists_result = &grabjson($getlisurl, 0, 0, 0, undef, 1); + + if ($lists_result && ref($lists_result) eq 'ARRAY') { + for my $list (@{$lists_result}) { + my $title = $list->{'title'} || ''; + if (lc($title) eq lc($list_title)) { + print $stdout "-- DEBUG: Found list ID: " . $list->{'id'} . " for $list_title\n" if ($verbose); + return $list->{'id'}; + } + } + } + + print $stdout "-- DEBUG: Could not find list ID for title: $list_title\n" if ($verbose); + return undef; +} + sub defaulteventhandle { (&flag_default_call, return) if ($multi_module_context); my $event_ref = shift;