Skip to content

Instantly share code, notes, and snippets.

@tiagoandrepro
Last active July 6, 2023 01:43
Show Gist options
  • Save tiagoandrepro/9e0528b254a80baf466d1a8a8e540913 to your computer and use it in GitHub Desktop.
Save tiagoandrepro/9e0528b254a80baf466d1a8a8e540913 to your computer and use it in GitHub Desktop.
{
"entry": [
{
"id": "108668968127687",
"time": 1688574192,
"changes": [
{
"field": "feed",
"value": {
"from": {
"id": "6641860719170915",
"name": "Tiago Ribeiro"
},
"item": "comment",
"post": {
"id": "108668968127687_309238454782311",
"status_type": "mobile_status_update",
"is_published": true,
"updated_time": "2023-07-05T16:23:09+0000",
"permalink_url": "https://www.facebook.com/permalink.php?story_fbid=pfbid02ohGBfrSA1yFu39kCMRP6GzP5wq3bT7tbKvrVSqWWv4BFvfmDzZMXbUmqjjYhibuKl&id=100070884768232",
"promotion_status": "inactive"
},
"verb": "add",
"message": "ore por minha familia",
"post_id": "108668968127687_309238454782311",
"parent_id": "108668968127687_309238454782311",
"comment_id": "309238454782311_1196445024343184",
"created_time": 1688574189
}
}
]
}
],
"object": "page"
}
<?php
namespace App\Jobs;
use App\Events\CommentEvent;
use App\Models\Api;
use App\Models\Comment;
use App\Models\Contact;
use App\Models\Conversation;
use App\Models\Post;
use App\Models\Service;
use App\Utils\Botpress;
use App\Utils\OpenAi;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class CommentJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* Create a new job instance.
*/
public $comment, $service;
public function __construct($service, $comment)
{
$this->comment = $comment;
$this->service = $service;
}
/**
* Execute the job.
*/
public function handle(): void
{
$service = Service::where('external_id', $this->service)->first();
$contact = Contact::updateOrCreate([
'external_id' => $this->comment['value']['from']['id'],
'service_id' => $service->id
], [
'name' => $this->comment['value']['from']['name']
]);
$post = Post::updateOrCreate([
'external_id' => $this->comment['value']['post']['id']
], [
'type' => $this->comment['value']['post']['status_type'],
'service_id' => $service->id,
]);
if ($post->wasRecentlyCreated) {
PostUpdateJob::dispatchSync($post);
}
$comment = Comment::updateOrCreate([
'external_id' => $this->comment['value']['comment_id'],
], [
'post_id' => $post->id,
'message' => $this->comment['value']['message'] ?? null,
'parent_id' => $this->comment['value']['parent_id'],
'created_time' => $this->comment['value']['created_time'],
'contact_id' => $contact->id,
'service_id' => $service->id,
'is_echo' => $service->external_id == $contact->external_id,
'photo' => $this->comment['value']['photo'] ?? null,
'video' => $this->comment['value']['video'] ?? null
]);
event(new CommentEvent($comment));
if ($comment->message == null) {
try {
$response = \App\Utils\Facebook::run('GET', $comment->external_id, [
'access_token' => $service->token,
'fields' => 'attachment'
]);
if (isset($response->attachment)) {
$comment->update([
'attachment' => json_encode($response->attachment)
]);
}
} catch (Exception $e) {
Log::info($e);
}
}
if ($service->external_id != $contact->external_id) {
if (env('APP_ENV') == 'production') {
if (!is_null($comment->message) and $comment->is_reply_comment == false) {
$responses = Botpress::setText($comment->message, $contact->id, 'ely-teruel');
$openAi = OpenAi::chat($comment->contact->name, $comment->message);
Api::create([
'comment_id' => $comment->id,
'data' => $openAi,
'source' => 'OpenAI'
]);
$comment->update([
'reply' => $openAi
]);
$comments = \App\Utils\Facebook::run('GET', $comment->external_id, [
'access_token' => $service->token,
'fields' => 'id,parent,message'
]);
if (isset($comments->parent) == false) {
\App\Utils\Facebook::run('POST', $comment->external_id . '/comments', [
'access_token' => $service->token,
'message' => $comment->reply->choices[0]->message->content
]);
$comment->update([
'is_reply_comment' => true,
]);
if ($contact->chats->count() == 0) {
foreach ($responses->responses as $response) {
\App\Utils\Facebook::run('POST', $service->external_id . '/messages', [
'access_token' => $service->token,
'message' => ['text' => $response->text],
'recipient' => ['comment_id' => $comment->external_id],
'message_type' => 'RESPONSE'
]);
$comment->update([
'is_reply_inbox' => true,
]);
}
}
}
}
}
}
}
}
{
"entry": [
{
"id": "108668968127687",
"time": 1688572808933,
"messaging": [
{
"sender": {
"id": "6615556848467333"
},
"message": {
"mid": "m_k_3qx353XpMA0iyb2J6cMOCyWxW6M26mqzWNxWlhxSK_5qIwnlpwfZxaNc3_cFF_CZwBBbGVqrg2m9LbgiVDrQ",
"text": "06149310"
},
"recipient": {
"id": "108668968127687"
},
"timestamp": 1688572808608
}
]
}
],
"object": "page"
}
{
"entry": [
{
"id": "108668968127687",
"time": 1688572823341,
"messaging": [
{
"sender": {
"id": "108668968127687"
},
"message": {
"mid": "m_6dHZ--vDXTloM9FjRT_EZOCyWxW6M26mqzWNxWlhxSLpgfjyIj9ABCeYs-ej0cRaYISlajVTj8BY0BaImdvRJQ",
"text": "Qual número da residencia?",
"app_id": 9315000188573062,
"is_echo": true
},
"recipient": {
"id": "6615556848467333"
},
"timestamp": 1688572823242
}
]
}
],
"object": "page"
}
@jjcodes78
Copy link

