|
| 1 | +<?php |
| 2 | +declare(strict_types=1); |
| 3 | + |
| 4 | +/** |
| 5 | +* @link https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads |
| 6 | +* @link https://github.com/github/docs/blob/main/content/developers/webhooks-and-events/webhooks/webhook-events-and-payloads.md |
| 7 | +* @link https://github.com/organizations/interserver/settings/hooks/359889086?tab=deliveries |
| 8 | +* |
| 9 | +*/ |
| 10 | + |
| 11 | +header('Content-Type: text/plain; charset=utf-8'); |
| 12 | +// set default response code |
| 13 | +http_response_code(500); |
| 14 | + |
| 15 | +require __DIR__ . '/../src/config.php'; |
| 16 | +require __DIR__ . '/../src/GithubWebhook.php'; |
| 17 | +require __DIR__ . '/../src/IgnoredEventException.php'; |
| 18 | +require __DIR__ . '/../src/NotImplementedException.php'; |
| 19 | + |
| 20 | +$Hook = new GitHubWebHook(); |
| 21 | +try { |
| 22 | + if (!$Hook->ValidateHubSignature(GITHUB_WEBHOOKS_SECRET)) { |
| 23 | + throw new Exception('Secret validation failed.'); |
| 24 | + } |
| 25 | + $Hook->ProcessRequest(); |
| 26 | + $RepositoryName = $Hook->GetFullRepositoryName(); |
| 27 | + $EventType = $Hook->GetEventType(); |
| 28 | + // format message |
| 29 | + //$Converter = new Converter($Hook->GetEventType(), $Hook->GetPayload()); |
| 30 | + //$Message = $Converter->GetEmbed(); |
| 31 | + $Message = $Hook->GetPayload(); |
| 32 | + $log = ['repo' => $RepositoryName, 'event' => $EventType, 'data' => $Message]; |
| 33 | + $Msg = []; |
| 34 | + if (isset($Message[$EventType]['app']['name'])) { |
| 35 | + $User = $Message[$EventType]['app']['name']; |
| 36 | + } else { |
| 37 | + $User = $Message['sender']['login']; |
| 38 | + } |
| 39 | + if (isset($Message[$EventType]['app']['owner']['avatar_url'])) { |
| 40 | + $Msg['avatar'] = $Message[$EventType]['app']['owner']['avatar_url']; |
| 41 | + } elseif (isset($Message['avatar_url'])) { |
| 42 | + $Msg['avatar'] = $Message['avatar_url']; |
| 43 | + } else { |
| 44 | + $Msg['avatar'] = $Message['sender']['avatar_url']; |
| 45 | + } |
| 46 | + if (isset($Message['head_commit'])) { |
| 47 | + $Msg['alias'] = $Message['head_commit']['author']['name']; |
| 48 | + } elseif (isset($Message['commits']) && isset($Message['commits'][0]['author']['name'])) { |
| 49 | + $Msg['alias'] = $Message['commits'][0]['author']['name']; |
| 50 | + } elseif (isset($Message['commit']) && isset($Message['commit']['commit']['author']['name'])) { |
| 51 | + $Msg['alias'] = $Message['commit']['commit']['author']['name']; |
| 52 | + } |
| 53 | + file_put_contents(__DIR__.'/../log/'.date('Ymd_His').'_'.$EventType.(isset($Message['action']) ? '_'.$Message['action'] : '').'_'.$User.'_'.str_replace(['/', '-', ' '], ['_', '_', '_'], $RepositoryName).'.json', json_encode($log, JSON_PRETTY_PRINT)); |
| 54 | + if (empty($Message)) { |
| 55 | + throw new Exception('Empty message, not sending.'); |
| 56 | + } |
| 57 | + |
| 58 | + |
| 59 | + switch ($EventType) { |
| 60 | + case 'issues': |
| 61 | + if ($Message['action'] == 'opened') { |
| 62 | + $ChatMsg = "[{$User}](https://github.com/{$User}) opened a new [Issue](https://github.com/{$RepositoryName}/issues/{$Message['issue']['number']}) for [{$RepositoryName}](https://github.com/{$RepositoryName}) _{$Message['issue']['title']}_."; |
| 63 | + $Msg['text'] = $ChatMsg; |
| 64 | + //error_log($Msg['text']); |
| 65 | + SendToChat('int-dev', $Msg); |
| 66 | + } else { |
| 67 | + $ChatMsg = "{$User} triggered a {$EventType} event ".(isset($Message['action']) ? $Message['action'].' action ' : '')." notification on https://github.com/{$RepositoryName} ".(isset($Message['ref']) ? str_replace('refs/heads/', '', $Message['ref']) : '')."."; |
| 68 | + $Msg['text'] = $ChatMsg; |
| 69 | + //error_log($Msg['text']); |
| 70 | + SendToChat('notifications', $Msg); |
| 71 | + } |
| 72 | + // no break |
| 73 | + case 'push': |
| 74 | + $Branch = isset($Message['ref']) && !is_null($Message['ref']) ? str_replace('refs/heads/', '', $Message['ref']) : ''; |
| 75 | + if (isset($Message['head_commit']['message'])) { |
| 76 | + $CommitMsg = $Message['head_commit']['message']; |
| 77 | + } elseif (isset($Message['data']['issue']['title'])) { |
| 78 | + $CommitMsg = $Message['data']['issue']['title']; |
| 79 | + } else { |
| 80 | + $CommitMsg = ''; |
| 81 | + } |
| 82 | + $CommitCount = isset($Message['commits']) ? count($Message['commits']) : 1; |
| 83 | + $ChatMsg = "{$Msg['alias']} pushed ".($CommitCount == 1 ? 'a commit' : $CommitCount.' commits')." to https://github.com/{$RepositoryName} [*{$Branch}*]\n🕮 {$CommitMsg}"; |
| 84 | + $Msg['text'] = $ChatMsg; |
| 85 | +//error_log($Msg['text']); |
| 86 | + SendToChat('notifications', $Msg); |
| 87 | + break; |
| 88 | + case 'check_suite': |
| 89 | + case 'check_run': |
| 90 | + case 'create': |
| 91 | + case 'pull_request': |
| 92 | + case 'workflow_run': |
| 93 | + case 'workflow_job': |
| 94 | + break; |
| 95 | + default: |
| 96 | + $ChatMsg = "{$Msg['alias']} triggered a {$EventType} event ".(isset($Message['action']) ? $Message['action'].' action ' : '')." notification on https://github.com/{$RepositoryName} ".(isset($Message['ref']) ? str_replace('refs/heads/', '', $Message['ref']) : '')."."; |
| 97 | + $Msg['text'] = $ChatMsg; |
| 98 | +//error_log($Msg['text']); |
| 99 | + SendToChat('notifications', $Msg); |
| 100 | + break; |
| 101 | + } |
| 102 | + /* |
| 103 | + foreach($githubWebhooks as $Event => $Repos) { |
| 104 | + if (!WildMatch($EventType, $Event)) |
| 105 | + foreach ($Repos as $Repo => $SendTargets) { |
| 106 | + if (!WildMatch($RepositoryName, $Repo)) |
| 107 | + continue; |
| 108 | + foreach($SendTargets as $ChannelName) { |
| 109 | + SendToChat($ChannelName, $Message); |
| 110 | + } |
| 111 | + } |
| 112 | + } |
| 113 | + */ |
| 114 | + //error_log('GitHub Hook '.$EventType.' on '.$RepositoryName.' called'); |
| 115 | + http_response_code(202); |
| 116 | +} catch (IgnoredEventException $e) { |
| 117 | + http_response_code(200); |
| 118 | + error_log('This GitHub event is ignored.'); |
| 119 | +} catch (NotImplementedException $e) { |
| 120 | + http_response_code(501); |
| 121 | + error_log('Unsupported GitHub event: ' . $e->EventName); |
| 122 | +} catch (Exception $e) { |
| 123 | + error_log('Exception: ' . $e->getMessage() . PHP_EOL); |
| 124 | +} |
| 125 | + |
| 126 | +function WildMatch(string $string, string $expression) : bool |
| 127 | +{ |
| 128 | + if (strpos($expression, '*') === false) { |
| 129 | + return strcmp($expression, $string) === 0; |
| 130 | + } |
| 131 | + $expression = preg_quote($expression, '/'); |
| 132 | + $expression = str_replace('\*', '.*', $expression); |
| 133 | + return preg_match('/^' . $expression . '$/', $string) === 1; |
| 134 | +} |
| 135 | + |
| 136 | +function SendToChat(string $Where, array $Payload) : bool |
| 137 | +{ |
| 138 | + global $chatChannels; |
| 139 | + $Url = $chatChannels['rocketchat'][$Where]; |
| 140 | + $c = curl_init(); |
| 141 | + curl_setopt_array($c, [ |
| 142 | + CURLOPT_USERAGENT => 'https://github.com/xPaw/GitHub-WebHook', |
| 143 | + CURLOPT_RETURNTRANSFER => true, |
| 144 | + CURLOPT_FOLLOWLOCATION => 0, |
| 145 | + CURLOPT_TIMEOUT => 30, |
| 146 | + CURLOPT_CONNECTTIMEOUT => 30, |
| 147 | + CURLOPT_URL => $Url, |
| 148 | + CURLOPT_POST => true, |
| 149 | + CURLOPT_POSTFIELDS => json_encode($Payload), |
| 150 | + CURLOPT_HTTPHEADER => [ |
| 151 | + 'Content-Type: application/json', |
| 152 | + ], |
| 153 | + ]); |
| 154 | + curl_exec($c); |
| 155 | + $Code = curl_getinfo($c, CURLINFO_HTTP_CODE); |
| 156 | + curl_close($c); |
| 157 | + //error_log('Rocket Chat HTTP ' . $Code . PHP_EOL); |
| 158 | + $c = curl_init(); |
| 159 | + $Url = $chatChannels['teams'][$Where]; |
| 160 | + curl_setopt_array($c, [ |
| 161 | + CURLOPT_USERAGENT => 'https://github.com/xPaw/GitHub-WebHook', |
| 162 | + CURLOPT_RETURNTRANSFER => true, |
| 163 | + CURLOPT_FOLLOWLOCATION => 0, |
| 164 | + CURLOPT_TIMEOUT => 30, |
| 165 | + CURLOPT_CONNECTTIMEOUT => 30, |
| 166 | + CURLOPT_URL => $Url, |
| 167 | + CURLOPT_POST => true, |
| 168 | + CURLOPT_POSTFIELDS => json_encode([ |
| 169 | + 'type' => 'message', |
| 170 | + 'message' => $Payload['text'] |
| 171 | + ]), |
| 172 | + CURLOPT_HTTPHEADER => [ |
| 173 | + 'Content-Type: application/json', |
| 174 | + ], |
| 175 | + ]); |
| 176 | + curl_exec($c); |
| 177 | + $Code = curl_getinfo($c, CURLINFO_HTTP_CODE); |
| 178 | + curl_close($c); |
| 179 | + |
| 180 | + return $Code >= 200 && $Code < 300; |
| 181 | +} |
0 commit comments