This repository has been archived on 2024-08-28. You can view files and clone it, but cannot push or open issues or pull requests.
satori-services/public/git-broadcast.php
2023-04-12 02:34:38 +00:00

170 lines
7 KiB
PHP

<?php
/*
* (21:42:47) malloc_CDLVII: i think that's one of the two rules of Flash Wave Development
* (21:42:57) malloc_CDLVII: 1. if it is written, it will be rewritten
* (21:43:04) malloc_CDLVII: 2. it will have automatic updates
*/
header('Content-Type: text/plain; charset=utf-8');
ini_set('display_errors', 'on');
error_reporting(-1);
if($_SERVER['REQUEST_METHOD'] !== 'POST')
die('no');
$config = __DIR__ . '/../config/git-broadcast.ini';
if(!is_file($config))
die('config missing');
$config = parse_ini_file($config, true);
if(empty($config['tokens']['token']))
die('config invalid');
$isGitea = isset($_SERVER['HTTP_X_GITEA_DELIVERY']) && isset($_SERVER['HTTP_X_GITEA_EVENT']);
$rawData = file_get_contents('php://input');
$sigParts = $isGitea
? ['sha256', $_SERVER['HTTP_X_GITEA_SIGNATURE']]
: explode('=', $_SERVER['HTTP_X_HUB_SIGNATURE'] ?? '', 2);
if(empty($sigParts[1]))
die('invalid signature');
$repoAuthenticated = false;
foreach($config['tokens']['token'] as $repoName => $repoToken) {
if(hash_equals(hash_hmac($sigParts[0], $rawData, $repoToken), $sigParts[1])) {
$repoAuthenticated = true;
break;
}
}
if(!$repoAuthenticated)
die('signature check failed');
$data = json_decode($_SERVER['CONTENT_TYPE'] === 'application/x-www-form-urlencoded'
? $_POST['payload']
: $rawData);
if(empty($data))
die('body is corrupt');
if(empty($data->repository->full_name))
die('body is corrupt');
if($data->repository->full_name !== $repoName)
die('invalid repository token');
$message = '';
switch($_SERVER['HTTP_X_GITHUB_EVENT']) {
case 'ping':
$message = "ping received from {$data->repository->full_name}!";
break;
case 'create':
switch ($data->ref_type) {
case 'tag':
$message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url][/b]: [url={$data->sender->html_url}]{$data->sender->login}[/url] created tag [url={$data->repository->html_url}/releases/tag/{$data->ref}]{$data->ref}[/url]";
break;
case 'branch':
$message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url][/b]: [url={$data->sender->html_url}]{$data->sender->login}[/url] created branch [url={$data->repository->html_url}/tree/{$data->ref}]{$data->ref}[/url]";
break;
case 'repository':
// doubt we'll ever get here
// TODO: test organisation level webhooks?
break;
}
break;
case 'delete':
switch($data->ref_type) {
case 'tag':
if (acl_check(ACL_BROADCAST))
$message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url][/b]: [url={$data->sender->html_url}]{$data->sender->login}[/url] deleted tag {$data->ref}";
break;
case 'branch':
if (acl_check(ACL_BROADCAST))
$message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url][/b]: [url={$data->sender->html_url}]{$data->sender->login}[/url] deleted branch {$data->ref}";
break;
case 'repository':
if (acl_check(ACL_BROADCAST))
$message = "[b]{$data->repository->full_name}[/b]: [url={$data->sender->html_url}]{$data->sender->login}[/url] deleted the repository :crying:";
break;
}
break;
case 'push':
$commitCount = count($data->commits);
if($commitCount < 1)
break;
$message .= "[b]{$data->repository->full_name}:" . substr($data->ref, strrpos($data->ref, '/') + 1) . "[/b] {$commitCount} new commit" . ($commitCount === 1 ? '' : 's') . "\r\n";
foreach($data->commits as $commit) {
$timestamp = strtotime($commit->timestamp);
$commit->message = trim($commit->message);
$message .= "[b][url={$commit->url}][code]" . substr($commit->id, 0, 7) . "[/code][/url][/b] {$commit->message} - [url=" . ($isGitea ? 'https://git.flash.moe/' : 'https://github.com/') . "{$commit->author->username}]{$commit->author->username}[/url]\r\n";
}
break;
case 'status':
$status_colour['failure'] = '#cb2431';
//$status_colour['pending'] = '#b5ab86';
$status_colour['success'] = '#28a745';
$status_colour['error'] = '#586069';
$status_emotes['failure'] = [':angry:', ':angrier:', ':angriest:', ':sad:', ':ouch:', ':dizzy:', ':sweat:', ':fat:', ':jew:'];
$status_emotes['success'] = [':happy:', ':lol:', ':yay:'];
$status_emotes['error'] = [':blank:'];
$status_name['continuous-integration/travis-ci/push'] = 'Unit Tests';
$status_name['continuous-integration/styleci/push'] = 'Style Check';
if (!array_key_exists($data->context, $status_name) || !array_key_exists($data->state, $status_colour)) {
//$message = "/msg flash {$data->context}: {$data->state}";
break;
}
$message = "[b][url={$data->commit->html_url}]{$data->repository->full_name}[/url] [url={$data->target_url}]" . $status_name[$data->context] . '[/url][/b]: [b][i][color=' . $status_colour[$data->state] . ']' . ucfirst($data->state) . ' ' . $status_emotes[$data->state][array_rand($status_emotes[$data->state])] . '[/color][/i][/b]';
break;
case 'watch':
switch($data->action) {
case 'started':
$message = "[url={$data->sender->html_url}]{$data->sender->login}[/url] starred [url={$data->repository->html_url}]{$data->repository->full_name}[/url] :love:";
break;
}
break;
case 'fork':
$message = "[url={$data->forkee->html_url}]{$data->forkee->owner->login}[/url] forked [url={$data->repository->html_url}]{$data->repository->full_name}[/url] :omg:";
break;
case 'issues':
if(!in_array($data->action, ['opened', /*'edited',*/ 'closed', 'reopened']))
break;
$message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url] [url={$data->sender->html_url}]{$data->sender->login}[/url] {$data->action} issue [/b][url={$data->issue->html_url}][b]#{$data->issue->number}[/b]: {$data->issue->title}[/url]";
break;
case 'pull_request':
if(!in_array($data->action, ['opened', /*'edited',*/ 'closed', 'reopened']))
break;
$message = "[b][url={$data->repository->html_url}]{$data->repository->full_name}[/url]: [url={$data->sender->html_url}]{$data->sender->login}[/url] {$data->action} pull request [/b][url={$data->pull_request->html_url}][b]#{$data->pull_request->number}[/b]: {$data->pull_request->title}[/url]";
break;
}
if(!empty($message)) {
// the
var_dump($message);
$sock = fsockopen($config['boat']['host'], $config['boat']['port'], $errno, $errstr, 5);
$message = chr(1) . '/msg flash ' . $message;
$message = hash_hmac('sha256', $message, $config['boat']['secret'], true) . $message;
fwrite($sock, $message);
}