Coder Social home page Coder Social logo

go-mastodon's Introduction

go-mastodon

Build Status Codecov Go Reference Go Report Card

Usage

Application

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/mattn/go-mastodon"
)

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

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/mattn/go-mastodon"
)

func main() {
	c := mastodon.NewClient(&mastodon.Config{
		Server:       "https://mstdn.jp",
		ClientID:     "client-id",
		ClientSecret: "client-secret",
	})
	err := c.Authenticate(context.Background(), "your-email", "your-password")
	if err != nil {
		log.Fatal(err)
	}
	timeline, err := c.GetTimelineHome(context.Background(), nil)
	if err != nil {
		log.Fatal(err)
	}
	for i := len(timeline) - 1; i >= 0; i-- {
		fmt.Println(timeline[i])
	}
}

Status of implementations

  • GET /api/v1/accounts/:id
  • GET /api/v1/accounts/verify_credentials
  • PATCH /api/v1/accounts/update_credentials
  • GET /api/v1/accounts/:id/followers
  • GET /api/v1/accounts/:id/following
  • GET /api/v1/accounts/:id/statuses
  • POST /api/v1/accounts/:id/follow
  • POST /api/v1/accounts/:id/unfollow
  • GET /api/v1/accounts/:id/block
  • GET /api/v1/accounts/:id/unblock
  • GET /api/v1/accounts/:id/mute
  • GET /api/v1/accounts/:id/unmute
  • GET /api/v1/accounts/:id/lists
  • GET /api/v1/accounts/relationships
  • GET /api/v1/accounts/search
  • GET /api/v1/apps/verify_credentials
  • GET /api/v1/bookmarks
  • POST /api/v1/apps
  • GET /api/v1/blocks
  • GET /api/v1/conversations
  • DELETE /api/v1/conversations/:id
  • POST /api/v1/conversations/:id/read
  • GET /api/v1/favourites
  • GET /api/v1/filters
  • POST /api/v1/filters
  • GET /api/v1/filters/:id
  • PUT /api/v1/filters/:id
  • DELETE /api/v1/filters/:id
  • GET /api/v1/follow_requests
  • POST /api/v1/follow_requests/:id/authorize
  • POST /api/v1/follow_requests/:id/reject
  • POST /api/v1/follows
  • GET /api/v1/instance
  • GET /api/v1/instance/activity
  • GET /api/v1/instance/peers
  • GET /api/v1/lists
  • GET /api/v1/lists/:id/accounts
  • GET /api/v1/lists/:id
  • POST /api/v1/lists
  • PUT /api/v1/lists/:id
  • DELETE /api/v1/lists/:id
  • POST /api/v1/lists/:id/accounts
  • DELETE /api/v1/lists/:id/accounts
  • POST /api/v1/media
  • GET /api/v1/mutes
  • GET /api/v1/notifications
  • GET /api/v1/notifications/:id
  • POST /api/v1/notifications/:id/dismiss
  • POST /api/v1/notifications/clear
  • POST /api/v1/push/subscription
  • GET /api/v1/push/subscription
  • PUT /api/v1/push/subscription
  • DELETE /api/v1/push/subscription
  • GET /api/v1/reports
  • POST /api/v1/reports
  • GET /api/v2/search
  • GET /api/v1/statuses/:id
  • GET /api/v1/statuses/:id/context
  • GET /api/v1/statuses/:id/card
  • GET /api/v1/statuses/:id/history
  • GET /api/v1/statuses/:id/reblogged_by
  • GET /api/v1/statuses/:id/source
  • GET /api/v1/statuses/:id/favourited_by
  • POST /api/v1/statuses
  • PUT /api/v1/statuses/:id
  • DELETE /api/v1/statuses/:id
  • POST /api/v1/statuses/:id/reblog
  • POST /api/v1/statuses/:id/unreblog
  • POST /api/v1/statuses/:id/favourite
  • POST /api/v1/statuses/:id/unfavourite
  • POST /api/v1/statuses/:id/bookmark
  • POST /api/v1/statuses/:id/unbookmark
  • GET /api/v1/timelines/home
  • GET /api/v1/timelines/public
  • GET /api/v1/timelines/tag/:hashtag
  • GET /api/v1/timelines/list/:id
  • GET /api/v1/streaming/user
  • GET /api/v1/streaming/public
  • GET /api/v1/streaming/hashtag?tag=:hashtag
  • GET /api/v1/streaming/hashtag/local?tag=:hashtag
  • GET /api/v1/streaming/list?list=:list_id
  • GET /api/v1/streaming/direct

