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