#!/usr/bin/perl # # DW::Logic::AdultContent # # This module provides logic for various adult content related functions. # # Authors: # Janine Smith # # 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'. # package DW::Logic::AdultContent; use strict; # changes an adult post into a fake LJ-cut if this journal/entry is marked as adult content # and the viewer doesn't want to see such entries sub transform_post { my ( $class, %opts ) = @_; my $post = delete $opts{post} or return ''; return $post unless LJ::is_enabled('adult_content'); my $entry = $opts{entry} or return $post; my $journal = $opts{journal} or return $post; my $remote = delete $opts{remote} || LJ::get_remote(); # we should show the entry expanded if: # the remote user owns the journal that the entry is posted in OR # the remote user posted the entry my $poster = $entry->poster; return $post if LJ::isu($remote) && ( $remote->can_manage($journal) || $remote->equals($poster) ); my $adult_content = $entry->adult_content_calculated || $journal->adult_content_calculated; return $post if $adult_content eq 'none'; my $view_adult = LJ::isu($remote) ? $remote->hide_adult_content : 'concepts'; if ( !$view_adult || $view_adult eq 'none' || ( $view_adult eq 'explicit' && $adult_content eq 'concepts' ) ) { return $post; } # return a fake LJ-cut going to an adult content warning interstitial page my $adult_interstitial = sub { return $class->adult_interstitial_link( type => shift(), %opts ) || $post; }; if ( $adult_content eq 'concepts' ) { return $adult_interstitial->('concepts'); } elsif ( $adult_content eq 'explicit' ) { return $adult_interstitial->('explicit'); } return $post; } # returns an link to an adult content warning page sub adult_interstitial_link { my ( $class, %opts ) = @_; my $entry = $opts{entry}; my $type = $opts{type}; my $journal = $opts{journal}; return '' unless $entry && $type; my $url = $entry->url; my $msg; my $markedby = $entry->adult_content_marker; if ( $journal->is_community ) { $markedby .= '.community'; } else { $markedby .= '.personal'; } if ( $type eq 'explicit' ) { $msg = LJ::Lang::ml( 'contentflag.viewingexplicit.by' . $markedby ); } else { $msg = LJ::Lang::ml( 'contentflag.viewingconcepts.by' . $markedby ); } return '' unless $msg; my $fake_cut = qq{( $msg )}; return $fake_cut; } # returns path for adult content warning page sub adult_interstitial_path { my ( $class, %opts ) = @_; my $type = $opts{type}; return '' unless $type; my $path = "/journal/adult_${type}"; return $path; } sub interstitial_reason { my ( $class, $journal, $entry ) = @_; my $poster = defined $entry ? $entry->poster : $journal; my $ret = ""; my $reason_exists = 0; if ( $journal->adult_content ne 'none' && $journal->adult_content_reason ) { my $what = $journal->is_community ? 'community' : 'journal'; my $reason = LJ::ehtml( $journal->adult_content_reason ); if ( $journal->adult_content_calculated eq 'concepts' ) { $ret .= LJ::Lang::ml( '/journal/adult_content.tt.message.concepts.' . $what . 'reason', { journal => $journal->ljuser_display, poster => $poster->ljuser_display, reason => $reason } ); } else { $ret .= LJ::Lang::ml( '/journal/adult_content.tt.message.explicit.' . $what . 'reason', { journal => $journal->ljuser_display, poster => $poster->ljuser_display, reason => $reason } ); } $reason_exists = 1; } if ( defined $entry && $entry->adult_content && $entry->adult_content ne 'none' && $entry->adult_content_reason ) { $ret .= "
" if $reason_exists; my $reason = LJ::ehtml( $entry->adult_content_reason ); if ( $entry->adult_content eq 'concepts' ) { $ret .= LJ::Lang::ml( '/journal/adult_content.tt.message.concepts.byposter.reason', { journal => $journal->ljuser_display, poster => $poster->ljuser_display, reason => $reason } ); } else { $ret .= LJ::Lang::ml( '/journal/adult_content.tt.message.explicit.byposter.reason', { journal => $journal->ljuser_display, poster => $poster->ljuser_display, reason => $reason } ); } $reason_exists = 1; } if ( defined $entry && $entry->adult_content_maintainer && $entry->adult_content_maintainer ne 'none' && $entry->adult_content_maintainer_reason ) { $ret .= "
" if $reason_exists; my $reason = LJ::ehtml( $entry->adult_content_maintainer_reason ); if ( $entry->adult_content_maintainer eq 'concepts' ) { $ret .= LJ::Lang::ml( '/journal/adult_content.tt.message.concepts.byjournal.reason', { journal => $journal->ljuser_display, poster => $poster->ljuser_display, reason => $reason } ); } else { $ret .= LJ::Lang::ml( '/journal/adult_content.tt.message.explicit.byjournal.reason', { journal => $journal->ljuser_display, poster => $poster->ljuser_display, reason => $reason } ); } $reason_exists = 1; } if ($reason_exists) { $ret = "

$ret

"; } return $ret; } ################################################################################ # These methods are for holding/retrieving data in memcache that states whether # a particular user has confirmed seeing an adult journal or entry. The # structure of the hash in memcache is as follows: # # { # explicit => { # journalid => [ entryid, entryid, ... ], # journalid => [ entryid, entryid, ... ], # }, # concepts => { # journalid => [ entryid, entryid, ... ], # journalid => [ entryid, entryid, ... ], # }, # } # # Note that an entryid of 0 means that the journal itself has been confirmed. ################################################################################ sub _memcache_key { my ( $class, $u ) = @_; my $key = "confirmedadult:"; return [ $u->id, $key . $u->id ] if LJ::isu($u); return $key . LJ::UniqCookie->current_uniq; } sub confirmed_pages { my ( $class, $u ) = @_; my $memkey = $class->_memcache_key($u); return LJ::MemCache::get($memkey) || {}; } sub set_confirmed_pages { my ( $class, %opts ) = @_; my $u = $opts{user}; my $journalid = $opts{journalid} + 0; my $entryid = $opts{entryid} + 0; my $adult_content = $opts{adult_content}; my $confirmed_pages = $class->confirmed_pages($u); if ( $entryid && $journalid ) { push @{ $confirmed_pages->{$adult_content}->{$journalid} }, $entryid; } elsif ($journalid) { push @{ $confirmed_pages->{$adult_content}->{$journalid} }, 0; } my $memkey = $class->_memcache_key($u); return LJ::MemCache::set( $memkey, $confirmed_pages, 60 * 30 ); } sub user_confirmed_page { my ( $class, %opts ) = @_; my $u = $opts{user}; my $journal = $opts{journal}; my $entry = $opts{entry}; my $adult_content = $opts{adult_content}; my $confirmed_pages = DW::Logic::AdultContent->confirmed_pages($u); my $page_confirmed = 0; if ( $confirmed_pages && $confirmed_pages->{$adult_content} && $confirmed_pages->{$adult_content}->{ $journal->id } ) { if ( defined $entry && defined $journal ) { $page_confirmed = 1 if grep { $_ == $entry->ditemid } @{ $confirmed_pages->{$adult_content}->{ $journal->id } }; } elsif ( defined $journal ) { $page_confirmed = 1 if grep { $_ == 0 } @{ $confirmed_pages->{$adult_content}->{ $journal->id } }; } } return $page_confirmed; } 1;