class WebhookData implements JsonSerializable {

    public array $entry;

    public string $object;

    public function __construct(array $data) {

        $this->entry = $data["entry"];

        $this->object = $data["object"];
    }

    public function getEntry() {
        return $this->entry[0];
    }

    public function getMessaging(): array {
        if (Arr::has($this->getEntry(), "messaging")) {
            return $this->getEntry()["messaging"];
        }
    }

    public function isMessaging(): bool
    {
        return Arr::has($this->getEntry(), "messaging");
    }

    protected function getChanges(): array
    {
        if (!collect($this->getEntry())->has("changes")) {
            return [];
        }
        return $this->getEntry()["changes"];
    }

    protected function getChangesCollection(): \Illuminate\Support\Collection
    {
        return collect($this->getChanges());
    }

    public function isComment(): bool
    {
        if (Arr::has($this->getEntry(), "changes") && count($this->getChanges()) > 0) {
            return $this->isAddingComment();
        }
        return false;
    }

    protected function isAddingComment(): bool
    {
        return ($this->getChanges()[0]["value"]["item"] == "comment"
            && $this->getChanges()[0]["value"]["verb"] == "add");
    }

    public function toJson(): string {
        return collect($this->entry)->toJson();
    }

    public function jsonSerialize(): mixed
    {
        return $this->toJson();
    }
}

@jjcodes78
Copy link

class ValidateService {
    public function __invoke(WebhookData $message, Closure $next)
    {
        $id = $message->getEntry()["id"];

        if ($id != "108668968127687") {
            return;
        }

        return $next($message);
    }
}

@jjcodes78
Copy link

class ValidateMessage {
    public function __invoke(WebhookData $message, Closure $next)
    {
        if (! $message->isMessaging()) {
            return $next($message);
        }

        // fazer algo relacionado a mensagem

        // disparar um evento?

        // atualizar o model

        return $next($message);
    }
}

@jjcodes78
Copy link

 $recMsg = (new WebhookData(receiveComment()));

//    return $recMsg->getEntry();

    $pipe = Pipeline::send($recMsg)
        ->through([
            ValidateService::class,
            ValidateMessage::class,
            ValidateComment::class,
        ])->thenReturn();

@jjcodes78
Copy link

<?php

use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Pipeline;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "web" middleware group. Make something great!
|
*/

function sendMessage(): array
{
    return json_decode(<<<EOD
{
	"entry": [
		{
			"id": "108668968127687",
			"time": 1688572823341,
			"messaging": [
				{
					"sender": {
						"id": "108668968127687"
					},
					"message": {
						"mid": "m_6dHZ--vDXTloM9FjRT_EZOCyWxW6M26mqzWNxWlhxSLpgfjyIj9ABCeYs-ej0cRaYISlajVTj8BY0BaImdvRJQ",
						"text": "Qual número da residencia?",
						"app_id": 9315000188573062,
						"is_echo": true
					},
					"recipient": {
						"id": "6615556848467333"
					},
					"timestamp": 1688572823242
				}
			]
		}
	],
	"object": "page"
}
EOD, true, 512, JSON_OBJECT_AS_ARRAY);
}

function receiveMessage(): array
{
    return json_decode(<<<EOD
{
	"entry": [
		{
			"id": "108668968127687",
			"time": 1688572808933,
			"messaging": [
				{
					"sender": {
						"id": "6615556848467333"
					},
					"message": {
						"mid": "m_k_3qx353XpMA0iyb2J6cMOCyWxW6M26mqzWNxWlhxSK_5qIwnlpwfZxaNc3_cFF_CZwBBbGVqrg2m9LbgiVDrQ",
						"text": "06149310"
					},
					"recipient": {
						"id": "108668968127687"
					},
					"timestamp": 1688572808608
				}
			]
		}
	],
	"object": "page"
}
EOD, true, 512, JSON_OBJECT_AS_ARRAY);
}

function receiveComment(): array
{
    return json_decode(<<<EOD
{
	"entry": [
		{
			"id": "108668968127687",
			"time": 1688574192,
			"changes": [
				{
					"field": "feed",
					"value": {
						"from": {
							"id": "6641860719170915",
							"name": "Tiago Ribeiro"
						},
						"item": "comment",
						"post": {
							"id": "108668968127687_309238454782311",
							"status_type": "mobile_status_update",
							"is_published": true,
							"updated_time": "2023-07-05T16:23:09+0000",
							"permalink_url": "https://www.facebook.com/permalink.php?story_fbid=pfbid02ohGBfrSA1yFu39kCMRP6GzP5wq3bT7tbKvrVSqWWv4BFvfmDzZMXbUmqjjYhibuKl&id=100070884768232",
							"promotion_status": "inactive"
						},
						"verb": "add",
						"message": "ore por minha familia",
						"post_id": "108668968127687_309238454782311",
						"parent_id": "108668968127687_309238454782311",
						"comment_id": "309238454782311_1196445024343184",
						"created_time": 1688574189
					}
				}
			]
		}
	],
	"object": "page"
}
EOD, true, 512, JSON_OBJECT_AS_ARRAY);
}

class WebhookData implements JsonSerializable {

    public array $entry;

    public string $object;

    public $service;

    public function __construct(array $data) {

        $this->entry = $data["entry"];

        $this->object = $data["object"];
    }

    public function getEntry() {
        return $this->entry[0];
    }

    public function getMessaging(): array {
        if (Arr::has($this->getEntry(), "messaging")) {
            return $this->getEntry()["messaging"];
        }

        return [];
    }

    protected function getEntryId(): string
    {
        return $this->getEntry()["id"];
    }

