duukkis/maphpodon

Mastodon REST API 客户端

1.2 2023-02-17 16:54 UTC

This package is auto-updated.

Last update: 2024-09-19 15:01:32 UTC


README

PHP 客户端 API for Mastodon。API 方法在 https://docs.joinmastodon.org/ 中有文档说明。所有实体函数都有一个链接对应到文档。

安装

composer require duukkis/maphpodon

用法

include('../vendor/autoload.php');

use Maphpodon\Maphpodon;

$masto = new Maphpodon(
    "mastobotti.eu",
    "CLIENT_ID",
    "CLIENT_SECRET",
    "ALL_YOU_NEED_IS_AUTH_TOKEN",
);

####### Timelines
$result = $masto->timelines()->public(["limit" => 10]);
/** @var \Maphpodon\models\Status $status */
foreach ($result as $i => $status) {
    print "User " . $status->account->username . 
    " posted at " . $status->created_at->format("Y-m-d. H:i") . 
    " this " .$status->content . PHP_EOL;
}
$result = $masto->timelines()->home(["limit" => 2]);
$result = $masto->timelines()->tag("fish");

####### Statuses
$result = $masto->statuses()->post(["status" => "testi"]);
$result = $masto->statuses()->get($result->id);
$result = $masto->statuses()->get("109825403503402367");
$result = $masto->statuses()->delete("109823185566762882");
$result = $masto->statuses()->reblogged_by("109825461095585733");
$result = $masto->statuses()->favourited_by("109825461095585733");

####### Poll
$result = $masto->statuses()->post(
    [
        "status" => "What is the best way to make a poll?",
        "poll" => [
            "options" => [
                "This way",
                "Some other way"
            ],
            "expires_in" => 60 * 60,
            "multiple" => false,
        ]
    ]
);
$result = $masto->polls()->get("5");
$result = $masto->polls()->vote("5", ["choices" => [0, 1]]);

####### Remote status favourite
// find a remote post, use resolve true! so it gets federated to local instance
$result = $masto->search()->get(["q" => "https://mas.to/@duukkis/109818862518591984", "resolve" => true]);
/** @var \Maphpodon\models\Status $status */
$status = $result->statuses[0];
$result = $masto->statuses()->favourite($status->id);

####### Media handling
$result = $masto->media()->post("./IMG_6298.jpg", "description of somesort", null]);
$result = $masto->media()->get("109825314440397270");
####### post with media
$result = $masto->statuses()->post(["status" => "dippa", "media_ids" => ["109825314440397270"]]);

####### Notifications
$result = $masto->notifications()->index();
$result = $masto->notifications()->get("1");
$masto->notifications()->dismiss("1");
$masto->notifications()->clear();

####### Instance
$result = $masto->instance()->index();

####### Accounts
$result = $masto->accounts()->get("109807809719057795");
$result = $masto->accounts()->statuses("109807809719057795", ["min_id" => "109816527054798413", "limit" => 4]);
$result = $masto->accounts()->followers("109807809719057795", ["limit" => 2]);
$result = $masto->accounts()->featured_tags("109807491887075545", []);
$result = $masto->accounts()->lists("109817168119540210", []);
$result = $masto->accounts()->follow("109817168119540210");
$result = $masto->accounts()->unfollow("109817168119540210");
$result = $masto->accounts()->pin/unpin/block/unblock/...("109817168119540210");
$result = $masto->accounts()->note("109817168119540210", ["comment" => "api test"]);
$result = $masto->accounts()->note("109817168119540210"); // remove comment
$result = $masto->accounts()->search(["q" => "päivän"]);
$result = $masto->accounts()->lookup(["acct" => "duukkis"]);
// these gave me 500, so something there or then it's just my instance
$result = $masto->accounts()->relationships(["id" => ["109817168119540210", "109813823501112312"]]);
$result = $masto->accounts()->familiar_followers(["id" => ["109817168119540210", "109813823501112312"]]);

####### Oauth token fetching

// just put in a ID and secret
$masto = new Maphpodon(
    "mastobotti.eu",
    "CLIENT_ID",
    "CLIENT_SECRET",
);

// this will return an url where to redirect customer
$result = $masto->auth()->authorize(
    "read",
    "urn:ietf:wg:oauth:2.0:oob",
    "false",
    "en"
);
print $result . PHP_EOL;
// or header("Location: " . $result); exit();

# After user has clicked ok or returned to actual return url given above, you get authorization code in &code param
# THIS IS DIFFERENT FROM AUTH_TOKEN so we need to fetch the token with below method

