Experimental updates, this may be the first of a batchto be reverted only time will tell.
This commit is contained in:
+181
-26
@@ -169,7 +169,7 @@ BEGIN {
|
||||
# notrack=0 # Disable tracking
|
||||
# filterusers= # Filter posts from specific users
|
||||
# filterats= # Filter posts with specific @mentions
|
||||
# filterrts= # Filter retweets/boosts
|
||||
# filterrts= # Filter boosts
|
||||
# filteratonly= # Only show posts with @mentions
|
||||
# filterflags= # Filter flags
|
||||
# nofilter=0 # Disable all filtering
|
||||
@@ -193,7 +193,7 @@ BEGIN {
|
||||
|
||||
# === ADVANCED/TECHNICAL ===
|
||||
# runcommand= # Command to run on startup
|
||||
# twarg= # Legacy Twitter argument (unused)
|
||||
# twarg= # Legacy argument (unused)
|
||||
# user= # Username override
|
||||
# leader= # Command leader character
|
||||
|
||||
@@ -2908,6 +2908,7 @@ EOF
|
||||
print $stdout "-- /refresh in streaming mode is pretty impatient\n"
|
||||
if ($dostream);
|
||||
&thump;
|
||||
&dmthump_no_skip if ($dmpause); # Also refresh DMs but don't skip timeline
|
||||
return 0;
|
||||
}
|
||||
if (m#^/a(gain)?(\s+\+\d+)?$#) { # the asynchronous form
|
||||
@@ -3105,7 +3106,7 @@ EOF
|
||||
|
||||
# grab all the IDs
|
||||
my $ids_ref = &grabjson(
|
||||
"$mode?count=${countmaybe}&screen_name=${who}&stringify_ids=true",
|
||||
"$mode?limit=${countmaybe}&screen_name=${who}",
|
||||
0, 0, 0, undef, 1);
|
||||
return 0 if (!$ids_ref || ref($ids_ref) ne 'HASH' ||
|
||||
!$ids_ref->{'ids'});
|
||||
@@ -3173,7 +3174,7 @@ EOF
|
||||
if(!scalar(@usarray)) {
|
||||
last FABIO if ($nofetch);
|
||||
$json_ref = &grabjson(
|
||||
"${mode}?count=${countper}&cursor=${cursor}${user}",
|
||||
"${mode}?limit=${countper}&cursor=${cursor}${user}",
|
||||
0, 0, 0, undef, 1);
|
||||
@usarray = @{ $json_ref->{'users'} };
|
||||
last FABIO if (!scalar(@usarray));
|
||||
@@ -3835,8 +3836,8 @@ EOF
|
||||
my $my_json_ref = &grabjson($timeline_url, 0, 0, $countmaybe || 20, undef, 1);
|
||||
|
||||
if ($timeline_name eq 'notifications') {
|
||||
# Notifications have a different structure, need special handling
|
||||
&dt_tdisplay($my_json_ref, "notifications");
|
||||
# Notifications need individual type mapping for sound alerts
|
||||
¬ifications_tdisplay($my_json_ref);
|
||||
} else {
|
||||
&dt_tdisplay($my_json_ref, $timeline_name);
|
||||
}
|
||||
@@ -3886,7 +3887,7 @@ EOF
|
||||
$countmaybe = sprintf("%03i", $countmaybe);
|
||||
print $stdout "-- background request sent\n" unless ($synch);
|
||||
|
||||
$mode = ($mode =~ /^s/) ? 's' : 'd';
|
||||
$mode = ($mode eq 'sent') ? 's' : 'd';
|
||||
print C "${mode}mreset${countmaybe}---------\n";
|
||||
&sync_semaphore;
|
||||
return 0;
|
||||
@@ -4153,7 +4154,7 @@ EOF
|
||||
if(!scalar(@usarray)) {
|
||||
last LABIO if ($nofetch);
|
||||
$json_ref = &grabjson(
|
||||
"${furl}&count=${countper}&cursor=${cursor}", 0, 0, 0,
|
||||
"${furl}&limit=${countper}&cursor=${cursor}", 0, 0, 0,
|
||||
undef, 1);
|
||||
@usarray = @{ ((length($lname)) ?
|
||||
$json_ref->{'users'} :
|
||||
@@ -4585,6 +4586,9 @@ $interactive = $previous_last_id = $we_got_signal = 0;
|
||||
$suspend_output = -1;
|
||||
$stream_failure = 0;
|
||||
$dm_first_time = ($dmpause) ? 1 : 0;
|
||||
$dm_display_only = 0; # Flag to suppress notifications during user-initiated /dms commands
|
||||
$dm_notification_sent = 0; # Flag to prevent duplicate notifications per refresh cycle
|
||||
# DM tracking now uses Mastodon's unread flag instead of content comparison
|
||||
$stuck_stdin = 0;
|
||||
|
||||
# tell the foreground we are ready
|
||||
@@ -4605,10 +4609,14 @@ for(;;) {
|
||||
&dmrefresh(0);
|
||||
$dmcount = $dmpause;
|
||||
} elsif (!$interactive) {
|
||||
print $stdout "-- DEBUG: DM countdown: $dmcount -> " . ($dmcount - 1) . "\n" if ($verbose);
|
||||
if (!--$dmcount) {
|
||||
print $stdout "-- DEBUG: Triggering background DM refresh\n" if ($verbose);
|
||||
&dmrefresh($interactive); # using dm_first_time
|
||||
$dmcount = $dmpause;
|
||||
}
|
||||
} else {
|
||||
print $stdout "-- DEBUG: Skipping DM countdown (interactive=$interactive)\n" if ($verbose);
|
||||
}
|
||||
}
|
||||
DONT_REFRESH:
|
||||
@@ -4919,15 +4927,31 @@ EOF
|
||||
if ($rout =~ /^reset(\d+)/);
|
||||
($dmfetchwanted = 0+$1, $last_dm = 0)
|
||||
if ($rout =~ /^dmreset(\d+)/);
|
||||
if ($rout =~ /^smreset/) { # /dmsent
|
||||
if ($rout =~ /^dmreset/) { # /dms (received)
|
||||
$dmfetchwanted = 0+$1
|
||||
if ($rout =~ /(\d+)/);
|
||||
&dmrefresh(1, 1);
|
||||
$dm_display_only = 1; # Suppress notifications for user-initiated /dms
|
||||
&dmrefresh(1, 0); # interactive=1, sent_dm=0
|
||||
$dm_display_only = 0; # Reset flag
|
||||
&send_repaint if ($termrl);
|
||||
# we do not want to force a refresh.
|
||||
goto DONT_REFRESH;
|
||||
} elsif ($rout =~ /^smreset/) { # /dmsent
|
||||
$dmfetchwanted = 0+$1
|
||||
if ($rout =~ /(\d+)/);
|
||||
$dm_display_only = 1; # Suppress notifications for user-initiated /dmsent
|
||||
&dmrefresh(1, 1); # interactive=1, sent_dm=1
|
||||
$dm_display_only = 0; # Reset flag
|
||||
&send_repaint if ($termrl);
|
||||
# we do not want to force a refresh.
|
||||
goto DONT_REFRESH;
|
||||
}
|
||||
if ($rout =~ /^dm/) {
|
||||
if ($rout =~ /^dmthump_no_skip/) {
|
||||
&dmrefresh(0); # Force background-style refresh to update last_dm
|
||||
&send_repaint if ($termrl);
|
||||
$dmcount = $dmpause;
|
||||
# Don't skip - let timeline refresh continue
|
||||
} elsif ($rout =~ /^dm/) {
|
||||
&dmrefresh($interactive);
|
||||
&send_repaint if ($termrl);
|
||||
$dmcount = $dmpause;
|
||||
@@ -5018,7 +5042,7 @@ sub update_effpause {
|
||||
if ($effpause > 120) {
|
||||
$effpause = 120; # Maximum 2 minutes for fediverse
|
||||
}
|
||||
# this will usually be 75s (Twitter) or 120s (fediverse cap)
|
||||
# this will usually be 120s (fediverse rate limit cap)
|
||||
# for lists, however, we have to drain the list bucket faster, so for every
|
||||
# list AFTER THE FIRST ONE we subscribe to, add rate_limit_rate to slow.
|
||||
# for search, it has 180 requests, so we don't care so much. if this
|
||||
@@ -5777,7 +5801,7 @@ sub tdisplay { # used by both synchronous /again and asynchronous refreshes
|
||||
$wrapseq++;
|
||||
|
||||
$printed += scalar(&$handle($j,
|
||||
($class || (($id <= $relative_last_id) ? 'again' :
|
||||
($class || (($id le $relative_last_id) ? 'again' :
|
||||
undef))));
|
||||
}
|
||||
}
|
||||
@@ -5823,12 +5847,46 @@ $my_json_ref->[(&min($print_max,scalar(@{ $my_json_ref }))-1)]->{'created_at'});
|
||||
}
|
||||
}
|
||||
|
||||
sub notifications_tdisplay {
|
||||
my $my_json_ref = shift;
|
||||
if (defined($my_json_ref)
|
||||
&& ref($my_json_ref) eq 'ARRAY'
|
||||
&& scalar(@{ $my_json_ref })) {
|
||||
|
||||
# Process each notification with proper type mapping
|
||||
for my $notification (@{ $my_json_ref }) {
|
||||
my $type = $notification->{'type'} || 'default';
|
||||
# Map Mastodon notification types to sound categories
|
||||
my $sound_class = $type;
|
||||
$sound_class = 'mention' if ($type eq 'mention');
|
||||
$sound_class = 'boost' if ($type eq 'reblog');
|
||||
$sound_class = 'favourite' if ($type eq 'favourite');
|
||||
$sound_class = 'follow' if ($type eq 'follow');
|
||||
|
||||
# Process as individual post with proper class
|
||||
&$handle($notification, $sound_class);
|
||||
}
|
||||
|
||||
unless ($timestamp) {
|
||||
my ($time, $ts1) = &$wraptime(
|
||||
$my_json_ref->[(&min($print_max,scalar(@{ $my_json_ref }))-1)]->{'created_at'});
|
||||
my ($time, $ts2) = &$wraptime($my_json_ref->[0]->{'created_at'});
|
||||
print $stdout &wwrap(
|
||||
"-- update covers $ts1 thru $ts2\n");
|
||||
}
|
||||
&$conclude;
|
||||
}
|
||||
}
|
||||
|
||||
# thump for DMs
|
||||
sub dmrefresh {
|
||||
my $interactive = shift;
|
||||
my $sent_dm = shift;
|
||||
# for streaming API to inject DMs it receives
|
||||
my $my_json_ref = shift;
|
||||
|
||||
# Reset notification flag for this refresh cycle
|
||||
$dm_notification_sent = 0;
|
||||
|
||||
if ($anonymous) {
|
||||
print $stdout
|
||||
@@ -5859,6 +5917,8 @@ sub dmrefresh {
|
||||
my $g;
|
||||
my $key;
|
||||
|
||||
print $stdout "-- DEBUG: DM response: " . scalar(@{ $my_json_ref }) . " conversations, disp_max=$disp_max\n" if ($verbose);
|
||||
|
||||
if ($disp_max) { # an empty list can be valid
|
||||
if ($dm_first_time) {
|
||||
sleep 5 while ($suspend_output > 0);
|
||||
@@ -5867,13 +5927,39 @@ sub dmrefresh {
|
||||
"-- checking for most recent direct messages:\n";
|
||||
$disp_max = 2;
|
||||
$interactive = 1;
|
||||
print $stdout "-- DEBUG: dm_first_time: disp_max reduced to $disp_max\n" if ($verbose);
|
||||
}
|
||||
print $stdout "-- DEBUG: Starting DM display loop: $disp_max conversations\n" if ($verbose);
|
||||
for($i = $disp_max; $i > 0; $i--) {
|
||||
$g = ($i-1);
|
||||
my $j = $my_json_ref->[$g];
|
||||
next if (!$sent_dm && $j->{'id'} <= $last_dm);
|
||||
next if (!$j->{'accounts'} || !@{$j->{'accounts'}} ||
|
||||
!$j->{'last_status'});
|
||||
print $stdout "-- DEBUG: Processing DM #$i (index $g)\n" if ($verbose);
|
||||
|
||||
# Skip if missing data
|
||||
if (!$j->{'accounts'} || !@{$j->{'accounts'}} || !$j->{'last_status'}) {
|
||||
print $stdout "-- DEBUG: Skipping DM #$i - missing data (accounts=" . (defined($j->{'accounts'}) ? scalar(@{$j->{'accounts'}}) : 'undef') . ")\n" if ($verbose);
|
||||
next;
|
||||
}
|
||||
|
||||
# For background refresh (interactive=0), use unread flag detection
|
||||
if (!$interactive && !$sent_dm) {
|
||||
my $is_unread = $j->{'unread'} || 0;
|
||||
print $stdout "-- DEBUG: DM #$i unread flag: " . ($is_unread ? "true" : "false") . "\n" if ($verbose);
|
||||
|
||||
if (!$is_unread) {
|
||||
print $stdout "-- DEBUG: Skipping DM #$i - already read (unread=false)\n" if ($verbose);
|
||||
next;
|
||||
}
|
||||
|
||||
# Only play sound for the first unread conversation to avoid spam
|
||||
if ($dm_notification_sent) {
|
||||
print $stdout "-- DEBUG: Suppressing notification for DM #$i - already notified this cycle\n" if ($verbose);
|
||||
# Still display the DM but suppress notification
|
||||
} else {
|
||||
# Mark that we will send a notification for this unread DM
|
||||
print $stdout "-- DEBUG: Will send notification for unread DM #$i\n" if ($verbose);
|
||||
}
|
||||
}
|
||||
|
||||
$key = substr($alphabet, $dm_counter/10, 1) .
|
||||
$dm_counter % 10;
|
||||
@@ -5887,7 +5973,10 @@ sub dmrefresh {
|
||||
&send_removereadline if ($termrl);
|
||||
$wrapseq++;
|
||||
|
||||
$printed += scalar(&$dmhandle($j));
|
||||
print $stdout "-- DEBUG: Calling dmhandle for DM #$i\n" if ($verbose);
|
||||
my $dm_result = scalar(&$dmhandle($j));
|
||||
print $stdout "-- DEBUG: dmhandle returned: $dm_result\n" if ($verbose);
|
||||
$printed += $dm_result;
|
||||
}
|
||||
$max = $my_json_ref->[0]->{'id'};
|
||||
}
|
||||
@@ -5899,8 +5988,26 @@ sub dmrefresh {
|
||||
: "-- sorry, no new direct messages.\n");
|
||||
$wrapseq = 1;
|
||||
}
|
||||
$last_dm = ($sent_dm) ? $orig_last_dm
|
||||
: &max($last_dm, $max);
|
||||
# Update last_dm for background refresh AND manual /dms
|
||||
# Background calls: $interactive=0
|
||||
# Manual /dms: $interactive=1, $sent_dm=0 (receives messages, should update read marker)
|
||||
# Manual /dmsent: $interactive=1, $sent_dm=1 (shows sent messages, don't update)
|
||||
if (!$interactive || $dm_first_time || ($interactive && !$sent_dm)) {
|
||||
$last_dm = ($sent_dm) ? $orig_last_dm
|
||||
: &max($last_dm, $max);
|
||||
|
||||
# Update content bookmark for the newest DM (index 0)
|
||||
if (!$sent_dm && scalar(@{ $my_json_ref }) > 0) {
|
||||
my $newest_dm = $my_json_ref->[0];
|
||||
if ($newest_dm->{'last_status'}) {
|
||||
# Track newest DM for next comparison (unread flag handles change detection)
|
||||
}
|
||||
}
|
||||
|
||||
print $stdout "-- DEBUG: Updated last_dm to $last_dm (interactive=$interactive, dm_first_time=$dm_first_time, sent_dm=$sent_dm)\n" if ($verbose);
|
||||
} else {
|
||||
print $stdout "-- DEBUG: NOT updating last_dm (interactive=$interactive, keeping last_dm=$last_dm)\n" if ($verbose);
|
||||
}
|
||||
$dm_first_time = 0 if ($last_dm || !scalar(@{ $my_json_ref }));
|
||||
print $stdout "-- dm bookmark is $last_dm.\n" if ($verbose);
|
||||
&$dmconclude;
|
||||
@@ -6111,6 +6218,11 @@ EOF
|
||||
$lasttwit = $string;
|
||||
&$postpost($string);
|
||||
}
|
||||
|
||||
# Send "me" notification for outgoing DMs
|
||||
if ($user_name_dm) {
|
||||
¬ifytype_dispatch('me', $string, undef);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6328,6 +6440,16 @@ sub standardpost {
|
||||
}
|
||||
}
|
||||
|
||||
# Add poll indicator if this post has a poll
|
||||
if (exists($ref->{'poll'}) && $ref->{'poll'}) {
|
||||
my $poll_indicator = '[Poll]';
|
||||
if ($nocolour) {
|
||||
$info_line .= " $poll_indicator";
|
||||
} else {
|
||||
$info_line .= " ${GREEN}${poll_indicator}${OFF}";
|
||||
}
|
||||
}
|
||||
|
||||
# Add content warning/title if present
|
||||
my $cw_text = '';
|
||||
if (exists($ref->{'reblog'}) && $ref->{'reblog'} && exists($ref->{'reblog'}->{'spoiler_text'})) {
|
||||
@@ -7028,15 +7150,47 @@ sub defaultdmhandle {
|
||||
my $dm_ref = shift;
|
||||
my $sns = &descape($dm_ref->{'last_status'}->{'account'}->{'username'} || $dm_ref->{'last_status'}->{'account'}->{'acct'});
|
||||
|
||||
print $streamout &standarddm($dm_ref);
|
||||
my $dm_content = &standarddm($dm_ref);
|
||||
print $streamout $dm_content;
|
||||
print $stdout "-- DEBUG: DM displayed: " . substr($dm_content, 0, 50) . "...\n" if ($verbose);
|
||||
&senddmnotifies($dm_ref) if ($sns ne $whoami);
|
||||
|
||||
# Mark conversation as read if it was unread
|
||||
if ($dm_ref->{'unread'}) {
|
||||
&mark_conversation_read($dm_ref->{'id'});
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub senddmnotifies {
|
||||
my $dm_ref = shift;
|
||||
¬ifytype_dispatch('dm', &standarddm($dm_ref, 1), $dm_ref)
|
||||
if ($notify_list{'dm'} && $last_dm);
|
||||
# Only send notification if we haven't already sent one this refresh cycle
|
||||
# and we're not in initial load (either timeline or DM first time)
|
||||
# and we're not in display-only mode (user-initiated /dms commands)
|
||||
if ($notify_list{'dm'} && !$initial_load_in_progress && !$dm_first_time && !$dm_notification_sent && !$dm_display_only) {
|
||||
¬ifytype_dispatch('dm', &standarddm($dm_ref, 1), $dm_ref);
|
||||
$dm_notification_sent = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub mark_conversation_read {
|
||||
my $conversation_id = shift;
|
||||
return unless ($conversation_id);
|
||||
|
||||
print $stdout "-- DEBUG: Marking conversation $conversation_id as read\n" if ($verbose);
|
||||
|
||||
# Build the URL for marking conversation as read
|
||||
my $read_url = "$baseurl/api/v1/conversations/$conversation_id/read";
|
||||
|
||||
# Make POST request with empty data to mark as read
|
||||
my $result = &postjson($read_url, "");
|
||||
|
||||
if ($result) {
|
||||
print $stdout "-- DEBUG: Successfully marked conversation $conversation_id as read\n" if ($verbose);
|
||||
} else {
|
||||
print $stdout "-- DEBUG: Failed to mark conversation $conversation_id as read\n" if ($verbose);
|
||||
}
|
||||
}
|
||||
|
||||
sub defaulteventhandle {
|
||||
@@ -7386,6 +7540,7 @@ sub thump {
|
||||
&sync_semaphore;
|
||||
}
|
||||
sub dmthump { print C "dmthump------------\n"; &sync_semaphore; }
|
||||
sub dmthump_no_skip { print C "dmthump_no_skip----\n"; &sync_semaphore; }
|
||||
|
||||
sub sync_n_quit {
|
||||
if ($child) {
|
||||
@@ -8192,14 +8347,14 @@ sub grabjson {
|
||||
$url = substr($url, 0, $i);
|
||||
}
|
||||
|
||||
# count needs to be removed for the default case due to show, etc.
|
||||
push(@xargs, "count=$count") if ($count);
|
||||
# limit parameter for Mastodon API (replaces Twitter's count parameter)
|
||||
push(@xargs, "limit=$count") if ($count);
|
||||
# timeline control. this speeds up parsing since there's less data.
|
||||
# can't use skip_user: no SN
|
||||
push (@xargs, "since_id=${last_id}") if ($last_id);
|
||||
|
||||
# request entities, which should be supported everywhere now
|
||||
push (@xargs, "include_entities=1") if ($do_entities);
|
||||
# include_entities is Twitter-specific, not needed for Mastodon
|
||||
# push (@xargs, "include_entities=1") if ($do_entities);
|
||||
|
||||
my $resource = (scalar(@xargs)) ?
|
||||
[ $url, join('&', sort @xargs) ] : $url;
|
||||
|
||||
Reference in New Issue
Block a user