206 lines
6.1 KiB
PHP
206 lines
6.1 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace Core\Plug\Web3\Farcaster;
|
||
|
|
|
||
|
|
use Core\Plug\Concern\BuildsResponse;
|
||
|
|
use Core\Plug\Concern\ManagesTokens;
|
||
|
|
use Core\Plug\Concern\UsesHttp;
|
||
|
|
use Core\Plug\Contract\Readable;
|
||
|
|
use Core\Plug\Response;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Farcaster profile and cast reading.
|
||
|
|
*/
|
||
|
|
class Read implements Readable
|
||
|
|
{
|
||
|
|
use BuildsResponse;
|
||
|
|
use ManagesTokens;
|
||
|
|
use UsesHttp;
|
||
|
|
|
||
|
|
private const NEYNAR_API = 'https://api.neynar.com/v2/farcaster';
|
||
|
|
|
||
|
|
private string $apiKey = '';
|
||
|
|
|
||
|
|
private ?int $fid = null;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set the Neynar API key.
|
||
|
|
*/
|
||
|
|
public function withApiKey(string $apiKey): self
|
||
|
|
{
|
||
|
|
$this->apiKey = $apiKey;
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set the FID for user operations.
|
||
|
|
*/
|
||
|
|
public function forFid(int $fid): self
|
||
|
|
{
|
||
|
|
$this->fid = $fid;
|
||
|
|
|
||
|
|
return $this;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get a specific cast by hash.
|
||
|
|
*/
|
||
|
|
public function get(string $id): Response
|
||
|
|
{
|
||
|
|
$response = $this->http()
|
||
|
|
->withHeaders(['api_key' => $this->apiKey])
|
||
|
|
->get(self::NEYNAR_API.'/cast', [
|
||
|
|
'identifier' => $id,
|
||
|
|
'type' => 'hash',
|
||
|
|
]);
|
||
|
|
|
||
|
|
return $this->fromHttp($response, fn ($data) => [
|
||
|
|
'hash' => $data['cast']['hash'],
|
||
|
|
'text' => $data['cast']['text'],
|
||
|
|
'author' => [
|
||
|
|
'fid' => $data['cast']['author']['fid'],
|
||
|
|
'username' => $data['cast']['author']['username'],
|
||
|
|
'display_name' => $data['cast']['author']['display_name'],
|
||
|
|
'pfp_url' => $data['cast']['author']['pfp_url'],
|
||
|
|
],
|
||
|
|
'timestamp' => $data['cast']['timestamp'],
|
||
|
|
'reactions' => [
|
||
|
|
'likes_count' => $data['cast']['reactions']['likes_count'] ?? 0,
|
||
|
|
'recasts_count' => $data['cast']['reactions']['recasts_count'] ?? 0,
|
||
|
|
],
|
||
|
|
'replies' => [
|
||
|
|
'count' => $data['cast']['replies']['count'] ?? 0,
|
||
|
|
],
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get the authenticated user's profile by FID.
|
||
|
|
*/
|
||
|
|
public function me(): Response
|
||
|
|
{
|
||
|
|
if (! $this->fid) {
|
||
|
|
return $this->error('FID is required');
|
||
|
|
}
|
||
|
|
|
||
|
|
return $this->user($this->fid);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get user by FID.
|
||
|
|
*/
|
||
|
|
public function user(int $fid): Response
|
||
|
|
{
|
||
|
|
$response = $this->http()
|
||
|
|
->withHeaders(['api_key' => $this->apiKey])
|
||
|
|
->get(self::NEYNAR_API.'/user/bulk', [
|
||
|
|
'fids' => $fid,
|
||
|
|
]);
|
||
|
|
|
||
|
|
return $this->fromHttp($response, function ($data) {
|
||
|
|
$user = $data['users'][0] ?? null;
|
||
|
|
|
||
|
|
if (! $user) {
|
||
|
|
return ['error' => 'User not found'];
|
||
|
|
}
|
||
|
|
|
||
|
|
return [
|
||
|
|
'fid' => $user['fid'],
|
||
|
|
'username' => $user['username'],
|
||
|
|
'name' => $user['display_name'],
|
||
|
|
'image' => $user['pfp_url'],
|
||
|
|
'bio' => $user['profile']['bio']['text'] ?? null,
|
||
|
|
'followers_count' => $user['follower_count'] ?? 0,
|
||
|
|
'following_count' => $user['following_count'] ?? 0,
|
||
|
|
'verified_addresses' => $user['verified_addresses'] ?? [],
|
||
|
|
'power_badge' => $user['power_badge'] ?? false,
|
||
|
|
];
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get user by username.
|
||
|
|
*/
|
||
|
|
public function userByUsername(string $username): Response
|
||
|
|
{
|
||
|
|
$response = $this->http()
|
||
|
|
->withHeaders(['api_key' => $this->apiKey])
|
||
|
|
->get(self::NEYNAR_API.'/user/by_username', [
|
||
|
|
'username' => $username,
|
||
|
|
]);
|
||
|
|
|
||
|
|
return $this->fromHttp($response, fn ($data) => [
|
||
|
|
'fid' => $data['user']['fid'],
|
||
|
|
'username' => $data['user']['username'],
|
||
|
|
'name' => $data['user']['display_name'],
|
||
|
|
'image' => $data['user']['pfp_url'],
|
||
|
|
'bio' => $data['user']['profile']['bio']['text'] ?? null,
|
||
|
|
'followers_count' => $data['user']['follower_count'] ?? 0,
|
||
|
|
'following_count' => $data['user']['following_count'] ?? 0,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get user's casts.
|
||
|
|
*/
|
||
|
|
public function list(array $params = []): Response
|
||
|
|
{
|
||
|
|
$fid = $params['fid'] ?? $this->fid;
|
||
|
|
|
||
|
|
if (! $fid) {
|
||
|
|
return $this->error('FID is required');
|
||
|
|
}
|
||
|
|
|
||
|
|
$response = $this->http()
|
||
|
|
->withHeaders(['api_key' => $this->apiKey])
|
||
|
|
->get(self::NEYNAR_API.'/feed/user/casts', [
|
||
|
|
'fid' => $fid,
|
||
|
|
'limit' => $params['limit'] ?? 25,
|
||
|
|
'cursor' => $params['cursor'] ?? null,
|
||
|
|
'include_replies' => $params['include_replies'] ?? false,
|
||
|
|
]);
|
||
|
|
|
||
|
|
return $this->fromHttp($response, fn ($data) => [
|
||
|
|
'casts' => array_map(fn ($cast) => [
|
||
|
|
'hash' => $cast['hash'],
|
||
|
|
'text' => $cast['text'],
|
||
|
|
'timestamp' => $cast['timestamp'],
|
||
|
|
'likes_count' => $cast['reactions']['likes_count'] ?? 0,
|
||
|
|
'recasts_count' => $cast['reactions']['recasts_count'] ?? 0,
|
||
|
|
'replies_count' => $cast['replies']['count'] ?? 0,
|
||
|
|
], $data['casts'] ?? []),
|
||
|
|
'cursor' => $data['next']['cursor'] ?? null,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get channel feed.
|
||
|
|
*/
|
||
|
|
public function channel(string $channelId, array $params = []): Response
|
||
|
|
{
|
||
|
|
$response = $this->http()
|
||
|
|
->withHeaders(['api_key' => $this->apiKey])
|
||
|
|
->get(self::NEYNAR_API.'/feed/channel', [
|
||
|
|
'channel_ids' => $channelId,
|
||
|
|
'limit' => $params['limit'] ?? 25,
|
||
|
|
'cursor' => $params['cursor'] ?? null,
|
||
|
|
]);
|
||
|
|
|
||
|
|
return $this->fromHttp($response, fn ($data) => [
|
||
|
|
'casts' => array_map(fn ($cast) => [
|
||
|
|
'hash' => $cast['hash'],
|
||
|
|
'text' => $cast['text'],
|
||
|
|
'author' => [
|
||
|
|
'fid' => $cast['author']['fid'],
|
||
|
|
'username' => $cast['author']['username'],
|
||
|
|
],
|
||
|
|
'timestamp' => $cast['timestamp'],
|
||
|
|
], $data['casts'] ?? []),
|
||
|
|
'cursor' => $data['next']['cursor'] ?? null,
|
||
|
|
]);
|
||
|
|
}
|
||
|
|
}
|