Skip to content

Instantly share code, notes, and snippets.

@MeesterPaul
Last active March 8, 2022 11:09
Show Gist options
  • Select an option

  • Save MeesterPaul/bfedbabe5a8ea53acc54d8ab7e4287a9 to your computer and use it in GitHub Desktop.

Select an option

Save MeesterPaul/bfedbabe5a8ea53acc54d8ab7e4287a9 to your computer and use it in GitHub Desktop.
Linking a Rocketbook to GitHub via Mailgun
GITHUB_TOKEN="YOUR-GITHUB-TOKEN"
GITHUB_USERNAME="YOUR-GITHUB-USERNAME"
MAILGUN_WEBHOOK_SIGNING_KEY="YOUR-MAILGUN-WEBHOOK-SIGNING-KEY"
ALLOWED_REPOS="
{
\"RocketbookTagName1\": {
\"user\": \"GITHUB-USER-1\",
\"repo\": \"REPO-1\"
},
\"RocketbookTagName2\": {
\"user\": \"GITHUB-USER-2\",
\"repo\": \"GITHUB-USER-2\"
}
}
"
<?php
// PHP script to link a Rocketbook to GitHub issues via a Mailgun webhook
// You will need dotenv and the GitHub API installed:
// composer require vlucas/phpdotenv knplabs/github-api:^3.0 guzzlehttp/guzzle:^7.0.1 http-interop/http-factory-guzzle:^1.0
// You'll also need a Rocketbook notebook, the Rocketbook app, a Mailgun account,
// a Github account, something to run the whole thing on and a fair amount of coffee
// See the article at https://rpress.io//articles/rocketbook-to-github-via-mailgun
/*
MIT License
Copyright 2022 Paul Ratcliffe
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
if (is_file('path/to/vendor/autoload.php')) {
require_once('path/to/vendor/autoload.php');
} else {
die("Cannot find 'vendor/autoload.php'. Run `composer install`.");
}
$logLocation = 'path/to/log/directory/' . date('Ymdhis') . '.log';
$dotenv = Dotenv\Dotenv::createImmutable('path/to/dotenv/file/'); // Load configuration from a .env file (see https://github.com/vlucas/phpdotenv)
$dotenv->safeLoad();
try {
$dotenv->required(['GITHUB_TOKEN','GITHUB_USERNAME','MAILGUN_WEBHOOK_SIGNING_KEY','ALLOWED_REPOS']);
} catch (Exception $e) {
$log = json_encode(['error' => 'Missing required environment variable']);
header('HTTP/1.1 406 Not Acceptable');
echo $log;
// file_put_contents( $logLocation, $log); // You can write to the log here, but I prefer to keep the log quieter in production
exit();
}
header('Content-Type: application/json; charset=utf-8');
$githubToken = $_ENV['GITHUB_TOKEN'];
$githubUsername = $_ENV['GITHUB_USERNAME'];
$signingKey = $_ENV['MAILGUN_WEBHOOK_SIGNING_KEY'];
// I'd recommend reading this to get some basics on Mailgun webhooks
// https://www.mailgun.com/blog/a-guide-to-using-mailguns-webhooks/
// Link the RocketBook tags to specific Github Repositories
$allowedRepos = json_decode($_ENV['ALLOWED_REPOS'],true);
if(!is_array($allowedRepos) || (is_array($allowedRepos) && count($allowedRepos) < 1)){
$log = json_encode(['error' => 'No linked Github repositories']);
header('HTTP/1.1 406 Not Acceptable');
echo $log;
// file_put_contents( $logLocation, $log); // You can write to the log here, but I prefer to keep the log quieter in production
exit();
}
$client = new \Github\Client(); // See https://github.com/KnpLabs/php-github-api
$client->authenticate($githubUsername, $githubToken, Github\AuthMethod::CLIENT_ID);
if($_SERVER['REQUEST_METHOD'] != 'POST'){
$log = json_encode(['error' => 'Request must be POST']);
header('HTTP/1.1 406 Not Acceptable');
echo $log;
// file_put_contents( $logLocation, $log); // You can write to the log here, but I prefer to keep the log quieter in production
exit();
}
if(!isset($_POST['token']) || !isset($_POST['timestamp']) || !isset($_POST['signature']) || !isset($_POST['stripped-text'])){
$log = json_encode(['error' => 'Missing expected POST fields']);
header('HTTP/1.1 406 Not Acceptable');
echo $log;
// file_put_contents( $logLocation, $log); // You can write to the log here, but I prefer to keep the log quieter
exit();
}
// Test to ensure it's a genuine POST from Mailgun
$testSignature = hash_hmac('SHA256', $_POST['timestamp'] . $_POST['token'], $signingKey);
if($testSignature !== $_POST['signature']){
$log = json_encode(['error' => 'Signatures do not match']);
header('HTTP/1.1 406 Not Acceptable');
echo $log;
// file_put_contents( $logLocation, $log); // You can write to the log here, but I prefer to keep the log quieter in production
exit();
}
$separator = "\r\n";
$line = strtok($_POST['stripped-text'], $separator);
$contentArray = [];
while ($line !== false) {
$contentArray[] = $line;
$line = strtok( $separator );
}
$lineCount = 0;
$sortedItems = [];
$started = false;
$what = 'issues';
$sortedItemsCounter = -1;
$currentlyProcessing = 'nothing';
$skipLine = false;
foreach($contentArray as $rawLine){
$lineCount++;
if($started) {
// Do stuff
$rawLine = trim($rawLine);
if(strpos($rawLine, 'ext transcription is made possible with OCR') !== false ){
$started = false;
} elseif(strpos($rawLine, '----') !== false){
// Page break, ignore this and next line
$skipLine = true;
} elseif($skipLine){
$skipLine = false;
} elseif(strpos($rawLine, 'Page ') === 0){
// Ignore line
} elseif(strpos($rawLine, '#') === 0){
// Ignore line
} elseif($rawLine[0] === "*"){
$sortedItems[] = ['title' => trim( substr($rawLine,1) ) ];
$currentlyProcessing = 'title';
$sortedItemsCounter++;
} elseif($rawLine[0] === "?" && $currentlyProcessing === 'title'){
$sortedItems[$sortedItemsCounter]['body'] = trim( substr($rawLine,1) );
$currentlyProcessing = 'body';
} elseif($sortedItemsCounter > -1 && $rawLine !== ""){
$sortedItems[$sortedItemsCounter][$currentlyProcessing] .= " " . $rawLine;
}
} elseif(trim($rawLine) === 'ISSUES'){
$started = true;
} elseif(trim($rawLine) === 'MILESTONES') {
$started = true;
$what = 'milestones';
}
}
preg_match('#\[(.*?)\]#', $_POST['Subject'], $match); // Extract the RocketBook tag
$processedContent = [
'repo' => $allowedRepos[$match[1]], // Match the RocketBook tag to the correct repo
'what' => $what,
'items' => $sortedItems,
];
if( isset($allowedRepos[$match[1]]) && count($sortedItems) > 0 ){
if( $processedContent['what'] === 'issues' ){
foreach( $processedContent['items'] as $issue ){
$client->api('issue')->create($processedContent['repo']['user'], $processedContent['repo']['repo'], $issue); // https://github.com/KnpLabs/php-github-api/blob/master/doc/issues.md
}
} elseif($processedContent['what'] === 'milestones'){
foreach( $processedContent['items'] as $milestone ){
$client->api('issue')->milestones()->create($processedContent['repo']['user'], $processedContent['repo']['repo'], [ 'title' => $milestone['title'], 'description' => $milestone['body'] ] ); // https://github.com/KnpLabs/php-github-api/blob/master/doc/issue/milestones.md
}
}
$log = json_encode($processedContent);
file_put_contents( $logLocation, $log);
print $log;
exit();
} else {
$processedContent['error'] = 'Could not find any issues or could not match repository';
$log = json_encode($processedContent);
file_put_contents( $logLocation, $log);
header('HTTP/1.1 406 Not Acceptable');
print $log;
exit();
}
@MeesterPaul
Copy link
Author

Linking a Rocketbook to GitHub via Mailgun

What if you could write down notes in a notebook with a pen, then have them magically appear in your GitHub issues list? How cool would that be?

You will probably want to read the article at https://rpress.io//articles/rocketbook-to-github-via-mailgun

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment