load_tasks.pl 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #!/usr/local/perl-cbt/bin/perl
  2. use Modern::Perl;
  3. use Carp;
  4. use Data::Dumper;
  5. use HTTP::Request;
  6. use JSON;
  7. use LWP::UserAgent;
  8. use MIME::Base64 qw/decode_base64/;
  9. use Try::Tiny;
  10. my $BASE_URL = 'https://taskboard.example.com/api';
  11. my $TOKEN = 'MY_TOKEN';
  12. my $me = 'MY_USER_ID';
  13. my $ua = LWP::UserAgent->new();
  14. my @headers;
  15. push @headers, ( 'Accept', 'application/json' );
  16. push @headers, ( 'Authorization', "Bearer $TOKEN" );
  17. my @form_headers;
  18. push @form_headers, ( 'Content-Type', 'application/json' );
  19. push @form_headers, ( 'Accept', 'application/json' );
  20. push @form_headers, ( 'Authorization', "Bearer $TOKEN" );
  21. # Prior to running this, I built all the boards, with labels and lists and swimlanes.
  22. # Grabbed the IDs for the boards for each project, and put them here to match up with
  23. # filenames from the Asana export script.
  24. my %board_to_use = (
  25. Project_1 => 'F5ZiCXnf4d7qNBRjp',
  26. Project_2 => 'Shw3tyfC2JWCutBLj',
  27. );
  28. opendir my $files_dir, '.'
  29. or croak "Cannot open input directory: $!";
  30. my @files = readdir $files_dir;
  31. closedir $files_dir;
  32. foreach my $tasks_file (@files) {
  33. next if $tasks_file !~ /_exported.json/;
  34. my $project = $tasks_file;
  35. $project =~ s/_exported.json//;
  36. say "Project - $project";
  37. my $board;
  38. if ( $board_to_use{$project} ) {
  39. $board = $board_to_use{$project};
  40. }
  41. say ' No board!' if !$board;
  42. next if !$board;
  43. my $labels_req = HTTP::Request->new( 'GET', "$BASE_URL/boards/$board", \@headers );
  44. my $labels_res = $ua->request($labels_req);
  45. my $board_data = decode_json( $labels_res->content);
  46. my $labels = $board_data->{labels};
  47. my $label_to_use;
  48. # We're merging several Asana boards onto one Wekan board, with labels per project.
  49. foreach my $label (@$labels) {
  50. $label_to_use = $label->{_id} if $label->{name} eq $project;
  51. }
  52. my $lanes_req = HTTP::Request->new( 'GET', "$BASE_URL/boards/$board/swimlanes", \@headers );
  53. my $lanes_res = $ua->request($lanes_req);
  54. my $lanes = decode_json( $lanes_res->content );
  55. my $lane_to_use;
  56. foreach my $lane (@$lanes) {
  57. # Our Asana didn't use swimlanes; all of our Wekan boards have a "Bugs" lane, so use that.
  58. $lane_to_use = $lane->{_id} if $lane->{title} eq 'Bugs';
  59. }
  60. my $lists_req = HTTP::Request->new( 'GET', "$BASE_URL/boards/$board/lists", \@headers );
  61. my $lists_res = $ua->request($lists_req);
  62. my $lists = decode_json( $lists_res->content );
  63. my %list_to_use;
  64. foreach my $list (@$lists) {
  65. $list_to_use{ $list->{title} } = $list->{_id};
  66. }
  67. open my $task_export_file, '<', $tasks_file;
  68. my $tasks_json = readline($task_export_file);
  69. close $task_export_file;
  70. my $tasks = decode_json($tasks_json);
  71. foreach my $task (@$tasks) {
  72. say ' - ' . $task->{title};
  73. my %body_info = (
  74. swimlaneId => $lane_to_use,
  75. authorId => $task->{userId},
  76. assignees => $task->{assignees},
  77. title => $task->{title},
  78. description => $task->{description},
  79. );
  80. my $body = encode_json( \%body_info );
  81. my $list = $list_to_use{ $task->{listId} } // $list_to_use{'Backlog'};
  82. my $task_req = HTTP::Request->new( 'POST', "$BASE_URL/boards/$board/lists/$list/cards",
  83. \@form_headers, $body );
  84. my $task_res = $ua->request($task_req);
  85. my $res;
  86. try {
  87. $res = decode_json( $task_res->content );
  88. } catch {
  89. # Did these manually afterward.
  90. say "--->UNABLE TO LOAD TASK";
  91. next;
  92. };
  93. my $card = $res->{_id};
  94. if ($label_to_use) {
  95. my $card_edit_body = encode_json( { labelIds => [ $label_to_use ]});
  96. my $card_edit_req = HTTP::Request->new( 'PUT', "$BASE_URL/boards/$board/lists/$list/cards/$card",
  97. \@form_headers, $card_edit_body );
  98. my $card_edit_res = $ua->request($card_edit_req);
  99. }
  100. foreach my $comment ( @{ $task->{comments} } ) {
  101. my $comment_body =
  102. encode_json( { authorId => $comment->{userId}, comment => $comment->{text} } );
  103. my $comment_req =
  104. HTTP::Request->new( 'POST', "$BASE_URL/boards/$board/cards/$card/comments",
  105. \@form_headers, $comment_body );
  106. my $comment_res = $ua->request($comment_req);
  107. }
  108. }
  109. }