Skip to content

Instantly share code, notes, and snippets.

@Daniel15
Last active December 6, 2021 20:37
Show Gist options
  • Star 82 You must be signed in to star a gist
  • Fork 30 You must be signed in to fork a gist
  • Save Daniel15/820281 to your computer and use it in GitHub Desktop.
Save Daniel15/820281 to your computer and use it in GitHub Desktop.
Twitter autoresponder bot

Twitter autoresponder bot

By Daniel15 (dan.cx) This is a very simple Twitter autoresponder bot. It requires PECL OAuth extension to be installed (run "pecl install oauth", or if on Windows, grab php-oauth.dll. If using cPanel you can install it via WHM). The authentication is designed for command-line usage, it won't work too well via a web browser. You'll have to sign up for an application on Twitter's site to get the consumer key and secret.

Could be modified to be more advanced (match regular expressions to answer questions, etc.)

Questions? See my blog post - http://dan.cx/blog/2011/06/twitter-autoreply-bot-dbznappa

Modified 2013-06-13 - Twitter API 1.0 discontinued, modified to use Twitter API 1.1

#!/usr/bin/php
<?php
date_default_timezone_set('Australia/Melbourne');
require('TwitterAutoReply.php');
// Consumer key and consumer secret
$twitter = new TwitterAutoReply('******', '************************');
// Token and secret
$twitter->setToken('********-*******************', '*****************8');
$twitter->addReply('over 9000', 'WHAT?! NINE THOUSAND?!');
$twitter->addReply('over nine thousand', 'WHAT?! NINE THOUSAND?!');
$twitter->run();
?>
<?php
// Twitter autoreply
// By Daniel15 <http://dan.cx/>
// Modified 2013-06-13 to support Twitter API 1.1
class TwitterAutoReply
{
// Constants
const SEARCH_URL = 'https://api.twitter.com/1.1/search/tweets.json?q=%s&since_id=%s';
const UPDATE_URL = 'https://api.twitter.com/1.1/statuses/update.json';
const VERIFY_URL = 'https://api.twitter.com/1.1/account/verify_credentials.json';
const REQUEST_TOKEN_URL = 'https://twitter.com/oauth/request_token';
const ACCESS_TOKEN_URL = 'https://twitter.com/oauth/access_token';
const AUTH_URL = 'http://twitter.com/oauth/authorize';
// Variables
private $_replies = array();
private $_oauth;
private $_screenName;
// Methods
public function __construct($consumer_key, $consumer_secret)
{
$this->_oauth = new OAuth($consumer_key, $consumer_secret, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
$this->_oauth->disableSSLChecks();
}
public function setToken($token, $secret)
{
$this->_oauth->setToken($token, $secret);
}
public function addReply($term, $reply)
{
$this->_replies[$term] = $reply;
}
public function run()
{
echo '========= ', date('Y-m-d g:i:s A'), " - Started =========\n";
// Get the last ID we replied to
$since_id = @file_get_contents('since_id');
if ($since_id == null)
$since_id = 0;
// This will store the ID of the last tweet we get
$max_id = $since_id;
// Verify their Twitter account is valid
if (!$this->verifyAccountWorks())
{
// Get a request token and show instructions
$this->doAuth();
die();
}
// Go through each reply
foreach ($this->_replies as $term => $reply)
{
echo 'Performing search for "', $term, '"... ';
$this->_oauth->fetch(sprintf(self::SEARCH_URL, urlencode($term), $since_id));
$search = json_decode($this->_oauth->getLastResponse());
echo 'Done, ', count($search->statuses), " results.\n";
// Store the max ID
if ($search->search_metadata->max_id_str > $max_id)
$max_id = $search->search_metadata->max_id_str;
// Now let's go through the results
foreach ($search->statuses as $tweet)
{
// Ensure we don't reply to ourself!
if ($tweet->user->screen_name == $this->_screenName)
continue;
$this->sendReply($tweet, $reply);
sleep(1);
}
}
file_put_contents('since_id', $max_id);
echo '========= ', date('Y-m-d g:i:s A'), " - Finished =========\n";
}
private function sendReply($tweet, $reply)
{
try
{
echo '@', $tweet->user->screen_name, ' said: ', $tweet->text, "\n";
$this->_oauth->fetch(self::UPDATE_URL, array(
'status' => '@' . $tweet->user->screen_name . ' ' . $reply,
'in_reply_to_status_id' => $tweet->id_str,
), OAUTH_HTTP_METHOD_POST);
}
catch (OAuthException $ex)
{
echo 'ERROR: ' . $ex->lastResponse;
die();
}
}
private function verifyAccountWorks()
{
try
{
$this->_oauth->fetch(self::VERIFY_URL, array(), OAUTH_HTTP_METHOD_GET);
$response = json_decode($this->_oauth->getLastResponse());
$this->_screenName = $response->screen_name;
return true;
}
catch (Exception $ex)
{
return false;
}
}
private function doAuth()
{
// First get a request token, and prompt them to go to the URL
$request_token_info = $this->_oauth->getRequestToken(self::REQUEST_TOKEN_URL);
echo 'Please navigate to the following URL to get an authentication token:', "\n";
echo self::AUTH_URL, '?oauth_token=', $request_token_info['oauth_token'], "\n";
echo 'Once done (and you have a PIN number), press ENTER.';
fread(STDIN, 10);
echo 'PIN Number: ';
$pin = trim(fread(STDIN, 10));
// Now let's swap that for an access token
$this->_oauth->setToken($request_token_info['oauth_token'], $request_token_info['oauth_token_secret']);
$access_token_info = $this->_oauth->getAccessToken(self::ACCESS_TOKEN_URL, null, $pin);
echo 'Success, ', $access_token_info['screen_name'], ' has authorized the application. Please change your setToken line to something like the following:', "\n";
echo '$twitter->setToken(\'', $access_token_info['oauth_token'], '\', \'', $access_token_info['oauth_token_secret'], '\');';
die();
}
public function testTweet()
{
$this->_oauth->fetch(self::UPDATE_URL, array(
'status' => 'Test from TwitterAutoReply',
), OAUTH_HTTP_METHOD_POST);
}
}
?>
@sarawutbody
Copy link

Hi Daniel.. @Daniel15

!/usr/bin/php

Fatal error: Class 'OAuth' not found in C:\xampp\htdocs\Twitter-Keyword-AutoReply-master\TwitterAutoReply.php on line 24

@hsanb
Copy link

hsanb commented Mar 6, 2015

how can i set up please !

@Shermainnnnw
Copy link

How do i use this? what do i need to do this 24/7 even if my pc is off or is it for a webhost? does someone have a youtube tutorial? i want this very much!

@KristianQ
Copy link

Does not seem to run.

@Daniel15
Copy link
Author

@Vanqaqi What errors are you encountering?

@TheSecretCandy You need a server you can upload the script onto. A webhost is fine if they have SSH access.

@ceremonials
Copy link

hi! is there a way to set this up so it replies with a specific tweet automatically to users I follow, regardless of WHAT they tweet?

@AmgedOsman
Copy link

So here's my contribution
Make sure it's not a retweet
Make sure it's not a reply

                  ` // Now let's go through the results
        foreach ($search->statuses as $tweet)
        {

            // Ensure we don't reply to ourself!
            if ($tweet->user->screen_name == $this->_screenName)
                continue;

            //@Amged Edits
            // Ensure it's not a retweet
            $pos = strpos($tweet->text, 'RT');
            if ( $pos === 0 )
            continue;

            //@Amged Edits
            //Ensure it's not a reply to a conversation
            if ($tweet->in_reply_to_status_id)
            continue;

            //@Amged Edits - Debug
            /*
            echo "<pre>";
            echo print_r($tweet);
            echo "</pre><br /> ---------------------<br />";
            */
            $this->sendReply($tweet, $reply);
            sleep(1);

        }` 

@agusrevival
Copy link

how to use in laravel ?

@Silverstonery
Copy link

Silverstonery commented Apr 29, 2017

@OmgedOsman Good edits. I've made some major edits to your modified version. Allows for keyword filtering. If keyword is present tweet will be ignored.
$badstrings is a string array.
Usage: $twitter->addReply('Search for', 'Reply with', $badstrings)
Filtering isn't necessary, this will work too: $twitter->addReply('Search for', 'Reply with')

<?php
// Twitter autoreply
// By Daniel15 <http://dan.cx/>
// Modified 2013-06-13 to support Twitter API 1.1
//Modified 2017-04-29 to allow for advanced keyword filtering(@Silverstonery)
class TwitterAutoReply
{
	// Constants
	const SEARCH_URL = 'https://api.twitter.com/1.1/search/tweets.json?q=%s&since_id=%s';
	const UPDATE_URL = 'https://api.twitter.com/1.1/statuses/update.json';
	const VERIFY_URL = 'https://api.twitter.com/1.1/account/verify_credentials.json';
	const REQUEST_TOKEN_URL = 'https://twitter.com/oauth/request_token';
	const ACCESS_TOKEN_URL = 'https://twitter.com/oauth/access_token';
	const AUTH_URL = 'http://twitter.com/oauth/authorize';
	
	// Variables
	private $_replies = array();
	private $_oauth;
	private $_screenName;
	private $_badstrings = null; //@Silverstronery Edits: Declare Bad strings variable
	// Methods
	public function __construct($consumer_key, $consumer_secret)
	{
		$this->_oauth = new OAuth($consumer_key, $consumer_secret, OAUTH_SIG_METHOD_HMACSHA1, OAUTH_AUTH_TYPE_URI);
		$this->_oauth->disableSSLChecks();
	}
	
	public function setToken($token, $secret)
	{
		$this->_oauth->setToken($token, $secret);
	}
	
	public function addReply($term, $reply, $bad)
	{
		$this->_replies[$term] = $reply;
		$this->_badstrings = $bad;
	}
	
	public function run()
	{
		//echo '========= ', date('Y-m-d g:i:s A'), " - Started =========\n";
		// Get the last ID we replied to
		$since_id = @file_get_contents('since_id');
		if ($since_id == null)
			$since_id = 0;
			
		// This will store the ID of the last tweet we get
		$max_id = $since_id;
		
		// Verify their Twitter account is valid
		if (!$this->verifyAccountWorks())
		{
			// Get a request token and show instructions
			$this->doAuth();
			die();
		}
		
		// Go through each reply
		foreach ($this->_replies as $term => $reply)
		{
			echo 'Performing search for "', $term, '"... ';
			$this->_oauth->fetch(sprintf(self::SEARCH_URL, urlencode($term), $since_id));
			$search = json_decode($this->_oauth->getLastResponse());
			echo 'Done, ', count($search->statuses), " results.\n";
			// Store the max ID
			if ($search->search_metadata->max_id_str > $max_id)
				$max_id = $search->search_metadata->max_id_str;
			
			// Now let's go through the results
			foreach ($search->statuses as $tweet)
        {

            // Ensure we don't reply to ourself!
            if ($tweet->user->screen_name == $this->_screenName)
                continue;

            //@Amged Edits
            // Ensure it's not a retweet
            $pos = strpos($tweet->text, 'RT');
            if ( $pos === 0 ){
            continue;
            }
            
            //@Silverstonery Edits
            //Filter through tweets
            $good = true;
            if($this->_badstrings != null){
                foreach ($this->_badstrings as $badstring) {
                    //if (strstr($tweet->text, $badstring)) { //Alternate version(Difference in speed)
                    if (strpos($tweet->text, $badstring) !== false) {
                        $good = false; 
                    }
                }
            }
            
            if(!$good){
                continue;
            }
            
            //@Amged Edits - Debug
            /*
            echo "<pre>";
            echo print_r($tweet);
            echo "</pre><br /> ---------------------<br />";
            */
            $this->sendReply($tweet, $reply);
            sleep(8); //@Silverstonery edit. Prevent bot from getting disabled, increases speed because 5 minute bot timouts from twitter take longer to happen than 7 more seconds of waiting

        }
		}
		
		file_put_contents('since_id', $max_id);
		echo '========= ', date('Y-m-d g:i:s A'), " - Finished =========\n";
	}
	
	private function sendReply($tweet, $reply)
	{
		try
		{
			echo '@', $tweet->user->screen_name, ' said: ', $tweet->text, "\n";
			$this->_oauth->fetch(self::UPDATE_URL, array(
				'status' => '@' . $tweet->user->screen_name . ' ' . $reply,
				'in_reply_to_status_id' => $tweet->id_str,
			), OAUTH_HTTP_METHOD_POST);
		}
		catch (OAuthException $ex) 
		{
				echo 'ERROR: ' . $ex->lastResponse;
				die();
		}
	}
	
	private function verifyAccountWorks()
	{
		try
		{
			$this->_oauth->fetch(self::VERIFY_URL, array(), OAUTH_HTTP_METHOD_GET);
			$response = json_decode($this->_oauth->getLastResponse());
			$this->_screenName = $response->screen_name;
			return true;
		}
		catch (Exception $ex)
		{
			return false;
		}
	}
	
	private function doAuth()
	{
		// First get a request token, and prompt them to go to the URL
		$request_token_info = $this->_oauth->getRequestToken(self::REQUEST_TOKEN_URL);
		echo 'Please navigate to the following URL to get an authentication token:', "\n";
		echo self::AUTH_URL, '?oauth_token=', $request_token_info['oauth_token'], "\n";
		echo 'Once done (and you have a PIN number), press ENTER.';
		fread(STDIN, 10);
		
		echo 'PIN Number: ';
		$pin = trim(fread(STDIN, 10));
		
		// Now let's swap that for an access token
		$this->_oauth->setToken($request_token_info['oauth_token'], $request_token_info['oauth_token_secret']);
		$access_token_info = $this->_oauth->getAccessToken(self::ACCESS_TOKEN_URL, null, $pin);
		
		echo 'Success, ', $access_token_info['screen_name'], ' has authorized the application. Please change your setToken line to something like the following:', "\n";
		echo '$twitter->setToken(\'', $access_token_info['oauth_token'], '\', \'', $access_token_info['oauth_token_secret'], '\');';
		die();
	}
	
	public function testTweet()
	{
		$this->_oauth->fetch(self::UPDATE_URL, array(
			'status' => 'Test from TwitterAutoReply',
		), OAUTH_HTTP_METHOD_POST);
	}
}
?>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment