This commit is contained in:
gutmet 2022-11-20 21:31:59 +01:00
parent 7274b5e624
commit 1dfacac66a
11 changed files with 179 additions and 183 deletions

View File

@ -4,34 +4,6 @@ Fork of https://github.com/mattn/go-mastodon
## Usage
### Application
```go
package main
import (
"context"
"fmt"
"log"
mastodon "git.gutmet.org/go-mastodon.git"
)
func main() {
app, err := mastodon.RegisterApp(context.Background(), &mastodon.AppConfig{
Server: "https://mstdn.jp",
ClientName: "client-name",
Scopes: "read write follow",
Website: "https://github.com/mattn/go-mastodon",
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("client-id : %s\n", app.ClientID)
fmt.Printf("client-secret: %s\n", app.ClientSecret)
}
```
### Client
```go
@ -46,16 +18,13 @@ import (
)
func main() {
c := mastodon.NewClient(&mastodon.Config{
mastodon.Initialize(&mastodon.Config{
Server: "https://mstdn.jp",
ClientID: "client-id",
ClientSecret: "client-secret",
AccessToken: "accessToken",
})
err := c.Authenticate(context.Background(), "your-email", "your-password")
if err != nil {
log.Fatal(err)
}
timeline, err := c.GetTimelineHome(context.Background(), nil)
timeline, err := GetTimelineHome(nil)
if err != nil {
log.Fatal(err)
}

View File

@ -8,7 +8,6 @@ import (
"time"
)
// Account holds information for a mastodon account.
type Account struct {
ID ID `json:"id"`
Username string `json:"username"`
@ -33,6 +32,14 @@ type Account struct {
Source *AccountSource `json:"source"`
}
func (account *Account) GetID() string {
if account != nil {
return string(account.ID)
} else {
return ""
}
}
// Field is a Mastodon account profile field.
type Field struct {
Name string `json:"name"`
@ -40,7 +47,6 @@ type Field struct {
VerifiedAt time.Time `json:"verified_at"`
}
// AccountSource is a Mastodon account profile field.
type AccountSource struct {
Privacy *string `json:"privacy"`
Sensitive *bool `json:"sensitive"`
@ -126,38 +132,38 @@ func UpdateCurrentAccount(profile *Profile) (*Account, error) {
return &account, nil
}
func GetAccountStatuses(id ID, pg *Pagination) ([]*Status, error) {
func (a *Account) GetStatuses(pg *Pagination) ([]*Status, error) {
var statuses []*Status
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/statuses", url.PathEscape(string(id))), nil, &statuses, pg)
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/statuses", url.PathEscape(a.GetID())), nil, &statuses, pg)
if err != nil {
return nil, err
}
return statuses, nil
}
func GetAccountPinnedStatuses(id ID) ([]*Status, error) {
func (a *Account) GetPinnedStatuses() ([]*Status, error) {
var statuses []*Status
params := url.Values{}
params.Set("pinned", "true")
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/statuses", url.PathEscape(string(id))), params, &statuses, nil)
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/statuses", url.PathEscape(a.GetID())), params, &statuses, nil)
if err != nil {
return nil, err
}
return statuses, nil
}
func GetAccountFollowers(id ID, pg *Pagination) ([]*Account, error) {
func (a *Account) GetFollowers(pg *Pagination) ([]*Account, error) {
var accounts []*Account
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/followers", url.PathEscape(string(id))), nil, &accounts, pg)
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/followers", url.PathEscape(a.GetID())), nil, &accounts, pg)
if err != nil {
return nil, err
}
return accounts, nil
}
func GetAccountFollowing(id ID, pg *Pagination) ([]*Account, error) {
func (a *Account) GetFollowing(pg *Pagination) ([]*Account, error) {
var accounts []*Account
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/following", url.PathEscape(string(id))), nil, &accounts, pg)
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/following", url.PathEscape(a.GetID())), nil, &accounts, pg)
if err != nil {
return nil, err
}
@ -173,7 +179,6 @@ func GetBlockList(pg *Pagination) ([]*Account, error) {
return accounts, nil
}
// Relationship holds information for relationship to the account.
type Relationship struct {
ID ID `json:"id"`
Following bool `json:"following"`
@ -187,61 +192,61 @@ type Relationship struct {
Endorsed bool `json:"endorsed"`
}
func FollowAccount(id ID) (*Relationship, error) {
func Follow(account *Account) (*Relationship, error) {
var relationship Relationship
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/follow", url.PathEscape(string(id))), nil, &relationship, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/follow", url.PathEscape(account.GetID())), nil, &relationship, nil)
if err != nil {
return nil, err
}
return &relationship, nil
}
func UnfollowAccount(id ID) (*Relationship, error) {
func Unfollow(account *Account) (*Relationship, error) {
var relationship Relationship
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/unfollow", url.PathEscape(string(id))), nil, &relationship, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/unfollow", url.PathEscape(account.GetID())), nil, &relationship, nil)
if err != nil {
return nil, err
}
return &relationship, nil
}
func BlockAccount(id ID) (*Relationship, error) {
func Block(account *Account) (*Relationship, error) {
var relationship Relationship
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/block", url.PathEscape(string(id))), nil, &relationship, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/block", url.PathEscape(account.GetID())), nil, &relationship, nil)
if err != nil {
return nil, err
}
return &relationship, nil
}
func UnblockAccount(id ID) (*Relationship, error) {
func Unblock(account *Account) (*Relationship, error) {
var relationship Relationship
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/unblock", url.PathEscape(string(id))), nil, &relationship, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/unblock", url.PathEscape(account.GetID())), nil, &relationship, nil)
if err != nil {
return nil, err
}
return &relationship, nil
}
func MuteAccount(id ID) (*Relationship, error) {
func Mute(account *Account) (*Relationship, error) {
var relationship Relationship
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/mute", url.PathEscape(string(id))), nil, &relationship, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/mute", url.PathEscape(account.GetID())), nil, &relationship, nil)
if err != nil {
return nil, err
}
return &relationship, nil
}
func UnmuteAccount(id ID) (*Relationship, error) {
func Unmute(account *Account) (*Relationship, error) {
var relationship Relationship
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/unmute", url.PathEscape(string(id))), nil, &relationship, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/accounts/%s/unmute", url.PathEscape(account.GetID())), nil, &relationship, nil)
if err != nil {
return nil, err
}
return &relationship, nil
}
func GetAccountRelationships(ids []string) ([]*Relationship, error) {
func GetRelationships(ids []string) ([]*Relationship, error) {
params := url.Values{}
for _, id := range ids {
params.Add("id[]", id)
@ -268,6 +273,7 @@ func SearchAccounts(q string, limit int64) ([]*Account, error) {
return accounts, nil
}
// uri: username@domain of the person you want to follow
func FollowRemoteUser(uri string) (*Account, error) {
params := url.Values{}
params.Set("uri", uri)
@ -289,12 +295,12 @@ func GetFollowRequests(pg *Pagination) ([]*Account, error) {
return accounts, nil
}
func AuthorizeFollowRequest(id ID) error {
return doAPI(http.MethodPost, fmt.Sprintf("/api/v1/follow_requests/%s/authorize", url.PathEscape(string(id))), nil, nil, nil)
func AuthorizeFollowRequest(account *Account) error {
return doAPI(http.MethodPost, fmt.Sprintf("/api/v1/follow_requests/%s/authorize", url.PathEscape(account.GetID())), nil, nil, nil)
}
func RejectFollowRequest(id ID) error {
return doAPI(http.MethodPost, fmt.Sprintf("/api/v1/follow_requests/%s/reject", url.PathEscape(string(id))), nil, nil, nil)
func RejectFollowRequest(account *Account) error {
return doAPI(http.MethodPost, fmt.Sprintf("/api/v1/follow_requests/%s/reject", url.PathEscape(account.GetID())), nil, nil, nil)
}
func GetMuteList(pg *Pagination) ([]*Account, error) {

View File

@ -9,7 +9,6 @@ import (
"strings"
)
// AppConfig is a setting for registering applications.
type AppConfig struct {
http.Client
Server string
@ -27,7 +26,6 @@ type AppConfig struct {
Website string
}
// Application is a mastodon application.
type Application struct {
ID ID `json:"id"`
RedirectURI string `json:"redirect_uri"`
@ -38,7 +36,6 @@ type Application struct {
AuthURI string `json:"auth_uri,omitempty"`
}
// RegisterApp returns the mastodon application.
func RegisterApp(appConfig *AppConfig) (*Application, error) {
ctx := context.Background()
params := url.Values{}

View File

@ -8,7 +8,6 @@ import (
"time"
)
// Filter is metadata for a filter of users.
type Filter struct {
ID ID `json:"id"`
Phrase string `json:"phrase"`
@ -18,6 +17,14 @@ type Filter struct {
Irreversible bool `json:"irreversible"`
}
func (f *Filter) GetID() string {
if f != nil {
return string(f.ID)
} else {
return ""
}
}
func GetFilters() ([]*Filter, error) {
var filters []*Filter
err := doAPI(http.MethodGet, "/api/v1/filters", nil, &filters, nil)
@ -27,93 +34,92 @@ func GetFilters() ([]*Filter, error) {
return filters, nil
}
// was ist id ?
func GetFilter(id ID) (*Filter, error) {
func GetFilter(filterId ID) (*Filter, error) {
var filter Filter
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/filters/%s", url.PathEscape(string(id))), nil, &filter, nil)
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/filters/%s", url.PathEscape(string(filterId))), nil, &filter, nil)
if err != nil {
return nil, err
}
return &filter, nil
}
func CreateFilter(filter *Filter) (*Filter, error) {
if filter == nil {
func (f *Filter) Create() (*Filter, error) {
if f == nil {
return nil, errors.New("filter can't be nil")
}
if filter.Phrase == "" {
if f.Phrase == "" {
return nil, errors.New("phrase can't be empty")
}
if len(filter.Context) == 0 {
if len(f.Context) == 0 {
return nil, errors.New("context can't be empty")
}
params := url.Values{}
params.Set("phrase", filter.Phrase)
for _, c := range filter.Context {
params.Set("phrase", f.Phrase)
for _, c := range f.Context {
params.Add("context[]", c)
}
if filter.WholeWord {
if f.WholeWord {
params.Add("whole_word", "true")
}
if filter.Irreversible {
if f.Irreversible {
params.Add("irreversible", "true")
}
if !filter.ExpiresAt.IsZero() {
diff := time.Until(filter.ExpiresAt)
if !f.ExpiresAt.IsZero() {
diff := time.Until(f.ExpiresAt)
params.Add("expires_in", fmt.Sprintf("%.0f", diff.Seconds()))
}
var f Filter
err := doAPI(http.MethodPost, "/api/v1/filters", params, &f, nil)
var ret Filter
err := doAPI(http.MethodPost, "/api/v1/filters", params, &ret, nil)
if err != nil {
return nil, err
}
return &f, nil
return &ret, nil
}
func UpdateFilter(id ID, filter *Filter) (*Filter, error) {
if filter == nil {
func (f *Filter) Update(newFilter *Filter) (*Filter, error) {
if newFilter == nil {
return nil, errors.New("filter can't be nil")
}
if id == ID("") {
if f.GetID() == "" {
return nil, errors.New("ID can't be empty")
}
if filter.Phrase == "" {
if newFilter.Phrase == "" {
return nil, errors.New("phrase can't be empty")
}
if len(filter.Context) == 0 {
if len(newFilter.Context) == 0 {
return nil, errors.New("context can't be empty")
}
params := url.Values{}
params.Set("phrase", filter.Phrase)
for _, c := range filter.Context {
params.Set("phrase", newFilter.Phrase)
for _, c := range newFilter.Context {
params.Add("context[]", c)
}
if filter.WholeWord {
if newFilter.WholeWord {
params.Add("whole_word", "true")
} else {
params.Add("whole_word", "false")
}
if filter.Irreversible {
if newFilter.Irreversible {
params.Add("irreversible", "true")
} else {
params.Add("irreversible", "false")
}
if !filter.ExpiresAt.IsZero() {
diff := time.Until(filter.ExpiresAt)
if !newFilter.ExpiresAt.IsZero() {
diff := time.Until(newFilter.ExpiresAt)
params.Add("expires_in", fmt.Sprintf("%.0f", diff.Seconds()))
} else {
params.Add("expires_in", "")
}
var f Filter
err := doAPI(http.MethodPut, fmt.Sprintf("/api/v1/filters/%s", url.PathEscape(string(id))), params, &f, nil)
var ret Filter
err := doAPI(http.MethodPut, fmt.Sprintf("/api/v1/filters/%s", url.PathEscape(f.GetID())), params, &ret, nil)
if err != nil {
return nil, err
}
return &f, nil
return &ret, nil
}
func DeleteFilter(id ID) error {
return doAPI(http.MethodDelete, fmt.Sprintf("/api/v1/filters/%s", url.PathEscape(string(id))), nil, nil, nil)
func (f *Filter) Delete() error {
return doAPI(http.MethodDelete, fmt.Sprintf("/api/v1/filters/%s", url.PathEscape(f.GetID())), nil, nil, nil)
}

View File

@ -6,12 +6,19 @@ import (
"net/url"
)
// List is metadata for a list of users.
type List struct {
ID ID `json:"id"`
Title string `json:"title"`
}
func (l *List) GetID() string {
if l != nil {
return string(l.ID)
} else {
return ""
}
}
func GetLists() ([]*List, error) {
var lists []*List
err := doAPI(http.MethodGet, "/api/v1/lists", nil, &lists, nil)
@ -21,10 +28,9 @@ func GetLists() ([]*List, error) {
return lists, nil
}
// GetAccountLists returns the lists containing a given account.
func GetListWithAccount(id ID) ([]*List, error) {
func (a *Account) GetContainingLists() ([]*List, error) {
var lists []*List
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/lists", url.PathEscape(string(id))), nil, &lists, nil)
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/accounts/%s/lists", url.PathEscape(a.GetID())), nil, &lists, nil)
if err != nil {
return nil, err
}
@ -61,34 +67,32 @@ func CreateList(title string) (*List, error) {
return &list, nil
}
func RenameList(list *List, newTitle string) error {
func (l *List) Rename(newTitle string) error {
params := url.Values{}
params.Set("title", newTitle)
return doAPI(http.MethodPut, fmt.Sprintf("/api/v1/lists/%s", url.PathEscape(string(list.ID))), params, nil, nil)
return doAPI(http.MethodPut, fmt.Sprintf("/api/v1/lists/%s", url.PathEscape(l.GetID())), params, nil, nil)
}
func DeleteList(id ID) error {
return doAPI(http.MethodDelete, fmt.Sprintf("/api/v1/lists/%s", url.PathEscape(string(id))), nil, nil, nil)
func (l *List) Delete() error {
return doAPI(http.MethodDelete, fmt.Sprintf("/api/v1/lists/%s", url.PathEscape(l.GetID())), nil, nil, nil)
}
// AddToList adds accounts to a list.
//
// Only accounts already followed by the user can be added to a list.
func AddToList(list ID, accounts ...ID) error {
func (l *List) Add(accounts ...*Account) error {
params := url.Values{}
for _, acct := range accounts {
params.Add("account_ids", string(acct))
for _, a := range accounts {
params.Add("account_ids", string(a.GetID()))
}
return doAPI(http.MethodPost, fmt.Sprintf("/api/v1/lists/%s/accounts", url.PathEscape(string(list))), params, nil, nil)
return doAPI(http.MethodPost, fmt.Sprintf("/api/v1/lists/%s/accounts", url.PathEscape(l.GetID())), params, nil, nil)
}
func RemoveFromList(list ID, accounts ...ID) error {
func (l *List) Remove(accounts ...*Account) error {
params := url.Values{}
for _, acct := range accounts {
params.Add("account_ids", string(acct))
for _, a := range accounts {
params.Add("account_ids", a.GetID())
}
return doAPI(http.MethodDelete, fmt.Sprintf("/api/v1/lists/%s/accounts", url.PathEscape(string(list))), params, nil, nil)
return doAPI(http.MethodDelete, fmt.Sprintf("/api/v1/lists/%s/accounts", url.PathEscape(l.GetID())), params, nil, nil)
}

View File

@ -14,7 +14,6 @@ import (
"time"
)
// Config is a setting for access mastodon APIs.
type Config struct {
Server string
ClientID string
@ -22,7 +21,6 @@ type Config struct {
AccessToken string
}
// Client is a API client for mastodon.
type Client struct {
http.Client
Config *Config
@ -141,7 +139,6 @@ func doAPI(method string, uri string, params interface{}, res interface{}, pg *P
return json.NewDecoder(resp.Body).Decode(&res)
}
// NewClient returns a new mastodon API client.
func newClient(config *Config) *Client {
return &Client{
Client: *http.DefaultClient,
@ -227,7 +224,6 @@ func (c *Client) authenticate(ctx context.Context, params url.Values) error {
return nil
}
// Convenience constants for Toot.Visibility
const (
VisibilityPublic = "public"
VisibilityUnlisted = "unlisted"
@ -235,7 +231,6 @@ const (
VisibilityDirectMessage = "direct"
)
// Toot is a struct to post status.
type Toot struct {
Status string `json:"status"`
InReplyToID ID `json:"in_reply_to_id"`
@ -248,7 +243,6 @@ type Toot struct {
Poll *TootPoll `json:"poll"`
}
// TootPoll holds information for creating a poll in Toot.
type TootPoll struct {
Options []string `json:"options"`
ExpiresInSeconds int64 `json:"expires_in"`
@ -256,7 +250,6 @@ type TootPoll struct {
HideTotals bool `json:"hide_totals"`
}
// Mention hold information for mention.
type Mention struct {
URL string `json:"url"`
Username string `json:"username"`
@ -264,21 +257,18 @@ type Mention struct {
ID ID `json:"id"`
}
// Tag hold information for tag.
type Tag struct {
Name string `json:"name"`
URL string `json:"url"`
History []History `json:"history"`
}
// History hold information for history.
type History struct {
Day string `json:"day"`
Uses string `json:"uses"`
Accounts string `json:"accounts"`
}
// Attachment hold information for attachment.
type Attachment struct {
ID ID `json:"id"`
Type string `json:"type"`
@ -290,13 +280,11 @@ type Attachment struct {
Meta AttachmentMeta `json:"meta"`
}
// AttachmentMeta holds information for attachment metadata.
type AttachmentMeta struct {
Original AttachmentSize `json:"original"`
Small AttachmentSize `json:"small"`
}
// AttachmentSize holds information for attatchment size.
type AttachmentSize struct {
Width int64 `json:"width"`
Height int64 `json:"height"`
@ -304,7 +292,6 @@ type AttachmentSize struct {
Aspect float64 `json:"aspect"`
}
// Emoji hold information for CustomEmoji.
type Emoji struct {
ShortCode string `json:"shortcode"`
StaticURL string `json:"static_url"`
@ -312,7 +299,6 @@ type Emoji struct {
VisibleInPicker bool `json:"visible_in_picker"`
}
// Results hold information for search result.
type Results struct {
Accounts []*Account `json:"accounts"`
Statuses []*Status `json:"statuses"`

View File

@ -11,7 +11,6 @@ import (
"time"
)
// Notification holds information for a mastodon notification.
type Notification struct {
ID ID `json:"id"`
Type string `json:"type"`
@ -20,6 +19,14 @@ type Notification struct {
Status *Status `json:"status"`
}
func (n *Notification) GetID() string {
if n != nil {
return string(n.ID)
} else {
return ""
}
}
type PushSubscription struct {
ID ID `json:"id"`
Endpoint string `json:"endpoint"`
@ -52,8 +59,8 @@ func GetNotification(id ID) (*Notification, error) {
return &notification, nil
}
func DismissNotification(id ID) error {
return doAPI(http.MethodPost, fmt.Sprintf("/api/v1/notifications/%v/dismiss", id), nil, nil, nil)
func (n *Notification) Dismiss() error {
return doAPI(http.MethodPost, fmt.Sprintf("/api/v1/notifications/%v/dismiss", n.GetID()), nil, nil, nil)
}
func ClearNotifications() error {

View File

@ -20,6 +20,14 @@ type Poll struct {
Emojis []Emoji `json:"emojis"`
}
func (p *Poll) GetID() string {
if p != nil {
return string(p.ID)
} else {
return ""
}
}
type PollOption struct {
Title string `json:"title"`
VotesCount int64 `json:"votes_count"`
@ -34,14 +42,14 @@ func GetPoll(id ID) (*Poll, error) {
return &poll, nil
}
func PollVote(id ID, choices ...int) (*Poll, error) {
func (p *Poll) Vote(choices ...int) (*Poll, error) {
params := url.Values{}
for _, c := range choices {
params.Add("choices[]", fmt.Sprintf("%d", c))
}
var poll Poll
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/polls/%s/votes", url.PathEscape(string(id))), params, &poll, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/polls/%s/votes", url.PathEscape(p.GetID())), params, &poll, nil)
if err != nil {
return nil, err
}

View File

@ -5,7 +5,6 @@ import (
"net/url"
)
// Report holds information for a mastodon report.
type Report struct {
ID int64 `json:"id"`
ActionTaken bool `json:"action_taken"`

View File

@ -43,6 +43,14 @@ type Status struct {
Pinned interface{} `json:"pinned"`
}
func (s *Status) GetID() string {
if s != nil {
return string(s.ID)
} else {
return ""
}
}
type Context struct {
Ancestors []*Status `json:"ancestors"`
Descendants []*Status `json:"descendants"`
@ -70,6 +78,14 @@ type Conversation struct {
LastStatus *Status `json:"last_status"`
}
func (c *Conversation) GetID() string {
if c != nil {
return string(c.ID)
} else {
return ""
}
}
type Media struct {
File io.Reader
Thumbnail io.Reader
@ -161,97 +177,97 @@ func GetStatus(id ID) (*Status, error) {
return &status, nil
}
func GetStatusContext(id ID) (*Context, error) {
func (s *Status) GetContext() (*Context, error) {
var context Context
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/statuses/%s/context", id), nil, &context, nil)
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/statuses/%s/context", s.GetID()), nil, &context, nil)
if err != nil {
return nil, err
}
return &context, nil
}
func GetStatusCard(id ID) (*Card, error) {
func (s *Status) GetCard() (*Card, error) {
var card Card
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/statuses/%s/card", id), nil, &card, nil)
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/statuses/%s/card", s.GetID()), nil, &card, nil)
if err != nil {
return nil, err
}
return &card, nil
}
func GetRebloggedBy(id ID, pg *Pagination) ([]*Account, error) {
func (s *Status) GetRebloggedBy(pg *Pagination) ([]*Account, error) {
var accounts []*Account
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/statuses/%s/reblogged_by", id), nil, &accounts, pg)
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/statuses/%s/reblogged_by", s.GetID()), nil, &accounts, pg)
if err != nil {
return nil, err
}
return accounts, nil
}
func GetFavouritedBy(id ID, pg *Pagination) ([]*Account, error) {
func (s *Status) GetFavouritedBy(pg *Pagination) ([]*Account, error) {
var accounts []*Account
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/statuses/%s/favourited_by", id), nil, &accounts, pg)
err := doAPI(http.MethodGet, fmt.Sprintf("/api/v1/statuses/%s/favourited_by", s.GetID()), nil, &accounts, pg)
if err != nil {
return nil, err
}
return accounts, nil
}
func Reblog(id ID) (*Status, error) {
func (s *Status) DoReblog() (*Status, error) {
var status Status
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/reblog", id), nil, &status, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/reblog", s.GetID()), nil, &status, nil)
if err != nil {
return nil, err
}
return &status, nil
}
func Unreblog(id ID) (*Status, error) {
func (s *Status) Unreblog() (*Status, error) {
var status Status
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/unreblog", id), nil, &status, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/unreblog", s.GetID()), nil, &status, nil)
if err != nil {
return nil, err
}
return &status, nil
}
func Favourite(id ID) (*Status, error) {
func (s *Status) Favourite() (*Status, error) {
var status Status
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/favourite", id), nil, &status, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/favourite", s.GetID()), nil, &status, nil)
if err != nil {
return nil, err
}
return &status, nil
}
func Unfavourite(id ID) (*Status, error) {
func (s *Status) Unfavourite() (*Status, error) {
var status Status
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/unfavourite", id), nil, &status, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/unfavourite", s.GetID()), nil, &status, nil)
if err != nil {
return nil, err
}
return &status, nil
}
func Bookmark(id ID) (*Status, error) {
func (s *Status) Bookmark() (*Status, error) {
var status Status
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/bookmark", id), nil, &status, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/bookmark", s.GetID()), nil, &status, nil)
if err != nil {
return nil, err
}
return &status, nil
}
func (c *Client) Unbookmark(id ID) (*Status, error) {
func (s *Status) Unbookmark() (*Status, error) {
var status Status
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/unbookmark", id), nil, &status, nil)
err := doAPI(http.MethodPost, fmt.Sprintf("/api/v1/statuses/%s/unbookmark", s.GetID()), nil, &status, nil)
if err != nil {
return nil, err
}
return &status, nil
}
func (c *Client) GetHomeTimeline(pg *Pagination) ([]*Status, error) {
func GetHomeTimeline(pg *Pagination) ([]*Status, error) {
var statuses []*Status
err := doAPI(http.MethodGet, "/api/v1/timelines/home", nil, &statuses, pg)
if err != nil {
@ -359,8 +375,8 @@ func PostStatus(toot *Toot) (*Status, error) {
return &status, nil
}
func DeleteStatus(id ID) error {
return doAPI(http.MethodDelete, fmt.Sprintf("/api/v1/statuses/%s", id), nil, nil, nil)
func (s *Status) Delete() error {
return doAPI(http.MethodDelete, fmt.Sprintf("/api/v1/statuses/%s", s.GetID()), nil, nil, nil)
}
func Search(q string, resolve bool) (*Results, error) {
@ -431,10 +447,10 @@ func GetConversations(pg *Pagination) ([]*Conversation, error) {
return conversations, nil
}
func DeleteConversation(id ID) error {
return doAPI(http.MethodDelete, fmt.Sprintf("/api/v1/conversations/%s", id), nil, nil, nil)
func (c *Conversation) Delete() error {
return doAPI(http.MethodDelete, fmt.Sprintf("/api/v1/conversations/%s", c.GetID()), nil, nil, nil)
}
func MarkConversationAsRead(id ID) error {
return doAPI(http.MethodPost, fmt.Sprintf("/api/v1/conversations/%s/read", id), nil, nil, nil)
func (c *Conversation) MarkAsRead() error {
return doAPI(http.MethodPost, fmt.Sprintf("/api/v1/conversations/%s/read", c.GetID()), nil, nil, nil)
}

View File

@ -13,32 +13,27 @@ import (
"strings"
)
// UpdateEvent is a struct for passing status event to app.
type UpdateEvent struct {
Status *Status `json:"status"`
}
func (e *UpdateEvent) event() {}
// NotificationEvent is a struct for passing notification event to app.
type NotificationEvent struct {
Notification *Notification `json:"notification"`
}
func (e *NotificationEvent) event() {}
// DeleteEvent is a struct for passing deletion event to app.
type DeleteEvent struct{ ID ID }
func (e *DeleteEvent) event() {}
// ErrorEvent is a struct for passing errors to app.
type ErrorEvent struct{ err error }
func (e *ErrorEvent) event() {}
func (e *ErrorEvent) Error() string { return e.err.Error() }
// Event is an interface passing events to app.
type Event interface {
event()
}
@ -97,7 +92,10 @@ func handleReader(q chan Event, r io.Reader) error {
}
}
func (c *Client) streaming(ctx context.Context, p string, params url.Values) (chan Event, error) {
func streaming(p string, params url.Values) (chan Event, error) {
checkInit()
c := client
ctx := context.Background()
u, err := url.Parse(c.Config.Server)
if err != nil {
return nil, err
@ -125,14 +123,14 @@ func (c *Client) streaming(ctx context.Context, p string, params url.Values) (ch
default:
}
c.doStreaming(req, q)
doStreaming(req, q)
}
}()
return q, nil
}
func (c *Client) doStreaming(req *http.Request, q chan Event) {
resp, err := c.Do(req)
func doStreaming(req *http.Request, q chan Event) {
resp, err := client.Do(req)
if err != nil {
q <- &ErrorEvent{err}
return
@ -151,22 +149,22 @@ func (c *Client) doStreaming(req *http.Request, q chan Event) {
}
// StreamingUser returns a channel to read events on home.
func (c *Client) StreamingUser(ctx context.Context) (chan Event, error) {
return c.streaming(ctx, "user", nil)
func StreamingUser() (chan Event, error) {
return streaming("user", nil)
}
// StreamingPublic returns a channel to read events on public.
func (c *Client) StreamingPublic(ctx context.Context, isLocal bool) (chan Event, error) {
func StreamingPublic(isLocal bool) (chan Event, error) {
p := "public"
if isLocal {
p = path.Join(p, "local")
}
return c.streaming(ctx, p, nil)
return streaming(p, nil)
}
// StreamingHashtag returns a channel to read events on tagged timeline.
func (c *Client) StreamingHashtag(ctx context.Context, tag string, isLocal bool) (chan Event, error) {
func StreamingHashtag(tag string, isLocal bool) (chan Event, error) {
params := url.Values{}
params.Set("tag", tag)
@ -175,18 +173,18 @@ func (c *Client) StreamingHashtag(ctx context.Context, tag string, isLocal bool)
p = path.Join(p, "local")
}
return c.streaming(ctx, p, params)
return streaming(p, params)
}
// StreamingList returns a channel to read events on a list.
func (c *Client) StreamingList(ctx context.Context, id ID) (chan Event, error) {
func (l *List) Streaming() (chan Event, error) {
params := url.Values{}
params.Set("list", string(id))
params.Set("list", l.GetID())
return c.streaming(ctx, "list", params)
return streaming("list", params)
}
// StreamingDirect returns a channel to read events on a direct messages.
func (c *Client) StreamingDirect(ctx context.Context) (chan Event, error) {
return c.streaming(ctx, "direct", nil)
func StreamingDirect() (chan Event, error) {
return streaming("direct", nil)
}