1<?php 2/** 3 * AutoTweet 2 plugin 4 * Post the information of changes to Twitter 5 * 6 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 7 * @author HokkaidoPerson <dosankomali@yahoo.co.jp> 8 */ 9 10if(!defined('DOKU_INC')) die(); 11 12 13class action_plugin_autotweet2 extends DokuWiki_Action_Plugin { 14 15 public function register(Doku_Event_Handler $controller) { 16 $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'AFTER', $this, 'tweet', array()); 17 } 18 19 20 //Reference: https://syncer.jp/Web/API/Twitter/REST_API/ 21 22 public function tweet(Doku_Event $event, $param) { 23 24 // Load configurations and set up 25 $api_key = $this->getConf('apiKey'); 26 $api_secret = $this->getConf('apiSecret'); 27 $access_token = $this->getConf('accessToken'); 28 $access_token_secret = $this->getConf('accessTokenSecret'); 29 $request_url = 'https://api.twitter.com/1.1/statuses/update.json' ; 30 $request_method = 'POST' ; 31 32 // If keys and secrets are empty, the function will not run 33 if ($api_key == '' or $api_secret == '' or $access_token == '' or $access_token_secret == '') return; 34 35 // Check the blacklist 36 $blacklist = '|' . $this->getConf('blacklist') . '|'; 37 $savingid = $event->data['id']; 38 if (strpos($blacklist, '|' . $savingid . '|') !== FALSE) return; 39 40 41 // Check the type of editing and the conf "subjectOfTweet" 42 $subject = $this->getConf('subjectOfTweet'); 43 44 switch ($event->data['changeType']) { 45 case DOKU_CHANGE_TYPE_EDIT : if (strpos($subject, 'edit') === FALSE) return; else $edittype = $this->getLang('edit'); 46 break; 47 case DOKU_CHANGE_TYPE_REVERT : if (strpos($subject, 'revert') === FALSE) return; else $edittype = $this->getLang('revert'); 48 break; 49 case DOKU_CHANGE_TYPE_CREATE : if (strpos($subject, 'create') === FALSE) return; else $edittype = $this->getLang('create'); 50 break; 51 case DOKU_CHANGE_TYPE_DELETE : if (strpos($subject, 'delete') === FALSE) return; else $edittype = $this->getLang('delete'); 52 break; 53 case DOKU_CHANGE_TYPE_MINOR_EDIT: if (strpos($subject, 'minor') === FALSE) return; else $edittype = $this->getLang('minor'); 54 break; 55 default: 56 return; 57 } 58 59 // Construct the message 60 $message = $this->getConf('template'); 61 $message = str_replace('###WIKITITLE###', $conf['title'], $message); 62 $message = str_replace('###PAGETITLE###', tpl_pagetitle($savingid, 1), $message); 63 $message = str_replace('###TYPE###', $edittype, $message); 64 $message = str_replace('###SUMMARY###', $event->data['summary'], $message); 65 66 if (!isset($_SERVER['REMOTE_USER'])) { 67 switch ($this->getConf('guestIP')) { 68 case 'show': $message = str_replace('###EDITOR###', $_SERVER['REMOTE_ADDR'], $message); 69 break; 70 case 'alt' : 71 if(!plugin_isdisabled('hidingip')) { 72 $hidingip = plugin_load('helper', 'hidingip'); 73 $message = str_replace('###EDITOR###', $hidingip->altText(), $message); 74 break; 75 } 76 // Else, fall through 77 default : $message = str_replace('###EDITOR###', '', $message); 78 } 79 } else $message = str_replace('###EDITOR###', userlink(null, true), $message); 80 81 $pageurl = wl($savingid, '', TRUE); 82 83 if (strpos($message, '###PAGEURL###') === FALSE) $message .= ' ' . $pageurl; else $message = str_replace('###PAGEURL###', $pageurl, $message); 84 85 // Insert a space after "@" not to violent the Twitter rule that prohibits "automated @ tweets" 86 $message = str_replace('@', '@ ', $message); // one-byte @ 87 $message = str_replace('@', '@ ', $message); // two-byte @ 88 89 // Copied and adoped from the reference above 90 // 91 // Parameter A (the option of the request) 92 $params_a = array( 93 'status' => $message , 94 ) ; 95 96 // Make a key (URL encode) 97 $signature_key = rawurlencode( $api_secret ) . '&' . rawurlencode( $access_token_secret ) ; 98 99 // Parameter B (ingredients of the signature) 100 $params_b = array( 101 'oauth_token' => $access_token , 102 'oauth_consumer_key' => $api_key , 103 'oauth_signature_method' => 'HMAC-SHA1' , 104 'oauth_timestamp' => time() , 105 'oauth_nonce' => microtime() , 106 'oauth_version' => '1.0' , 107 ) ; 108 109 // Make parameter C by merging A and B 110 $params_c = array_merge( $params_a , $params_b ) ; 111 112 // Sort the associative array in alphabetical order 113 ksort( $params_c ) ; 114 115 // Convert the associative array of parameters into the string [key=value&key=value...] 116 $request_params = http_build_query( $params_c , '' , '&' ) ; 117 118 // Follow some characters 119 $request_params = str_replace( array( '+' , '%7E' ) , array( '%20' , '~' ) , $request_params ) ; 120 121 // URL-encode the converted string 122 $request_params = rawurlencode( $request_params ) ; 123 124 // URL-encode the request method 125 // In this time, it sholdn't include [?] in the last of the URL and after 126 $encoded_request_method = rawurlencode( $request_method ) ; 127 128 // URL-encode the request URL 129 $encoded_request_url = rawurlencode( $request_url ) ; 130 131 // Merge the request method, the request URL, and the parameters by [&] 132 $signature_data = $encoded_request_method . '&' . $encoded_request_url . '&' . $request_params ; 133 134 // Using the key [$signature_key] and the data [$signature_data], make a HMAC-SHA1 type hash value 135 $hash = hash_hmac( 'sha1' , $signature_data , $signature_key , TRUE ) ; 136 137 // Base64-encode, and the [$signature] is ready 138 $signature = base64_encode( $hash ) ; 139 140 // Add the signature to the associative array of the data [$params] 141 $params_c['oauth_signature'] = $signature ; 142 143 // Convert the associative array of the parameter into the string [key=value&key=value...] 144 $header_params = http_build_query( $params_c , '' , ',' ) ; 145 146 // Context for the request 147 $context = array( 148 'http' => array( 149 'method' => $request_method , // Request method 150 'header' => array( // Header 151 'Authorization: OAuth ' . $header_params , 152 ) , 153 ) , 154 ) ; 155 156 // If there is an option, make a POST field into the context 157 if ( $params_a ) { 158 $context['http']['content'] = http_build_query( $params_a ) ; 159 } 160 161 // Request by using cURL 162 $this->curl = curl_init() ; 163 curl_setopt( $this->curl, CURLOPT_URL , $request_url ) ; // Request URL 164 curl_setopt( $this->curl, CURLOPT_HEADER, true ) ; // Get the header 165 curl_setopt( $this->curl, CURLOPT_CUSTOMREQUEST, $context['http']['method'] ) ; // Method 166 curl_setopt( $this->curl, CURLOPT_SSL_VERIFYPEER, false ) ; // Don't verify the certificate 167 curl_setopt( $this->curl, CURLOPT_RETURNTRANSFER, true ) ; // Return the result of the curl_exec with a string 168 curl_setopt( $this->curl, CURLOPT_HTTPHEADER, $context['http']['header'] ) ; // Header 169 if( isset( $context['http']['content'] ) && !empty( $context['http']['content'] ) ) { 170 curl_setopt( $this->curl, CURLOPT_POSTFIELDS, $context['http']['content'] ) ; // Request body 171 } 172 curl_setopt( $this->curl, CURLOPT_TIMEOUT, 5 ) ; // Timeout seconds 173 $res1 = curl_exec( $this->curl ) ; 174 $res2 = curl_getinfo( $this->curl ) ; 175 curl_close( $this->curl ) ; 176 177 $json = substr( $res1, $res2['header_size'] ) ; // Got data (such as JSON) 178 $header = substr( $res1, 0, $res2['header_size'] ) ; // Response header 179 180 if ($this->getConf('debug') and auth_ismanager()) { 181 msg('[Debug] Body(JSON): ' . $json); 182 msg('[Debug] Response header: ' . $header); 183 } 184 185 } 186 187 188}