♻️ Use json body instead query string

close #6
This commit is contained in:
Maxim Lebedev 2020-01-14 11:30:18 +05:00
parent b847b512ed
commit a1d24ae6f9
No known key found for this signature in database
GPG Key ID: F8978F46FF0FFA4F
15 changed files with 330 additions and 255 deletions

View File

@ -8,10 +8,10 @@ import (
"golang.org/x/net/html" "golang.org/x/net/html"
) )
// ContentFormat transforms data to a DOM-based format to represent the content // ContentFormat transforms data to a DOM-based format to represent the content of the page.
// of the page.
func ContentFormat(data interface{}) (n []Node, err error) { func ContentFormat(data interface{}) (n []Node, err error) {
dst := new(html.Node) var dst *html.Node
switch src := data.(type) { switch src := data.(type) {
case string: case string:
dst, err = html.Parse(strings.NewReader(src)) dst, err = html.Parse(strings.NewReader(src))
@ -20,14 +20,16 @@ func ContentFormat(data interface{}) (n []Node, err error) {
case io.Reader: case io.Reader:
dst, err = html.Parse(src) dst, err = html.Parse(src)
default: default:
err = ErrInvalidDataType return nil, ErrInvalidDataType
} }
if err != nil { if err != nil {
return nil, err return nil, err
} }
n = append(n, domToNode(dst.FirstChild)) n = append(n, domToNode(dst.FirstChild))
return
return n, nil
} }
func domToNode(domNode *html.Node) interface{} { func domToNode(domNode *html.Node) interface{} {
@ -40,18 +42,16 @@ func domToNode(domNode *html.Node) interface{} {
} }
var nodeElement NodeElement var nodeElement NodeElement
switch strings.ToLower(domNode.Data) { switch strings.ToLower(domNode.Data) {
case "a", "aside", "b", "blockquote", "br", "code", "em", "figcaption", case "a", "aside", "b", "blockquote", "br", "code", "em", "figcaption", "figure", "h3", "h4", "hr", "i",
"figure", "h3", "h4", "hr", "i", "iframe", "img", "li", "ol", "iframe", "img", "li", "ol", "p", "pre", "s", "strong", "u", "ul", "video":
"p", "pre", "s", "strong", "u", "ul", "video":
nodeElement.Tag = domNode.Data nodeElement.Tag = domNode.Data
for i := range domNode.Attr { for i := range domNode.Attr {
switch strings.ToLower(domNode.Attr[i].Key) { switch strings.ToLower(domNode.Attr[i].Key) {
case "href", "src": case "href", "src":
nodeElement.Attrs = map[string]string{ nodeElement.Attrs = map[string]string{domNode.Attr[i].Key: domNode.Attr[i].Val}
domNode.Attr[i].Key: domNode.Attr[i].Val,
}
default: default:
continue continue
} }

View File

@ -1,27 +1,35 @@
package telegraph package telegraph
import ( type createAccount struct {
http "github.com/valyala/fasthttp" // Account name, helps users with several accounts remember which they are currently using. Displayed to the
) // user above the "Edit/Publish" button on Telegra.ph, other users don't see this name.
ShortName string `json:"short_name"`
// CreateAccount create a new Telegraph account. Most users only need one // Default author name used when creating new articles.
// account, but this can be useful for channel administrators who would like to AuthorName string `json:"author_name,omitempty"`
// 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 // Default profile link, opened when users click on the author's name below the title. Can be any link, not
// access_token field. // necessarily to a Telegram profile or channel.
AuthorURL string `json:"author_url,omitempty"`
}
// CreateAccount create a new Telegraph account. Most users only need one account, but this can be useful for channel
// administrators who would like to 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) (*Account, error) { func CreateAccount(account Account) (*Account, error) {
args := http.AcquireArgs() data, err := makeRequest("createAccount", createAccount{
defer http.ReleaseArgs(args) ShortName: account.ShortName,
args.Add("short_name", account.ShortName) // required AuthorName: account.AuthorName,
args.Add("author_name", account.AuthorName) AuthorURL: account.AuthorURL,
args.Add("author_url", account.AuthorURL) })
data, err := makeRequest("createAccount", args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var result Account result := new(Account)
err = parser.Unmarshal(data, &result) if err = parser.Unmarshal(data, result); err != nil {
return &result, err return nil, err
}
return result, nil
} }

View File

@ -1,33 +1,44 @@
package telegraph package telegraph
import ( type createPage struct {
"strconv" // Access token of the Telegraph account.
AccessToken string `json:"access_token"`
http "github.com/valyala/fasthttp" // Page title.
) Title string `json:"title"`
// Author name, displayed below the article's title.
AuthorName string `json:"author_name,omitempty"`
// Profile link, opened when users click on the author's name below the title. Can be any link, not
// necessarily to a Telegram profile or channel.
AuthorURL string `json:"author_url,omitempty"`
// Content of the page.
Content []Node `json:"content"`
// If true, a content field will be returned in the Page object.
ReturnContent bool `json:"return_content,omitempty"`
}
// CreatePage create a new Telegraph page. On success, returns a Page object. // CreatePage create a new Telegraph page. On success, returns a Page object.
func (a *Account) CreatePage(page Page, returnContent bool) (*Page, error) { func (a *Account) CreatePage(page Page, returnContent bool) (*Page, error) {
src, err := parser.Marshal(page.Content) data, err := makeRequest("createPage", createPage{
AccessToken: a.AccessToken,
Title: page.Title,
AuthorName: page.AuthorName,
AuthorURL: page.AuthorURL,
Content: page.Content,
ReturnContent: returnContent,
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
args := http.AcquireArgs() result := new(Page)
defer http.ReleaseArgs(args) if err = parser.Unmarshal(data, &result); err != nil {
args.Add("access_token", a.AccessToken) // required
args.Add("title", page.Title) // required
args.Add("author_name", page.AuthorName)
args.Add("author_url", page.AuthorURL)
args.AddBytesV("content", src)
args.Add("return_content", strconv.FormatBool(returnContent))
data, err := makeRequest("createPage", args)
if err != nil {
return nil, err return nil, err
} }
var result Page return result, nil
err = parser.Unmarshal(data, &result)
return &result, err
} }

17
doc.go
View File

@ -1,15 +1,14 @@
/* /*
Package telegraph has functions and types used for interacting with the Telegraph API. Package telegraph has functions and types used for interacting with the Telegraph API.
Telegra.ph is a minimalist publishing tool that allows you to create richly formatted posts and push Telegra.ph is a minimalist publishing tool that allows you to create richly formatted posts and push them to the Web
them to the Web in just a click. Telegraph posts also get beautiful Instant View pages on Telegram. in just a click. Telegraph posts also get beautiful Instant View pages on Telegram.
To maintain the purity of the basic interface, we launched the @Telegraph bot for those who require To maintain the purity of the basic interface, we launched the @Telegraph bot for those who require advanced features.
advanced features. This bot can help you manage your articles across any number of devices and This bot can help you manage your articles across any number of devices and get page view statistics for any Telegraph
get page view statistics for any Telegraph page. page.
Anyone can enjoy the simplicity of Telegraph publishing, not just Telegram users. For this reason, all Anyone can enjoy the simplicity of Telegraph publishing, not just Telegram users. For this reason, all developers are
developers are welcome to use this Telegraph API to create bots like @Telegraph for any other welcome to use this Telegraph API to create bots like @Telegraph for any other platform, or even standalone interfaces.
platform, or even standalone interfaces.
*/ */
package telegraph package telegraph // import "gitlab.com/toby3d/telegraph"

View File

@ -1,26 +1,37 @@
package telegraph package telegraph
import ( type editAccountInfo struct {
http "github.com/valyala/fasthttp" // Access token of the Telegraph account.
) AccessToken string `json:"access_token"`
// EditAccountInfo update information about a Telegraph account. Pass only the // New account name.
// parameters that you want to edit. On success, returns an Account object with ShortName string `json:"short_name,omitempty"`
// the default fields.
// New default author name used when creating new articles.
AuthorName string `json:"author_name,omitempty"`
// New default profile link, opened when users click on the author's name below the title. Can be any link,
// not necessarily to a Telegram profile or channel.
AuthorURL string `json:"author_url,omitempty"`
}
// 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) (*Account, error) { func (a *Account) EditAccountInfo(update Account) (*Account, error) {
args := http.AcquireArgs() data, err := makeRequest("editAccountInfo", editAccountInfo{
defer http.ReleaseArgs(args) AccessToken: a.AccessToken,
args.Add("access_token", a.AccessToken) // required ShortName: update.ShortName,
args.Add("short_name", update.ShortName) AuthorName: update.AuthorName,
args.Add("author_name", update.AuthorName) AuthorURL: update.AuthorURL,
args.Add("author_url", update.AuthorURL) })
data, err := makeRequest("editAccountInfo", args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var result Account result := new(Account)
err = parser.Unmarshal(data, &result) if err = parser.Unmarshal(data, result); err != nil {
return &result, err return nil, err
}
return result, nil
} }

View File

@ -2,34 +2,51 @@ package telegraph
import ( import (
"path" "path"
"strconv"
http "github.com/valyala/fasthttp"
) )
type editPage struct {
// Access token of the Telegraph account.
AccessToken string `json:"access_token"`
// Path to the page.
Path string `json:"path"`
// Page title.
Title string `json:"title"`
// Content of the page.
Content []Node `json:"content"`
// Author name, displayed below the article's title.
AuthorName string `json:"author_name,omitempty"`
// Profile link, opened when users click on the author's name below the title. Can be any link, not
// necessarily to a Telegram profile or channel.
AuthorURL string `json:"author_url,omitempty"`
// If true, a content field will be returned in the Page object.
ReturnContent bool `json:"return_content,omitempty"`
}
// EditPage edit an existing Telegraph page. On success, returns a Page object. // EditPage edit an existing Telegraph page. On success, returns a Page object.
func (a *Account) EditPage(update Page, returnContent bool) (*Page, error) { func (a *Account) EditPage(update Page, returnContent bool) (*Page, error) {
src, err := parser.Marshal(update.Content) data, err := makeRequest(path.Join("editPage", update.Path), editPage{
AccessToken: a.AccessToken,
Path: update.Path,
Title: update.Title,
Content: update.Content,
AuthorName: update.AuthorName,
AuthorURL: update.AuthorURL,
ReturnContent: returnContent,
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
args := http.AcquireArgs() result := new(Page)
defer http.ReleaseArgs(args) if err = parser.Unmarshal(data, result); err != nil {
args.Add("access_token", a.AccessToken) // required
args.Add("path", update.Path) // required
args.Add("title", update.Title) // required
args.AddBytesV("content", src) // required
args.Add("author_name", update.AuthorName)
args.Add("author_url", update.AuthorURL)
args.Add("return_content", strconv.FormatBool(returnContent))
data, err := makeRequest(path.Join("editPage", update.Path), args)
if err != nil {
return nil, err return nil, err
} }
var result Page return result, nil
err = parser.Unmarshal(data, &result)
return &result, err
} }

View File

@ -2,6 +2,7 @@ package telegraph_test
import ( import (
"log" "log"
"time"
"gitlab.com/toby3d/telegraph" "gitlab.com/toby3d/telegraph"
) )
@ -160,6 +161,7 @@ func ExampleAccount_GetPageList() {
errCheck(err) errCheck(err)
log.Println("Getted", list.TotalCount, "pages") log.Println("Getted", list.TotalCount, "pages")
for i := range list.Pages { for i := range list.Pages {
p := list.Pages[i] p := list.Pages[i]
log.Printf("%s: %s\n~ %s\n\n", p.Title, p.URL, p.Description) log.Printf("%s: %s\n~ %s\n\n", p.Title, p.URL, p.Description)
@ -168,7 +170,8 @@ func ExampleAccount_GetPageList() {
func ExampleGetViews() { func ExampleGetViews() {
pagePath := "Sample-Page-12-15" pagePath := "Sample-Page-12-15"
views, err := telegraph.GetViews(pagePath, 2016, 12) dateTime := time.Date(2016, time.December, 0, 0, 0, 0, 0, time.UTC)
views, err := telegraph.GetViews(pagePath, dateTime)
errCheck(err) errCheck(err)
log.Println(pagePath, "has been viewed", views.Views, "times") log.Println(pagePath, "has been viewed", views.Views, "times")

View File

@ -1,26 +1,27 @@
package telegraph package telegraph
import ( type getAccountInfo struct {
"strings" // Access token of the Telegraph account.
AccessToken string `json:"access_token"`
http "github.com/valyala/fasthttp" // List of account fields to return.
) Fields []string `json:"fields,omitempty"`
}
// GetAccountInfo get information about a Telegraph account. Returns an Account object on success. // GetAccountInfo get information about a Telegraph account. Returns an Account object on success.
func (a *Account) GetAccountInfo(fields ...string) (*Account, error) { func (a *Account) GetAccountInfo(fields ...string) (*Account, error) {
args := http.AcquireArgs() data, err := makeRequest("getAccountInfo", getAccountInfo{
defer http.ReleaseArgs(args) AccessToken: a.AccessToken,
args.Add("access_token", a.AccessToken) // required Fields: fields,
if len(fields) > 0 { })
args.Add("fields", `["`+strings.Join(fields, `","`)+`"]`)
}
data, err := makeRequest("getAccountInfo", args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var result Account result := new(Account)
err = parser.Unmarshal(data, &result) if err = parser.Unmarshal(data, result); err != nil {
return &result, err return nil, err
}
return result, nil
} }

View File

@ -2,24 +2,30 @@ package telegraph
import ( import (
gopath "path" gopath "path"
"strconv"
http "github.com/valyala/fasthttp"
) )
type getPage struct {
// Path to the Telegraph page (in the format Title-12-31, i.e. everything that comes after http://telegra.ph/).
Path string `json:"path"`
// If true, content field will be returned in Page object.
ReturnContent bool `json:"return_content,omitempty"`
}
// GetPage get a Telegraph page. Returns a Page object on success. // GetPage get a Telegraph page. Returns a Page object on success.
func GetPage(path string, returnContent bool) (*Page, error) { func GetPage(path string, returnContent bool) (*Page, error) {
args := http.AcquireArgs() data, err := makeRequest(gopath.Join("getPage", path), getPage{
defer http.ReleaseArgs(args) Path: path,
args.Add("path", path) // required ReturnContent: returnContent,
args.Add("return_content", strconv.FormatBool(returnContent)) })
data, err := makeRequest(gopath.Join("getPage", path), args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var result Page result := new(Page)
err = parser.Unmarshal(data, &result) if err = parser.Unmarshal(data, result); err != nil {
return &result, err return nil, err
}
return result, nil
} }

View File

@ -1,30 +1,32 @@
package telegraph package telegraph
import ( type getPageList struct {
"strconv" // Access token of the Telegraph account.
AccessToken string `json:"access_token"`
http "github.com/valyala/fasthttp" // Sequential number of the first page to be returned.
) Offset int `json:"offset,omitempty"`
// GetPageList get a list of pages belonging to a Telegraph account. Returns a PageList object, sorted // Limits the number of pages to be retrieved.
// by most recently created pages first. Limit int `json:"limit,omitempty"`
}
// 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) (*PageList, error) { func (a *Account) GetPageList(offset, limit int) (*PageList, error) {
args := http.AcquireArgs() data, err := makeRequest("getPageList", getPageList{
defer http.ReleaseArgs(args) AccessToken: a.AccessToken,
args.Add("access_token", a.AccessToken) // required Offset: offset,
if offset > 0 { Limit: limit,
args.Add("offset", strconv.Itoa(offset)) })
}
if limit > 0 {
args.Add("limit", strconv.Itoa(limit))
}
data, err := makeRequest("getPageList", args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var result PageList result := new(PageList)
err = parser.Unmarshal(data, &result) if err = parser.Unmarshal(data, result); err != nil {
return &result, err return nil, err
}
return result, nil
} }

View File

@ -2,36 +2,49 @@ package telegraph
import ( import (
gopath "path" gopath "path"
"strconv" "time"
http "github.com/valyala/fasthttp"
) )
// GetViews get the number of views for a Telegraph article. By default, the total number of page type getViews struct {
// views will be returned. Returns a PageViews object on success. // Path to the Telegraph page (in the format Title-12-31, where 12 is the month and 31 the day the article was
func GetViews(path string, date ...int) (*PageViews, error) { // first published).
args := http.AcquireArgs() Path string `json:"path"`
defer http.ReleaseArgs(args)
args.Add("path", path) // required // Required if month is passed. If passed, the number of page views for the requested year will be returned.
if len(date) > 0 { Year int `json:"year,omitempty"`
args.Add("year", strconv.Itoa(date[0]))
} // Required if day is passed. If passed, the number of page views for the requested month will be returned.
if len(date) > 1 { Month int `json:"month,omitempty"`
args.Add("month", strconv.Itoa(date[1]))
} // Required if hour is passed. If passed, the number of page views for the requested day will be returned.
if len(date) > 2 { Day int `json:"day,omitempty"`
args.Add("day", strconv.Itoa(date[2]))
} // If passed, the number of page views for the requested hour will be returned.
if len(date) > 3 { Hour int `json:"hour,omitempty"`
args.Add("hour", strconv.Itoa(date[3])) }
// 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) (*PageViews, error) {
p := new(getViews)
p.Path = path
if !date.IsZero() {
p.Year = date.Year()
p.Month = int(date.Month())
p.Day = date.Day()
p.Hour = date.Hour()
} }
data, err := makeRequest(gopath.Join("getViews", path), args) data, err := makeRequest(gopath.Join("getViews", path), p)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var result PageViews result := new(PageViews)
err = parser.Unmarshal(data, &result) if err = parser.Unmarshal(data, &result); err != nil {
return &result, err return nil, err
}
return result, nil
} }

View File

@ -2,6 +2,7 @@ package telegraph
import ( import (
"testing" "testing"
"time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -9,32 +10,41 @@ import (
func TestGetViews(t *testing.T) { func TestGetViews(t *testing.T) {
t.Run("invalid", func(t *testing.T) { t.Run("invalid", func(t *testing.T) {
t.Run("path", func(t *testing.T) { t.Run("path", func(t *testing.T) {
_, err := GetViews("wtf") _, err := GetViews("wtf", time.Time{})
assert.Error(t, err) assert.Error(t, err)
}) })
t.Run("year", func(t *testing.T) { t.Run("year", func(t *testing.T) {
_, err := GetViews("Sample-Page-12-15", 1980) dt := time.Date(1980, 0, 0, 0, 0, 0, 0, time.UTC)
_, err := GetViews("Sample-Page-12-15", dt)
assert.Error(t, err) assert.Error(t, err)
}) })
t.Run("month", func(t *testing.T) { t.Run("month", func(t *testing.T) {
_, err := GetViews("Sample-Page-12-15", 2000, 22) dt := time.Date(2000, 22, 0, 0, 0, 0, 0, time.UTC)
assert.Error(t, err) result, err := GetViews("Sample-Page-12-15", dt)
assert.NoError(t, err)
assert.NotNil(t, result)
}) })
t.Run("day", func(t *testing.T) { t.Run("day", func(t *testing.T) {
_, err := GetViews("Sample-Page-12-15", 2000, 2, 42) dt := time.Date(2000, time.February, 42, 0, 0, 0, 0, time.UTC)
assert.Error(t, err) result, err := GetViews("Sample-Page-12-15", dt)
assert.NoError(t, err)
assert.NotNil(t, result)
}) })
t.Run("hour", func(t *testing.T) { t.Run("hour", func(t *testing.T) {
_, err := GetViews("Sample-Page-12-15", 2000, 2, 12, 65) dt := time.Date(2000, time.February, 12, 65, 0, 0, 0, time.UTC)
assert.Error(t, err) result, err := GetViews("Sample-Page-12-15", dt)
assert.NoError(t, err)
assert.NotNil(t, result)
}) })
}) })
t.Run("valid", func(t *testing.T) { t.Run("valid", func(t *testing.T) {
stats, err := GetViews("Sample-Page-12-15") dt := time.Date(2016, time.December, 31, 0, 0, 0, 0, time.UTC)
stats, err := GetViews("Sample-Page-12-15", dt)
assert.NoError(t, err) assert.NoError(t, err)
if !assert.NotNil(t, stats) { if !assert.NotNil(t, stats) {
t.FailNow() t.FailNow()
} }
assert.NotZero(t, stats.Views) assert.NotZero(t, stats.Views)
}) })
} }

View File

@ -1,23 +1,25 @@
package telegraph package telegraph
import ( type revokeAccessToken struct {
http "github.com/valyala/fasthttp" // Access token of the Telegraph account.
) AccessToken string `json:"access_token"`
}
// RevokeAccessToken revoke access_token and generate a new one, for example, if the user would // 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 // 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. // success, returns an Account object with new access_token and auth_url fields.
func (a *Account) RevokeAccessToken() (*Account, error) { func (a *Account) RevokeAccessToken() (*Account, error) {
args := http.AcquireArgs() resp, err := makeRequest("revokeAccessToken", revokeAccessToken{
defer http.ReleaseArgs(args) AccessToken: a.AccessToken,
args.Add("access_token", a.AccessToken) })
resp, err := makeRequest("revokeAccessToken", args)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var account Account account := new(Account)
err = parser.Unmarshal(resp, &account) if err = parser.Unmarshal(resp, &account); err != nil {
return &account, err return nil, err
}
return account, nil
} }

View File

@ -2,49 +2,53 @@
package telegraph package telegraph
import ( import (
gojson "encoding/json" "encoding/json"
"errors" "errors"
json "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
http "github.com/valyala/fasthttp" http "github.com/valyala/fasthttp"
) )
// Response contains a JSON object, which always has a Boolean field ok. If ok // Response contains a JSON object, which always has a Boolean field ok. If ok equals true, the request was
// equals true, the request was successful, and the result of the query can be // successful, and the result of the query can be found in the result field. In case of an unsuccessful request, ok
// found in the result field. In case of an unsuccessful request, ok equals // equals false, and the error is explained in the error field (e.g. SHORT_NAME_REQUIRED).
// false, and the error is explained in the error field (e.g.
// SHORT_NAME_REQUIRED).
type Response struct { type Response struct {
Ok bool `json:"ok"` Ok bool `json:"ok"`
Error string `json:"error"` Error string `json:"error,omitempty"`
Result gojson.RawMessage `json:"result,omitempty"` Result json.RawMessage `json:"result,omitempty"`
} }
var parser = json.ConfigFastest //nolint:gochecknoglobals var parser = jsoniter.ConfigFastest //nolint:gochecknoglobals
func makeRequest(path string, payload interface{}) ([]byte, error) {
src, err := parser.Marshal(payload)
if err != nil {
return nil, err
}
func makeRequest(path string, args *http.Args) ([]byte, error) {
u := http.AcquireURI() u := http.AcquireURI()
defer http.ReleaseURI(u) defer http.ReleaseURI(u)
u.SetScheme("https") u.SetScheme("https")
u.SetHost("api.telegra.ph") u.SetHost("api.telegra.ph")
u.SetPath(path) u.SetPath(path)
args.CopyTo(u.QueryArgs())
req := http.AcquireRequest() req := http.AcquireRequest()
defer http.ReleaseRequest(req) defer http.ReleaseRequest(req)
req.Header.SetMethod(http.MethodGet)
req.SetRequestURIBytes(u.FullURI()) req.SetRequestURIBytes(u.FullURI())
req.Header.SetMethod(http.MethodPost)
req.Header.SetUserAgent("toby3d/telegraph") req.Header.SetUserAgent("toby3d/telegraph")
req.Header.SetContentType("application/json; charset=utf-8") req.Header.SetContentType("application/json")
req.SetBody(src)
resp := http.AcquireResponse() resp := http.AcquireResponse()
defer http.ReleaseResponse(resp) defer http.ReleaseResponse(resp)
if err := http.Do(req, resp); err != nil { if err := http.Do(req, resp); err != nil {
return nil, err return nil, err
} }
var r Response r := new(Response)
if err := parser.Unmarshal(resp.Body(), &r); err != nil { if err := parser.Unmarshal(resp.Body(), r); err != nil {
return nil, err return nil, err
} }

View File

@ -3,43 +3,38 @@ package telegraph
import "errors" import "errors"
// All types used in the Telegraph API responses are represented as JSON-objects. // All types used in the Telegraph API responses are represented as JSON-objects. Optional fields may be not returned
// Optional fields may be not returned when irrelevant. // when irrelevant.
type ( type (
// Account represents a Telegraph account. // Account represents a Telegraph account.
Account struct { Account struct {
// Only returned by the createAccount and revokeAccessToken // Only returned by the createAccount and revokeAccessToken method. Access token of the Telegraph
// method. Access token of the Telegraph account. // account.
AccessToken string `json:"access_token"` // optional AccessToken string `json:"access_token"`
// URL to authorize a browser on telegra.ph and connect it to a // URL to authorize a browser on telegra.ph and connect it to a Telegraph account. This URL is valid
// Telegraph account. This URL is valid for only one use and for // for only one use and for 5 minutes only.
// 5 minutes only. AuthURL string `json:"auth_url,omitempty"`
AuthURL string `json:"auth_url,omitempty"` // optional
// Account name, helps users with several accounts remember which // Account name, helps users with several accounts remember which they are currently using. Displayed
// they are currently using. Displayed to the user above the // to the user above the "Edit/Publish" button on Telegra.ph, other users don't see this name.
// "Edit/Publish" button on Telegra.ph, other users don't see
// this name.
ShortName string `json:"short_name"` ShortName string `json:"short_name"`
// Default author name used when creating new articles. // Default author name used when creating new articles.
AuthorName string `json:"author_name"` AuthorName string `json:"author_name"`
// Profile link, opened when users click on the author's name // Profile link, opened when users click on the author's name below the title. Can be any link, not
// below the title. Can be any link, not necessarily to a // necessarily to a Telegram profile or channel.
// Telegram profile or channel.
AuthorURL string `json:"author_url"` AuthorURL string `json:"author_url"`
// Number of pages belonging to the Telegraph account. // Number of pages belonging to the Telegraph account.
PageCount int `json:"page_count,omitempty"` // optional PageCount int `json:"page_count,omitempty"`
} }
// PageList represents a list of Telegraph articles belonging to an // PageList represents a list of Telegraph articles belonging to an account. Most recently created articles
// account. Most recently created articles first. // first.
PageList struct { PageList struct {
// Total number of pages belonging to the target Telegraph // Total number of pages belonging to the target Telegraph account.
// account.
TotalCount int `json:"total_count"` TotalCount int `json:"total_count"`
// Requested pages of the target Telegraph account. // Requested pages of the target Telegraph account.
@ -61,25 +56,23 @@ type (
Description string `json:"description"` Description string `json:"description"`
// Name of the author, displayed below the title. // Name of the author, displayed below the title.
AuthorName string `json:"author_name,omitempty"` // optional AuthorName string `json:"author_name,omitempty"`
// Profile link, opened when users click on the author's name // Profile link, opened when users click on the author's name below the title. Can be any link, not
// below the title. Can be any link, not necessarily to a // necessarily to a Telegram profile or channel.
// Telegram profile or channel. AuthorURL string `json:"author_url,omitempty"`
AuthorURL string `json:"author_url,omitempty"` // optional
// Image URL of the page. // Image URL of the page.
ImageURL string `json:"image_url,omitempty"` // optional ImageURL string `json:"image_url,omitempty"`
// Content of the page. // Content of the page.
Content []Node `json:"content,omitempty"` // optional Content []Node `json:"content,omitempty"`
// Number of page views for the page. // Number of page views for the page.
Views int `json:"views"` Views int `json:"views"`
// Only returned if access_token passed. True, if the target // Only returned if access_token passed. True, if the target Telegraph account can edit the page.
// Telegraph account can edit the page. CanEdit bool `json:"can_edit,omitempty"`
CanEdit bool `json:"can_edit,omitempty"` // optional
} }
// PageViews represents the number of page views for a Telegraph article. // PageViews represents the number of page views for a Telegraph article.
@ -88,50 +81,45 @@ type (
Views int `json:"views"` Views int `json:"views"`
} }
// Node is abstract object represents a DOM Node. It can be a String // Node is abstract object represents a DOM Node. It can be a String which represents a DOM text node or a
// which represents a DOM text node or a NodeElement object. // NodeElement object.
Node interface{} Node interface{}
// NodeElement represents a DOM element node. // NodeElement represents a DOM element node.
NodeElement struct { NodeElement struct {
// Name of the DOM element. // Name of the DOM element. Available tags: a, aside, b, blockquote, br, code, em, figcaption, figure,
// Available tags: a, aside, b, blockquote, br, code, em, // h3, h4, hr, i, iframe, img, li, ol, p, pre, s, strong, u, ul, video.
// figcaption, figure, h3, h4, hr, i, iframe, img, li, ol, p,
// pre, s, strong, u, ul, video.
Tag string `json:"tag"` Tag string `json:"tag"`
// Attributes of the DOM element. Key of object represents name // Attributes of the DOM element. Key of object represents name of attribute, value represents value
// of attribute, value represents value of attribute. // of attribute. Available attributes: href, src.
// Available attributes: href, src. Attrs map[string]string `json:"attrs,omitempty"`
Attrs map[string]string `json:"attrs,omitempty"` // optional
// List of child nodes for the DOM element. // List of child nodes for the DOM element.
Children []Node `json:"children,omitempty"` // optional Children []Node `json:"children,omitempty"`
} }
) )
const ( const (
// FieldShortName used as GetAccountInfo argument for getting account name. // FieldShortName used as GetAccountInfo argument for getting account name.
FieldShortName = "short_name" FieldShortName string = "short_name"
// FieldAuthorName used as GetAccountInfo argument for getting author name. // FieldAuthorName used as GetAccountInfo argument for getting author name.
FieldAuthorName = "author_name" FieldAuthorName string = "author_name"
// FieldAuthorURL used as GetAccountInfo argument for getting profile link. // FieldAuthorURL used as GetAccountInfo argument for getting profile link.
FieldAuthorURL = "author_url" FieldAuthorURL string = "author_url"
// FieldAuthURL used as GetAccountInfo argument for getting URL to authorize // FieldAuthURL used as GetAccountInfo argument for getting URL to authorize a browser on telegra.ph.
// a browser on telegra.ph. FieldAuthURL string = "auth_url"
FieldAuthURL = "auth_url"
// FieldPageCount used as GetAccountInfo argument for getting number of pages // FieldPageCount used as GetAccountInfo argument for getting number of pages belonging to the Telegraph
// belonging to the Telegraph account. // account.
FieldPageCount = "page_count" FieldPageCount string = "page_count"
) )
var ( var (
// ErrInvalidDataType is returned when ContentFormat function are passed // ErrInvalidDataType is returned when ContentFormat function are passed a data argument of invalid type.
// a data argument of invalid type.
ErrInvalidDataType = errors.New("invalid data type") ErrInvalidDataType = errors.New("invalid data type")
// ErrNoInputData is returned when any method get nil argument. // ErrNoInputData is returned when any method get nil argument.