$result = $masto->auth()->token(
    [
        "grant_type" => "authorization_code",
        "code" => "AUTHORIZATION_CODE_FROM_ABOVE",
        "client_id" => $masto->clientKey,
        "client_secret" => $masto->clientSecret,
        "redirect_uri" => "urn:ietf:wg:oauth:2.0:oob",
        "scope" => "read",
    ]
);
/*
print_r($result);

Maphpodon\models\Token Object
(
    [access_token] => HERE-IS-A-TOKEN-YOU-CAN-USE
    [token_type] => Bearer
    [scope] => read
    [created_at] => 1675972651
)
*/
$result = $masto->auth()->revoke(
    [
        "client_id" => $masto->clientKey,
        "client_secret" => $masto->clientSecret,
        "token" => "HERE-IS-A-TOKEN-YOU-CAN-USE",
    ]
);

####### Apps
$result = $masto->apps()->post(
    [
        "client_name" => "Duukkis new Api client",
        "redirect_uris" => "urn:ietf:wg:oauth:2.0:oob",
        "scopes" => "read follow write:lists",
        "website" => "https://github.com/duukkis/maphpodon",
    ]
);
$result = $masto->apps()->verify_credentials();

####### Admin
$result = $masto->admin()->accounts()->viewV1(["limit" => 2]);
$result = $masto->admin()->accounts()->viewV2(["status" => "active", "limit" => 2]);
$result = $masto->admin()->accounts()->view("109807491887075545");
$result = $masto->admin()->accounts()->approve("109807491887075545");
$masto->admin()->accounts()->action("109807491887075545", ["type" => "none"]);
// reject, delete, enable, unsilence, unsuspend, unsensitive

$result = $masto->admin()->domain_allows()->list([]);
$result = $masto->admin()->domain_blocks()->list([]);
$result = $masto->admin()->ip_blocks()->list();
$result = $masto->admin()->ip_blocks()->view("1");
$result = $masto->admin()->ip_blocks()->create(["..."]);
$result = $masto->admin()->ip_blocks()->update("1", ["..."]);
$masto->admin()->ip_blocks()->delete("1");

$result = $masto->admin()->reports()->list([]);
$result = $masto->admin()->reports()->view("2");
$result = $masto->admin()->reports()->assign_to_self("2");
$result = $masto->admin()->reports()->unassign("2");
$result = $masto->admin()->reports()->resolve("2");
$result = $masto->admin()->reports()->reopen("2");

$result = $masto->admin()->trends()->statuses([]);
$result = $masto->admin()->trends()->links([]);
$result = $masto->admin()->trends()->tags([]);

$result = $masto->admin()->canonical_email_blocks()->list();
$result = $masto->admin()->dimensions()->list(["keys" => ["languages", "sources", "servers", "space_usage", "software_versions"]]);
$result = $masto->admin()->measures()->list(
    [
        "keys" => ["active_users", "new_users"],
        "start_at" => \Carbon\Carbon::now()->subMonth()->format("Y-m-d"),
        "end_at" => \Carbon\Carbon::now()->format("Y-m-d"),
    ]
);

代码结构

实例

方法返回 Model、数组或仅 void。

class Accounts
{
    // takes in the Maphpodon wrapper with GuzzleClient
    public function __construct(protected Maphpodon $maphpodon)
    {
    }
    
     /**
     * @link https://docs.joinmastodon.org/methods/accounts/#get
     * @param string $id
     * @return Account
     */
    public function get(string $id): Model|Account
    {
        return Mapper::mapJsonObjectToClass(
            $this->maphpodon->get(sprintf('v1/accounts/%s', $id), []),
            new Account()
        );
    }
    
    /**
     * @link https://docs.joinmastodon.org/methods/accounts/#statuses
     * @param string $id
     * @param array $params
     * @return Status[]
     */
    public function statuses(string $id, array $params = []): array
    {
        return Mapper::mapJsonObjectToClassArray(
            $this->maphpodon->get(sprintf('v1/accounts/%s/statuses', $id), ["query" => $params]),
            new Status()
        );
    }

模型

返回的对象映射到模型中。

class Status extends Model
{
    // not nullable
    public string $id;
    // Carbon::parse
    public Carbon $created_at;
    // can be null
    public ?string $in_reply_to_id;
    public bool $sensitive;
    // this is mapped to Application model
    public Application $application;
    // check if we have mapper in $mapArrayToObjects and map array to those
    public array $media_attachments = [];
    // we have no mapper for this, just put json-objects to array
    public array $emojis = [];
    
    public array $mapArrayToObjects = [
        "media_attachments" => MediaAttachment::class,

异常

创建了一个名为 ExceptionCatcher 的接口,它可以被任何处理 GuzzleException 的 Catcher 覆盖。默认情况下将仅重新抛出异常。例如,在 helpers 目录中创建了一个 DevelopmentExceptionCatcher。

测试

有一个基本的 phpunit 设置。

Lorem Ipsum

命名遵循路径。/api/v1/accounts 在 entities/Accounts 中,/api/v1/accounts/follow 是一个 follow 函数。

祝您玩得开心!