Installation

go install github.com/mattn/go-mastodon@latest

License

MIT

Author

Yasuhiro Matsumoto (a.k.a. mattn)

go-mastodon's People

Contributors

178inaba avatar bamchoh avatar benlubar avatar buckket avatar datsuns avatar dtluna avatar hiromi-mi avatar hymkor avatar keltia avatar makenowjust avatar marians avatar mattn avatar mellowdrifter avatar muesli avatar orzfly avatar philoserf avatar raff avatar rasmuslindroth avatar renovate-bot avatar shinenelson avatar spotlightishere avatar strubbl avatar suzukaze avatar till avatar tyrm avatar utam0k avatar vyskocilm avatar waybackarchiver avatar y0za avatar ykzts avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-mastodon's Issues

bad authorization: 400 Bad Request: invalid_grant

I know this has been raised before although I can't seem to work out what the issue is. I've tried registering the app in the web UI preferences and also with [go-mastodon](https://github.com/mattn/go-mastodon) and whatever I try I get bad authorization: 400 Bad Request: invalid_grant in response.

I've tried the following code (obviously with the correct values) and I can't get it to work, any ideas I could try?

Thanks!

package main

import (
	"context"
	"log"

	"github.com/mattn/go-mastodon"
)

func main() {
	app, err := mastodon.RegisterApp(context.Background(), &mastodon.AppConfig{
		Server:     "https://the.server",
		ClientName: "my-client",
		Scopes:     "read write follow",
		Website:    "https://github.com/the/path",
	})
	if err != nil {
		log.Fatal(err)
	}

	cl := mastodon.NewClient(&mastodon.Config{
		Server:       "https://the.server",
		ClientID:     app.ClientID,
		ClientSecret: app.ClientSecret,
	})
	err = cl.Authenticate(context.Background(), "[email protected]", "password")
	if err != nil {
		log.Fatal(err)
	}
}

param name for client.AddToList should be account_ids[] not account_ids

Currently the URL that's produced is like so:

https://social.coop/api/v1/lists/1064/accounts?account_ids=109348240344188934

Which returns 200 but does not add to the list.

This will actually add to the list:

https://social.coop/api/v1/lists/1064/accounts?account_ids[]=109348240344188934

I made this change to complete my task, but not raising a PR because I'm not sure where else this might be happening.

+++ b/lists.go
@@ -90,7 +90,7 @@ func (c *Client) DeleteList(ctx context.Context, id ID) error {
 func (c *Client) AddToList(ctx context.Context, list ID, accounts ...ID) error {
        params := url.Values{}
        for _, acct := range accounts {
-               params.Add("account_ids", string(acct))
+               params.Add("account_ids[]", string(acct))
        }

Question on pagination

I am attempting to use this library to write a bot that posts markov generated sentences based upon a users history. Below is a snippet of the code I am using to download an accounts history:

pg := mastodon.Pagination{}
last, err := s.db.GetLastStatusIdForAccount(*account)
fmt.Println(fmt.Sprintf("Continuing from: %s", last))

if err != nil {
	return cli.Exit(err, 1)
}

if last != "-1" {
	pg.MinID = last
}

page := 1
for {
	ss, err := s.client.GetAccountStatuses(context.Background(), account.ID, &pg)
	if err != nil {
		return cli.Exit(err, 1)
	}

	err = s.db.InsertStatuses(ss)
	if err != nil {
		return cli.Exit(err, 1)
	}

	fmt.Println(fmt.Sprintf("%d, Messages Found: %d", page, len(ss)))

	if pg.MaxID == "" {
		break
	}
	pg.SinceID = ""
	pg.MinID = ""
	time.Sleep(3 * time.Second)
	page++
}

By setting the MinID to an empty string in each iteration it seems to go from the most recent page backwards; my account has about 6000 statuses but this seems to get to 70 pages of 20 results plus a final page of 6 making for a total of about 1,300 statuses.

Is there something I am doing wrong or does Mastodon/Pleroma limit how far back in history we can go with the API?

Make scope configurable

It would be nice to make the scope to operate on configurable in Authenticate. Currently it's hard-coded to "read write follow", which seems to be the full permission set.

How do you add max_id, since_id, limit?

max_id, since_id, limit is required with the following APIs.

  • GET /api/v1/accounts/:id/followers
  • GET /api/v1/accounts/:id/following
  • GET /api/v1/accounts/:id/statuses
  • GET /api/v1/blocks
  • GET /api/v1/favourites
  • GET /api/v1/follow_requests
  • GET /api/v1/mutes
  • GET /api/v1/notifications
  • GET /api/v1/statuses/:id/reblogged_by
  • GET /api/v1/statuses/:id/favourited_by
  • GET /api/v1/timelines/home
  • GET /api/v1/timelines/public
  • GET /api/v1/timelines/tag/:hashtag

https://github.com/tootsuite/documentation/blob/master/Using-the-API/API.md

I have three ideas.

  1. Definitely define arguments and return values.
func (c *Client) GetTimelineHome(ctx context.Context, maxID, sinceID, limit *int) (tl []*Status, retMaxID, retSinceID int, err error)
  1. Will use the new type Pagination.
type Pagination struct {
	MaxID   *int
	SinceID *int
	Limit   *int
}

func (c *Client) GetTimelineHome(ctx context.Context, pn *Pagination) ([]*Status, *Pagination, error)
  1. Return the max_id and since_id using the Timeline type.
type Timeline struct {
	Statuses []*Status
	MaxID    int
	SinceID  int
}

func (c *Client) GetTimelineHome(ctx context.Context, maxID, sinceID, limit *int) (*Timeline, error)

Which do you think is good?
Also, please tell me if there is any other good way.

Why is the default HTTP client passed by value and not as a pointer?

To give a bit of context as to what I am talking about, here is how the NewClient function looks like:

// NewClient returns a new mastodon API client.
func NewClient(config *Config) *Client {
	return &Client{
		Client: *http.DefaultClient,
		Config: config,
	}
}

While I could possibly understand the concerns (prevent mutability, etc), it breaks the expected semantic. http.Client is a pointer type (as it can be seen by http.DefaultHTTPClient). Even though a copy by value is perfectly OK for now, you may never know if it won't hold a mutex or something similar in the future that would turn making a copy into a bug.

AccessToken is private

When trying to work with AuthenticateToken I found it quite confusing on how to get the returned AccessToken. It's currently located in a private member of the client and it's unclear how the developer intends for you to save it for future use.

I ended up just temporarily modifying the code to just print it out to console, but that seems like an awful solution. I think a could solution would be return it on AuthenticateToken().

bad authorization: invalid_request while trying to connect to a gotosocial instance

Im trying to send a Toot to a gotosocial instance.
While its working perfectly fine sending a Toot to a Mastodon Instance, it does throw an invalid_request error to gotosocial.

The code that I use for reference

func postToMastodon(text string) error {

  var c *mastodon.Client
  var t *mastodon.Toot

  // Register App
  app, err := mastodon.RegisterApp(context.Background(), &mastodon.AppConfig{
    Server:     "https://this.server/",
    ClientName: "relaystation",
    Scopes:     "read write follow",
    Website:    "urn:ietf:wg:oauth:2.0:oob",
  })
  if err != nil {
    log.Fatal(err)
  }

  // authenticate 
  c = mastodon.NewClient(&mastodon.Config{
    Server:       "https://this.server/",
    ClientID:     app.ClientID,
    ClientSecret: app.ClientSecret,
  })

  err = c.Authenticate(context.Background(), "[email protected]",  "secret")
  if err != nil {
    log.Fatal(err)
  }

  t = &mastodon.Toot{}
  t.Status = text

}

This is the error that I get

2022/12/20 11:47:53 bad authorization: 400 Bad Request: invalid_request

This is in the logs of gotosocial.

gotosocial[843043]: timestamp="20/12/2022 10:07:17.585" func=router.loggingMiddleware.func1 level=INFO latency=338.232µs clientIP=10.88.0.29 userAgent=Go-http-client/2.0 method=POST statusCode=400 path=/oauth/token msg="Bad Request: wrote 115B"

And the corresponding part on the gotosocial side of auth is https://github.com/superseriousbusiness/gotosocial/blob/694a49058951de31cca4ea061e2c08d44e712612/internal/api/client/auth/token.go#L32-L55

I'm not entirely sure what the cause, someone else having this issue or am I doing something wrong?

not get ContactAccount

Instance構造体のContactAccountですが、jsonの定義が間違っているためデータがnilで返ってきます。
json:"contact_account"」が正しいのではないでしょうか?

"bad authorization: 401 Unauthorized: invalid_grant"

I'm currently trying to write a mastodon bot (source code is available here), but unfortunately I get a "invalid_grant" error. The exact error message is:

bad authorization: 401 Unauthorized: invalid_grant

If I register my app and the immediately post a status everything's fine. But the bots purpose is to post every 3.56 days the current status of the year (e.g. "51% if the year is over"), and this somehow leads to the mentioned error. Any idea on how to debug this? Or what I could do about it?! Currently I'm using username/password for authentication, so this shouldn't be a problem (IMHO, not sure about that). Is there maybe a (hidden) access token that gets invalid after a certain time?

Edit: The instance I'm using is mastodon.bayern (Mastodon v2.8.0), and the account is marked as "bot". Not sure if this makes any difference.

streaming endpoint URL not at the main domain

The streaming endpoint URL may not be located at the main domain. For instance mastodon.social has it's streaming endpoint at streaming.mastodon.social.

streaming.go currently expects the endpoint to be at the main domain. The actual URL should probably be fetched in StreamingUser() and handed over to streaming() in full. Both methods would need to be touched. Do you want me to apply the change?

Provide formatted text in --json?

Currently, we can decide whether we want --simplejson, which lacks a lot of detail (acct, date...)
or --json, which contains all upstream data but no conveniently formatted text.

Would it be possible to add the result of textContent to the --json format too, so it's easier to work with it without formatting HTML downstream?

I got an error when I use websocket.

I got an error below when I use StreamingWSUser().


panic: interface conversion: interface {} is string, not float64

goroutine 18 [running]:
github.com/mattn/go-mastodon.(*WSClient).handleWS(0xc4204261c0, 0x7d4cc0, 0xc420016058, 0xc42008a780, 0x7d, 0xc42001a7e0, 0x0, 0xc420280240)
/go/src/github.com/mattn/go-mastodon/streaming_ws.go:131 +0x93d
github.com/mattn/go-mastodon.(*WSClient).streamingWS.func1(0xc42001a7e0, 0xc4204261c0, 0x7d4cc0, 0xc420016058, 0xc4200dc280)
/go/src/github.com/mattn/go-mastodon/streaming_ws.go:72 +0x95
created by github.com/mattn/go-mastodon.(*WSClient).streamingWS
/go/src/github.com/mattn/go-mastodon/streaming_ws.go:69 +0x339

Can't get it working.

I know I'm just an idiot, but I can't figure out how to get it working. Please, send instructions. I have been trying to get it to work for 1+ hrs. I use Win11, I have Go installed.

ClientID/ClientSecret requirement for AuthenticateToken

I've previously used Mastodon.py and once you have the AccessToken you don't require the ClientID and ClientSecret. This doesn't seem to be the case with go-mastodon. Is there a reason for this? Can this be changed to Mastodon.py's behavior?

Registration with Mastodon 2.0 server?

Is it possible that this a problem with Mastodon 2.0?
vxv@vxl:/wrk/scoop/cli$ cat reg.go

package main

import (
	"context"
	"fmt"
	"log"

	masto "github.com/mattn/go-mastodon"
)

func main() {
	app, err := masto.RegisterApp(context.Background(), &masto.AppConfig{
		Server:     "https://social.coop",
		ClientName: "socialcoop-blog",
		Scopes:     "read write follow",
		Website:    "https://social.coop/@h",
	})
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("client-id    : %v+\n", app.ClientID)
	fmt.Printf("client-secret: %v+\n", app.ClientSecret)
}
vxv@vxl:/wrk/scoop/cli$ go build reg.go
vxv@vxl:/wrk/scoop/cli$ ./reg
2017/11/22 22:48:38 json: cannot unmarshal string into Go struct field Application.id of type int64
vxv@vxl:/wrk/scoop/cli$ 

AuthenticateApp doesn't provide scopes but Authenticate does?

I'm trying to use AuthenticateApp and it seems to be authenticating ok (at least, it doesn't err) but when I try to post a status I get the following error:

bad request: 403 Forbidden: This action is outside the authorized scopes

yet I have read/write all scopes selected on my app configuration within mastodon (created manually and just using teh client id/secret from that)

So I got to looking and noticed that the Authenticate func provides scopes:

// Authenticate gets access-token to the API.
func (c *Client) Authenticate(ctx context.Context, username, password string) error {
	params := url.Values{
		"client_id":     {c.Config.ClientID},
		"client_secret": {c.Config.ClientSecret},
		"grant_type":    {"password"},
		"username":      {username},
		"password":      {password},
		"scope":         {"read write follow"},
	}

	return c.authenticate(ctx, params)
}

Here's the action I'm trying to take:

theToot := mastodon.Toot{
		Status: message,
	}
_, err = client.PostStatus(context.Background(), &theToot)

Does AuthenticateApp need to do the same to work? Or am I doing something dumb? :)

Thanks!

No API v2 support yet?

It looks like the library doesn't yet have any support for the V2 APIs introduced in Mastodon 4.0.0. Is there work underway to add it? I need some support for it and don't mind at all starting to add it in, but I don't want to duplicate work that's already underway.

Edit post/status

Hi,
I was wondering if there is any editing option for the statuses in the package or not. So for example if we have a status that is already posted on Mastodon, is there any way that we can edit that?

Pagination not working with GetTimelinePublic and Mastodon 2.6.5

I tried using go-mastodon against the https://chaos.social instance, which uses version 2.6.5 according to https://chaos.social/api/v1/instance, with following code:

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/mattn/go-mastodon"
)

