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/
<?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.