Simple Machines Community Forum

Customizing SMF => SMF Coding Discussion => Topic started by: digital-pig on March 17, 2018, 09:06:30 PM

Title: Posting via cUrl for mod
Post by: digital-pig on March 17, 2018, 09:06:30 PM
Hey all,

I'm looking at creating a mod that will have a cron which runs and posts replies to topics based on data from GitHub. I'm having some issues getting started though as I cannot seem to create a post. I would really rather not go the route of writing directly to the database as that will not run other code/mods which check posts as they're made on the site by users.

I've included some test code here so you can see what I'm attempting. The site is locally hosted for dev.


// File: config.php

$forumUrl = 'https://forum.test';
$forumUser = 'admin';
$forumUserPassword = 'xxxxxxxx';

$testBoardId = 12;
$testTopicId = 13;




// File: cron_poster.php

require 'Application/config/config.php';
require 'Application/Tmod/ForumPoster.php';

$testLoginOnly = false;
$testVerboseOutput = false;

$test = new \Application\Tmod\ForumPoster($forumUrl, $forumUser, $forumUserPassword);
$test->test($testLoginOnly, $testVerboseOutput, $testTopicId);

print "\nDone!\n";




// File: ForumPoster.php

namespace Application\Tmod;

class ForumPoster {

    private $curlSession = null;
    private $forumUser = '';
    private $forumPass = '';
    private $forumUrl = '';

    public function __construct($url, $username, $password) {
        $this->forumUrl = $url;
        $this->forumUser = $username;
        $this->forumPass = $password;
    }

    public function test($loginOnly, $testVerboseOutput, $topicId) {
        $testResult = $this->getCurlSession($testVerboseOutput);
        if ($loginOnly) {
            curl_close($this->curlSession);
            print_r($testResult);
            exit;
        }

        if ($testResult['success'] === true) {
            $subject = 'This is a test at ' . strftime('%d-%m-%y %H:%M:%s');
            $message = 'Trying to post a test to the forum';
            $testPostResult = $this->postIssue($message, $subject, $topicId);

            if (stripos($testPostResult['debug'], $subject) !== false) {
                print "Success!";
            } else {
                print "Failed!";
            }
        } else {
            print 'Failed to get login session';
        }
        curl_close($this->curlSession);
    }

    private function postIssue($message, $subject, $topicId) {
        $ch = $this->curlSession;
        $data = '?' . http_build_query([
            'message' => $message,
            'subject' => $subject,
            'topic' => $topicId,
            'post' => 'Post',
            'notify' => 0,
            'action' => 'post2',
            'board' => 1
        ]);

        curl_setopt($this->curlSession, CURLOPT_POSTFIELDS, $data);
        $result = curl_exec($ch);
        $error = curl_error($ch);

        $success = (empty($error));
       
        return [
            'success' => $success,
            'error' => $error,
            'debug' => $result
        ];
    }

    private function getCurlSession($verboseOutput) {
        $data = '?' . http_build_query([
            'action' => 'login2',
            'user' => $this->forumUser,
            'passwrd' => $this->forumPass,
            'cookielength' => -1,
            'submit' => 'Login'
        ]);

        $curlUserAgent = 'Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11';
        $curlHttpHeader = [
            'Accept: text/plain,text/html;',
            'Accept-Language: en-us,en;q=0.5',
            'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7',
            'Content-Length: ' . strlen($data)
        ];

        $ch = curl_init();

        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_HEADER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $curlHttpHeader);
        curl_setopt($ch, CURLOPT_VERBOSE, $verboseOutput);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FAILONERROR, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_USERAGENT, $curlUserAgent);
        curl_setopt($ch, CURLOPT_COOKIEJAR, './cookie_jar');
        curl_setopt($ch, CURLOPT_COOKIEFILE, './cookie_jar');
        curl_setopt($ch, CURLOPT_COOKIESESSION, true);
        curl_setopt($ch, CURLOPT_URL, $this->forumUrl . '/index.php');

        $result = curl_exec($ch);
        $error = curl_error($ch);

        $success = (empty($error));
        if ($success) {
            $this->curlSession = $ch;
        } else {
            curl_close($ch);
        }
        $ch = null;

        return [
            'success' => $success,
            'error' => $error,
            'debug' => $result
        ];
    }
}



Hopefully it's easy to follow, just a curl session to get a cookie, store it, then use the session to create a post.

Any help is really appreciated.
Paul