[dw-free] Implement a feature similar to popwithfriends.bml
[commit: http://hg.dwscoalition.org/dw-free/rev/5e837b3c4787]
http://bugs.dwscoalition.org/show_bug.cgi?id=1748
Add Popular Subscriptions feature, helps find new people to subscribe to.
Patch by
yvi.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=1748
Add Popular Subscriptions feature, helps find new people to subscribe to.
Patch by
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Files modified:
- bin/upgrading/en.dat
- cgi-bin/DW/Logic/MenuNav.pm
- cgi-bin/LJ/User.pm
- etc/config.pl
- htdocs/tools/popsubscriptions.bml
- htdocs/tools/popsubscriptions.bml.text
-------------------------------------------------------------------------------- diff -r f64ccc1de255 -r 5e837b3c4787 bin/upgrading/en.dat --- a/bin/upgrading/en.dat Tue Jan 05 22:53:19 2010 +0000 +++ b/bin/upgrading/en.dat Tue Jan 05 23:58:20 2010 +0000 @@ -2097,6 +2097,8 @@ menunav.explore.interests=Interests menunav.explore.directorysearch=Directory Search +menunav.explore.popsubscriptions=Popular Subscriptions + menunav.explore.randomjournal=Random Journal menunav.explore.randomcommunity=Random Community diff -r f64ccc1de255 -r 5e837b3c4787 cgi-bin/DW/Logic/MenuNav.pm --- a/cgi-bin/DW/Logic/MenuNav.pm Tue Jan 05 22:53:19 2010 +0000 +++ b/cgi-bin/DW/Logic/MenuNav.pm Tue Jan 05 23:58:20 2010 +0000 @@ -55,6 +55,7 @@ sub get_menu_navigation { my $loggedin_canjoincomms = ( $loggedin && $u->is_person ) ? 1 : 0; # note the semantic difference my $loggedin_hasnetwork = ( $loggedin && $u->can_use_network_page ) ? 1 : 0; my $loggedin_ispaid = ( $loggedin && $u->is_paid ) ? 1 : 0; + my $loggedin_popsubscriptions = ( $loggedin && $u->can_use_popsubscriptions ); my $loggedout = $loggedin ? 0 : 1; my $always = 1; my $never = 0; @@ -215,6 +216,11 @@ sub get_menu_navigation { display => $always, }, { + url => "$LJ::SITEROOT/tools/popsubscriptions", + text => "menunav.explore.popsubscriptions", + display => $loggedin_popsubscriptions, + }, + { url => "$LJ::SITEROOT/support/faq", text => "menunav.explore.faq", display => $always, diff -r f64ccc1de255 -r 5e837b3c4787 cgi-bin/LJ/User.pm --- a/cgi-bin/LJ/User.pm Tue Jan 05 22:53:19 2010 +0000 +++ b/cgi-bin/LJ/User.pm Tue Jan 05 23:58:20 2010 +0000 @@ -1956,6 +1956,10 @@ sub can_use_mass_privacy { return $_[0]->get_cap( 'mass_privacy' ) ? 1 : 0; } +sub can_use_popsubscriptions { + return $_[0]->get_cap( 'popsubscriptions' ) ? 1 : 0; +} + sub can_use_network_page { return 0 unless $_[0]->get_cap( 'friendsfriendsview' ) && $_[0]->is_person; } diff -r f64ccc1de255 -r 5e837b3c4787 etc/config.pl --- a/etc/config.pl Tue Jan 05 22:53:19 2010 +0000 +++ b/etc/config.pl Tue Jan 05 23:58:20 2010 +0000 @@ -365,7 +365,6 @@ 'findsim' => 0, 'friendsfriendsview' => 0, 'friendspage_per_day' => 0, - 'friendspopwithfriends' => 0, 'friendsviewupdate' => 0, 'full_rss' => 1, 'getselfemail' => 0, @@ -378,6 +377,7 @@ 'mod_queue' => 50, 'mod_queue_per_poster' => 3, 'moodthemecreate' => 0, + popsubscriptions => 0, 's2layersmax' => 0, 's2props' => 0, 's2styles' => 0, @@ -421,7 +421,6 @@ 'findsim' => 1, 'friendsfriendsview' => 1, 'friendspage_per_day' => 1, - 'friendspopwithfriends' => 1, 'friendsviewupdate' => 1, 'full_rss' => 1, 'getselfemail' => 1, @@ -434,6 +433,7 @@ 'mod_queue' => 100, 'mod_queue_per_poster' => 5, 'moodthemecreate' => 1, + popsubscriptions => 1, 's2layersmax' => 150, 's2props' => 1, 's2styles' => 1, @@ -475,7 +475,6 @@ 'findsim' => 1, 'friendsfriendsview' => 1, 'friendspage_per_day' => 1, - 'friendspopwithfriends' => 1, 'friendsviewupdate' => 1, 'full_rss' => 1, 'getselfemail' => 1, @@ -488,6 +487,7 @@ 'mod_queue' => 100, 'mod_queue_per_poster' => 5, 'moodthemecreate' => 1, + popsubscriptions => 1, 's2layersmax' => 300, 's2props' => 1, 's2styles' => 1, @@ -536,7 +536,6 @@ 'findsim' => 1, 'friendsfriendsview' => 1, 'friendspage_per_day' => 1, - 'friendspopwithfriends' => 1, 'friendsviewupdate' => 1, 'full_rss' => 1, 'getselfemail' => 1, @@ -549,6 +548,7 @@ 'mod_queue' => 100, 'mod_queue_per_poster' => 5, 'moodthemecreate' => 1, + popsubscriptions => 1, 's2layersmax' => 300, 's2props' => 1, 's2styles' => 1, @@ -588,7 +588,6 @@ 'findsim' => 1, 'friendsfriendsview' => 1, 'friendspage_per_day' => 1, - 'friendspopwithfriends' => 1, 'friendsviewupdate' => 1, 'full_rss' => 1, 'getselfemail' => 1, @@ -601,6 +600,7 @@ 'mod_queue' => 100, 'mod_queue_per_poster' => 5, 'moodthemecreate' => 1, + popsubscriptions => 1, 's2layersmax' => 300, 's2props' => 1, 's2styles' => 1, diff -r f64ccc1de255 -r 5e837b3c4787 htdocs/tools/popsubscriptions.bml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/htdocs/tools/popsubscriptions.bml Tue Jan 05 23:58:20 2010 +0000 @@ -0,0 +1,203 @@ +<?_c +# +# tools/popsubscriptions.bml +# +# Page that shows a sorted list of popular accounts in the user's circle. User can pick +# which circle group to base these calculations on by selecting from a drop-down menu. +# Results are displayed in three sections: personal accounts, community accounts, feed accounts. +# +# Authors: +# Rebecca Freiburg <beckyvi@gmail.com> +# +# Copyright (c) 2009 by Dreamwidth Studios, LLC. +# This program is free software; you may redistribute it and/or modify it under +# the same terms as Perl itself. For a copy of the license, please reference +# 'perldoc perlartistic' or 'perldoc perlgpl'. +_c?> + +<?page +title=><?_ml .title _ml?> +body<= +<?_code +{ + use strict; + use warnings; + + my $ret = "<?p $ML{'.intro'} p?>"; + + my $remote = LJ::get_remote(); + + return "<?needlogin?>" unless $remote; + + return $ML{'.invalidaccounttype'} unless $remote->can_use_popsubscriptions; + + return $ML{'.disabled'} unless LJ::is_enabled( 'popsubscriptions' ); + + # filters options: + # 1: only accounts subscribed to + # 2: only mutually subscribed accounts + # 3: trusted accounts + # 4: mutually trusted accounts + # 5: whole circle => subscriptions + gives access to + + my @calc_options; + @calc_options = ("1", $ML{'.filters.subscriptions'}, "2", $ML{'.filters.mutualsubscriptions'}, "3", $ML{'.filters.access'}, + "4", $ML{'.filters.mutualaccess'}, "5", $ML{'.filters.circle'} ); + + # drop-down menu and button for selecting which user accounts to base the calulations on + $ret .= "<?p $ML{'.options.filter'} p?>"; + $ret .= "<form method='get' action='/tools/popsubscriptions'>\n"; + $ret .= LJ::html_select( { name => 'filter'}, @calc_options ); + $ret .= LJ::html_submit( $ML{'.options.submit'} ); + $ret .= "</form><br /></p>"; + + # circle_ids stores the user ids of accounts to base the calculation on. which accounts these are is based on which filter the user picks. + # default: subscriptions (filter: 1) + my @circle_ids; + + my $filter = $GET{filter}; + if ( !$filter || $filter == 1 ) { + @circle_ids = $remote->watched_userids; + } elsif ( $filter == 2 ) { + @circle_ids = $remote->mutually_watched_userids; + } elsif ( $filter == 3 ) { + @circle_ids = $remote->trusted_userids; + } elsif ( $filter == 4 ) { + @circle_ids = $remote->mutually_trusted_userids; + } else { + @circle_ids = $remote->circle_userids; + } + + # circle can currently have a maximum of 4,000 userid (2,000 watched, 2,000 trusted) calculate for a maximum of 750 of them + # on those scales, we won't lose much resolution doing this, as trusted and watched are almost always overlapping + my $circle_limit = 750; + @circle_ids = splice( @circle_ids, 0, $circle_limit ) if @circle_ids > $circle_limit; + + # hash for searching whether the user is already subscribed to someone later + my %circle_members; + foreach my $id ( @circle_ids ) { + $circle_members{$id} = 1; + } + + # hash for counting how many accounts in @circle_ids are subscribed to a particular account + my %count; + + # limit the number of userids loaded for each @circle_ids user to 500 + my $limit = 500; + my $remote_id = $remote->userid; + + # load users... + my $circleusers = LJ::load_userids( @circle_ids ); + + # now load the accounts the users are watching... + foreach my $uid ( @circle_ids ) { + # don't want to include the user themself + next if $uid == $remote_id; + + # since we have just loaded all user objects, we can now load subscribed accounts of that user + my $circleuser = $circleusers->{$uid}; + + # but we only include undeleted, unsuspended, personal journals (personal + identity) + next unless $circleuser->is_individual || ! $circleuser->is_inactive; + + # get userids subscribers are watching + my @subsubs =$circleuser->watched_userids( limit => $limit ) ; + + # if there are none, skip to next subscription + next unless @subsubs; + + # now we count the occurance of the userids + foreach my $userid ( @subsubs ) { + $count{$userid}++; + } + } + + # now that we have the count for all userids, we sort it and take the most popular 500 + my @pop = sort { $count{$b} <=> $count{$a} } keys %count; + @pop = splice( @pop, 0, 500 ); + + # now we sort according to personal, community or feed account and only take the top 50 accounts + # for this we need to lead the user objects + my $popusers = LJ::load_userids( @pop ); + my ( @poppersonal, @popcomms, @popfeeds ); + my ( $numberpersonal, $numbercomms, $numberfeeds ) = ( 0, 0, 0 ); + my $maximum = 50; + foreach my $uid ( @pop ) { + my $popuser = $popusers->{$uid}; + + # don't show already subscribed to accounts, inactive accounts, or banned accounts + next if $circle_members{$uid} || $uid == $remote_id || $popuser->is_inactive || $remote->is_banned( $popuser, $remote); + + # sort userids into arrays + if ( $numberpersonal < $maximum && $popuser->is_personal ) { + push @poppersonal, $uid; + $numberpersonal++; + } elsif ( $numbercomms < $maximum && $popuser->is_community ) { + push @popcomms, $uid; + $numbercomms++; + } elsif ( $numberfeeds < $maximum && $popuser->is_syndicated ) { + push @popfeeds, $uid; + $numberfeeds++; + } + + # don't continue loop if all three arrays have reached the maximum number + last if $numberpersonal + $numbercomms + $numberfeeds >= $maximum * 3; + } + + # function to construct table rows which we print later + sub make_results_rows { + my ( $poparray, $count ) = @_; + my ( $results, $count_user, $popularu ); + + # need to load user objects to use ->ljuser_display. this is for a maximum of 50 accounts here + my $popularusers = LJ::load_userids( @$poparray ); + + foreach my $popularid ( @$poparray ) { + $count_user = $count->{$popularid}; + $popularu = $popularusers->{$popularid}; + $results .= "<tr><td>" . $popularu->ljuser_display . "</td>"; + $results .= "<td align='right'> $count_user</td></tr>"; + } + return $results; + } + + # store results in table format. these rows can be empty + my ( $results_personal, $results_communities, $results_feeds ); + $results_personal = make_results_rows ( \@poppersonal, \%count ); + $results_communities = make_results_rows ( \@popcomms, \%count ); + $results_feeds = make_results_rows ( \@popfeeds, \%count ); + + # no results to display: show error message + unless ( $results_personal || $results_communities || $results_feeds ) { + $ret .= $ML{'.error.noresults'}; + return $ret; + } + + # print the tables + # only show each result section if there are accounts in them, if not show a message + if ( $results_personal ) { + $ret .= $ML{'.results.personal'}; + $ret .= "<table cellpadding='3'>" . $results_personal . "</table><br /></p>"; + } else { + $ret .= "<?p $ML{'.error.noresults.personal'} p?>"; + } + if ( $results_communities ) { + $ret .= $ML{'.results.communities'}; + $ret .= "<table cellpadding='3'>" . $results_communities . "</table><br /></p>"; + } else { + $ret .= "<?p $ML{'.error.noresults.communities'} p?>"; + } + if ( $results_feeds) { + $ret .= $ML{'.results.feeds'}; + $ret .= "<table cellpadding='3'>" . $results_feeds . "</table><br /></p>"; + } else { + $ret .= "<?p $ML{'.error.noresults.feeds'} p?>"; + } + + return $ret; + + +} +_code?> +<=body +page?> diff -r f64ccc1de255 -r 5e837b3c4787 htdocs/tools/popsubscriptions.bml.text --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/htdocs/tools/popsubscriptions.bml.text Tue Jan 05 23:58:20 2010 +0000 @@ -0,0 +1,39 @@ +.communities.intro=These are the most popular community accounts in your circle: + +.disabled=This feature is not available on this service. + +.error.noresults=Sorry, there were no accounts found for your search. + +.error.noresults.communities=Sorry, there were no community accounts found for your search. + +.error.noresults.feeds=Sorry, there were no personal accounts found for your search. + +.error.noresults.personal=Sorry, there were no feeds found for your search. + +.feeds.intro=These are the most popular feeds in your circle: + +.filters.access=access list + +.filters.circle=your circle + +.filters.mutualaccess=mutual access + +.filters.mutualsubscriptions=mutual subscriptions + +.filters.subscriptions=subscriptions + +.intro=This page displays popular subscriptions within your circle. Only personal accounts are used for this analysis. + +.invalidaccounttype=Sorry, your account type does not permit using this page. + +.options.filter=Select a method to filter which users to include for this analysis. + +.options.submit=Submit + +.results.communities=These are the most popular community accounts in your circle: + +.results.feeds=These are the most popular feeds in your circle: + +.results.personal=These are the most popular personal accounts in your circle: + +.title=Popular With Circle --------------------------------------------------------------------------------
no subject
Looking forward to this going live.
no subject
no subject
no subject