1 package NonameTV
::Importer
;
11 use NonameTV qw
/CompareArrays/;
19 Abstract base-class for the NonameTV::Importer::* classes.
21 A package derived from NonameTV::Importer can be used to import
22 data from different datasources into the NonameTV programming
25 NonameTV::Importer::*-objects are instantiated from the nonametv.conf
26 configuration file. To instantiate an object, add an entry in the
27 'Importers'-hash. Each entry consists of a hash with configuration
28 parameters for the importer. The following keys are common to all
31 Type - The class-name for the importer, i.e. the instantiated object
32 will be of class NonameTV::Importer::$Type.
34 Channels - The channels that this importer shall import data for. The
35 value shall be another hash with xmltvids as keys and arrays as
36 values. The array shall contain the following data in this order:
38 display_name, grabber_info, sched_lang, empty_ok, def_pty,
41 The fields def_pty, def_cat, url, and chgroup are optional and can be
44 A sample entry for an importer can look like this:
47 Type => 'Aftonbladet_http',
49 UrlRoot => "http://www.aftonbladet.se/atv/pressrum/tabla",
51 "tv7.aftonbladet.se" =>
52 [ "Aftonbladet TV7", "", "sv", 0, "", "", "", "" ],
56 The MaxWeeks and UrlRoot parameters are implemented by the classes
57 deriving from Importer.
67 The constructor for the object. Called with a hashref as the first parameter.
68 This is a ref to the configuration for the object from the nonametv.conf-
69 file. The second parameter is a NonameTV::DataStore object.
74 my $class = ref( $_[0] ) || $_[0];
79 # Copy the parameters supplied in the constructor.
80 foreach my $key (keys(%{$_[1]})) {
81 $self->{$key} = ($_[1])->{$key};
84 $self->{datastore
} = $_[2];
91 Import is called from the nonametv-import executable. It takes a hashref as
92 the only parameter. The hashref
93 points to a hash with the command-line parameters decoded by Getopt::Long
94 using the $NonameTV::Importer::*::Options arrayref as format specification.
99 my( $self, $param ) = @_;
101 $self->ImportData( $param );
106 ImportData is called from Import. It takes a hashref as the only
107 parameter. The hashref points to a hash with the command-line
108 parameters decoded by Getopt::Long using the
109 $NonameTV::Importer::*::Options arrayref as format specification.
111 The ImportData method must be overridden in classes inheriting from
117 my( $self, $param ) = @_;
119 die "You must override ImportData in your own class";
124 my( $batch_id, $data ) = @_;
126 my $root = "/var/local/nonametv/override";
130 if( -f
( "$root/new/$batch_id" ) ) {
131 move
( "$root/new/$batch_id", "$root/data/$batch_id" );
135 if( -f
( "$root/data/$batch_id" ) ) {
136 # Check if the data on site has changed
137 my( $site_content, $site_code ) =
138 $self->FetchDataFromSite( $batch_id, $data );
140 print STDERR
"$batch_id New data available for override.\n"
143 $site_content = undef;
145 # Load data from file
148 open( my $fh, "$root/data/$batch_id" )
149 or die "Failed to read form $root/data/$batch_id: $@";
154 ( $content, $code ) = $self->FetchDataFromSite( $batch_id, $data );
155 if( -f
( "$root/delete/$batch_id" ) ) {
156 # Delete the old override and force update from site.
157 unlink( "$root/delete/$batch_id" );
162 return ($content, $code);
168 Import the content from a single file.
174 my( $contentname, $filename, $p ) = @_;
178 # Load data from file
181 open( my $fh, "$filename" )
182 or die "Failed to read from $filename: $@";
186 return $self->ImportContent( $contentname, \
$content, $p );
192 return if defined $self->{_ChannelsUpdated
};
194 if( not defined( $self->{Channels
} ) ) {
195 $self->LoadChannelsFromDb();
198 $self->SyncChannelsToDb();
201 $self->{_ChannelsUpdated
} = 1;
206 Return an arrayref with one entry per channnel configured for this
207 grabber. Each entry is a hash with information about the channel.
214 $self->UpdateChannels();
216 return $self->{_ChannelData
};
219 sub LoadChannelsFromDb
{
222 $self->{_ChannelData
} = $self->{datastore
}->FindGrabberChannels(
223 $self->{ConfigName
} );
227 my( $value, $default ) = @_;
229 return defined $value ?
$value : $default;
233 my( $conf, $db ) = @_;
235 return 0 if $conf->{display_name
} ne $db->{display_name
};
236 return 0 if $conf->{sched_lang
} ne $db->{sched_lang
};
237 return 0 if $conf->{empty_ok
} ne $db->{empty_ok
};
238 return 0 if $conf->{def_pty
} ne $db->{def_pty
};
239 return 0 if $conf->{def_cat
} ne $db->{def_cat
};
240 return 0 if defdef
($conf->{url
}, "") ne defdef
( $db->{url
}, "");
241 return 0 if defdef
($conf->{chgroup
}, "") ne defdef
($db->{chgroup
}, "");
243 return 0 if $conf->{grabber_info
} ne $db->{grabber_info
};
248 sub SyncChannelsToDb
{
251 # 1. Convert Channels to _ChannelData. Order by xmltvid.
252 # 2. Iterate through _ChannelData and FindGrabberChannels.
254 $self->{_ChannelData
} = [];
256 foreach my $xmltvid (sort keys %{$self->{Channels
}}) {
257 my $e = $self->{Channels
}->{$xmltvid};
260 display_name
=> $e->[0],
261 grabber_info
=> defdef
( $e->[1], "" ),
262 sched_lang
=> $e->[2],
263 empty_ok
=> defdef
( $e->[3], 0 ),
264 def_pty
=> defdef
( $e->[4], "" ),
265 def_cat
=> defdef
( $e->[5], "" ),
267 chgroup
=> defdef
( $e->[7], "" ),
270 push @
{$self->{_ChannelData
}}, $ce;
273 my $db = $self->{datastore
}->FindGrabberChannels( $self->{ConfigName
} );
274 my $conf = $self->{_ChannelData
};
276 CompareArrays
( $conf, $db, {
277 cmp => sub { $_[0]->{xmltvid
} cmp $_[1]->{xmltvid
} },
279 print STDERR
"Adding channel info for $_[0]->{xmltvid}\n";
280 $self->AddChannel( $_[0] );
283 print STDERR
"Deleting channel info for $_[0]->{xmltvid}\n";
284 $self->{datastore
}->ClearChannel( $_[0]->{id
} );
285 $self->{datastore
}->sa->Delete( "channels", { id
=> $_[0]->{id
} } );
288 # The channel id only exists in the database.
289 $_[0]->{id
} = $_[1]->{id
};
291 if( not isequal
( $_[0], $_[1] ) ) {
292 print STDERR
"Updating channel info for $_[0]->{xmltvid}\n";
293 $self->UpdateChannel( $_[0] );
296 max
=> { xmltvid
=> "zzzzzzz" },
305 xmltvid
=> $cc->{xmltvid
},
306 display_name
=> $cc->{display_name
},
307 grabber
=> $self->{ConfigName
},
308 grabber_info
=> $cc->{grabber_info
},
309 sched_lang
=> $cc->{sched_lang
},
310 empty_ok
=> $cc->{empty_ok
},
311 def_pty
=> $cc->{def_pty
},
312 def_cat
=> $cc->{def_cat
},
314 chgroup
=> $cc->{chgroup
},
317 $self->{datastore
}->sa->Update( 'channels', {id
=> $cc->{id
}}, $data );
325 xmltvid
=> $cc->{xmltvid
},
326 display_name
=> $cc->{display_name
},
327 grabber
=> $self->{ConfigName
},
328 grabber_info
=> $cc->{grabber_info
},
329 sched_lang
=> $cc->{sched_lang
},
330 empty_ok
=> $cc->{empty_ok
},
331 def_pty
=> $cc->{def_pty
},
332 def_cat
=> $cc->{def_cat
},
334 chgroup
=> $cc->{chgroup
},
338 $self->{datastore
}->sa->Add( 'channels', $data );
339 my $id = $self->{datastore
}->sa->Lookup( 'channels',
340 { xmltvid
=> $cc->{xmltvid
},
341 grabber
=> $self->{ConfigName
} },
347 =head1 CLASS VARIABLES
349 =item $OptionSpec, $OptionDefaults
351 Format specifications and default values for Getopt::Long.
353 our $OptionSpec = [ qw/force-update/ ];
354 our %OptionDefaults = (
361 Copyright (C) 2004-2008 Mattias Holmlund.