root/xchestival/xchat_speak.pl

Revision 1064, 14.7 kB (checked in by alpt, 3 years ago)

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/usr/bin/perl
2 #
3 # Un interfaccia a festival per X-Chat, ottimizzata per l'italiano.
4 #
5 # Questo codice deriva da xchat_speak.pl:
6 # http://www.nogas.org/xchat_speak/
7 #
8 # Il nuovo codice e' stato scritto da AlpT (@freaknet.org)
9 #
10 # http://www.freaknet.org/alpt/src/xchestival/
11
12 ########### CONFIGURE THIS BIT!
13 # Adjust this so it reflects the location of your festival executable
14 $festival='/usr/bin/festival --pipe';
15
16 $home=`echo ~`;   # la tua home
17 $home =~ s/\n//;  # toglia la newline finale
18 # Il file usato da xchestival per le sostituzioni
19 $xchestival_sub = "$home/.xchat2/xchestival.sub";
20 $xchestival_sub_default="/usr/share/xchestival/xchestival.sub";
21
22 $lang="it"#"en" if english
23
24 # Adjust this to your preferred Voice
25 $VOICE = "voice_lp_mbrola";     # Voce della femmina italiana
26
27 #$VOICE = "voice_pc_mbrola";    # voce del maschio italiano
28 #$VOICE = "voice_lp_diphone";   # voce del robot femmina italiano
29 #$VOICE = "voice_pc_diphone";   # voce del robot maschio italiano
30 #$VOICE = "voice_rab_diphone"; # A muted British-esque voice
31 #$VOICE = "voice_kal_diphone"; # An American male voice
32 #$VOICE = "voice_ked_diphone"; # A less mechanical American male voice
33
34 # Smaller numbers = faster speech
35 $SPEED = ".99";
36
37 ########## YOU CAN STOP CONFIGURING!
38
39 $already_loaded=0;
40 $spaccaballe=1;
41 $do_queue_mutex=0;
42 $pidof_festival="";
43 $lastchan="";
44 $lastquery="";
45 $buf_lines = "10"# Quante linee svuota ogni volta dal buffer del canale.
46 $says="dice";
47 $query_says="ti dice";
48 $line_highlight="";
49 $MY_NAME = "xchat_speak.pl";
50 $VERSION = "0.3.6";
51
52 %chan_queue = ();
53 %channels = ();
54 $lastthingsaid = "";
55 %lastwho = ();
56 %smilesub = ();
57 %wordsub = ();
58
59 IRC::register ($MY_NAME, $VERSION, "cmd_speechoff", "");
60 IRC::print("*** modulo $MY_NAME text->speech $VERSION caricato");
61 IRC::add_command_handler("muto", cmd_speechoff);
62 IRC::add_command_handler("voce", cmd_speechvoice);
63 IRC::add_command_handler("velocita", cmd_speechspeed);
64 IRC::add_command_handler("censure", cmd_censure);
65 IRC::add_command_handler("parla", cmd_speechon);
66 IRC::add_command_handler("associazioni", load_sub);
67 IRC::add_command_handler("associa", write_sub);
68 IRC::add_command_handler("seleziona", cmd_highlight);
69 IRC::add_command_handler("solotesto", cmd_solotesto);
70 IRC::add_command_handler("parlatutto", cmd_parlatutto);
71 IRC::add_command_handler("parlasoloin", cmq_parlasoloin);
72
73 sub cmd_parlatutto {
74         $spaccaballe=1;
75         IRC::print("   Comunico anche: topic, join, cambio nick, invite, part e quit\n");
76 }
77 sub cmd_solotesto {
78         $spaccaballe=0;
79         IRC::print("   Non dico: topic, join, cambio nick, invite, part e quit\n");
80 }
81
82 sub update_chan_list {
83         my $linein=$_[0], $c, $status;
84
85         if(!$linein) {
86                 $status="on";
87         } else {
88                 $status=$linein;
89         }
90        
91         @chan_list=IRC::channel_list();
92         foreach my $ch (@chan_list) {
93                 $c = (split(/ /, $ch))[0];
94                 if($c =~ /^[#+]/) {
95                         $channels{$c}=$status;
96 #                       IRC::print("$c == $channels{$c}");
97                 }
98
99         }
100 }
101
102 sub cmq_parlasoloin {
103         my $linein=$_[0];
104         if(!$linein) { return 0; }
105         &cmd_speechoff();
106         &cmd_speechon($linein);
107 }
108
109 sub cmd_highlight {
110         my $linein=$_[0];
111        
112         if(!$linein) {
113                 IRC::print("La selezione delle frasi e' disabilitata");
114                 undef $line_highlight;
115                 return;
116         }
117
118         $line_highlight=$linein;
119         IRC::print("Ora leggero' solo le frasi che contengono: $line_highlight");
120 }
121
122 sub load_sub {
123         my $linein=$_[0], $smi, $line;
124         if(!$linein) { $linein = $xchestival_sub; }
125
126         open(SUBFD, "< $linein")
127         || do {
128                         IRC::print("*E* Error opening $linein : $!");
129                         IRC::print("*E* trying with $xchestival_sub_default");
130                 $linein = $xchestival_sub_default;
131                 open(SUBFD, "< $linein")
132                         || do {
133                      IRC::print("*E* Error opening $xchestival_sub_default : $!");
134                          return;
135                                   };
136               };
137
138         IRC::print("Il file delle sostituzioni ora e': $linein");
139         %smilesub = ();
140         %wordsub = ();
141
142         while(<SUBFD>) {
143                 s/[\r\n]//g;
144                 warning("whitespace follows the \\ at the end-of-line.\nIf you
145                         meant to have a line continuation, remove the trailing
146                         whitespace.")
147                 if /\\\s+$/;
148                 $line = "$_\n" unless /^#/;
149                 s/#.*//;                # remove comments
150                 s/^\s+//;               # remove leading white space
151                 s/\s+$//;               # remove trailing white space
152                 s/\s+/ /g;              # canonify
153                 next if /^$/;
154
155                 $line =~ s/[\r\n]//g;
156                 $smi=0;
157                 if($line =~ /^SMILE:/) { $line =~ s/SMILE://; $smi=1; }
158                 $line =~ s/^\s+//;
159                
160                 ($a, $b) = split(/\s*==\s*/, "$line", 2);
161
162                 if($smi) {
163                         $smilesub{$a} = $b;     
164                 } else {
165                         $wordsub{$a} = $b;
166                 }
167         }
168         close SUBFD;
169 }
170
171 sub write_sub {
172         my $sub=$_[0] ,$linein, $line;
173        
174         if(!$sub) { return; }
175         $linein = $xchestival_sub;
176
177         open(SUBFD, ">>$linein") || do { IRC::print("*E* Error opening $linein : $!"); return; };
178        
179         print SUBFD "$sub\n";
180
181         $line = $sub;
182         if($line =~ /^SMILE:/) { $line =~ s/SMILE://; $smi=1; }
183         $line =~ s/^\s+//;
184         ($a, $b) = split(/\s*==\s*/, "$line", 2);
185         if($smi) {
186                 $smilesub{$a} = $b;
187                 IRC::print("smile $a == $b");
188         } else {
189                 $wordsub{$a} = $b;
190                 IRC::print("$a == $b");
191         }
192         close SUBFD;
193 }
194
195 sub smile_sub {
196         my $linein=$_[0];
197         my $sub;
198
199         foreach my $word (split(' ',$linein)) {
200                 $sub=$smilesub{$word} unless $sub;
201                 if ($sub) {
202                         return $sub;
203                 }
204                 undef($sub);
205         }
206         return $sub;
207 }
208
209 sub spch_substitute {
210         my $linein=$_[0];
211         my ($sub,$lineout);
212         foreach my $word (split(' ',$linein)) {
213                 #       $sub=$wordsub{$word};
214                 $sub=$wordsub{$word} unless $sub;
215                 if ($sub) {
216                         $lineout.=" $sub ";
217                 } else {
218                         $lineout.=" $word ";
219                 }
220                 undef($sub);
221         }
222         return($lineout);
223 }
224
225 sub cmd_censure {
226         if(!$already_loaded) { return 0; }
227         IRC::print("Questa e' la lista dei canali dove NON posso parlare:");
228         @key=keys(%channels);
229         foreach my $ch (@key) {
230                 $channels{$ch} eq "off" && IRC::print("   $ch\n");
231         }
232 }
233
234 sub cmd_speechvoice {
235         if(!$_[0]) { return 0; }
236         $says="dice";
237         $query_says="ti dice";
238         $lang="it";
239         if ( $_[0] eq "donna" )
240         {
241                 $VOICE = "voice_lp_mbrola";
242                 $ghgh="Voce settata a femmina italiana.";
243         }
244         if( $_[0] eq "uomo" )
245         {       
246                 $VOICE = "voice_pc_mbrola";
247                 $ghgh="Voce settata a masculo italiano.";
248         }
249         if( $_[0] eq "uomo_robot" )
250         {               
251                 $VOICE = "voice_pc_diphone";
252                 $ghgh="Voce settata a robot maschio italiano";
253         }
254         if ( $_[0] eq "donna_robot" )
255         {       $VOICE = "voice_lp_diphone";
256                 $ghgh="Voce settata a robot femmina italiana";
257         }
258
259         if ( $_[0] eq "inglese" )
260         {               $VOICE = "voice_ked_diphone";
261                 $ghgh="Voice setted to brute yankee";
262                 $says="says";
263                 $query_says="says";
264                 $lang="en";
265         }
266
267         IRC::print("*** Voice $VOICE");
268         print SPEECH "($VOICE)\n";
269         &speak("$ghgh");
270 }
271
272 sub cmd_speechspeed {
273         if(!$_[0]) { return 0; }
274         $SPEED=$_[0];
275         if($SPEED > 3) {
276                 &parla("Non posso settare quella velocita', sarei troppo lenta!", "1");
277                 IRC::print("Non posso settare quella velocita', sarei troppo lenta!", "1");
278                 return 0;
279         }
280         if($SPEED < 0.40) {
281                 &parla("Non posso settare quella velocita', sarei troppo veloce!", "1");
282                 IRC::print("Non posso settare quella velocita', sarei troppo veloce!");
283                 return 0;
284         }
285         IRC::print("*** Speed $SPEED");
286         print SPEECH "(Parameter.set 'Duration_Stretch $SPEED)\n";
287         &parla("Velocita' settata a: $SPEED", "1");
288         %lastwho = ();
289 }               
290
291 sub cmd_speechon {
292         my $linein=$_[0];
293
294
295         if (!defined($speech_pipe)) {
296                 open(SPEECH,"|$festival 2>&1 >/dev/null") || do { &print("*E* Error opening pipe to $festival"); return; };
297                 $pidof_festival=`pidof -s festival`;
298                 $pidof_festival =~ s/\n//;
299                 $fhcp=select(SPEECH);
300                 $|=1;
301                 select($fhcp);
302                 $speech_pipe=1;
303                 IRC::print("*** Speech activated!");
304                 if(!$already_loaded) {
305                         IRC::add_message_handler("PRIVMSG","speak");
306                         IRC::add_message_handler("SAY","speak");
307                         IRC::add_message_handler("TOPIC","speak");
308                         IRC::add_message_handler("JOIN","speak");
309                         IRC::add_message_handler("NICK","speak");
310                         IRC::add_message_handler("INVITE","speak");
311                         IRC::add_message_handler("PART","speak");
312                         IRC::add_message_handler("QUIT","speak");
313                         $already_loaded=1;
314                 }
315                 print SPEECH "($VOICE)\n";
316                 print SPEECH "(Parameter.set 'Duration_Stretch $SPEED)\n";
317                
318                 if(!$linein) {
319                         $channels{"1"}="on";
320                         &update_chan_list("on");
321                         @key=keys(%channels);
322                         foreach my $ch (@key) { $channels{$ch}="on"; }
323
324                         %lastwho = ();
325                         print SPEECH "(SayText \"Ora  comincio a parlare\")\n";
326                         &load_sub($xchestival_sub);
327                         return(1);
328                 }
329         }
330
331         if($linein) {
332                 $linein =~ s/ //g;
333                 $channels{$linein} = "on";
334                 IRC::print("Ora parlero' nel canale $linein");
335                 $linein =~ s/#//;
336                 print SPEECH "(SayText \"Ora parlero' nel canale $linein\")\n";
337                 $lastwho{$linein} = "";
338                 return 0;
339         } else {
340                 @key=keys(%channels);
341                 foreach my $ch (@key) { $channels{$ch}="on";    }
342                 IRC::print("Ora parlero' in tutti i canali");
343                 print SPEECH "(SayText \"Ora parlero' in tutti i canali\")\n";
344                 %lastwho = ();
345         }
346 }
347
348 sub cmd_speechoff {
349         my $linein=$_[0];
350
351         if(defined($speech_pipe)) {
352                 if($linein) {
353                         $linein =~ s/ //g;
354                         $channels{$linein} = "off";
355                         @{ $chan_queue{$linein} } = undef;
356                         IRC::print("Ora staro' muta nel canale $linein");
357                         $linein =~ s/#//;
358                         &parla("Ora staro' muta nel canale $linein", "1");
359                         $lastwho{$linein} = "";
360                         return 0;
361                 } else {
362                         &update_chan_list("off");
363                         @key=keys(%channels);
364                         foreach my $ch (@key) {
365                                 $channels{$ch}="off";
366                                 @{ $chan_queue{$ch} } = undef;
367                         }
368                         IRC::print("*** Ora mi disattivo");
369                         print SPEECH "(SayText \"Ora mi disattivo\")\n";
370                         %lastwho = ();
371                         undef($speech_pipe);
372                         if($pidof_festival) {
373                                 kill 15, $pidof_festival;
374                                 $pidof_festival="";
375                         }
376                         close(SPEECH);
377                 }
378
379         }
380
381         return(1);
382 }
383
384 sub do_chan_queue {
385         if($do_queue_mutex) { return 0; }
386         $do_queue_mutex=1;
387        
388         @key=keys(%chan_queue);
389         foreach my $ch (@key) {
390                 my $sayit="cacca", $i=0, $chh="";
391                 while($sayit && $i < $buf_lines) {
392                         $sayit=shift @{ $chan_queue{$ch} };
393                         if($channels{$ch} eq "off" || !$sayit) { last; }
394                         if($sayit && (($channels{$ch} eq "on") || $ch eq "1")) {
395                                 if(!$i && ($lastchan ne $ch) && ($ch ne "1") &&
396                                 ($ch =~ /^[#+]/)) {
397                                         ($chh = $ch) =~ s/[^a-zA-Z]//g;
398                                         print SPEECH "(SayText \"Nel canale $chh, \")\n";
399                                 }
400                                 #               IRC::print( "ch: $ch, last: $lastchan, $sayit");
401
402                                 print SPEECH "(SayText \"$sayit\")\n";
403                                 $lastchan=$ch;
404                                 $i++;
405                         }
406                 }
407         }
408         $do_queue_mutex=0;
409 }
410
411 sub parla {
412         my $linein=$_[0];
413         my $can=$_[1];
414
415         if(!$can) { $can="1"; }
416         push @{ $chan_queue{$can} }, $linein;
417
418         &do_chan_queue();
419 }
420
421 sub togli_merda {
422         my $linein=$_[0];
423
424         # Togliamo tutta la MMERDA dalla stringa,
425         # Questa REGEX DELLA MORTE MALE e' stata scritta da quel pazzo di sand,
426         # lode a lui o/
427 #       $linein =~ s/(?:\s|\A)\S*?[^a-z\s]+\S*?(?<![\.,:;'`])(?:\s|\Z)/ /gi;
428 #       $linein =~ s/(?:\s|\A)\S*?[^a-z\s]+\S*?(?<![\.,:;'`?!])(?:\s|\Z)/ /gi;
429 #       $linein =~ s/(?:\s|\A)\S*?[^a-z\s']+\S*?(?<![\.,:;'`?!])(?:\s|\Z)/ /gi;
430         $linein =~ s/(?:\s|\A)\S*?[^a-z0-9\s')("]+\S*?(?<![\.,:;'`?!])(?:\s|\Z)/ /gi;
431         return $linein;
432 }
433
434 sub speak {
435         defined($speech_pipe) || return;
436         my $speakline;
437         my $smile, $chan="1", $query=0, $qualcosa=0;
438         $speakline=$_[0];
439         $speakline = lc($speakline);
440         
441
442         if("$lastthingsaid" eq "$speakline") {  return 0; }
443         $lastthingsaid = $speakline;
444
445
446         #### Escludi i canali e le query azzittite #####
447         if ($speakline=~/^:(.*)!.*privmsg[^:]*[#+]([a-z0-9_A-Z]*)/) {
448                 $chan = "#"."$2";
449                 if($channels{$chan} eq "off") { return 0; }
450         } else {
451                 if ($speakline=~/^:(.*)!.*privmsg[^:]*[a-z0-9_A-Z]*/) {
452                         $chan=$1;
453                         $query=1;
454                         if($channels{$chan} eq "off") { return 0; }
455                 }
456         }
457         if ($speakline=~/^:(.*)!.*part[^:]*[#+]([a-z0-9_A-Z]*)/) {
458                 $chan = "#"."$2";
459                 if($channels{$chan} eq "off") { return 0; }
460         }
461         if ($speakline=~/^:(.*)!.*topic[^:]*[#+]([a-z0-9_A-Z]*)/) {
462                 $chan = "#"."$2";
463                 if($channels{$chan} eq "off") { return 0; }
464         }
465         if ($speakline=~/^:(.*)!.*join[^:]*:(.*)/) {
466                 $chan = "#"."$2";
467                 if($channels{$chan} eq "off") { return 0; }
468         }
469
470         $channels{$chan}="on";
471
472         if(!$query) { $lastquery=""; }
473
474         if ($speakline=~/^:(.*)!.*privmsg[^:]*:(.*)/) {
475                 $uno=$1;
476                 $smile=&smile_sub($2);
477                 $due = &togli_merda($2);
478
479                 if($speakline =~ /:.action /) {
480                         $speakline =~ s/.action//;
481                         if($speakline =~/^:(.*)!.*privmsg[^:]*:(.*)/) {
482                                 $uno=$1; $due = $2;
483                                 $uno =~ s/[^a-z]//g;
484                                 $speakline ="$uno $due";
485                                 $lastwho{$chan} = "";
486                                 if($query) { $lastquery=""; }
487                         }
488                 } else {
489                         $uno =~ s/[^a-z]//g;
490                         if($query) { $speakline="$uno $query_says, $due";
491                         } else {$speakline="$uno $says, $due"; }
492                         if(!$query && $lastwho{$chan} eq "$uno") { $speakline="$due"; }
493                         if($query && $lastquery eq "$chan") { $speakline="$due"; }
494                         if($query) { $lastquery=$chan; }
495                         $lastwho{$chan} = $uno;
496                 }
497                 ($t=$due)=~ s/ //g;
498                 if(!$due || !$t) { if($smile) { &parla("$uno $smile", "$chan"); } return 0; }
499                 $qualcosa=1;
500         }
501         
502         if ($spaccaballe) {
503         if ($speakline=~/^:(.*)!.*topic[^:]*:(.*)/) {
504                 $uno=$1;
505                 $smile=&smile_sub($2);
506                 $due = &togli_merda($2);
507                 $speakline="il nuovo topicc e': $due";
508                 $uno =~ s/[^a-z]//g;
509                 ($t=$due)=~ s/ //g;
510                 if(!$due || !$t) { if($smile) { &parla("$uno $smile","$chan"); } return 0; }
511                 $lastwho{$chan} = "";
512         }
513         if ($speakline=~/^:(.*)!.*join[^:]*:(.*)/) {
514                 $uno=$1; $due=$2;
515                 $uno =~ s/[^a-z]//g;
516                 $speakline="$uno ha gioinato";
517                 $lastwho{$chan} = "";
518         }
519         if ($speakline=~/^:(.*)!.*nick[^:]*:(.*)/) {
520                 $uno=$1; $due = $2;
521                 $uno =~ s/[^a-z]//g;
522                 $due =~ s/[^a-z]//g;
523                 $speakline="$uno ha cambiato il nick in  $due";
524                 $lastwho{$chan} = "";
525         }
526         if ($speakline=~/^:(.*)!.*invite[^:]*:(.*)/) {
527                 $uno=$1;
528                 $uno =~ s/[^a-z]//g;
529                 $due = &togli_merda($2);
530                 $chan = "1";
531                 $speakline="$uno ti ha invitato in  $due";
532                 $lastwho{$chan} = "";
533         }
534         if ($speakline=~/^:(.*)!.*part[^:]*:(.*)/) {
535                 $uno=$1;
536                 $due = &togli_merda($2);
537                 $uno =~ s/[^a-z]//g;
538                 $speakline="$uno e' uscito e dice: $due";
539                 $lastwho{$chan} = "";
540         }
541         if ($speakline=~/^:(.*)!.*quit[^:]*:(.*)/) {
542                 $uno=$1;
543                 $due = &togli_merda($2);
544                 $uno =~ s/[^a-z]//g;
545                 $speakline="$uno e' uscito e dice: $due";
546                 $lastwho{$chan} = "";
547         }
548                 $qualcosa=1;
549         }
550         if(!$qualcosa) { return; }
551
552         $speakline=&spch_substitute($speakline);
553
554         $speakline =~ tr/a-z0-9,.<>?'@+=&%$£!\/: ]//cd;
555         $speakline =~ s/\?+/\?/g; # Collapse '?'
556         $speakline =~ s/\!+/\!/g; # Collapse '!'
557         $speakline =~ s/ +/ /g; # Collapse spaces
558         $speakline =~ s/\.{2,}/ /g; # Collapse multiple dots
559         $speakline =~ s/\s*\?\s*$/\?/; # "phrase    ?" = "phrase?"
560         $speakline =~ s/\s*\!\s*$/\!/; # "phrase    !" = "frase!"
561         $speakline =~ s/\s*\?/\?/; # "phrase    ?" = "phrase?"
562         $speakline =~ s/\s*\!/\!/; # "phrase    !" = "frase!"
563
564         # " frase " = ,frase,;   ( frase  ) = ,frase,;
565         $speakline =~ s/([a-zA-Z])\s*\)|\(\s*([a-zA-Z])/\1, \2/g;
566         $speakline =~ s/\s*"\s*/, /g;
567         $speakline =~ s/\s*,\s*,\s*/, /g;
568         $speakline =~ s/^,\s*//g;
569         $speakline =~ s/\s*,\s*$//g;
570
571         #collapse long repetition
572         foreach my $i (split(//, $speakline)) {
573                 if($i) { $speakline=~ s/[$i]{8,}/$i$i$i$i$i$i$i/g; }
574         }
575         
576         
577         if($lang eq "it") { $speakline =~ s/y/i/g; } # 'y' = 'i'
578
579 #       IRC::print("$speakline");
580         
581         if($line_highlight && $speakline !~ /$line_highlight/) { return 0; }
582         
583         &parla("$speakline", "$chan");
584         if($smile) { &parla("$uno $smile", "$chan"); }
585
586         return 0;
587 }
588
589 IRC::command("/parla");
590
Note: See TracBrowser for help on using the browser.