ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/Net-Knuddels/eg/markovd
Revision: 1.26
Committed: Sun Jan 30 05:56:40 2005 UTC (21 years, 7 months ago) by root
Branch: MAIN
Changes since 1.25: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #!/opt/bin/perl
2
3 use strict;
4
5 use Socket;
6 use IO::Socket::INET;
7
8 use YAML;
9 use Encode;
10 use Event;
11 use Net::Knuddels;
12 use Algorithm::MarkovChain;
13 use String::Similarity;
14 use List::Util;
15
16 my @CHANNELS = (
17 'Flirt',
18 'Flirt Private',
19 'Singles 11-14',
20 'Singles 15-17',
21
22 'Singles 11-14 2',
23 'Singles 15-17 2',
24 'Flirt 2',
25 'Flirt Private 2',
26 'Singles 11-14 3',
27 'Singles 15-17 3',
28 'Flirt 3',
29 'Flirt Private 3',
30 'Singles 11-14 4',
31 'Singles 15-17 4',
32 'Flirt 4',
33 'Flirt Private 4',
34 'Singles 11-14 5',
35 'Singles 15-17 5',
36 'Flirt 5',
37 'Flirt Private 5',
38 'Singles 11-14 6',
39 'Singles 15-17 6',
40 'Flirt 6',
41 'Flirt Private 6',
42 'Singles 11-14 7',
43 'Singles 15-17 7',
44 'Flirt 7',
45 'Flirt Private 7',
46 'Singles 11-14 8',
47 'Singles 15-17 8',
48 'Flirt 8',
49 'Flirt Private 8',
50 );
51
52 my $logdir = "logs";
53
54 my $Knick = "ich bin suess";
55 my $Kpass = "qwerty";
56
57 my $client;
58
59 my $seed = Load do { open my $fh, "<", "markovbot.dat"; binmode $fh, ":utf8"; local $/; <$fh> };
60 $seed ||= [];
61
62 my $fwd = new Algorithm::MarkovChain;
63 my $rev = new Algorithm::MarkovChain;
64
65 my %freq;
66 my $word_cnt;
67
68 sub word {
69 $_[0] =~ /(\w+)/ ? lc $1 : ();
70 }
71
72 sub seed_msg {
73 my $msg = $_[0];
74
75 return if $msg =~ /leck|fick|möse|mose|moese|uschi|usci|ushi|fikkn
76 |bumsen|wichs|wix|popp|popen|fuck|dreck|laber|saugen|pussy
77 |\bblas|piss|schluck|fingern|spritz|\bloch
78 |hure|strich|sklave|handschell
79 |stengel|penis|schwanz|pimmel|steifen|ejak|sperma|\btitt|\bass|\bsack|\bsaft\b
80 |\bcs\b|\bts\b|\brs\b|\bicq\b
81 |cam\b|\bmsn\b|\bbot\b|\bchat.*bot\b|tanga|schlafen|sex|\bsau\b
82 |intim|arsch|fotze|dumm|schnauze|klappe|rasiert|fresse|maul\b|\bmaul|rosett?e
83 |zieh.*aus|nackt
84 |sätz|saetz|setze|\bsatz
85 |sc?h?wul|schwuchtel|transe|transv|schlampe|tussi|nutte|mädel
86 |admin|nachgeburt
87 |(?-i:[A-Z]{4,})
88 |\S{20,}
89 /xi;
90
91 my @msg = $msg =~ m/(\S+)/g;
92
93 $freq{word $_}++ for @msg;
94 $word_cnt += @msg;
95
96 $fwd->seed (symbols => \@msg, longest => 14);
97 $rev->seed (symbols => [reverse @msg], longest => 14);
98 }
99
100 for (@$seed) {
101 seed_msg $_;
102 }
103
104 my %grammar_reply = qw(
105 ich du
106 du ich
107 mir dir
108 dir mir
109 mein dein
110 dein mein
111 frau mann
112 mädel junge
113 mädchen junge
114 freund freundin
115 freundin freund
116 girls boys
117 boys girls
118 huhu hi
119 hi hi
120 hallo hi
121 typen mädels
122 );
123
124 sub gen_reply {
125 my ($msg) = @_;
126
127 my @msg = $msg =~ /(\S+)/g;
128
129 @msg = map {
130 my $word = word $_;
131
132 $grammar_reply{$word}
133 or $freq{$word} < $word_cnt * 0.002
134 && $freq{$word} >= 2
135 && 4 < length $word
136 ? $word
137 : ()
138 } @msg;
139
140 my $reply;
141 my $best = 2;
142
143 for (1..15) {
144 shift @msg if @msg > $_;
145 my $len = rand() ** 4 * 20 + 2;
146 my @r = reverse $rev->spew (complete => [reverse @msg], length => $len, stop_at_terminal => 1);
147 @r = $fwd->spew (complete => \@r, length => $len, stop_at_terminal => 1);
148 my $r = join " ", @r;
149 my $b = (List::Util::sum map $freq{word $_} / $word_cnt, @r) / @r;
150 ($reply, $best) = ($r, $b) if $b < $best;
151 }
152
153 $reply;
154 }
155
156 while (0) {
157 my $r = gen_reply scalar <>;
158 print "$r\n\n";
159 }
160
161 Event->signal (signal => "INT", cb => sub { Event::unloop(-1) });
162
163 Event->timer (interval => 60, cb => sub {
164 open my $fh, ">", "markovbot.dat~"
165 or return;
166 print $fh Encode::encode_utf8 Dump $seed;
167 close $fh;
168 rename "markovbot.dat~", "markovbot.dat";
169 });
170
171 sub logit {
172 my ($msg, $file, $src, $dst, $room) = @_;
173
174 mkdir $logdir;
175 my $fh;
176
177 unless (open $fh, ">>:utf8", Encode::encode_utf8 "$logdir/$file") {
178 warn "Couldn't open for appending $logdir/$src: $!\n";
179 return;
180 }
181
182 print $fh "$room\t$src\t$dst\t$msg\n";
183 }
184
185 ####################################################################################
186 ########################## MAIN START ##############################################
187 ####################################################################################
188
189 $client = new Net::Knuddels::Client
190 PeerAddr => "213.61.5.150:2710",
191 command_wait => sub {
192 my ($client, $wait) = @_;
193 Event->timer (after => $wait, cb => sub { $client->command_cb });
194 };
195
196 Event->io (
197 fd => $client->fh,
198 poll => 'r',
199 cb => sub {
200 $client->ready
201 or $_[0]->w->cancel;
202 });
203
204 $client->login;
205
206 #$client->register (ALL => sub {
207 # use Dumpvalue;
208 # print "---\n";
209 # Dumpvalue->new (compactDump => 1, veryCompact => 1, quoteHighBit => 1, tick => '"')->dumpValue ([@_]);
210 #});
211
212 $client->register (login => sub {
213 $client->enter_room ($_, $Knick, $Kpass)
214 for @CHANNELS;
215 });
216
217 $client->register (msg_room => sub {
218 my ($room, $user, $msg) = @_;
219 });
220
221 my @queue;
222
223 Event->timer (interval => 1, cb => sub {
224 my $msg = shift @queue
225 or return;
226
227 logit ($msg->[2], $msg->[0], $Knick, $msg->[0], $msg->[1]);
228 $client->send_priv_msg (@$msg);
229 });
230
231 my $some_room;
232
233 $client->register (room_info => sub {
234 print "JOIN ROOM: $_[0]\n";
235 $some_room = $_[0];
236 });
237
238 Event->timer (after => 60, interval => 60, cb => sub {
239 $client->send_priv_msg ("James", $some_room, "/knuschel");
240 });
241
242 my %next_time;
243
244 $client->register (msg_priv_nondup => sub {
245 my ($room, $src, $dst, $msg) = @_;
246
247 $msg =~ s/\260[^\260]*\260//g;
248
249 print "($room) $src >> $msg\n";
250 logit ($msg, $src, $src, $dst, $room);
251
252 return if $next_time{$src} > time; # do not talk unnaturally often
253
254 my $reply = gen_reply $msg;
255
256 push @$seed, $msg;
257 seed_msg $msg;
258
259 my $delay = 30 * (rand) ** 5 + 0.3 * length $reply;
260 $next_time{$src} = time + $delay;
261
262 print "($room) $src << $reply ($delay)\n";
263
264 Event->timer (after => $delay, cb => sub {
265 push @queue, [$src, $room, $reply];
266 });
267 });
268
269 Event::loop;
270