620 lines
19 KiB
Perl
620 lines
19 KiB
Perl
# ==================================================================
|
|
# Plugins::SocialMedia - Auto Generated Program Module
|
|
#
|
|
# Plugins::SocialMedia
|
|
# Author : Gossamer Threads Inc.
|
|
# Version : 1.0
|
|
# Updated : Tue Oct 29 11:32:05 2013
|
|
#
|
|
# ==================================================================
|
|
#
|
|
|
|
package Plugins::SocialMedia;
|
|
# ==================================================================
|
|
|
|
use strict;
|
|
use GT::Base;
|
|
use GT::Plugins qw/STOP CONTINUE/;
|
|
use Links qw/:objects/;
|
|
use Links::Build;
|
|
use Links::SiteHTML;
|
|
use Net::Twitter;
|
|
use Links::Plugins;
|
|
use LWP::Simple;
|
|
use JSON;
|
|
use URI;
|
|
use utf8;
|
|
use vars qw/$USE_HTML $TIME_START $TOTAL_TIME @CARP_NOT $GRAND_TOTAL/;
|
|
#use Scalar::Util 'blessed';
|
|
use GT::File::Tools qw/mkpath dirname/;
|
|
use Carp;
|
|
|
|
@CARP_NOT = 'GT::Plugins';
|
|
|
|
# Inherit from base class for debug and error methods
|
|
@Plugins::SocialMedia::ISA = qw(GT::Base);
|
|
|
|
# Your code begins here.
|
|
|
|
|
|
# PLUGIN HOOKS
|
|
# ===================================================================
|
|
|
|
sub post_twitter {
|
|
my $link = shift;
|
|
$link = format_link($link);
|
|
$link || return;
|
|
|
|
# When no authentication is required:
|
|
my $nt = Net::Twitter->new(legacy => 0);
|
|
|
|
my $consumer_key = "u4xwsqHZBKrdWYPrKCm8Lw";
|
|
my $consumer_secret = "vjDF6FjeoPJW0WVwgqMEJeuJzilgSIu5QbPGQnWrMI";
|
|
my $token = "1921299666-fMicJMBunBjgBb4ieszHo6tYV0mQcbbaMZU5wSB";
|
|
my $token_secret = "Ko9gPpBaLxqQj6u68EWdlgnPinGSseVzrzUvytWric";
|
|
|
|
#return { error => 'error posting...unknown' };
|
|
my $tags = $IN->param('twitter_hash_tags');
|
|
$tags =~ s/\s+//g;
|
|
my @tags = split(',',$tags);
|
|
my $newtags;
|
|
for (@tags) {
|
|
$newtags .= ' #' . $_;
|
|
}
|
|
my $post_title = $IN->param('twitter_status');
|
|
|
|
my $len = length $link->{detailed_url};
|
|
$len = 140 - 5 - $len;
|
|
$post_title = substr($post_title,0,$len) . "..." if (length $post_title > $len);
|
|
$post_title .= " " . $link->{detailed_url};
|
|
$post_title .= $newtags;
|
|
|
|
# As of 13-Aug-2010, Twitter requires OAuth for authenticated requests
|
|
$nt = Net::Twitter->new(
|
|
traits => [qw/API::RESTv1_1/],
|
|
consumer_key => $consumer_key,
|
|
consumer_secret => $consumer_secret,
|
|
access_token => $token,
|
|
access_token_secret => $token_secret,
|
|
);
|
|
|
|
my $result;
|
|
my $res = eval { $result = $nt->update($post_title) };
|
|
if ( my $err = $@ ) {
|
|
die $@ unless $err and $err->isa('Net::Twitter::Error');
|
|
#warn "HTTP Response Code: ", $err->code, "\n",
|
|
#"HTTP Message......: ", $err->message, "\n",
|
|
#"Twitter error.....: ", $err->error, "\n";
|
|
$result->{error} = $err->error;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
sub post_facebook {
|
|
# -------------------------------------------------------------------
|
|
my $access_token = shift;
|
|
my $id = shift;
|
|
my $link = format_link($id);
|
|
|
|
if ($link->{facebook_hashtags}) {
|
|
$link->{Description} .= " ";
|
|
$link->{Description} .= $link->{facebook_hashtags};
|
|
}
|
|
|
|
#Publish to a facebook page as admin
|
|
my $cfg = Links::Plugins::get_plugin_user_cfg('Auth_Facebook');
|
|
my $result = facebook_graph_api('/' . $cfg->{fb_fanpageid} . '/links',{
|
|
link => "http://www.slowtwitch.com/temp/$id.html",
|
|
#link => $link->{detailed_url},
|
|
message => $link->{Description},
|
|
picture => $link->{Picture},
|
|
access_token => $access_token,
|
|
method => 'post'
|
|
});
|
|
|
|
return $result;
|
|
}
|
|
|
|
sub facebook_graph_api {
|
|
# -------------------------------------------------------------------
|
|
my $uri = new URI('https://graph.facebook.com/' . shift);
|
|
$uri->query_form(shift);
|
|
|
|
require GT::WWW;
|
|
my $www = GT::WWW->get("$uri");
|
|
my $resp = $www->content;
|
|
return defined $resp ? decode_json($resp) : undef;
|
|
}
|
|
|
|
sub format_link {
|
|
# -------------------------------------------------------------------
|
|
my $link = shift;
|
|
if ($link =~ /^(\d+)$/) {
|
|
$link = $DB->table('Links')->get($link);
|
|
}
|
|
$link or return;
|
|
$link = Links::SiteHTML::tags('link',$link);
|
|
|
|
my $len = length $link->{detailed_url};
|
|
$len = 140 - 5 - $len;
|
|
$link->{Description} = substr($link->{Description},0,$len) . "..." if (length $link->{Description} > $len);
|
|
|
|
my @cats = $DB->table('Category', 'CatLinks')->select('Category.Full_Name', { 'CatLinks.LinkID' => $link->{ID} })->fetchall_list;
|
|
$link->{Category} = join "\n", sort @cats;
|
|
|
|
use Plugins::SlideShow;
|
|
my $paths = Plugins::SlideShow::generate_paths($link->{ID});
|
|
$link->{image_paths} = $paths;
|
|
my $img = $link->{facebook_published_image} || "Image1";
|
|
$link->{Picture} = $paths->{$img . '_largest_path'} if ($paths->{$img . '_largest_path'});
|
|
|
|
return $link;
|
|
}
|
|
|
|
sub publish_it {
|
|
# -------------------------------------------------------------------
|
|
if ($IN->param('build')) {
|
|
my $linkid = $IN->param('linkid');
|
|
my ($twitter, $fb);
|
|
use Time::HiRes;
|
|
#Time::HiRes::sleep(5); #.1 seconds
|
|
#print $IN->header;
|
|
$IN->param('t','dev'); #FIXME
|
|
#print $IN->header;
|
|
build_it($linkid);
|
|
my $hash = {};
|
|
|
|
#print Links::user_page('add_success_publish.html', { success => '1', built => 1, twitter => $twitter, %$hash });
|
|
#return;
|
|
|
|
if ($IN->param('post_facebook')) {
|
|
if ($IN->param('post_twitter')) {
|
|
my $res = post_twitter($linkid);
|
|
if ($res->{id}) {
|
|
$DB->table('Links')->update({ twitter_published => $res->{id} }, { ID => $linkid });
|
|
$hash->{twitter_published} = 1;
|
|
}
|
|
else {
|
|
$DB->table('Links')->update({ twitter_published_message => $res->{error} }, { ID => $linkid });
|
|
$hash->{twitter_published_message} = $res->{error} if ($res->{error});
|
|
}
|
|
}
|
|
use Plugins::Auth_Facebook;
|
|
Plugins::Auth_Facebook::user_auth($linkid);
|
|
return;
|
|
}
|
|
elsif ($IN->param('post_twitter')) {
|
|
my $res = post_twitter($linkid);
|
|
if ($res->{id}) {
|
|
$DB->table('Links')->update({ twitter_published => $res->{id} }, { ID => $linkid });
|
|
$hash->{twitter_published} = 1;
|
|
}
|
|
else {
|
|
$DB->table('Links')->update({ twitter_published_message => $res->{error} }, { ID => $linkid });
|
|
$hash->{twitter_published_message} = $res->{error} if ($res->{error});
|
|
}
|
|
}
|
|
$IN->param('t','dev'); #FIXME
|
|
print $IN->header;
|
|
print Links::user_page('add_success_publish.html', { success => '1', built => 1, twitter => $twitter, %$hash });
|
|
}
|
|
else {
|
|
print $IN->header;
|
|
print Links::user_page('error.html', { error => 'no error' });
|
|
}
|
|
}
|
|
|
|
sub build_it {
|
|
# -------------------------------------------------------------------
|
|
#
|
|
my $linkid = shift || return;
|
|
my $unix_time = $CFG->{last_build} ? $CFG->{last_build} : time;
|
|
Links::init_date();
|
|
my $time = GT::Date::date_get($unix_time - $CFG->{date_offset} * 3600, '%yyyy%-%mm%-%dd% %HH%:%MM%:%ss%');
|
|
|
|
=tag
|
|
# Do any backups.
|
|
_build_backup();
|
|
|
|
# Update isNew, isCool, isPopular flags.
|
|
_build_reset_hits();
|
|
_build_new_flags();
|
|
_build_changed_flags();
|
|
_build_cool_flags();
|
|
|
|
# Build Home Page.
|
|
$PLG->dispatch('create_home', \&_build_home, {});
|
|
=cut
|
|
|
|
=tag
|
|
# Build New Page.
|
|
$PLG->dispatch('create_new', \&_build_new, {});
|
|
|
|
# Build Cool Page.
|
|
$PLG->dispatch('create_cool', \&_build_cool, {});
|
|
|
|
# Build Ratings Page.
|
|
$PLG->dispatch('create_ratings', \&_build_ratings, {});
|
|
=cut
|
|
|
|
# Build Changed Detailed Page.
|
|
$PLG->dispatch('create_detailed_changed', \&_build_detailed, GT::SQL::Condition->new('Links.ID', '=', $linkid));
|
|
|
|
=tag
|
|
# Build Changed Category Pages.
|
|
$PLG->dispatch('create_category_changed', \&_build_category, GT::SQL::Condition->new('Timestmp', '>', $time));
|
|
|
|
$CFG->{last_build} = time;
|
|
$CFG->save;
|
|
=cut
|
|
|
|
}
|
|
|
|
sub get_path {
|
|
# -------------------------------------------------------------------
|
|
#
|
|
my $field = shift;
|
|
my $filefield = $field . "_largest_path";
|
|
my $link = GT::Template->tags();
|
|
if (!$link->{$filefield}) {
|
|
$filefield = $field . "_medium_path";
|
|
}
|
|
return $link->{$filefield};
|
|
}
|
|
|
|
# ------------------------------------------------------------------
|
|
# MISC BUILD functions
|
|
# ------------------------------------------------------------------
|
|
sub _build_home {
|
|
# ------------------------------------------------------------------
|
|
# Generate the home page.
|
|
#
|
|
_time_start();
|
|
|
|
my $index = $CFG->{build_home} || $CFG->{build_index};
|
|
my $page = "$CFG->{build_root_path}/$index";
|
|
print $USE_HTML
|
|
? qq'Building <a href="$CFG->{build_root_url}/$index" target="_blank">Home Page</a>...\n'
|
|
: qq'Building Home Page...\n';
|
|
|
|
my $fh = _open_write($page);
|
|
print $fh Links::Build::build(home => {});
|
|
close $fh;
|
|
my $perms = oct $CFG->{build_file_per};
|
|
chmod $perms, $page;
|
|
|
|
_display_time();
|
|
}
|
|
|
|
sub _build_detailed {
|
|
# ------------------------------------------------------------------
|
|
# Generate one html page per link.
|
|
#
|
|
require Links::Tools;
|
|
|
|
my ($cond, $cust_page, $cust_limit);
|
|
if (ref $_[0] eq 'HASH') {
|
|
$cust_page = $_[0]->{page};
|
|
$cust_limit = $_[0]->{limit};
|
|
}
|
|
else {
|
|
$cond = shift;
|
|
}
|
|
unless ($CFG->{build_detailed}) {
|
|
print "Skipping Detailed Build (disabled).\n\n";
|
|
return;
|
|
}
|
|
|
|
_time_start();
|
|
|
|
#print "Building Detailed pages...\n";
|
|
|
|
# Only build validated links
|
|
$cond ||= GT::SQL::Condition->new;
|
|
$cond->add(VIEWABLE);
|
|
|
|
# Loop through, building 1000 at a time
|
|
my ($limit, $offset, $count, $second_pass) = (1000, 0, 0);
|
|
my $rel = $DB->table(qw/Links CatLinks Category/);
|
|
#print "\t";
|
|
|
|
my $Links = $DB->table('Links');
|
|
while () {
|
|
# Links can be in multiple categories, make sure their detailed pages are only built once
|
|
$rel->select_options("GROUP BY LinkID") if $CFG->{build_detail_format} eq '%ID%';
|
|
$rel->select_options("ORDER BY LinkID");
|
|
|
|
if ($cust_page or $cust_limit) {
|
|
last if $second_pass++;
|
|
$rel->select_options(sprintf "LIMIT %d OFFSET %d", $cust_limit, ($cust_page-1) * $cust_limit);
|
|
}
|
|
else {
|
|
$rel->select_options(sprintf "LIMIT %d OFFSET %d", $limit, $offset*$limit);
|
|
}
|
|
my %links_cols = %{$Links->cols};
|
|
# Only select Category columns that don't conflict with Links columns.
|
|
my @cat_cols = grep !$links_cols{$_}, keys %{$DB->table('Category')->cols};
|
|
|
|
my $sth = $rel->select('Links.*', @cat_cols, 'CategoryID' => $cond);
|
|
|
|
last unless $sth->rows;
|
|
|
|
while (my $link = $sth->fetchrow_hashref) {
|
|
my $format = $Links->detailed_url($link);
|
|
$format = "temp/" . $link->{ID} . ".html"; #FIXME
|
|
my $page = "$CFG->{build_detail_path}/$format";
|
|
my $url = "$CFG->{build_detail_url}/$format";
|
|
|
|
{
|
|
my $fh = _open_write($page);
|
|
print $fh Links::Build::build(detailed => $link);
|
|
}
|
|
my $perms = oct $CFG->{build_file_per};
|
|
chmod $perms, $page;
|
|
|
|
=tag
|
|
$USE_HTML ?
|
|
print qq'<a href="$url" target="_blank">$link->{ID}</a> ' :
|
|
print "$link->{ID} ";
|
|
print "\n\t" if ++$count % 20 == 0;
|
|
=cut
|
|
}
|
|
$offset++;
|
|
}
|
|
=tag
|
|
print "\n";
|
|
_display_time();
|
|
=cut
|
|
}
|
|
|
|
sub _build_category {
|
|
# ------------------------------------------------------------------
|
|
# Generate the category pages.
|
|
#
|
|
my ($cond, $cust_page, $cust_limit);
|
|
if (ref $_[0] eq 'HASH') {
|
|
$cust_page = $_[0]->{page};
|
|
$cust_limit = $_[0]->{offset};
|
|
$cond = {};
|
|
}
|
|
else {
|
|
$cond = shift;
|
|
}
|
|
|
|
_time_start();
|
|
|
|
print "Building Category pages...\n\n";
|
|
|
|
my $Cat = $DB->table('Category');
|
|
my $CatLinks = $DB->table('Links', 'CatLinks');
|
|
|
|
$Cat->select_options('ORDER BY Full_Name');
|
|
if (defined $cust_page and $cust_limit) {
|
|
$Cat->select_options(sprintf "LIMIT %d OFFSET %d", $cust_limit, ($cust_page-1)*$cust_limit);
|
|
}
|
|
my $sth = $Cat->select(ID => Full_Name => $cond);
|
|
while (my ($id, $name) = $sth->fetchrow_array) {
|
|
my $clean_name = $Cat->as_url($name);
|
|
my $page = $CFG->{build_root_path} . "/" . $clean_name . '/' . $CFG->{build_index};
|
|
my $url = $CFG->{build_root_url} . "/" . $clean_name . '/' . $CFG->{build_index};
|
|
print $USE_HTML
|
|
? "\tBuilding category <a href='$url' target='_blank'>$name</a>...\n"
|
|
: "\tBuilding category $name...\n";
|
|
my $total = $CatLinks->count({ 'CatLinks.CategoryID' => $id }, VIEWABLE);
|
|
print "\t\tLinks: $total\n";
|
|
|
|
# Do sub-pages if requested.
|
|
if ($CFG->{build_span_pages}) {
|
|
my $lpp = $CFG->{build_links_per_page} || 25;
|
|
my $num_pages = int($total / $lpp);
|
|
$num_pages++ if $total % $lpp;
|
|
|
|
# Create the main page.
|
|
{
|
|
my $fh = _open_write($page);
|
|
print $fh Links::Build::build(category => { id => $id, nh => 1, mh => $lpp });
|
|
}
|
|
my $perms = oct $CFG->{build_file_per};
|
|
chmod $perms, $page;
|
|
|
|
# Create the sub pages.
|
|
for (2 .. $num_pages) {
|
|
$page = "$CFG->{build_root_path}/$clean_name/$CFG->{build_more}$_$CFG->{build_extension}";
|
|
$url = "$CFG->{build_root_url}/$clean_name/$CFG->{build_more}$_$CFG->{build_extension}";
|
|
print "\t\tBuilding subpage: " . ($USE_HTML
|
|
? "<a href='$url' target='_blank'>$_</a>\n"
|
|
: "$_\n"
|
|
);
|
|
{
|
|
my $fh = _open_write($page);
|
|
print $fh Links::Build::build(category => { id => $id, nh => $_, mh => $lpp });
|
|
}
|
|
chmod $perms, $page;
|
|
}
|
|
}
|
|
else {
|
|
{
|
|
my $fh = _open_write($page);
|
|
print $fh Links::Build::build(category => { id => $id });
|
|
}
|
|
my $perms = oct $CFG->{build_file_per};
|
|
chmod $perms, $page;
|
|
}
|
|
print "\tDone\n\n";
|
|
}
|
|
_display_time("Finished building categories");
|
|
}
|
|
|
|
sub _build_backup {
|
|
# ------------------------------------------------------------------
|
|
# Create a backup file in our backup directory.
|
|
#
|
|
if (! $CFG->{build_use_backup}) {
|
|
print "Creating backup file... skipped\n\n";
|
|
return;
|
|
}
|
|
_time_start();
|
|
print "Creating backup file...\n";
|
|
require Links::Import::S2BK;
|
|
|
|
my $max_keep = 7;
|
|
my $root = $CFG->{admin_root_path} . '/backup';
|
|
my $filename = 'BACKUP';
|
|
|
|
for my $n (reverse 0 .. $max_keep) {
|
|
my $oldname = join '.', $filename, $n || ();
|
|
my $newname = join '.', $filename, $n+1;
|
|
if (-e "$root/$oldname") {
|
|
rename "$root/$oldname", "$root/$newname" or print "\tCouldn't rename '$root/$oldname' -> '$root/$newname': $!";
|
|
}
|
|
}
|
|
Links::Import::S2BK::import({ source => "$CFG->{admin_root_path}/defs", destination => "$root/$filename", delimiter => "\t" }, sub { print "\n\tWARNING: @_\n" }, sub { die @_ }, sub { print "\n\tWARNING: @_\n" }, sub { });
|
|
_display_time();
|
|
}
|
|
|
|
sub _build_reset_hits {
|
|
# ------------------------------------------------------------------
|
|
# Updates the What's New flags.
|
|
#
|
|
_time_start();
|
|
print "Resetting hits and rates...\n";
|
|
my $ret = Links::Build::build(reset_hits => shift || {});
|
|
_display_time();
|
|
return $ret;
|
|
}
|
|
|
|
sub _build_new_flags {
|
|
# ------------------------------------------------------------------
|
|
# Updates the What's New flags.
|
|
#
|
|
_time_start();
|
|
print "Updating new flags...\n";
|
|
my $ret = Links::Build::build(new_flags => shift || {});
|
|
_display_time();
|
|
return $ret;
|
|
}
|
|
|
|
sub _build_changed_flags {
|
|
# ------------------------------------------------------------------
|
|
# Updates the isChanged flags.
|
|
#
|
|
_time_start();
|
|
print "Updating changed flags...\n";
|
|
my $ret = Links::Build::build(changed_flags => shift || {});
|
|
_display_time();
|
|
return $ret;
|
|
}
|
|
|
|
sub _build_cool_flags {
|
|
# ------------------------------------------------------------------
|
|
# Updates the What's Cool flags.
|
|
#
|
|
_time_start();
|
|
print "Updating Cool Flags...\n";
|
|
my $ret = Links::Build::build(cool_flags => shift || {});
|
|
_display_time();
|
|
return $ret;
|
|
}
|
|
|
|
sub _time_start {
|
|
# ------------------------------------------------------------------
|
|
# Start a timer.
|
|
#
|
|
$TIME_START = time;
|
|
}
|
|
|
|
sub _display_time {
|
|
# ------------------------------------------------------------------
|
|
# Return time results.
|
|
#
|
|
my $message = shift || 'Done';
|
|
return;
|
|
printf "%s (%.2fs)\n\n", $message, time - $TIME_START;
|
|
}
|
|
|
|
sub _header {
|
|
# ------------------------------------------------------------------
|
|
# Print intro.
|
|
#
|
|
my ($msg, $msg2, $refresh, $started) = @_;
|
|
my $time = scalar localtime;
|
|
|
|
$refresh ||= '';
|
|
$TOTAL_TIME = $started || time;
|
|
$refresh &&= "<meta http-equiv='Refresh' content='2; URL=$refresh'>";
|
|
if ($USE_HTML) {
|
|
print $IN->header(-nph => $CFG->{nph_headers});
|
|
print <<BUILDING;
|
|
<html>
|
|
<head>
|
|
$refresh
|
|
<title>Building HTML Pages</title>
|
|
<body bgcolor="white">
|
|
BUILDING
|
|
print Links::header("Building HTML Pages: $msg", $msg2, 0);
|
|
print <<STARTED;
|
|
<pre>Started at $time.
|
|
|
|
STARTED
|
|
}
|
|
else {
|
|
print "Started at $time.\n\nBuilding HTML pages...\n\n";
|
|
}
|
|
}
|
|
|
|
sub _footer {
|
|
# ------------------------------------------------------------------
|
|
# Print the footer.
|
|
#
|
|
my $end = time;
|
|
my $elapsed = sprintf "%.2f", $end - $TOTAL_TIME;
|
|
|
|
print "All done. Total time: (${elapsed}s)\n";
|
|
print "</pre></body></html>" if $USE_HTML;
|
|
}
|
|
|
|
sub _open_write {
|
|
# -----------------------------------------------------------------------------
|
|
# Opens a file for writing (overwriting anything already there), and returns a
|
|
# filehandle reference. Dies with a more user-friendly error then Links::fatal
|
|
# if the open fails. Can take a second argument which, if true, will cause the
|
|
# function _not_ to attempt to make the containing directory.
|
|
#
|
|
my ($page, $nomkdir) = @_;
|
|
unless ($nomkdir) {
|
|
mkpath(dirname($page), oct $CFG->{build_dir_per});
|
|
}
|
|
my $fh = \do { local *FH; *FH };
|
|
open $fh, "> $page" and return $fh;
|
|
|
|
my $error = "$!";
|
|
my $user = eval { getpwuid($>) } || 'webserver';
|
|
if ($error =~ /permission/i) {
|
|
print "\n\n<b>ERROR:</b> Unable to open '$page': $error\n\n";
|
|
if (-e $page) {
|
|
print <<HELP;
|
|
This means that the user '$user' is not able to overwrite the existing file.
|
|
Please make sure you have set the permissions in the setup to 0666 if you plan
|
|
to build from both the web and shell at the same time.
|
|
|
|
HELP
|
|
}
|
|
else {
|
|
print <<HELP;
|
|
This means that the user '$user' is not able to create a file in your pages
|
|
directory. Please chmod the main directory 0777 so the program can create the
|
|
file.
|
|
|
|
HELP
|
|
}
|
|
croak "Debug information";
|
|
}
|
|
else {
|
|
croak "Unable to open: '$page': $error";
|
|
}
|
|
}
|
|
|
|
1;
|
|
|