func main() {
	ctx := context.Background()

	c := mastodon.NewClient(&mastodon.Config{
		Server: "https://chaos.social",
	})

	pg := mastodon.Pagination{}

	for {
		timeline, err := c.GetTimelinePublic(ctx, false, &pg)
		if err != nil {
			log.Println(err)
		}

		for _, item := range timeline {
			fmt.Printf("%#v\n", item)
		}

		if pg.MaxID == "" {
			break
		}

		time.Sleep(10 * time.Second)
	}
}

This quits with the output

2018/12/21 07:25:04 strconv.ParseInt: parsing "": invalid syntax

which is coming from

id, err := strconv.ParseInt(val, 10, 64)

I have an experimental fix that works for me here for the simple purpose of the above code: https://github.com/marians/go-mastodon/pull/1/files

My understanding of the Mastodon API version differences is not deep enough to tell when min_id has been introduced, where it is used, whether since_id is still in use etc. So I can't provide a PR currently that makes pagination work in all cases. Hopefully the description is enough for others to do so. Thanks!

Display acct, not username

Since Mastodon is a federated system, usernames are not unique, and we don't necessarily know which username was the real poster. The data in account.acct will be equal to username for the same instance, and else something like [email protected].

(This is what the official web frontend displays too.)

Add description to attachments

