Skip to content

Instantly share code, notes, and snippets.

@2shortplanks
Last active May 10, 2019 18:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 2shortplanks/4ca8458953f51f665ddb3bdb6059141f to your computer and use it in GitHub Desktop.
Save 2shortplanks/4ca8458953f51f665ddb3bdb6059141f to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
use strict;
use warnings;
use HTTP::Tiny;
use IPC::Run3 qw( run3 );
use JSON::PP qw( encode_json decode_json );
my $PROJECT_ID = ...; # The numbers at the end of your project URL
my $TOKEN = ...; # "API token" from https://www.pivotaltracker.com/profile
my $PTUSERNAME = ...; # "User name" from https://www.pivotaltracker.com/profile
my $FOLDERID = ...; # the id of the folder to create projects in (the end of what you get when right click on folder and "Copy as link")
my $of_projects = get_of_data();
my $pt_projects = get_pt_data();
for my $project (@{ $pt_projects->{stories}{stories} } ) {
next if of_data_contains_url( $project->{url} );
create_new_project(
name => "PT: $project->{name}",
note => <<"NOTE",
$project->{url}
$project->{description}
NOTE
);
}
###
# talking to PT
###
sub get_pt_data {
my $response = HTTP::Tiny->new->get(
"https://www.pivotaltracker.com/services/v5/projects/$PROJECT_ID/search?query=mywork:$PTUSERNAME",
{
headers => {
'X-TrackerToken' => $TOKEN,
},
},
);
unless ($response->{success}) { die "$response->{status} $response->{reason}" }
return decode_json($response->{content});
}
###
# talking to OF
###
sub get_of_data { return run_jxa(<<'JAVASCRIPT') }
JSON.stringify(
Application('OmniFocus')
.defaultDocument
.tags["pt"]
.remainingTasks()
.map(e => e.containingProject())
.filter(e => e)
.sort(a => a.id())
.filter( (v,i,a) => (i === 0) || (v.id() !== a[i-1].id() ))
.map(a => ({ name : a.name(), note : a.note.text() }))
);
JAVASCRIPT
sub create_new_project { return run_jxa(<<'JAVASCRIPT', { @_, folder_id => $FOLDERID }) }
var omnifocus = Application("OmniFocus");
var project = omnifocus.Project({
name: data.name,
note: data.note,
});
omnifocus.defaultDocument.folders.byId(data.folder_id).projects.push(project);
var tag = omnifocus.defaultDocument.tags["pt"];
omnifocus.add(
tag,
{ to: project.rootTask().tags }
);
{ done: true };
JAVASCRIPT
sub run_jxa {
my $javascript = shift;
my $input = shift;
$javascript = "let data = @{[ encode_json($input // {}) ]};\n$javascript";
my $stdout = q{};
my $stderr = q{};
run3([ '/usr/bin/osascript', '-l', 'JavaScript' ], \$javascript, \$stdout, \$stderr);
die $? if $?;
die $stderr if $stderr;
return decode_json($stdout);
}
sub of_data_contains_url {
my $url = shift;
for my $item (@{ $of_projects }) {
return 1 if index($item->{note} // q{}, $url) != -1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment