[Slashdotjp-dev 759] [272] merge from upstream 2.5.0.186 branch

Back to archive index

svnno****@sourc***** svnno****@sourc*****
2007年 12月 6日 (木) 18:17:48 JST


Revision: 272
          http://svn.sourceforge.jp/cgi-bin/viewcvs.cgi?root=slashdotjp&view=rev&rev=272
Author:   tach
Date:     2007-12-06 18:17:47 +0900 (Thu, 06 Dec 2007)

Log Message:
-----------
merge from upstream 2.5.0.186 branch

Modified Paths:
--------------
    slashjp/trunk/Slash/Apache/User/User.pm
    slashjp/trunk/Slash/DB/MySQL/MySQL.pm
    slashjp/trunk/plugins/Admin/Admin.pm
    slashjp/trunk/plugins/Admin/admin.pl
    slashjp/trunk/plugins/Admin/templates/editStory;admin;default
    slashjp/trunk/plugins/Ajax/PLUGIN
    slashjp/trunk/plugins/Ajax/htdocs/ajax.pl
    slashjp/trunk/plugins/Ajax/htdocs/images/admin.js
    slashjp/trunk/plugins/Ajax/htdocs/images/common.js
    slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js
    slashjp/trunk/plugins/Ajax/mysql_dump.sql
    slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_d2_posting;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_messages;ajax;default
    slashjp/trunk/plugins/Console/Console.pm
    slashjp/trunk/plugins/Console/console.pl
    slashjp/trunk/plugins/Console/templates/display;console;default
    slashjp/trunk/plugins/FAQSlashdot/faq/tags.shtml
    slashjp/trunk/plugins/FireHose/FireHose.pm
    slashjp/trunk/plugins/FireHose/firehose.css
    slashjp/trunk/plugins/FireHose/firehose.pl
    slashjp/trunk/plugins/FireHose/templates/admin_extras;misc;default
    slashjp/trunk/plugins/FireHose/templates/list;firehose;default
    slashjp/trunk/plugins/FireHose/templates/nodnix_menus;firehose;default
    slashjp/trunk/plugins/Stats/Stats.pm
    slashjp/trunk/plugins/Stats/adminmail.pl
    slashjp/trunk/plugins/Stats/templates/display;adminmail;default
    slashjp/trunk/plugins/Tags/Clout/Describe.pm
    slashjp/trunk/plugins/Tags/Clout.pm
    slashjp/trunk/plugins/Tags/PLUGIN
    slashjp/trunk/plugins/Tags/Tagbox.pm
    slashjp/trunk/plugins/Tags/Tags.pm
    slashjp/trunk/plugins/Tags/templates/data;tags;default
    slashjp/trunk/sql/mysql/defaults.sql
    slashjp/trunk/sql/mysql/upgrades
    slashjp/trunk/tagboxes/Top/mysql_dump.sql
    slashjp/trunk/themes/slashcode/htdocs/base.css
    slashjp/trunk/themes/slashcode/htdocs/comments.css
    slashjp/trunk/themes/slashcode/htdocs/images/comments.js
    slashjp/trunk/themes/slashcode/htdocs/users.pl
    slashjp/trunk/themes/slashcode/tasks/freshenup.pl
    slashjp/trunk/themes/slashcode/templates/prefs_titlebar;misc;default
    slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default

Added Paths:
-----------
    slashjp/trunk/plugins/Ajax/templates/prefs_sectional;ajax;default
    slashjp/trunk/plugins/Ajax/templates/prefs_user;ajax;default
    slashjp/trunk/plugins/Tags/templates/recenttagnamesbox;misc;default


-------------- next part --------------
Modified: slashjp/trunk/Slash/Apache/User/User.pm
===================================================================
--- slashjp/trunk/Slash/Apache/User/User.pm	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/Slash/Apache/User/User.pm	2007-12-06 09:17:47 UTC (rev 272)
@@ -961,6 +961,10 @@
 Bender:Stop doing the right thing, you jerk!
 Bender:Are you familiar with the old robot saying "does not compute"?
 Bender:The sparks keep me warm.
+Bender:Boy, were we suckers!
+Bender:Whaddya say, folks? Hot or not?
+Bender:Bender knows when to use finesse.
+Bender:And I bet it's gonna get a lot more confusing.
 Fry:There's a lot about my face you don't know.
 Fry:These new hands are great. I'm gonna break them in tonight.
 Fry:I refuse to testify on the grounds that my organs will be chopped up into a patty.
@@ -1007,6 +1011,9 @@
 Fry:I have more important things to do today than laugh and clap my hands.
 Fry:I'll be whatever I wanna do.
 Fry:There's a political debate on. Quick, change the channel!
+Fry:It's all there, in the macaroni.
+Fry:Can I pull up my pants now?
+Fry:Robots don't go to heaven.
 Leela:There's a political debate on. Quick, change the channel!
 Leela:You did the best you could, I guess, and some of these gorillas are okay.
 Leela:This wangs chung.
@@ -1016,6 +1023,8 @@
 Leela:I'm a millionaire! Suddenly I have an opinion about the capital gains tax.
 Leela:Do you have idiots on your planet?
 Leela:My old life wasn't as glamorous as my webpage made it look.
+Leela:No, Leela will show you out.
+Hermes:Without my body, I'm a nobody.
 EOT
 
 1;

Modified: slashjp/trunk/Slash/DB/MySQL/MySQL.pm
===================================================================
--- slashjp/trunk/Slash/DB/MySQL/MySQL.pm	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/Slash/DB/MySQL/MySQL.pm	2007-12-06 09:17:47 UTC (rev 272)
@@ -12423,20 +12423,12 @@
 	my $noid = $self->sqlSelect('noid','submissions_notes',
 		'submatch=' . $self->sqlQuote($submatch));
 
-        if ($noid) {
-                $self->sqlUpdate('submissions_notes', {
-                        subnote => $subnote,
-                        uid     => $user->{uid},
-                        '-time' => 'NOW()',
-                }, "noid=" . $noid);
-        } else {
-                $self->sqlInsert('submissions_notes', {
-                        submatch        => $submatch,
-                        subnote         => $subnote,
-			uid             => $user->{uid},
-                        '-time'         => 'NOW()',
-                });
-	}
+	$self->sqlInsert('submissions_notes', {
+       		submatch        => $submatch,
+		subnote         => $subnote,
+		uid             => $user->{uid},
+                '-time'         => 'NOW()',
+        });
 }
 
 sub getSubmissionMemory {

Modified: slashjp/trunk/plugins/Admin/Admin.pm
===================================================================
--- slashjp/trunk/plugins/Admin/Admin.pm	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Admin/Admin.pm	2007-12-06 09:17:47 UTC (rev 272)
@@ -455,10 +455,10 @@
 		tasks_next              => \@tasks_next,
 		tasks_inprogress        => \@tasks_inprogress,
 		tasks_last              => \@tasks_last,
-	}, , { Return => 1 });
-	
+	}, { Return => 1 });
+
 	return $text if $options->{contents_only};
-	
+
 	$updater = getData('slashdbox_js', {}, "admin") if $options->{updater};
 	slashDisplay('sidebox', {
 		updater 	=> $updater,
@@ -479,7 +479,7 @@
 	my $updater;
 	my $perf_box = slashDisplay('performance_box', {}, { Return => 1 });
 	return $perf_box if $options->{contents_only};
-	$updater =getData('perfbox_js', {}, "admin") if $options->{updater};
+	$updater = getData('perfbox_js', {}, "admin") if $options->{updater};
 	slashDisplay("sidebox", {
 		updater 	=> $updater,
 		name 		=> 'performancebox',

Modified: slashjp/trunk/plugins/Admin/admin.pl
===================================================================
--- slashjp/trunk/plugins/Admin/admin.pl	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Admin/admin.pl	2007-12-06 09:17:47 UTC (rev 272)
@@ -10,7 +10,6 @@
 use Time::HiRes;
 use LWP::UserAgent;
 use URI;
-use XML::Simple;
 
 use Slash;
 use Slash::Display;
@@ -1448,34 +1447,6 @@
 		}
 	}
 
-	my $yoogli_similar_stories = {};
-	if ($constants->{yoogli_oai_search}) {
-		my $query = $constants->{yoogli_oai_query_base} .= '?verb=GetRecord&metadataPrefix=oai_dc&rescount=';
-		$query .= $constants->{yoogli_oai_result_count} . '&identifier=' . URI->new($storyref->{introtext});
-
-		my $ua = new LWP::UserAgent;
-		$ua->timeout($constants->{yoogli_oai_result_count} + 2);
-		my $req = new HTTP::Request GET => $query;
-		my $res = $ua->request($req);
-		if ($res->is_success) {
-			my $xml = new XML::Simple;
-			my $content = eval { $xml->XMLin($res->content) };
-			unless ($@) {
-				my $sid_regex = regexSid();
-				foreach my $metadata (@{$content->{'GetRecord'}{'record'}}) {
-                                        next if $metadata->{'metadata'}{'title'} eq $storyref->{title};
-					my $key = $metadata->{'header'}{'identifier'};
-					my($sid) = $metadata->{'metadata'}{'identifier'} =~ $sid_regex;
-					$yoogli_similar_stories->{$key}{'date'}  = $reader->getStory($sid, 'time');
-					$yoogli_similar_stories->{$key}{'url'}   = $metadata->{'metadata'}{'identifier'};
-					$yoogli_similar_stories->{$key}{'title'} = $metadata->{'metadata'}{'title'};
-					$yoogli_similar_stories->{$key}{'relevance'} = $metadata->{'metadata'}{'relevance'};
-					$yoogli_similar_stories->{$key}{'sid'} = $sid;
-				}
-			}
-		}
-	}
-
 	my $admindb = getObject('Slash::Admin');
 	my $authortext = $admindb->showStoryAdminBox($storyref);
 	my $slashdtext = $admindb->showSlashdBox();
@@ -1556,7 +1527,6 @@
 		signofftext		=> $signofftext,
 		user_signoff		=> $user_signoff,
 		add_related_text	=> $add_related_text,
-		yoogli_similar_stories  => $yoogli_similar_stories,
 		pending_file_count	=> $pending_file_count,
 		story_static_files	=> $story_static_files
 	});
@@ -2094,6 +2064,12 @@
 	$data->{neverdisplay} = $form->{display} ? '' : 1;
 
 #print STDERR "admin.pl before updateStory data: " . Dumper($data);
+	if ($data->{neverdisplay}) {
+		print STDERR "Setting sid: $form->{sid} to neverdisplay\n";
+		use Data::Dumper;
+		print STDERR Dumper($form);
+		print STDERR Dumper($data);
+	}
 	if (!$slashdb->updateStory($form->{sid}, $data)) {
 		titlebar('100%', getTitle('story_update_failed'));
 		editStory(@_);

Modified: slashjp/trunk/plugins/Admin/templates/editStory;admin;default
===================================================================
--- slashjp/trunk/plugins/Admin/templates/editStory;admin;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Admin/templates/editStory;admin;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -78,16 +78,6 @@
 					[% seen_related.${story.sid} = 1 %]
 				</tr>
 				[% END %]
-			        [% FOREACH story = yoogli_similar_stories.keys.sort %]
-                                <tr class="story_main">
-                                        <td>Y=[% yoogli_similar_stories.$story.relevance.substr(0, 4) %]</td>
-                                        <td><a href="[% yoogli_similar_stories.$story.url %]">[% yoogli_similar_stories.$story.title.substr(0, 35) %]...</a></td>
-                                        <td>[% Slash.timeCalc(yoogli_similar_stories.$story.date) %]</td>
-                                        <td><input type="checkbox" name="related_story" value="[% yoogli_similar_stories.$story.sid | strip_attribute %]"[% IF storyref.related_sids_hr.${yoogli_similar_stories.$story.sid}; constants.markup_checked_attribute; END %]></td>
-                                        <td>&nbsp;</td>
-                                        [% seen_related.${yoogli_similar_stories.$story.sid} = 1 %]
-                                </tr>
-                                [% END %]	
 
 		[% FOREACH rel_sid = storyref.related_sids_hr.keys %]
 			[% IF seen_related.$rel_sid; NEXT; END; %]

Modified: slashjp/trunk/plugins/Ajax/PLUGIN
===================================================================
--- slashjp/trunk/plugins/Ajax/PLUGIN	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Ajax/PLUGIN	2007-12-06 09:17:47 UTC (rev 272)
@@ -37,3 +37,5 @@
 template=templates/prefs_d2_posting;ajax;default
 template=templates/prefs_messages;ajax;default
 template=templates/modal_footer;misc;default
+template=templates/prefs_user;ajax;default
+template=templates/prefs_sectional;ajax;default

Modified: slashjp/trunk/plugins/Ajax/htdocs/ajax.pl
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/ajax.pl	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Ajax/htdocs/ajax.pl	2007-12-06 09:17:47 UTC (rev 272)
@@ -171,7 +171,7 @@
 
 	my $master_value = !$multiple_values ? $first_val : "";
 
-	return slashDisplay("sectionpref",
+	return slashDisplay("prefs_sectional",
 		{
 			nexusref		=> $nexus_hr,
 			nexustid_order		=> \@nexustid_order,
@@ -183,7 +183,7 @@
 	);
 }
 
-sub setSectionNexusPrefs() {
+sub setSectionNexusPrefs {
 	my($slashdb, $constants, $user, $form) = @_;
 
 	my $reader = getObject('Slash::DB', { db_type => 'reader' });
@@ -259,7 +259,7 @@
 		}
 	);
 
-	return getData('set_section_prefs_success_msg');
+        #return getData('set_section_prefs_success_msg');
 }
 
 ###################
@@ -538,8 +538,10 @@
 			},
 			{ Return => 1 }
 		);
-	} else {
-		return
+	} elsif ($form->{'section'} eq 'sectional') {
+               getSectionPrefsHTML($slashdb, $constants, $user, $form);
+        } else {
+                return
 			slashDisplay('prefs_' . $form->{'section'}, {
 				user => $user,
 			},
@@ -571,14 +573,9 @@
 	}
 
 	if ($params{'formname'} eq 'd2_posting') {
-		my $karma_bonus      = ($params{'karma_bonus'}      !~ /^[\-+]?\d+$/) ? "+1" : $params{'karma_bonus'};
-		my $subscriber_bonus = ($params{'subscriber_bonus'} !~ /^[\-+]?\d+$/) ? "+1" : $params{'subscriber_bonus'};
-
 		$user_edits_table = {
 			emaildisplay      => $params{'emaildisplay'} || undef,
-			karma_bonus       => ($karma_bonus ne '+1' ? $karma_bonus : undef),
 			nobonus           => ($params{'nobonus'} ? 1 : undef),
-			subscriber_bonus  => ($subscriber_bonus || undef),
 			nosubscriberbonus => ($params{'nosubscriberbonus'} ? 1 : undef),
 			posttype          => $params{'posttype'},
 			textarea_rows     => ($params{'textarea_rows'} != $constants->{'textarea_rows'}
@@ -612,6 +609,109 @@
 		};
 	}
 
+        if ($params{'formname'} eq 'user') {
+                my $user_edit = $slashdb->getUser($params{uid});
+                my $gSkin = getCurrentSkin();
+
+                # Real Email
+                if ($user_edit->{realemail} ne $params{realemail}) {
+                        if ($slashdb->existsEmail($params{realemail})) {
+                                $params{realemail} = $user_edit->{realemail};
+                        }
+                }
+
+                # Homepage
+                my $homepage = $params{homepage};
+                $homepage = '' if $homepage eq 'http://';
+                $homepage = fudgeurl($homepage);
+                $homepage = URI->new_abs($homepage, $gSkin->{absolutedir})
+                               ->canonical
+                               ->as_string if $homepage ne '';
+                $homepage = substr($homepage, 0, 100) if $homepage ne '';
+
+                # Calendar
+                my $calendar_url = $params{calendar_url};
+                if (length $calendar_url) {
+                        $calendar_url =~ s/^webcal/http/i;
+                        $calendar_url = fudgeurl($calendar_url);
+                        $calendar_url = URI->new_abs($calendar_url, $gSkin->{absolutedir})
+                                           ->canonical
+                                           ->as_string if $calendar_url ne '';
+                        $calendar_url =~ s|^http://||i;
+                        $calendar_url = substr($calendar_url, 0, 200) if $calendar_url ne '';
+                }
+
+                my(%extr, $err_message, %limit);
+                $limit{sig} = 120;
+                $limit{bio} = $constants->{users_bio_length} || 1024;
+
+                for my $key (keys %limit) {
+                        my $dat = chopEntity($params{$key}, $limit{$key});
+                        $dat = strip_html($dat);
+                        $dat = balanceTags($dat, { deep_nesting => 2, length => $limit{$key} });
+                        $dat = addDomainTags($dat) if $dat;
+
+                        if ($key eq 'sig' && defined($dat) && length($dat) > 200) {
+                                $extr{sig} = undef;
+                        }
+
+                        if ((length($dat) > 1 && !filterOk('comments', 'postersubj', $dat, \$err_message)) ||
+                            (!compressOk('comments', 'postersubj', $dat))) {
+                                $extr{$key} = undef;
+                        }
+                        else {
+                                $extr{$key} = $dat;
+                        }
+                }
+
+                $user_edits_table = {
+                        homepage            => $homepage,
+                        realname            => $params{realname},
+                        calendar_url        => $calendar_url,
+                        yahoo               => $params{yahoo},
+                        jabber              => $params{jabber},
+                        aim                 => $params{aim},
+                        aimdisplay          => $params{aimdisplay},
+                        icq                 => $params{icq},
+                        playing             => $params{playing},
+                        mobile_text_address => $params{mobile_text_address},
+                };
+
+                for (keys %extr) {
+                        $user_edits_table->{$_} = $extr{$_} if defined $extr{$_};
+                }
+
+                for (keys %$user_edits_table) {
+                        $user_edits_table->{$_} = '' unless defined $user_edits_table->{$_};
+                }
+
+                if ($user_edit->{realemail} ne $params{realemail}) {
+                        $user_edits_table->{realemail} = chopEntity($params{realemail}, 50);
+                        my $new_fakeemail = '';
+
+                        if ($user->{emaildisplay}) {
+                                $new_fakeemail = getArmoredEmail($params{uid}, $user_edits_table->{realemail}) if $user->{emaildisplay} == 1;
+                                $new_fakeemail = $user_edits_table->{realemail} if $user->{emaildisplay} == 2;
+                        }
+                        $user_edits_table->{fakeemail} = $new_fakeemail;
+                }
+
+                my $reader = getObject('Slash::DB', { db_type => 'reader' });
+                my $otherparams  = $reader->getDescriptions('otherusersparam');
+                for my $param (keys %$otherparams) {
+                        if (exists $params{$param}) {
+                                $user_edits_table->{$param} = $user->{$param} = $params{$param} || undef;
+                        }
+                }
+        }
+
+        if ($params{'formname'} eq "sectional") {
+                setSectionNexusPrefs($slashdb, $constants, $user, \%params);
+        }
+        else {
+                $slashdb->setUser($params{uid}, $user_edits_table);
+        }
+        
 	$slashdb->setUser($params{uid}, $user_edits_table);
 }
 

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/admin.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/admin.js	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/admin.js	2007-12-06 09:17:47 UTC (rev 272)
@@ -180,6 +180,12 @@
 	ajax_periodic_update(secs, params, "storyadmin-content");
 }
 
+function admin_recenttagnamesbox_fetch(secs) {
+	var params = [];
+	params['op'] = 'admin_recenttagnamesbox';
+	ajax_periodic_update(secs, params, "recenttagnames-content");
+}
+
 function console_update(use_fh_interval, require_fh_timeout) {
 	use_fh_interval = use_fh_interval || 0;
 

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/common.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/common.js	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/common.js	2007-12-06 09:17:47 UTC (rev 272)
@@ -1451,7 +1451,7 @@
 		onComplete: function() {
 			hide_modal_box();
 			if (document.forms['modal_prefs'].refreshable.value)
-				document.location=document.forms['modal_prefs'].refreshable.value;
+				document.location=document.URL;
 		}
 	};
 	ajax_update(params, '', handlers);

Modified: slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js
===================================================================
--- slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Ajax/htdocs/images/sectionprefs.js	2007-12-06 09:17:47 UTC (rev 272)
@@ -17,12 +17,12 @@
 function masterChange(el) {
 	swapClassColors('secpref_master','secpref_nexus_row');
 	updateNexusAllTidPrefs(el);
-	postSectionPrefChanges(el);	
+	//postSectionPrefChanges(el);	
 }
 
 function individualChange(el) {
 	swapClassColors('secpref_nexus_row','secpref_master');
-	postSectionPrefChanges(el);	
+	//postSectionPrefChanges(el);	
 }
 
 function postSectionPrefChanges(el) {
@@ -50,7 +50,8 @@
 }
 
 function updateNexusAllTidPrefs(el) {
-	theForm = document.forms["sectionprefs"];
+	//theForm = document.forms["sectionprefs"];
+	theForm = document.forms["modal_prefs"];
 	for(i=0; i<theForm.elements.length; i++){
 		var regex = /^nexustid\d+$/;
 		if (regex.test(theForm.elements[i].name)) {

Modified: slashjp/trunk/plugins/Ajax/mysql_dump.sql
===================================================================
--- slashjp/trunk/plugins/Ajax/mysql_dump.sql	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Ajax/mysql_dump.sql	2007-12-06 09:17:47 UTC (rev 272)
@@ -162,6 +162,7 @@
 INSERT INTO ajax_ops VALUES (NULL, 'admin_storyadminbox', 'Slash::Admin', 'ajax_storyadminbox', 'ajax_admin', 'createuse');
 INSERT INTO ajax_ops VALUES (NULL, 'admin_authorbox', 'Slash::Admin', 'ajax_authorbox', 'ajax_admin', 'createuse');
 INSERT INTO ajax_ops VALUES (NULL, 'admin_perfbox', 'Slash::Admin', 'ajax_perfbox', 'ajax_admin', 'createuse');
+INSERT INTO ajax_ops VALUES (NULL, 'admin_recenttagnamesbox', 'Slash::Tags', 'ajax_recenttagnamesbox', 'ajax_admin', 'createuse');
 INSERT INTO ajax_ops VALUES (NULL, 'admin_learnword', 'Slash::Admin', 'admin_learnword', 'ajax_admin', 'createuse');
 
 

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_d2;ajax;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -24,7 +24,7 @@
 		IF user.discussion2 == 'slashdot';
 			d2_check = constants.markup_checked_attribute;
 		END %]
-		<label><input type="checkbox" name="discussion2"[% d2_check %] onclick="javascript:void(document.forms['modal_prefs'].refreshable.value=document.URL);">&nbsp;Enable Dynamic Discussions</label>
+		<label><input type="checkbox" name="discussion2"[% d2_check %] onclick="javascript:void(document.forms['modal_prefs'].refreshable.value=1);">&nbsp;Enable Dynamic Discussions</label>
 
 		&nbsp;<p>
 

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_d2_posting;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_d2_posting;ajax;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_d2_posting;ajax;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -47,15 +47,6 @@
         <input type="radio" name="emaildisplay" [% emaildisplay.2 %] value=2> Show your real email address without cowering behind childish anonymity or obfuscation.
         </div></blockquote>
 
-	<b><a name="karma_bonus">Karma Bonus</a></b> (modifier assigned to posts where the user has good karma)<br>
-	[% karma_bonus = 0;
-	IF user.karma_bonus;
-		karma_bonus = user.karma_bonus;
-	END %]
-	[% Slash.createSelect('karma_bonus', range, karma_bonus, 1, 1) %]
-
-	&nbsp;<p>
-
 	[% IF user.karma > constants.goodkarma;
 		b_check = '';
 		IF user.nobonus;
@@ -63,19 +54,8 @@
 		END %]
 		<input type="hidden" name="nobonus_present" value="1">
 		<label><input type="checkbox" name="nobonus"[% b_check %]> No Karma Bonus</label>
-
-		&nbsp;<p>
 	[% END %]
 
-	<b><a name="subscriber_bonus">Subscriber Bonus</a></b> (modifier assigned to posts where the user was a subscriber)<br>
-	[% subscriber_bonus = 0;
-	IF user.subscriber_bonus;
-		subscriber_bonus = user.subscriber_bonus;
-        END %]
-	[% Slash.createSelect('subscriber_bonus', range, subscriber_bonus, 1, 1) %] 
-
-	&nbsp;<p>
-
 	[% IF user.is_subscriber;
 		sb_check = '';
 		IF user.nosubscriberbonus;

Modified: slashjp/trunk/plugins/Ajax/templates/prefs_messages;ajax;default
===================================================================
--- slashjp/trunk/plugins/Ajax/templates/prefs_messages;ajax;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Ajax/templates/prefs_messages;ajax;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -12,8 +12,6 @@
 __name__
 prefs_messages
 __template__
-<div id="users-blocks">
-	<div class="generalbody">
 		[%
 		   usernick = user.nickname | strip_literal;
 
@@ -22,6 +20,8 @@
 		   modeweb  = Slash.MSG_MODE_WEB;
 		%]
 
+                &nbsp;<br>
+
 		From this page you can configure various messages that [% constants.sitename %] can optionally send to you. The primary options are [% deliverymodes.$modenone %] (Disabled), [% deliverymodes.$modemail %], [% deliverymodes.$modeweb %], [% IF constants.im_screenname %]AIM,[% END %] and Mobile Text. Not all options are available for all message types.  [% deliverymodes.$modeweb %] messages <b>will be deleted</b> after <b>[% constants.message_web_expire || 31 %] days</b>.[% IF constants.im_screenname %] If you plan on receiving AIM messages, please add [% constants.im_screenname %] to your buddylist.[% END %]
 
 	&nbsp;<p>
@@ -91,8 +91,6 @@
 	<input type="hidden" name="formname" value="messages">
 	<input type="button" value="Save" onclick="saveModalPrefs()">
 	</form>
-	</div>
-</div>
 __seclev__
 500
 __version__

Copied: slashjp/trunk/plugins/Ajax/templates/prefs_sectional;ajax;default (from rev 269, slashjp/branches/upstream/current/plugins/Ajax/templates/prefs_sectional;ajax;default)

Copied: slashjp/trunk/plugins/Ajax/templates/prefs_user;ajax;default (from rev 269, slashjp/branches/upstream/current/plugins/Ajax/templates/prefs_user;ajax;default)

Modified: slashjp/trunk/plugins/Console/Console.pm
===================================================================
--- slashjp/trunk/plugins/Console/Console.pm	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Console/Console.pm	2007-12-06 09:17:47 UTC (rev 272)
@@ -46,6 +46,9 @@
 	$html->{'slashdbox-content'}	= $admindb->showSlashdBox({ contents_only => 1});
 	$html->{'performancebox-content'}	= $admindb->showPerformanceBox({ contents_only => 1});
 	$html->{'authoractivity-content'}	= $admindb->showAuthorActivityBox({ contents_only => 1});
+	if (my $tagsdb = getObject('Slash::Tags')) {
+		$html->{'recenttagnames-content'} = $tagsdb->showRecentTagnamesBox({ contents_only => 1 });
+	}
 	return Data::JavaScript::Anon->anon_dump({
 		html	=> 	$html
 	});

Modified: slashjp/trunk/plugins/Console/console.pl
===================================================================
--- slashjp/trunk/plugins/Console/console.pl	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Console/console.pl	2007-12-06 09:17:47 UTC (rev 272)
@@ -60,18 +60,24 @@
 	my $firehosebox = "";
 	if ($constants->{plugin}{FireHose}) {
 		my $firehose = getObject("Slash::FireHose");
-		$user->{state}{firehose_page} = "console";
+		local $user->{state}{firehose_page} = 'console';
 		$firehosebox = $firehose->listView({ fh_page => 'console.pl'});
 	}
+	my $tagnamesbox = '';
+	my $tags = getObject('Slash::Tags');
+	if ($tags) {
+		my $rtoi_ar = $tags->getRecentTagnamesOfInterest();
+		$tagnamesbox = $tags->showRecentTagnamesBox();
+	}
 
-
 	slashDisplay('display', {
 		remarks 	=> $remarkstext,
 		storyadmin 	=> $storyadmin,
 		slashdbox 	=> $slashdbox,
 		perfbox		=> $perfbox,
 		authorbox	=> $authorbox,
-		firehosebox	=> $firehosebox
+		firehosebox	=> $firehosebox,
+		tagnamesbox	=> $tagnamesbox,
 	});
 
 }

Modified: slashjp/trunk/plugins/Console/templates/display;console;default
===================================================================
--- slashjp/trunk/plugins/Console/templates/display;console;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Console/templates/display;console;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -17,6 +17,7 @@
 	[% perfbox %]
 	[% Slash.sidebox("Firehose Usage", ' ', "firehose_usage", 1) %]
 	[% slashdbox %]
+	[% tagnamesbox %]
 </div>
 <div id="console">
 	[% remarks %]

Modified: slashjp/trunk/plugins/FAQSlashdot/faq/tags.shtml
===================================================================
--- slashjp/trunk/plugins/FAQSlashdot/faq/tags.shtml	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/FAQSlashdot/faq/tags.shtml	2007-12-06 09:17:47 UTC (rev 272)
@@ -40,7 +40,7 @@
 multiple tags. Use "bigbrother", not "big brother".
 <li>For the <b>opposite</b> of a tag, prefix it with "!", e.g.  "!funny"
 means "not funny."</li>
-<li>Keep your tags brief.</li>
+<li>Keep your tags brief. No full sentences. Tags are not comments.</li>
 <li>We provide a few example tags for you. Use them if you like.</li>
 <li>Don't forget to click 'Tag' to save your tags.</li>
 <li>After you save, your current list of tags is put back into the
@@ -50,7 +50,8 @@
 <li>Tags must be all-lowercase, no punctuation. Numbers can  
 appear but can't be first. Smoosh them up: for "Web 2.0", tag  
 "web20". Max 64 chars.</li>
-<li>Avoid plurals when possible: "harddrive", not "harddrives".</li>
+<li>Avoid plurals when possible: "harddrive", not "harddrives".
+But sometimes singular would be silly: "starwars".</li>
 </ul>
 
 <p>We're excited about this, and see huge potential for this system.
@@ -60,7 +61,7 @@
 
 <p><i><font size=-1>Answered by: <a  
 href="mailto:malda****@slash*****">CmdrTaco</a></font></i>
-<br><i><font size=-1>Last Modified: 11/02/06</font></i>
+<br><i><font size=-1>Last Modified: 11/22/07</font></i>
 
 
 
@@ -115,11 +116,13 @@
 grammatical errors, or bad HTML like a malformed link. Do not tag
 the story with the misspelled word in question.</p>
 
-<p>These tags will alert us to problems immediately (but they won't show
-up on the top tags list).</p>
+<p>These tags will alert us to problems immediately, which we love!
+But they won't show up on the top tags list. Trying to get around this
+with similarly spelled (but system-meaningless) tags like "dupitydupe"
+is discouraged.</p>
 
 <p><i><font size=-1>Answered by: <a href="mailto:malda****@slash*****">CmdrTaco</a></font></i>
-<br><i><font size=-1>Last Modified: 11/02/06</font></i>
+<br><i><font size=-1>Last Modified: 11/22/07</font></i>
 
 
 <br><a name="tags300" id="tags300"></a>

Modified: slashjp/trunk/plugins/FireHose/FireHose.pm
===================================================================
--- slashjp/trunk/plugins/FireHose/FireHose.pm	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/FireHose/FireHose.pm	2007-12-06 09:17:47 UTC (rev 272)
@@ -36,7 +36,6 @@
 use POSIX qw(ceil);
 use LWP::UserAgent;
 use URI;
-use XML::Simple;
 
 use base 'Slash::DB::Utility';
 use base 'Slash::DB::MySQL';
@@ -613,7 +612,15 @@
 
 #print STDERR "[\nSELECT $columns\nFROM   $tables\nWHERE  $where\n$other\n]\n";
 	my $hr_ar = $self->sqlSelectAllHashrefArray($columns, $tables, $where, $other);
-	my $count = $self->sqlSelect("count(*)", $tables, $where, $count_other);
+	my $count;
+	if ($options->{tagged_by_uid}) {
+		my $rows = $self->sqlSelectAllHashrefArray("count(*)", $tables, $where, $count_other);
+		$count = @$rows;
+	} else {
+		$count = $self->sqlSelect("count(*)", $tables, $where, $count_other);
+	}
+
+
 	my $page_size = $options->{limit} || 1;
 	$results->{records_pages} ||= ceil($count / $page_size);
 	$results->{records_page}  ||= (int(($options->{offset} || 0) / $options->{limit}) + 1) || 1;
@@ -648,7 +655,6 @@
 
 		$items = $hr_ar;
 	}
-
 	return($items, $results, $count);
 }
 
@@ -782,7 +788,7 @@
 
 sub itemHasSpamURL {
 	my($self, $item) = @_;
-	my @spamurlregexes = grep { $_ } split /\s+/, ($self->getBlock('spamurlregexes') || '');
+	my @spamurlregexes = grep { $_ } split /\s+/, ($self->getBlock('spamurlregexes', 'block') || '');
 	return 0 unless @spamurlregexes;
 	my @urls = $self->getURLsForItem($item);
 	for my $url (@urls) {
@@ -1392,9 +1398,6 @@
 		$accepted_from_ipid = $slashdb->countSubmissionsFromIPID($item->{ipid}, { del => 2});
 	}
 
-	my $yoogli_similar_stories = 0;
-	$yoogli_similar_stories = $firehose->getYoogliSimilarForItem($item) if $constants->{yoogli_oai_search};
-
 	my $the_user = $slashdb->getUser($item->{uid});
 
 	my $byline = getData("byline", {
@@ -1415,7 +1418,6 @@
 		item				=> $item,
 		subnotes_ref			=> $subnotes_ref,
 		similar_stories			=> $similar_stories,
-		yoogli_similar_stories          => $yoogli_similar_stories,
 	}, { Return => 1 });
 
 	return Data::JavaScript::Anon->anon_dump({
@@ -1590,43 +1592,6 @@
 	return $similar_stories;
 }
 
-sub getYoogliSimilarForItem {
-	my($self, $item) = @_;
-
-	my $user = getCurrentUser();
-	my $constants = getCurrentStatic();
-	return 0 unless $user->{is_admin} && $constants->{yoogli_oai_query_base} && $constants->{yoogli_oai_result_count};
-
-	my $query = $constants->{yoogli_oai_query_base} .= '?verb=GetRecord&metadataPrefix=oai_dc&rescount=';
-	$query .= $constants->{yoogli_oai_result_count} . '&identifier=' . URI->new($item->{introtext});
-	my $yoogli_similar_stories = {};
-
-	my $ua = new LWP::UserAgent;
-	# Timeout is set to the number of responses we're expecting +1 for wiggle room.
-	$ua->timeout($constants->{yoogli_oai_result_count} + 2);
-	my $req = new HTTP::Request GET => $query;
-	my $res = $ua->request($req);
-	if ($res->is_success) {
-		my $xml = new XML::Simple;
-		my $content = eval { $xml->XMLin($res->content) };
-		unless ($@) {
-			my $reader = getObject("Slash::DB", { db_type => "reader" });
-			my $sid_regex = regexSid();
-			foreach my $metadata (@{$content->{'GetRecord'}{'record'}}) {
-                                next if $metadata->{'metadata'}{'title'} eq $item->{title};
-				my $key = $metadata->{'header'}{'identifier'};
-				my($sid) = $metadata->{'metadata'}{'identifier'} =~ $sid_regex;
-				$yoogli_similar_stories->{$key}{'date'}  = $reader->getStory($sid, 'time');
-				$yoogli_similar_stories->{$key}{'url'}   = $metadata->{'metadata'}{'identifier'};
-				$yoogli_similar_stories->{$key}{'title'} = $metadata->{'metadata'}{'title'};
-				$yoogli_similar_stories->{$key}{'relevance'} = $metadata->{'metadata'}{'relevance'};
-			}
-		}
-	}
-
-	return $yoogli_similar_stories;
-}
-
 sub getAndSetOptions {
 	my($self, $opts) = @_;
 	my $user 	= getCurrentUser();
@@ -1670,7 +1635,6 @@
 			$self->setUser($user->{uid}, { firehose_paused => $options->{pause} });
 		}
 	}
-
 	if (defined $form->{duration}) {
 		if ($form->{duration} =~ /^-?\d+$/) {
 			$options->{duration} = $form->{duration};
@@ -1700,7 +1664,6 @@
 	
 
 	my $colors = $self->getFireHoseColors();
-
 	if ($form->{color} && $colors->{$form->{color}}) {
 		$options->{color} = $form->{color};
 	}
@@ -1748,9 +1711,9 @@
 	# XXX
 	my $user_tabs = $self->getUserTabs();
 	my %user_tab_names = map { $_->{tabname} => 1 } @$user_tabs;
-	my %firehose_tabs_given = map { $_ => 1 } split (/\|/, $user->{firehose_tabs_given});
+	my $tabs_given = $user->{firehose_tabs_given} || '';
+	my %firehose_tabs_given = map { $_ => 1 } split (/\|/, $tabs_given);
 	my @tab_fields = qw(tabname filter mode color orderdir orderby);
-	my $tabs_given = $user->{firehose_tabs_given};
 
 	my $system_tabs = $self->getSystemDefaultTabs();
 	foreach my $tab (@$system_tabs) {
@@ -1876,11 +1839,7 @@
 	# ...for which we'll have fewer items per page
 	if ($force_smaller) {
 		$options->{smalldevices} = 1;
-		if ($mode eq "full") {
-			$options->{limit} = $pagesize eq "large" ? 15 : 10;
-		} else {
-			$options->{limit} = $pagesize eq "large" ? 20 : 15;
-		}
+		$options->{limit} = 10;
 	}
 
 	if ($user->{is_admin} && $form->{setusermode}) {
@@ -2060,7 +2019,6 @@
 		$options->{duration} = 1;
 	}
 
-
 	return $options;
 }
 

Modified: slashjp/trunk/plugins/FireHose/firehose.css
===================================================================
--- slashjp/trunk/plugins/FireHose/firehose.css	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/FireHose/firehose.css	2007-12-06 09:17:47 UTC (rev 272)
@@ -451,4 +451,4 @@
 .briefarticle .storylinks .comments a:hover {background:transparent url('//images.slashdot.org/sic_icons.png') no-repeat scroll 0px -1498px; color: #fff !important}
 .briefarticle .storylinks .comments.nocomment, .briefarticle .storylinks .comments span  {display: none}
 
-.embed .paginate, .embed .firemenu, .embed + .copyright { display: none; }
+.embed .paginate, .embed .firemenu, .embed a.skin, .copyright.embed { display: none; }

Modified: slashjp/trunk/plugins/FireHose/firehose.pl
===================================================================
--- slashjp/trunk/plugins/FireHose/firehose.pl	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/FireHose/firehose.pl	2007-12-06 09:17:47 UTC (rev 272)
@@ -65,7 +65,8 @@
 			$redirect = 0;
 		} 
 		if ($redirect) {
-			redirect("$gSkin->{rootdir}/firehose.shtml");
+			my $prefix = $form->{embed} ? "embed_" : "";
+			redirect("$gSkin->{rootdir}/${prefix}firehose.shtml");
 			return;
 		}
 	}

Modified: slashjp/trunk/plugins/FireHose/templates/admin_extras;misc;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/admin_extras;misc;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/FireHose/templates/admin_extras;misc;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -40,7 +40,7 @@
         </tr>
 </table>
 </form>
-[% IF similar_stories.size > 0 or yoogli_similar_stories %]
+[% IF similar_stories.size > 0 %]
 	<table border="0" cellpadding="2" cellspacing="0" class="data">
 		<tr class="data_head"><td><b>Similar Stories</b></td></tr>
 		[% FOREACH story = similar_stories %]
@@ -64,16 +64,6 @@
 			</td>
 			</tr>
 		[% END %]
-                [% FOREACH story = yoogli_similar_stories.keys.sort %]
-                        <tr>
-                        <td>&nbsp;</td>
-                        <td>Y=[% yoogli_similar_stories.$story.relevance.substr(0, 4) %]</td>
-                        <td valign="TOP"><a href="[% yoogli_similar_stories.$story.url %]" title="[% yoogli_similar_stories.$story.title %]">
-                        [% yoogli_similar_stories.$story.title.substr(0, 35) %]...</a></td>
-                        <td valign="TOP">[% Slash.timeCalc(yoogli_similar_stories.$story.date, "%Y-%m-%d") %]</td>
-                        <td>&nbsp;</td>
-                        </tr>
-                [% END %]
 	</table>
 [% END %]
 __version__

Modified: slashjp/trunk/plugins/FireHose/templates/list;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/list;firehose;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/FireHose/templates/list;firehose;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -132,7 +132,7 @@
 [% END %]
 </div>
 </div>
-[% IF !user.is_admin || (user.is_admin && user.firehose_usermode ) %]
+[% IF !form.embed && (!user.is_admin || (user.is_admin && user.firehose_usermode )) %]
 <p style="padding: 1em 1em 0 1em">
 The Slashdot Firehose is a collaborative system designed to allow
 users to assist our editors in the story selection process.  The hose

Modified: slashjp/trunk/plugins/FireHose/templates/nodnix_menus;firehose;default
===================================================================
--- slashjp/trunk/plugins/FireHose/templates/nodnix_menus;firehose;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/FireHose/templates/nodnix_menus;firehose;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -19,6 +19,7 @@
   <div class="menu" onmouseover="dont_hide_nodnix_menu()" onmouseout="hide_nodnix_menu(750)" onmousedown="hide_nodnix_menu()">
     <ul>
       <li title="Tag this item 'interesting', voting it up" onmousedown="nodnix_tag('interesting', '+')">interesting</li>
+      <li title="Tag this item 'fresh', voting it up" onmousedown="nodnix_tag('fresh', '+')">fresh</li>
       <li title="Tag this item 'funny', voting it up" onmousedown="nodnix_tag('funny', '+')">funny</li>
       <li title="Tag this item 'insightful', voting it up" onmousedown="nodnix_tag('insightful', '+')">insightful</li>
     </ul>
@@ -33,6 +34,7 @@
       <li title="Tag this item 'offtopic', voting it down" onmousedown="nodnix_tag('offtopic', '-')">offtopic</li>
       <li title="Tag this item 'stupid', voting it down" onmousedown="nodnix_tag('stupid', '-')">stupid</li>
       <li title="Tag this item 'slownewsday', voting it down" onmousedown="nodnix_tag('slownewsday', '-')">slownewsday</li>
+      <li title="Tag this item 'stale', voting it down" onmousedown="nodnix_tag('stale', '-')">stale</li>
     </ul>
   </div>
 </div>

Modified: slashjp/trunk/plugins/Stats/Stats.pm
===================================================================
--- slashjp/trunk/plugins/Stats/Stats.pm	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Stats/Stats.pm	2007-12-06 09:17:47 UTC (rev 272)
@@ -1670,11 +1670,54 @@
 	return $self->sqlSelectAll(
 		"DISTINCT SUBSTRING_INDEX(referer,'/',3) AS referer, COUNT(id) AS c",
 		"accesslog_temp",
-		"referer IS NOT NULL AND LENGTH(referer) > 0 AND referer LIKE 'http%' $where ",
+		"op != 'slashdot-it'
+		 AND referer IS NOT NULL AND LENGTH(referer) > 0 AND referer LIKE 'http%'
+		 $where",
 		"GROUP BY referer ORDER BY c DESC, referer LIMIT $count"
 	);
 }
 
+sub getTopBadgeURLs {
+	my($self, $options) = @_;
+	# This is Slashdot-specific.  It won't make much sense for any
+	# other site to use it.
+	my $constants = getCurrentStatic();
+	return [ ] unless $constants->{basedomain} eq 'slashdot.org';
+
+	my $count = $options->{count} || 10;
+	my $top_ar = $self->sqlSelectAll(
+		"query_string AS qs, COUNT(*) AS c",
+		"accesslog_temp",
+		"op='slashdot-it'",
+		"GROUP BY qs ORDER BY c DESC, qs LIMIT $count"
+	);
+	for my $duple (@$top_ar) {
+		my($qs, $c) = @$duple;
+		$qs =~ s/^.*url=//;
+		$qs =~ s/\%[a-fA-F0-9]?$//;
+		$qs =~ s/%([a-fA-F0-9]{2})/pack('C', hex($1))/ge;
+		$duple = [$qs, $c];
+	}
+	return $top_ar;
+}
+
+sub getTopBadgeHosts {
+	my($self, $options) = @_;
+	my $count = $options->{count} || 10;
+	my $url_count = $count * 20;
+	my $top_ar = $self->getTopBadgeURLs({ count => $url_count });
+	my %count = ( );
+	for my $duple (@$top_ar) {
+		my($uri, $c) = @$duple;
+		my $host = URI->new($uri)->host();
+		$count{$host} += $c;
+	}
+	my @top_hosts = (sort { $count{$b} <=> $count{$a} || $a <=> $b } keys %count);
+	$#top_hosts = $count-1 if scalar @top_hosts > $count;
+	my @top = ( map { [ $_, $count{$_} ] } @top_hosts );
+	return \@top;
+}
+
 ########################################################
 sub countSfNetIssues {
 	my($self, $group_id) = @_;

Modified: slashjp/trunk/plugins/Stats/adminmail.pl
===================================================================
--- slashjp/trunk/plugins/Stats/adminmail.pl	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Stats/adminmail.pl	2007-12-06 09:17:47 UTC (rev 272)
@@ -819,6 +819,8 @@
 	}
 
 	$data{top_referers} = $logdb->getTopReferers({count => 20});
+	$data{top_badgehosts} = $logdb->getTopBadgeHosts({count => 20});
+	$data{top_badgeurls} = $logdb->getTopBadgeURLs({count => 20});
 
 	my $new_users_yest = $slashdb->getNumNewUsersSinceDaysback(1)
 		- $slashdb->getNumNewUsersSinceDaysback(0);

Modified: slashjp/trunk/plugins/Stats/templates/display;adminmail;default
===================================================================
--- slashjp/trunk/plugins/Stats/templates/display;adminmail;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Stats/templates/display;adminmail;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -164,6 +164,24 @@
 [% END %]
 [% END %]
 
+[% IF top_badgehosts.size %]
+-----------------------      
+
+Top badge hosts:
+[% FOREACH badgehost = top_badgehosts -%]
+[% badgehost.1 %]  [% badgehost.0 %]
+[% END %]
+[% END %]
+
+[% IF top_badgeurls.size %]
+-----------------------      
+
+Top badge URLs:
+[% FOREACH badgeurl = top_badgeurls -%]
+[% badgeurl.1 %]  [% badgeurl.0 %]
+[% END %]
+[% END %]
+
 [% IF errors.size -%]
 -----------------------      
 Error count by Page:

Modified: slashjp/trunk/plugins/Tags/Clout/Describe.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Clout/Describe.pm	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Tags/Clout/Describe.pm	2007-12-06 09:17:47 UTC (rev 272)
@@ -62,7 +62,9 @@
 		 sourcetag.tagnameid,
 		 sourcetag.globjid,
 		 gtid",
-		"tags AS sourcetag, globjs, tags_peerclout AS sourcetpc, users_info,
+		"tags AS sourcetag,
+		 tagname_params AS tagparam,
+		 globjs, tags_peerclout AS sourcetpc, users_info,
 		 tags AS newtag LEFT JOIN tags_peerclout AS newtpc USING (uid)",
 		"sourcetag.inactivated IS NULL
 		 AND sourcetag.globjid=globjs.globjid
@@ -70,7 +72,8 @@
 		 AND sourcetpc.clid=$self->{clid}
 		 AND sourcetag.globjid=newtag.globjid
 		 AND sourcetag.tagnameid=newtag.tagnameid
-		 AND sourcetag.tagnameid NOT IN ($self->{nodid}, $self->{nixid})
+			AND sourcetag.tagnameid=tagparam.tagnameid
+			AND tagparam.name='descriptive'
 		 AND sourcetag.tagid != newtag.tagid
 		 AND newtag.created_at >= DATE_SUB(NOW(), INTERVAL $self->{months_back} MONTH)
 		 AND newtag.uid=users_info.uid
@@ -271,10 +274,10 @@
 	my $total = $w_pos_mag+$w_neg_mag;
 	if ($w_pos_mag > $total * 0.60) {
 		my $neg_reduc_factor = $w_neg_mag*3/$w_pos_mag;
-		@ret = map { $_ < 0 ? $_*$neg_reduc_factor : $_ } @_;
+		@ret = map { $_ < 0 ? $_*$neg_reduc_factor : $_ } @w;
 	} elsif ($w_neg_mag > $total * 0.60) {
 		my $pos_reduc_factor = $w_pos_mag*3/$w_neg_mag;
-		@ret = map { $_ > 0 ? $_*$pos_reduc_factor : $_ } @_;
+		@ret = map { $_ > 0 ? $_*$pos_reduc_factor : $_ } @w;
 	} else {
 		# No change.
 		@ret = @w;

Modified: slashjp/trunk/plugins/Tags/Clout.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Clout.pm	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Tags/Clout.pm	2007-12-06 09:17:47 UTC (rev 272)
@@ -39,30 +39,5 @@
 	1;
 }
 
-#sub insert_nextgen {
-#        my($g, $insert_ar) = @_;
-#        my $slashdb = getCurrentDB();
-#        for my $hr (@$insert_ar) {
-#                $hr->{gen} = $g; 
-#                $slashdb->sqlInsert('tags_peerweight', $hr);
-#        }
-#}       
-#        
-#sub update_tags_peerweight {
-#        my($insert_ar) = @_;
-#        for my $hr (@$insert_ar) {
-#                $tags_peerweight->{ $hr->{uid} } = $hr->{weight}; 
-#        } 
-#}               
-#                
-#sub B_copy_peerweight_sql {
-#        my $slashdb = getCurrentDB();
-#        $slashdb->sqlDo("SET AUTOCOMMIT=0");
-#        $slashdb->sqlDo("DELETE FROM users_param WHERE name='tagpeerval2'");
-#        $slashdb->sqlDo("INSERT INTO users_param SELECT NULL, uid, 'tagpeerval2', ROUND(weight,6)+0 FROM tags_peerweight");
-#        $slashdb->sqlDo("COMMIT");
-#        $slashdb->sqlDo("SET AUTOCOMMIT=1");
-#}
-
 1;
 

Modified: slashjp/trunk/plugins/Tags/PLUGIN
===================================================================
--- slashjp/trunk/plugins/Tags/PLUGIN	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Tags/PLUGIN	2007-12-06 09:17:47 UTC (rev 272)
@@ -10,6 +10,7 @@
 task=tags_updateclouts.pl
 template=templates/data;tags;default
 template=templates/index;tags;default
+template=templates/recenttagnamesbox;misc;default
 template=templates/tagsstorydivadmin;misc;default
 template=templates/tagsstorydivtagbox;misc;default
 template=templates/tagsurldivtagbox;misc;default

Modified: slashjp/trunk/plugins/Tags/Tagbox.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Tagbox.pm	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Tags/Tagbox.pm	2007-12-06 09:17:47 UTC (rev 272)
@@ -287,6 +287,20 @@
 	return $self->sqlInsert('tagboxlog_feeder', $info_hr);
 }
 
