User:AnomieBOT/source/tasks/WikiUninterestingNumbers.pm

package tasks::WikiUninterestingNumbers;

=pod

=begin metadata

Bot:     AnomieBOT
Task:    WikiUninterestingNumbers
BRFA:    N/A
Status:  Begun 2024-01-28
Created: 2024-01-24

Create a page listing some [[interesting number]]s:
* Smallest number that is not the primary topic.
* Smallest number without its own article.
* Smallest number without an article or redirect.

This assumes that all number articles will be at or have a redirect from a title like [[42 (number)]].

=end metadata

=cut

use utf8;
use strict;

use AnomieBOT::Task;
use vars qw/@ISA/;
@ISA=qw/AnomieBOT::Task/;

use Data::Dumper;

sub new {
    my $class=shift;
    my $self=$class->SUPER::new;
    bless $self, $class;
    return $self;
}

=pod

=for info
Per [[WP:BOT#Approval]], any bot or automated editing process that only
affects only the operators' user and talk pages (or subpages thereof),
and which are not otherwise disruptive, may be run without prior
approval.

=cut

sub approved {
    return 999;
}

sub run {
    my ( $self, $api ) = @_;

    $api->task( 'WikiUninterestingNumbers', 0, 10, qw(d::IWNS) );

    my $t = ( $api->store->{'nextrun'} // 0 ) - time();
    return $t if $t>0;

    my $ts = time();

    my $title = 'User:AnomieBOT/Wiki-uninteresting numbers';
    my $tok = $api->edittoken( $title, EditRedir => 1 );
    if ( $tok->{'code'} eq 'shutoff' ) {
        $api->warn( "Task disabled: " . $tok->{'content'} . "\n" );
        return 300;
    }
    if ( $tok->{'code'} ne 'success' ) {
        $api->warn( "Failed to get edit token for $title: " . $tok->{'error'} . "\n" );
        return 300;
    }
    
    my $dbh;
    eval {
        $dbh = $api->connectToReplica( 'enwiki', 'analytics' );
    };
    if ( $@ ) {
        $api->warn( "Error connecting to replica: $@\n" );
        return 300;
    }

    my ( $nonprimary, $nonredir, $nonexist );
    eval {
        $nonprimary = ( @{ $dbh->selectcol_arrayref( qq(
            SELECT seq
            FROM seq_1_to_18446744073709551615
                LEFT JOIN page ON(page_namespace=0 and page_title=CONCAT(seq, '_(number)'))
                LEFT JOIN redirect ON(rd_from=page_id)
            WHERE rd_from IS null OR NOT (rd_namespace = 0 AND rd_title = seq)
            LIMIT 1
        ) ) } )[0];
        $nonredir = ( @{ $dbh->selectcol_arrayref( qq(
            SELECT seq
            FROM seq_1_to_18446744073709551615
                LEFT JOIN page ON(page_namespace=0 and page_title=CONCAT(seq, '_(number)'))
                LEFT JOIN redirect ON(rd_from=page_id)
            WHERE NOT (rd_from IS null OR rd_namespace = 0 AND rd_title = seq)
            LIMIT 1
        ) ) } )[0];
        $nonexist = ( @{ $dbh->selectcol_arrayref( qq(
            SELECT seq
            FROM seq_1_to_18446744073709551615
                LEFT JOIN page ON(page_namespace=0 and page_title=CONCAT(seq, '_(number)'))
            WHERE page_id IS NULL
            LIMIT 1
        ) ) } )[0];
    };
    if ( $@ ) {
        $api->warn( "DB query failed: $@\n" );
        return 300;
    }

    my $txt = qq(
        {{ $title/{{{1|display}}}
         | non-primary  = $nonprimary
         | non-redir    = $nonredir
         | non-existing = $nonexist
         | lastchange = $ts
         | arg = {{{2|}}}
        }}
    );
    $txt =~ s/^        //mg;
    $txt =~ s/^\s+//;
    $txt =~ s/\s*$/\n/;

    my $intxt = $tok->{'revisions'}[0]{'slots'}{'main'}{'*'} // '';
    $intxt =~ s/^\s+//;
    $intxt =~ s/\s*$/\n/;
    $intxt =~ s/\| lastchange = \d+/| lastchange = $ts/;

    if ( $txt ne $intxt ) {
        my $summary = "Updating list of wiki-interesting numbers: $nonprimary, $nonredir, and $nonexist";
        $api->log( "$summary in $title" );
        my $r = $api->edit( $tok, $txt, "$summary", 0, 1 );
        if ( $r->{'code'} ne 'success' ) {
            $api->warn( "Write error for $title: " . $r->{'error'} . "\n" );
            return 60;
        }
    }

    $t = 86400 - ( time() % 86400 );
    $api->store->{'nextrun'} = time + $t;
    return $t;
}

1;