use XML::Simple;
use Data::Dumper;
use File::Spec;
+use File::Temp qw(tempfile);
use BettIrssi 101 qw(_bcb _bcs);
use LWP::UserAgent;
+use JSON -support_by_pp;
my @grabbers;
my @getters;
my $getter;
my $conf;
-my $conffile = File::Spec->catfile(Irssi::get_irssi_dir(), 'videosite.xml');
+my $xmlconffile = File::Spec->catfile(Irssi::get_irssi_dir(), 'videosite.xml');
+my $conffile = File::Spec->catfile(Irssi::get_irssi_dir(), 'videosite.json');
my $scriptdir = File::Spec->catfile(Irssi::get_irssi_dir(), 'scripts');
my $plugindir = File::Spec->catfile($scriptdir, 'videosite');
my @outputstack = (undef);
my $PARAMS = {
'getter' => '',
- 'mode' => 'download'
+ 'mode' => 'download',
+ 'connectorlist' => ['direct'],
+ 'connectors' => {},
};
cmd_mode(@_);
},
+ 'connector' => sub {
+ cmd_connector(@_);
+ },
+
'debug' => sub {
$debug = 1;
foreach (@grabbers, @getters) {
'2\.ly/[[:alnum:]]+',
't\.co/[[:alnum:]]+',
'shar\.es/[[:alnum:]]+',
+ 'goo\.gl/[[:alnum:]]+',
);
- my $ua = LWP::UserAgent->new(agent => 'Mozilla', max_redirect => 0);
+ my $ua = LWP::UserAgent->new(agent => 'Mozilla', max_redirect => 0, timeout => 5);
my $i = 10;
OUTER: while (($os ne $s) and ($i > 0)) {
return $s;
}
+sub connectorlist {
+ my @c;
+
+ foreach (@{$conf->{'videosite'}->{'connectorlist'}}) {
+ push(@c, $conf->{'videosite'}->{'connectors'}->{$_});
+ }
+
+ return @c;
+}
+
sub check_for_link {
my $event = shift;
sub cmd_save {
eval {
- open(CONF, '>'.$conffile) or die 'Could not open config file';
- print CONF XML::Simple::XMLout($conf, KeepRoot => 1, KeyAttr => {'config' => 'module', 'option' => 'key'});
- close(CONF);
+ my ($tempfile, $tempfn) = tempfile("videosite.json.XXXXXX", dir => Irssi::get_irssi_dir());
+ print $tempfile JSON->new->pretty->utf8->encode($conf);
+ close($tempfile);
+ rename($tempfn, $conffile);
};
if ($@) {
write_irssi('Could not save config to %s: %s', ($conffile, $@));
disable [modulename]: disable the usage of this module (grabbers only)
reload: reload all modules (this is somewhat experimental)
mode [modename]: display or set the operation mode (download/display)
+ connector [subcommand]: manage connectors (proxies)
debug: enable debugging messages
nodebug: disable debugging messages
EOT
}
}
+sub cmd_connector {
+ my $subcmd = shift;
+ my $connconf = $conf->{'videosite'}->{'connectors'};
+
+ unless(defined($subcmd)) {
+ $subcmd = "help";
+ }
+
+ $subcmd = lc($subcmd);
+
+ if ($subcmd eq 'list') {
+ write_irssi("Defined connectors");
+ foreach (keys(%{$connconf})) {
+ write_irssi($_);
+ my $schemas = $connconf->{$_}->{'schemas'};
+ if (scalar(keys(%{$schemas})) == 0) {
+ write_irssi(" No schemas defined");
+ } else {
+ foreach (keys(%{$schemas})) {
+ write_irssi(' %s: %s', $_, $schemas->{$_});
+ }
+ }
+ }
+
+ write_irssi();
+ write_irssi("Selected connectors: %s", join(", ", @{$conf->{'videosite'}->{'connectorlist'}}));
+ } elsif ($subcmd eq 'add') {
+ my ($name) = @_;
+
+ unless(defined($name)) {
+ write_irssi("No name given");
+ return;
+ }
+
+ $name = lc($name);
+
+ if (exists($connconf->{$_})) {
+ write_irssi("Connector already exists");
+ return;
+ }
+
+ $connconf->{$name} = {'name' => $name, 'schemas' => {}};
+ } elsif ($subcmd eq 'del') {
+ my ($name) = @_;
+
+ unless(defined($name)) {
+ write_irssi("No name given");
+ return;
+ }
+
+ $name = lc($name);
+
+ unless (exists($connconf->{$name})) {
+ write_irssi("Connector does not exist");
+ return;
+ }
+
+ if (exists($connconf->{$name}->{'_immutable'})) {
+ write_irssi("Connector cannot be removed");
+ return;
+ }
+
+ delete($connconf->{$name});
+
+ # Remove from list of active connectors
+ $conf->{'videosite'}->{'connectorlist'} =
+ [ grep { $_ ne $name } @{$conf->{'videosite'}->{'connectorlist'}} ];
+
+ if (scalar(@{$conf->{'videosite'}->{'connectorlist'}}) == 0) {
+ write_irssi("List of selected connectors is empty, resetting to direct");
+ $conf->{'videosite'}->{'connectorlist'} = [ 'direct' ];
+ }
+ } elsif ($subcmd eq 'addschema') {
+ my ($conn, $schema, $proxy) = @_;
+
+ unless(defined($conn)) {
+ write_irssi("No connector name given");
+ return;
+ }
+
+ $conn = lc($conn);
+
+ if (exists($connconf->{$conn}->{'_immutable'})) {
+ write_irssi("Connector cannot be modified");
+ return;
+ }
+
+ unless(defined($schema)) {
+ write_irssi("No schema given");
+ return;
+ }
+
+ $schema = lc($schema);
+
+ unless(defined($proxy)) {
+ write_irssi("No proxy given");
+ return;
+ }
+
+ unless(exists($connconf->{$conn})) {
+ write_irssi("Connector does not exist");
+ return;
+ }
+
+ $connconf->{$conn}->{'schemas'}->{$schema} = $proxy;
+ } elsif ($subcmd eq 'delschema') {
+ my ($conn, $schema) = @_;
+
+ unless(defined($conn)) {
+ write_irssi("No connector name given");
+ return;
+ }
+
+ $conn = lc($conn);
+
+ if (exists($connconf->{$conn}->{'_immutable'})) {
+ write_irssi("Connector cannot be modified");
+ return;
+ }
+
+ unless(defined($schema)) {
+ write_irssi("No schema given");
+ return;
+ }
+
+ $schema = lc($schema);
+
+ unless(exists($connconf->{$conn})) {
+ write_irssi("Connector does not exist");
+ return;
+ }
+
+ delete($connconf->{$conn}->{'schemas'}->{$schema});
+ } elsif ($subcmd eq 'select') {
+ my @connlist = map { lc } @_;
+
+ if (scalar(@connlist) == 0) {
+ write_irssi("No connectors given");
+ return;
+ }
+
+ foreach (@connlist) {
+ unless(exists($connconf->{$_})) {
+ write_irssi("Connector %s does not exist", $_);
+ return;
+ }
+ }
+
+ $conf->{'videosite'}->{'connectorlist'} = [ @connlist ];
+ } else {
+ write_irssi("connector [list|add|del|addschema|delschema|help] <options>");
+ write_irssi(" help: Show this help");
+ write_irssi(" list: List the defined connectors");
+ write_irssi(" add <name>: Add a connector with name <name>");
+ write_irssi(" del <name>: Delete the connector with name <name>");
+ write_irssi(" addschema <name> <schema> <proxy>: Add proxy to connector for the given schema");
+ write_irssi(" delschema <name> <schema>: Remove the schema from the connector");
+ write_irssi(" select <name> [<name>...]: Select the connectors to use");
+ }
+}
+
+
+
# save on unload
sub sig_command_script_unload {
if ($type eq $g->{'TYPE'}) {
push(@g, $g);
$g->setio(\&write_irssi);
+ $g->setconn(\&connectorlist);
} else {
write_irssi('%s has wrong type (got %s, expected %s)', $p, $g->{'TYPE'}, $type);
delete($INC{$p});
my $bindings = shift;
my $p;
- unless(-r $conffile && defined($conf = XML::Simple::XMLin($conffile, ForceArray => ['config', 'option'], KeepRoot => 1, KeyAttr => {'config' => 'module', 'option' => 'key'}))) {
+ if (-r $conffile) {
+ write_debug("Attempting JSON config load from %s", $conffile);
+ eval {
+ local $/;
+ open(CONF, '<', $conffile);
+ $conf = JSON->new->utf8->decode(<CONF>);
+ close(CONF);
+ };
+ } elsif (-r $xmlconffile) {
+ write_debug("Attempting XML config load from %s", $xmlconffile);
+ $conf = XML::Simple::XMLin($xmlconffile, ForceArray => ['config', 'option', 'connectorlist'], KeepRoot => 1, KeyAttr => {'connector' => '+name', 'config' => 'module', 'option' => 'key'});
+ }
+
+ unless(defined($conf)) {
# No config, start with an empty one
write_debug('No config found, using defaults');
$conf = { 'videosite' => { }};
}
+
foreach (keys(%{$PARAMS})) {
unless (exists($conf->{'videosite'}->{$_})) {
$conf->{'videosite'}->{$_} = $PARAMS->{$_};
}
}
+ # Make sure there is a connector called 'direct', which defines no
+ # proxies
+ unless (exists($conf->{'videosite'}->{'connectors'}->{'direct'})) {
+ $conf->{'videosite'}->{'connectors'}->{'direct'} = {
+ 'name' => 'direct',
+ '_immutable' => '1',
+ 'schemas' => {},
+ };
+ }
+
_load_modules($plugindir);
unless (defined(@grabbers) && defined(@getters)) {