From 659a2ab6122270c22d3bc3dfc18b7e5cdc6238b2 Mon Sep 17 00:00:00 2001 From: Frey Date: Sat, 5 Jul 2014 17:57:51 +0200 Subject: Scripts: add vidinfo.pl. --- scripts/vidinfo.pl | 363 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 363 insertions(+) create mode 100644 scripts/vidinfo.pl (limited to 'scripts') diff --git a/scripts/vidinfo.pl b/scripts/vidinfo.pl new file mode 100644 index 0000000..1585174 --- /dev/null +++ b/scripts/vidinfo.pl @@ -0,0 +1,363 @@ +# Copyright 2009 -- 2011, Olof Johansson +# Improved by Cyprien Debu , 2014 +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. This file is offered as-is, +# without any warranty. + +use v5.10.1; +use strict; +use HTML::Entities; +use Irssi; +use JSON::Parse qw(json_to_perl); +use LWP::UserAgent; +use Regexp::Common qw(URI); +use URI; +use URI::QueryParam; +use XML::Simple; + +our $VERSION = '1.00'; +our %IRSSI = ( + authors => 'Olof "zibri" Johansson, Cyprien Debu', + contact => 'olof@ethup.se, frey@notk.org', + name => 'vidinfo', + description => 'Prints some info of a linked video automatically', + license => 'GPL', + changed => '2014-07' +); + +my $sn = $IRSSI{name}; + +my %domains = ( + 'dailymotion.com' => { + idextr => \&idextr_dailymotion_com, + site => 'dm', + }, + 'vimeo.com' => { + idextr => \&idextr_vimeo_com, + site => 'vm', + }, + 'youtu.be' => { + idextr => \&idextr_youtu_be, + site => 'yt', + }, + 'youtube.com' => { + idextr => \&idextr_youtube_com, + site => 'yt', + }, +); + +my $domains_rx = '(' . join('|', keys %domains) . ')'; +my %rules = {}; +my $default_rule = '='; + +Irssi::settings_add_bool($sn, $sn.'_print_own', 0); +Irssi::settings_add_str ($sn, $sn.'_print_rules', $default_rule); +Irssi::settings_add_str ($sn, $sn.'_site_color', '7'); + +sub print_help { + print( < 1); + $default_rule = $_ if (length $_ == 1); + } +} + +sub process { + my ($srv, $tgt, $rule, $vid) = @_; + + my $info = get_title($vid); + + if (exists $info->{error}) { + print_error($srv, $tgt, $info->{error}); + } else { + print_title($srv, $tgt, $rule, $info->{site}, $info->{title}, $info->{duration}); + } +} + +sub canon_domain { + my $_ = shift; + s/^www\.//; + return $_; +} + +sub idextr_dailymotion_com { + my $u = URI->new(shift); + my $_ = ($u->path_segments())[2]; + s/_.+//; + return $_; +} + +sub idextr_vimeo_com { + my $u = URI->new(shift); + return ($u->path_segments())[1]; +} + +sub idextr_youtu_be { + my $u = URI->new(shift); + return ($u->path_segments())[1]; +} + +sub idextr_youtube_com { + my $u = URI->new(shift); + return $u->query_param('v') if $u->path eq '/watch'; +} + +sub vid_from_uri { + my $uri = URI->new(shift); + my $domain = canon_domain($uri->host); + + my $info = $domains{$domain}; + + return { + id => $domains{$domain}->{idextr}->($uri), + site => $domains{$domain}->{site}, + } if ref $domains{$domain}->{idextr} eq 'CODE'; +} + +sub get_vids { + my $msg = shift; + my $re_uri = qr($RE{URI}{HTTP}{-scheme=>'https?'}); + my @vids; + + foreach ($msg =~ /$re_uri/g) { + my $vid = vid_from_uri($_); + push @vids, $vid if $vid; + } + + return @vids; +} + +sub do_get { + my $ua = LWP::UserAgent->new(); + + $ua->agent("$sn/$VERSION (irssi)"); + $ua->timeout(3); + $ua->env_proxy; + + return $ua->get(shift); +} + +sub dm_get_title { + my $response = shift; + + my $json = json_to_perl($response->decoded_content); + + my $title = $json->{title}; + my $s = $json->{duration}; + + my $m = $s / 60; + my $d = sprintf "%d:%02d", $m, $s % 60; + + return ($title, $d); +} + +sub vm_get_title { + my $response = shift; + + my $json = (json_to_perl($response->decoded_content))->[0]; + + my $title = $json->{title}; + my $s = $json->{duration}; + + my $m = $s / 60; + my $d = sprintf "%d:%02d", $m, $s % 60; + + return ($title, $d); +} + +sub yt_get_title { + my $response = shift; + + my $content = $response->decoded_content; + + my $xml = XMLin($content)->{'media:group'}; + my $title = $xml->{'media:title'}->{content}; + my $s = $xml->{'yt:duration'}->{seconds}; + + my $m = $s / 60; + my $d = sprintf "%d:%02d", $m, $s % 60; + + return ($title, $d); +} + +sub get_title { + my $vid = shift; + my $site = $vid->{site}; + + my %sites = ( + dm => { + sitename => 'DailyMotion', + get_title => \&dm_get_title, + url => "https://api.dailymotion.com/video/$vid->{id}?fields=title,duration", + }, + vm => { + sitename => 'Vimeo', + get_title => \&vm_get_title, + url => "http://vimeo.com/api/v2/video/$vid->{id}.json", + }, + yt => { + sitename => 'YouTube', + get_title => \&yt_get_title, + url => "http://gdata.youtube.com/feeds/api/videos/$vid->{id}", + }, + ); + + my $response = do_get($sites{$site}->{url}); + + if ($response->is_success) { + my ($title, $duration) = $sites{$site}->{get_title}->($response); + + if ($title) { + return { + title => $title, + duration => $duration, + site => $sites{$site}->{sitename}, + }; + } + + return {error => 'could not find title'}; + } + + return {error => $response->message}; +} + +sub print_error { + my ($srv, $tgt, $msg) = @_; + $srv->window_item_find($tgt)->printformat( + MSGLEVEL_CLIENTCRAP, $sn.'_error', $msg + ); +} + +sub print_title { + my ($srv, $tgt, $rule, $site, $title, $time) = @_; + + $title = decode_entities($title); + $time = decode_entities($time); + my $c = Irssi::settings_get_str($sn.'_site_color'); + my $line = ($c ne '' ? "\x03$c$site:\x03" : "$site:") . " $title ($time)"; + + for ($rule) { + when (/=/) { + my $witem = Irssi::window_item_find $tgt; + $witem->print($line); + } + when (/\+/) { + # Remove colors in channels with mode 'c' + my $chan = $srv->channel_find($tgt); + if (defined $chan and $chan->{mode} =~ /c/ and $c ne '') { + $line = "\x02$site:\x02 $title ($time)"; + } + $srv->command("msg $tgt $line"); + } + default { } + } +} + +load_rules(); + +Irssi::theme_register([ + $sn.'_error', '%rError fetching video title:%n $0', +]); + +Irssi::signal_add("message public", \&on_msg_public); +Irssi::signal_add("message private", \&on_msg_private); +Irssi::signal_add("message own_public", \&on_msg_own_public ); +Irssi::signal_add("message own_private", \&on_msg_own_private ); +Irssi::signal_add("setup changed", \&load_rules); + +# Help command handler +Irssi::command_bind 'help', sub { + $_[0] =~ s/\s+$//g; + return unless $_[0] eq $sn; + print_help; + Irssi::signal_stop; +}; + +# Subcommands handler +Irssi::command_bind $sn, sub { + my ($data, $server, $item) = @_; + $data =~ s/\s+$//g; + Irssi::command_runsub $sn, $data, $server, $item; +}; + +# Subcommands +Irssi::command_bind "$sn help", \&print_help; + -- cgit v1.2.3