Fix for dms showing timeout or no data. Locally tracking them to prevent showing them over and over.
This commit is contained in:
+157
-21
@@ -40,12 +40,10 @@ BEGIN {
|
||||
|
||||
$command_line = $0; $0 = "TTYverse";
|
||||
$TTYverse_VERSION = "2025.07.25";
|
||||
$TTYverse_PATCH_VERSION = "";
|
||||
$TTYverse_RC_NUMBER = 0; # non-zero for release candidate
|
||||
# this is kludgy, yes.
|
||||
$LANG = $ENV{'LANG'} || $ENV{'GDM_LANG'} || $ENV{'LC_CTYPE'} ||
|
||||
$ENV{'ALL'};
|
||||
$my_version_string = ($TTYverse_PATCH_VERSION) ? "${TTYverse_VERSION}.${TTYverse_PATCH_VERSION}" : "${TTYverse_VERSION}";
|
||||
$my_version_string = $TTYverse_VERSION;
|
||||
(warn ("$my_version_string\n"), exit) if ($version);
|
||||
|
||||
# Set up XDG directories early for -create-rc and extensions
|
||||
@@ -224,7 +222,6 @@ EOF
|
||||
undef $master_store;
|
||||
undef %push_stack;
|
||||
|
||||
$padded_patch_version = substr($TTYverse_PATCH_VERSION . " ", 0, 2);
|
||||
|
||||
%opts_boolean = map { $_ => 1 } qw(
|
||||
ansi noansi verbose superverbose ttytteristas noprompt
|
||||
@@ -263,7 +260,7 @@ EOF
|
||||
);
|
||||
|
||||
%opts_can_set = map { $_ => 1 } qw(
|
||||
url pause dmurl dmpause superverbose ansi verbose
|
||||
url pause dmurl dmpause dmmarkread superverbose ansi verbose
|
||||
update uurl rurl wurl avatar ttytteristas frurl track
|
||||
rlurl noprompt shoreblogurl newline wrap verify autosplit
|
||||
notimeline queryurl fediverseserver colourprompt colourme
|
||||
@@ -1093,9 +1090,10 @@ $slowpost ||= 0;
|
||||
$twarg ||= undef;
|
||||
|
||||
$verbose ||= $superverbose;
|
||||
$dmpause = 4 if (!defined $dmpause); # NOT ||= ... zero is a VALID value!
|
||||
$dmpause = 4 if (!defined $dmpause); # NOT ||= ... zero is a VALID value!
|
||||
$dmpause = 0 if ($anonymous);
|
||||
$dmpause = 0 if ($pause eq '0');
|
||||
$dmmarkread = 1 if (!defined $dmmarkread); # Default to enabled
|
||||
$ansi = ($noansi) ? 0 :
|
||||
(($ansi || $ENV{'TERM'} eq 'ansi' || $ENV{'TERM'} eq 'xterm-color')
|
||||
? 1 : 0);
|
||||
@@ -1748,6 +1746,7 @@ if ($daemon) {
|
||||
&update_effpause;
|
||||
&refresh(0);
|
||||
$dont_refresh_first_time = 0;
|
||||
# Move DM refresh after timeline refresh so timeline updates show even if no unread DMs
|
||||
if ($dmpause) {
|
||||
if (!--$dmcount) {
|
||||
&dmrefresh(0);
|
||||
@@ -1833,7 +1832,7 @@ unless ($simplestart) {
|
||||
print <<"EOF";
|
||||
|
||||
========================================
|
||||
TTYverse ${TTYverse_VERSION}.${padded_patch_version} (c)2025 Storm Dragon
|
||||
TTYverse ${TTYverse_VERSION} (c)2025 Storm Dragon
|
||||
all rights reserved.
|
||||
|
||||
https://git.stormux.org/storm/ttyverse
|
||||
@@ -4649,7 +4648,9 @@ $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
|
||||
# DM tracking now uses Mastodon's unread flag with local read tracking fallback
|
||||
%dm_seen_status = (); # Hash to track seen conversation_id:last_status_id pairs
|
||||
&load_dm_seen_status(); # Load persistent tracking data
|
||||
$stuck_stdin = 0;
|
||||
|
||||
# tell the foreground we are ready
|
||||
@@ -5994,6 +5995,24 @@ sub dmrefresh {
|
||||
|
||||
print $stdout "-- DEBUG: DM response: " . scalar(@{ $my_json_ref }) . " conversations, disp_max=$disp_max\n" if ($verbose);
|
||||
|
||||
# For background refresh, check if there are any unread DMs first
|
||||
if (!$interactive && !$sent_dm && $disp_max) {
|
||||
my $has_unread = 0;
|
||||
for (my $check_i = 0; $check_i < $disp_max; $check_i++) {
|
||||
my $check_j = $my_json_ref->[$check_i];
|
||||
next if (!$check_j->{'accounts'} || !@{$check_j->{'accounts'}} || !$check_j->{'last_status'});
|
||||
if ($check_j->{'unread'}) {
|
||||
$has_unread = 1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
if (!$has_unread) {
|
||||
print $stdout "-- DEBUG: No unread DMs found in background refresh, returning early\n" if ($verbose);
|
||||
return;
|
||||
}
|
||||
print $stdout "-- DEBUG: Found unread DMs in background refresh, proceeding\n" if ($verbose);
|
||||
}
|
||||
|
||||
if ($disp_max) { # an empty list can be valid
|
||||
if ($dm_first_time) {
|
||||
sleep 5 while ($suspend_output > 0);
|
||||
@@ -6016,12 +6035,23 @@ sub dmrefresh {
|
||||
next;
|
||||
}
|
||||
|
||||
# For background refresh (interactive=0), use unread flag detection
|
||||
# For background refresh (interactive=0), use unread flag detection with local tracking fallback
|
||||
if (!$interactive && !$sent_dm) {
|
||||
my $is_unread = $j->{'unread'} || 0;
|
||||
print $stdout "-- DEBUG: DM #$i unread flag: " . ($is_unread ? "true" : "false") . "\n" if ($verbose);
|
||||
my $conversation_id = $j->{'id'};
|
||||
my $last_status_id = $j->{'last_status'}->{'id'} || $j->{'last_status'}->{'id_str'};
|
||||
my $tracking_key = "${conversation_id}:${last_status_id}";
|
||||
|
||||
if (!$is_unread) {
|
||||
print $stdout "-- DEBUG: DM #$i unread flag: " . ($is_unread ? "true" : "false") . ", tracking_key: $tracking_key\n" if ($verbose);
|
||||
|
||||
# Check if we've already seen this exact conversation+status combination
|
||||
if ($dm_seen_status{$tracking_key}) {
|
||||
print $stdout "-- DEBUG: Skipping DM #$i - already seen locally (key: $tracking_key)\n" if ($verbose);
|
||||
next;
|
||||
}
|
||||
|
||||
# For servers that support unread flag, also check that
|
||||
if (!$is_unread && !$dm_seen_status{$tracking_key}) {
|
||||
print $stdout "-- DEBUG: Skipping DM #$i - already read (unread=false)\n" if ($verbose);
|
||||
next;
|
||||
}
|
||||
@@ -7251,9 +7281,19 @@ sub defaultdmhandle {
|
||||
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'});
|
||||
# Mark conversation as read if it was unread (can be disabled with dmmarkread=0)
|
||||
if ($dm_ref->{'unread'} && (!defined($dmmarkread) || $dmmarkread)) {
|
||||
my $mark_result = &mark_conversation_read($dm_ref->{'id'});
|
||||
|
||||
# If server-side mark-as-read failed, track locally to prevent re-showing
|
||||
if (!$mark_result) {
|
||||
my $conversation_id = $dm_ref->{'id'};
|
||||
my $last_status_id = $dm_ref->{'last_status'}->{'id'} || $dm_ref->{'last_status'}->{'id_str'};
|
||||
my $tracking_key = "${conversation_id}:${last_status_id}";
|
||||
$dm_seen_status{$tracking_key} = time(); # Store timestamp when seen
|
||||
print $stdout "-- DEBUG: Marked DM as seen locally (key: $tracking_key)\n" if ($verbose);
|
||||
&save_dm_seen_status(); # Persist the change
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -7277,15 +7317,46 @@ sub mark_conversation_read {
|
||||
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";
|
||||
my $read_url = "${apibase}/conversations/$conversation_id/read";
|
||||
print $stdout "-- DEBUG: Mark-as-read URL: $read_url\n" if ($verbose);
|
||||
|
||||
# Make POST request with shorter timeout for mark-as-read
|
||||
my $old_timeout = $timeout;
|
||||
my $old_exception = $exception;
|
||||
$timeout = 5; # Short timeout for non-critical operation
|
||||
|
||||
# Use a custom exception handler to capture detailed error info
|
||||
$exception = sub {
|
||||
my ($severity, $message) = @_;
|
||||
print $stdout "-- DEBUG: Mark-as-read API call failed (severity=$severity): $message" if ($verbose);
|
||||
# Don't show user warning for this - it's not critical, but log the error
|
||||
};
|
||||
|
||||
# Make POST request with empty data to mark as read
|
||||
my $result = &postjson($read_url, "");
|
||||
|
||||
# Restore original handlers
|
||||
$timeout = $old_timeout;
|
||||
$exception = $old_exception;
|
||||
|
||||
if ($result) {
|
||||
print $stdout "-- DEBUG: Successfully marked conversation $conversation_id as read\n" if ($verbose);
|
||||
return 1;
|
||||
} else {
|
||||
print $stdout "-- DEBUG: Failed to mark conversation $conversation_id as read\n" if ($verbose);
|
||||
print $stdout "-- DEBUG: Failed to mark conversation $conversation_id as read - trying alternative method\n" if ($verbose);
|
||||
|
||||
# Fallback: Some servers might need different approach
|
||||
# Try sending empty message to conversation (some implementations mark as read this way)
|
||||
my $alt_url = "${apibase}/conversations/$conversation_id";
|
||||
print $stdout "-- DEBUG: Trying alternative approach: GET $alt_url\n" if ($verbose);
|
||||
|
||||
my $alt_result = &grabjson($alt_url, 0, 0, 1, undef, 1);
|
||||
if ($alt_result) {
|
||||
print $stdout "-- DEBUG: Alternative method succeeded (conversation fetched)\n" if ($verbose);
|
||||
return 1;
|
||||
} else {
|
||||
print $stdout "-- DEBUG: All methods failed - server may not support conversation read API\n" if ($verbose);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8227,8 +8298,14 @@ sub updatecheck {
|
||||
} elsif ($latest_version eq $current_version) {
|
||||
$vs .= "-- your version of TTYverse is up to date ($current_version)\n";
|
||||
} else {
|
||||
$vs .= "-- you appear to have a development version ($current_version)\n";
|
||||
$vs .= "-- latest stable release: $latest_version\n";
|
||||
# Local version is newer - check if we're in a git repo
|
||||
if (-d '.git') {
|
||||
$vs .= "-- your version ($current_version) is newer than latest remote ($latest_version)\n";
|
||||
$vs .= "-- you may have unpushed changes or unreleased version\n";
|
||||
} else {
|
||||
$vs .= "-- you appear to have a development version ($current_version)\n";
|
||||
$vs .= "-- latest stable release: $latest_version\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$vs .= "-- warning: unable to determine latest version\n";
|
||||
@@ -8736,10 +8813,14 @@ sub normalizejson {
|
||||
print $stdout "-- DEBUG: Found poll in main post\n" if ($verbose);
|
||||
}
|
||||
|
||||
# Store poll data for display
|
||||
if ($poll_data) {
|
||||
# Store poll data for display - but only if it's a valid poll with options
|
||||
if ($poll_data && ref($poll_data) eq 'HASH' && exists($poll_data->{'options'}) && @{$poll_data->{'options'}}) {
|
||||
$i->{'poll'} = $poll_data;
|
||||
print $stdout "-- DEBUG: Poll data stored for display\n" if ($verbose);
|
||||
} else {
|
||||
# Clear any false poll data
|
||||
delete $i->{'poll'} if exists($i->{'poll'});
|
||||
print $stdout "-- DEBUG: No valid poll data found, cleared poll flag\n" if ($verbose && $poll_data);
|
||||
}
|
||||
|
||||
return $i;
|
||||
@@ -9818,4 +9899,59 @@ sub signrequest {
|
||||
return "-H \"Authorization: Bearer $tokenkey\"";
|
||||
}
|
||||
|
||||
# Load locally tracked DM seen status from persistent storage
|
||||
sub load_dm_seen_status {
|
||||
my $seen_file = "$config/dm_seen_status";
|
||||
return unless (-r $seen_file);
|
||||
|
||||
if (open(SEEN, '<', $seen_file)) {
|
||||
print $stdout "-- DEBUG: Loading DM seen status from $seen_file\n" if ($verbose);
|
||||
my $count = 0;
|
||||
while (my $line = <SEEN>) {
|
||||
chomp($line);
|
||||
next unless ($line =~ /^(.+):(\d+)$/);
|
||||
my ($tracking_key, $timestamp) = ($1, $2);
|
||||
|
||||
# Skip entries older than 30 days to prevent infinite growth
|
||||
if (time() - $timestamp < 30 * 24 * 3600) {
|
||||
$dm_seen_status{$tracking_key} = $timestamp;
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
close(SEEN);
|
||||
print $stdout "-- DEBUG: Loaded $count DM seen entries\n" if ($verbose);
|
||||
}
|
||||
}
|
||||
|
||||
# Save locally tracked DM seen status to persistent storage
|
||||
sub save_dm_seen_status {
|
||||
my $seen_file = "$config/dm_seen_status";
|
||||
|
||||
# Ensure config directory exists
|
||||
unless (-d $config) {
|
||||
mkdir($config, 0700) || do {
|
||||
print $stdout "-- DEBUG: Could not create config directory $config: $!\n" if ($verbose);
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
if (open(SEEN, '>', $seen_file)) {
|
||||
print $stdout "-- DEBUG: Saving DM seen status to $seen_file\n" if ($superverbose);
|
||||
my $count = 0;
|
||||
for my $key (keys %dm_seen_status) {
|
||||
my $timestamp = $dm_seen_status{$key};
|
||||
# Only save entries from last 30 days
|
||||
if (time() - $timestamp < 30 * 24 * 3600) {
|
||||
print SEEN "$key:$timestamp\n";
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
close(SEEN);
|
||||
chmod(0600, $seen_file); # Keep private
|
||||
print $stdout "-- DEBUG: Saved $count DM seen entries\n" if ($superverbose);
|
||||
} else {
|
||||
print $stdout "-- DEBUG: Could not save DM seen status to $seen_file: $!\n" if ($verbose);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user