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 )