summaryrefslogtreecommitdiffstats
path: root/scripts/leodict.pl
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/leodict.pl')
-rw-r--r--scripts/leodict.pl435
1 files changed, 435 insertions, 0 deletions
diff --git a/scripts/leodict.pl b/scripts/leodict.pl
new file mode 100644
index 0000000..8b1fd8a
--- /dev/null
+++ b/scripts/leodict.pl
@@ -0,0 +1,435 @@
+#!/usr/bin/perl
+#
+# by Stefan "Tommie" Tomanek
+use strict;
+
+use vars qw($VERSION %IRSSI);
+$VERSION = '20220104';
+%IRSSI = (
+ authors => 'Stefan \'tommie\' Tomanek, bw1',
+ contact => 'bw1@aol.at',
+ name => 'leodict',
+ description => 'translates via dict.leo.org',
+ license => 'GPLv2',
+ url => 'http://irssi.org/scripts/',
+ modules => 'Mojo::UserAgent Encode JSON::PP Mojo::DOM Getopt::Long POSIX',
+ commands => "leodict",
+ selfcheckcmd=> 'leodict -chec',
+);
+use vars qw($forked);
+use utf8;
+use Encode;
+use Irssi 20020324;
+use JSON::PP;
+use Mojo::DOM;
+use Getopt::Long qw(GetOptionsFromString);
+use Mojo::UserAgent;
+use POSIX;
+
+# global
+my %gresult;
+my $lang;
+my $dlang= 'englisch-deutsch/';
+my $help;
+my $browse;
+my $paste;
+my $word;
+my $dir;
+my $ddir= '';
+my $check;
+
+# for fork
+my $ftext;
+my %fresult;
+
+sub draw_box ($$$$) {
+ my ($title, $text, $footer, $colour) = @_;
+ my $box = '';
+ $box .= '%R,--[%n%9%U'.$title.'%U%9%R]%n'."\n";
+ foreach (split(/\n/, $text)) {
+ $box .= '%R|%n '.$_."\n";
+ }
+ $box .= '%R`--<%n'.$footer.'%R>->%n';
+ $box =~ s/%.//g unless $colour;
+ return $box;
+}
+
+sub show_help() {
+ my $help = "LeoDict $VERSION
+SYNOPSIS
+ /leodict [OPTION] <word> [OPTION]
+ searches dict.leo.org for appropiate translations
+DESCRIPTION
+ -p
+ paste the translations to the current channel or query
+ The number of translations is limited by the setting
+ 'leodict_paste_max_translations'
+ -b
+ open dict.leo.org in your web browser (uses openurl.pl)
+
+ -from from German
+ -to to German
+ -both from and to German
+ -en English
+ -fr French
+ -es Spanish
+ -it Italian
+ -zh Chinese
+ -ru Russian
+ -pt Portuguese
+ -pl Polish
+ -chec selfcheck
+SETTINGS
+ 'leodict_default_options'
+ example: -it -from
+ 'leodict_paste_max_translations'
+ 'leodict_paste_beautify'
+ 'leodict_http_proxy_address'
+ example: 127.0.0.1
+ defaults to none, meaning no proxy will be used for requests.
+ despite the name, does not have to be http proxy.
+ 'leodict_http_proxy_port'
+ example: 9050
+ defaults to 0, but must be changed if proxy address is not none.
+ 'leodict_http_proxy_type'
+ supported: socks, https, http
+";
+ my $text='';
+ foreach (split(/\n/, $help)) {
+ $_ =~ s/^\/(.*)$/%9\/$1%9/;
+ $text .= $_."\n";
+ }
+ print CLIENTCRAP draw_box($IRSSI{name}, $text, "help", 1);
+}
+
+sub parser {
+ my %ignore=(
+ 'Suchwort' => 1,
+ 'Beispiele' => 1,
+ 'Orthographisch ähnliche Wörter' => 1,
+ 'Aus dem Umfeld der Suche' => 1,
+ 'Forumsdiskussionen, die den Suchbegriff enthalten' =>1,
+ #'Substantive'
+ #'Verben'
+ #'Adjektive / Adverbien'
+ #'Phrasen'
+ );
+ %fresult=();
+
+ # tables
+ unless (defined $ftext) {
+ %fresult=('Error'=>[['no data']]);
+ return;
+ }
+ my $dom = Mojo::DOM->new($ftext);
+ foreach my $tbl ( $dom->find('table')->each ) {
+
+ # head
+ my $thead =$tbl->at('thead');
+ next unless (defined $thead );
+ my $headname = $thead->descendant_nodes->last->to_string;
+ next if (exists $ignore{ $headname } );
+
+
+ # rows
+ my @rows=();
+ foreach my $row ( $tbl->find('tr')->each) {
+
+ # colums
+ my @columns=();
+ foreach my $col ( $row->find('td')->each ) {
+ my $co = $col->to_string;
+ $co =~ s/<.*?>//sg;
+ if ( length($co) >2 ) {
+ push(@columns ,$co);
+ }
+ }
+ if ( scalar(@columns) > 0 ) {
+ push(@rows, [@columns]);
+ }
+ }
+ $fresult{ $headname } = [ @rows ];
+ }
+}
+
+sub get_page ($) {
+ my ($url) = @_;
+ #return get('http://dict.leo.org/?search='.$word.'&relink=off');
+ my $ua = Mojo::UserAgent->new;
+
+ # Add proxy to Mojo if needed
+ my $proxy_addr = Irssi::settings_get_str('leodict_http_proxy_address');
+ my $proxy_port = Irssi::settings_get_int('leodict_http_proxy_port');
+ my $proxy_type = Irssi::settings_get_str('leodict_http_proxy_type');
+ if ($proxy_addr ne 'none') {
+ # Socks proxy
+ if ($proxy_type eq 'socks' || $proxy_type eq 'https') {
+ $ua->proxy->http("$proxy_type://$proxy_addr:$proxy_port")->https("$proxy_type://$proxy_addr:$proxy_port");
+ }
+ # Must be http proxy
+ else {
+ $ua->proxy->http("$proxy_type://$proxy_addr:$proxy_port");
+ }
+ }
+
+ my $res;
+ eval {
+ $res=$ua->get($url)->result;
+ };
+ if (defined $res && $res->is_success) {
+ $ftext = $res->body;
+ utf8::decode($ftext);
+ } else {
+ $ftext=undef;
+ }
+}
+
+sub call_openurl ($) {
+ my ($url) = @_;
+ no strict "refs";
+ # check for a loaded openurl
+ if (defined &{ "Irssi::Script::openurl::launch_url" } ) {
+ &{ "Irssi::Script::openurl::launch_url" }($url);
+ } else {
+ print CLIENTCRAP "%R>>%n Please install openurl.pl";
+ }
+}
+
+sub translate ($$$) {
+ my ($url, $target, $server) = @_;
+ my ($rh, $wh);
+ pipe($rh, $wh);
+ if ($forked) {
+ print CLIENTCRAP "%R>>%n Please wait until your earlier request has been finished.";
+ return;
+ }
+
+ # Validate proxy if needed
+ my $proxy_addr = Irssi::settings_get_str('leodict_http_proxy_address');
+ my $proxy_port = Irssi::settings_get_int('leodict_http_proxy_port');
+ my $proxy_type = Irssi::settings_get_str('leodict_http_proxy_type');
+ if ($proxy_addr ne 'none') {
+ if ($proxy_type ne 'socks' && $proxy_type ne 'https' && $proxy_type ne 'http') {
+ print CLIENTCRAP "%R>>%n Invalid proxy type: $proxy_type.";
+ return;
+ }
+ if ($proxy_port eq 0) {
+ print CLIENTCRAP "%R>>%n Please specify a proxy port.";
+ return;
+ }
+ }
+
+ my $pid = fork();
+ $forked = 1;
+ if ($pid > 0) {
+ print CLIENTCRAP "%R>>%n Please wait..." unless $target;
+ close $wh;
+ Irssi::pidwait_add($pid);
+ my $pipetag;
+ my @args = ($rh, \$pipetag, $target, $server);
+ $pipetag = Irssi::input_add(fileno($rh), INPUT_READ, \&pipe_input, \@args);
+ } else {
+ get_page($url);
+ parser();
+ print($wh encode_json(\%fresult));
+ close($wh);
+ POSIX::_exit(1);
+ }
+}
+
+sub one_site {
+ my ($site, $cat) = @_;
+ my @res;
+ foreach my $r ( @{$gresult{$cat}} ) {
+ push @res,$r->[$site];
+ }
+ return [@res];
+}
+
+sub pipe_input ($) {
+ my ($rh, $pipetag, $target, $tag) = @{$_[0]};
+ $forked = 0;
+ local $\;
+ my $res=<$rh>;
+ close $rh;
+ return if (length($res) <5);
+ %gresult = %{decode_json( $res )};
+ Irssi::input_remove($$pipetag);
+
+ if ($target eq '') {
+ show_translations(\%gresult, $word);
+ } else {
+ my $server = Irssi::server_find_tag($tag);
+ my $witem = $server->window_item_find($target);
+ paste_translations(\%gresult, $word, $witem) if $witem;
+ }
+}
+
+sub show_translations($$) {
+ my %trans = %{$_[0]};
+ my $word = $_[1];
+ self_check(\%trans) if ( defined $check );
+ if (%trans) {
+ my $text;
+ foreach my $k (keys %trans) {
+ $text .= "== $k ==\n";
+ foreach (@{ $trans{$k} }) {
+ $text .= "%U".$_->[0]."%U \n";
+ $text .= " `-> ".$_->[1]."\n";
+ }
+ }
+ my $term_charset= Irssi::settings_get_str('term_charset');
+ if ('UTF-8' ne $term_charset) {
+ $text= encode($term_charset, $text);
+ }
+ print CLIENTCRAP draw_box('LeoDict', $text, $word, 1);
+ } else {
+ print CLIENTCRAP "%R>>>%n No translations found (".$word.").";
+ }
+}
+
+sub paste_translations ($$) {
+ my ($trans, $word, $target) = @_;
+ return unless ($target->{type} eq "CHANNEL" || $target->{type} eq "QUERY");
+ if (%{ $trans }) {
+ my $text;
+ my $beauty = Irssi::settings_get_bool('leodict_paste_beautify');
+ my $max = Irssi::settings_get_int('leodict_paste_max_translations');
+ foreach my $k (keys %{ $trans }) {
+ $text .= "== $k ==\n";
+ my $i = 0;
+ foreach (@{ $trans->{$k}}) {
+ if ($i < $max || $max == 0) {
+ if ($beauty) {
+ $text .= $_->[0]." \n";
+ $text .= " `-> ".$_->[1]."\n";
+ } else {
+ $text .= $_->[0].' => '.$_->[1]."\n";
+ }
+ $i++;
+ } else {
+ $text .= '...'."\n";
+ last;
+ }
+ }
+ }
+ my $msg = $text;
+ $msg = draw_box('LeoDict', $text, $word, 0) if $beauty;
+ $target->command('MSG '.$target->{name}. ' '.$_) foreach (split(/\n/, $msg));
+ }
+}
+
+#https://dict.leo.org/englisch-deutsch/word
+#https://dict.leo.org/franz%C3%B6sisch-deutsch/word
+#https://dict.leo.org/spanisch-deutsch/word
+#https://dict.leo.org/italienisch-deutsch/word
+#https://dict.leo.org/chinesisch-deutsch/word
+#https://dict.leo.org/russisch-deutsch/word
+#https://dict.leo.org/portugiesisch-deutsch/word
+#https://dict.leo.org/polnisch-deutsch/word
+#https://dict.leo.org/polnisch-deutsch/word?side=left pl -> de
+#https://dict.leo.org/polnisch-deutsch/word?side=right pl <- de
+my %options = (
+ "from" => sub {$dir= '?side=right';},
+ "to" => sub {$dir= '?side=left';},
+ "both" => sub {$dir= '';},
+ "en" => sub {$lang = 'englisch-deutsch/'; },
+ "fr" => sub {$lang = 'franz%C3%B6sisch-deutsch/'; },
+ "es" => sub {$lang = 'spanisch-deutsch/'; },
+ "it" => sub {$lang = 'italienisch-deutsch/'; },
+ "zh" => sub {$lang = 'chinesisch-deutsch/'; },
+ "ru" => sub {$lang = 'russisch-deutsch/'; },
+ "pt" => sub {$lang = 'portugiesisch-deutsch/'; },
+ "pl" => sub {$lang = 'polnisch-deutsch/'; },
+ "h" => \$help,
+ "b" => \$browse,
+ "p" => \$paste,
+ "chec" => \$check,
+);
+
+sub cmd_leodict ($$$) {
+ my ($args, $server, $witem) = @_;
+ utf8::decode($args);
+ my $burl = "https://dict.leo.org/";
+ my $url;
+
+ $lang= $dlang;
+ $dir= $ddir;
+ undef $help;
+ undef $browse;
+ undef $paste;
+ undef $check;
+
+ my ($ret, $arg) = GetOptionsFromString($args, %options);
+
+ $word= $arg->[0];
+ $url=$burl.$lang.$word.$dir;
+
+ if (defined $help) {
+ show_help();
+ return();
+ }
+ if (defined $browse) {
+ call_openurl($url);
+ return();
+ }
+
+ if (defined $paste) {
+ #paste_translations($_, $witem) if $witem;
+ return unless defined $witem;
+ return unless defined $server;
+ translate($url, $witem->{name}, $witem->{server}->{tag});
+ } elsif (defined $check) {
+ $url=$burl.'englisch-deutsch/'.'tree'.$dir;
+ translate($url,'', '');
+ } else {
+ #show_translations($_);
+ translate($url,'', '');
+ }
+}
+
+sub self_check {
+ my ( $tr ) =@_;
+ my $s='ok';
+ Irssi::print("selfcheck: categorys ".scalar( keys %$tr ));
+ my $count=0;
+ foreach my $n ( keys %$tr ) {
+ Irssi::print("selfcheck: category $n ".scalar( @{$tr->{$n}} ));
+ $count +=scalar( @{$tr->{$n}} );
+ }
+ Irssi::print("selfcheck: results $count");
+ if ( scalar( keys %$tr ) <4 ) {
+ $s='Error: categorys ('.scalar( keys %$tr ).')';
+ } elsif ( $count < 35 ) {
+ $s="Error: results ($count)";
+ }
+ Irssi::print("selfcheck: $s");
+ my $schs = exists $Irssi::Script::{'selfcheckhelperscript::'};
+ Irssi::command("selfcheckhelperscript $s") if ( $schs );
+}
+
+sub sig_setup_changed {
+ my $args =Irssi::settings_get_str('leodict_default_options');
+ my ($ret, $arg) = GetOptionsFromString($args, %options);
+ $dlang=$lang;
+ $ddir=$dir;
+}
+
+Irssi::signal_add('setup changed', 'sig_setup_changed');
+
+Irssi::command_bind('leodict', 'cmd_leodict');
+
+Irssi::command_set_options('leodict', join(" ",keys %options));
+
+Irssi::settings_add_str($IRSSI{'name'}, 'leodict_default_options', '-en -both');
+Irssi::settings_add_int($IRSSI{'name'}, 'leodict_paste_max_translations', 2);
+Irssi::settings_add_bool($IRSSI{'name'}, 'leodict_paste_beautify', 1);
+Irssi::settings_add_str($IRSSI{'name'}, 'leodict_http_proxy_address', 'none');
+Irssi::settings_add_int($IRSSI{'name'}, 'leodict_http_proxy_port', 0);
+Irssi::settings_add_str($IRSSI{'name'}, 'leodict_http_proxy_type', 'none');
+
+sig_setup_changed();
+
+print CLIENTCRAP "%B>>%n ".$IRSSI{name}." ".$VERSION." loaded: /leodict -h for help";
+
+# vim:set ts=8 sw=4: