App-RoboBot

 view release on metacpan or  search on metacpan

lib/App/RoboBot/Plugin/API/Github.pm  view on Meta::CPAN

            return;
        }

        my $repo = $self->bot->config->db->do(q{
            select repo_id
            from github_repos
            where lower(owner_name) = lower(?) and lower(repo_name) = lower(?)
        }, $owner_name, $repo_name);

        if ($repo && $repo->next) {
            my $res = $self->bot->config->db->do(q{
                delete from github_repo_channels where repo_id = ? and channel_id = ? returning *
            }, $repo->{'repo_id'}, $message->channel->id);

            if ($res) {
                if ($res->next) {
                    $message->response->push(sprintf('I will no longer notify this channel about events from %s.', $url));
                    next REPO;
                } else {
                    $message->response->raise('I was not watching %s for this channel.', $url);
                    next REPO;
                }
            } else {
                $message->response->raise('Encountered an error when attempting to remove this channel\'s watcher for %s.', $url);
                next REPO;
            }
        } else {
            $message->response->raise('"%s" is not a Github repository that I have been watching.', $url);
            next REPO;
        }
    }

    return;
}

sub clean_repo_url {
    my ($self, $url) = @_;

    $url =~ s{(^\<|\>$)}{}gs;
    $url =~ s{\.git(/|$)}{$1}s;

    return $url;
}

sub get_repo_parts {
    my ($self, $url) = @_;

    if ($url =~ m{github\.com/([^/]+)/([^/]+)(?:\.git)?}i) {
        return ($1, $2);
    }

    return;
}

sub get_repo_notices {
    my ($self, $repo) = @_;

    # Update repo with polled_at = now() - 10 seconds, so that every time we
    # poll GH, we're actually looking at a window of length(watcher_interval)
    # offset 10 seconds in the past. This gives events on the GH side of things
    # time to propogate to their API endpoints, so we don't miss out.
    my $poll_t = $self->bot->config->db->do(q{
        update github_repos
        set polled_at = now() - interval '10 seconds'
        where repo_id = ?
        returning to_char(polled_at at time zone 'UTC','YYYY-MM-DD"T"HH24:MI:SS"Z"') as polled_at
    }, $repo->{'repo_id'});

    return unless $poll_t && $poll_t->next;

    my ($json, @notices);

    my $api_path = ['repos',$repo->{'owner_name'},$repo->{'repo_name'},'commits'];
    my $api_args = { since => $repo->{'polled_at'}, until => $poll_t->{'polled_at'} };

    if ($json = $self->make_gh_api_call($api_path,$api_args)) {
        if (ref($json) eq 'ARRAY' && @{$json} > 0) {
            my $oldest_commit;
            my %commiters;
            my @commits;

            foreach my $commit (@{$json}) {
                $commiters{$commit->{'commit'}{'author'}{'email'}}
                    =    $commit->{'commit'}{'author'}{'name'}
                      // $commit->{'commit'}{'author'}{'email'}
                    if exists $commit->{'commit'}{'author'}{'email'};

                $oldest_commit = $commit->{'parents'}[0]{'sha'} if exists $commit->{'parents'}[0]{'sha'};

                push(@commits, {
                    # TODO: proper commit hash shortening (problem: requires git
                    #       repo access to ensure uniqueness of short hash)
                    id      => substr($commit->{'sha'}, 0, 10),
                    sha     => $commit->{'sha'},
                    comment => $self->short_commit_comment($commit->{'commit'}{'message'}),
                    url     => $commit->{'commit'}{'html_url'},
                    author  => $commit->{'commit'}{'author'}{'name'} // $commit->{'commit'}{'author'}{'email'},
                });
            }

            # TODO: The links are really useful in Slack channel notices, but
            #       they're going to be painful in IRC channels. Make sure this
            #       gets cleaned up whenever per-network output templating is
            #       implemented. Also, Slack seems to currently have an issue
            #       server-side with parsing incoming <link|label> strings and
            #       displays them literally instead of parsing.
            push(@notices, sprintf('[https://github.com/%s/%s] %d new commit%s by %s.',
                $repo->{'owner_name'}, $repo->{'repo_name'},
                scalar(@commits), (scalar(@commits) == 1 ? '' : 's'),
                join(', ', sort { $a cmp $b } values %commiters)));
            push(@notices, sprintf('> *%s*: %s - _%s_',
                $_->{'id'}, $_->{'comment'}, $_->{'author'})) foreach @commits;

            if (defined $oldest_commit) {
                push(@notices, sprintf('View diff on Github: https://github.com/%s/%s/compare/%s...%s',
                    $repo->{'owner_name'}, $repo->{'repo_name'},
                    substr($oldest_commit, 0, 16),
                    substr($commits[0]{'sha'}, 0, 16)));
            }
        }
    } else {



( run in 2.584 seconds using v1.01-cache-2.11-cpan-ceb78f64989 )