Commit 66f01bb2 authored by void's avatar void

plugin: autopost to mastodon

parent dcd12635
# MastodonOAuthPHP
PHP Library for Mastodon REST API
## What's in it?
* App creation.
* Full oAuth implementation to authorize your App by users.
* Create and get authorization token, access token, client_id, client_secret and bearer token.
* Authenticate users
* Get user information
* Get user followers and following
* Get user status
* Post status update
## Installation using Composer
```
composer require thecodingcompany/php-mastodon
```
## Questions and example?
Yes, mail me at: vangelier at hotmail dot com
Contact me on #Twitter @digital_human
Contact me on #Mastodon https://mastodon.social/@digitalhuman
## Get started
### Step 1
First step is you need to create a so called App. This app represents your 'service'. With this app you provide services to users or use Mastodon for other reasons.
To create an App is as simple as:
```
<?php
/**
* Intellectual Property of #Mastodon
*
* @copyright (c) 2017, #Mastodon
* @author V.A. (Victor) Angelier <victor@thecodingcompany.se>
* @version 1.0
* @license http://www.apache.org/licenses/GPL-compatibility.html GPL
*
*/
require_once("autoload.php");
$t = new \theCodingCompany\Mastodon();
/**
* Create a new App and get the client_id and client_secret
*/
$token_info = $t->createApp("MyCoolAppName", "http://www.internet.com");
$serializedData = serialize($token_info);
// save the special tokens to a file, so you don't lose them
file_put_contents('mastodon_creds', $serializedData); // this will save it in the same folder as this file
?>
```
The parameter ```$token_info``` now has your 'client_id' and 'client_secret'. This information is important for the rest of your life ;). Store it in a file, DB or array. You need this everytime you communicate with Mastodon.
### Step 2
Now you (your app) wants to provide services to a user. For this the user needs to authorize your app. Else you can't help him/her. To do this you need to redirect the user, with your tokens to Mastodon and ask for permission so to say. And example:
```
<?php
/**
* Intellectual Property of #Mastodon
*
* @copyright (c) 2017, #Mastodon
* @author V.A. (Victor) Angelier <victor@thecodingcompany.se>
* @version 1.0
* @license http://www.apache.org/licenses/GPL-compatibility.html GPL
*
*/
require_once("autoload.php");
$recoveredData = file_get_contents('mastodon_creds');
// unserializing to get actual array
$recoveredArray = unserialize($recoveredData);
$t = new \theCodingCompany\Mastodon();
/**
* We now have a client_id and client_secret. Set the domain and provide the library with your App's client_id and secret.
*/
$t->setMastodonDomain("mastodon.social"); // Set the mastodon domain, you can remove this line if you're using mastodon.social as it's the default
$t->setCredentials($recoveredArray); // use the keys from the file we stored in Step 1
/**
* Now that is set we can get the Authorization URL and redirect the user to Mastodon
* After the user approves your App, it will return with an Access Token.
*/
$auth_url = $t->getAuthUrl();
header("Location: {$auth_url}", true);
exit;
```
### Step 3
So you now have 3 tokens. The client_id, client_secret and the users access_token. Now exchange the access token for a bearer token and you are done. Save these tokens!
```
<?php
/**
* Intellectual Property of #Mastodon
*
* @copyright (c) 2017, #Mastodon
* @author V.A. (Victor) Angelier <victor@thecodingcompany.se>
* @version 1.0
* @license http://www.apache.org/licenses/GPL-compatibility.html GPL
*
*/
require_once("autoload.php");
$recoveredData = file_get_contents('mastodon_creds');
// unserializing to get actual array
$recoveredArray = unserialize($recoveredData);
$t = new \theCodingCompany\Mastodon();
/**
* We now have a client_id and client_secret. Set the domain and provide the library with your App's client_id and secret.
*/
$t->setMastodonDomain("mastodon.social"); // Set the mastodon domain, you can remove this line if you're using mastodon.social as it's the default
$t->setCredentials(recoveredArray); // use the keys from the file we stored in Step 1
$token_info = $t->getAccessToken("7c47d0c636314a1dff21reryyy5edf91884856dc0f78148f848d475136"); //The access token you received in step 2 from the user.
/**
* The above '$token_info' will now give you a bearer token (If successfull), you also need to store that and keep it safe!
*
*/
```
## Step 4
To then post a status, you just do this:
```
require_once("autoload.php");
$t = new \theCodingCompany\Mastodon();
$t->setMastodonDomain(website address); // change this to whatever Mastodon instance you're using, or remove it entirely if you're using mastodon.social (as it's the default)
$t->setCredentials($credentials); // where $credentials are your "client_id", "client_secret" and "bearer" in the form of an array with those exact names (from what you got in the earlier steps)
$t->postStatus('API Test - PLZ ignore <3');
```
## Full code overview options etc
```
<?php
/**
* Intellectual Property of #Mastodon
*
* @copyright (c) 2017, #Mastodon
* @author V.A. (Victor) Angelier <victor@thecodingcompany.se>
* @version 1.0
* @license http://www.apache.org/licenses/GPL-compatibility.html GPL
*
*/
require_once("autoload.php");
$t = new \theCodingCompany\Mastodon();
/**
* Create a new App and get the client_id and client_secret
*/
$token_info = $t->createApp("MyCoolAppName", "http://www.internet.com");
//Get the authorization url
$auth_url = $t->getAuthUrl();
/*
* 1) Send the above URL '$auth_url' to the user. The need to authorize your App.
* 2) When they authorized your app, they will receive a token. The authorization token.
* 3) Put the authorization token in the request below to exchange it for a bearer token.
*/
//Request the bearer token
$token_info = $t->getAccessToken("7c47d0c636314a1dff21reryyy5edf91884856dc0f78148f848d475136");
/**
* The above '$token_info' will now be an array with the info like below. (If successfull)
* No these are not real, your right.
*
{
"client_id": "87885c2bf1a9d9845345345318d1eeeb1e48bb676aa747d3216adb96f07",
"client_secret": "a1284899df5250bd345345f5fb971a5af5c520ca2c3e4ce10c203f81c6",
"bearer": "77e0daa7f252941ae8343543653454f4de8ca7ae087caec4ba85a363d5e08de0d"
}
*/
/**
* Authenticate a user by username and password and receive the bearer token
*/
$bearer_token = $t->authUser("vangelier@hotmail.com", "MySecretP@ssW0rd");
/**
* Get the userinfo by authentication
*/
$user_info = $t->getUser("vangelier@hotmail.com", "MySecretP@ssW0rd");
/**
* Get user followers / following
*/
$followers = $t->authenticate("vangelier@hotmail.com", "MySecretP@ssW0rd")
->getFollowers();
/**
* Get user statusses
*/
$statusses = $t->authenticate("vangelier@hotmail.com", "MySecretP@ssW0rd")
->getStatuses();
/**
* Post status update
*/
$status = $t->authenticate("vangelier@hotmail.com", "MySecretP@ssW0rd")
->postStatus("Text status update");
```
<?php
/**
* Intellectual Property of #Mastodon
*
* @copyright (c) 2017, #Mastodon
* @author V.A. (Victor) Angelier <victor@thecodingcompany.se>
* @version 1.0
* @license http://www.apache.org/licenses/GPL-compatibility.html GPL
*
*/
define('CLASS_DIR', __DIR__);
set_include_path(get_include_path().PATH_SEPARATOR.CLASS_DIR);
spl_autoload_register(function($name){
//For namespaces we replace \ with / to correct the Path
$filename = str_replace("\\", "/", $name);
require_once "{$filename}.php";
});
\ No newline at end of file
{
"name": "thecodingcompany/php-mastodon",
"type": "library",
"description": "Mastodon PHP library oAuth and API",
"keywords": ["php","mastodon","api","oauth"],
"homepage": "https://github.com/TheCodingCompany/MastodonOAuthPHP",
"license": "MIT",
"authors": [
{
"name": "Victor Angelier",
"email": "vangelier@hotmail.com",
"homepage": "https://www.thecodingcompany.se",
"role": "Founder"
}
],
"require": {
"php": ">=5.6.0"
},
"autoload": {
"psr-4": {
"theCodingCompany\\": "theCodingCompany/"
}
}
}
<?php
/**
* Intellectual Property of #Mastodon
*
* @copyright (c) 2017, #Mastodon
* @author V.A. (Victor) Angelier <victor@thecodingcompany.se>
* @version 1.0
* @license http://www.apache.org/licenses/GPL-compatibility.html GPL
*
*/
require_once("autoload.php");
$t = new \theCodingCompany\Mastodon();
/**
* Create a new App and get the client_id and client_secret
*/
$token_info = $t->createApp("MyCoolAppName", "http://www.internet.com");
//Get the authorization url
$auth_url = $t->getAuthUrl();
/*
* 1) Send the above URL '$auth_url' to the user. The need to authorize your App.
* 2) When they authorized your app, they will receive a token. The authorization token.
* 3) Put the authorization token in the request below to exchange it for a bearer token.
*/
//Request the bearer token
$token_info = $t->getAccessToken("7c47d0c636314a1dff21reryyy5edf91884856dc0f78148f848d475136");
/**
* The above '$token_info' will now be an array with the info like below. (If successfull)
* No these are not real, your right.
*
{
"client_id": "87885c2bf1a9d9845345345318d1eeeb1e48bb676aa747d3216adb96f07",
"client_secret": "a1284899df5250bd345345f5fb971a5af5c520ca2c3e4ce10c203f81c6",
"bearer": "77e0daa7f252941ae8343543653454f4de8ca7ae087caec4ba85a363d5e08de0d"
}
*/
/**
* Authenticate a user by username and password and receive the bearer token
*/
$bearer_token = $t->authUser("vangelier@hotmail.com", "MySecretP@ssW0rd");
/**
* Get the userinfo by authentication
*/
$user_info = $t->getUser("vangelier@hotmail.com", "MySecretP@ssW0rd");
/**
* Get user followers / following
*/
$followers = $t->authenticate("vangelier@hotmail.com", "MySecretP@ssW0rd")
->getFollowers();
/**
* Get user statusses
*/
$statusses = $t->authenticate("vangelier@hotmail.com", "MySecretP@ssW0rd")
->getStatuses();
<?php
/**
* Intellectual Property of #Mastodon
*
* @copyright (c) 2017, #Mastodon
* @author V.A. (Victor) Angelier <victor@thecodingcompany.se>
* @version 1.0
* @license http://www.apache.org/licenses/GPL-compatibility.html GPL
*
*/
namespace theCodingCompany;
/**
* HTTP Request object finetune for High Security
*/
final class HttpRequest
{
/**
* Holds our base path. In most cases this is just /, but it can be /api for example
* @var string
*/
private static $base_path = "/";
/**
* Base URL without leading /
* @var string
*/
private static $base_url = "";
/**
* Holds our instance
* @var array
*/
private static $instance = array();
/**
* Enable debugging
* @var bool
*/
private static $debug = false;
/**
* Construct new HttpRequest
* @param string $base_url Base url like http://api.website.com without leading /
* @param string $base_path Base path like, / or /api
*/
protected function __construct($base_url = "", $base_path = "/") {
self::$base_path = $base_path;
self::$base_url = $base_url;
}
protected function __clone(){}
protected function __wakeup(){}
/**
* Singleton design pattern
* @param string $base_url The full FQDN url. http://api.domainname.com
* @param string $base_path The endpoint. We start at /
* @return HttpRequest instance
*/
public static function Instance($base_url = "", $base_path = "/"){
$cls = get_called_class();
if(!isset(self::$instance[$cls])){
self::$instance[$cls] = new HttpRequest($base_url, $base_path);
}
return self::$instance[$cls];
}
/**
* HTTP POST request
* @param string $path
* @param array $parameters
* @param array $headers
* @return bool
*/
public static function Post($path = "", $parameters = array(), $headers = array()){
//Sen the request and return response
$post_data = json_encode($parameters);
return self::http_request(
"POST",
self::$base_url.self::$base_path.$path,
$headers,
$post_data
);
}
/**
* HTTP GET request
* @param string $path
* @param array $parameters
* @param array $headers
* @return bool
*/
public static function Get($path = "", $parameters = array(), $headers = array()){
//Sen the request and return response
return self::http_request(
"GET",
self::$base_url.self::$base_path.$path,
$headers,
$parameters
);
}
/**
* Buikd the HTTP request
* @param string $method GET|POST
* @param string $url
* @param array $headers
* @param array $parameters
* @return boolean
*/
private static function http_request($method = "GET", $url = "", $headers = array(), $parameters = array()) {
//Check if we have parameters to post
if (count($parameters) > 0 && is_array($parameters)) {
$content = "";
foreach($parameters as $k => $v) {
$content .= "&".urlencode($k)."=" . urlencode($v);
}
// Strip first & sign
$content = substr($content, 1);
// If the method is get, append to the URL
if ($method == "GET") {
$url .= "?" . $content;
$body = "";
}
// Otherwise, post in the content
else {
$body = $content;
}
}
elseif ($parameters) {
$body = $parameters;
}
$args = array(
'method' => $method,
'headers' => $headers,
'body' => $body,
'timeout' => '30',
'httpversion' => '1.1'
);
$response = wp_remote_request( $url, $args );
$body = wp_remote_retrieve_body($response);
if (is_wp_error($response)) {
$error = "<pre>" . print_r(error_get_last(), true) . "</pre>";
$error .= "<pre>Error Found ( ".$response->get_error_message()." )</pre>";
if(self::$debug){ print_r($error); }
return $error;
}
else{
//Debug the response/url
self::debug_response($url, null);
if (($json = \json_decode($body, true)) !== NULL) {
return $json;
}
else {
return $body;
}
}
}
/**
* Debug method for response analyzing
* @param string $url
* @param resource $context
*/
private static function debug_response($url, $context){
//Get and debug headers
if(self::$debug){
//Get meta data for debugging
$fp = @fopen($url, "r", false, $context);
if($fp){
$req_headers = stream_get_meta_data($fp);
if(isset($req_headers["wrapper_data"])){
echo "<pre>".print_r($req_headers["wrapper_data"], true)."</pre>";
}else{
echo "<pre>".print_r($req_headers, true)."</pre>";
}
}
echo "<pre>Check host alive headers<br/>\r\n";
$headers = @get_headers($url);
if($headers !== FALSE){
print_r($headers);
}
echo "</pre>";
}
}
}
<?php
/**
* Intellectual Property of #Mastodon
*
* @copyright (c) 2017, #Mastodon
* @author V.A. (Victor) Angelier <victor@thecodingcompany.se>
* @version 1.0
* @license http://www.apache.org/licenses/GPL-compatibility.html GPL
*
*/
namespace theCodingCompany;
use \theCodingCompany\HttpRequest;
/**
* Mastodon main class
*/
class Mastodon
{
//Mastodon oAuth
use \theCodingCompany\oAuth;
/**
* Holds our current user_id for :id in API calls
* @var string
*/
private $mastodon_user_id = null;
/**
* Holds our current userinfo
* @var array
*/
private $mastodon_userinfo = null;
/**
* Construct new Mastodon class
*/
public function __construct($domainname = "mastodon.social") {
//Set the domain name to use
$this->setMastodonDomain($domainname);
}
/**
* Create an App and get client_id and client_secret
* @param string $name
* @param string $website_url
* @return array|bool
*/
public function createApp($name, $website_url){
if(!empty($name) && !empty($website_url)){
//Set our info
$this->app_config["client_name"] = $name;
$this->app_config["website"] = $website_url;
return $this->getAppConfig();
}
return false;
}
/**
* Authenticate the user
* @param string $username
* @param string $password
* @return $this
*/
public function authenticate($username = null, $password = null) {
$this->authUser($username, $password);
//Set current working userid
$this->mastodon_userinfo = $this->getUser();
return $this; //For method chaining
}
/**
* Post a new status to your {visibility} timeline
* @param string $text
* @param string $visibility
* @return HttpRequest | bool
*/
public function postStatus($text = "", $visibility = "public", $in_reply_to_id = null){
if($this->getCredentials()){
$headers = $this->getHeaders();
//Create our object
$http = HttpRequest::Instance($this->getApiURL());
$status = $http::Post(
"api/v1/statuses",
array(
"status" => $text,
"visibility" => $visibility,
"in_reply_to_id" => $in_reply_to_id
),
$headers
);
return $status;
}
return false;
}
/**
* Get mastodon user
*/
public function getUser(){
if(empty($this->mastodon_userinfo)){
//Create our object
$http = HttpRequest::Instance($this->getApiURL());
$user_info = $http::Get(
"api/v1/accounts/verify_credentials",
null,
$this->getHeaders()
);
if(is_array($user_info) && isset($user_info["username"])){
$this->mastodon_user_id = (int)$user_info["id"];
return $user_info;
}else{
echo "Authentication or authorization failed\r\n";
}
}
return $this->mastodon_userinfo;
}
/**
* Get current user's followers
*/
public function getFollowers(){
if($this->mastodon_user_id > 0){
//Create our object
$http = HttpRequest::Instance($this->getApiURL());
$accounts = $http::Get(
"api/v1/accounts/{$this->mastodon_user_id}/followers",
null,
$this->getHeaders()
);
if(is_array($accounts) && count($accounts) > 0){
return $accounts;
}
}
return false;
}
/**
* Get current user's following
*/
public function getFollowing(){