#!/usr/bin/perl

#
# Apply SEEN state to messages via IMAP.
#
# ./apply-seen-state.pl < state.SEEN
#
# Supply lines containing "<UID>: UNSEEN" or "<UID>: FLAG_SEEN" on stdin.
# For example:
#
# -----
# 00000005: FLAG_SEEN
# 00001670: UNSEEN
# -----
#
# Andy Bennett <andyjpb@ashurst.eu.org>, 2025/08/12 17:50.
#

use Net::IMAP::Client;  # https://metacpan.org/pod/Net::IMAP::Client


my $imap = Net::IMAP::Client->new(
	server => '',
	user   => '',
	pass   => '',
	ssl    => 1,
	ssl_verify_peer => 1,
	port   => 993
) or die "Could not connect to IMAP server";

$imap->login or die('Login failed: ' . $imap->last_error);

# my @folders = $imap->folders;

$imap->select('INBOX');

# Read batches from stdin.
# Add UIDs to an array for seen or unseen.
# Send arrays to server with the appropriate call.

my @seen_uids   = ();
my @unseen_uids = ();
my $line_no     = 0;

sub flush_seen_uids {
	$imap->add_flags(\@seen_uids, "\\Seen");
	@seen_uids = ();
}

sub flush_unseen_uids {
	$imap->del_flags(\@unseen_uids, "\\Seen");
	@unseen_uids = ();
}

while ($line = <STDIN>) {
	chomp $line;
	$line_no += 1;

	if ($line =~ /^([0-9]+): ((FLAG_SEEN)|(UNSEEN))$/) {

		$uid   = $1;
		$state = $2;

		if ($state eq "FLAG_SEEN") {
			push @seen_uids, int($uid);

		} elsif ($state eq "UNSEEN") {
			push @unseen_uids, int($uid);
		}

		if (@seen_uids >= 10) {
			flush_seen_uids;
		}
		if (@unseen_uids >= 10) {
			flush_unseen_uids;
		}

	} else {
		die("Syntax error on $line_no! Got: <$line>\n");
	}
}

if (@seen_uids > 0) {
	flush_seen_uids;
}
if (@unseen_uids > 0) {
	flush_unseen_uids;
}