Hi,

UploadMedia and UploadMediaFromReader doesn't seem to support adding a description to your files or am I missing something?

I can help with a PR in that case, but want to know if it's already possible first

panic: interface conversion: interface {} is string, not float64

wsClientを使って、タイムラインを取得するとpanicします。以下がエラー情報です。

panic: interface conversion: interface {} is string, not float64

goroutine 15 [running]:
github.com/silverscat/mastodon-go-test/vendor/github.com/mattn/go-mastodon.(*WSClient).handleWS(0xc42030d650, 0x6fa860, 0xc42001a0e8, 0xc42008b300, 0x7c, 0xc42007ce40, 0x0, 0x0)
        /home/kugo/go/src/github.com/silverscat/mastodon-go-test/vendor/github.com/mattn/go-mastodon/streaming_ws.go:130 +0x7d8
github.com/silverscat/mastodon-go-test/vendor/github.com/mattn/go-mastodon.(*WSClient).streamingWS.func1(0xc42007ce40, 0xc42030d650, 0x6fa860, 0xc42001a0e8, 0xc42011ae00)
        /home/kugo/go/src/github.com/silverscat/mastodon-go-test/vendor/github.com/mattn/go-mastodon/streaming_ws.go:71 +0x95
created by github.com/silverscat/mastodon-go-test/vendor/github.com/mattn/go-mastodon.(*WSClient).streamingWS
        /home/kugo/go/src/github.com/silverscat/mastodon-go-test/vendor/github.com/mattn/go-mastodon/streaming_ws.go:68 +0x352
