2 # Freshmeat.pl: Frontend to www.freshmeat.net
4 # Version: v0.7d (20000923)
12 ### download compressed version instead?
15 'public' => 'http://www.freshmeat.net/backend/appindex.txt',
16 'private' => 'http://feed.freshmeat.net/appindex/appindex.txt',
20 # Usage: &Freshmeat($string);
23 my $refresh = &::getChanConfDefault("freshmeatRefreshInterval",
26 my $last_refresh = &::dbGet("freshmeat", "name","_","stable");
29 if (defined $last_refresh) {
30 $renewtable++ if (time() - $last_refresh > $refresh);
34 $renewtable++ if (&::countKeys("freshmeat") < 10);
36 if ($renewtable and $$ == $::bot_pid) {
37 &::Forker("freshmeat", sub {
41 # both parent/fork runs here, in case the following looks weird.
42 return if ($$ == $::bot_pid);
45 if (!&showPackage($sstr)) { # no exact match.
46 my $start_time = &::timeget();
49 # search by key/NAME first.
50 foreach (&::searchTable("freshmeat", "name","name",$sstr)) {
51 $hash{$_} = 1 unless exists $hash{$_};
54 # search by description line.
55 foreach (&::searchTable("freshmeat", "name","oneliner", $sstr)) {
56 $hash{$_} = 1 unless exists $hash{$_};
57 last if (scalar keys %hash > 15);
60 my @list = keys %hash;
61 # search by value, if we have enough room to do it.
62 if (scalar @list == 1) {
63 &::status("only one match found; showing full info.");
64 &showPackage($list[0]);
68 # show how long it took.
69 my $delta_time = &::timedelta($start_time);
70 &::status(sprintf("freshmeat: %.02f sec to complete query.", $delta_time)) if ($delta_time > 0);
74 s/([\,\;]+)/\037$1\037/g;
77 &::performStrictReply( &::formListReply(1, "Freshmeat ", @list) );
83 my @fm = &::dbGet("freshmeat", "name",$pkg,"*");
85 if (scalar @fm) { #1: perfect match of name.
87 $retval = "$fm[0] \002(\002$fm[11]\002)\002, ";
88 $retval .= "section $fm[3], ";
89 $retval .= "is $fm[4]. ";
90 $retval .= "Stable: \002$fm[1]\002, ";
91 $retval .= "Development: \002$fm[2]\002. ";
92 $retval .= $fm[5] || $fm[6]; # fallback to 'download'.
93 $retval .= " deb: ".$fm[8] if ($fm[8] ne ""); # 'deb'.
94 &::performStrictReply($retval);
102 my @fm = &::randKey("freshmeat","*");
104 if (scalar @fm) { #1: perfect match of name.
106 $retval = "$fm[0] \002(\002$fm[11]\002)\002, ";
107 $retval .= "section $fm[3], ";
108 $retval .= "is $fm[4]. ";
109 $retval .= "Stable: \002$fm[1]\002, ";
110 $retval .= "Development: \002$fm[2]\002. ";
111 $retval .= $fm[5] || $fm[6]; # fallback to 'download'.
112 $retval .= " deb: ".$fm[8] if ($fm[8] ne ""); # 'deb'.
121 my $start_time = &::timeget(); # set the start time.
122 my $idx = "$::param{tempDir}/fm_index.txt";
124 &::msg($::who, "Updating freshmeat index... please wait");
126 if (&::isStale($idx, 1)) {
127 &::status("Freshmeat: fetching data.");
128 foreach (keys %urls) {
129 my $retval = &::getURLAsFile($urls{$_}, $idx);
130 next if ($retval =~ /^(403|500)$/);
132 &::DEBUG("FM: last! retval => '$retval'.");
136 &::status("Freshmeat: local file hack.");
140 &::msg($::who, "the freshmeat butcher is closed.");
144 if ( -s $idx < 100000) {
145 &::DEBUG("FM: index too small?");
147 &::msg($::who, "internal error?");
151 if ($idx =~ /bz2$/) {
152 open(IN, "bzcat $idx |");
153 } elsif ($idx =~ /gz$/) {
154 open(IN, "gzcat $idx |");
159 # delete the table before we redo it.
160 &::deleteTable("freshmeat");
162 ### lets get on with business.
163 # set the last refresh time. fixes multiple spawn bug.
164 &::dbSet("freshmeat", "name","_","stable",time());
167 while (my $line = <IN>) {
169 $i++ if ($line eq "%%");
173 &::dbRaw("LOCK", "LOCK TABLES freshmeat WRITE");
176 while (my $line = <IN>) {
183 if ($i % 200 == 0 and $i != 0) {
184 &::DEBUG("FM: unlocking and locking.");
185 &::dbRaw("UNLOCK", "UNLOCK TABLES");
186 ### another lame hack to "prevent" errors.
187 select(undef, undef, undef, 0.2);
188 &::dbRaw("LOCK", "LOCK TABLES freshmeat WRITE");
191 if (grep /^\Q$data[0]\E$/, @done) {
192 &::DEBUG("dupe? $data[0]");
201 &::dbSetRow("freshmeat", @data);
202 push(@done,$data[0]);
206 &::DEBUG("FM: data ".scalar(@data) );
207 &::dbRaw("UNLOCK", "UNLOCK TABLES");
209 my $delta_time = &::timedelta($start_time);
210 &::status(sprintf("Freshmeat: %.02f sec to complete.", $delta_time)) if ($delta_time > 0);
212 my $count = &::countKeys("freshmeat");
213 &::status("Freshmeat: $count entries loaded.");
216 sub freshmeatAnnounce {
217 my $file = "$::param{tempDir}/fm_recent.txt";
220 ### if file exists, lets read it.
230 my @array = &::getURL("http://core.freshmeat.net/backend/recentnews.txt");
234 my($what,$date,$url) = splice(@array,0,3);
238 ### if file does not exist, write new.
250 for(my $i=0; $i<scalar(@old); $i++) {
251 last if ($now[$i] eq $old[0]);
252 push(@new, $now[$i]);
256 &::DEBUG("fA: no new items.");
267 return "Freshmeat update: ".join(" \002::\002 ", @new);