Creating an automated blog link Reddit submitter

Creating an automated system to submit my blog posts to my subreddit using PHP and the Reddit API.

The idea is every couple of hours a check will be made to see if my latest blog post is the most recent post on /r/corbpie. If it isn’t then using the API class a post will be submitted using the blog post URL and its title.

The PHP class is a stripped-down and cleaned up version from the outdated reddit-php-sdk.

The main part of this task is authenticating the POST submit. By setting the client id and client secret with the redirect URL this is achieved.

Reddit API client id and client secret can be found at www.reddit.com/prefs/apps/

reddit api client secret client id

<?php
public function __construct($client_id, $client_secret, $endpoint_redirect)
    {
        $this->clientId = $client_id;
        $this->clientSecret = $client_secret;
        $endpoint_oauth = 'https://oauth.reddit.com';
        $endpoint_oauth_authorize = 'https://ssl.reddit.com/api/v1/authorize';
        $endpoint_oauth_token = 'https://ssl.reddit.com/api/v1/access_token';
        $scopes = 'save,modposts,identity,edit,flair,history,modconfig,modflair,modlog,modposts,modwiki,mysubreddits,privatemessages,read,report,submit,subscribe,vote,wikiedit,wikiread';
        if (isset($_COOKIE['reddit_token'])) {//Access token exists
            $token_info = explode(":", $_COOKIE['reddit_token']);
            $this->tokenType = $token_info[0];
            $this->accessToken = $token_info[1];
        } else {
            if (isset($_GET['code'])) {
                $code = $_GET["code"];
                $post_values = sprintf("code=%s&redirect_uri=%s&grant_type=authorization_code",
                    $code,
                    $endpoint_redirect
                );
                $token = $this->doCurl($endpoint_oauth_token, $post_values, null, true);
                if (isset($token->access_token)) {
                    $this->accessToken = $token->access_token;
                    $this->tokenType = $token->token_type;
                    $cookie_time = 3600 * 480 + time();//Token expires in 480hrs
                    setcookie('reddit_token', "" . $this->tokenType . ":" . $this->accessToken . "", $cookie_time);
                }
            } else {
                $state = rand();
                $urlAuth = sprintf("%s?response_type=code&client_id=%s&redirect_uri=%s&scope=%s&state=%s&duration=permanent",
                    $endpoint_oauth_authorize,
                    $client_id,
                    $endpoint_redirect,
                    $scopes,
                    $state
                );
                header("Location: $urlAuth");
            }
        }
        $this->apiMain = $endpoint_oauth;
        $this->authMode = 'oauth';
    }

The cURL function which does the GET and POST requests with the authentication

<?php
    private function doCurl($url, $post_values = null, $headers = null, $auth = false)
    {
        $ch = curl_init($url);
        $options = array(
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CONNECTTIMEOUT => 6,
            CURLOPT_TIMEOUT => 8,
            CURLOPT_USERAGENT => 'write.corbpie blog poster'
        );
        if ($post_values != null) {
            $options[CURLOPT_POSTFIELDS] = $post_values;
            $options[CURLOPT_CUSTOMREQUEST] = "POST";
        }
        if ($this->authMode == 'oauth') {
            $headers = array("Authorization: " . $this->tokenType . " " . $this->accessToken . "");
            $options[CURLOPT_HEADER] = false;
            $options[CURLINFO_HEADER_OUT] = false;
            $options[CURLOPT_HTTPHEADER] = $headers;
        }
        if ($auth) {
            $options[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC;
            $options[CURLOPT_USERPWD] = $this->clientId . ":" . $this->clientSecret;
            $options[CURLOPT_SSLVERSION] = 4;
            $options[CURLOPT_SSL_VERIFYPEER] = false;
            $options[CURLOPT_SSL_VERIFYHOST] = 2;
        }
        curl_setopt_array($ch, $options);
        $apiResponse = curl_exec($ch);
        $response = json_decode($apiResponse);
        curl_close($ch);
        return $response;
    }

The following functions are the Reddit workers, starting with the post create function. This needs to have a defined title, URL and subreddit to submit to.

Next is a function that will approve the post since /r/corbpie is locked down, this goes with the getName function which returns the posts name (its id) which is needed to approve it.

There are functions to get the most recent post URL and title from /r/corbpie, this is used when comparing to the most recent blog post.

getListing function is used by these past few stated functions, it returns data about the most recent posts from a chosen sub.

<?php
    public function createPost($title = null, $url = null, $subreddit = null)
    {
        $urlSubmit = "" . $this->apiMain . "/api/submit";
        if ($title == null || $subreddit == null) {
            return "Please set a title and URL";
        }
        //Check if post is URL or self post (text)
        $kind = ($url == null) ? "self" : "link";
        //Build post data
        $postData = sprintf("kind=%s&sr=%s&title=%s&r=%s",
            $kind,
            $subreddit,
            urlencode($title),
            $subreddit
        );
        //if link exists add to POST data
        if ($url != null) {
            $postData .= "&url=" . urlencode($url);
        }
        $response = $this->doCurl($urlSubmit, $postData);
    }

    public function approvePost($id)
    {
        $url = "" . $this->apiMain . "/api/approve";
        $postData = "id=$id";
        return $this->doCurl($url, $postData);
    }

    public function getLastUrl($sub)
    {
        $data = $this->getListing($sub);
        return $data->data->children[0]->data->url;
    }

    public function getName($sub)
    {
        $data = $this->getListing($sub);
        return $data->data->children[0]->data->name;
    }

    public function getTitle($sub)
    {
        $data = $this->getListing($sub);
        return $data->data->children[0]->data->title;
    }

    public function getListing($sr, $limit = 5)
    {
        return json_decode(file_get_contents("https://www.reddit.com/r/$sr/new.json?&limit=$limit"));
    }

Finally, the functions that interact with the WordPress REST API, these get the title and URL from the most recent published blog post at write.corbpie.com

<?php
    public function getLatestBlogData()
    {
        return json_decode(file_get_contents("https://write.corbpie.com/wp-json/wp/v2/posts"), true);
    }

    public function getLatestBlogUrl($data)
    {
        return $data[0]['link'];
    }

    public function getLatestBlogTitle($data)
    {
        return $data[0]['title']['rendered'];
    }

These function wrapped in the class corbpieBlogPoster are called upon:

<?php
$cbp = new corbpieBlogPoster('CLIENTID', 'CLIENTSECRET', 'https://domain.com/dir/file.php');

$last_sub_url = $cbp->getLastUrl('corbpie');//Get latest post url on sub corbpie

$blog_data = $cbp->getLatestBlogData();//Get latest write.corbpie.com posts data
$latest_blog_url = $cbp->getLatestBlogUrl($blog_data);//Latest blog post url

if ($latest_blog_url === $last_sub_url) {
    echo "Same";//Most recent blog url and recent sub url are the same
} else {
    $title = $cbp->getLatestBlogTitle($blog_data);//Latest blog title
    $new_post = $cbp->createPost($title, $latest_blog_url, 'corbpie');//Create new reddit post at r/corbpie
    sleep(4);//Gives time for post to show up
    $approve_post = $cbp->approvePost($cbp->getName('corbpie'));//Approve the new post
    echo "New[$title][$latest_blog_url]";
}

The full class can be found here.