exit status 2

以下のコードで再現

package main

import (
	"context"
	"fmt"
	"log"
	"regexp"

	mastodon "github.com/mattn/go-mastodon"
)

func main() {
	client := mastodon.NewClient(&mastodon.Config{Server: "https://pawoo.net", ClientID: "くらいあんとあいでー", ClientSecret: "くらいあんとしーくれっと"})
	if err := client.Authenticate(context.Background(), "いーめーる", "ぱすわーど"); err != nil {
		log.Fatal(err)
	}
	wsClient := client.NewWSClient()

	for {
		events, err := wsClient.StreamingWSPublic(context.Background(), false)
		if err != nil {
			log.Fatal(err)
		}
		for event := range events {
			if upEvent, ok := event.(*mastodon.UpdateEvent); ok {
				fmt.Println(fmt.Sprintf("%s %s %s", upEvent.Status.Account.Acct, upEvent.Status.CreatedAt.Local().Format("2006/1/2 15:04:05"), upEvent.Status.Content))
			}
		}
	}
}

Remove 1.15 build test?

This project has a go.mod version set to 1.16, but build tests are still testing on 1.15 - Is this intentional? I ask as a couple of functions were moved out of ioutil into os in 1.16 and I'd like to clean that up. But that breaks the 1.15 build