+sub forceFeederRecalc {
+	my($self, $tbid, $affected_id) = @_;
+	my $info_hr = {
+		-created_at =>	'NOW()',
+		tbid =>		$tbid,
+		affected_id =>	$affected_id,
+		importance =>	9999,
+		tagid =>	0,
+		tdid =>		0,
+		tuid =>		0,
+	};
+	return $self->sqlInsert('tagboxlog_feeder', $info_hr);
+}
+
 sub markTagboxLogged {
 	my($self, $tbid, $update_hr) = @_;
 	$self->sqlUpdate('tagboxes', $update_hr, "tbid=$tbid");

Modified: slashjp/trunk/plugins/Tags/Tags.pm
===================================================================
--- slashjp/trunk/plugins/Tags/Tags.pm	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Tags/Tags.pm	2007-12-06 09:17:47 UTC (rev 272)
@@ -364,22 +364,41 @@
 	my($self, $id, $params) = @_;
 	return 0 if !$id || !$params || !%$params;
 
+	my $tagboxdb = getObject("Slash::Tagbox");
+	my @feeder = ( );
+	my $tagboxes = $tagboxdb->getTagboxes();
+	my($globjid, $uid) = $self->sqlSelect('globjid, uid', 'tags', "tagid=$id");
+
 	my $changed = 0;
 	for my $key (sort keys %$params) {
 		next if $key =~ /^(tagid|tagname|tagnameid|globjid|uid|created_at|inactivated|private)$/; # don't get to override existing fields
 		my $value = $params->{$key};
+		my $this_changed = 0;
 		if (defined($value) && length($value)) {
-			$changed = 1 if $self->sqlReplace('tag_params', {
+			$this_changed = 1 if $self->sqlReplace('tag_params', {
 				tagid =>	$id,
 				name =>		$key,
 				value =>	$value,
 			});
 		} else {
 			my $key_q = $self->sqlQuote($key);
-			$changed = 1 if $self->sqlDelete('tag_params',
+			$this_changed = 1 if $self->sqlDelete('tag_params',
 				"tagid = $id AND name = $key_q"
 			);
 		}
+		if ($this_changed) {
+			for my $tagbox_hr (@$tagboxes) {
+				my $tbid = $tagbox_hr->{tbid};
+				my $affected = $tagbox_hr->{affected_type} eq 'user'
+					? $uid : $globjid;
+				$tagboxdb->addFeederInfo($tbid, {
+					affected_id =>	$affected,
+					importance =>	1,
+					tagid =>	$id,
+				});
+			}
+		}
+		$changed ||= $this_changed;
 	}
 
 	if ($changed) {
@@ -1126,6 +1145,14 @@
 		$tags->processAdminCommand($c, $id, $table);
 	}
 
+	my $globjid = $tags_reader->getGlobjidFromTargetIfExists($table, $id);
+	my $tagboxdb = getObject('Slash::Tagbox');
+	my $tagboxes = $tagboxdb->getTagboxes();
+	for my $tagbox_hr (@$tagboxes) {
+		next if $tagbox_hr->{affected_type} eq 'user';
+		$tagboxdb->forceFeederRecalc($tagbox_hr->{tbid}, $globjid);
+	}
+
 	my $tags_admin_str = "Performed commands: '@commands'.";
 	if ($type eq "stories") {
 		return slashDisplay('tagsstorydivadmin', {
@@ -1153,17 +1180,23 @@
 		$_adcmd_prefix{0} = '_';
 		for my $i (1..5) { $_adcmd_prefix{$i} = '#' x $i }
 	}
+	my @new = ( );
 	my %count = ( );
 	for my $c (@commands) {
 		my($type, $tagname) = $self->getTypeAndTagnameFromAdminCommand($c);
 		next unless $type;
+		if ($type !~ /$(_|#+)/) {
+			push @new, $c;
+			next;
+		}
 		my $count = $type =~ tr/#/#/;
 		$count{$tagname} ||= 0;
 		$count{$tagname} = $count if $count{$tagname} < $count;
 		my $opp = $self->getOppositeTagname($tagname);
 		$count{$opp} ||= 0;
 	}
-	my @new = ( map { $_adcmd_prefix{$count{$_}} . $_ } sort keys %count );
+	
+	push @new, ( map { $_adcmd_prefix{$count{$_}} . $_ } sort keys %count );
 	return @new;
 }
 }
@@ -1291,8 +1324,17 @@
 
 	my $new_min_tagid = 0;
 
-#print STDERR "type '$type' for c '$c' new_clout '$new_user_clout' for table $table id $id\n";
-	if ($type eq '^') {
+print STDERR "type '$type' for c '$c' new_clout '$new_user_clout' for table $table id $id\n";
+	if ($type eq '+') {
+		# Plus sign means admin is saying this tagname is "OK",
+		# which (at least so far, 2007/12) means it is not
+		# malicious or stupid or pointless or etc.
+		$self->setTagname($tagnameid, { admin_ok => 1 });
+	} elsif ($type eq ')') {
+		# Right-paren means admin is labelling this tagname as
+		# descriptive.  Mnemonic: ")" looks like "D"
+		$self->setTagname($tagnameid, { descriptive => 1 });
+	} elsif ($type eq '^') {
 		# Set individual clouts to 0 for tags of this name on
 		# this story that have already been applied.  Future
 		# tags of this name on this story will apply with
@@ -1369,7 +1411,7 @@
 
 sub getTypeAndTagnameFromAdminCommand {
 	my($self, $c) = @_;
-	my($type, $tagname) = $c =~ /^(\^|\$?\_|\$?\#{1,5})(.+)$/;
+	my($type, $tagname) = $c =~ /^(\^|\+|\)|\$?\_|\$?\#{1,5})(.+)$/;
 #print STDERR scalar(gmtime) . " get c '$c' type='$type' tagname='$tagname'\n";
 	return (undef, undef) if !$type || !$self->tagnameSyntaxOK($tagname);
 	return($type, $tagname);
@@ -1407,7 +1449,7 @@
 # are all the opposites of at least one of the inputs.
 
 sub getOppositeTagnameids {
-	my($self, $data) = @_;
+	my($self, $data, $create) = @_;
 
 	my @tagnameids = ( );
 	$data = [ $data ] if !ref($data);
@@ -1434,7 +1476,15 @@
 	# Type one:
 	my @tagnames =		map { $self->getTagnameDataFromId($_)->{tagname} }	@tagnameids;
 	my @opp_tagnames =	map { $self->getOppositeTagname($_) }			@tagnames;
-	my @opp_tagnameids_1 =	map { $self->getTagnameidCreate($_) }			@opp_tagnames;
+	my @opp_tagnameids_1 =	( );
+	if ($create) {
+		@opp_tagnameids_1 =
+				map { $self->getTagnameidCreate($_) }			@opp_tagnames;
+	} else {
+		@opp_tagnameids_1 =
+				grep { $_ }
+				map { $self->getTagnameidFromNameIfExists($_) }		@opp_tagnames;
+	}
 	# Type two:
 	my $src_tnids_str = join(',', @tagnameids);
 	my $opp_tagnameids_2_ar = $self->sqlSelectColArrayref(
@@ -1685,6 +1735,161 @@
 	}, { ignore => 1, delayed => 1 });
 }
 
+sub getRecentTagnamesOfInterest {
+	my($self, $options) = @_;
+	my $max_num = $options->{max_num} || 10;
+	my $min_weight = $options->{min_weight} || 1;
+
+	# First, collect the list of all tagnames used recently.
+	my $secsback = $options->{secsback} || 12 * 3600;
+	my $tagname_recent_ar = $self->listTagnamesRecent({ seconds => $secsback });
+	# If none, short-circuit out.
+	return [ ] if !@$tagname_recent_ar;
+
+	# Get their tagnameids.
+	my $tagname_str = join(',', map { $self->sqlQuote($_) } sort @$tagname_recent_ar);
+	my $tagnameid_to_name = $self->sqlSelectAllKeyValue(
+		'tagnameid, tagname',
+		'tagnames',
+		"tagname IN ($tagname_str)");
+	my $tagnameid_str = join(',', map { $self->sqlQuote($_) } sort keys %$tagnameid_to_name);
+	my $tagname_to_id = { reverse %$tagnameid_to_name };
+
+	# Next, build a hash identifying which of those are new tagnames,
+	# i.e. which were used for the first time within the same recent
+	# time interval we're looking at.
+	my $tagname_firstrecent_ar = $self->sqlSelectColArrayref(
+		'tagname, MIN(created_at) AS firstuse',
+		'tagnames, tags',
+		"tagnames.tagnameid IN ($tagnameid_str)
+		 AND tagnames.tagnameid=tags.tagnameid",
+		"GROUP BY tagname
+		 HAVING firstuse >= DATE_SUB(NOW(), INTERVAL $secsback SECOND)");
+	my %tagname_firstrecent = ( map { ($_, 1) } @$tagname_firstrecent_ar );
+
+	# Build a regex that will identify tagnames that begin with an
+	# author's name, and a hash matching recent tagnames.
+	my $author_names = join('|', map { "\Q\L$_\E" } @{ $self->getAuthorNames() });
+	my $author_regex = qr{^($author_names)};
+	my %tagname_startauthor = ( map { ($_, 1) }
+		grep { $_ =~ $author_regex } @$tagname_recent_ar );
+
+	# Build a hash identifying those tagnames which have been
+	# marked by an admin, at any time, as being "ok."
+	my $tagnameid_ok_ar = $self->sqlSelectColArrayref(
+		'DISTINCT tagnameid',
+		'tagcommand_adminlog',
+		"tagnameid IN ($tagnameid_str)
+		 AND cmdtype='+'");
+	my %tagname_adminok = ( map { ($tagnameid_to_name->{$_}, 1) } @$tagnameid_ok_ar );
+
+	# Build a hash identifying those tagnames which have been
+	# marked by an admin, at any time, as being bad (# etc.).
+	my $tagnameid_bad_ar = $self->sqlSelectColArrayref(
+		'DISTINCT tagnameid',
+		'tagcommand_adminlog',
+		"tagnameid IN ($tagnameid_str)
+		 AND cmdtype REGEXP '#'");
+	my %tagname_bad = ( map { ($tagnameid_to_name->{$_}, 1) } @$tagnameid_bad_ar );
+
+	# Using the hashes, build a list of all recent tagnames which
+	# are of interest.
+	my @tagnames_of_interest = grep {
+		     $tagname_bad{$_}
+		||   $tagname_startauthor{$_}
+		|| ( $tagname_firstrecent{$_} && !$tagname_adminok{$_} )
+	} @$tagname_recent_ar;
+if (!@tagnames_of_interest) { use Data::Dumper; print STDERR "none interesting in '@$tagname_recent_ar', bad: " . Dumper(\%tagname_bad) . "startauthor: " . Dumper(\%tagname_startauthor) . "firstrecent: " . Dumper(\%tagname_firstrecent) . "adminok: " . Dumper(\%tagname_adminok); }
+	return [ ] if !@tagnames_of_interest;
+	my @tagnameids_of_interest = map { $tagname_to_id->{$_} } @tagnames_of_interest;
+	my $tagnameids_of_interest_str = join(',', map { $self->sqlQuote($_) }
+		sort @tagnameids_of_interest);
+
+	# Now sort the tagnames in order of the sum of their current
+	# weights.  Exclude those with sum weight 0, because there's
+	# no need for admins to evaluate those.
+	my $tags_ar = $self->sqlSelectAllHashrefArray(
+		'*',
+		'tags',
+		"tagnameid IN ($tagnameids_of_interest_str)
+		 AND created_at >= DATE_SUB(NOW(), INTERVAL $secsback SECOND)");
+	$self->addCloutsToTagArrayref($tags_ar, 'describe');
+	my %tagnameid_weightsum = ( );
+	my %t_globjid_weightsum = ( );
+	for my $tag_hr (@$tags_ar) {
+		my $tc = $tag_hr->{total_clout};
+		next unless $tc;
+		my $tagnameid = $tag_hr->{tagnameid};
+		my $globjid = $tag_hr->{globjid};
+		$tagnameid_weightsum{ $tagnameid } ||= 0;
+		$tagnameid_weightsum{ $tagnameid }  += $tc;
+		$t_globjid_weightsum{ $tagnameid }{ $globjid } ||= 0;
+		$t_globjid_weightsum{ $tagnameid }{ $globjid }  += $tc;
+	}
+	my @tagnameids_top =
+		sort { $tagnameid_weightsum{$b} <=> $tagnameid_weightsum{$a}
+			|| $b <=> $a }
+		grep { $tagnameid_weightsum{$_} >= $min_weight }
+		keys %tagnameid_weightsum;
+	$#tagnameids_top = $max_num-1 if $#tagnameids_top > $max_num;
+
+	# Now we just have to construct the data structure to return.
+	my @rtoi = ( );
+	my %globjid_linktext = ( );
+	my $linktext_next = 'a'; # label the links simply 'a', 'b', etc.
+	for my $tagnameid (@tagnameids_top) {
+		my @globjids =
+			sort { $t_globjid_weightsum{$tagnameid}{$b} <=> $t_globjid_weightsum{$tagnameid}{$a}
+				|| $b <=> $a }
+			keys %{$t_globjid_weightsum{$tagnameid}};
+		$#globjids = $max_num-1 if $#globjids > $max_num;
+		my @globjid_data = ( );
+		for my $globjid (@globjids) {
+			my $lt = $globjid_linktext{$globjid} || '';
+			if (!$lt) {
+				$lt = $globjid_linktext{$globjid} = $linktext_next;
+				++$linktext_next;
+			}
+			push @globjid_data, {
+				globjid => $globjid,
+				linktext => $lt,
+			};
+		}
+		$self->addGlobjEssentialsToHashrefArray(\@globjid_data);
+		push @rtoi, {
+			tagname =>	$tagnameid_to_name->{$tagnameid},
+			globjs =>	\@globjid_data,
+		};
+	}
+use Data::Dumper; print STDERR scalar(localtime) . " rtoi: " . Dumper(\@rtoi);
+
+	return \@rtoi;
+}
+
+sub showRecentTagnamesBox {
+	my($self, $options) = @_;
+	my $rtoi_ar = $self->getRecentTagnamesOfInterest($options);
+
+	my $text = slashDisplay('recenttagnamesbox', {
+		rtoi => $rtoi_ar,
+	}, { Return => 1 });
+
+	return $text if $options->{contents_only};
+
+	my $updater = getData('recenttagnamesbox_js', { }, 'tags') if $options->{updater};
+	slashDisplay('sidebox', {
+		updater		=> $updater,
+		title		=> 'Recent Tagnames',
+		contents	=> $text,
+		name		=> 'recenttagnames',
+	}, { Return => 1 });
+}
+
+sub ajax_recenttagnamesbox {
+	my $tagsdb = getObject("Slash::Tags");
+	$tagsdb->showRecentTagnamesBox({ contents_only => 1});
+}
+
 #################################################################
 sub DESTROY {
 	my($self) = @_;

Modified: slashjp/trunk/plugins/Tags/templates/data;tags;default
===================================================================
--- slashjp/trunk/plugins/Tags/templates/data;tags;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/plugins/Tags/templates/data;tags;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -42,6 +42,9 @@
 		<i>(none)</i>
 	[% END %]
 
+[% CASE 'recenttagnamesbox_js' %]
+	<script type="text/javascript">admin_recenttagnamesbox_fetch(60);</script>
+
 [% CASE 'error' %]
 	Sorry, an error occurred.
 	[% returnme.data_constant = 1 %] 

Copied: slashjp/trunk/plugins/Tags/templates/recenttagnamesbox;misc;default (from rev 269, slashjp/branches/upstream/current/plugins/Tags/templates/recenttagnamesbox;misc;default)

Modified: slashjp/trunk/sql/mysql/defaults.sql
===================================================================
--- slashjp/trunk/sql/mysql/defaults.sql	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/sql/mysql/defaults.sql	2007-12-06 09:17:47 UTC (rev 272)
@@ -832,7 +832,7 @@
 INSERT INTO vars (name, value, description) VALUES ('cur_performance_stats_lastid', '0', 'accesslogid to start searching at');
 INSERT INTO vars (name, value, description) VALUES ('cur_performance_stats_weeks', '8', 'number of weeks back to compare current stats to');
 INSERT INTO vars (name, value, description) VALUES ('currentqid',1,'The Current Question on the homepage pollbooth');
-INSERT INTO vars (name, value, description) VALUES ('cvs_tag_currentcode','T_2_5_0_184','The current cvs tag that the code was updated to - this does not affect site behavior but may be useful for your records');
+INSERT INTO vars (name, value, description) VALUES ('cvs_tag_currentcode','T_2_5_0_186','The current cvs tag that the code was updated to - this does not affect site behavior but may be useful for your records');
 INSERT INTO vars (name, value, description) VALUES ('datadir','/usr/local/slash/www.example.com','What is the root of the install for Slash');
 INSERT INTO vars (name, value, description) VALUES ('db_auto_increment_increment','1','If your master DB uses auto_increment_increment, i.e. multiple master replication, echo its value into this var');
 INSERT INTO vars (name, value, description) VALUES ('dbsparklines_disp','0','Display dbsparklines in the currentAdminUsers box?');

Modified: slashjp/trunk/sql/mysql/upgrades
===================================================================
--- slashjp/trunk/sql/mysql/upgrades	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/sql/mysql/upgrades	2007-12-06 09:17:47 UTC (rev 272)
@@ -4963,8 +4963,6 @@
 # 2007-10-25
 UPDATE vars SET value = 'T_2_5_0_181' WHERE name = 'cvs_tag_currentcode';
 
-# PUDGE LAST UPDATED HERE
-
 # For plugins/FireHose
 # Install CPAN module File::Type for plugins/FireHose 
 ALTER TABLE firehose_text ADD COLUMN media TEXT;
@@ -5007,8 +5005,6 @@
 # 18 = "Invalid HTML Input" (see the Messages dump to add back)
 DELETE FROM message_codes WHERE code = 18;
 
-# SLASHCODE/USEPERL LAST UPDATED HERE
-
 # Redundant for many sites, but this is here because an earlier error
 # in the upgrades file may have left your site without them if you
 # didn't have the FireHose plugin installed.
@@ -5036,8 +5032,6 @@
 # 2007-11-08
 UPDATE vars SET value = 'T_2_5_0_183' WHERE name = 'cvs_tag_currentcode';
 
-# SLASHDOT LAST UPDATED HERE
-
 INSERT INTO blocks (bid, block, seclev, type, description, skin, ordernum, title, portal, url, rdf, retrieve) VALUES ('spamurlregexes','',100,'static','Whitespace-delimited list of regexes which indicate a spammer URL.','mainpage',5,'Spam URL Regexes',0,NULL,NULL,0);
 INSERT IGNORE INTO vars (name, value, description) VALUES ('al2_type_aliases', 'spammer->nosubmit spammer->nopost nopost->nopostanon', 'List of AL2s that imply other AL2s, in a whitespace-delimited list of A->B format');
 
@@ -5047,8 +5041,29 @@
 UPDATE code_param SET name = 'Oldest' WHERE type = 'd2_comment_order' AND name = 'Date';
 UPDATE code_param SET name = 'Highest Rated' WHERE type = 'd2_comment_order' AND name = 'Score';
 
-UPDATE al2_types SET name='spammer',title='Binspammer' WHERE name='binspam';
+UPDATE al2_types SET name='spammer',title='Spammer' WHERE name='binspam';
 
 # 2007-11-14
 UPDATE vars SET value = 'T_2_5_0_184' WHERE name = 'cvs_tag_currentcode';
 
+# SLASHDOT LAST UPDATED HERE
+
+# not for slashdot
+UPDATE vars SET value = 'yes no binspam dupe notthebest offtopic stupid slownewsday interesting funny insightful' WHERE name = 'tagbox_top_excludetagnames';
+
+# PUDGE LAST UPDATED HERE
+
+# 2007-12-05
+UPDATE vars SET value = 'T_2_5_0_185' WHERE name = 'cvs_tag_currentcode';
+
+# SLASHCODE/USEPERL LAST UPDATED HERE
+
+# for plugins/Tags
+INSERT INTO ajax_ops VALUES (NULL, 'admin_recenttagnamesbox', 'Slash::Tags', 'ajax_recenttagnamesbox', 'ajax_admin', 'createuse');
+
+# for plugins/FireHose
+INSERT IGNORE INTO ajax_ops VALUES (NULL, 'firehose_usage', 'Slash::FireHose', 'ajaxFireHoseUsage', 'ajax_admin', 'createuse');
+
+# 2007-12-05
+UPDATE vars SET value = 'T_2_5_0_186' WHERE name = 'cvs_tag_currentcode';
+

Modified: slashjp/trunk/tagboxes/Top/mysql_dump.sql
===================================================================
--- slashjp/trunk/tagboxes/Top/mysql_dump.sql	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/tagboxes/Top/mysql_dump.sql	2007-12-06 09:17:47 UTC (rev 272)
@@ -4,7 +4,7 @@
 
 INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_top_minscore_stories', '2', 'Minimum score a tag must have to make it into the top tags for a story');
 INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_top_minscore_urls', '2', 'Minimum score a tag must have to make it into the top tags for a URL');
-INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_top_excludetagnames', 'yes no binspam dupe notthebest offtopic stupid slownewsday interesting funny insightful', 'Minimum score a tag must have to make it into the top tags for a story or firehose item');
+INSERT IGNORE INTO vars (name, value, description) VALUES ('tagbox_top_excludetagnames', 'yes no binspam dupe notthebest offtopic stupid slownewsday stale interesting funny insightful fresh', 'Minimum score a tag must have to make it into the top tags for a story or firehose item');
 
 INSERT INTO tagbox_userkeyregexes VALUES ('Top', '^tag_clout$');
 

Modified: slashjp/trunk/themes/slashcode/htdocs/base.css
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/base.css	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/themes/slashcode/htdocs/base.css	2007-12-06 09:17:47 UTC (rev 272)
@@ -755,7 +755,7 @@
 #modal_cover {background-color: #222; height: 100%; opacity: 0.75; filter: alpha(opacity=75); position: fixed; width: 100%; z-index: 1000000;}
 #modal_box .generaltitle .title h3 {background: transparent; margin: 0; padding: .1em .3em 0 .3em;}
 #modal_box .generaltitle .title { margin: 0; border: none;}
-#modal_box {position: fixed; margin: 15% 25%; width: 60%;z-index: 1000001;border: 4px solid #222;}
+#modal_box {position: fixed; margin: 15% 25%; width: 50%;z-index: 1000001;border: 4px solid #222; overflow: auto; background: #fff; height: 65%;}
 #modal_box h3 a {position: absolute !important; right: .3em; top: .3em}
 #modal_box #modal_box_content legend {display: none;}
 #modal_box #modal_box_content fieldset {margin: 0;padding: 0;border: none;}

Modified: slashjp/trunk/themes/slashcode/htdocs/comments.css
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/comments.css	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/themes/slashcode/htdocs/comments.css	2007-12-06 09:17:47 UTC (rev 272)
@@ -234,6 +234,9 @@
 #commentlisting {clear: right;}
 #commentControlBoxStatus {border-bottom: 1px solid #444; border-top: 1px solid #ccc; text-align: center; padding: 3px; background: #666; color: #fff; }
 
+#bindings-legend {display: none; position: relative; text-align: center; font-family: monospace}
+.vertical #bindings-legend {display: block;}
+
 .escape-link { position: absolute; left: 0.8em; }
 
 .horizontal .loki {display: block;}

Modified: slashjp/trunk/themes/slashcode/htdocs/images/comments.js
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/images/comments.js	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/themes/slashcode/htdocs/images/comments.js	2007-12-06 09:17:47 UTC (rev 272)
@@ -14,7 +14,7 @@
 var root_comments_hash = {};
 var last_updated_comments = [];
 var last_updated_comments_index = 0;
-var last_updated_comments_started = 0;
+var comments_started = 0;
 var current_cid = 0;
 var more_comments_num;
 var behaviors = {
@@ -45,6 +45,7 @@
 var loaded = 0;
 var shift_down = 0;
 var alt_down = 0;
+var ctrl_down = 0;
 var d2_seen = '';
 
 var agt = navigator.userAgent.toLowerCase();
@@ -123,14 +124,14 @@
 
 	var kidhiddens = 0;
 	if (comment && comment['kids'] && comment['kids'].length) {
-		if (!subexpand) {
-			if (shift_down && !alt_down && futuredisplaymode[cid] == 'full') {
-				subexpand = 1;
-			} else if (shift_down && !alt_down && futuredisplaymode[cid] == 'oneline') {
-				subexpand = 2;
-				threshold = user_threshold;
-			}
-		}
+// 		if (!subexpand) {
+// 			if (shift_down && !alt_down && futuredisplaymode[cid] == 'full') {
+// 				subexpand = 1;
+// 			} else if (shift_down && !alt_down && futuredisplaymode[cid] == 'oneline') {
+// 				subexpand = 2;
+// 				threshold = user_threshold;
+// 			}
+// 		}
 
 		for (var kiddie = 0; kiddie < comment['kids'].length; kiddie++) {
 			kidhiddens += updateCommentTree(comment['kids'][kiddie], threshold, subexpand);
@@ -644,6 +645,8 @@
 /*******************/
 /* misc. functions */
 /*******************/
+function numsort (a, b) { return (a - b) }
+
 function toHash(thisobject) {
 	return thisobject.map(function (pair) {
 		return pair.map(encodeURIComponent).join(',');
@@ -1027,7 +1030,7 @@
 		if (!noshow_comments_hash[cid])
 			last_updated_comments.push(cid);
 	}
-	last_updated_comments = last_updated_comments.sort(function (a, b) { return (a - b) });
+	last_updated_comments = last_updated_comments.sort(numsort);
 
 	if (1 || user_is_admin) {
 		if (window.addEventListener) // DOM method for binding an event
@@ -1038,7 +1041,7 @@
 			document.body.onkeydown = keyHandler;
 	}
 
-	setCurrentComment(last_updated_comments[i]);
+	setCurrentComment(last_updated_comments[last_updated_comments_index]);
 
 	if (more_comments_num)
 		updateMoreNum(more_comments_num);
@@ -1065,12 +1068,12 @@
 function resetModifiers () {
 	shift_down = 0;
 	alt_down   = 0;
+	ctrl_down  = 0;
 }
 
 function doModifiers (e) {
 	e = e || window.event;
-	shift_down = 0;
-	alt_down   = 0;
+	resetModifiers();
 
 	if (e) {
 		if (e.modifiers) {
@@ -1078,11 +1081,15 @@
 				shift_down = 1;
 			if (e.modifiers & Event.ALT_MASK)
 				alt_down = 1;
+			if (e.modifiers & Event.CTRL_MASK)
+				ctrl_down = 1;
 		} else {
 			if (e.shiftKey)
 				shift_down = 1;
 			if (e.altKey)
 				alt_down = 1;
+			if (e.ctrlKey)
+				ctrl_down = 1;
 		}
 	}
 }
@@ -1299,7 +1306,10 @@
 }
 
 function commentIsInWindow(cid) {
-	return isInWindow(fetchEl('comment_' + cid));
+	var in_window = isInWindow(fetchEl('comment_' + cid));
+	if (in_window && fetchEl('comment_body_' + cid))
+		in_window = isInWindow(fetchEl('comment_body_' + cid));
+	return in_window;
 }
 
 function isInWindow(obj) {
@@ -1690,62 +1700,220 @@
 }
 
 
-function keyHandler(e) {
-	e = e || window.event;
+/* keys
+prev comment: A, H
+next comment: D, L
+prev thread: W, J
+next thread: S, K
+prev comm chrono: Q
+next comm chrono: E
+*/
 
-	if (e) {
+var validkeys = {
+	A: { thread : 1, prev: 1, comment: 1 },
+	D: { thread : 1, next: 1, comment: 1 },
+	W: { thread : 1, prev: 1 },
+	S: { thread : 1, next: 1 },
+	Q: { chrono : 1, prev: 1, comment: 1 },
+	E: { chrono : 1, next: 1, comment: 1 },
+};
+
+validkeys['H'] = validkeys['A'];
+validkeys['L'] = validkeys['D'];
+validkeys['J'] = validkeys['W'];
+validkeys['K'] = validkeys['S'];
+
+function keyHandler(e, k) {
+	if (!k)
+		e = e || window.event;
+
+	if (k || e) {
 		// don't handle for forms ... "type" should handle all our cases here
-		if (e.target && e.target.type)
+		if (!k && e.target && e.target.type)
 			return;
 
-		var c = e.keyCode;
-		if (c) {
-			var key = String.fromCharCode(c);
-			if (key == 'J' || key == 'K' || key == 'W' || key == 'S') {
+		var c;
+		if (e)
+			c = e.keyCode;
+		if (k || c) {
+			if (!k)
+				doModifiers(e);
+			var collapseCurrent = shift_down;
+			var getNextUnread   = ctrl_down;
+			if (!k)
+				resetModifiers();
+
+			var update = 0;
+			var next_cid = 0;
+			var key = k || String.fromCharCode(c);
+			var keyo = validkeys[key];
+			// forward and back between comments, in order of how they were loaded
+			if (keyo && keyo['chrono']) {
 				var i = last_updated_comments_index;
 				var l = last_updated_comments.length - 1;
-				var update = 0;
-				if (key == 'J' || key == 'S') {
-					update = 1;
+				update = 1;
+
+				if (keyo['prev']) {
 					if (i <= 0) {
 						// this did go back to end; nothing, for now
 						//i = l;
 					} else
 						i = i - 1;
-				} else if (key == 'K' || key == 'W') {
+				} else if (keyo['next']) {
 					if (i >= l) {
 						if (ajaxCommentsWait())
 							return;
 						update = 2;
 						ajaxFetchComments(0, 1, '', 1);
 					} else {
-						update = 1;
-						if (!i && !last_updated_comments_started && !commentIsInWindow(last_updated_comments[i]))
-							last_updated_comments_started = 1; // only come here once
+						if (!i && noSeeFirstComment(last_updated_comments[i]))
+							comments_started = 1; // only come here once
 						else
 							i = i + 1;
 					}
 				}
 
-				if (update) {
-					doModifiers(e);
-					var this_shift_down = shift_down;
-					resetModifiers();
-					if (this_shift_down && current_cid) { // if shift, collapse previously selected
-						setFocusComment('-' + current_cid, 1);
+				if (update == 1) {
+					last_updated_comments_index = i;
+					next_cid = last_updated_comments[i];
+				}
+			}
+
+			// forward and back between threads, and comments within each thread
+			else if (keyo && keyo['thread']) {
+				update = 1;
+				if (keyo['next']) {
+					if (noSeeFirstComment(current_cid))
+						next_cid = current_cid;
+					else {
+						if (keyo['comment'])
+							next_cid = commTreeNextComm(current_cid, 0, getNextUnread);
+						else
+							next_cid = commTreeNextComm(comments[current_cid].pid, current_cid, getNextUnread);
 					}
-					if (update == 1) {
-						last_updated_comments_index = i;
-						setFocusComment(last_updated_comments[i], 1);
-					}
 				}
+
+				else if (keyo['prev'] && keyo['comment'])
+					next_cid = commTreePrevComm(current_cid);
+
+				else if (keyo['prev'])
+					next_cid = commTreePrevComm(current_cid, 1);
 			}
+
+			if (update && next_cid) {
+				comments_started = 1;
+				if (collapseCurrent && current_cid)
+					setFocusComment('-' + current_cid, 1);
+				if (update == 1)
+					setFocusComment(next_cid, 1);
+			}
 		}
 	}
+}
 
+// at first comment, comment is not in window OR comment is not full
+function noSeeFirstComment (cid) {
+	setDefaultDisplayMode(cid);
+	if (!comments_started && (!commentIsInWindow(cid) || (viewmodevalue[displaymode[cid]] < viewmodevalue['full']))) {
+		return 1;
+	}
+	return 0;
 }
 
+// XXX somehow sync this with the prev/next by load order?  might require
+// a quick grep to find the position
+function commTreeNextComm (cid, old_cid, getNextUnread) {
+	var kids;
+	if (cid)
+		kids = sortKids(cid);
+	else
+		kids = rootSort();
 
+	for (var i = 0; i < kids.length; i++) {
+		var next_cid = kids[i];
+		if (next_cid > old_cid) {
+			if (next_cid)
+				if (!getNextUnread || (next_cid = getNextUnreadCid(next_cid)))
+					return next_cid;
+			continue;
+		}
+	}
+
+	if (!cid)
+		return 0; // at the end, stay where we are
+
+	// we can't continue here, go back up a level
+	return commTreeNextComm(comments[cid].pid, cid, getNextUnread);
+}
+
+function commTreePrevComm (cid, to_parent) {
+	var root_kids = root_comments.sort(numsort);
+	var comm = comments[cid];
+	var pid = comm.pid;
+
+	if (to_parent == 1) {
+		if (pid)
+			return pid;
+		else // if in roots, then just climb up roots
+			return commTreePrevComm(cid, 2);
+	}
+
+	var kids;
+	if (pid)
+		kids = sortKids(pid);
+	else
+		kids = root_kids;
+
+	for (var i = 0; i < kids.length; i++) {
+		if (cid == kids[i]) {
+			if (i == 0) // go up
+				return pid;
+			else if (to_parent)
+				return kids[i - 1];
+			else 
+				return getLastChild(kids[i - 1]);
+		}
+	}
+}
+
+function rootSort() { // maybe cache later
+	return root_comments.sort(numsort);
+}
+
+function sortKids(cid) { // maybe cache later
+	return comments[cid].kids.sort(numsort);
+}
+
+function isUnread(cid) {
+	var this_id  = fetchEl('comment_top_' + cid);
+	if (this_id)
+		if (this_id.className.match(' oldcomment'))
+			return 0;
+		else
+			return 1;
+}
+
+function getNextUnreadCid(cid) {
+	if (isUnread(cid))
+		return cid;
+	var kids = sortKids(cid);
+	for (var i = 0; i < kids.length; i++) {
+		var next_cid = getNextUnreadCid(kids[i]);
+		if (next_cid)
+			return next_cid;
+	}
+	return 0;
+}
+
+function getLastChild(cid) {
+	var kids = sortKids(cid);
+	if (kids.length)
+		return getLastChild(kids[kids.length - 1]);
+	else
+		return cid;
+}
+
+
 function dummyComment(cid) {
 	var html = '<li id="tree_--CID--" class="comment">\
 <div id="comment_status_--CID--" class="commentstatus"></div>\

Modified: slashjp/trunk/themes/slashcode/htdocs/users.pl
===================================================================
--- slashjp/trunk/themes/slashcode/htdocs/users.pl	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/themes/slashcode/htdocs/users.pl	2007-12-06 09:17:47 UTC (rev 272)
@@ -906,7 +906,7 @@
 	$form->{mode} = "full";
 	$form->{color} = "black";
 	$form->{orderby} = "createtime";
-	$form->{orderdidr} = "DESC";
+	$form->{orderdir} = "DESC";
 	$form->{skipmenu} = 1;
 	$form->{duration} = -1;
 	$form->{fhfilter} = "\"user:$user_edit->{nickname}\"";

Modified: slashjp/trunk/themes/slashcode/tasks/freshenup.pl
===================================================================
--- slashjp/trunk/themes/slashcode/tasks/freshenup.pl	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/themes/slashcode/tasks/freshenup.pl	2007-12-06 09:17:47 UTC (rev 272)
@@ -409,8 +409,9 @@
 		});
 
 		if ($constants->{plugin}{FireHose}) {
-			gen_firehose_static($virtual_user, "index_firehose.shtml", $gSkin->{name}, "", {  skipmenu => 1, skippop => 1, fhfilter=> "story", duration => "7", mode => 'fulltitle', mixedmode => '1', setfield => '1', color => "black", index => "1", nocolors => 1  }); 
+			gen_firehose_static($virtual_user, "index_firehose.shtml", $gSkin->{name}, "", {  skipmenu => 1, skippop => 1, fhfilter => "story", duration => "7", mode => 'fulltitle', mixedmode => '1', setfield => '1', color => "black", index => "1", nocolors => 1  }); 
 			gen_firehose_static($virtual_user, "firehose.shtml", $gSkin->{name}, "", { duration => "7", mode => 'fulltitle', mixedmode => '1', setfield => '1', color => "blue", nodates => '1'  }); 
+			gen_firehose_static($virtual_user, "embed_index.shtml", $gSkin->{name}, "", { embed => '1', smalldevices => '1', fhfilter => "story", duration => "7", mode => 'fulltitle', setfield => '1', color => "black", index => "1", nodates => '1', nocolors => 1  }); 
 			gen_firehose_static($virtual_user, "embed_firehose.shtml", $gSkin->{name}, "", { embed => '1', smalldevices => '1', duration => "7", mode => 'fulltitle', setfield => '1', color => "blue", nodates => '1'  }); 
 		}
 		$slashdb->markSkinClean($mp_skid);
@@ -440,8 +441,9 @@
 					handle_err =>	0
 			});
 			if ($constants->{plugin}{FireHose}) {
-				gen_firehose_static($virtual_user, "index_firehose.shtml", $skin->{name}, $skinname, { skipmenu => 1, skippop => 1, fhfilter=> "'story $skin->{name}'", duration => "7", mode => 'fulltitle', mixedmode => '1', setfield => '1', color => "black", index => "1", nocolors => "1"  }); 
+				gen_firehose_static($virtual_user, "index_firehose.shtml", $skin->{name}, $skinname, { skipmenu => 1, skippop => 1, fhfilter => "'story $skin->{name}'", duration => "7", mode => 'fulltitle', mixedmode => '1', setfield => '1', color => "black", index => "1", nocolors => "1"  }); 
 				gen_firehose_static($virtual_user, "firehose.shtml", $skin->{name}, $skinname, { duration => "7", mode => 'fulltitle', mixedmode => '1', setfield => '1', color => "blue", nodates => '1', fhfilter => "'$skin->{name}'" }); 
+				gen_firehose_static($virtual_user, "embed_index.shtml", $gSkin->{name}, "", { embed => '1', smalldevices => '1', fhfilter => "'story $skin->{name}'", duration => "7", mode => 'fulltitle', setfield => '1', color => "black", index => "1", nodates => '1', nocolors => 1  }); 
 				gen_firehose_static($virtual_user, "embed_firehose.shtml", $skin->{name}, $skinname, { embed => '1', smalldevices => '1', duration => "7", mode => 'fulltitle', setfield => '1', color => "blue", nodates => '1', fhfilter => "'$skin->{name}'" }); 
 			}
 

Modified: slashjp/trunk/themes/slashcode/templates/prefs_titlebar;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/prefs_titlebar;misc;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/themes/slashcode/templates/prefs_titlebar;misc;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -18,8 +18,13 @@
 PROCESS titlebar title=title;
 '<div id="usermenu">'; 
 
+user_link = '/users.pl?op=edituser';
+IF constants.modal_prefs_active;
+        user_link = user_link _ "\" onclick=\"getModalPrefs('user', 'User')\; return false";
+END;
+
 tabs = [
-	{ link = "/users.pl?op=edituser",	label = "User",		sel_label = "user" },
+	{ link = user_link,                     label = "User",		sel_label = "user" },
 	{ link = "/users.pl?op=edithome",	label = "Homepage",	sel_label = "home" },
 	{ link = "/users.pl?op=editcomm",	label = "Comments",	sel_label = "comments" }
 ];

Modified: slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default
===================================================================
--- slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default	2007-12-06 09:12:31 UTC (rev 271)
+++ slashjp/trunk/themes/slashcode/templates/printCommentsMain;misc;default	2007-12-06 09:17:47 UTC (rev 272)
@@ -282,6 +282,14 @@
 				subject_only => 1
 			}) %]
 		[% END %]
+			<div id="bindings-legend">Keybindings Beta<br>
+<a href="#" onclick="keyHandler('','Q'); return false" title="previous comment by load order">Q</a>
+<a href="#" onclick="keyHandler('','W'); return false" title="previous thread"               >W</a>
+<a href="#" onclick="keyHandler('','E'); return false" title="next comment by load order"    >E</a><br>
+<a href="#" onclick="keyHandler('','A'); return false" title="previous comment in thread"    >A</a>
+<a href="#" onclick="keyHandler('','S'); return false" title="next thread"                   >S</a>
+<a href="#" onclick="keyHandler('','D'); return false" title="next comment in thread"        >D</a>
+			</div>
 		</div>
 		<div id="commentControlBoxStatus" class="hide"><b>Loading ... Please wait.</b></div>
 	</div>


Slashdotjp-dev メーリングリストの案内
Back to archive index