migrate2.pl 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #!/usr/bin/env perl
  2. use v5.36;
  3. use re '/aa';
  4. # Migrate early on tcms3 flatfile sites to 'all posts are series code' (august 2021) code
  5. use FindBin;
  6. use lib "$FindBin::Bin/../lib";
  7. use Trog::Config;
  8. use Trog::Data;
  9. use List::Util;
  10. use UUID::Tiny;
  11. use Trog::SQLite;
  12. use Trog::SQLite::TagIndex;
  13. =head1 SYNOPSIS
  14. Migrate early tCMS3 flatfile sites to the 'all posts are series' code (August
  15. 2021).
  16. Re-keys every post from a timestamp onto a UUID, keeping the old URL as an
  17. alias so nothing already linked breaks, and fills in the fields that release
  18. started requiring: local_href, callback, method, visibility and the form each
  19. post is edited with. Then it rebuilds the index and adds the series posts
  20. (/series, /about, /config) that the new code expects to exist.
  21. =head2 USAGE
  22. Edit $user and @extra_series below to suit your installation, then:
  23. bin/migrate2.pl
  24. Run from the tCMS root.
  25. =head2 CAVEATS
  26. Historical, and one way. It deletes the timestamp keyed flat files as it
  27. rewrites them, so take a backup of data/ before running it.
  28. Also unlinks data/posts.db up front, as the index is rebuilt at the end
  29. regardless.
  30. The form a post gets is guessed from its tags and content type, and series
  31. child_form from the series title, so anything unusual will want checking
  32. afterwards.
  33. =cut
  34. # Kill the post index
  35. unlink "$FindBin::Bin/../data/posts.db";
  36. $ENV{NOHUP} = 1;
  37. sub uuid { return UUID::Tiny::create_uuid_as_string( UUID::Tiny::UUID_V1, UUID::Tiny::UUID_NS_DNS ); }
  38. # Modify these variables to suit your installation.
  39. my $user = 'george';
  40. my @extra_series;
  41. my $conf = Trog::Config::get();
  42. my $search_info = Trog::Data->new($conf);
  43. my @all = $search_info->get( raw => 1, limit => 0 );
  44. my %posts;
  45. foreach my $post (@all) {
  46. $posts{ $post->{id} } //= [];
  47. # Re-do the IDs
  48. push( @{ $posts{ $post->{id} } }, $post );
  49. }
  50. foreach my $timestamp ( keys(%posts) ) {
  51. my $file_to_kill = "$FindBin::Bin/../data/files/$timestamp";
  52. my $new_id = uuid();
  53. # Preserve old URLs
  54. foreach my $post ( @{ $posts{$timestamp} } ) {
  55. delete $post->{app};
  56. delete $post->{preview_file};
  57. delete $post->{wallpaper_file};
  58. delete $post->{scheme};
  59. delete $post->{route};
  60. delete $post->{domain};
  61. $post->{id} = $new_id;
  62. $post->{local_href} = "/posts/$new_id";
  63. $post->{aliases} = ["/posts/$timestamp"];
  64. $post->{callback} = "Trog::Routes::HTML::posts";
  65. $post->{method} = 'GET';
  66. @{ $post->{tags} } = grep { defined $_ } @{ $post->{tags} };
  67. $post->{content_type} //= 'text/html';
  68. $post->{form} = 'microblog.tx';
  69. $post->{form} = 'blog.tx' if grep { $_ eq 'blog' } @{ $post->{tags} };
  70. $post->{form} = 'file.tx' if $post->{content_type} =~ m/^video\//;
  71. $post->{form} = 'file.tx' if $post->{content_type} =~ m/^audio\//;
  72. $post->{form} = 'file.tx' if $post->{content_type} =~ m/^image\//;
  73. if ( grep { $_ eq 'about' } @{ $post->{tags} } ) {
  74. $post->{form} = 'profile.tx';
  75. $post->{local_href} = "/users/$post->{user}";
  76. $post->{callback} = "Trog::Routes::HTML::users";
  77. }
  78. if ( grep { $_ eq 'series' } @{ $post->{tags} } ) {
  79. $post->{form} = 'series.tx';
  80. $post->{callback} = "Trog::Routes::HTML::series";
  81. $post->{child_form} = 'microblog.tx';
  82. $post->{child_form} = 'blog.tx' if $post->{title} =~ m/^blog/i;
  83. $post->{child_form} = 'file.tx' if $post->{title} =~ m/^video\//;
  84. $post->{child_form} = 'file.tx' if $post->{title} =~ m/^audio\//;
  85. $post->{child_form} = 'file.tx' if $post->{title} =~ m/^image\//;
  86. $post->{local_href} = "/$post->{aclname}";
  87. $post->{aliases} = [ "/series/$timestamp", "/series/$new_id" ];
  88. }
  89. $search_info->write( [$post] );
  90. unlink $file_to_kill;
  91. }
  92. }
  93. # Rebuild the index
  94. Trog::SQLite::TagIndex::build_index($search_info);
  95. Trog::SQLite::TagIndex::build_routes($search_info);
  96. # Add in the series
  97. my $series = [
  98. {
  99. "aclname" => "series",
  100. "acls" => [],
  101. aliases => [],
  102. "callback" => "Trog::Routes::HTML::series",
  103. method => 'GET',
  104. "data" => "Series",
  105. "href" => "/series",
  106. "local_href" => "/series",
  107. "preview" => "/img/sys/testpattern.jpg",
  108. "tags" => [qw{series topbar}],
  109. visibility => 'public',
  110. "title" => "Series",
  111. user => $user,
  112. form => 'series.tx',
  113. child_form => 'series.tx',
  114. },
  115. {
  116. "aclname" => "about",
  117. "acls" => [],
  118. aliases => [],
  119. "callback" => "Trog::Routes::HTML::series",
  120. method => 'GET',
  121. "data" => "About",
  122. "href" => "/about",
  123. "local_href" => "/about",
  124. "preview" => "/img/sys/testpattern.jpg",
  125. "tags" => [qw{series topbar public}],
  126. visibility => 'public',
  127. "title" => "About",
  128. user => $user,
  129. form => 'series.tx',
  130. child_form => 'profile.tx',
  131. },
  132. {
  133. "aclname" => "admin",
  134. acls => [],
  135. aliases => [],
  136. "callback" => "Trog::Routes::HTML::config",
  137. 'method' => 'GET',
  138. "content_type" => "text/plain",
  139. "data" => "Config",
  140. "href" => "/config",
  141. "local_href" => "/config",
  142. "preview" => "/img/sys/testpattern.jpg",
  143. "tags" => [qw{admin}],
  144. visibility => 'private',
  145. "title" => "Configure tCMS",
  146. user => $user,
  147. },
  148. ];
  149. $search_info->add( @$series, @extra_series );