tag commits from time to time

Hey,

can you please start tagging your commits from time to time to be able to stay up to date when using go mod?

Cheers

pagination since_id is ignored when max_id is set

For example, if I have the following statusIDs.
100, 99, 98 ... 1

If I make the following call:
/api/v1/timelines/public?since_id=74&max_id=78

I would expect the following results: [77, 76, 75]. This is also what I get when I call the api directly.

However, what I currently see is : [77, 76, 75, 74, 73, 72, ... etc]

I don't understand why go-mastodon deliberately sets since_id to an empty string if a max_id is specified. I would like to be able to paginate through the results until I reach the since_id that I specified, but that's not currently possible because when I specify a max_id, then my since_id value is ignored...

Instead of https://github.com/mattn/go-mastodon/blob/master/mastodon.go#L311

func (p *Pagination) setValues(params url.Values) url.Values {
	if p.MaxID != "" {
		params.Set("max_id", string(p.MaxID))
	} else if p.SinceID != "" {
		params.Set("since_id", string(p.SinceID))
	}
	if p.Limit > 0 {
		params.Set("limit", fmt.Sprint(p.Limit))
	}

	return params
}

why not?:

	if p.MaxID != "" {
		params.Set("max_id", string(p.MaxID))
	}
if p.SinceID != "" {
		params.Set("since_id", string(p.SinceID))
	}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.