    protected function getSenderId(): string
    {
        if ($this->isMessaging()) {
            return $this->getMessaging()[0]["sender"]["id"];
        }
        return "";
    }

    public function itsMe(): bool
    {
        return $this->getEntryId() == $this->getSenderId();
    }

    public function isMessaging(): bool
    {
        return Arr::has($this->getEntry(), "messaging");
    }

    protected function getChanges(): array
    {
        if (!collect($this->getEntry())->has("changes")) {
            return [];
        }
        return $this->getEntry()["changes"];
    }

    protected function getChangesCollection(): \Illuminate\Support\Collection
    {
        return collect($this->getChanges());
    }

    public function isComment(): bool
    {
        if (Arr::has($this->getEntry(), "changes") && count($this->getChanges()) > 0) {
            return $this->isAddingComment();
        }
        return false;
    }

    protected function isAddingComment(): bool
    {
        return ($this->getChanges()[0]["value"]["item"] == "comment"
            && $this->getChanges()[0]["value"]["verb"] == "add");
    }

    public function toJson(): string {
        return collect([
            'data' => $this->entry,
            'service' => $this->service
        ])->toJson();
    }

    public function jsonSerialize(): mixed
    {
        return $this->toJson();
    }
}

class TransformText {

    public function __invoke(WebhookData $message, Closure $next)
    {
        $m = $message->getMessaging();



        $m[0]["message"]["text"] = "Outro texto";

        return $next($m);
    }

}

class ValidateService {
    public function __invoke(WebhookData $message, Closure $next)
    {
        $id = $message->getEntry()["id"];

        //$service = Service::where('external_id', $id)->first();

        if ($id != "108668968127687") {
            return null;
        }

        $message->service = "XPTO";

        return $next($message);
    }
}

class ValidateMessage {
    public function __invoke(WebhookData $message, Closure $next)
    {
        if (! $message->isMessaging()) {
            return $next($message);
        }

        if ($message->itsMe()) {
            return $next($message);
        }
        // fazer algo relacionado a mensagem
        //event(new (UUUUUU($meesage));

        $data = [
            "message" => $message,
            "service" => $message->service
        ];

        $pipe = Pipeline::send($data)
            ->through([
                function (array $data, Closure $next) {
                    //dd($data["service"]);
                }
            ])->thenReturn();


        // disparar um evento?

        // atualizar o model

        return $next($message);
    }
}

class ValidateComment {
    public function __invoke(WebhookData $message, Closure $next)
    {
        if (! $message->isComment()) {
            return $next($message);
        }

        return $next($message);
    }
}

class ValidatePost {
    public function __invoke(WebhookData $message, Closure $next)
    {
        if (! $message->isComment()) {
            return $next($message);
        }

        return $next($message);
    }
}


Route::get('/', function () {

    $recMsg = (new WebhookData(receiveMessage()));

//    return $recMsg->getEntry();

    $pipe = Pipeline::send($recMsg)
        ->through([
            ValidateService::class,
            ValidateMessage::class,
            ValidateComment::class,
            ValidatePost::class,
        ])->thenReturn();

    return $pipe;

});

@jjcodes78
Copy link

<?php

namespace App\DialogFlow;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;

class FacebookComment extends Model
{
    use ObjectFactory;

    protected $fillable = [
        'entry',
        'object'
    ];


    public function entries(): Attribute
    {
        return Attribute::make(
            get: fn() => collect($this->entry)
        );
    }
    public function comment(): Attribute
    {
        return Attribute::make(
            get: fn() => $this->convertArrayToObject($this->entries->first())
        );
    }

    public function changes(): Attribute
    {
        return Attribute::make(
            get: fn() => $this->convertArrayToObject($this->comment()->changes)
        );
    }
}

@jjcodes78
Copy link

<?php

namespace App\DialogFlow;

trait ObjectFactory
{
    protected function convertArrayToObject(array $data): mixed
    {
        return json_decode(json_encode($data), false);
    }
}

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