diff --git a/content.go b/content.go index 13df2d8..d7e4fe4 100644 --- a/content.go +++ b/content.go @@ -15,21 +15,15 @@ func ContentFormat(data interface{}) (n []Node, err error) { switch src := data.(type) { case string: dst, err = html.Parse(strings.NewReader(src)) - if err != nil { - return nil, err - } case []byte: dst, err = html.Parse(bytes.NewReader(src)) - if err != nil { - return nil, err - } case io.Reader: dst, err = html.Parse(src) - if err != nil { - return nil, err - } default: - return nil, ErrInvalidDataType + err = ErrInvalidDataType + } + if err != nil { + return nil, err } n = append(n, domToNode(dst.FirstChild)) diff --git a/content_test.go b/content_test.go new file mode 100644 index 0000000..73cc211 --- /dev/null +++ b/content_test.go @@ -0,0 +1,27 @@ +package telegraph + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestContentFormat(t *testing.T) { + t.Run("invalid", func(t *testing.T) { + _, err := ContentFormat(42) + assert.EqualError(t, ErrInvalidDataType, err.Error()) + }) + + t.Run("valid", func(t *testing.T) { + t.Run("string", func(t *testing.T) { + validContentDOM, err := ContentFormat(`

Hello, World!

`) + assert.NoError(t, err) + assert.NotEmpty(t, validContentDOM) + }) + t.Run("bytes", func(t *testing.T) { + validContentDOM, err := ContentFormat([]byte(`

Hello, World!

`)) + assert.NoError(t, err) + assert.NotEmpty(t, validContentDOM) + }) + }) +} diff --git a/create_account.go b/create_account.go index 8bfff9d..e550a83 100644 --- a/create_account.go +++ b/create_account.go @@ -1,7 +1,6 @@ package telegraph import ( - json "github.com/pquerna/ffjson/ffjson" http "github.com/valyala/fasthttp" ) @@ -10,24 +9,19 @@ import ( // keep individual author names and profile links for each of their channels. On // success, returns an Account object with the regular fields and an additional // access_token field. -func CreateAccount(account *Account) (r *Account, err error) { - if account == nil { - return nil, ErrNoInputData - } - +func CreateAccount(account Account) (*Account, error) { args := http.AcquireArgs() defer http.ReleaseArgs(args) args.Add("short_name", account.ShortName) // required args.Add("author_name", account.AuthorName) args.Add("author_url", account.AuthorURL) - dst := new(Response) - dst, err = makeRequest("createAccount", args) + data, err := makeRequest("createAccount", args) if err != nil { - return + return nil, err } - r = new(Account) - err = json.Unmarshal(*dst.Result, r) - return + var result Account + err = parser.Unmarshal(data, &result) + return &result, err } diff --git a/create_account_test.go b/create_account_test.go new file mode 100644 index 0000000..105dfd6 --- /dev/null +++ b/create_account_test.go @@ -0,0 +1,31 @@ +package telegraph + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCreateAccount(t *testing.T) { + t.Run("invalid", func(t *testing.T) { + t.Run("nil", func(t *testing.T) { + _, err := CreateAccount(Account{}) + assert.Error(t, err) + }) + t.Run("without shortname", func(t *testing.T) { + _, err := CreateAccount(Account{ + ShortName: "", + AuthorName: "Anonymous", + }) + assert.Error(t, err) + }) + }) + t.Run("valid", func(t *testing.T) { + account, err := CreateAccount(Account{ + ShortName: "Sandbox", + AuthorName: "Anonymous", + }) + assert.NoError(t, err) + assert.NotNil(t, account) + }) +} diff --git a/create_page.go b/create_page.go index e702119..89382c6 100644 --- a/create_page.go +++ b/create_page.go @@ -3,38 +3,31 @@ package telegraph import ( "strconv" - json "github.com/pquerna/ffjson/ffjson" http "github.com/valyala/fasthttp" ) // CreatePage create a new Telegraph page. On success, returns a Page object. -func (a *Account) CreatePage(page *Page, returnContent bool) (r *Page, err error) { - if page == nil { - return nil, ErrNoInputData - } - - var src []byte - src, err = json.Marshal(page.Content) +func (a *Account) CreatePage(page Page, returnContent bool) (*Page, error) { + src, err := parser.Marshal(page.Content) if err != nil { - return + return nil, err } args := http.AcquireArgs() defer http.ReleaseArgs(args) args.Add("access_token", a.AccessToken) // required args.Add("title", page.Title) // required - args.Add("author_name", a.AuthorName) - args.Add("author_url", a.AuthorURL) - args.Add("content", string(src)) + args.Add("author_name", page.AuthorName) + args.Add("author_url", page.AuthorURL) + args.AddBytesV("content", src) args.Add("return_content", strconv.FormatBool(returnContent)) - dst := new(Response) - dst, err = makeRequest("createPage", args) + data, err := makeRequest("createPage", args) if err != nil { return nil, err } - r = new(Page) - err = json.Unmarshal(*dst.Result, r) - return + var result Page + err = parser.Unmarshal(data, &result) + return &result, err } diff --git a/create_page_test.go b/create_page_test.go new file mode 100644 index 0000000..6c0f5e4 --- /dev/null +++ b/create_page_test.go @@ -0,0 +1,39 @@ +package telegraph + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCreatePage(t *testing.T) { + content, err := ContentFormat(`

Hello, world!

`) + assert.NoError(t, err) + + t.Run("invalid", func(t *testing.T) { + var a Account + _, err := a.CreatePage(Page{ + Title: "Sample Page", + AuthorName: "Anonymous", + Content: content, + }, true) + assert.Error(t, err) + }) + t.Run("valid", func(t *testing.T) { + a := Account{ + AccessToken: "b968da509bb76866c35425099bc0989a5ec3b32997d55286c657e6994bbb", + ShortName: "Sandbox", + AuthorName: "Anonymous", + } + + page, err := a.CreatePage(Page{ + Title: "Sample Page", + AuthorName: "Anonymous", + Content: content, + }, true) + if !assert.NoError(t, err) { + t.FailNow() + } + assert.NotEmpty(t, page.URL) + }) +} diff --git a/edit_account_info.go b/edit_account_info.go index e9f6f15..0356fea 100644 --- a/edit_account_info.go +++ b/edit_account_info.go @@ -1,18 +1,13 @@ package telegraph import ( - json "github.com/pquerna/ffjson/ffjson" http "github.com/valyala/fasthttp" ) // EditAccountInfo update information about a Telegraph account. Pass only the // parameters that you want to edit. On success, returns an Account object with // the default fields. -func (a *Account) EditAccountInfo(update *Account) (r *Account, err error) { - if update == nil { - return nil, ErrNoInputData - } - +func (a *Account) EditAccountInfo(update Account) (*Account, error) { args := http.AcquireArgs() defer http.ReleaseArgs(args) args.Add("access_token", a.AccessToken) // required @@ -20,13 +15,12 @@ func (a *Account) EditAccountInfo(update *Account) (r *Account, err error) { args.Add("author_name", update.AuthorName) args.Add("author_url", update.AuthorURL) - dst := new(Response) - dst, err = makeRequest("editAccountInfo", args) + data, err := makeRequest("editAccountInfo", args) if err != nil { return nil, err } - r = new(Account) - err = json.Unmarshal(*dst.Result, r) - return + var result Account + err = parser.Unmarshal(data, &result) + return &result, err } diff --git a/edit_account_info_test.go b/edit_account_info_test.go new file mode 100644 index 0000000..2c1d1c2 --- /dev/null +++ b/edit_account_info_test.go @@ -0,0 +1,28 @@ +package telegraph + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestEditAccountInfo(t *testing.T) { + t.Run("invalid", func(t *testing.T) { + var a Account + _, err := a.EditAccountInfo(Account{}) + assert.Error(t, err) + }) + t.Run("valid", func(t *testing.T) { + a := Account{ + AccessToken: "b968da509bb76866c35425099bc0989a5ec3b32997d55286c657e6994bbb", + ShortName: "Sandbox", + AuthorName: "Anonymous", + } + + _, err := a.EditAccountInfo(Account{ + ShortName: "Sandbox", + AuthorName: "Anonymous", + }) + assert.NoError(t, err) + }) +} diff --git a/edit_page.go b/edit_page.go index 69530e9..14065f7 100644 --- a/edit_page.go +++ b/edit_page.go @@ -4,20 +4,14 @@ import ( "path" "strconv" - json "github.com/pquerna/ffjson/ffjson" http "github.com/valyala/fasthttp" ) // EditPage edit an existing Telegraph page. On success, returns a Page object. -func (a *Account) EditPage(update *Page, returnContent bool) (r *Page, err error) { - if update == nil { - return nil, ErrNoInputData - } - - var src []byte - src, err = json.Marshal(update.Content) +func (a *Account) EditPage(update Page, returnContent bool) (*Page, error) { + src, err := parser.Marshal(update.Content) if err != nil { - return + return nil, err } args := http.AcquireArgs() @@ -25,18 +19,17 @@ func (a *Account) EditPage(update *Page, returnContent bool) (r *Page, err error args.Add("access_token", a.AccessToken) // required args.Add("path", update.Path) // required args.Add("title", update.Title) // required - args.Add("content", string(src)) // required - args.Add("author_name", a.AuthorName) - args.Add("author_url", a.AuthorURL) + args.AddBytesV("content", src) // required + args.Add("author_name", update.AuthorName) + args.Add("author_url", update.AuthorURL) args.Add("return_content", strconv.FormatBool(returnContent)) - dst := new(Response) - dst, err = makeRequest(path.Join("editPage", update.Path), args) + data, err := makeRequest(path.Join("editPage", update.Path), args) if err != nil { return nil, err } - r = new(Page) - err = json.Unmarshal(*dst.Result, r) - return + var result Page + err = parser.Unmarshal(data, &result) + return &result, err } diff --git a/edit_page_test.go b/edit_page_test.go new file mode 100644 index 0000000..acc8842 --- /dev/null +++ b/edit_page_test.go @@ -0,0 +1,38 @@ +package telegraph + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestEditPage(t *testing.T) { + content, err := ContentFormat("

Hello, world!

") + assert.NoError(t, err) + + t.Run("invalid", func(t *testing.T) { + var a Account + _, err := a.EditPage(Page{ + Title: "Sample Page", + AuthorName: "Anonymous", + Content: content, + }, true) + assert.Error(t, err) + }) + t.Run("valid", func(t *testing.T) { + a := Account{ + AccessToken: "b968da509bb76866c35425099bc0989a5ec3b32997d55286c657e6994bbb", + ShortName: "Sandbox", + AuthorName: "Anonymous", + } + + page, err := a.EditPage(Page{ + Path: "Sample-Page-12-15", + Title: "Sample Page", + AuthorName: "Anonymous", + Content: content, + }, true) + assert.NoError(t, err) + assert.NotEmpty(t, page.Content) + }) +} diff --git a/example_test.go b/example_test.go index ea39b00..e55ac0b 100644 --- a/example_test.go +++ b/example_test.go @@ -2,7 +2,6 @@ package telegraph_test import ( "log" - "time" "gitlab.com/toby3d/telegraph" ) @@ -23,9 +22,9 @@ const data = ` ` var ( - account = new(telegraph.Account) - page = new(telegraph.Page) - content []telegraph.Node + account *telegraph.Account //nolint:gochecknoglobals + page *telegraph.Page //nolint:gochecknoglobals + content []telegraph.Node //nolint:gochecknoglobals ) func errCheck(err error) { @@ -37,7 +36,7 @@ func errCheck(err error) { func Example_fastStart() { var err error // Create new Telegraph account. - requisites := &telegraph.Account{ + requisites := telegraph.Account{ ShortName: "toby3d", // required // Author name/link can be epmty. So secure. Much anonymously. Wow. @@ -58,7 +57,7 @@ func Example_fastStart() { // Boom!.. And your text will be understandable for Telegraph. MAGIC. // Create new Telegraph page - pageData := &telegraph.Page{ + pageData := telegraph.Page{ Title: "My super-awesome page", // required Content: content, // required @@ -75,7 +74,7 @@ func Example_fastStart() { func ExampleCreateAccount() { var err error - account, err = telegraph.CreateAccount(&telegraph.Account{ + account, err = telegraph.CreateAccount(telegraph.Account{ ShortName: "Sandbox", AuthorName: "Anonymous", }) @@ -89,7 +88,7 @@ func ExampleCreateAccount() { func ExampleAccount_EditAccountInfo() { var err error - account, err = account.EditAccountInfo(&telegraph.Account{ + account, err = account.EditAccountInfo(telegraph.Account{ ShortName: "Sandbox", AuthorName: "Anonymous", }) @@ -122,7 +121,7 @@ func ExampleAccount_RevokeAccessToken() { func ExampleAccount_CreatePage() { var err error - page, err = account.CreatePage(&telegraph.Page{ + page, err = account.CreatePage(telegraph.Page{ Title: "Sample Page", AuthorName: account.AuthorName, Content: content, @@ -135,7 +134,7 @@ func ExampleAccount_CreatePage() { func ExampleAccount_EditPage() { var err error - page, err = account.EditPage(&telegraph.Page{ + page, err = account.EditPage(telegraph.Page{ Title: "Sample Page", AuthorName: account.AuthorName, Content: content, @@ -169,10 +168,7 @@ func ExampleAccount_GetPageList() { func ExampleGetViews() { pagePath := "Sample-Page-12-15" - views, err := telegraph.GetViews( - pagePath, - time.Date(2016, 12, 0, 0, 0, 0, 0, nil), - ) + views, err := telegraph.GetViews(pagePath, 2016, 12) errCheck(err) log.Println(pagePath, "has been viewed", views.Views, "times") diff --git a/get_account_info.go b/get_account_info.go index caaa32e..ba8cc1f 100644 --- a/get_account_info.go +++ b/get_account_info.go @@ -3,24 +3,24 @@ package telegraph import ( "strings" - json "github.com/pquerna/ffjson/ffjson" http "github.com/valyala/fasthttp" ) // GetAccountInfo get information about a Telegraph account. Returns an Account object on success. -func (a *Account) GetAccountInfo(fields ...string) (r *Account, err error) { +func (a *Account) GetAccountInfo(fields ...string) (*Account, error) { args := http.AcquireArgs() defer http.ReleaseArgs(args) args.Add("access_token", a.AccessToken) // required - args.Add("fields", `["`+strings.Join(fields, `","`)+`"]`) + if len(fields) > 0 { + args.Add("fields", `["`+strings.Join(fields, `","`)+`"]`) + } - dst := new(Response) - dst, err = makeRequest("getAccountInfo", args) + data, err := makeRequest("getAccountInfo", args) if err != nil { return nil, err } - r = new(Account) - err = json.Unmarshal(*dst.Result, r) - return + var result Account + err = parser.Unmarshal(data, &result) + return &result, err } diff --git a/get_account_info_test.go b/get_account_info_test.go new file mode 100644 index 0000000..5dc2824 --- /dev/null +++ b/get_account_info_test.go @@ -0,0 +1,27 @@ +package telegraph + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetAccountInfo(t *testing.T) { + t.Run("invalid", func(t *testing.T) { + var a Account + _, err := a.GetAccountInfo() + assert.Error(t, err) + }) + t.Run("valid", func(t *testing.T) { + a := Account{ + AccessToken: "b968da509bb76866c35425099bc0989a5ec3b32997d55286c657e6994bbb", + ShortName: "Sandbox", + AuthorName: "Anonymous", + } + + info, err := a.GetAccountInfo(FieldShortName, FieldPageCount) + assert.NoError(t, err) + assert.Equal(t, a.ShortName, info.ShortName) + assert.NotZero(t, info.PageCount) + }) +} diff --git a/get_page.go b/get_page.go index 0f34b5a..fad4420 100644 --- a/get_page.go +++ b/get_page.go @@ -4,24 +4,22 @@ import ( gopath "path" "strconv" - json "github.com/pquerna/ffjson/ffjson" http "github.com/valyala/fasthttp" ) // GetPage get a Telegraph page. Returns a Page object on success. -func GetPage(path string, returnContent bool) (r *Page, err error) { +func GetPage(path string, returnContent bool) (*Page, error) { args := http.AcquireArgs() defer http.ReleaseArgs(args) args.Add("path", path) // required args.Add("return_content", strconv.FormatBool(returnContent)) - dst := new(Response) - dst, err = makeRequest(gopath.Join("getPage", path), args) + data, err := makeRequest(gopath.Join("getPage", path), args) if err != nil { return nil, err } - r = new(Page) - err = json.Unmarshal(*dst.Result, r) - return + var result Page + err = parser.Unmarshal(data, &result) + return &result, err } diff --git a/get_page_list.go b/get_page_list.go index 78db217..5a90dab 100644 --- a/get_page_list.go +++ b/get_page_list.go @@ -3,26 +3,28 @@ package telegraph import ( "strconv" - json "github.com/pquerna/ffjson/ffjson" http "github.com/valyala/fasthttp" ) // GetPageList get a list of pages belonging to a Telegraph account. Returns a PageList object, sorted // by most recently created pages first. -func (a *Account) GetPageList(offset, limit int) (r *PageList, err error) { +func (a *Account) GetPageList(offset, limit int) (*PageList, error) { args := http.AcquireArgs() defer http.ReleaseArgs(args) args.Add("access_token", a.AccessToken) // required - args.Add("offset", strconv.Itoa(offset)) - args.Add("limit", strconv.Itoa(limit)) + if offset > 0 { + args.Add("offset", strconv.Itoa(offset)) + } + if limit > 0 { + args.Add("limit", strconv.Itoa(limit)) + } - dst := new(Response) - dst, err = makeRequest("getPageList", args) + data, err := makeRequest("getPageList", args) if err != nil { return nil, err } - r = new(PageList) - err = json.Unmarshal(*dst.Result, r) - return + var result PageList + err = parser.Unmarshal(data, &result) + return &result, err } diff --git a/get_page_list_test.go b/get_page_list_test.go new file mode 100644 index 0000000..000bb97 --- /dev/null +++ b/get_page_list_test.go @@ -0,0 +1,26 @@ +package telegraph + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetPageList(t *testing.T) { + t.Run("invalid", func(t *testing.T) { + var a Account + _, err := a.GetPageList(0, 0) + assert.Error(t, err) + }) + t.Run("valid", func(t *testing.T) { + a := Account{ + AccessToken: "b968da509bb76866c35425099bc0989a5ec3b32997d55286c657e6994bbb", + ShortName: "Sandbox", + AuthorName: "Anonymous", + } + + list, err := a.GetPageList(1, 1) + assert.NoError(t, err) + assert.NotNil(t, list) + }) +} diff --git a/get_page_test.go b/get_page_test.go new file mode 100644 index 0000000..32a0734 --- /dev/null +++ b/get_page_test.go @@ -0,0 +1,19 @@ +package telegraph + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetPage(t *testing.T) { + t.Run("invalid", func(t *testing.T) { + _, err := GetPage("wtf", true) + assert.Error(t, err) + }) + t.Run("valid", func(t *testing.T) { + page, err := GetPage("Sample-Page-12-15", true) + assert.NoError(t, err) + assert.NotNil(t, page) + }) +} diff --git a/get_views.go b/get_views.go index bb2c985..f5c2fa5 100644 --- a/get_views.go +++ b/get_views.go @@ -3,30 +3,35 @@ package telegraph import ( gopath "path" "strconv" - "time" - json "github.com/pquerna/ffjson/ffjson" http "github.com/valyala/fasthttp" ) // GetViews get the number of views for a Telegraph article. By default, the total number of page // views will be returned. Returns a PageViews object on success. -func GetViews(path string, date time.Time) (r *PageViews, err error) { +func GetViews(path string, date ...int) (*PageViews, error) { args := http.AcquireArgs() defer http.ReleaseArgs(args) args.Add("path", path) // required - args.Add("year", strconv.Itoa(date.Year())) - args.Add("month", strconv.Itoa(int(date.Month()))) - args.Add("day", strconv.Itoa(date.Day())) - args.Add("hour", strconv.Itoa(date.Hour())) + if len(date) > 0 { + args.Add("year", strconv.Itoa(date[0])) + } + if len(date) > 1 { + args.Add("month", strconv.Itoa(date[1])) + } + if len(date) > 2 { + args.Add("day", strconv.Itoa(date[2])) + } + if len(date) > 3 { + args.Add("hour", strconv.Itoa(date[3])) + } - dst := new(Response) - dst, err = makeRequest(gopath.Join("getViews", path), args) + data, err := makeRequest(gopath.Join("getViews", path), args) if err != nil { return nil, err } - r = new(PageViews) - err = json.Unmarshal(*dst.Result, r) - return + var result PageViews + err = parser.Unmarshal(data, &result) + return &result, err } diff --git a/get_views_test.go b/get_views_test.go new file mode 100644 index 0000000..7167407 --- /dev/null +++ b/get_views_test.go @@ -0,0 +1,40 @@ +package telegraph + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGetViews(t *testing.T) { + t.Run("invalid", func(t *testing.T) { + t.Run("path", func(t *testing.T) { + _, err := GetViews("wtf") + assert.Error(t, err) + }) + t.Run("year", func(t *testing.T) { + _, err := GetViews("Sample-Page-12-15", 1980) + assert.Error(t, err) + }) + t.Run("month", func(t *testing.T) { + _, err := GetViews("Sample-Page-12-15", 2000, 22) + assert.Error(t, err) + }) + t.Run("day", func(t *testing.T) { + _, err := GetViews("Sample-Page-12-15", 2000, 2, 42) + assert.Error(t, err) + }) + t.Run("hour", func(t *testing.T) { + _, err := GetViews("Sample-Page-12-15", 2000, 2, 12, 65) + assert.Error(t, err) + }) + }) + t.Run("valid", func(t *testing.T) { + stats, err := GetViews("Sample-Page-12-15") + assert.NoError(t, err) + if !assert.NotNil(t, stats) { + t.FailNow() + } + assert.NotZero(t, stats.Views) + }) +} diff --git a/request.go b/request.go deleted file mode 100644 index daabef5..0000000 --- a/request.go +++ /dev/null @@ -1,65 +0,0 @@ -package telegraph - -import ( - gojson "encoding/json" - "errors" - "net/url" - - "github.com/kirillDanshin/dlog" - json "github.com/pquerna/ffjson/ffjson" - http "github.com/valyala/fasthttp" -) - -// Response contains a JSON object, which always has a Boolean field ok. If ok -// equals true, the request was successful, and the result of the query can be -// found in the result field. In case of an unsuccessful request, ok equals -// false, and the error is explained in the error field (e.g. -// SHORT_NAME_REQUIRED). -type Response struct { - Ok bool `json:"ok"` - Error string `json:"error"` - Result *gojson.RawMessage `json:"result,omitempty"` -} - -var defaultURL = url.URL{ - Scheme: "https", - Host: "api.telegra.ph", -} - -func makeRequest(path string, args *http.Args) (r *Response, err error) { - requestURL := defaultURL - requestURL.Path = path - requestURL.RawQuery = args.String() - - req := http.AcquireRequest() - defer http.ReleaseRequest(req) - req.Header.SetMethod("GET") - req.SetRequestURI(requestURL.String()) - req.Header.SetUserAgent("toby3d/telegraph") - req.Header.SetContentType("application/json;charset=utf-8") - - dlog.Ln("request:") - dlog.D(req) - - resp := http.AcquireResponse() - defer http.ReleaseResponse(resp) - err = http.Do(req, resp) - if err != nil { - dlog.Ln(err.Error()) - return - } - - dlog.Ln("response:") - dlog.D(resp) - - r = new(Response) - if err = json.Unmarshal(resp.Body(), r); err != nil { - return - } - - if !r.Ok { - err = errors.New(r.Error) - } - - return -} diff --git a/revoke_access_token.go b/revoke_access_token.go index f232663..27fbd4c 100644 --- a/revoke_access_token.go +++ b/revoke_access_token.go @@ -1,30 +1,23 @@ package telegraph import ( - json "github.com/pquerna/ffjson/ffjson" http "github.com/valyala/fasthttp" ) -type revokeAccessTokenParameters struct { - // Access token of the Telegraph account. - AccessToken string `json:"access_token"` // required -} - // RevokeAccessToken revoke access_token and generate a new one, for example, if the user would // like to reset all connected sessions, or you have reasons to believe the token was compromised. On // success, returns an Account object with new access_token and auth_url fields. -func (a *Account) RevokeAccessToken() (r *Account, err error) { +func (a *Account) RevokeAccessToken() (*Account, error) { args := http.AcquireArgs() defer http.ReleaseArgs(args) args.Add("access_token", a.AccessToken) - dst := new(Response) - dst, err = makeRequest("revokeAccessToken", args) + resp, err := makeRequest("revokeAccessToken", args) if err != nil { - return + return nil, err } - r = new(Account) - err = json.Unmarshal(*dst.Result, r) - return + var account Account + err = parser.Unmarshal(resp, &account) + return &account, err } diff --git a/revoke_access_token_test.go b/revoke_access_token_test.go new file mode 100644 index 0000000..69cadb4 --- /dev/null +++ b/revoke_access_token_test.go @@ -0,0 +1,31 @@ +package telegraph + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRevokeAccessToken(t *testing.T) { + t.Run("invalid", func(t *testing.T) { + var account Account + _, err := account.RevokeAccessToken() + assert.Error(t, err) + }) + t.Run("valid", func(t *testing.T) { + a, err := CreateAccount(Account{ + ShortName: "Sandbox", + AuthorName: "Anonymous", + }) + if !assert.NoError(t, err) { + t.FailNow() + } + + newAccount, err := a.RevokeAccessToken() + if !assert.NoError(t, err) { + t.FailNow() + } + assert.NotEqual(t, a.AccessToken, newAccount.AccessToken) + assert.NotEmpty(t, newAccount.AuthURL) + }) +} diff --git a/telegraph.go b/telegraph.go new file mode 100644 index 0000000..48619f1 --- /dev/null +++ b/telegraph.go @@ -0,0 +1,56 @@ +//go:generate ffjson $GOFILE +package telegraph + +import ( + gojson "encoding/json" + "errors" + + json "github.com/json-iterator/go" + http "github.com/valyala/fasthttp" +) + +// Response contains a JSON object, which always has a Boolean field ok. If ok +// equals true, the request was successful, and the result of the query can be +// found in the result field. In case of an unsuccessful request, ok equals +// false, and the error is explained in the error field (e.g. +// SHORT_NAME_REQUIRED). +type Response struct { + Ok bool `json:"ok"` + Error string `json:"error"` + Result gojson.RawMessage `json:"result,omitempty"` +} + +var parser = json.ConfigFastest //nolint:gochecknoglobals + +func makeRequest(path string, args *http.Args) ([]byte, error) { + u := http.AcquireURI() + defer http.ReleaseURI(u) + u.SetScheme("https") + u.SetHost("api.telegra.ph") + u.SetPath(path) + args.CopyTo(u.QueryArgs()) + + req := http.AcquireRequest() + defer http.ReleaseRequest(req) + req.Header.SetMethod(http.MethodGet) + req.SetRequestURIBytes(u.FullURI()) + req.Header.SetUserAgent("toby3d/telegraph") + req.Header.SetContentType("application/json; charset=utf-8") + + resp := http.AcquireResponse() + defer http.ReleaseResponse(resp) + if err := http.Do(req, resp); err != nil { + return nil, err + } + + var r Response + if err := parser.Unmarshal(resp.Body(), &r); err != nil { + return nil, err + } + + if !r.Ok { + return nil, errors.New(r.Error) + } + + return r.Result, nil +} diff --git a/types.go b/types.go index 4de8c3f..97ea0e7 100644 --- a/types.go +++ b/types.go @@ -1,9 +1,10 @@ -// All types used in the Telegraph API responses are represented as JSON-objects. -// Optional fields may be not returned when irrelevant. +//go:generate ffjson $GOFILE package telegraph import "errors" +// All types used in the Telegraph API responses are represented as JSON-objects. +// Optional fields may be not returned when irrelevant. type ( // Account represents a Telegraph account. Account struct {