This topic seems to be discussed a lot, but there appears to be no definitive answer.
I have developed a wraparound class for the TwitterAPIExchange API for Twitter. It works, in that I can post a text status, but if I try and post a status with an image, the status appears, but not the image.
I note that, I first upload the image, get an id and then add this to the ‘postfield’.
The class I have developed is shown at the end of this post, along with a small wraparound function to instatiate it, and call the various CTwitter functions.
The output that is produced (along with var_dump’s) is shown below.
From what I can see the ‘media_ids’ paramater is just being ignored and I don’t know why.
=== Output from test run ===
Soundbite harness: Start CTwitter (1.00): uploadImage: At start of function CTwitter (1.00): json: string(169) “{“media_id”:1035388812191399936,“media_id_string”:“1035388812191399936”,“size”:1660220,“expires_after_secs”:86400,“image”:{“image_type”:“image/jpeg”,“w”:4961,“h”:3307}}”
CTwitter (1.00): res: object(stdClass)#9 (5) { [“media_id”]=> int(1035388812191399936) [“media_id_string”]=> string(19) “1035388812191399936” [“size”]=> int(1660220) [“expires_after_secs”]=> int(86400) [“image”]=> object(stdClass)#10 (3) { [“image_type”]=> string(10) “image/jpeg” [“w”]=> int(4961) [“h”]=> int(3307) } }
ID at the end of uploadImage: 1035388812191399936
CTwitter (1.00): uploadImage: At end of function ID returned from uploadImage: 1035388812191399936
CTwitter (1.00): postImage: At start of function CTwitter (1.00): post: At start of function CTwitter (1.00): postfields: array(2) { [“status”]=> string(17) “Delete this tweet” [“media_ids”]=> string(19) “1035388812191399936” }
CTwitter (1.00): json: string(2457) “{“created_at”:“Fri Aug 31 04:48:25 +0000 2018”,“id”:1035388817312628737,“id_str”:“1035388817312628737”,“text”:“Delete this tweet”,“truncated”:false,“entities”:{“hashtags”:[],“symbols”:[],“user_mentions”:[],“urls”:[]},“source”:”\u003ca href=“http://www.xxxxxx.com/twitter” rel=“nofollow”\u003exxxxx\u003c/a\u003e",“in_reply_to_status_id”:null,“in_reply_to_status_id_str”:null,“in_reply_to_user_id”:null,“in_reply_to_user_id_str”:null,“in_reply_to_screen_name”:null,“user”:{“id”:180287955,“id_str”:“180287955”,“name”:“xxxxxx”,“screen_name”:“xxxxxx”,“location”:“xxxxx”,“description”:“xxxxx @xxxxx/@xxxxx. xxxxx”,“url”:“https://t.co/xxxxx",“entities”:{“url”:{“urls”:[{“url”:“https://t.co/ybqkAuOSbL”,“expanded_url”:“http://www.xxxxx.com”,“display_url”:“xxxxx.com”,“indices”:[0,23]}]},“description”:{“urls”:[]}},“protected”:false,“followers_count”:1529,“friends_count”:842,“listed_count”:159,“created_at”:"Thu Aug 19 07:36:32 +0000 2010”,“favourites_count”:1437,“utc_offset”:null,“time_zone”:null,“geo_enabled”:true,“verified”:false,“statuses_count”:43754,“lang”:“en”,“contributors_enabled”:false,“is_translator”:false,“is_translation_enabled”:false,“profile_background_color”:“FFFFFF”,“profile_background_image_url”:"http://abs.twimg.com/images/themes/theme1/bg.png",“profile_background_image_url_https”:“https://abs.twimg.com/images/themes/theme1/bg.png”,“profile_background_tile”:false,“profile_image_url”:“http://pbs.twimg.com/profile_images/775725280002355200/q7dt7vQB_normal.jpg”,“profile_image_url_https”:“https://pbs.twimg.com/profile_images/775725280002355200/q7dt7vQB_normal.jpg”,“profile_banner_url”:“https://pbs.twimg.com/profile_banners/180287955/1484967410”,“profile_link_color”:“0084B4”,“profile_sidebar_border_color”:“000203”,“profile_sidebar_fill_color”:“CFDFE6”,“profile_text_color”:“333333”,“profile_use_background_image”:true,“has_extended_profile”:false,“default_profile”:false,“default_profile_image”:false,“following”:false,“follow_request_sent”:false,“notifications”:false,“translator_type”:“none”},“geo”:null,“coordinates”:null,“place”:null,“contributors”:null,“is_quote_status”:false,“retweet_count”:0,“favorite_count”:0,“favorited”:false,“retweeted”:false,“lang”:“en”}"
CTwitter (1.00): postImage: At end of function Soundbite harness: after instatiating CTwitterSoundbite
== end ==
Any help/advice appreciated
G
=== CTwitter Class ===
class CTwitter {
// Member Variables
private $username; // Username of the main user
private $settings; // this holds the access tokens and the consumer keys
//private $runFromCron; // This indicates if the job was run from a cron (so $ROOT can’t be (easily) established
// Twitter URLs
private $baseTwitterURL;
private $statusTwitterURL;
private $uploadTwitterURL;
private $version; // Holds the current version of this class
private $className; // Holds the name of this class
private $newline = “
”; // Provides easy access to a new line
private $trace; // Defines whether we want to display (possibly debugging) information
// Paths
private $ROOT;
private $paths;
// === Constructor ===
function _construct($uname, $settings) {
$this->version = "1.00";
$this->className = "CTwitter";
$this->setTrace( true );
$this->includes();
$this->twitterURLs();
$this->username = $uname;
$this->settings = $settings_;
} // constructor
// === Destuctor ====
function __destruct() {
}
// Destuctor
private
function getNameVersion() {
return $this->getName() . " (" . $this->getVersion() . “)”;
}
private
function getName() {
return $this->className;
}
private
function getVersion() {
return $this->version;
}
// Includes the various files that are required
private function includes() {
$this->ROOT = $_SERVER['DOCUMENT_ROOT'];
require_once( $this->ROOT . '/php/classes/' . 'Cpaths.php' );
$this->paths = new Cpaths();
$this->requireClass("TwitterAPIExchange");
}
private function twitterURLs() {
$this->baseTwitterURL = 'https://api.twitter.com/1.1/';
$this->statusTwitterURL = $this->baseTwitterURL . 'statuses/update.json';
$this->uploadTwitterURL = "https://upload.twitter.com/1.1/media/upload.json";
}
private function requireClass($file) {
require_once($this->paths->getPHPClasses() . $file . ".php");
}
public function setTrace($t) {
$this->trace = $t;
}
private function post($postfields) {
if ( $this->trace ) echo $this->getNameVersion() . ": post: At start of function" . $this->newline;
echo $this->getNameVersion() . ": postfields: " . $this->newline;
var_dump($postfields);
echo $this->newline . $this->newline;
$requestMethod = 'POST';
try{
$twitter = new TwitterAPIExchange($this->settings);
$json = $twitter->buildOauth($this->statusTwitterURL, $requestMethod)
->setPostfields($postfields)
->performRequest();
echo $this->getNameVersion() . ": json: " . $this->newline;
var_dump($json);
echo $this->newline . $this->newline;
return $json;
} catch (Exception $ex) {
echo $ex->getMessage();
}
if ( $this->trace ) echo $this->getNameVersion() . ": post: At end of function" . $this->newline;
}
public function postStatus($tweet) {
$postfields = array(
'status' => $tweet
);
$this->post($postfields);
} // post
public function postImage($tweet, $id) {
if ( $this->trace ) echo $this->getNameVersion() . “: postImage: At start of function” . $this->newline;
$postfields = array('status' => $tweet, 'media_ids' => $id);
$json = $this->post($postfields);
if ( $this->trace ) echo $this->getNameVersion() . ": postImage: At end of function" . $this->newline;
} // postWithImage
public function uploadImage() {
if ( $this->trace ) echo $this->getNameVersion() . “: uploadImage: At start of function” . $this->newline;
$twitter = new TwitterAPIExchange($this->settings);
$file = file_get_contents($this->ROOT . '/publications/Images/abk2011.jpg');
$data = base64_encode($file);
$method = "POST";
$params = array(
"media_data" => $data
);
$json = $twitter->setPostfields( $params )->buildOauth( $this->uploadTwitterURL, $method )->performRequest();
echo $this->getNameVersion() . ": json: " . $this->newline;
var_dump($json);
echo $this->newline . $this->newline;
// Result is a json string
$res = json_decode( $json );
echo $this->getNameVersion() . ": res: " . $this->newline;
var_dump($res);
echo $this->newline . $this->newline;
// Extract media id
$id = $res->media_id_string;
echo "ID at the end of uploadImage: " . $id . $this->newline . $this->newline;
if ( $this->trace ) echo $this->getNameVersion() . ": uploadImage: At end of function" . $this->newline;
return $id;
}
} // CTwitter class
=== End: CTwitter Class ===
=== Calling CTwitter Class ===
function __construct($uname) {
$this->version = "1.00";
$this->className = "CTwitterSoundbite";
$this->setTrace( false );
$this->includes();
if($this->trace) echo $this->getNameVersion() . ": __construct" . $this->newline;
$this->username = $uname;
$this->twitterDets = new CTwitterUserDetails($this->getUser());
$this->twitter = new CTwitter($this->getUser(), $this->twitterDets->getSettings());
$id = $this->twitter->uploadImage();
echo "ID returned from uploadImage: " . $id . $this->newline . $this->newline;
$this->twitter->postImage("Delete this tweet", $id);
} // constructor