Ticket #1263: myth.rebuilddatabase.pl

File myth.rebuilddatabase.pl, 12.2 KB (added by gnassas@…, 20 years ago)

the new script

Line 
1#!/usr/bin/perl
2## written by greg froese (g_froese@yahoo.com)
3## install instructions by Robert Kulagowski (rkulagow@rocketmail.com)
4##
5## I had trouble maintaining my catalog of recordings when upgrading to
6## cvs and from cvs to more recent cvs, so I wrote this.
7##
8## Here is what this program is supposed to do.
9## It first scans through your myth database and displays all shows listed
10## in the recorded table.
11## It will then traverse your myth directory (set with --dir /YOURMYTHDIR) and
12## find all your .nuv files and check them against the database to make sure
13## they have an entry. If no entry exists, you will be prompted for the title
14## and subtitle of the recording and a record will be created.
15##
16## The following options are available to be changed from the command line
17## (I've put defaults in if you leave them out, except for $dir)
18## --dbhost DBHOSTNAME
19## --host HOSTNAME
20## --user DBUSERNAME
21## --pass DBPASSWORD
22## --dir /MYTHFILESARESTOREDHERE
23## --database DATABASENAME
24##
25## use at your own risk, i am not responsible for anything this program may
26## or may not do.
27
28## To run:
29## Ensure that the script is executable
30## chmod a+x myth.rebuilddatabase.pl
31## ./myth.rebuilddatabase.pl
32
33## Change log:
34## 9-19-2003: (awithers@anduin.com)
35## Anduin fights the urge to make code more readable (aka C like). Battle
36## of urges ends in stalemate: code was reindented but not "changed" (much).
37## To make it a little less useless a contribution also did:
38## - added ability to grab title/subtitle/description from oldrecorded
39## - support for multiple backends (via separation of host and dbhost
40## and bothering to insert the host in the recorded table).
41## - removed dependency on File::Find::Rule stuff
42## - attempt to determine good default host name
43## - provide default for --dir from DB (if not provided)
44## - added --test_mode (for debugging, does everything except INSERT)
45## - added --try_default (good for when you must specify a command
46## line option but don't really need to)
47## - added --quick_run for those occasions where you just don't have
48## the sort of time to be sitting around hitting enter
49## - changed all the DB calls to use parameters (avoids escape issues,
50## and it looks better)
51
52use strict;
53use DBI;
54use Getopt::Long;
55use Sys::Hostname;
56use File::Basename;
57use Date::Parse;
58use Time::Format qw(time_format);
59
60## get command line args
61
62my ($verbose, $dir);
63
64my $show_existing = 0;
65my $test_mode = 0;
66my $quick_run = 0;
67my $try_default = 0;
68
69my $host = hostname;
70my $dbhost = $host;
71my $database = "mythconverg";
72my $user = "mythtv";
73my $pass = "mythtv";
74my $ext = "nuv";
75my $file = "";
76my @answers;
77my $norename = 0;
78
79my $date_regx = qr/(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)/;
80my $db_date_regx = qr/(\d\d\d\d)-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)/;
81my $channel_regx = qr/(\d\d\d\d)/;
82
83sub GetAnswer {
84 my ($prompt, $default) = @_;
85 print $prompt;
86 if ($default) {
87 print " [", $default, "]";
88 }
89 print ": ";
90
91 my $answer;
92 if ($#answers >= 0) {
93 $answer = shift @answers;
94 print $answer, "\n";
95 } else {
96 chomp($answer = <STDIN>);
97 $answer = $default if !$answer;
98 }
99
100 return $answer;
101}
102
103my $script_name = $0;
104
105if ($0 =~ m/([^\/]+)$/) {
106 $script_name = $1;
107}
108
109my $script_version = "0.0.2";
110
111my $argc=@ARGV;
112if ($argc == 0) {
113 print "$script_name Version $script_version
114 usage: $script_name [options]
115
116 Where [options] is:
117 --host - hostname of this backend (default: \"$host\")
118 --dbhost - hostname or IP address of the mysql server
119 (default: \"$dbhost\")
120 --user - DBUSERNAME (default: \"$user\")
121 --pass - DBPASSWORD (default: \"$pass\")
122 --database - DATABASENAME (default: \"$database\")
123 --show_existing - Dumps current recorded table.
124 --dir - path to recordings (default: queried from db)
125 --try_default - Try to just run with the defaults.
126 --quick_run - don't prompt for title/subtitle/description just
127 use the default
128 --test_mode - do everything except update the database
129 --ext - file extensions to scan for
130 --file - specific file to import
131 --answer - command-line response to prompts (give as many
132 answers as you like)
133 --norename - don't rename file to myth convention
134
135 Example 1:
136 Assumption: The script is run on DB/backend machine.
137
138 $script_name --try_default
139
140 Example 2:
141 Assumption: The script is run on a backend other than the DB machine.
142
143 $script_name --dbhost=mydbserver
144";
145 exit(0);
146}
147
148GetOptions('verbose+'=>\$verbose,
149 'database=s'=>\$database,
150 'dbhost=s'=>\$dbhost,
151 'host=s'=>\$host,
152 'user=s'=>\$user,
153 'pass=s'=>\$pass,
154 'dir=s'=>\$dir,
155 'show_existing|se'=>\$show_existing,
156 'try_default|td'=>\$try_default,
157 'quick_run|qr'=>\$quick_run,
158 'test_mode|t|tm'=>\$test_mode,
159 'ext=s'=>\$ext,
160 'file=s'=>\$file,
161 'answer=s'=>\@answers, # =s{,} would be nice but isn't implemented widely
162 'norename'=>\$norename
163 );
164
165my $dbh = DBI->connect("dbi:mysql:database=$database:host=$dbhost",
166 "$user","$pass") or die "Cannot connect to database ($!)\n";
167
168my ($starttime, $endtime, $title, $subtitle, $channel, $description);
169my ($syear, $smonth, $sday, $shour, $sminute, $ssecond, $eyear, $emonth, $eday,
170 $ehour, $eminute, $esecond);
171
172my $q = "";
173my $sth;
174
175if (!$dir) {
176 my $dir_query = "select data from settings where value='RecordFilePrefix' and hostname=(?)";
177 $sth = $dbh->prepare($dir_query);
178 $sth->execute($host) or die "Could not execute ($dir_query)";
179 if (my @row = $sth->fetchrow_array) {
180 $dir = $row[0];
181 }
182}
183
184if (!$dir) {
185 print("Error: no directory found or specified\n");
186 exit 1;
187}
188
189# remove trailing slash
190$dir =~ s/\/$//;
191
192if ($show_existing) {
193 $q = "select title, subtitle, starttime, endtime, chanid from recorded order by starttime";
194 $sth = $dbh->prepare($q);
195 $sth->execute or die "Could not execute ($q)\n";
196
197 print "\nYour myth database ($database) is reporting the following programs as being recorded:\n\n";
198
199 while (my @row=$sth->fetchrow_array) {
200 $title = $row[0];
201 $subtitle = $row[1];
202 $starttime = $row[2];
203 $endtime = $row[3];
204 $channel = $row[4];
205
206## get the pieces of the time
207 if ($starttime =~ m/$db_date_regx/) {
208 ($syear, $smonth, $sday, $shour, $sminute, $ssecond) =
209 ($1, $2, $3, $4, $5, $6);
210 }
211
212 if ($endtime =~ m/$db_date_regx/) {
213 ($eyear, $emonth, $eday, $ehour, $eminute, $esecond) =
214 ($1, $2, $3, $4, $5, $6);
215 }
216
217## print "Channel $channel\t$smonth/$sday/$syear $shour:$sminute:$ssecond - $ehour:$eminute:$esecond - $title ($subtitle)\n";
218 print "Channel: $channel\n";
219 print "Start time: $smonth/$sday/$syear - $shour:$sminute:$ssecond\n";
220 print "End time: $emonth/$eday/$eyear - $ehour:$eminute:$esecond\n";
221 print "Title: $title\n";
222 print "Subtitle: $subtitle\n\n";
223 }
224}
225
226print "\nThese are the files stored in ($dir) and will be checked against\n";
227print "your database to see if the exist. If they do not, you will be prompted\n";
228print "for a title and subtitle of the entry, and a record will be created.\n\n";
229
230my @files = $file ? ($dir . "/" . $file) : glob("$dir/*.$ext");
231
232foreach my $show (@files) {
233 my $showBase = basename($show);
234
235 my $found_title = $dbh->selectrow_array("select title from recorded where hostname=(?) and basename=(?)",
236 undef, $host, $showBase);
237
238 if ($found_title) {
239 print("Found a match between file and database\n");
240 print(" File: '$show'\n");
241 print(" Title: '$found_title'\n");
242
243 # use this so the stuff below doesn't have to be indented
244 next;
245 }
246
247 print("Unknown file $show found.\n");
248 next unless GetAnswer("Do you want to import?", "y") eq "y";
249
250
251 # normal case: import file into the database
252
253 my ($channel, $syear, $smonth, $sday, $shour, $sminute, $ssecond,
254 $eyear, $emonth, $eday, $ehour, $eminute, $esecond);
255 my ($starttime, $duration, $endtime);
256 my ($mythfile);
257
258 # filename varies depending on when the recording was
259 # created. Gleam as much as possible from the name.
260
261 if ($showBase =~ m/$channel_regx\_/) {
262 $channel = $1;
263 } else {
264 $channel = "0000";
265 }
266
267 if ($showBase =~ m/$channel_regx\_$date_regx\./) {
268 ($syear, $smonth, $sday, $shour, $sminute, $ssecond) =
269 ($2, $3, $4, $5, $6, $7);
270 }
271
272 if ($showBase =~ m/$channel_regx\_$date_regx\_$date_regx/) {
273 ($eyear, $emonth, $eday, $ehour, $eminute, $esecond) =
274 ($8, $9, $10, $11, $12, $13);
275 }
276
277 my $guess_title = "Unknown";
278 my $guess_subtitle = "";
279 my $guess_description = "Recovered file " . $showBase;
280
281 # have enough to look for an past recording?
282 if ($ssecond) {
283 $starttime = "$syear$smonth$sday$shour$sminute$ssecond";
284
285 my $guess = "select title, subtitle, description from oldrecorded where chanid=(?) and starttime=(?)";
286 $sth = $dbh->prepare($guess);
287 $sth->execute($channel, $starttime)
288 or die "Could not execute ($guess)\n";
289
290 if (my @row = $sth->fetchrow_array) {
291 $guess_title = $row[0];
292 $guess_subtitle = $row[1];
293 $guess_description = $row[2];
294 }
295
296 print "Found an orphaned file, initializing database record\n";
297 print "Channel: $channel\n";
298 print "Start time: $smonth/$sday/$syear - $shour:$sminute:$ssecond\n";
299 print "End time: $emonth/$eday/$eyear - $ehour:$eminute:$esecond\n";
300 }
301
302 my $newtitle = $guess_title;
303 my $newsubtitle = $guess_subtitle;
304 my $newdescription = $guess_description;
305
306 if ($quick_run) {
307
308 print("QuickRun defaults:\n");
309 print(" title: '$newtitle'\n");
310 print(" subtitle: '$newsubtitle'\n");
311 print(" description: '$newdescription'\n");
312
313 } else {
314
315 $channel = GetAnswer("Enter channel", $channel);
316 $newtitle = GetAnswer("... title", $newtitle);
317 $newsubtitle = GetAnswer("... subtitle", $newsubtitle);
318 $newdescription = GetAnswer("Description", $newdescription);
319 $starttime = GetAnswer("... start time (YYYY-MM-DD HH:MM:SS)", $starttime);
320
321 if ($endtime) {
322 $duration = (str2time($endtime) - str2time($starttime)) / 60;
323 } else {
324 $duration = "60";
325 }
326 $duration = GetAnswer("... duration (in minutes)", $duration);
327 $endtime = time_format("yyyy-mm{on}-dd HH:mm{in}:ss", str2time($starttime) + $duration * 60);
328
329 }
330
331 if ($norename) {
332 $mythfile = $showBase;
333 } else {
334 my ($ext) = $showBase =~ /([^\.]*)$/;
335 my $time1 = $starttime;
336 $time1 =~ s/[ \-:]//g;
337 $mythfile = sprintf("%s_%s.%s", $channel, $time1, $ext);
338 }
339
340 my $sql = "insert into recorded (chanid, starttime, endtime, title, subtitle, description, hostname, basename, progstart, progend) values ((?), (?), (?), (?), (?), (?), (?), (?), (?), (?))";
341
342 if ($test_mode) {
343
344 $sql =~ s/\(\?\)/"%s"/g;
345 my $statement = sprintf($sql, $channel, $starttime, $endtime, $newtitle,
346 $newsubtitle, $newdescription, $host, $mythfile,
347 $starttime, $endtime);
348 print("Test mode: insert would have been been:\n");
349 print($statement, ";\n");
350
351 } else {
352
353 $sth = $dbh->prepare($sql);
354 $sth->execute($channel, $starttime, $endtime, $newtitle,
355 $newsubtitle, $newdescription, $host, $mythfile,
356 $starttime, $endtime)
357 or die "Could not execute ($sql)\n";
358
359 if ($mythfile ne $showBase) {
360 rename($show, $dir. "/" . $mythfile);
361 }
362 }
363
364
365 print("Building a seek table should improve FF/RW and JUMP functions when watching this video\n");
366
367 if (GetAnswer("Do you want to build a seek table for this file?", "y") eq "y") {
368 if (!$test_mode) {
369 exec("mythcommflag --file $mythfile --rebuild");
370 } else {
371 print("Test mode: exec would have done\n");
372 print(" Exec: 'mythcommflag --file $mythfile --rebuild'\n");
373 }
374 }
375
376} ## foreach loop
377
378# vim:sw=4 ts=4 syn=off: