DEV Community

Cover image for How I Built a Twitter Auto-Poster Bot using Laravel
Tushar Gugnani
Tushar Gugnani

Posted on

How I Built a Twitter Auto-Poster Bot using Laravel

In this tutorial, I will demonstrate how I created a twitter-bot for auto-posting on Twitter using the powers of Laravel Zero and Laravel Dusk.

The Bot is very simple it takes the current weather details for a city from the OpenWeatherMap API, forms a nice tweet out of different variables returned by the API and tweets the weather updates it every hour.

Here is the twitter account:-

Let's see how I built it, step by step.

Step 1: Create a new Laravel Zero Project

Laravel Zero is built out of Laravel and it's a microframework for building console-based applications. Perfect for our requirements.

First, download the laravel-zero installer if you don't already have it on your machine

composer global require "laravel-zero/installer"

Once you have the installer, you can create a new project using it

laravel-zero new twitterBot

Step 2: Install Laravel-Console-Dusk

The next step is to install the Laravel-Console-Dusk Dependency on the project by running the following command inside the project

php twitterBot app:install console-dusk

Alt Text

Step 3: Create a New Console Command

Next, we need to generate a new Laravel Zero Console Command, we will be utilizing this Command as an instruction to our Bot to do the job.

php twitterBot make:command postTweet

Alt Text

Here is the code that I wrote for getting current weather updates from OpenWeatherMap API and posting it on twitter.

<?php

namespace App\Commands;

use Carbon\Carbon;
use Illuminate\Support\Str;
use Illuminate\Console\Scheduling\Schedule;
use LaravelZero\Framework\Commands\Command;

class PostTweet extends Command
{
    /**
     * The signature of the command.
     *
     * @var string
     */
    protected $signature = 'post:tweet';

    /**
     * The description of the command.
     *
     * @var string
     */
    protected $description = 'This commands posts new tweet on Twitter Timeline';

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $weather_tweet = $this->getTweetText();

        $this->postTweetOnTwitter($weather_tweet);
    }


    /**
     * This function gets current weather info and returns string 
     * 
     * @return string
     */
    public function getTweetText(){
        $client = new \GuzzleHttp\Client();
        $request = $client->get('https://api.openweathermap.org/data/2.5/weather?id=1262180&units=metric&appid=6c743793a5539486877ce02335831dc3');
        $response = $request->getBody();

        //Weather Data
        $data = json_decode($response);


        //Tweet String
        $weather_tweet = "Current Temperature ".$data->main->temp."°С , \nwind ".$data->wind->speed." m/s. clouds ".$data->clouds->all." %,\nat ".Carbon::now('Asia/Kolkata')->toDateTimeString()." \n#Nagpur #NagpurWeather ";

        return $weather_tweet;
    }

    /** 
     * Post tweet on twitter using Dusk
     * 
     */
    public function postTweetOnTwitter($tweet){
        $this->browse(function ($browser) use($tweet)  {

            $browser->visit('https://twitter.com/login')
                    ->pause(4000);


            $browser->type('session[username_or_email]', env('twitter_username'))
                    ->type('session[password]', env('twitter_password'))
                    ->pause(1000)
                    ->click('div[role="button"]')
                    ->pause(4000);

                if($browser->element('#challenge_response') != null){
                        $browser->value('#challenge_response', env('challenge_response'))
                                ->click('#email_challenge_submit')
                                ->pause(3000);
                }

                //Post Tweet
                $browser->assertSee('Home')
                    ->pause(2000)
                    ->visit('https://twitter.com/compose/tweet')
                    ->pause(3000)
                    ->click('.public-DraftStyleDefault-block')
                    ->keys(".public-DraftStyleDefault-block", $tweet)
                    ->pause(4000)
                    ->click('div[data-testid="tweetButton"]')
                    ->pause(3000);

        });
    }

    /**
     * Define the command's schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule $schedule
     * @return void
     */
    public function schedule(Schedule $schedule): void
    {
        $schedule->command(static::class)->everyThirtyMinutes();
    }
}

The handle() will get invoked on running the following command

php twitterBot post:tweet

handle() method is doing two jobs.

  1. getTweetText(): This method makes a call to OpenWeatherMap API via Guzzle and forms a tweet from the different variables returned by the API.

  2. postTweetOnTwitter(): This method makes use of Dusk to open the browser, login into twitter and post the latest weather update.

That's All.

In the schedule method, we have scheduled the command to run for every thirty minutes.

Step 4: Deploy on Server and Configure Cron

As the final part of creating this bot, we want to run this code automatically. The project is deployed on a DigitalOcean Droplet and the following command is added to the list of cron jobs.

* * * * * php /home/twitterBot/twitterbot schedule:run >> /dev/null 2>&1

Here is the working video of the Bot.

Top comments (1)

Collapse
 
andypiper profile image
Andy Piper

Curious as to why you chose to use Dusk for the Twitter piece instead of using something that uses the Twitter API such as TwitterOauth? (Web scraping and automation is against the Twitter terms of service, yet you’ve used the OpenWeather API directly). Also, be aware of the Twitter Automation Rules if you choose to build something like this t.co/automation