├── .gitignore
├── Gopkg.lock
├── Gopkg.toml
├── LICENSE
├── README.md
├── archive
└── main.go
├── cmd
└── grain
│ ├── .gitignore
│ ├── lookup.json
│ └── main.go
├── facebook
├── api.go
└── facebook.go
├── gen
├── facebook
│ ├── archive.pb.go
│ ├── download
│ │ ├── about_you.pb.go
│ │ ├── ads.pb.go
│ │ ├── apps.pb.go
│ │ ├── comments.pb.go
│ │ ├── events.pb.go
│ │ ├── following_and_followers.pb.go
│ │ ├── friends.pb.go
│ │ └── groups.pb.go
│ ├── node.pb.go
│ ├── photo.pb.go
│ └── user.pb.go
└── twitter
│ ├── archive.pb.go
│ ├── dm.pb.go
│ ├── entity.pb.go
│ ├── list.pb.go
│ ├── tweet.pb.go
│ └── user.pb.go
├── proto
├── facebook
│ ├── archive.proto
│ ├── download
│ │ ├── about_you.proto
│ │ ├── ads.proto
│ │ ├── apps.proto
│ │ ├── comments.proto
│ │ ├── events.proto
│ │ ├── following_and_followers.proto
│ │ ├── friends.proto
│ │ └── groups.proto
│ ├── node.proto
│ ├── photo.proto
│ └── user.proto
├── prototool.yaml
└── twitter
│ ├── archive.proto
│ ├── dm.proto
│ ├── entity.proto
│ ├── list.proto
│ ├── tweet.proto
│ └── user.proto
├── twitter
├── api.go
├── csv.go
├── errors.go
└── twitter.go
└── vendor
├── github.com
├── ChimeraCoder
│ └── tokenbucket
│ │ ├── .gitignore
│ │ ├── COPYING
│ │ ├── LICENSE
│ │ ├── README
│ │ ├── README.md
│ │ └── tokenbucket.go
├── garyburd
│ └── go-oauth
│ │ └── oauth
│ │ ├── oauth.go
│ │ ├── oauth16.go
│ │ └── oauth17.go
├── golang
│ └── protobuf
│ │ ├── AUTHORS
│ │ ├── CONTRIBUTORS
│ │ ├── LICENSE
│ │ ├── jsonpb
│ │ └── jsonpb.go
│ │ ├── proto
│ │ ├── clone.go
│ │ ├── decode.go
│ │ ├── discard.go
│ │ ├── encode.go
│ │ ├── equal.go
│ │ ├── extensions.go
│ │ ├── lib.go
│ │ ├── message_set.go
│ │ ├── pointer_reflect.go
│ │ ├── pointer_unsafe.go
│ │ ├── properties.go
│ │ ├── table_marshal.go
│ │ ├── table_merge.go
│ │ ├── table_unmarshal.go
│ │ ├── text.go
│ │ └── text_parser.go
│ │ └── ptypes
│ │ └── struct
│ │ ├── struct.pb.go
│ │ └── struct.proto
├── google
│ └── btree
│ │ ├── .travis.yml
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── btree.go
│ │ └── btree_mem.go
├── gregjones
│ └── httpcache
│ │ ├── .travis.yml
│ │ ├── LICENSE.txt
│ │ ├── README.md
│ │ ├── diskcache
│ │ └── diskcache.go
│ │ └── httpcache.go
├── pelletier
│ └── go-toml
│ │ ├── .gitignore
│ │ ├── .travis.yml
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── benchmark.json
│ │ ├── benchmark.sh
│ │ ├── benchmark.toml
│ │ ├── benchmark.yml
│ │ ├── doc.go
│ │ ├── example-crlf.toml
│ │ ├── example.toml
│ │ ├── fuzz.go
│ │ ├── fuzz.sh
│ │ ├── keysparsing.go
│ │ ├── lexer.go
│ │ ├── marshal.go
│ │ ├── marshal_test.toml
│ │ ├── parser.go
│ │ ├── position.go
│ │ ├── test.sh
│ │ ├── token.go
│ │ ├── toml.go
│ │ ├── tomltree_create.go
│ │ └── tomltree_write.go
├── petar
│ └── GoLLRB
│ │ ├── AUTHORS
│ │ ├── LICENSE
│ │ └── llrb
│ │ ├── avgvar.go
│ │ ├── iterator.go
│ │ ├── llrb-stats.go
│ │ ├── llrb.go
│ │ └── util.go
└── peterbourgon
│ └── diskv
│ ├── LICENSE
│ ├── README.md
│ ├── compression.go
│ ├── diskv.go
│ └── index.go
└── golang.org
└── x
├── net
├── AUTHORS
├── CONTRIBUTORS
├── LICENSE
├── PATENTS
└── context
│ ├── context.go
│ ├── go17.go
│ ├── go19.go
│ ├── pre_go17.go
│ └── pre_go19.go
└── sync
├── AUTHORS
├── CONTRIBUTORS
├── LICENSE
├── PATENTS
└── errgroup
└── errgroup.go
/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleconroy/grain/5b2671dfb5f42dcccf7376cc63f7ef6d5b92cd4b/.gitignore
--------------------------------------------------------------------------------
/Gopkg.lock:
--------------------------------------------------------------------------------
1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
2 |
3 |
4 | [[projects]]
5 | branch = "master"
6 | name = "github.com/ChimeraCoder/tokenbucket"
7 | packages = ["."]
8 | revision = "c5a927568de7aad8a58127d80bcd36ca4e71e454"
9 |
10 | [[projects]]
11 | branch = "master"
12 | name = "github.com/garyburd/go-oauth"
13 | packages = ["oauth"]
14 | revision = "bca2e7f09a178fd36b034107a00e2323bca6a82e"
15 |
16 | [[projects]]
17 | name = "github.com/golang/protobuf"
18 | packages = [
19 | "jsonpb",
20 | "proto",
21 | "ptypes/struct"
22 | ]
23 | revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
24 | version = "v1.1.0"
25 |
26 | [[projects]]
27 | branch = "master"
28 | name = "github.com/google/btree"
29 | packages = ["."]
30 | revision = "e89373fe6b4a7413d7acd6da1725b83ef713e6e4"
31 |
32 | [[projects]]
33 | branch = "master"
34 | name = "github.com/gregjones/httpcache"
35 | packages = [
36 | ".",
37 | "diskcache"
38 | ]
39 | revision = "9cad4c3443a7200dd6400aef47183728de563a38"
40 |
41 | [[projects]]
42 | name = "github.com/pelletier/go-toml"
43 | packages = ["."]
44 | revision = "acdc4509485b587f5e675510c4f2c63e90ff68a8"
45 | version = "v1.1.0"
46 |
47 | [[projects]]
48 | branch = "master"
49 | name = "github.com/petar/GoLLRB"
50 | packages = ["llrb"]
51 | revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4"
52 |
53 | [[projects]]
54 | name = "github.com/peterbourgon/diskv"
55 | packages = ["."]
56 | revision = "5f041e8faa004a95c88a202771f4cc3e991971e6"
57 | version = "v2.0.1"
58 |
59 | [[projects]]
60 | branch = "master"
61 | name = "golang.org/x/net"
62 | packages = ["context"]
63 | revision = "1e491301e022f8f977054da4c2d852decd59571f"
64 |
65 | [[projects]]
66 | branch = "master"
67 | name = "golang.org/x/sync"
68 | packages = ["errgroup"]
69 | revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
70 |
71 | [solve-meta]
72 | analyzer-name = "dep"
73 | analyzer-version = 1
74 | inputs-digest = "1d178e106be67bc1adfbec88d4b2d4fd7294d3344064be1687c9dbe17304e40c"
75 | solver-name = "gps-cdcl"
76 | solver-version = 1
77 |
--------------------------------------------------------------------------------
/Gopkg.toml:
--------------------------------------------------------------------------------
1 | # Gopkg.toml example
2 | #
3 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
4 | # for detailed Gopkg.toml documentation.
5 | #
6 | # required = ["github.com/user/thing/cmd/thing"]
7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
8 | #
9 | # [[constraint]]
10 | # name = "github.com/user/project"
11 | # version = "1.0.0"
12 | #
13 | # [[constraint]]
14 | # name = "github.com/user/project2"
15 | # branch = "dev"
16 | # source = "github.com/myfork/project2"
17 | #
18 | # [[override]]
19 | # name = "github.com/x/y"
20 | # version = "2.4.0"
21 | #
22 | # [prune]
23 | # non-go = false
24 | # go-tests = true
25 | # unused-packages = true
26 |
27 |
28 | [prune]
29 | go-tests = true
30 | unused-packages = true
31 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Kyle Conroy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Grain
2 |
3 | The Entire History of You
4 |
5 | ## Usage
6 |
7 | Grain looks for API access keys and secrets in `config.toml`.
8 |
9 | ## Twitter
10 |
11 | Grain will download a full archive of your Twitter account, unlike the official
12 | Twitter Archive. Your Grain archive includes the following records:
13 |
14 | - Direct messages
15 | - Favorites
16 | - Followers
17 | - Friends
18 | - Lists
19 | - Tweets
20 |
21 | The archive also includes all media associated with the above records.
22 |
23 | For privacy and performance reasons, you'll need to obtain your own API
24 | credentials.
25 |
26 | 1. Log onto [Twitter](https://twitter.com) with the account you'd like to archive
27 | 2. Request your archive from your [Settings page](https://twitter.com/settings/account)
28 | 3. Create a new [application](https://apps.twitter.com)
29 | 4. Go to the "Keys and Access Tokens" section for your application
30 | 5. Generate access tokens via "Create my access token"
31 | 6. Fill in `config.toml` with the access and secret tokens
32 |
33 | ```
34 | [twitter]
35 | username = ""
36 | tweet-csv = "path/to/tweets.csv"
37 | consumer-key = ""
38 | consumer-secret = ""
39 | access-token = ""
40 | access-token-secret = ""
41 | ```
42 |
43 | Running `grain` will download records to `archive/twitter` in the current
44 | working directory.
45 |
46 | ### Limitations
47 |
48 | The Twitter API has a set of limitations which makes archiving certain records
49 | difficult.
50 |
51 | - The API only returns the most recent 3,200 tweets from your timeline. You'll
52 | need to download your official Twitter Archive for Grain to successfully
53 | archive all of your tweets.
54 | - Only the last 30 days of direct message activity is available via the API.
55 | - Rate limits are very aggressive which means certain records take forever to
56 | archive.
57 |
58 | ## Facebook
59 |
60 | Coming soon…
61 |
--------------------------------------------------------------------------------
/archive/main.go:
--------------------------------------------------------------------------------
1 | package archive
2 |
3 | import (
4 | "context"
5 | "io/ioutil"
6 | "net/http"
7 | "net/url"
8 | "os"
9 | "path"
10 | "path/filepath"
11 | )
12 |
13 | func ArchiveURL(ctx context.Context, service, folder, uri string) error {
14 | parsed, err := url.Parse(uri)
15 | if err != nil {
16 | return err
17 | }
18 | if parsed.Host == "" {
19 | panic("All URLs must have attached host names: " + uri)
20 | }
21 |
22 | fullpath := path.Join("archive", service, folder, parsed.Host, parsed.Path)
23 |
24 | if _, err := os.Stat(fullpath); err == nil {
25 | // path/to/whatever exists
26 | return nil
27 | }
28 |
29 | if err := os.MkdirAll(filepath.Dir(fullpath), 0755); err != nil {
30 | return err
31 | }
32 |
33 | resp, err := http.Get(parsed.String())
34 | if err != nil {
35 | return err
36 | }
37 |
38 | // For now, ignore everything else that isn't 200
39 | if resp.StatusCode != http.StatusOK {
40 | return nil
41 | }
42 |
43 | defer resp.Body.Close()
44 | blob, err := ioutil.ReadAll(resp.Body)
45 | if err != nil {
46 | return err
47 | }
48 |
49 | return ioutil.WriteFile(fullpath, blob, 0644)
50 | }
51 |
--------------------------------------------------------------------------------
/cmd/grain/.gitignore:
--------------------------------------------------------------------------------
1 | archive
2 | config.toml
3 | grain
4 | httpcache
5 |
--------------------------------------------------------------------------------
/cmd/grain/lookup.json:
--------------------------------------------------------------------------------
1 | {
2 | "album": {
3 | "fields": [
4 | "id",
5 | "backdated_time",
6 | "backdated_time_granularity",
7 | "can_backdate",
8 | "can_upload",
9 | "count",
10 | "cover_photo",
11 | "created_time",
12 | "description",
13 | "edit_link",
14 | "event",
15 | "from",
16 | "is_user_facing",
17 | "link",
18 | "location",
19 | "modified_major",
20 | "name",
21 | "photo_count",
22 | "place",
23 | "privacy",
24 | "type",
25 | "updated_time",
26 | "video_count"
27 | ],
28 | "connections": [
29 | "reactions",
30 | "sharedposts",
31 | "comments",
32 | "likes",
33 | "photos"
34 | ]
35 | },
36 | "photo": {
37 | "fields": [
38 | "id",
39 | "album",
40 | "backdated_time",
41 | "backdated_time_granularity",
42 | "can_backdate",
43 | "can_delete",
44 | "can_tag",
45 | "created_time",
46 | "event",
47 | "from",
48 | "height",
49 | "icon",
50 | "images",
51 | "link",
52 | "name",
53 | "name_tags",
54 | "page_story_id",
55 | "picture",
56 | "place",
57 | "target",
58 | "updated_time",
59 | "webp_images",
60 | "width"
61 | ],
62 | "connections": [
63 | "sponsor_tags",
64 | "tags",
65 | "comments",
66 | "likes",
67 | "reactions",
68 | "sharedposts"
69 | ]
70 | },
71 | "user": {
72 | "fields": [
73 | "about",
74 | "id",
75 | "address",
76 | "age_range",
77 | "birthday",
78 | "can_review_measurement_request",
79 | "context",
80 | "cover",
81 | "currency",
82 | "devices",
83 | "education",
84 | "email",
85 | "favorite_athletes",
86 | "favorite_teams",
87 | "first_name",
88 | "gender",
89 | "hometown",
90 | "inspirational_people",
91 | "install_type",
92 | "installed",
93 | "interested_in",
94 | "is_famedeeplinkinguser",
95 | "is_shared_login",
96 | "is_verified",
97 | "languages",
98 | "last_name",
99 | "link",
100 | "locale",
101 | "location",
102 | "meeting_for",
103 | "middle_name",
104 | "name",
105 | "name_format",
106 | "payment_pricepoints",
107 | "political",
108 | "public_key",
109 | "quotes",
110 | "relationship_status",
111 | "religion",
112 | "security_settings",
113 | "shared_login_upgrade_required_by",
114 | "short_name",
115 | "significant_other",
116 | "sports",
117 | "test_group",
118 | "third_party_id",
119 | "timezone",
120 | "updated_time",
121 | "verified",
122 | "video_upload_limits",
123 | "viewer_can_send_gift",
124 | "website",
125 | "work"
126 | ],
127 | "connections": [
128 | "television",
129 | "video_broadcasts",
130 | "achievements",
131 | "adaccounts",
132 | "custom_labels",
133 | "friendlists",
134 | "photos",
135 | "posts",
136 | "rich_media_documents",
137 | "session_keys",
138 | "books",
139 | "feed",
140 | "tagged_places",
141 | "insights",
142 | "apprequestformerrecipients",
143 | "request_history",
144 | "adnetworkanalytics",
145 | "albums",
146 | "events",
147 | "groups",
148 | "domains",
149 | "promotable_events",
150 | "accounts",
151 | "favorite_requests",
152 | "ids_for_business",
153 | "videos",
154 | "asset3ds",
155 | "likes",
156 | "movies",
157 | "businesses",
158 | "friends",
159 | "business_users",
160 | "games",
161 | "tagged",
162 | "apprequests",
163 | "permissions",
164 | "family",
165 | "music"
166 | ]
167 | }
168 | }
--------------------------------------------------------------------------------
/cmd/grain/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "os"
7 |
8 | "github.com/kyleconroy/grain/facebook"
9 | "github.com/kyleconroy/grain/twitter"
10 | toml "github.com/pelletier/go-toml"
11 | )
12 |
13 | func run() error {
14 | config, err := toml.LoadFile("config.toml")
15 | if err != nil {
16 | return err
17 | }
18 |
19 | if config.Has("twitter") {
20 | config, ok := config.Get("twitter").(*toml.Tree)
21 | if !ok {
22 | return fmt.Errorf("Config file should contain a [twitter] section")
23 | }
24 | a, err := twitter.NewArchiver(config)
25 | if err != nil {
26 | return err
27 | }
28 | if err := a.Sync(context.TODO()); err != nil {
29 | return err
30 | }
31 | }
32 |
33 | if config.Has("facebook") {
34 | config, ok := config.Get("facebook").(*toml.Tree)
35 | if !ok {
36 | return fmt.Errorf("Config file should contain a [facebook] section")
37 | }
38 |
39 | a := facebook.NewArchiver(config)
40 | if err := a.Sync(context.TODO()); err != nil {
41 | return err
42 | }
43 | }
44 |
45 | return nil
46 | }
47 |
48 | func main() {
49 | if err := run(); err != nil {
50 | fmt.Println(err)
51 | os.Exit(1)
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/facebook/api.go:
--------------------------------------------------------------------------------
1 | package facebook
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "io/ioutil"
7 | "net/http"
8 | "net/http/httputil"
9 | "net/url"
10 | "strings"
11 |
12 | "github.com/golang/protobuf/proto"
13 | "github.com/kyleconroy/grain/gen/facebook"
14 | )
15 |
16 | type Client struct {
17 | HttpClient *http.Client
18 | baseURL string
19 | accessToken string
20 | }
21 |
22 | func NewClient(token string) *Client {
23 | return &Client{
24 | accessToken: token,
25 | HttpClient: http.DefaultClient,
26 | baseURL: "https://graph.facebook.com/v3.0/",
27 | }
28 | }
29 |
30 | type Field struct {
31 | Name string `json:"name"`
32 | Description string `json:"description"`
33 | Type string `json:"type"`
34 | }
35 |
36 | type Metadata struct {
37 | Fields []Field `json:"fields"`
38 | Connections map[string]string `json:"connections"`
39 | Type string `json:"type"`
40 | }
41 |
42 | type Node struct {
43 | Metadata Metadata `json:"metadata"`
44 | ID string `json:"id"`
45 |
46 | Message proto.Message
47 | }
48 |
49 | type Option func(*url.Values)
50 |
51 | func Fields(args ...string) func(form *url.Values) {
52 | return func(form *url.Values) {
53 | form.Set("fields", strings.Join(args, ","))
54 | }
55 | }
56 |
57 | func (c *Client) GetNode(id string, options ...Option) (*Node, error) {
58 | form := url.Values{}
59 | form.Set("access_token", c.accessToken)
60 | form.Set("metadata", "1")
61 | form.Set("method", "GET")
62 | for _, opt := range options {
63 | opt(&form)
64 | }
65 |
66 | req, _ := http.NewRequest("POST", c.baseURL+id, strings.NewReader(form.Encode()))
67 | resp, err := c.HttpClient.Do(req)
68 | if err != nil {
69 | return nil, err
70 | }
71 | if resp.StatusCode != http.StatusOK {
72 | blob, _ := httputil.DumpResponse(resp, true)
73 | fmt.Println(string(blob))
74 | return nil, fmt.Errorf("Unexpected status code: %d", resp.StatusCode)
75 | }
76 | defer resp.Body.Close()
77 | var n Node
78 | blob, err := ioutil.ReadAll(resp.Body)
79 | if err := json.Unmarshal(blob, &n); err != nil {
80 | return nil, err
81 | }
82 |
83 | // fmt.Println(string(blob))
84 | var m proto.Message
85 | switch n.Metadata.Type {
86 | case "album":
87 | m = &facebookpb.Album{}
88 | case "photo":
89 | m = &facebookpb.Photo{}
90 | case "user":
91 | m = &facebookpb.User{}
92 | default:
93 | m = &facebookpb.Node{}
94 | }
95 |
96 | if err := json.Unmarshal(blob, &m); err != nil {
97 | return nil, err
98 | }
99 |
100 | n.Message = m
101 | return &n, nil
102 | }
103 |
104 | type Paging struct {
105 | Previous string `json:"previous"`
106 | Next string `json:"next"`
107 | }
108 |
109 | type Datalist struct {
110 | Data []Node
111 | Paging Paging
112 | }
113 |
114 | func (c *Client) GetEdge(id, connection string, paging *Paging, options ...Option) (*Datalist, error) {
115 | form := url.Values{}
116 | form.Set("access_token", c.accessToken)
117 | form.Set("method", "GET")
118 | form.Set("limit", "2000")
119 | for _, opt := range options {
120 | opt(&form)
121 | }
122 |
123 | u := c.baseURL + id + "/" + connection
124 | if paging != nil && paging.Next != "" {
125 | u = paging.Next
126 | }
127 |
128 | req, _ := http.NewRequest("POST", u, strings.NewReader(form.Encode()))
129 | resp, err := c.HttpClient.Do(req)
130 | if err != nil {
131 | return nil, err
132 | }
133 | if resp.StatusCode != http.StatusOK {
134 | blob, _ := httputil.DumpResponse(resp, true)
135 | fmt.Println(string(blob))
136 | return nil, fmt.Errorf("Unexpected status code: %d", resp.StatusCode)
137 | }
138 | defer resp.Body.Close()
139 | var dl Datalist
140 | dec := json.NewDecoder(resp.Body)
141 | if err := dec.Decode(&dl); err != nil {
142 | return nil, err
143 | }
144 | return &dl, nil
145 | }
146 |
--------------------------------------------------------------------------------
/facebook/facebook.go:
--------------------------------------------------------------------------------
1 | package facebook
2 |
3 | import (
4 | "context"
5 | "encoding/json"
6 | "fmt"
7 | "io/ioutil"
8 | "path/filepath"
9 | "sort"
10 |
11 | "github.com/gregjones/httpcache"
12 | "github.com/gregjones/httpcache/diskcache"
13 | "github.com/kyleconroy/grain/archive"
14 | "github.com/kyleconroy/grain/gen/facebook"
15 | toml "github.com/pelletier/go-toml"
16 | )
17 |
18 | type fieldschema struct {
19 | Fields []string `json:"fields"`
20 | Conns []string `json:"connections"`
21 | }
22 |
23 | type Archiver struct {
24 | accessToken string
25 |
26 | count int
27 | seen map[string]struct{}
28 | api *Client
29 | archive *facebookpb.Archive
30 | metadata map[string]fieldschema
31 | }
32 |
33 | func NewArchiver(c *toml.Tree) *Archiver {
34 | fields := map[string]fieldschema{}
35 | if blob, err := ioutil.ReadFile("lookup.json"); err == nil {
36 | if err := json.Unmarshal(blob, &fields); err != nil {
37 | panic(err)
38 | }
39 | }
40 |
41 | transport := httpcache.NewTransport(diskcache.New("httpcache"))
42 | fapi := NewClient(c.Get("access-token").(string))
43 | fapi.HttpClient = transport.Client()
44 |
45 | return &Archiver{
46 | accessToken: c.Get("access-token").(string),
47 | archive: &facebookpb.Archive{},
48 | metadata: fields,
49 | api: fapi,
50 | seen: map[string]struct{}{},
51 | }
52 | }
53 |
54 | func (a *Archiver) buildMetadata(ctx context.Context, id string) (string, error) {
55 | // Get the metadata
56 | m, err := a.api.GetNode(id)
57 | if err != nil {
58 | return "", err
59 | }
60 |
61 | kind := m.Metadata.Type
62 |
63 | _, known := a.metadata[kind]
64 | if known {
65 | return kind, nil
66 | }
67 |
68 | fields := []string{}
69 | for _, field := range m.Metadata.Fields {
70 | fmt.Println("Checking field: ", field.Name)
71 | _, err := a.api.GetNode(id, Fields(field.Name))
72 | if err == nil {
73 | fields = append(fields, field.Name)
74 | }
75 | }
76 |
77 | conns := []string{}
78 | for edge, _ := range m.Metadata.Connections {
79 | fmt.Println("Checking connection: ", edge)
80 | if _, err := a.api.GetEdge(id, edge, nil); err == nil {
81 | conns = append(conns, edge)
82 | }
83 | }
84 |
85 | schema := fieldschema{
86 | Fields: fields,
87 | Conns: conns,
88 | }
89 |
90 | a.metadata[kind] = schema
91 |
92 | blob, _ := json.MarshalIndent(a.metadata, "", " ")
93 | ioutil.WriteFile("lookup.json", blob, 0644)
94 | return kind, nil
95 | }
96 |
97 | func (a *Archiver) save() error {
98 | {
99 | path := filepath.Join("archive", "facebook", "me.json")
100 | b, err := json.MarshalIndent(facebookpb.Archive{Me: a.archive.Me}, "", " ")
101 | if err != nil {
102 | return err
103 | }
104 | if err := ioutil.WriteFile(path, b, 0644); err != nil {
105 | return err
106 | }
107 | }
108 | {
109 | path := filepath.Join("archive", "facebook", "photos.json")
110 | b, err := json.MarshalIndent(facebookpb.Archive{Photos: a.archive.Photos}, "", " ")
111 | if err != nil {
112 | return err
113 | }
114 | if err := ioutil.WriteFile(path, b, 0644); err != nil {
115 | return err
116 | }
117 | }
118 | {
119 | path := filepath.Join("archive", "facebook", "albums.json")
120 | b, err := json.MarshalIndent(facebookpb.Archive{Albums: a.archive.Albums}, "", " ")
121 | if err != nil {
122 | return err
123 | }
124 | if err := ioutil.WriteFile(path, b, 0644); err != nil {
125 | return err
126 | }
127 | }
128 | {
129 | path := filepath.Join("archive", "facebook", "friends.json")
130 | b, err := json.MarshalIndent(facebookpb.Archive{Friends: a.archive.Friends}, "", " ")
131 | if err != nil {
132 | return err
133 | }
134 | if err := ioutil.WriteFile(path, b, 0644); err != nil {
135 | return err
136 | }
137 | }
138 | return nil
139 | }
140 |
141 | func (a *Archiver) archiveNode(ctx context.Context, id string) error {
142 | // Don't process a node twice
143 | if _, ok := a.seen[id]; ok {
144 | return nil
145 | }
146 |
147 | // Fetch the node
148 | kind, err := a.buildMetadata(ctx, id)
149 | if err != nil {
150 | return err
151 | }
152 |
153 | fmt.Printf("node:%s kind:%s\n", id, kind)
154 |
155 | node, err := a.api.GetNode(id, Fields(a.metadata[kind].Fields...))
156 | if err != nil {
157 | return err
158 | }
159 |
160 | a.seen[id] = struct{}{}
161 |
162 | switch v := node.Message.(type) {
163 | case *facebookpb.Photo:
164 | a.archive.Photos = append(a.archive.Photos, v)
165 | sort.Slice(v.Images, func(i, j int) bool {
166 | return (v.Images[i].Width + v.Images[i].Height) > (v.Images[j].Width + v.Images[j].Height)
167 | })
168 | if err := archive.ArchiveURL(ctx, "facebook", "media", v.Images[0].Source); err != nil {
169 | return err
170 | }
171 | case *facebookpb.Album:
172 | a.archive.Albums = append(a.archive.Albums, v)
173 | case *facebookpb.User:
174 | if id == "me" {
175 | a.archive.Me = v
176 | } else {
177 | a.archive.Friends = append(a.archive.Friends, v)
178 | }
179 | }
180 |
181 | a.count += 1
182 | if a.count > 100 {
183 | if err := a.save(); err != nil {
184 | return err
185 | }
186 | }
187 |
188 | // Archive connections
189 | for _, connection := range a.metadata[kind].Conns {
190 | if a.CanFollow(id, kind, connection) {
191 | if err := a.archiveConnection(ctx, id, connection); err != nil {
192 | return err
193 | }
194 | }
195 | }
196 |
197 | return nil
198 | }
199 |
200 | func (a *Archiver) CanFollow(id, kind, connection string) bool {
201 | if id == "me" {
202 | return connection == "photos" || connection == "albums"
203 | }
204 | switch kind {
205 | case "album":
206 | return connection == "photos"
207 | default:
208 | return false
209 | }
210 | }
211 |
212 | func (a *Archiver) archiveConnection(ctx context.Context, id, connection string) error {
213 | fmt.Println("Connection:", id, connection)
214 |
215 | paging := Paging{}
216 |
217 | for {
218 | data, err := a.api.GetEdge(id, connection, &paging)
219 | if err != nil {
220 | return err
221 | }
222 |
223 | for _, node := range data.Data {
224 | // TODO: Pass kind to archiveNode so we don't have to make two requests
225 | if err := a.archiveNode(ctx, node.ID); err != nil {
226 | return err
227 | }
228 | }
229 |
230 | paging = data.Paging
231 | if paging.Next == "" {
232 | return nil
233 | }
234 | }
235 | return nil
236 | }
237 |
238 | func (a *Archiver) Sync(ctx context.Context) error {
239 | err := a.archiveNode(ctx, "me")
240 | // best effort to save
241 | a.save()
242 | return err
243 | }
244 |
--------------------------------------------------------------------------------
/gen/facebook/archive.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // source: facebook/archive.proto
3 |
4 | /*
5 | Package facebookpb is a generated protocol buffer package.
6 |
7 | It is generated from these files:
8 | facebook/archive.proto
9 | facebook/node.proto
10 | facebook/photo.proto
11 | facebook/user.proto
12 |
13 | It has these top-level messages:
14 | Archive
15 | Node
16 | Owner
17 | Location
18 | Place
19 | Album
20 | Image
21 | Photo
22 | User
23 | */
24 | package facebookpb
25 |
26 | import proto "github.com/golang/protobuf/proto"
27 | import fmt "fmt"
28 | import math "math"
29 |
30 | // Reference imports to suppress errors if they are not otherwise used.
31 | var _ = proto.Marshal
32 | var _ = fmt.Errorf
33 | var _ = math.Inf
34 |
35 | // This is a compile-time assertion to ensure that this generated file
36 | // is compatible with the proto package it is being compiled against.
37 | // A compilation error at this line likely means your copy of the
38 | // proto package needs to be updated.
39 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
40 |
41 | type Archive struct {
42 | Me *User `protobuf:"bytes,1,opt,name=me" json:"me,omitempty"`
43 | Photos []*Photo `protobuf:"bytes,2,rep,name=photos" json:"photos,omitempty"`
44 | Albums []*Album `protobuf:"bytes,3,rep,name=albums" json:"albums,omitempty"`
45 | Friends []*User `protobuf:"bytes,4,rep,name=friends" json:"friends,omitempty"`
46 | }
47 |
48 | func (m *Archive) Reset() { *m = Archive{} }
49 | func (m *Archive) String() string { return proto.CompactTextString(m) }
50 | func (*Archive) ProtoMessage() {}
51 | func (*Archive) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
52 |
53 | func (m *Archive) GetMe() *User {
54 | if m != nil {
55 | return m.Me
56 | }
57 | return nil
58 | }
59 |
60 | func (m *Archive) GetPhotos() []*Photo {
61 | if m != nil {
62 | return m.Photos
63 | }
64 | return nil
65 | }
66 |
67 | func (m *Archive) GetAlbums() []*Album {
68 | if m != nil {
69 | return m.Albums
70 | }
71 | return nil
72 | }
73 |
74 | func (m *Archive) GetFriends() []*User {
75 | if m != nil {
76 | return m.Friends
77 | }
78 | return nil
79 | }
80 |
81 | func init() {
82 | proto.RegisterType((*Archive)(nil), "grain.facebook.Archive")
83 | }
84 |
85 | func init() { proto.RegisterFile("facebook/archive.proto", fileDescriptor0) }
86 |
87 | var fileDescriptor0 = []byte{
88 | // 187 bytes of a gzipped FileDescriptorProto
89 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4b, 0x4b, 0x4c, 0x4e,
90 | 0x4d, 0xca, 0xcf, 0xcf, 0xd6, 0x4f, 0x2c, 0x4a, 0xce, 0xc8, 0x2c, 0x4b, 0xd5, 0x2b, 0x28, 0xca,
91 | 0x2f, 0xc9, 0x17, 0xe2, 0x4b, 0x2f, 0x4a, 0xcc, 0xcc, 0xd3, 0x83, 0xc9, 0x4a, 0x89, 0xc0, 0xd5,
92 | 0x15, 0x64, 0xe4, 0x97, 0xe4, 0x43, 0x54, 0x49, 0x09, 0xc3, 0x45, 0x4b, 0x8b, 0x53, 0x8b, 0x20,
93 | 0x82, 0x4a, 0x7b, 0x19, 0xb9, 0xd8, 0x1d, 0x21, 0x86, 0x09, 0xa9, 0x70, 0x31, 0xe5, 0xa6, 0x4a,
94 | 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x1b, 0x89, 0xe8, 0xa1, 0x9a, 0xa9, 0x17, 0x5a, 0x9c, 0x5a, 0x14,
95 | 0xc4, 0x94, 0x9b, 0x2a, 0xa4, 0xcb, 0xc5, 0x06, 0x36, 0xb5, 0x58, 0x82, 0x49, 0x81, 0x59, 0x83,
96 | 0xdb, 0x48, 0x14, 0x5d, 0x65, 0x00, 0x48, 0x36, 0x08, 0xaa, 0x08, 0xa4, 0x3c, 0x31, 0x27, 0xa9,
97 | 0x34, 0xb7, 0x58, 0x82, 0x19, 0xbb, 0x72, 0x47, 0x90, 0x6c, 0x10, 0x54, 0x91, 0x90, 0x1e, 0x17,
98 | 0x7b, 0x5a, 0x51, 0x66, 0x6a, 0x5e, 0x4a, 0xb1, 0x04, 0x0b, 0x58, 0x3d, 0x76, 0x87, 0xc0, 0x14,
99 | 0x39, 0xf1, 0x44, 0x71, 0xc1, 0x64, 0x0a, 0x92, 0x92, 0xd8, 0xc0, 0x9e, 0x32, 0x06, 0x04, 0x00,
100 | 0x00, 0xff, 0xff, 0x17, 0x9f, 0x8d, 0x78, 0x29, 0x01, 0x00, 0x00,
101 | }
102 |
--------------------------------------------------------------------------------
/gen/facebook/download/about_you.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // source: facebook/download/about_you.proto
3 |
4 | /*
5 | Package grain_facebook_download is a generated protocol buffer package.
6 |
7 | It is generated from these files:
8 | facebook/download/about_you.proto
9 | facebook/download/ads.proto
10 | facebook/download/apps.proto
11 | facebook/download/comments.proto
12 | facebook/download/events.proto
13 | facebook/download/following_and_followers.proto
14 | facebook/download/friends.proto
15 | facebook/download/groups.proto
16 |
17 | It has these top-level messages:
18 | AddressBook
19 | Ads
20 | InstalledApps
21 | PostsFromApps
22 | YourApps
23 | Comment
24 | PhotoMetadata
25 | MediaMetadata
26 | Media
27 | AttachmentData
28 | Attachment
29 | Post
30 | YourPosts
31 | Coordinate
32 | Event
33 | EventInvitations
34 | EventResponses
35 | YourEvents
36 | FollowedPages
37 | Friend
38 | FriendsAdded
39 | RejectedRequests
40 | RemovedFriends
41 | SentRequests
42 | GroupsYouManage
43 | GroupMembershipActivity
44 | GroupPostsComments
45 | */
46 | package grain_facebook_download
47 |
48 | import proto "github.com/golang/protobuf/proto"
49 | import fmt "fmt"
50 | import math "math"
51 |
52 | // Reference imports to suppress errors if they are not otherwise used.
53 | var _ = proto.Marshal
54 | var _ = fmt.Errorf
55 | var _ = math.Inf
56 |
57 | // This is a compile-time assertion to ensure that this generated file
58 | // is compatible with the proto package it is being compiled against.
59 | // A compilation error at this line likely means your copy of the
60 | // proto package needs to be updated.
61 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
62 |
63 | type AddressBook struct {
64 | AddressBook *AddressBook_AddressBookEntry `protobuf:"bytes,1,opt,name=address_book,json=addressBook" json:"address_book,omitempty"`
65 | }
66 |
67 | func (m *AddressBook) Reset() { *m = AddressBook{} }
68 | func (m *AddressBook) String() string { return proto.CompactTextString(m) }
69 | func (*AddressBook) ProtoMessage() {}
70 | func (*AddressBook) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
71 |
72 | func (m *AddressBook) GetAddressBook() *AddressBook_AddressBookEntry {
73 | if m != nil {
74 | return m.AddressBook
75 | }
76 | return nil
77 | }
78 |
79 | type AddressBook_Details struct {
80 | ContactPoint string `protobuf:"bytes,1,opt,name=contact_point,json=contactPoint" json:"contact_point,omitempty"`
81 | }
82 |
83 | func (m *AddressBook_Details) Reset() { *m = AddressBook_Details{} }
84 | func (m *AddressBook_Details) String() string { return proto.CompactTextString(m) }
85 | func (*AddressBook_Details) ProtoMessage() {}
86 | func (*AddressBook_Details) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 0} }
87 |
88 | func (m *AddressBook_Details) GetContactPoint() string {
89 | if m != nil {
90 | return m.ContactPoint
91 | }
92 | return ""
93 | }
94 |
95 | type AddressBook_Contact struct {
96 | Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
97 | Details []*AddressBook_Details `protobuf:"bytes,2,rep,name=details" json:"details,omitempty"`
98 | }
99 |
100 | func (m *AddressBook_Contact) Reset() { *m = AddressBook_Contact{} }
101 | func (m *AddressBook_Contact) String() string { return proto.CompactTextString(m) }
102 | func (*AddressBook_Contact) ProtoMessage() {}
103 | func (*AddressBook_Contact) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 1} }
104 |
105 | func (m *AddressBook_Contact) GetName() string {
106 | if m != nil {
107 | return m.Name
108 | }
109 | return ""
110 | }
111 |
112 | func (m *AddressBook_Contact) GetDetails() []*AddressBook_Details {
113 | if m != nil {
114 | return m.Details
115 | }
116 | return nil
117 | }
118 |
119 | type AddressBook_AddressBookEntry struct {
120 | AddressBook []*AddressBook_Contact `protobuf:"bytes,1,rep,name=address_book,json=addressBook" json:"address_book,omitempty"`
121 | }
122 |
123 | func (m *AddressBook_AddressBookEntry) Reset() { *m = AddressBook_AddressBookEntry{} }
124 | func (m *AddressBook_AddressBookEntry) String() string { return proto.CompactTextString(m) }
125 | func (*AddressBook_AddressBookEntry) ProtoMessage() {}
126 | func (*AddressBook_AddressBookEntry) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0, 2} }
127 |
128 | func (m *AddressBook_AddressBookEntry) GetAddressBook() []*AddressBook_Contact {
129 | if m != nil {
130 | return m.AddressBook
131 | }
132 | return nil
133 | }
134 |
135 | func init() {
136 | proto.RegisterType((*AddressBook)(nil), "grain.facebook.download.AddressBook")
137 | proto.RegisterType((*AddressBook_Details)(nil), "grain.facebook.download.AddressBook.Details")
138 | proto.RegisterType((*AddressBook_Contact)(nil), "grain.facebook.download.AddressBook.Contact")
139 | proto.RegisterType((*AddressBook_AddressBookEntry)(nil), "grain.facebook.download.AddressBook.AddressBookEntry")
140 | }
141 |
142 | func init() { proto.RegisterFile("facebook/download/about_you.proto", fileDescriptor0) }
143 |
144 | var fileDescriptor0 = []byte{
145 | // 227 bytes of a gzipped FileDescriptorProto
146 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4c, 0x4b, 0x4c, 0x4e,
147 | 0x4d, 0xca, 0xcf, 0xcf, 0xd6, 0x4f, 0xc9, 0x2f, 0xcf, 0xcb, 0xc9, 0x4f, 0x4c, 0xd1, 0x4f, 0x4c,
148 | 0xca, 0x2f, 0x2d, 0x89, 0xaf, 0xcc, 0x2f, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x4f,
149 | 0x2f, 0x4a, 0xcc, 0xcc, 0xd3, 0x83, 0x29, 0xd4, 0x83, 0x29, 0x54, 0x7a, 0xcc, 0xc4, 0xc5, 0xed,
150 | 0x98, 0x92, 0x52, 0x94, 0x5a, 0x5c, 0xec, 0x94, 0x9f, 0x9f, 0x2d, 0x14, 0xc1, 0xc5, 0x93, 0x08,
151 | 0xe1, 0xc6, 0x83, 0x14, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x1b, 0x99, 0xea, 0xe1, 0xd0, 0xaf,
152 | 0x87, 0xa4, 0x17, 0x99, 0xed, 0x9a, 0x57, 0x52, 0x54, 0x19, 0xc4, 0x9d, 0x88, 0x10, 0x91, 0xd2,
153 | 0xe3, 0x62, 0x77, 0x49, 0x2d, 0x49, 0xcc, 0xcc, 0x29, 0x16, 0x52, 0xe6, 0xe2, 0x4d, 0xce, 0xcf,
154 | 0x2b, 0x49, 0x4c, 0x2e, 0x89, 0x2f, 0xc8, 0xcf, 0xcc, 0x2b, 0x01, 0xdb, 0xc2, 0x19, 0xc4, 0x03,
155 | 0x15, 0x0c, 0x00, 0x89, 0x49, 0xa5, 0x72, 0xb1, 0x3b, 0x43, 0xf8, 0x42, 0x42, 0x5c, 0x2c, 0x79,
156 | 0x89, 0xb9, 0xa9, 0x50, 0x65, 0x60, 0xb6, 0x90, 0x1b, 0x17, 0x7b, 0x0a, 0xc4, 0x38, 0x09, 0x26,
157 | 0x05, 0x66, 0x0d, 0x6e, 0x23, 0x1d, 0xa2, 0xdc, 0x08, 0x75, 0x42, 0x10, 0x4c, 0xb3, 0x54, 0x32,
158 | 0x97, 0x00, 0xba, 0xbb, 0x85, 0xfc, 0x31, 0x02, 0x81, 0x78, 0x0b, 0xa0, 0x6e, 0x46, 0xf1, 0x7b,
159 | 0x12, 0x1b, 0x38, 0x16, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x8e, 0x54, 0xa6, 0xff, 0xaa,
160 | 0x01, 0x00, 0x00,
161 | }
162 |
--------------------------------------------------------------------------------
/gen/facebook/download/ads.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // source: facebook/download/ads.proto
3 |
4 | package grain_facebook_download
5 |
6 | import proto "github.com/golang/protobuf/proto"
7 | import fmt "fmt"
8 | import math "math"
9 |
10 | // Reference imports to suppress errors if they are not otherwise used.
11 | var _ = proto.Marshal
12 | var _ = fmt.Errorf
13 | var _ = math.Inf
14 |
15 | type Ads struct {
16 | Topics []string `protobuf:"bytes,1,rep,name=topics" json:"topics,omitempty"`
17 | CustomAudiences []string `protobuf:"bytes,2,rep,name=custom_audiences,json=customAudiences" json:"custom_audiences,omitempty"`
18 | LeadGenInfo []string `protobuf:"bytes,3,rep,name=lead_gen_info,json=leadGenInfo" json:"lead_gen_info,omitempty"`
19 | History []*Ads_History `protobuf:"bytes,4,rep,name=history" json:"history,omitempty"`
20 | }
21 |
22 | func (m *Ads) Reset() { *m = Ads{} }
23 | func (m *Ads) String() string { return proto.CompactTextString(m) }
24 | func (*Ads) ProtoMessage() {}
25 | func (*Ads) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
26 |
27 | func (m *Ads) GetTopics() []string {
28 | if m != nil {
29 | return m.Topics
30 | }
31 | return nil
32 | }
33 |
34 | func (m *Ads) GetCustomAudiences() []string {
35 | if m != nil {
36 | return m.CustomAudiences
37 | }
38 | return nil
39 | }
40 |
41 | func (m *Ads) GetLeadGenInfo() []string {
42 | if m != nil {
43 | return m.LeadGenInfo
44 | }
45 | return nil
46 | }
47 |
48 | func (m *Ads) GetHistory() []*Ads_History {
49 | if m != nil {
50 | return m.History
51 | }
52 | return nil
53 | }
54 |
55 | type Ads_History struct {
56 | Title string `protobuf:"bytes,1,opt,name=title" json:"title,omitempty"`
57 | Action string `protobuf:"bytes,2,opt,name=action" json:"action,omitempty"`
58 | Timestamp int64 `protobuf:"varint,3,opt,name=timestamp" json:"timestamp,omitempty"`
59 | }
60 |
61 | func (m *Ads_History) Reset() { *m = Ads_History{} }
62 | func (m *Ads_History) String() string { return proto.CompactTextString(m) }
63 | func (*Ads_History) ProtoMessage() {}
64 | func (*Ads_History) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0, 0} }
65 |
66 | func (m *Ads_History) GetTitle() string {
67 | if m != nil {
68 | return m.Title
69 | }
70 | return ""
71 | }
72 |
73 | func (m *Ads_History) GetAction() string {
74 | if m != nil {
75 | return m.Action
76 | }
77 | return ""
78 | }
79 |
80 | func (m *Ads_History) GetTimestamp() int64 {
81 | if m != nil {
82 | return m.Timestamp
83 | }
84 | return 0
85 | }
86 |
87 | func init() {
88 | proto.RegisterType((*Ads)(nil), "grain.facebook.download.Ads")
89 | proto.RegisterType((*Ads_History)(nil), "grain.facebook.download.Ads.History")
90 | }
91 |
92 | func init() { proto.RegisterFile("facebook/download/ads.proto", fileDescriptor1) }
93 |
94 | var fileDescriptor1 = []byte{
95 | // 239 bytes of a gzipped FileDescriptorProto
96 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x90, 0x4d, 0x4b, 0xc4, 0x30,
97 | 0x10, 0x40, 0x69, 0xa3, 0xbb, 0x74, 0x16, 0x51, 0x82, 0x68, 0x50, 0x0f, 0x65, 0xf1, 0x50, 0x2f,
98 | 0x59, 0xd0, 0xbb, 0xd0, 0x93, 0x7a, 0x2d, 0x78, 0x2e, 0xd9, 0x24, 0x5d, 0x83, 0x6d, 0xa6, 0x34,
99 | 0xb3, 0x88, 0x67, 0xff, 0xb8, 0xf4, 0x23, 0x78, 0xf2, 0xf8, 0x1e, 0x6f, 0x60, 0x66, 0xe0, 0xb6,
100 | 0x51, 0xda, 0xee, 0x11, 0x3f, 0x77, 0x06, 0xbf, 0x7c, 0x8b, 0xca, 0xec, 0x94, 0x09, 0xb2, 0x1f,
101 | 0x90, 0x90, 0x5f, 0x1f, 0x06, 0xe5, 0xbc, 0x8c, 0x89, 0x8c, 0xc9, 0xf6, 0x27, 0x05, 0x56, 0x9a,
102 | 0xc0, 0xaf, 0x60, 0x45, 0xd8, 0x3b, 0x1d, 0x44, 0x92, 0xb3, 0x22, 0xab, 0x16, 0xe2, 0x0f, 0x70,
103 | 0xa1, 0x8f, 0x81, 0xb0, 0xab, 0xd5, 0xd1, 0x38, 0xeb, 0xb5, 0x0d, 0x22, 0x9d, 0x8a, 0xf3, 0xd9,
104 | 0x97, 0x51, 0xf3, 0x2d, 0x9c, 0xb5, 0x56, 0x99, 0xfa, 0x60, 0x7d, 0xed, 0x7c, 0x83, 0x82, 0x4d,
105 | 0xdd, 0x66, 0x94, 0x2f, 0xd6, 0xbf, 0xf9, 0x06, 0xf9, 0x33, 0xac, 0x3f, 0x5c, 0x20, 0x1c, 0xbe,
106 | 0xc5, 0x49, 0xce, 0x8a, 0xcd, 0xe3, 0xbd, 0xfc, 0x67, 0x33, 0x59, 0x9a, 0x20, 0x5f, 0xe7, 0xb6,
107 | 0x8a, 0x43, 0x37, 0xef, 0xb0, 0x5e, 0x1c, 0xbf, 0x84, 0x53, 0x72, 0xd4, 0x5a, 0x91, 0xe4, 0x49,
108 | 0x91, 0x55, 0x33, 0x8c, 0x77, 0x28, 0x4d, 0x0e, 0xbd, 0x48, 0x27, 0xbd, 0x10, 0xbf, 0x83, 0x8c,
109 | 0x5c, 0x67, 0x03, 0xa9, 0xae, 0x17, 0x2c, 0x4f, 0x0a, 0x56, 0xfd, 0x89, 0xfd, 0x6a, 0xfa, 0xd2,
110 | 0xd3, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0xd5, 0x3f, 0xfb, 0x44, 0x01, 0x00, 0x00,
111 | }
112 |
--------------------------------------------------------------------------------
/gen/facebook/download/following_and_followers.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // source: facebook/download/following_and_followers.proto
3 |
4 | package grain_facebook_download
5 |
6 | import proto "github.com/golang/protobuf/proto"
7 | import fmt "fmt"
8 | import math "math"
9 |
10 | // Reference imports to suppress errors if they are not otherwise used.
11 | var _ = proto.Marshal
12 | var _ = fmt.Errorf
13 | var _ = math.Inf
14 |
15 | // Stored as an array, not a top level message
16 | type FollowedPages struct {
17 | Pages []*FollowedPages_Page `protobuf:"bytes,1,rep,name=pages" json:"pages,omitempty"`
18 | }
19 |
20 | func (m *FollowedPages) Reset() { *m = FollowedPages{} }
21 | func (m *FollowedPages) String() string { return proto.CompactTextString(m) }
22 | func (*FollowedPages) ProtoMessage() {}
23 | func (*FollowedPages) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0} }
24 |
25 | func (m *FollowedPages) GetPages() []*FollowedPages_Page {
26 | if m != nil {
27 | return m.Pages
28 | }
29 | return nil
30 | }
31 |
32 | type FollowedPages_Data struct {
33 | Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
34 | }
35 |
36 | func (m *FollowedPages_Data) Reset() { *m = FollowedPages_Data{} }
37 | func (m *FollowedPages_Data) String() string { return proto.CompactTextString(m) }
38 | func (*FollowedPages_Data) ProtoMessage() {}
39 | func (*FollowedPages_Data) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0, 0} }
40 |
41 | func (m *FollowedPages_Data) GetName() string {
42 | if m != nil {
43 | return m.Name
44 | }
45 | return ""
46 | }
47 |
48 | type FollowedPages_Page struct {
49 | Title string `protobuf:"bytes,1,opt,name=title" json:"title,omitempty"`
50 | Timestamp int64 `protobuf:"varint,2,opt,name=timestamp" json:"timestamp,omitempty"`
51 | Data []*FollowedPages_Data `protobuf:"bytes,3,rep,name=data" json:"data,omitempty"`
52 | }
53 |
54 | func (m *FollowedPages_Page) Reset() { *m = FollowedPages_Page{} }
55 | func (m *FollowedPages_Page) String() string { return proto.CompactTextString(m) }
56 | func (*FollowedPages_Page) ProtoMessage() {}
57 | func (*FollowedPages_Page) Descriptor() ([]byte, []int) { return fileDescriptor5, []int{0, 1} }
58 |
59 | func (m *FollowedPages_Page) GetTitle() string {
60 | if m != nil {
61 | return m.Title
62 | }
63 | return ""
64 | }
65 |
66 | func (m *FollowedPages_Page) GetTimestamp() int64 {
67 | if m != nil {
68 | return m.Timestamp
69 | }
70 | return 0
71 | }
72 |
73 | func (m *FollowedPages_Page) GetData() []*FollowedPages_Data {
74 | if m != nil {
75 | return m.Data
76 | }
77 | return nil
78 | }
79 |
80 | func init() {
81 | proto.RegisterType((*FollowedPages)(nil), "grain.facebook.download.FollowedPages")
82 | proto.RegisterType((*FollowedPages_Data)(nil), "grain.facebook.download.FollowedPages.Data")
83 | proto.RegisterType((*FollowedPages_Page)(nil), "grain.facebook.download.FollowedPages.Page")
84 | }
85 |
86 | func init() { proto.RegisterFile("facebook/download/following_and_followers.proto", fileDescriptor5) }
87 |
88 | var fileDescriptor5 = []byte{
89 | // 210 bytes of a gzipped FileDescriptorProto
90 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x4f, 0x4b, 0x4c, 0x4e,
91 | 0x4d, 0xca, 0xcf, 0xcf, 0xd6, 0x4f, 0xc9, 0x2f, 0xcf, 0xcb, 0xc9, 0x4f, 0x4c, 0xd1, 0x4f, 0xcb,
92 | 0xcf, 0xc9, 0xc9, 0x2f, 0xcf, 0xcc, 0x4b, 0x8f, 0x4f, 0xcc, 0x4b, 0x89, 0x87, 0xf0, 0x52, 0x8b,
93 | 0x8a, 0xf5, 0x0a, 0x8a, 0xf2, 0x4b, 0xf2, 0x85, 0xc4, 0xd3, 0x8b, 0x12, 0x33, 0xf3, 0xf4, 0x60,
94 | 0xda, 0xf4, 0x60, 0xda, 0x94, 0x5e, 0x33, 0x72, 0xf1, 0xba, 0x41, 0x14, 0xa7, 0x04, 0x24, 0xa6,
95 | 0xa7, 0x16, 0x0b, 0x39, 0x72, 0xb1, 0x16, 0x80, 0x18, 0x12, 0x8c, 0x0a, 0xcc, 0x1a, 0xdc, 0x46,
96 | 0xda, 0x7a, 0x38, 0xb4, 0xea, 0xa1, 0x68, 0xd3, 0x03, 0x91, 0x41, 0x10, 0x9d, 0x52, 0x52, 0x5c,
97 | 0x2c, 0x2e, 0x89, 0x25, 0x89, 0x42, 0x42, 0x5c, 0x2c, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0x8c, 0x0a,
98 | 0x8c, 0x1a, 0x9c, 0x41, 0x60, 0xb6, 0x54, 0x35, 0x17, 0x0b, 0x48, 0xa9, 0x90, 0x08, 0x17, 0x6b,
99 | 0x49, 0x66, 0x49, 0x0e, 0x4c, 0x12, 0xc2, 0x11, 0x92, 0xe1, 0xe2, 0x2c, 0xc9, 0xcc, 0x4d, 0x2d,
100 | 0x2e, 0x49, 0xcc, 0x2d, 0x90, 0x60, 0x52, 0x60, 0xd4, 0x60, 0x0e, 0x42, 0x08, 0x08, 0xd9, 0x73,
101 | 0xb1, 0xa4, 0x24, 0x96, 0x24, 0x4a, 0x30, 0x93, 0xe4, 0x32, 0x90, 0x53, 0x82, 0xc0, 0x1a, 0x93,
102 | 0xd8, 0xc0, 0xa1, 0x61, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x22, 0x6e, 0xda, 0x17, 0x40, 0x01,
103 | 0x00, 0x00,
104 | }
105 |
--------------------------------------------------------------------------------
/gen/facebook/download/friends.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // source: facebook/download/friends.proto
3 |
4 | package grain_facebook_download
5 |
6 | import proto "github.com/golang/protobuf/proto"
7 | import fmt "fmt"
8 | import math "math"
9 |
10 | // Reference imports to suppress errors if they are not otherwise used.
11 | var _ = proto.Marshal
12 | var _ = fmt.Errorf
13 | var _ = math.Inf
14 |
15 | type Friend struct {
16 | Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
17 | Timestamp int64 `protobuf:"varint,2,opt,name=timestamp" json:"timestamp,omitempty"`
18 | }
19 |
20 | func (m *Friend) Reset() { *m = Friend{} }
21 | func (m *Friend) String() string { return proto.CompactTextString(m) }
22 | func (*Friend) ProtoMessage() {}
23 | func (*Friend) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{0} }
24 |
25 | func (m *Friend) GetName() string {
26 | if m != nil {
27 | return m.Name
28 | }
29 | return ""
30 | }
31 |
32 | func (m *Friend) GetTimestamp() int64 {
33 | if m != nil {
34 | return m.Timestamp
35 | }
36 | return 0
37 | }
38 |
39 | type FriendsAdded struct {
40 | Friends []*Friend `protobuf:"bytes,1,rep,name=friends" json:"friends,omitempty"`
41 | }
42 |
43 | func (m *FriendsAdded) Reset() { *m = FriendsAdded{} }
44 | func (m *FriendsAdded) String() string { return proto.CompactTextString(m) }
45 | func (*FriendsAdded) ProtoMessage() {}
46 | func (*FriendsAdded) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{1} }
47 |
48 | func (m *FriendsAdded) GetFriends() []*Friend {
49 | if m != nil {
50 | return m.Friends
51 | }
52 | return nil
53 | }
54 |
55 | type RejectedRequests struct {
56 | RejectedRequests []*Friend `protobuf:"bytes,1,rep,name=rejected_requests,json=rejectedRequests" json:"rejected_requests,omitempty"`
57 | }
58 |
59 | func (m *RejectedRequests) Reset() { *m = RejectedRequests{} }
60 | func (m *RejectedRequests) String() string { return proto.CompactTextString(m) }
61 | func (*RejectedRequests) ProtoMessage() {}
62 | func (*RejectedRequests) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{2} }
63 |
64 | func (m *RejectedRequests) GetRejectedRequests() []*Friend {
65 | if m != nil {
66 | return m.RejectedRequests
67 | }
68 | return nil
69 | }
70 |
71 | type RemovedFriends struct {
72 | DeletedFriends []*Friend `protobuf:"bytes,1,rep,name=deleted_friends,json=deletedFriends" json:"deleted_friends,omitempty"`
73 | }
74 |
75 | func (m *RemovedFriends) Reset() { *m = RemovedFriends{} }
76 | func (m *RemovedFriends) String() string { return proto.CompactTextString(m) }
77 | func (*RemovedFriends) ProtoMessage() {}
78 | func (*RemovedFriends) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{3} }
79 |
80 | func (m *RemovedFriends) GetDeletedFriends() []*Friend {
81 | if m != nil {
82 | return m.DeletedFriends
83 | }
84 | return nil
85 | }
86 |
87 | type SentRequests struct {
88 | SentRequests []*Friend `protobuf:"bytes,1,rep,name=sent_requests,json=sentRequests" json:"sent_requests,omitempty"`
89 | }
90 |
91 | func (m *SentRequests) Reset() { *m = SentRequests{} }
92 | func (m *SentRequests) String() string { return proto.CompactTextString(m) }
93 | func (*SentRequests) ProtoMessage() {}
94 | func (*SentRequests) Descriptor() ([]byte, []int) { return fileDescriptor6, []int{4} }
95 |
96 | func (m *SentRequests) GetSentRequests() []*Friend {
97 | if m != nil {
98 | return m.SentRequests
99 | }
100 | return nil
101 | }
102 |
103 | func init() {
104 | proto.RegisterType((*Friend)(nil), "grain.facebook.download.Friend")
105 | proto.RegisterType((*FriendsAdded)(nil), "grain.facebook.download.FriendsAdded")
106 | proto.RegisterType((*RejectedRequests)(nil), "grain.facebook.download.RejectedRequests")
107 | proto.RegisterType((*RemovedFriends)(nil), "grain.facebook.download.RemovedFriends")
108 | proto.RegisterType((*SentRequests)(nil), "grain.facebook.download.SentRequests")
109 | }
110 |
111 | func init() { proto.RegisterFile("facebook/download/friends.proto", fileDescriptor6) }
112 |
113 | var fileDescriptor6 = []byte{
114 | // 244 bytes of a gzipped FileDescriptorProto
115 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x91, 0xb1, 0x4b, 0x03, 0x31,
116 | 0x18, 0xc5, 0x39, 0x2b, 0x95, 0x7e, 0x9e, 0xb5, 0x66, 0xf1, 0x06, 0xa1, 0x47, 0xa6, 0x9b, 0x52,
117 | 0xd0, 0x49, 0x37, 0x41, 0x44, 0xc1, 0x29, 0x3a, 0xb9, 0x68, 0xda, 0xef, 0x55, 0x4e, 0x7b, 0x49,
118 | 0x4d, 0xa2, 0xfe, 0xfb, 0xe2, 0x35, 0xa7, 0x22, 0x08, 0xed, 0x16, 0x1e, 0xef, 0xfd, 0xbe, 0x1f,
119 | 0x84, 0xc6, 0x73, 0x33, 0xc3, 0xd4, 0xb9, 0x97, 0x09, 0xbb, 0x0f, 0xbb, 0x70, 0x86, 0x27, 0x73,
120 | 0x5f, 0xc3, 0x72, 0x50, 0x4b, 0xef, 0xa2, 0x13, 0x87, 0x4f, 0xde, 0xd4, 0x56, 0x75, 0x35, 0xd5,
121 | 0xd5, 0xe4, 0x19, 0xf5, 0x2f, 0xdb, 0xa6, 0x10, 0xb4, 0x6d, 0x4d, 0x83, 0x22, 0x2b, 0xb3, 0x6a,
122 | 0xa0, 0xdb, 0xb7, 0x38, 0xa2, 0x41, 0xac, 0x1b, 0x84, 0x68, 0x9a, 0x65, 0xb1, 0x55, 0x66, 0x55,
123 | 0x4f, 0xff, 0x04, 0xf2, 0x9a, 0xf2, 0xd5, 0x36, 0x9c, 0x33, 0x83, 0xc5, 0x29, 0xed, 0xa4, 0xab,
124 | 0x45, 0x56, 0xf6, 0xaa, 0xdd, 0xe3, 0xb1, 0xfa, 0xe7, 0xac, 0x5a, 0xed, 0x74, 0xd7, 0x97, 0x8f,
125 | 0x34, 0xd2, 0x78, 0xc6, 0x2c, 0x82, 0x35, 0x5e, 0xdf, 0x10, 0x62, 0x10, 0x37, 0x74, 0xe0, 0x53,
126 | 0xf6, 0xe0, 0x53, 0xb8, 0x2e, 0x78, 0xe4, 0xff, 0xd0, 0xe4, 0x3d, 0x0d, 0x35, 0x1a, 0xf7, 0x0e,
127 | 0x4e, 0xce, 0xe2, 0x8a, 0xf6, 0x19, 0x0b, 0x7c, 0xe1, 0x37, 0xd4, 0x1e, 0xa6, 0x5d, 0x22, 0xc9,
128 | 0x3b, 0xca, 0x6f, 0x61, 0xe3, 0xb7, 0xf9, 0x05, 0xed, 0x05, 0xd8, 0xb8, 0xb1, 0x75, 0x1e, 0x7e,
129 | 0x51, 0xa6, 0xfd, 0xf6, 0xeb, 0x4e, 0x3e, 0x03, 0x00, 0x00, 0xff, 0xff, 0x67, 0x24, 0x75, 0xe3,
130 | 0xdd, 0x01, 0x00, 0x00,
131 | }
132 |
--------------------------------------------------------------------------------
/gen/facebook/node.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // source: facebook/node.proto
3 |
4 | package facebookpb
5 |
6 | import proto "github.com/golang/protobuf/proto"
7 | import fmt "fmt"
8 | import math "math"
9 |
10 | // Reference imports to suppress errors if they are not otherwise used.
11 | var _ = proto.Marshal
12 | var _ = fmt.Errorf
13 | var _ = math.Inf
14 |
15 | type Node struct {
16 | Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
17 | }
18 |
19 | func (m *Node) Reset() { *m = Node{} }
20 | func (m *Node) String() string { return proto.CompactTextString(m) }
21 | func (*Node) ProtoMessage() {}
22 | func (*Node) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
23 |
24 | func (m *Node) GetId() string {
25 | if m != nil {
26 | return m.Id
27 | }
28 | return ""
29 | }
30 |
31 | func init() {
32 | proto.RegisterType((*Node)(nil), "grain.facebook.Node")
33 | }
34 |
35 | func init() { proto.RegisterFile("facebook/node.proto", fileDescriptor1) }
36 |
37 | var fileDescriptor1 = []byte{
38 | // 92 bytes of a gzipped FileDescriptorProto
39 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4e, 0x4b, 0x4c, 0x4e,
40 | 0x4d, 0xca, 0xcf, 0xcf, 0xd6, 0xcf, 0xcb, 0x4f, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17,
41 | 0xe2, 0x4b, 0x2f, 0x4a, 0xcc, 0xcc, 0xd3, 0x83, 0x49, 0x29, 0x89, 0x71, 0xb1, 0xf8, 0xe5, 0xa7,
42 | 0xa4, 0x0a, 0xf1, 0x71, 0x31, 0x65, 0xa6, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x31, 0x65,
43 | 0xa6, 0x38, 0xf1, 0x44, 0x71, 0xc1, 0xd4, 0x14, 0x24, 0x25, 0xb1, 0x81, 0x35, 0x1b, 0x03, 0x02,
44 | 0x00, 0x00, 0xff, 0xff, 0x12, 0x0e, 0xa2, 0xa1, 0x53, 0x00, 0x00, 0x00,
45 | }
46 |
--------------------------------------------------------------------------------
/gen/facebook/user.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // source: facebook/user.proto
3 |
4 | package facebookpb
5 |
6 | import proto "github.com/golang/protobuf/proto"
7 | import fmt "fmt"
8 | import math "math"
9 |
10 | // Reference imports to suppress errors if they are not otherwise used.
11 | var _ = proto.Marshal
12 | var _ = fmt.Errorf
13 | var _ = math.Inf
14 |
15 | type User struct {
16 | Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
17 | Birthday string `protobuf:"bytes,2,opt,name=birthday" json:"birthday,omitempty"`
18 | }
19 |
20 | func (m *User) Reset() { *m = User{} }
21 | func (m *User) String() string { return proto.CompactTextString(m) }
22 | func (*User) ProtoMessage() {}
23 | func (*User) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} }
24 |
25 | func (m *User) GetId() string {
26 | if m != nil {
27 | return m.Id
28 | }
29 | return ""
30 | }
31 |
32 | func (m *User) GetBirthday() string {
33 | if m != nil {
34 | return m.Birthday
35 | }
36 | return ""
37 | }
38 |
39 | func init() {
40 | proto.RegisterType((*User)(nil), "grain.facebook.User")
41 | }
42 |
43 | func init() { proto.RegisterFile("facebook/user.proto", fileDescriptor3) }
44 |
45 | var fileDescriptor3 = []byte{
46 | // 110 bytes of a gzipped FileDescriptorProto
47 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4e, 0x4b, 0x4c, 0x4e,
48 | 0x4d, 0xca, 0xcf, 0xcf, 0xd6, 0x2f, 0x2d, 0x4e, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17,
49 | 0xe2, 0x4b, 0x2f, 0x4a, 0xcc, 0xcc, 0xd3, 0x83, 0x49, 0x29, 0x19, 0x71, 0xb1, 0x84, 0x16, 0xa7,
50 | 0x16, 0x09, 0xf1, 0x71, 0x31, 0x65, 0xa6, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x31, 0x65,
51 | 0xa6, 0x08, 0x49, 0x71, 0x71, 0x24, 0x65, 0x16, 0x95, 0x64, 0xa4, 0x24, 0x56, 0x4a, 0x30, 0x81,
52 | 0x45, 0xe1, 0x7c, 0x27, 0x9e, 0x28, 0x2e, 0x98, 0xfe, 0x82, 0xa4, 0x24, 0x36, 0xb0, 0xc1, 0xc6,
53 | 0x80, 0x00, 0x00, 0x00, 0xff, 0xff, 0x79, 0xa0, 0xaf, 0x69, 0x6f, 0x00, 0x00, 0x00,
54 | }
55 |
--------------------------------------------------------------------------------
/gen/twitter/archive.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // source: twitter/archive.proto
3 |
4 | /*
5 | Package twitterpb is a generated protocol buffer package.
6 |
7 | It is generated from these files:
8 | twitter/archive.proto
9 | twitter/dm.proto
10 | twitter/entity.proto
11 | twitter/list.proto
12 | twitter/tweet.proto
13 | twitter/user.proto
14 |
15 | It has these top-level messages:
16 | Archive
17 | Target
18 | DirectMessageData
19 | DirectMessageCreate
20 | DirectMessageEvent
21 | Url
22 | Hashtag
23 | UserMention
24 | MediaSize
25 | MediaSizes
26 | Variant
27 | VideoInfo
28 | EntityMedia
29 | Entities
30 | List
31 | Place
32 | Coordinates
33 | ExtendedTweet
34 | Tweet
35 | User
36 | */
37 | package twitterpb
38 |
39 | import proto "github.com/golang/protobuf/proto"
40 | import fmt "fmt"
41 | import math "math"
42 |
43 | // Reference imports to suppress errors if they are not otherwise used.
44 | var _ = proto.Marshal
45 | var _ = fmt.Errorf
46 | var _ = math.Inf
47 |
48 | // This is a compile-time assertion to ensure that this generated file
49 | // is compatible with the proto package it is being compiled against.
50 | // A compilation error at this line likely means your copy of the
51 | // proto package needs to be updated.
52 | const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
53 |
54 | type Archive struct {
55 | Lists []*List `protobuf:"bytes,1,rep,name=lists" json:"lists,omitempty"`
56 | Friends []*User `protobuf:"bytes,2,rep,name=friends" json:"friends,omitempty"`
57 | Followers []*User `protobuf:"bytes,3,rep,name=followers" json:"followers,omitempty"`
58 | Timeline []*Tweet `protobuf:"bytes,4,rep,name=timeline" json:"timeline,omitempty"`
59 | Favorites []*Tweet `protobuf:"bytes,5,rep,name=favorites" json:"favorites,omitempty"`
60 | DirectMessages []*DirectMessageEvent `protobuf:"bytes,6,rep,name=direct_messages,json=directMessages" json:"direct_messages,omitempty"`
61 | }
62 |
63 | func (m *Archive) Reset() { *m = Archive{} }
64 | func (m *Archive) String() string { return proto.CompactTextString(m) }
65 | func (*Archive) ProtoMessage() {}
66 | func (*Archive) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
67 |
68 | func (m *Archive) GetLists() []*List {
69 | if m != nil {
70 | return m.Lists
71 | }
72 | return nil
73 | }
74 |
75 | func (m *Archive) GetFriends() []*User {
76 | if m != nil {
77 | return m.Friends
78 | }
79 | return nil
80 | }
81 |
82 | func (m *Archive) GetFollowers() []*User {
83 | if m != nil {
84 | return m.Followers
85 | }
86 | return nil
87 | }
88 |
89 | func (m *Archive) GetTimeline() []*Tweet {
90 | if m != nil {
91 | return m.Timeline
92 | }
93 | return nil
94 | }
95 |
96 | func (m *Archive) GetFavorites() []*Tweet {
97 | if m != nil {
98 | return m.Favorites
99 | }
100 | return nil
101 | }
102 |
103 | func (m *Archive) GetDirectMessages() []*DirectMessageEvent {
104 | if m != nil {
105 | return m.DirectMessages
106 | }
107 | return nil
108 | }
109 |
110 | func init() {
111 | proto.RegisterType((*Archive)(nil), "grain.twitter.Archive")
112 | }
113 |
114 | func init() { proto.RegisterFile("twitter/archive.proto", fileDescriptor0) }
115 |
116 | var fileDescriptor0 = []byte{
117 | // 258 bytes of a gzipped FileDescriptorProto
118 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0xd0, 0xcf, 0x4e, 0x83, 0x40,
119 | 0x10, 0xc7, 0xf1, 0xd8, 0xda, 0x56, 0xb6, 0xf1, 0x4f, 0xb6, 0x9a, 0x6c, 0x7a, 0x52, 0x4f, 0x7a,
120 | 0x10, 0xb5, 0x3e, 0x81, 0x46, 0x2f, 0x46, 0x2f, 0x44, 0x2f, 0x5e, 0x0c, 0x2d, 0x43, 0x9d, 0x04,
121 | 0xd8, 0x66, 0x66, 0x84, 0x57, 0xf4, 0xb1, 0x4c, 0x59, 0x56, 0x94, 0xa8, 0xd7, 0x1f, 0x9f, 0x2f,
122 | 0x13, 0x50, 0x07, 0x52, 0xa1, 0x08, 0xd0, 0x79, 0x4c, 0x8b, 0x37, 0x2c, 0x21, 0x5c, 0x91, 0x15,
123 | 0xab, 0xb7, 0x97, 0x14, 0x63, 0x11, 0x36, 0x0f, 0xa7, 0x7b, 0x5e, 0x25, 0xb9, 0x03, 0x53, 0xed,
124 | 0x97, 0x0c, 0x59, 0x9a, 0x6d, 0xe2, 0x37, 0xa9, 0x00, 0xa4, 0x0b, 0xdf, 0x19, 0xc8, 0x6d, 0xc7,
125 | 0x1f, 0x3d, 0x35, 0xba, 0x76, 0xf7, 0xf4, 0xa9, 0x1a, 0xac, 0x5f, 0xc1, 0x66, 0xe3, 0xb0, 0x7f,
126 | 0x32, 0x9e, 0x4d, 0xc2, 0x1f, 0x97, 0xc3, 0x07, 0x64, 0x89, 0x9c, 0xd0, 0x67, 0x6a, 0x94, 0x12,
127 | 0x42, 0x91, 0xb0, 0xe9, 0xfd, 0x8a, 0x9f, 0x19, 0x28, 0xf2, 0x46, 0x5f, 0xaa, 0x20, 0xb5, 0x59,
128 | 0x66, 0x2b, 0x20, 0x36, 0xfd, 0xbf, 0x83, 0x56, 0xe9, 0x0b, 0xb5, 0x25, 0x98, 0x43, 0x86, 0x05,
129 | 0x98, 0xcd, 0xba, 0xd8, 0xef, 0x14, 0x4f, 0xeb, 0x4f, 0x8b, 0xbe, 0x94, 0x9e, 0xa9, 0x20, 0x8d,
130 | 0x4b, 0x4b, 0x28, 0xc0, 0x66, 0xf0, 0x4f, 0xd2, 0x32, 0x7d, 0xaf, 0x76, 0x13, 0x24, 0x58, 0xc8,
131 | 0x6b, 0x0e, 0xcc, 0xf1, 0x12, 0xd8, 0x0c, 0xeb, 0xf2, 0xa8, 0x53, 0xde, 0xd6, 0xea, 0xd1, 0xa1,
132 | 0xbb, 0x12, 0x0a, 0x89, 0x76, 0x92, 0xef, 0x1b, 0xdf, 0x8c, 0x5f, 0x82, 0x46, 0xaf, 0xe6, 0xf3,
133 | 0x61, 0xfd, 0x7b, 0xaf, 0x3e, 0x03, 0x00, 0x00, 0xff, 0xff, 0x81, 0x31, 0xe5, 0x74, 0xd5, 0x01,
134 | 0x00, 0x00,
135 | }
136 |
--------------------------------------------------------------------------------
/gen/twitter/dm.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // source: twitter/dm.proto
3 |
4 | package twitterpb
5 |
6 | import proto "github.com/golang/protobuf/proto"
7 | import fmt "fmt"
8 | import math "math"
9 |
10 | // Reference imports to suppress errors if they are not otherwise used.
11 | var _ = proto.Marshal
12 | var _ = fmt.Errorf
13 | var _ = math.Inf
14 |
15 | type Target struct {
16 | RecipientId string `protobuf:"bytes,1,opt,name=recipient_id,json=recipientId" json:"recipient_id,omitempty"`
17 | }
18 |
19 | func (m *Target) Reset() { *m = Target{} }
20 | func (m *Target) String() string { return proto.CompactTextString(m) }
21 | func (*Target) ProtoMessage() {}
22 | func (*Target) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{0} }
23 |
24 | func (m *Target) GetRecipientId() string {
25 | if m != nil {
26 | return m.RecipientId
27 | }
28 | return ""
29 | }
30 |
31 | type DirectMessageData struct {
32 | Text string `protobuf:"bytes,1,opt,name=text" json:"text,omitempty"`
33 | Entities *Entities `protobuf:"bytes,2,opt,name=entities" json:"entities,omitempty"`
34 | }
35 |
36 | func (m *DirectMessageData) Reset() { *m = DirectMessageData{} }
37 | func (m *DirectMessageData) String() string { return proto.CompactTextString(m) }
38 | func (*DirectMessageData) ProtoMessage() {}
39 | func (*DirectMessageData) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{1} }
40 |
41 | func (m *DirectMessageData) GetText() string {
42 | if m != nil {
43 | return m.Text
44 | }
45 | return ""
46 | }
47 |
48 | func (m *DirectMessageData) GetEntities() *Entities {
49 | if m != nil {
50 | return m.Entities
51 | }
52 | return nil
53 | }
54 |
55 | type DirectMessageCreate struct {
56 | Target *Target `protobuf:"bytes,1,opt,name=target" json:"target,omitempty"`
57 | SenderId string `protobuf:"bytes,2,opt,name=sender_id,json=senderId" json:"sender_id,omitempty"`
58 | SourceAppId string `protobuf:"bytes,3,opt,name=source_app_id,json=sourceAppId" json:"source_app_id,omitempty"`
59 | MessageData *DirectMessageData `protobuf:"bytes,4,opt,name=message_data,json=messageData" json:"message_data,omitempty"`
60 | }
61 |
62 | func (m *DirectMessageCreate) Reset() { *m = DirectMessageCreate{} }
63 | func (m *DirectMessageCreate) String() string { return proto.CompactTextString(m) }
64 | func (*DirectMessageCreate) ProtoMessage() {}
65 | func (*DirectMessageCreate) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{2} }
66 |
67 | func (m *DirectMessageCreate) GetTarget() *Target {
68 | if m != nil {
69 | return m.Target
70 | }
71 | return nil
72 | }
73 |
74 | func (m *DirectMessageCreate) GetSenderId() string {
75 | if m != nil {
76 | return m.SenderId
77 | }
78 | return ""
79 | }
80 |
81 | func (m *DirectMessageCreate) GetSourceAppId() string {
82 | if m != nil {
83 | return m.SourceAppId
84 | }
85 | return ""
86 | }
87 |
88 | func (m *DirectMessageCreate) GetMessageData() *DirectMessageData {
89 | if m != nil {
90 | return m.MessageData
91 | }
92 | return nil
93 | }
94 |
95 | type DirectMessageEvent struct {
96 | Type string `protobuf:"bytes,1,opt,name=type" json:"type,omitempty"`
97 | Id string `protobuf:"bytes,2,opt,name=id" json:"id,omitempty"`
98 | CreatedTimestamp string `protobuf:"bytes,3,opt,name=created_timestamp,json=createdTimestamp" json:"created_timestamp,omitempty"`
99 | MessageCreate *DirectMessageCreate `protobuf:"bytes,4,opt,name=message_create,json=messageCreate" json:"message_create,omitempty"`
100 | }
101 |
102 | func (m *DirectMessageEvent) Reset() { *m = DirectMessageEvent{} }
103 | func (m *DirectMessageEvent) String() string { return proto.CompactTextString(m) }
104 | func (*DirectMessageEvent) ProtoMessage() {}
105 | func (*DirectMessageEvent) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{3} }
106 |
107 | func (m *DirectMessageEvent) GetType() string {
108 | if m != nil {
109 | return m.Type
110 | }
111 | return ""
112 | }
113 |
114 | func (m *DirectMessageEvent) GetId() string {
115 | if m != nil {
116 | return m.Id
117 | }
118 | return ""
119 | }
120 |
121 | func (m *DirectMessageEvent) GetCreatedTimestamp() string {
122 | if m != nil {
123 | return m.CreatedTimestamp
124 | }
125 | return ""
126 | }
127 |
128 | func (m *DirectMessageEvent) GetMessageCreate() *DirectMessageCreate {
129 | if m != nil {
130 | return m.MessageCreate
131 | }
132 | return nil
133 | }
134 |
135 | func init() {
136 | proto.RegisterType((*Target)(nil), "grain.twitter.Target")
137 | proto.RegisterType((*DirectMessageData)(nil), "grain.twitter.DirectMessageData")
138 | proto.RegisterType((*DirectMessageCreate)(nil), "grain.twitter.DirectMessageCreate")
139 | proto.RegisterType((*DirectMessageEvent)(nil), "grain.twitter.DirectMessageEvent")
140 | }
141 |
142 | func init() { proto.RegisterFile("twitter/dm.proto", fileDescriptor1) }
143 |
144 | var fileDescriptor1 = []byte{
145 | // 335 bytes of a gzipped FileDescriptorProto
146 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xcf, 0x6a, 0xc2, 0x40,
147 | 0x10, 0x87, 0x49, 0x2a, 0xa2, 0x13, 0x15, 0xdd, 0xb6, 0x54, 0xda, 0x8b, 0xcd, 0x49, 0x90, 0xa6,
148 | 0xa0, 0x4f, 0xd0, 0xaa, 0x87, 0x1c, 0x7a, 0x09, 0x9e, 0x4a, 0x21, 0xac, 0xd9, 0x41, 0xf6, 0x90,
149 | 0xb8, 0xec, 0x4e, 0xff, 0xf8, 0x56, 0x7d, 0x8e, 0x3e, 0x55, 0x71, 0x77, 0x4d, 0xab, 0x85, 0xde,
150 | 0xb2, 0xbf, 0xf9, 0x98, 0xf9, 0x66, 0x08, 0xf4, 0xe9, 0x5d, 0x12, 0xa1, 0xbe, 0x17, 0x65, 0xa2,
151 | 0xf4, 0x96, 0xb6, 0xac, 0xbb, 0xd1, 0x5c, 0x56, 0x89, 0xcf, 0xaf, 0x2f, 0x0e, 0x00, 0x56, 0x24,
152 | 0x69, 0xe7, 0xa0, 0x78, 0x02, 0xcd, 0x15, 0xd7, 0x1b, 0x24, 0x76, 0x0b, 0x1d, 0x8d, 0x85, 0x54,
153 | 0x12, 0x2b, 0xca, 0xa5, 0x18, 0x06, 0xa3, 0x60, 0xdc, 0xce, 0xa2, 0x3a, 0x4b, 0x45, 0xfc, 0x02,
154 | 0x83, 0x85, 0xd4, 0x58, 0xd0, 0x13, 0x1a, 0xc3, 0x37, 0xb8, 0xe0, 0xc4, 0x19, 0x83, 0x06, 0xe1,
155 | 0x07, 0x79, 0xde, 0x7e, 0xb3, 0x19, 0xb4, 0xec, 0x14, 0x89, 0x66, 0x18, 0x8e, 0x82, 0x71, 0x34,
156 | 0xbd, 0x4a, 0x8e, 0x6c, 0x92, 0xa5, 0x2f, 0x67, 0x35, 0x18, 0x7f, 0x05, 0x70, 0x7e, 0xd4, 0x7e,
157 | 0xae, 0x91, 0x13, 0xb2, 0x3b, 0x68, 0x92, 0x55, 0xb4, 0x23, 0xa2, 0xe9, 0xe5, 0x49, 0x2b, 0xe7,
158 | 0x9f, 0x79, 0x88, 0xdd, 0x40, 0xdb, 0x60, 0x25, 0x50, 0xef, 0x97, 0x08, 0xad, 0x54, 0xcb, 0x05,
159 | 0xa9, 0x60, 0x31, 0x74, 0xcd, 0xf6, 0x55, 0x17, 0x98, 0x73, 0xa5, 0xf6, 0xc0, 0x99, 0xdb, 0xd2,
160 | 0x85, 0x0f, 0x4a, 0xa5, 0x82, 0xcd, 0xa1, 0x53, 0x3a, 0x81, 0x5c, 0x70, 0xe2, 0xc3, 0x86, 0x9d,
161 | 0x3a, 0x3a, 0x99, 0xfa, 0xe7, 0x10, 0x59, 0x54, 0xfe, 0x3c, 0xe2, 0xcf, 0x00, 0xd8, 0x11, 0xb2,
162 | 0x7c, 0xc3, 0x8a, 0xec, 0xb1, 0x76, 0x0a, 0xeb, 0x63, 0xed, 0x14, 0xb2, 0x1e, 0x84, 0xb5, 0x69,
163 | 0x28, 0x05, 0x9b, 0xc0, 0xa0, 0xb0, 0x9b, 0x8b, 0x9c, 0x64, 0x89, 0x86, 0x78, 0xa9, 0xbc, 0x67,
164 | 0xdf, 0x17, 0x56, 0x87, 0x9c, 0xa5, 0xd0, 0x3b, 0xc8, 0xba, 0x9a, 0xd7, 0x8d, 0xff, 0xd3, 0x75,
165 | 0x87, 0xcd, 0xba, 0xe5, 0xef, 0xe7, 0x63, 0xf4, 0xdc, 0xf6, 0xb4, 0x5a, 0xaf, 0x9b, 0xf6, 0xf7,
166 | 0x98, 0x7d, 0x07, 0x00, 0x00, 0xff, 0xff, 0xab, 0xe9, 0x16, 0x97, 0x57, 0x02, 0x00, 0x00,
167 | }
168 |
--------------------------------------------------------------------------------
/gen/twitter/list.pb.go:
--------------------------------------------------------------------------------
1 | // Code generated by protoc-gen-go. DO NOT EDIT.
2 | // source: twitter/list.proto
3 |
4 | package twitterpb
5 |
6 | import proto "github.com/golang/protobuf/proto"
7 | import fmt "fmt"
8 | import math "math"
9 |
10 | // Reference imports to suppress errors if they are not otherwise used.
11 | var _ = proto.Marshal
12 | var _ = fmt.Errorf
13 | var _ = math.Inf
14 |
15 | type List struct {
16 | Slug string `protobuf:"bytes,1,opt,name=slug" json:"slug,omitempty"`
17 | Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
18 | Uri string `protobuf:"bytes,3,opt,name=uri" json:"uri,omitempty"`
19 | CreatedAt string `protobuf:"bytes,4,opt,name=created_at,json=createdAt" json:"created_at,omitempty"`
20 | Id int64 `protobuf:"varint,5,opt,name=id" json:"id,omitempty"`
21 | SubscriberCount int64 `protobuf:"varint,6,opt,name=subscriber_count,json=subscriberCount" json:"subscriber_count,omitempty"`
22 | MemberCount int64 `protobuf:"varint,7,opt,name=member_count,json=memberCount" json:"member_count,omitempty"`
23 | Mode string `protobuf:"bytes,8,opt,name=mode" json:"mode,omitempty"`
24 | FullName string `protobuf:"bytes,9,opt,name=full_name,json=fullName" json:"full_name,omitempty"`
25 | Description string `protobuf:"bytes,10,opt,name=description" json:"description,omitempty"`
26 | User *User `protobuf:"bytes,11,opt,name=user" json:"user,omitempty"`
27 | Following bool `protobuf:"varint,12,opt,name=following" json:"following,omitempty"`
28 | Members []*User `protobuf:"bytes,13,rep,name=members" json:"members,omitempty"`
29 | }
30 |
31 | func (m *List) Reset() { *m = List{} }
32 | func (m *List) String() string { return proto.CompactTextString(m) }
33 | func (*List) ProtoMessage() {}
34 | func (*List) Descriptor() ([]byte, []int) { return fileDescriptor3, []int{0} }
35 |
36 | func (m *List) GetSlug() string {
37 | if m != nil {
38 | return m.Slug
39 | }
40 | return ""
41 | }
42 |
43 | func (m *List) GetName() string {
44 | if m != nil {
45 | return m.Name
46 | }
47 | return ""
48 | }
49 |
50 | func (m *List) GetUri() string {
51 | if m != nil {
52 | return m.Uri
53 | }
54 | return ""
55 | }
56 |
57 | func (m *List) GetCreatedAt() string {
58 | if m != nil {
59 | return m.CreatedAt
60 | }
61 | return ""
62 | }
63 |
64 | func (m *List) GetId() int64 {
65 | if m != nil {
66 | return m.Id
67 | }
68 | return 0
69 | }
70 |
71 | func (m *List) GetSubscriberCount() int64 {
72 | if m != nil {
73 | return m.SubscriberCount
74 | }
75 | return 0
76 | }
77 |
78 | func (m *List) GetMemberCount() int64 {
79 | if m != nil {
80 | return m.MemberCount
81 | }
82 | return 0
83 | }
84 |
85 | func (m *List) GetMode() string {
86 | if m != nil {
87 | return m.Mode
88 | }
89 | return ""
90 | }
91 |
92 | func (m *List) GetFullName() string {
93 | if m != nil {
94 | return m.FullName
95 | }
96 | return ""
97 | }
98 |
99 | func (m *List) GetDescription() string {
100 | if m != nil {
101 | return m.Description
102 | }
103 | return ""
104 | }
105 |
106 | func (m *List) GetUser() *User {
107 | if m != nil {
108 | return m.User
109 | }
110 | return nil
111 | }
112 |
113 | func (m *List) GetFollowing() bool {
114 | if m != nil {
115 | return m.Following
116 | }
117 | return false
118 | }
119 |
120 | func (m *List) GetMembers() []*User {
121 | if m != nil {
122 | return m.Members
123 | }
124 | return nil
125 | }
126 |
127 | func init() {
128 | proto.RegisterType((*List)(nil), "grain.twitter.List")
129 | }
130 |
131 | func init() { proto.RegisterFile("twitter/list.proto", fileDescriptor3) }
132 |
133 | var fileDescriptor3 = []byte{
134 | // 299 bytes of a gzipped FileDescriptorProto
135 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0xbd, 0x4e, 0xc3, 0x30,
136 | 0x14, 0x85, 0x95, 0x26, 0xb4, 0xf5, 0x4d, 0x0b, 0xd5, 0x65, 0xb1, 0xf8, 0x91, 0x0c, 0x0b, 0x61,
137 | 0x20, 0x48, 0xf0, 0x04, 0xc0, 0x8a, 0x18, 0x22, 0xb1, 0xb0, 0x54, 0x49, 0xe3, 0x56, 0x96, 0x9c,
138 | 0xb8, 0xf2, 0x8f, 0xfa, 0x06, 0x3c, 0x37, 0xb2, 0x1d, 0x08, 0x0c, 0x6c, 0x47, 0xdf, 0xf9, 0x94,
139 | 0x1c, 0x5d, 0x03, 0xda, 0x83, 0xb0, 0x96, 0xeb, 0x7b, 0x29, 0x8c, 0x2d, 0xf7, 0x5a, 0x59, 0x85,
140 | 0xcb, 0x9d, 0xae, 0x45, 0x5f, 0x0e, 0xcd, 0xd9, 0x8f, 0xe2, 0x0c, 0xd7, 0x51, 0xb9, 0xfe, 0x4c,
141 | 0x21, 0x7b, 0x15, 0xc6, 0x22, 0x42, 0x66, 0xa4, 0xdb, 0xd1, 0x84, 0x25, 0x05, 0xa9, 0x42, 0xf6,
142 | 0xac, 0xaf, 0x3b, 0x4e, 0x27, 0x91, 0xf9, 0x8c, 0x2b, 0x48, 0x9d, 0x16, 0x34, 0x0d, 0xc8, 0x47,
143 | 0xbc, 0x04, 0xd8, 0x68, 0x5e, 0x5b, 0xde, 0xae, 0x6b, 0x4b, 0xb3, 0x50, 0x90, 0x81, 0x3c, 0x59,
144 | 0x3c, 0x86, 0x89, 0x68, 0xe9, 0x11, 0x4b, 0x8a, 0xb4, 0x9a, 0x88, 0x16, 0x6f, 0x61, 0x65, 0x5c,
145 | 0x63, 0x36, 0x5a, 0x34, 0x5c, 0xaf, 0x37, 0xca, 0xf5, 0x96, 0x4e, 0x43, 0x7b, 0x32, 0xf2, 0x17,
146 | 0x8f, 0xf1, 0x0a, 0x16, 0x1d, 0xef, 0x46, 0x6d, 0x16, 0xb4, 0x3c, 0xb2, 0xa8, 0x20, 0x64, 0x9d,
147 | 0x6a, 0x39, 0x9d, 0xc7, 0x89, 0x3e, 0xe3, 0x39, 0x90, 0xad, 0x93, 0x72, 0x1d, 0xb6, 0x93, 0x50,
148 | 0xcc, 0x3d, 0x78, 0xf3, 0xfb, 0x19, 0xe4, 0x2d, 0xf7, 0x7f, 0xd9, 0x5b, 0xa1, 0x7a, 0x0a, 0xa1,
149 | 0xfe, 0x8d, 0xf0, 0x06, 0x32, 0x7f, 0x20, 0x9a, 0xb3, 0xa4, 0xc8, 0x1f, 0x4e, 0xcb, 0x3f, 0x47,
150 | 0x2c, 0xdf, 0x0d, 0xd7, 0x55, 0x10, 0xf0, 0x02, 0xc8, 0x56, 0x49, 0xa9, 0x0e, 0xa2, 0xdf, 0xd1,
151 | 0x05, 0x4b, 0x8a, 0x79, 0x35, 0x02, 0xbc, 0x83, 0x59, 0x1c, 0x6a, 0xe8, 0x92, 0xa5, 0xff, 0x7d,
152 | 0xe9, 0xdb, 0x79, 0xce, 0x3f, 0xc8, 0x50, 0xec, 0x9b, 0x66, 0x1a, 0x1e, 0xe7, 0xf1, 0x2b, 0x00,
153 | 0x00, 0xff, 0xff, 0x98, 0x54, 0xe2, 0xff, 0xd5, 0x01, 0x00, 0x00,
154 | }
155 |
--------------------------------------------------------------------------------
/proto/facebook/archive.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | import "facebook/photo.proto";
4 | import "facebook/user.proto";
5 |
6 | package grain.facebook;
7 |
8 | option go_package = "facebookpb";
9 |
10 | message Archive {
11 | User me = 1;
12 | repeated Photo photos = 2;
13 | repeated Album albums = 3;
14 | repeated User friends = 4;
15 | }
16 |
--------------------------------------------------------------------------------
/proto/facebook/download/about_you.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grain.facebook.download;
4 |
5 | message AddressBook {
6 | message Details {
7 | string contact_point = 1;
8 | }
9 | message Contact {
10 | string name = 1;
11 | repeated Details details = 2;
12 | }
13 | message AddressBookEntry {
14 | repeated Contact address_book = 1;
15 | }
16 | AddressBookEntry address_book = 1;
17 | }
18 |
--------------------------------------------------------------------------------
/proto/facebook/download/ads.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grain.facebook.download;
4 |
5 | message Ads {
6 | message History {
7 | string title = 1;
8 | string action = 2;
9 | int64 timestamp = 3; // TODO: timestamp
10 | }
11 | repeated string topics = 1;
12 | repeated string custom_audiences = 2;
13 | repeated string lead_gen_info = 3;
14 | repeated History history = 4;
15 | }
16 |
--------------------------------------------------------------------------------
/proto/facebook/download/apps.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grain.facebook.download;
4 |
5 | message InstalledApps {
6 | message App {
7 | string name = 1;
8 | int64 time_added = 2; // TODO: timestamp
9 | }
10 | repeated App installed_apps = 1;
11 | }
12 |
13 | // Stored as an array, not a top level message
14 | message PostsFromApps {
15 | message ExternalContext {
16 | string name = 1;
17 | string url = 2;
18 | }
19 | message Data {
20 | ExternalContext external_context = 1;
21 | }
22 | message Attachment {
23 | repeated Data data = 1;
24 | }
25 | message Post {
26 | int64 timestamp = 1; // TODO: timestamp
27 | repeated Attachment attachments = 2;
28 | }
29 | repeated Post posts = 1;
30 | }
31 |
32 | message YourApps {
33 | message App {
34 | string name = 1;
35 | int64 time_added = 2; // TODO: timestamp
36 | }
37 | repeated App admined_apps = 1;
38 | }
39 |
--------------------------------------------------------------------------------
/proto/facebook/download/comments.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grain.facebook.download;
4 |
5 | message Comment {
6 | int64 timestamp = 1; // TODO: timestamp
7 | string comment = 2;
8 | string author = 3;
9 | string group = 4;
10 | }
11 |
12 | message PhotoMetadata {
13 | int64 iso_speed = 1;
14 | int64 orientation = 2;
15 | int64 original_width = 3;
16 | int64 original_height = 4;
17 | string upload_ip = 5;
18 | string camera_make = 6;
19 | string camera_model = 7;
20 | int64 taken_timestamp = 8;
21 | int64 modified_timestamp = 9;
22 | string exposure = 10;
23 | string focal_length = 11;
24 | string f_stop = 12;
25 | }
26 |
27 | message MediaMetadata {
28 | repeated PhotoMetadata photo_metadata = 1;
29 | }
30 |
31 | message Media {
32 | string uri = 1;
33 | string media_path = 2;
34 | int64 creation_timestamp = 3;
35 | MediaMetadata media_metadata = 4;
36 | repeated Comment comments = 5;
37 | }
38 |
39 | message AttachmentData {
40 | Media media = 1;
41 | }
42 |
43 | message Attachment {
44 | repeated AttachmentData data = 1;
45 | }
46 |
47 | message Post {
48 | message Data {
49 | string post = 1;
50 | Comment comment = 2;
51 | }
52 | int64 timestamp = 1; // TODO: timestamp
53 | string title = 2;
54 | repeated Data data = 3;
55 | repeated Attachment attachments = 4;
56 | }
57 |
58 | // Stored as an array, not a top level message
59 | message YourPosts {
60 | repeated Post posts = 1;
61 | }
62 |
--------------------------------------------------------------------------------
/proto/facebook/download/events.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grain.facebook.download;
4 |
5 | message Coordinate {
6 | float longitude = 1;
7 | float latitude = 2;
8 | }
9 |
10 | message Event {
11 | message Place {
12 | string name = 1;
13 | Coordinate coordinate = 2;
14 | string address = 3;
15 | }
16 | string name = 1;
17 | int64 start_timestamp = 2; // TODO: timestamp
18 | int64 end_timestamp = 3; // TODO: timestamp
19 | string description = 4;
20 | }
21 |
22 | message EventInvitations {
23 | repeated Event events_invited = 1;
24 | }
25 |
26 | message EventResponses {
27 | message Joined {
28 | repeated Event events_joined = 1;
29 | }
30 | Joined event_responses = 1;
31 | }
32 |
33 | message YourEvents {
34 | repeated Event your_events = 1;
35 | }
36 |
--------------------------------------------------------------------------------
/proto/facebook/download/following_and_followers.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grain.facebook.download;
4 |
5 | // Stored as an array, not a top level message
6 | message FollowedPages {
7 | message Data {
8 | string name = 1;
9 | }
10 | message Page {
11 | string title = 1;
12 | int64 timestamp = 2; // TODO: timestamp
13 | repeated Data data = 3;
14 | }
15 | repeated Page pages = 1;
16 | }
17 |
--------------------------------------------------------------------------------
/proto/facebook/download/friends.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grain.facebook.download;
4 |
5 | message Friend {
6 | string name = 1;
7 | int64 timestamp = 2; // TODO: timestamp
8 | }
9 |
10 | message FriendsAdded {
11 | repeated Friend friends = 1;
12 | }
13 |
14 | message RejectedRequests {
15 | repeated Friend rejected_requests = 1;
16 | }
17 |
18 | message RemovedFriends {
19 | repeated Friend deleted_friends = 1;
20 | }
21 |
22 | message SentRequests {
23 | repeated Friend sent_requests = 1;
24 | }
25 |
--------------------------------------------------------------------------------
/proto/facebook/download/groups.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | import "facebook/download/comments.proto";
4 |
5 | package grain.facebook.download;
6 |
7 | message GroupsYouManage {
8 | message Group {
9 | repeated string groups = 1;
10 | }
11 | Group groups_you_manage = 1;
12 | }
13 |
14 | // Stored as a top-level array
15 | message GroupMembershipActivity {
16 | message Data {
17 | string name = 1;
18 | }
19 | message Attachment {
20 | repeated Data data = 1;
21 | }
22 | message Group {
23 | int64 timestamp = 1; // TODO: timestamp
24 | string title = 2;
25 | repeated Attachment attachments = 3;
26 | }
27 | repeated Group membership_activity = 1;
28 | }
29 |
30 | // Stored as a top-level array
31 | message GroupPostsComments {
32 | repeated Post comments = 1;
33 | }
34 |
--------------------------------------------------------------------------------
/proto/facebook/node.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grain.facebook;
4 |
5 | option go_package = "facebookpb";
6 |
7 | message Node {
8 | string id = 1;
9 | }
10 |
--------------------------------------------------------------------------------
/proto/facebook/photo.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grain.facebook;
4 |
5 | option go_package = "facebookpb";
6 |
7 | message Owner {
8 | string name = 1;
9 | string id = 2;
10 | }
11 |
12 | message Location {
13 | string city = 1;
14 | string country = 2;
15 | float latitude = 3;
16 | float longitude = 4;
17 | }
18 |
19 | message Place {
20 | string id = 1;
21 | // The name of the Page
22 | string name = 2;
23 | // The location of this place. Applicable to all Places
24 | Location location = 3;
25 | }
26 |
27 | message Album {
28 | string id = 1;
29 | // A user-specified time for when this object was created
30 | string backdated_time = 2;
31 | // How accurate the backdated time is
32 | string backdated_time_granularity = 3;
33 | // Whether the viewer can backdate this album
34 | bool can_backdate = 4;
35 | // Whether the viewer can upload photos to this album
36 | bool can_upload = 5;
37 | // The approximate number of photos in the album. This is not necessarily an exact count
38 | uint32 count = 6;
39 | uint32 photo_count = 18;
40 | // Album cover photo id
41 | Photo cover_photo = 7;
42 | // The time the album was initially created
43 | string created_time = 8;
44 | // The description of the album
45 | string description = 9;
46 | // The URL for editing this album
47 | string edit_link = 10;
48 | // If this object has a place, the event associated with the place
49 | // string event = 11;
50 | // The profile that created the album
51 | Owner from = 12;
52 | // Determines whether or not the album should be shown to users
53 | bool is_user_facing = 13;
54 | // A link to this album on Facebook
55 | string link = 14;
56 | // The textual location of the album"
57 | string location = 15;
58 | // Time of the last major update (e.g. addition of photos) expressed as UNIX time
59 | string modified_major = 16;
60 | // The title of the album
61 | string name = 17;
62 | // The place associated with this album
63 | Place place = 19;
64 | // The privacy settings for the album
65 | string privacy = 20;
66 | // The type of the album: profile, mobile, wall, normal or album
67 | string type = 21;
68 | // The last time the album was updated
69 | string updated_time = 22;
70 | // The approximate number of videos in the album. This is not necessarily an exact count
71 | uint32 video_count = 23;
72 | }
73 |
74 | message Image {
75 | int32 height = 1;
76 | int32 width = 2;
77 | string source = 3;
78 | }
79 |
80 | message Photo {
81 | string id = 1;
82 | Album album = 2;
83 | // A user-specified time for when this object was created
84 | string backdated_time = 3;
85 | // How accurate the backdated time is
86 | string backdated_time_granularity = 4;
87 | bool can_backdate = 5;
88 | bool can_delete = 6;
89 | bool can_tag = 7;
90 | string created_time = 8;
91 | Owner from = 10;
92 | int32 height = 11;
93 | int32 width = 12;
94 | string icon = 13;
95 | repeated Image images = 14;
96 | string name = 15;
97 | // "link",
98 | // "name_tags",
99 | // "page_story_id",
100 | // "picture",
101 | // "place",
102 | // "target",
103 | // "updated_time",
104 | // "webp_images",
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/proto/facebook/user.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grain.facebook;
4 |
5 | option go_package = "facebookpb";
6 |
7 | message User {
8 | string id = 1;
9 | string birthday = 2;
10 | }
11 |
--------------------------------------------------------------------------------
/proto/prototool.yaml:
--------------------------------------------------------------------------------
1 | # The Protobuf version to use from https://github.com/google/protobuf/releases.
2 | # By default use 3.5.1.
3 | # You probably want to set this to make your builds completely reproducible.
4 | protoc_version: 3.5.1
5 | gen:
6 | go_options:
7 | import_path: github.com/kyleconroy/grain/gen
8 | plugins:
9 | - name: go
10 | output: ../gen
11 |
--------------------------------------------------------------------------------
/proto/twitter/archive.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | import "twitter/dm.proto";
4 | import "twitter/list.proto";
5 | import "twitter/tweet.proto";
6 | import "twitter/user.proto";
7 |
8 | package grain.twitter;
9 |
10 | option go_package = "twitterpb";
11 |
12 | message Archive {
13 | repeated List lists = 1;
14 | repeated User friends = 2;
15 | repeated User followers = 3;
16 | repeated Tweet timeline = 4;
17 | repeated Tweet favorites = 5;
18 | repeated DirectMessageEvent direct_messages = 6;
19 | }
20 |
--------------------------------------------------------------------------------
/proto/twitter/dm.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | import "twitter/entity.proto";
4 |
5 | package grain.twitter;
6 |
7 | option go_package = "twitterpb";
8 |
9 | message Target {
10 | string recipient_id = 1;
11 | }
12 |
13 | message DirectMessageData {
14 | string text = 1;
15 | Entities entities = 2;
16 | }
17 |
18 | message DirectMessageCreate {
19 | Target target = 1;
20 | string sender_id = 2;
21 | string source_app_id = 3;
22 | DirectMessageData message_data = 4;
23 | }
24 |
25 | message DirectMessageEvent {
26 | string type = 1;
27 | string id = 2;
28 | string created_timestamp = 3;
29 | DirectMessageCreate message_create = 4;
30 | }
31 |
--------------------------------------------------------------------------------
/proto/twitter/entity.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package grain.twitter;
4 |
5 | option go_package = "twitterpb";
6 |
7 | message Url {
8 | repeated int64 indices = 1;
9 | string url = 2;
10 | string display_url = 3;
11 | string expanded_url = 4;
12 | }
13 |
14 | message Hashtag {
15 | repeated int64 indices = 1;
16 | string text = 2;
17 | }
18 |
19 | message UserMention {
20 | reserved "id_str";
21 | repeated int64 indices = 1;
22 | string name = 2;
23 | string screen_name = 3;
24 | int64 id = 4;
25 | }
26 |
27 | message MediaSize {
28 | int32 w = 1;
29 | int32 h = 2;
30 | string resize = 3;
31 | }
32 |
33 | message MediaSizes {
34 | MediaSize medium = 1;
35 | MediaSize thumb = 2;
36 | MediaSize small = 3;
37 | MediaSize large = 4;
38 | }
39 |
40 | message Variant {
41 | int32 bitrate = 1;
42 | string content_type = 2;
43 | string url = 3;
44 | }
45 |
46 | message VideoInfo {
47 | repeated int32 aspect_ratio = 1;
48 | int64 duration_millis = 2;
49 | repeated Variant variants = 3;
50 | }
51 |
52 | message EntityMedia {
53 | reserved "id_str", "source_status_id_str";
54 | int64 id = 1;
55 | string media_url = 2;
56 | string media_url_https = 3;
57 | string url = 4;
58 | string display_url = 5;
59 | string expanded_url = 6;
60 | MediaSizes sizes = 7;
61 | int64 source_status_id = 8;
62 | string type = 9;
63 | repeated int64 indices = 10;
64 | VideoInfo video_info = 11;
65 | string ext_alt_text = 12;
66 | }
67 |
68 | message Entities {
69 | repeated Url urls = 1;
70 | repeated Hashtag hashtags = 2;
71 | Url url = 3;
72 | repeated UserMention user_mentions = 4;
73 | repeated EntityMedia media = 5;
74 | }
75 |
--------------------------------------------------------------------------------
/proto/twitter/list.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | import "twitter/user.proto";
4 |
5 | package grain.twitter;
6 |
7 | option go_package = "twitterpb";
8 |
9 | message List {
10 | string slug = 1;
11 | string name = 2;
12 | string uri = 3;
13 | string created_at = 4;
14 | int64 id = 5;
15 | int64 subscriber_count = 6;
16 | int64 member_count = 7;
17 | string mode = 8;
18 | string full_name = 9;
19 | string description = 10;
20 | User user = 11;
21 | bool following = 12;
22 | repeated User members = 13;
23 | }
24 |
--------------------------------------------------------------------------------
/proto/twitter/tweet.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | import "twitter/entity.proto";
4 | import "twitter/user.proto";
5 |
6 | package grain.twitter;
7 |
8 | option go_package = "twitterpb";
9 |
10 | message Place {}
11 |
12 | message Coordinates {}
13 |
14 | message ExtendedTweet {}
15 |
16 | message Tweet {
17 | reserved "id_str", "in_reply_to_status_id_str", "in_reply_to_user_id_str", "quoted_status_id_str";
18 | repeated int64 contributors = 1;
19 | Coordinates coordinates = 2;
20 | string created_at = 3;
21 | repeated int32 display_text_range = 4;
22 | Entities entities = 5;
23 | Entities extended_entities = 6;
24 | ExtendedTweet extended_tweet = 7;
25 | int32 favorite_count = 8;
26 | bool favorited = 9;
27 | string filter_level = 10;
28 | string full_text = 11;
29 | bool has_extended_profile = 12;
30 | int64 id = 13;
31 | string in_reply_to_screen_name = 14;
32 | int64 in_reply_to_status_id = 15;
33 | int64 in_reply_to_user_id = 16;
34 | string lang = 17;
35 | bool is_translation_enabled = 18;
36 | Place place = 19;
37 | int64 quoted_status_id = 20;
38 | Tweet quoted_status = 21;
39 | bool possibly_sensitive = 22;
40 | bool possibly_sensitive_appealable = 23;
41 | int32 retweet_count = 24;
42 | bool retweeted = 25;
43 | Tweet retweeted_status = 26;
44 | string source = 27;
45 | // map[string]interface{} scopes = 28;
46 | string text = 29;
47 | User user = 30;
48 | bool withheld_copyright = 31;
49 | repeated string withheld_in_countries = 32;
50 | string withheld_scope = 33;
51 | }
52 |
--------------------------------------------------------------------------------
/proto/twitter/user.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | import "twitter/entity.proto";
4 |
5 | package grain.twitter;
6 |
7 | option go_package = "twitterpb";
8 |
9 | message User {
10 | reserved "id_str";
11 | bool contributors_enabled = 1;
12 | string created_at = 2;
13 | bool default_profile = 3;
14 | bool default_profile_image = 4;
15 | string description = 5;
16 | string email = 6;
17 | Entities entities = 7;
18 | int64 favourites_count = 8;
19 | bool follow_request_sent = 9;
20 | int64 followers_count = 10;
21 | bool following = 11;
22 | int64 friends_count = 12;
23 | bool geo_enabled = 13;
24 | bool has_extended_profile = 14;
25 | int64 id = 15;
26 | bool is_translator = 17;
27 | bool is_translation_enabled = 18;
28 | string lang = 19; // BCP-47 code of user defined language
29 | int64 listed_count = 20;
30 | string location = 21; // User defined location
31 | string name = 22;
32 | bool notifications = 23;
33 | string profile_background_color = 24;
34 | string profile_background_image_url = 25;
35 | string profile_background_image_url_https = 26;
36 | bool profile_background_tile = 27;
37 | string profile_banner_url = 28;
38 | string profile_image_url = 29;
39 | string profile_image_url_https = 30;
40 | string profile_link_color = 31;
41 | string profile_sidebar_border_color = 32;
42 | string profile_sidebar_fill_color = 33;
43 | string profile_text_color = 34;
44 | bool profile_use_background_image = 35;
45 | bool protected = 37;
46 | string screen_name = 38;
47 | bool show_all_inline_media = 39;
48 | // Tweet status = 40; // Only included if the user is a friend
49 | int64 statuses_count = 41;
50 | string time_zone = 42;
51 | string url = 43;
52 | int64 utc_offset = 44;
53 | bool verified = 45;
54 | repeated string withheld_in_countries = 46;
55 | string withheld_scope = 47;
56 | }
57 |
--------------------------------------------------------------------------------
/twitter/csv.go:
--------------------------------------------------------------------------------
1 | package twitter
2 |
3 | import (
4 | "encoding/csv"
5 | "io"
6 | "strconv"
7 | "strings"
8 | "time"
9 | )
10 |
11 | type CSVTweet struct {
12 | TweetID int64
13 | InReplyToStatusID int64
14 | InReplyToUserID int64
15 | Timestamp time.Time
16 | Source string
17 | Text string
18 | RetweetedStatusID int64
19 | RetweetedStatusUserID int64
20 | RetweetedStatusTimestamp time.Time
21 | ExpandedURLs []string
22 | }
23 |
24 | type Reader struct {
25 | r *csv.Reader
26 | skipped bool
27 | }
28 |
29 | func parseInt(i string) (int64, error) {
30 | if i == "" {
31 | return 0, nil
32 | }
33 | return strconv.ParseInt(i, 10, 64)
34 | }
35 |
36 | func NewCSVReader(in io.Reader) *Reader {
37 | return &Reader{r: csv.NewReader(in)}
38 | }
39 |
40 | func (c *Reader) Read() (r CSVTweet, err error) {
41 | record, err := c.r.Read()
42 | if !c.skipped {
43 | record, err = c.r.Read()
44 | c.skipped = true
45 | }
46 |
47 | if err != nil {
48 | return CSVTweet{}, err
49 | }
50 |
51 | r.TweetID, err = parseInt(record[0])
52 | if err != nil {
53 | return
54 | }
55 |
56 | r.InReplyToStatusID, err = parseInt(record[1])
57 | if err != nil {
58 | return
59 | }
60 |
61 | r.InReplyToUserID, err = parseInt(record[2])
62 | if err != nil {
63 | return
64 | }
65 |
66 | if record[3] != "" {
67 | r.Timestamp, err = time.Parse("2006-01-02 15:04:05 -0700", record[3])
68 | if err != nil {
69 | return
70 | }
71 | }
72 |
73 | r.RetweetedStatusID, err = parseInt(record[6])
74 | if err != nil {
75 | return
76 | }
77 |
78 | r.RetweetedStatusUserID, err = parseInt(record[7])
79 | if err != nil {
80 | return
81 | }
82 |
83 | if record[8] != "" {
84 | r.RetweetedStatusTimestamp, err = time.Parse("2006-01-02 15:04:05 -0700", record[8])
85 | if err != nil {
86 | return
87 | }
88 | }
89 |
90 | r.Source = record[4]
91 | r.Text = record[5]
92 | r.ExpandedURLs = strings.Split(record[0], ",")
93 |
94 | return
95 | }
96 |
--------------------------------------------------------------------------------
/twitter/errors.go:
--------------------------------------------------------------------------------
1 | package twitter
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "io/ioutil"
7 | "net/http"
8 | "net/url"
9 | "strconv"
10 | "time"
11 | )
12 |
13 | const (
14 | //Error code defintions match the Twitter documentation
15 | //https://developer.twitter.com/en/docs/basics/response-codes
16 | TwitterErrorCouldNotAuthenticate = 32
17 | TwitterErrorDoesNotExist = 34
18 | TwitterErrorAccountSuspended = 64
19 | TwitterErrorApi1Deprecation = 68 //This should never be needed
20 | TwitterErrorRateLimitExceeded = 88
21 | TwitterErrorInvalidToken = 89
22 | TwitterErrorOverCapacity = 130
23 | TwitterErrorInternalError = 131
24 | TwitterErrorCouldNotAuthenticateYou = 135
25 | TwitterErrorStatusIsADuplicate = 187
26 | TwitterErrorBadAuthenticationData = 215
27 | TwitterErrorUserMustVerifyLogin = 231
28 |
29 | // Undocumented by Twitter, but may be returned instead of 34
30 | TwitterErrorDoesNotExist2 = 144
31 | )
32 |
33 | type ApiError struct {
34 | StatusCode int
35 | Header http.Header
36 | Body string
37 | Decoded TwitterErrorResponse
38 | URL *url.URL
39 | }
40 |
41 | func newApiError(resp *http.Response) *ApiError {
42 | // TODO don't ignore this error
43 | // TODO don't use ReadAll
44 | p, _ := ioutil.ReadAll(resp.Body)
45 |
46 | var twitterErrorResp TwitterErrorResponse
47 | _ = json.Unmarshal(p, &twitterErrorResp)
48 | return &ApiError{
49 | StatusCode: resp.StatusCode,
50 | Header: resp.Header,
51 | Body: string(p),
52 | Decoded: twitterErrorResp,
53 | URL: resp.Request.URL,
54 | }
55 | }
56 |
57 | // ApiError supports the error interface
58 | func (aerr ApiError) Error() string {
59 | return fmt.Sprintf("Get %s returned status %d, %s", aerr.URL, aerr.StatusCode, aerr.Body)
60 | }
61 |
62 | // Check to see if an error is a Rate Limiting error. If so, find the next available window in the header.
63 | // Use like so:
64 | //
65 | // if aerr, ok := err.(*ApiError); ok {
66 | // if isRateLimitError, nextWindow := aerr.RateLimitCheck(); isRateLimitError {
67 | // <-time.After(nextWindow.Sub(time.Now()))
68 | // }
69 | // }
70 | //
71 | func (aerr *ApiError) RateLimitCheck() (isRateLimitError bool, nextWindow time.Time) {
72 | // TODO check for error code 130, which also signifies a rate limit
73 | if aerr.StatusCode == 429 {
74 | if reset := aerr.Header.Get("X-Rate-Limit-Reset"); reset != "" {
75 | if resetUnix, err := strconv.ParseInt(reset, 10, 64); err == nil {
76 | resetTime := time.Unix(resetUnix, 0)
77 | // Reject any time greater than an hour away
78 | if resetTime.Sub(time.Now()) > time.Hour {
79 | return true, time.Now().Add(15 * time.Minute)
80 | }
81 |
82 | return true, resetTime
83 | }
84 | }
85 | }
86 |
87 | return false, time.Time{}
88 | }
89 |
90 | //TwitterErrorResponse has an array of Twitter error messages
91 | //It satisfies the "error" interface
92 | //For the most part, Twitter seems to return only a single error message
93 | //Currently, we assume that this always contains exactly one error message
94 | type TwitterErrorResponse struct {
95 | Errors []TwitterError `json:"errors"`
96 | }
97 |
98 | func (tr TwitterErrorResponse) First() error {
99 | return tr.Errors[0]
100 | }
101 |
102 | func (tr TwitterErrorResponse) Error() string {
103 | return tr.Errors[0].Message
104 | }
105 |
106 | //TwitterError represents a single Twitter error messages/code pair
107 | type TwitterError struct {
108 | Message string `json:"message"`
109 | Code int `json:"code"`
110 | }
111 |
112 | func (te TwitterError) Error() string {
113 | return te.Message
114 | }
115 |
--------------------------------------------------------------------------------
/vendor/github.com/ChimeraCoder/tokenbucket/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | *.swo
3 | *.swn
4 | conf.sh
5 |
--------------------------------------------------------------------------------
/vendor/github.com/ChimeraCoder/tokenbucket/COPYING:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/vendor/github.com/ChimeraCoder/tokenbucket/LICENSE:
--------------------------------------------------------------------------------
1 | COPYING
--------------------------------------------------------------------------------
/vendor/github.com/ChimeraCoder/tokenbucket/README:
--------------------------------------------------------------------------------
1 | [](http://godoc.org/github.com/ChimeraCoder/tokenbucket)
2 |
3 | tokenbucket
4 | ====================
5 |
6 | This package provides an implementation of [Token bucket](https://en.wikipedia.org/wiki/Token_bucket) scheduling in Go. It is useful for implementing rate-limiting, traffic shaping, or other sorts of scheduling that depend on bandwidth constraints.
7 |
8 |
9 | Example
10 | ------------
11 |
12 |
13 | To create a new bucket, specify a capacity (how many tokens can be stored "in the bank"), and a rate (how often a new token is added).
14 |
15 | ````go
16 |
17 | // Create a new bucket
18 | // Allow a new action every 5 seconds, with a maximum of 3 "in the bank"
19 | bucket := tokenbucket.NewBucket(3, 5 * time.Second)
20 | ````
21 |
22 | This bucket should be shared between any functions that share the same constraints. (These functions may or may not run in separate goroutines).
23 |
24 |
25 | Anytime a regulated action is performed, spend a token.
26 |
27 | ````go
28 | // To perform a regulated action, we must spend a token
29 | // RegulatedAction will not be performed until the bucket contains enough tokens
30 | <-bucket.SpendToken(1)
31 | RegulatedAction()
32 | ````
33 |
34 | `SpendToken` returns immediately. Reading from the channel that it returns will block until the action has "permission" to continue (ie, until there are enough tokens in the bucket).
35 |
36 |
37 | (The channel that `SpendToken` returns is of type `error`. For now, the value will always be `nil`, so it can be ignored.)
38 |
39 |
40 |
41 | ####License
42 |
43 | `tokenbucket` is free software provided under version 3 of the LGPL license.
44 |
45 |
46 | Software that uses `tokenbucket` may be released under *any* license, as long as the source code for `tokenbucket` (including any modifications) are made available under the LGPLv3 license.
47 |
48 | You do not need to release the rest of the software under the LGPL, or any free/open-source license, for that matter (though we would encourage you to do so!).
49 |
--------------------------------------------------------------------------------
/vendor/github.com/ChimeraCoder/tokenbucket/README.md:
--------------------------------------------------------------------------------
1 | README
--------------------------------------------------------------------------------
/vendor/github.com/ChimeraCoder/tokenbucket/tokenbucket.go:
--------------------------------------------------------------------------------
1 | package tokenbucket
2 |
3 | import (
4 | "sync"
5 | "time"
6 | )
7 |
8 | type Bucket struct {
9 | capacity int64
10 | tokens chan struct{}
11 | rate time.Duration // Add a token to the bucket every 1/r units of time
12 | rateMutex sync.Mutex
13 | }
14 |
15 | func NewBucket(rate time.Duration, capacity int64) *Bucket {
16 |
17 | //A bucket is simply a channel with a buffer representing the maximum size
18 | tokens := make(chan struct{}, capacity)
19 |
20 | b := &Bucket{capacity, tokens, rate, sync.Mutex{}}
21 |
22 | //Set off a function that will continuously add tokens to the bucket
23 | go func(b *Bucket) {
24 | ticker := time.NewTicker(rate)
25 | for _ = range ticker.C {
26 | b.tokens <- struct{}{}
27 | }
28 | }(b)
29 |
30 | return b
31 | }
32 |
33 | func (b *Bucket) GetRate() time.Duration {
34 | b.rateMutex.Lock()
35 | tmp := b.rate
36 | b.rateMutex.Unlock()
37 | return tmp
38 | }
39 |
40 | func (b *Bucket) SetRate(rate time.Duration) {
41 | b.rateMutex.Lock()
42 | b.rate = rate
43 | b.rateMutex.Unlock()
44 | }
45 |
46 | //AddTokens manually adds n tokens to the bucket
47 | func (b *Bucket) AddToken(n int64) {
48 | }
49 |
50 | func (b *Bucket) withdrawTokens(n int64) error {
51 | for i := int64(0); i < n; i++ {
52 | <-b.tokens
53 | }
54 | return nil
55 | }
56 |
57 | func (b *Bucket) SpendToken(n int64) <-chan error {
58 | // Default to spending a single token
59 | if n < 0 {
60 | n = 1
61 | }
62 |
63 | c := make(chan error)
64 | go func(b *Bucket, n int64, c chan error) {
65 | c <- b.withdrawTokens(n)
66 | close(c)
67 | return
68 | }(b, n, c)
69 |
70 | return c
71 | }
72 |
73 | // Drain will empty all tokens in the bucket
74 | // If the tokens are being added too quickly (if the rate is too fast)
75 | // this will never drain
76 | func (b *Bucket) Drain() error{
77 | // TODO replace this with a more solid approach (such as replacing the channel altogether)
78 | for {
79 | select {
80 | case _ = <-b.tokens:
81 | continue
82 | default:
83 | return nil
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/vendor/github.com/garyburd/go-oauth/oauth/oauth16.go:
--------------------------------------------------------------------------------
1 | // +build !go1.7
2 |
3 | package oauth
4 |
5 | import (
6 | "net/http"
7 |
8 | "golang.org/x/net/context"
9 | )
10 |
11 | func requestWithContext(ctx context.Context, req *http.Request) *http.Request {
12 | return req
13 | }
14 |
--------------------------------------------------------------------------------
/vendor/github.com/garyburd/go-oauth/oauth/oauth17.go:
--------------------------------------------------------------------------------
1 | // +build go1.7
2 |
3 | package oauth
4 |
5 | import (
6 | "context"
7 | "net/http"
8 | )
9 |
10 | func requestWithContext(ctx context.Context, req *http.Request) *http.Request {
11 | return req.WithContext(ctx)
12 | }
13 |
--------------------------------------------------------------------------------
/vendor/github.com/golang/protobuf/AUTHORS:
--------------------------------------------------------------------------------
1 | # This source code refers to The Go Authors for copyright purposes.
2 | # The master list of authors is in the main Go distribution,
3 | # visible at http://tip.golang.org/AUTHORS.
4 |
--------------------------------------------------------------------------------
/vendor/github.com/golang/protobuf/CONTRIBUTORS:
--------------------------------------------------------------------------------
1 | # This source code was written by the Go contributors.
2 | # The master list of contributors is in the main Go distribution,
3 | # visible at http://tip.golang.org/CONTRIBUTORS.
4 |
--------------------------------------------------------------------------------
/vendor/github.com/golang/protobuf/LICENSE:
--------------------------------------------------------------------------------
1 | Go support for Protocol Buffers - Google's data interchange format
2 |
3 | Copyright 2010 The Go Authors. All rights reserved.
4 | https://github.com/golang/protobuf
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are
8 | met:
9 |
10 | * Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above
13 | copyright notice, this list of conditions and the following disclaimer
14 | in the documentation and/or other materials provided with the
15 | distribution.
16 | * Neither the name of Google Inc. nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 |
--------------------------------------------------------------------------------
/vendor/github.com/golang/protobuf/proto/encode.go:
--------------------------------------------------------------------------------
1 | // Go support for Protocol Buffers - Google's data interchange format
2 | //
3 | // Copyright 2010 The Go Authors. All rights reserved.
4 | // https://github.com/golang/protobuf
5 | //
6 | // Redistribution and use in source and binary forms, with or without
7 | // modification, are permitted provided that the following conditions are
8 | // met:
9 | //
10 | // * Redistributions of source code must retain the above copyright
11 | // notice, this list of conditions and the following disclaimer.
12 | // * Redistributions in binary form must reproduce the above
13 | // copyright notice, this list of conditions and the following disclaimer
14 | // in the documentation and/or other materials provided with the
15 | // distribution.
16 | // * Neither the name of Google Inc. nor the names of its
17 | // contributors may be used to endorse or promote products derived from
18 | // this software without specific prior written permission.
19 | //
20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 |
32 | package proto
33 |
34 | /*
35 | * Routines for encoding data into the wire format for protocol buffers.
36 | */
37 |
38 | import (
39 | "errors"
40 | "fmt"
41 | "reflect"
42 | )
43 |
44 | // RequiredNotSetError is the error returned if Marshal is called with
45 | // a protocol buffer struct whose required fields have not
46 | // all been initialized. It is also the error returned if Unmarshal is
47 | // called with an encoded protocol buffer that does not include all the
48 | // required fields.
49 | //
50 | // When printed, RequiredNotSetError reports the first unset required field in a
51 | // message. If the field cannot be precisely determined, it is reported as
52 | // "{Unknown}".
53 | type RequiredNotSetError struct {
54 | field string
55 | }
56 |
57 | func (e *RequiredNotSetError) Error() string {
58 | return fmt.Sprintf("proto: required field %q not set", e.field)
59 | }
60 |
61 | var (
62 | // errRepeatedHasNil is the error returned if Marshal is called with
63 | // a struct with a repeated field containing a nil element.
64 | errRepeatedHasNil = errors.New("proto: repeated field has nil element")
65 |
66 | // errOneofHasNil is the error returned if Marshal is called with
67 | // a struct with a oneof field containing a nil element.
68 | errOneofHasNil = errors.New("proto: oneof field has nil value")
69 |
70 | // ErrNil is the error returned if Marshal is called with nil.
71 | ErrNil = errors.New("proto: Marshal called with nil")
72 |
73 | // ErrTooLarge is the error returned if Marshal is called with a
74 | // message that encodes to >2GB.
75 | ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
76 | )
77 |
78 | // The fundamental encoders that put bytes on the wire.
79 | // Those that take integer types all accept uint64 and are
80 | // therefore of type valueEncoder.
81 |
82 | const maxVarintBytes = 10 // maximum length of a varint
83 |
84 | // EncodeVarint returns the varint encoding of x.
85 | // This is the format for the
86 | // int32, int64, uint32, uint64, bool, and enum
87 | // protocol buffer types.
88 | // Not used by the package itself, but helpful to clients
89 | // wishing to use the same encoding.
90 | func EncodeVarint(x uint64) []byte {
91 | var buf [maxVarintBytes]byte
92 | var n int
93 | for n = 0; x > 127; n++ {
94 | buf[n] = 0x80 | uint8(x&0x7F)
95 | x >>= 7
96 | }
97 | buf[n] = uint8(x)
98 | n++
99 | return buf[0:n]
100 | }
101 |
102 | // EncodeVarint writes a varint-encoded integer to the Buffer.
103 | // This is the format for the
104 | // int32, int64, uint32, uint64, bool, and enum
105 | // protocol buffer types.
106 | func (p *Buffer) EncodeVarint(x uint64) error {
107 | for x >= 1<<7 {
108 | p.buf = append(p.buf, uint8(x&0x7f|0x80))
109 | x >>= 7
110 | }
111 | p.buf = append(p.buf, uint8(x))
112 | return nil
113 | }
114 |
115 | // SizeVarint returns the varint encoding size of an integer.
116 | func SizeVarint(x uint64) int {
117 | switch {
118 | case x < 1<<7:
119 | return 1
120 | case x < 1<<14:
121 | return 2
122 | case x < 1<<21:
123 | return 3
124 | case x < 1<<28:
125 | return 4
126 | case x < 1<<35:
127 | return 5
128 | case x < 1<<42:
129 | return 6
130 | case x < 1<<49:
131 | return 7
132 | case x < 1<<56:
133 | return 8
134 | case x < 1<<63:
135 | return 9
136 | }
137 | return 10
138 | }
139 |
140 | // EncodeFixed64 writes a 64-bit integer to the Buffer.
141 | // This is the format for the
142 | // fixed64, sfixed64, and double protocol buffer types.
143 | func (p *Buffer) EncodeFixed64(x uint64) error {
144 | p.buf = append(p.buf,
145 | uint8(x),
146 | uint8(x>>8),
147 | uint8(x>>16),
148 | uint8(x>>24),
149 | uint8(x>>32),
150 | uint8(x>>40),
151 | uint8(x>>48),
152 | uint8(x>>56))
153 | return nil
154 | }
155 |
156 | // EncodeFixed32 writes a 32-bit integer to the Buffer.
157 | // This is the format for the
158 | // fixed32, sfixed32, and float protocol buffer types.
159 | func (p *Buffer) EncodeFixed32(x uint64) error {
160 | p.buf = append(p.buf,
161 | uint8(x),
162 | uint8(x>>8),
163 | uint8(x>>16),
164 | uint8(x>>24))
165 | return nil
166 | }
167 |
168 | // EncodeZigzag64 writes a zigzag-encoded 64-bit integer
169 | // to the Buffer.
170 | // This is the format used for the sint64 protocol buffer type.
171 | func (p *Buffer) EncodeZigzag64(x uint64) error {
172 | // use signed number to get arithmetic right shift.
173 | return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
174 | }
175 |
176 | // EncodeZigzag32 writes a zigzag-encoded 32-bit integer
177 | // to the Buffer.
178 | // This is the format used for the sint32 protocol buffer type.
179 | func (p *Buffer) EncodeZigzag32(x uint64) error {
180 | // use signed number to get arithmetic right shift.
181 | return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
182 | }
183 |
184 | // EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
185 | // This is the format used for the bytes protocol buffer
186 | // type and for embedded messages.
187 | func (p *Buffer) EncodeRawBytes(b []byte) error {
188 | p.EncodeVarint(uint64(len(b)))
189 | p.buf = append(p.buf, b...)
190 | return nil
191 | }
192 |
193 | // EncodeStringBytes writes an encoded string to the Buffer.
194 | // This is the format used for the proto2 string type.
195 | func (p *Buffer) EncodeStringBytes(s string) error {
196 | p.EncodeVarint(uint64(len(s)))
197 | p.buf = append(p.buf, s...)
198 | return nil
199 | }
200 |
201 | // Marshaler is the interface representing objects that can marshal themselves.
202 | type Marshaler interface {
203 | Marshal() ([]byte, error)
204 | }
205 |
206 | // EncodeMessage writes the protocol buffer to the Buffer,
207 | // prefixed by a varint-encoded length.
208 | func (p *Buffer) EncodeMessage(pb Message) error {
209 | siz := Size(pb)
210 | p.EncodeVarint(uint64(siz))
211 | return p.Marshal(pb)
212 | }
213 |
214 | // All protocol buffer fields are nillable, but be careful.
215 | func isNil(v reflect.Value) bool {
216 | switch v.Kind() {
217 | case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
218 | return v.IsNil()
219 | }
220 | return false
221 | }
222 |
--------------------------------------------------------------------------------
/vendor/github.com/golang/protobuf/ptypes/struct/struct.proto:
--------------------------------------------------------------------------------
1 | // Protocol Buffers - Google's data interchange format
2 | // Copyright 2008 Google Inc. All rights reserved.
3 | // https://developers.google.com/protocol-buffers/
4 | //
5 | // Redistribution and use in source and binary forms, with or without
6 | // modification, are permitted provided that the following conditions are
7 | // met:
8 | //
9 | // * Redistributions of source code must retain the above copyright
10 | // notice, this list of conditions and the following disclaimer.
11 | // * Redistributions in binary form must reproduce the above
12 | // copyright notice, this list of conditions and the following disclaimer
13 | // in the documentation and/or other materials provided with the
14 | // distribution.
15 | // * Neither the name of Google Inc. nor the names of its
16 | // contributors may be used to endorse or promote products derived from
17 | // this software without specific prior written permission.
18 | //
19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
31 | syntax = "proto3";
32 |
33 | package google.protobuf;
34 |
35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes";
36 | option cc_enable_arenas = true;
37 | option go_package = "github.com/golang/protobuf/ptypes/struct;structpb";
38 | option java_package = "com.google.protobuf";
39 | option java_outer_classname = "StructProto";
40 | option java_multiple_files = true;
41 | option objc_class_prefix = "GPB";
42 |
43 |
44 | // `Struct` represents a structured data value, consisting of fields
45 | // which map to dynamically typed values. In some languages, `Struct`
46 | // might be supported by a native representation. For example, in
47 | // scripting languages like JS a struct is represented as an
48 | // object. The details of that representation are described together
49 | // with the proto support for the language.
50 | //
51 | // The JSON representation for `Struct` is JSON object.
52 | message Struct {
53 | // Unordered map of dynamically typed values.
54 | map fields = 1;
55 | }
56 |
57 | // `Value` represents a dynamically typed value which can be either
58 | // null, a number, a string, a boolean, a recursive struct value, or a
59 | // list of values. A producer of value is expected to set one of that
60 | // variants, absence of any variant indicates an error.
61 | //
62 | // The JSON representation for `Value` is JSON value.
63 | message Value {
64 | // The kind of value.
65 | oneof kind {
66 | // Represents a null value.
67 | NullValue null_value = 1;
68 | // Represents a double value.
69 | double number_value = 2;
70 | // Represents a string value.
71 | string string_value = 3;
72 | // Represents a boolean value.
73 | bool bool_value = 4;
74 | // Represents a structured value.
75 | Struct struct_value = 5;
76 | // Represents a repeated `Value`.
77 | ListValue list_value = 6;
78 | }
79 | }
80 |
81 | // `NullValue` is a singleton enumeration to represent the null value for the
82 | // `Value` type union.
83 | //
84 | // The JSON representation for `NullValue` is JSON `null`.
85 | enum NullValue {
86 | // Null value.
87 | NULL_VALUE = 0;
88 | }
89 |
90 | // `ListValue` is a wrapper around a repeated field of values.
91 | //
92 | // The JSON representation for `ListValue` is JSON array.
93 | message ListValue {
94 | // Repeated field of dynamically typed values.
95 | repeated Value values = 1;
96 | }
97 |
--------------------------------------------------------------------------------
/vendor/github.com/google/btree/.travis.yml:
--------------------------------------------------------------------------------
1 | language: go
2 |
--------------------------------------------------------------------------------
/vendor/github.com/google/btree/README.md:
--------------------------------------------------------------------------------
1 | # BTree implementation for Go
2 |
3 | 
4 |
5 | This package provides an in-memory B-Tree implementation for Go, useful as
6 | an ordered, mutable data structure.
7 |
8 | The API is based off of the wonderful
9 | http://godoc.org/github.com/petar/GoLLRB/llrb, and is meant to allow btree to
10 | act as a drop-in replacement for gollrb trees.
11 |
12 | See http://godoc.org/github.com/google/btree for documentation.
13 |
--------------------------------------------------------------------------------
/vendor/github.com/google/btree/btree_mem.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 Google Inc.
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | // +build ignore
16 |
17 | // This binary compares memory usage between btree and gollrb.
18 | package main
19 |
20 | import (
21 | "flag"
22 | "fmt"
23 | "math/rand"
24 | "runtime"
25 | "time"
26 |
27 | "github.com/google/btree"
28 | "github.com/petar/GoLLRB/llrb"
29 | )
30 |
31 | var (
32 | size = flag.Int("size", 1000000, "size of the tree to build")
33 | degree = flag.Int("degree", 8, "degree of btree")
34 | gollrb = flag.Bool("llrb", false, "use llrb instead of btree")
35 | )
36 |
37 | func main() {
38 | flag.Parse()
39 | vals := rand.Perm(*size)
40 | var t, v interface{}
41 | v = vals
42 | var stats runtime.MemStats
43 | for i := 0; i < 10; i++ {
44 | runtime.GC()
45 | }
46 | fmt.Println("-------- BEFORE ----------")
47 | runtime.ReadMemStats(&stats)
48 | fmt.Printf("%+v\n", stats)
49 | start := time.Now()
50 | if *gollrb {
51 | tr := llrb.New()
52 | for _, v := range vals {
53 | tr.ReplaceOrInsert(llrb.Int(v))
54 | }
55 | t = tr // keep it around
56 | } else {
57 | tr := btree.New(*degree)
58 | for _, v := range vals {
59 | tr.ReplaceOrInsert(btree.Int(v))
60 | }
61 | t = tr // keep it around
62 | }
63 | fmt.Printf("%v inserts in %v\n", *size, time.Since(start))
64 | fmt.Println("-------- AFTER ----------")
65 | runtime.ReadMemStats(&stats)
66 | fmt.Printf("%+v\n", stats)
67 | for i := 0; i < 10; i++ {
68 | runtime.GC()
69 | }
70 | fmt.Println("-------- AFTER GC ----------")
71 | runtime.ReadMemStats(&stats)
72 | fmt.Printf("%+v\n", stats)
73 | if t == v {
74 | fmt.Println("to make sure vals and tree aren't GC'd")
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/vendor/github.com/gregjones/httpcache/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: go
3 | go:
4 | - 1.6.x
5 | - 1.7.x
6 | - 1.8.x
7 | - 1.9.x
8 | - master
9 | matrix:
10 | allow_failures:
11 | - go: master
12 | fast_finish: true
13 | install:
14 | - # Do nothing. This is needed to prevent default install action "go get -t -v ./..." from happening here (we want it to happen inside script step).
15 | script:
16 | - go get -t -v ./...
17 | - diff -u <(echo -n) <(gofmt -d .)
18 | - go tool vet .
19 | - go test -v -race ./...
20 |
--------------------------------------------------------------------------------
/vendor/github.com/gregjones/httpcache/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright © 2012 Greg Jones (greg.jones@gmail.com)
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/vendor/github.com/gregjones/httpcache/README.md:
--------------------------------------------------------------------------------
1 | httpcache
2 | =========
3 |
4 | [](https://travis-ci.org/gregjones/httpcache) [](https://godoc.org/github.com/gregjones/httpcache)
5 |
6 | Package httpcache provides a http.RoundTripper implementation that works as a mostly [RFC 7234](https://tools.ietf.org/html/rfc7234) compliant cache for http responses.
7 |
8 | It is only suitable for use as a 'private' cache (i.e. for a web-browser or an API-client and not for a shared proxy).
9 |
10 | Cache Backends
11 | --------------
12 |
13 | - The built-in 'memory' cache stores responses in an in-memory map.
14 | - [`github.com/gregjones/httpcache/diskcache`](https://github.com/gregjones/httpcache/tree/master/diskcache) provides a filesystem-backed cache using the [diskv](https://github.com/peterbourgon/diskv) library.
15 | - [`github.com/gregjones/httpcache/memcache`](https://github.com/gregjones/httpcache/tree/master/memcache) provides memcache implementations, for both App Engine and 'normal' memcache servers.
16 | - [`sourcegraph.com/sourcegraph/s3cache`](https://sourcegraph.com/github.com/sourcegraph/s3cache) uses Amazon S3 for storage.
17 | - [`github.com/gregjones/httpcache/leveldbcache`](https://github.com/gregjones/httpcache/tree/master/leveldbcache) provides a filesystem-backed cache using [leveldb](https://github.com/syndtr/goleveldb/leveldb).
18 | - [`github.com/die-net/lrucache`](https://github.com/die-net/lrucache) provides an in-memory cache that will evict least-recently used entries.
19 | - [`github.com/die-net/lrucache/twotier`](https://github.com/die-net/lrucache/tree/master/twotier) allows caches to be combined, for example to use lrucache above with a persistent disk-cache.
20 | - [`github.com/birkelund/boltdbcache`](https://github.com/birkelund/boltdbcache) provides a BoltDB implementation (based on the [bbolt](https://github.com/coreos/bbolt) fork).
21 |
22 | License
23 | -------
24 |
25 | - [MIT License](LICENSE.txt)
26 |
--------------------------------------------------------------------------------
/vendor/github.com/gregjones/httpcache/diskcache/diskcache.go:
--------------------------------------------------------------------------------
1 | // Package diskcache provides an implementation of httpcache.Cache that uses the diskv package
2 | // to supplement an in-memory map with persistent storage
3 | //
4 | package diskcache
5 |
6 | import (
7 | "bytes"
8 | "crypto/md5"
9 | "encoding/hex"
10 | "github.com/peterbourgon/diskv"
11 | "io"
12 | )
13 |
14 | // Cache is an implementation of httpcache.Cache that supplements the in-memory map with persistent storage
15 | type Cache struct {
16 | d *diskv.Diskv
17 | }
18 |
19 | // Get returns the response corresponding to key if present
20 | func (c *Cache) Get(key string) (resp []byte, ok bool) {
21 | key = keyToFilename(key)
22 | resp, err := c.d.Read(key)
23 | if err != nil {
24 | return []byte{}, false
25 | }
26 | return resp, true
27 | }
28 |
29 | // Set saves a response to the cache as key
30 | func (c *Cache) Set(key string, resp []byte) {
31 | key = keyToFilename(key)
32 | c.d.WriteStream(key, bytes.NewReader(resp), true)
33 | }
34 |
35 | // Delete removes the response with key from the cache
36 | func (c *Cache) Delete(key string) {
37 | key = keyToFilename(key)
38 | c.d.Erase(key)
39 | }
40 |
41 | func keyToFilename(key string) string {
42 | h := md5.New()
43 | io.WriteString(h, key)
44 | return hex.EncodeToString(h.Sum(nil))
45 | }
46 |
47 | // New returns a new Cache that will store files in basePath
48 | func New(basePath string) *Cache {
49 | return &Cache{
50 | d: diskv.New(diskv.Options{
51 | BasePath: basePath,
52 | CacheSizeMax: 100 * 1024 * 1024, // 100MB
53 | }),
54 | }
55 | }
56 |
57 | // NewWithDiskv returns a new Cache using the provided Diskv as underlying
58 | // storage.
59 | func NewWithDiskv(d *diskv.Diskv) *Cache {
60 | return &Cache{d}
61 | }
62 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/.gitignore:
--------------------------------------------------------------------------------
1 | test_program/test_program_bin
2 | fuzz/
3 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: go
3 | go:
4 | - 1.8.5
5 | - 1.9.2
6 | - tip
7 | matrix:
8 | allow_failures:
9 | - go: tip
10 | fast_finish: true
11 | script:
12 | - if [ -n "$(go fmt ./...)" ]; then exit 1; fi
13 | - ./test.sh
14 | - ./benchmark.sh $TRAVIS_BRANCH https://github.com/$TRAVIS_REPO_SLUG.git
15 | before_install:
16 | - go get github.com/axw/gocov/gocov
17 | - go get github.com/mattn/goveralls
18 | - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
19 | branches:
20 | only: [master]
21 | after_success:
22 | - $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=coverage.out -repotoken $COVERALLS_TOKEN
23 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 - 2017 Thomas Pelletier, Eric Anderton
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/README.md:
--------------------------------------------------------------------------------
1 | # go-toml
2 |
3 | Go library for the [TOML](https://github.com/mojombo/toml) format.
4 |
5 | This library supports TOML version
6 | [v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md)
7 |
8 | [](http://godoc.org/github.com/pelletier/go-toml)
9 | [](https://github.com/pelletier/go-toml/blob/master/LICENSE)
10 | [](https://travis-ci.org/pelletier/go-toml)
11 | [](https://coveralls.io/github/pelletier/go-toml?branch=master)
12 | [](https://goreportcard.com/report/github.com/pelletier/go-toml)
13 |
14 | ## Features
15 |
16 | Go-toml provides the following features for using data parsed from TOML documents:
17 |
18 | * Load TOML documents from files and string data
19 | * Easily navigate TOML structure using Tree
20 | * Mashaling and unmarshaling to and from data structures
21 | * Line & column position data for all parsed elements
22 | * [Query support similar to JSON-Path](query/)
23 | * Syntax errors contain line and column numbers
24 |
25 | ## Import
26 |
27 | ```go
28 | import "github.com/pelletier/go-toml"
29 | ```
30 |
31 | ## Usage example
32 |
33 | Read a TOML document:
34 |
35 | ```go
36 | config, _ := toml.Load(`
37 | [postgres]
38 | user = "pelletier"
39 | password = "mypassword"`)
40 | // retrieve data directly
41 | user := config.Get("postgres.user").(string)
42 |
43 | // or using an intermediate object
44 | postgresConfig := config.Get("postgres").(*toml.Tree)
45 | password := postgresConfig.Get("password").(string)
46 | ```
47 |
48 | Or use Unmarshal:
49 |
50 | ```go
51 | type Postgres struct {
52 | User string
53 | Password string
54 | }
55 | type Config struct {
56 | Postgres Postgres
57 | }
58 |
59 | doc := []byte(`
60 | [Postgres]
61 | User = "pelletier"
62 | Password = "mypassword"`)
63 |
64 | config := Config{}
65 | toml.Unmarshal(doc, &config)
66 | fmt.Println("user=", config.Postgres.User)
67 | ```
68 |
69 | Or use a query:
70 |
71 | ```go
72 | // use a query to gather elements without walking the tree
73 | q, _ := query.Compile("$..[user,password]")
74 | results := q.Execute(config)
75 | for ii, item := range results.Values() {
76 | fmt.Println("Query result %d: %v", ii, item)
77 | }
78 | ```
79 |
80 | ## Documentation
81 |
82 | The documentation and additional examples are available at
83 | [godoc.org](http://godoc.org/github.com/pelletier/go-toml).
84 |
85 | ## Tools
86 |
87 | Go-toml provides two handy command line tools:
88 |
89 | * `tomll`: Reads TOML files and lint them.
90 |
91 | ```
92 | go install github.com/pelletier/go-toml/cmd/tomll
93 | tomll --help
94 | ```
95 | * `tomljson`: Reads a TOML file and outputs its JSON representation.
96 |
97 | ```
98 | go install github.com/pelletier/go-toml/cmd/tomljson
99 | tomljson --help
100 | ```
101 |
102 | ## Contribute
103 |
104 | Feel free to report bugs and patches using GitHub's pull requests system on
105 | [pelletier/go-toml](https://github.com/pelletier/go-toml). Any feedback would be
106 | much appreciated!
107 |
108 | ### Run tests
109 |
110 | You have to make sure two kind of tests run:
111 |
112 | 1. The Go unit tests
113 | 2. The TOML examples base
114 |
115 | You can run both of them using `./test.sh`.
116 |
117 | ### Fuzzing
118 |
119 | The script `./fuzz.sh` is available to
120 | run [go-fuzz](https://github.com/dvyukov/go-fuzz) on go-toml.
121 |
122 | ## Versioning
123 |
124 | Go-toml follows [Semantic Versioning](http://semver.org/). The supported version
125 | of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of
126 | this document. The last two major versions of Go are supported
127 | (see [Go Release Policy](https://golang.org/doc/devel/release.html#policy)).
128 |
129 | ## License
130 |
131 | The MIT License (MIT). Read [LICENSE](LICENSE).
132 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/benchmark.json:
--------------------------------------------------------------------------------
1 | {
2 | "array": {
3 | "key1": [
4 | 1,
5 | 2,
6 | 3
7 | ],
8 | "key2": [
9 | "red",
10 | "yellow",
11 | "green"
12 | ],
13 | "key3": [
14 | [
15 | 1,
16 | 2
17 | ],
18 | [
19 | 3,
20 | 4,
21 | 5
22 | ]
23 | ],
24 | "key4": [
25 | [
26 | 1,
27 | 2
28 | ],
29 | [
30 | "a",
31 | "b",
32 | "c"
33 | ]
34 | ],
35 | "key5": [
36 | 1,
37 | 2,
38 | 3
39 | ],
40 | "key6": [
41 | 1,
42 | 2
43 | ]
44 | },
45 | "boolean": {
46 | "False": false,
47 | "True": true
48 | },
49 | "datetime": {
50 | "key1": "1979-05-27T07:32:00Z",
51 | "key2": "1979-05-27T00:32:00-07:00",
52 | "key3": "1979-05-27T00:32:00.999999-07:00"
53 | },
54 | "float": {
55 | "both": {
56 | "key": 6.626e-34
57 | },
58 | "exponent": {
59 | "key1": 5e+22,
60 | "key2": 1000000,
61 | "key3": -0.02
62 | },
63 | "fractional": {
64 | "key1": 1,
65 | "key2": 3.1415,
66 | "key3": -0.01
67 | },
68 | "underscores": {
69 | "key1": 9224617.445991227,
70 | "key2": 1e+100
71 | }
72 | },
73 | "fruit": [{
74 | "name": "apple",
75 | "physical": {
76 | "color": "red",
77 | "shape": "round"
78 | },
79 | "variety": [{
80 | "name": "red delicious"
81 | },
82 | {
83 | "name": "granny smith"
84 | }
85 | ]
86 | },
87 | {
88 | "name": "banana",
89 | "variety": [{
90 | "name": "plantain"
91 | }]
92 | }
93 | ],
94 | "integer": {
95 | "key1": 99,
96 | "key2": 42,
97 | "key3": 0,
98 | "key4": -17,
99 | "underscores": {
100 | "key1": 1000,
101 | "key2": 5349221,
102 | "key3": 12345
103 | }
104 | },
105 | "products": [{
106 | "name": "Hammer",
107 | "sku": 738594937
108 | },
109 | {},
110 | {
111 | "color": "gray",
112 | "name": "Nail",
113 | "sku": 284758393
114 | }
115 | ],
116 | "string": {
117 | "basic": {
118 | "basic": "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."
119 | },
120 | "literal": {
121 | "multiline": {
122 | "lines": "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n",
123 | "regex2": "I [dw]on't need \\d{2} apples"
124 | },
125 | "quoted": "Tom \"Dubs\" Preston-Werner",
126 | "regex": "\u003c\\i\\c*\\s*\u003e",
127 | "winpath": "C:\\Users\\nodejs\\templates",
128 | "winpath2": "\\\\ServerX\\admin$\\system32\\"
129 | },
130 | "multiline": {
131 | "continued": {
132 | "key1": "The quick brown fox jumps over the lazy dog.",
133 | "key2": "The quick brown fox jumps over the lazy dog.",
134 | "key3": "The quick brown fox jumps over the lazy dog."
135 | },
136 | "key1": "One\nTwo",
137 | "key2": "One\nTwo",
138 | "key3": "One\nTwo"
139 | }
140 | },
141 | "table": {
142 | "inline": {
143 | "name": {
144 | "first": "Tom",
145 | "last": "Preston-Werner"
146 | },
147 | "point": {
148 | "x": 1,
149 | "y": 2
150 | }
151 | },
152 | "key": "value",
153 | "subtable": {
154 | "key": "another value"
155 | }
156 | },
157 | "x": {
158 | "y": {
159 | "z": {
160 | "w": {}
161 | }
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/benchmark.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | reference_ref=${1:-master}
6 | reference_git=${2:-.}
7 |
8 | if ! `hash benchstat 2>/dev/null`; then
9 | echo "Installing benchstat"
10 | go get golang.org/x/perf/cmd/benchstat
11 | go install golang.org/x/perf/cmd/benchstat
12 | fi
13 |
14 | tempdir=`mktemp -d /tmp/go-toml-benchmark-XXXXXX`
15 | ref_tempdir="${tempdir}/ref"
16 | ref_benchmark="${ref_tempdir}/benchmark-`echo -n ${reference_ref}|tr -s '/' '-'`.txt"
17 | local_benchmark="`pwd`/benchmark-local.txt"
18 |
19 | echo "=== ${reference_ref} (${ref_tempdir})"
20 | git clone ${reference_git} ${ref_tempdir} >/dev/null 2>/dev/null
21 | pushd ${ref_tempdir} >/dev/null
22 | git checkout ${reference_ref} >/dev/null 2>/dev/null
23 | go test -bench=. -benchmem | tee ${ref_benchmark}
24 | popd >/dev/null
25 |
26 | echo ""
27 | echo "=== local"
28 | go test -bench=. -benchmem | tee ${local_benchmark}
29 |
30 | echo ""
31 | echo "=== diff"
32 | benchstat -delta-test=none ${ref_benchmark} ${local_benchmark}
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/benchmark.toml:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | ## Comment
3 |
4 | # Speak your mind with the hash symbol. They go from the symbol to the end of
5 | # the line.
6 |
7 |
8 | ################################################################################
9 | ## Table
10 |
11 | # Tables (also known as hash tables or dictionaries) are collections of
12 | # key/value pairs. They appear in square brackets on a line by themselves.
13 |
14 | [table]
15 |
16 | key = "value" # Yeah, you can do this.
17 |
18 | # Nested tables are denoted by table names with dots in them. Name your tables
19 | # whatever crap you please, just don't use #, ., [ or ].
20 |
21 | [table.subtable]
22 |
23 | key = "another value"
24 |
25 | # You don't need to specify all the super-tables if you don't want to. TOML
26 | # knows how to do it for you.
27 |
28 | # [x] you
29 | # [x.y] don't
30 | # [x.y.z] need these
31 | [x.y.z.w] # for this to work
32 |
33 |
34 | ################################################################################
35 | ## Inline Table
36 |
37 | # Inline tables provide a more compact syntax for expressing tables. They are
38 | # especially useful for grouped data that can otherwise quickly become verbose.
39 | # Inline tables are enclosed in curly braces `{` and `}`. No newlines are
40 | # allowed between the curly braces unless they are valid within a value.
41 |
42 | [table.inline]
43 |
44 | name = { first = "Tom", last = "Preston-Werner" }
45 | point = { x = 1, y = 2 }
46 |
47 |
48 | ################################################################################
49 | ## String
50 |
51 | # There are four ways to express strings: basic, multi-line basic, literal, and
52 | # multi-line literal. All strings must contain only valid UTF-8 characters.
53 |
54 | [string.basic]
55 |
56 | basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."
57 |
58 | [string.multiline]
59 |
60 | # The following strings are byte-for-byte equivalent:
61 | key1 = "One\nTwo"
62 | key2 = """One\nTwo"""
63 | key3 = """
64 | One
65 | Two"""
66 |
67 | [string.multiline.continued]
68 |
69 | # The following strings are byte-for-byte equivalent:
70 | key1 = "The quick brown fox jumps over the lazy dog."
71 |
72 | key2 = """
73 | The quick brown \
74 |
75 |
76 | fox jumps over \
77 | the lazy dog."""
78 |
79 | key3 = """\
80 | The quick brown \
81 | fox jumps over \
82 | the lazy dog.\
83 | """
84 |
85 | [string.literal]
86 |
87 | # What you see is what you get.
88 | winpath = 'C:\Users\nodejs\templates'
89 | winpath2 = '\\ServerX\admin$\system32\'
90 | quoted = 'Tom "Dubs" Preston-Werner'
91 | regex = '<\i\c*\s*>'
92 |
93 |
94 | [string.literal.multiline]
95 |
96 | regex2 = '''I [dw]on't need \d{2} apples'''
97 | lines = '''
98 | The first newline is
99 | trimmed in raw strings.
100 | All other whitespace
101 | is preserved.
102 | '''
103 |
104 |
105 | ################################################################################
106 | ## Integer
107 |
108 | # Integers are whole numbers. Positive numbers may be prefixed with a plus sign.
109 | # Negative numbers are prefixed with a minus sign.
110 |
111 | [integer]
112 |
113 | key1 = +99
114 | key2 = 42
115 | key3 = 0
116 | key4 = -17
117 |
118 | [integer.underscores]
119 |
120 | # For large numbers, you may use underscores to enhance readability. Each
121 | # underscore must be surrounded by at least one digit.
122 | key1 = 1_000
123 | key2 = 5_349_221
124 | key3 = 1_2_3_4_5 # valid but inadvisable
125 |
126 |
127 | ################################################################################
128 | ## Float
129 |
130 | # A float consists of an integer part (which may be prefixed with a plus or
131 | # minus sign) followed by a fractional part and/or an exponent part.
132 |
133 | [float.fractional]
134 |
135 | key1 = +1.0
136 | key2 = 3.1415
137 | key3 = -0.01
138 |
139 | [float.exponent]
140 |
141 | key1 = 5e+22
142 | key2 = 1e6
143 | key3 = -2E-2
144 |
145 | [float.both]
146 |
147 | key = 6.626e-34
148 |
149 | [float.underscores]
150 |
151 | key1 = 9_224_617.445_991_228_313
152 | key2 = 1e1_00
153 |
154 |
155 | ################################################################################
156 | ## Boolean
157 |
158 | # Booleans are just the tokens you're used to. Always lowercase.
159 |
160 | [boolean]
161 |
162 | True = true
163 | False = false
164 |
165 |
166 | ################################################################################
167 | ## Datetime
168 |
169 | # Datetimes are RFC 3339 dates.
170 |
171 | [datetime]
172 |
173 | key1 = 1979-05-27T07:32:00Z
174 | key2 = 1979-05-27T00:32:00-07:00
175 | key3 = 1979-05-27T00:32:00.999999-07:00
176 |
177 |
178 | ################################################################################
179 | ## Array
180 |
181 | # Arrays are square brackets with other primitives inside. Whitespace is
182 | # ignored. Elements are separated by commas. Data types may not be mixed.
183 |
184 | [array]
185 |
186 | key1 = [ 1, 2, 3 ]
187 | key2 = [ "red", "yellow", "green" ]
188 | key3 = [ [ 1, 2 ], [3, 4, 5] ]
189 | #key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok
190 |
191 | # Arrays can also be multiline. So in addition to ignoring whitespace, arrays
192 | # also ignore newlines between the brackets. Terminating commas are ok before
193 | # the closing bracket.
194 |
195 | key5 = [
196 | 1, 2, 3
197 | ]
198 | key6 = [
199 | 1,
200 | 2, # this is ok
201 | ]
202 |
203 |
204 | ################################################################################
205 | ## Array of Tables
206 |
207 | # These can be expressed by using a table name in double brackets. Each table
208 | # with the same double bracketed name will be an element in the array. The
209 | # tables are inserted in the order encountered.
210 |
211 | [[products]]
212 |
213 | name = "Hammer"
214 | sku = 738594937
215 |
216 | [[products]]
217 |
218 | [[products]]
219 |
220 | name = "Nail"
221 | sku = 284758393
222 | color = "gray"
223 |
224 |
225 | # You can create nested arrays of tables as well.
226 |
227 | [[fruit]]
228 | name = "apple"
229 |
230 | [fruit.physical]
231 | color = "red"
232 | shape = "round"
233 |
234 | [[fruit.variety]]
235 | name = "red delicious"
236 |
237 | [[fruit.variety]]
238 | name = "granny smith"
239 |
240 | [[fruit]]
241 | name = "banana"
242 |
243 | [[fruit.variety]]
244 | name = "plantain"
245 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/benchmark.yml:
--------------------------------------------------------------------------------
1 | ---
2 | array:
3 | key1:
4 | - 1
5 | - 2
6 | - 3
7 | key2:
8 | - red
9 | - yellow
10 | - green
11 | key3:
12 | - - 1
13 | - 2
14 | - - 3
15 | - 4
16 | - 5
17 | key4:
18 | - - 1
19 | - 2
20 | - - a
21 | - b
22 | - c
23 | key5:
24 | - 1
25 | - 2
26 | - 3
27 | key6:
28 | - 1
29 | - 2
30 | boolean:
31 | 'False': false
32 | 'True': true
33 | datetime:
34 | key1: '1979-05-27T07:32:00Z'
35 | key2: '1979-05-27T00:32:00-07:00'
36 | key3: '1979-05-27T00:32:00.999999-07:00'
37 | float:
38 | both:
39 | key: 6.626e-34
40 | exponent:
41 | key1: 5.0e+22
42 | key2: 1000000
43 | key3: -0.02
44 | fractional:
45 | key1: 1
46 | key2: 3.1415
47 | key3: -0.01
48 | underscores:
49 | key1: 9224617.445991227
50 | key2: 1.0e+100
51 | fruit:
52 | - name: apple
53 | physical:
54 | color: red
55 | shape: round
56 | variety:
57 | - name: red delicious
58 | - name: granny smith
59 | - name: banana
60 | variety:
61 | - name: plantain
62 | integer:
63 | key1: 99
64 | key2: 42
65 | key3: 0
66 | key4: -17
67 | underscores:
68 | key1: 1000
69 | key2: 5349221
70 | key3: 12345
71 | products:
72 | - name: Hammer
73 | sku: 738594937
74 | - {}
75 | - color: gray
76 | name: Nail
77 | sku: 284758393
78 | string:
79 | basic:
80 | basic: "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF."
81 | literal:
82 | multiline:
83 | lines: |
84 | The first newline is
85 | trimmed in raw strings.
86 | All other whitespace
87 | is preserved.
88 | regex2: I [dw]on't need \d{2} apples
89 | quoted: Tom "Dubs" Preston-Werner
90 | regex: "<\\i\\c*\\s*>"
91 | winpath: C:\Users\nodejs\templates
92 | winpath2: "\\\\ServerX\\admin$\\system32\\"
93 | multiline:
94 | continued:
95 | key1: The quick brown fox jumps over the lazy dog.
96 | key2: The quick brown fox jumps over the lazy dog.
97 | key3: The quick brown fox jumps over the lazy dog.
98 | key1: |-
99 | One
100 | Two
101 | key2: |-
102 | One
103 | Two
104 | key3: |-
105 | One
106 | Two
107 | table:
108 | inline:
109 | name:
110 | first: Tom
111 | last: Preston-Werner
112 | point:
113 | x: 1
114 | y: 2
115 | key: value
116 | subtable:
117 | key: another value
118 | x:
119 | y:
120 | z:
121 | w: {}
122 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/doc.go:
--------------------------------------------------------------------------------
1 | // Package toml is a TOML parser and manipulation library.
2 | //
3 | // This version supports the specification as described in
4 | // https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md
5 | //
6 | // Marshaling
7 | //
8 | // Go-toml can marshal and unmarshal TOML documents from and to data
9 | // structures.
10 | //
11 | // TOML document as a tree
12 | //
13 | // Go-toml can operate on a TOML document as a tree. Use one of the Load*
14 | // functions to parse TOML data and obtain a Tree instance, then one of its
15 | // methods to manipulate the tree.
16 | //
17 | // JSONPath-like queries
18 | //
19 | // The package github.com/pelletier/go-toml/query implements a system
20 | // similar to JSONPath to quickly retrieve elements of a TOML document using a
21 | // single expression. See the package documentation for more information.
22 | //
23 | package toml
24 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/example-crlf.toml:
--------------------------------------------------------------------------------
1 | # This is a TOML document. Boom.
2 |
3 | title = "TOML Example"
4 |
5 | [owner]
6 | name = "Tom Preston-Werner"
7 | organization = "GitHub"
8 | bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
9 | dob = 1979-05-27T07:32:00Z # First class dates? Why not?
10 |
11 | [database]
12 | server = "192.168.1.1"
13 | ports = [ 8001, 8001, 8002 ]
14 | connection_max = 5000
15 | enabled = true
16 |
17 | [servers]
18 |
19 | # You can indent as you please. Tabs or spaces. TOML don't care.
20 | [servers.alpha]
21 | ip = "10.0.0.1"
22 | dc = "eqdc10"
23 |
24 | [servers.beta]
25 | ip = "10.0.0.2"
26 | dc = "eqdc10"
27 |
28 | [clients]
29 | data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
30 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/example.toml:
--------------------------------------------------------------------------------
1 | # This is a TOML document. Boom.
2 |
3 | title = "TOML Example"
4 |
5 | [owner]
6 | name = "Tom Preston-Werner"
7 | organization = "GitHub"
8 | bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
9 | dob = 1979-05-27T07:32:00Z # First class dates? Why not?
10 |
11 | [database]
12 | server = "192.168.1.1"
13 | ports = [ 8001, 8001, 8002 ]
14 | connection_max = 5000
15 | enabled = true
16 |
17 | [servers]
18 |
19 | # You can indent as you please. Tabs or spaces. TOML don't care.
20 | [servers.alpha]
21 | ip = "10.0.0.1"
22 | dc = "eqdc10"
23 |
24 | [servers.beta]
25 | ip = "10.0.0.2"
26 | dc = "eqdc10"
27 |
28 | [clients]
29 | data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
30 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/fuzz.go:
--------------------------------------------------------------------------------
1 | // +build gofuzz
2 |
3 | package toml
4 |
5 | func Fuzz(data []byte) int {
6 | tree, err := LoadBytes(data)
7 | if err != nil {
8 | if tree != nil {
9 | panic("tree must be nil if there is an error")
10 | }
11 | return 0
12 | }
13 |
14 | str, err := tree.ToTomlString()
15 | if err != nil {
16 | if str != "" {
17 | panic(`str must be "" if there is an error`)
18 | }
19 | panic(err)
20 | }
21 |
22 | tree, err = Load(str)
23 | if err != nil {
24 | if tree != nil {
25 | panic("tree must be nil if there is an error")
26 | }
27 | return 0
28 | }
29 |
30 | return 1
31 | }
32 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/fuzz.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 | set -eu
3 |
4 | go get github.com/dvyukov/go-fuzz/go-fuzz
5 | go get github.com/dvyukov/go-fuzz/go-fuzz-build
6 |
7 | if [ ! -e toml-fuzz.zip ]; then
8 | go-fuzz-build github.com/pelletier/go-toml
9 | fi
10 |
11 | rm -fr fuzz
12 | mkdir -p fuzz/corpus
13 | cp *.toml fuzz/corpus
14 |
15 | go-fuzz -bin=toml-fuzz.zip -workdir=fuzz
16 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/keysparsing.go:
--------------------------------------------------------------------------------
1 | // Parsing keys handling both bare and quoted keys.
2 |
3 | package toml
4 |
5 | import (
6 | "bytes"
7 | "errors"
8 | "fmt"
9 | "unicode"
10 | )
11 |
12 | // Convert the bare key group string to an array.
13 | // The input supports double quotation to allow "." inside the key name,
14 | // but escape sequences are not supported. Lexers must unescape them beforehand.
15 | func parseKey(key string) ([]string, error) {
16 | groups := []string{}
17 | var buffer bytes.Buffer
18 | inQuotes := false
19 | wasInQuotes := false
20 | ignoreSpace := true
21 | expectDot := false
22 |
23 | for _, char := range key {
24 | if ignoreSpace {
25 | if char == ' ' {
26 | continue
27 | }
28 | ignoreSpace = false
29 | }
30 | switch char {
31 | case '"':
32 | if inQuotes {
33 | groups = append(groups, buffer.String())
34 | buffer.Reset()
35 | wasInQuotes = true
36 | }
37 | inQuotes = !inQuotes
38 | expectDot = false
39 | case '.':
40 | if inQuotes {
41 | buffer.WriteRune(char)
42 | } else {
43 | if !wasInQuotes {
44 | if buffer.Len() == 0 {
45 | return nil, errors.New("empty table key")
46 | }
47 | groups = append(groups, buffer.String())
48 | buffer.Reset()
49 | }
50 | ignoreSpace = true
51 | expectDot = false
52 | wasInQuotes = false
53 | }
54 | case ' ':
55 | if inQuotes {
56 | buffer.WriteRune(char)
57 | } else {
58 | expectDot = true
59 | }
60 | default:
61 | if !inQuotes && !isValidBareChar(char) {
62 | return nil, fmt.Errorf("invalid bare character: %c", char)
63 | }
64 | if !inQuotes && expectDot {
65 | return nil, errors.New("what?")
66 | }
67 | buffer.WriteRune(char)
68 | expectDot = false
69 | }
70 | }
71 | if inQuotes {
72 | return nil, errors.New("mismatched quotes")
73 | }
74 | if buffer.Len() > 0 {
75 | groups = append(groups, buffer.String())
76 | }
77 | if len(groups) == 0 {
78 | return nil, errors.New("empty key")
79 | }
80 | return groups, nil
81 | }
82 |
83 | func isValidBareChar(r rune) bool {
84 | return isAlphanumeric(r) || r == '-' || unicode.IsNumber(r)
85 | }
86 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/marshal_test.toml:
--------------------------------------------------------------------------------
1 | title = "TOML Marshal Testing"
2 |
3 | [basic]
4 | bool = true
5 | date = 1979-05-27T07:32:00Z
6 | float = 123.4
7 | int = 5000
8 | string = "Bite me"
9 | uint = 5001
10 |
11 | [basic_lists]
12 | bools = [true,false,true]
13 | dates = [1979-05-27T07:32:00Z,1980-05-27T07:32:00Z]
14 | floats = [12.3,45.6,78.9]
15 | ints = [8001,8001,8002]
16 | strings = ["One","Two","Three"]
17 | uints = [5002,5003]
18 |
19 | [basic_map]
20 | one = "one"
21 | two = "two"
22 |
23 | [subdoc]
24 |
25 | [subdoc.first]
26 | name = "First"
27 |
28 | [subdoc.second]
29 | name = "Second"
30 |
31 | [[subdoclist]]
32 | name = "List.First"
33 |
34 | [[subdoclist]]
35 | name = "List.Second"
36 |
37 | [[subdocptrs]]
38 | name = "Second"
39 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/position.go:
--------------------------------------------------------------------------------
1 | // Position support for go-toml
2 |
3 | package toml
4 |
5 | import (
6 | "fmt"
7 | )
8 |
9 | // Position of a document element within a TOML document.
10 | //
11 | // Line and Col are both 1-indexed positions for the element's line number and
12 | // column number, respectively. Values of zero or less will cause Invalid(),
13 | // to return true.
14 | type Position struct {
15 | Line int // line within the document
16 | Col int // column within the line
17 | }
18 |
19 | // String representation of the position.
20 | // Displays 1-indexed line and column numbers.
21 | func (p Position) String() string {
22 | return fmt.Sprintf("(%d, %d)", p.Line, p.Col)
23 | }
24 |
25 | // Invalid returns whether or not the position is valid (i.e. with negative or
26 | // null values)
27 | func (p Position) Invalid() bool {
28 | return p.Line <= 0 || p.Col <= 0
29 | }
30 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # fail out of the script if anything here fails
3 | set -e
4 | set -o pipefail
5 |
6 | # set the path to the present working directory
7 | export GOPATH=`pwd`
8 |
9 | function git_clone() {
10 | path=$1
11 | branch=$2
12 | version=$3
13 | if [ ! -d "src/$path" ]; then
14 | mkdir -p src/$path
15 | git clone https://$path.git src/$path
16 | fi
17 | pushd src/$path
18 | git checkout "$branch"
19 | git reset --hard "$version"
20 | popd
21 | }
22 |
23 | # Remove potential previous runs
24 | rm -rf src test_program_bin toml-test
25 |
26 | # Run go vet
27 | go vet ./...
28 |
29 | go get github.com/pelletier/go-buffruneio
30 | go get github.com/davecgh/go-spew/spew
31 | go get gopkg.in/yaml.v2
32 | go get github.com/BurntSushi/toml
33 |
34 | # get code for BurntSushi TOML validation
35 | # pinning all to 'HEAD' for version 0.3.x work (TODO: pin to commit hash when tests stabilize)
36 | git_clone github.com/BurntSushi/toml master HEAD
37 | git_clone github.com/BurntSushi/toml-test master HEAD #was: 0.2.0 HEAD
38 |
39 | # build the BurntSushi test application
40 | go build -o toml-test github.com/BurntSushi/toml-test
41 |
42 | # vendorize the current lib for testing
43 | # NOTE: this basically mocks an install without having to go back out to github for code
44 | mkdir -p src/github.com/pelletier/go-toml/cmd
45 | mkdir -p src/github.com/pelletier/go-toml/query
46 | cp *.go *.toml src/github.com/pelletier/go-toml
47 | cp -R cmd/* src/github.com/pelletier/go-toml/cmd
48 | cp -R query/* src/github.com/pelletier/go-toml/query
49 | go build -o test_program_bin src/github.com/pelletier/go-toml/cmd/test_program.go
50 |
51 | # Run basic unit tests
52 | go test github.com/pelletier/go-toml -covermode=count -coverprofile=coverage.out
53 | go test github.com/pelletier/go-toml/cmd/tomljson
54 | go test github.com/pelletier/go-toml/query
55 |
56 | # run the entire BurntSushi test suite
57 | if [[ $# -eq 0 ]] ; then
58 | echo "Running all BurntSushi tests"
59 | ./toml-test ./test_program_bin | tee test_out
60 | else
61 | # run a specific test
62 | test=$1
63 | test_path='src/github.com/BurntSushi/toml-test/tests'
64 | valid_test="$test_path/valid/$test"
65 | invalid_test="$test_path/invalid/$test"
66 |
67 | if [ -e "$valid_test.toml" ]; then
68 | echo "Valid Test TOML for $test:"
69 | echo "===="
70 | cat "$valid_test.toml"
71 |
72 | echo "Valid Test JSON for $test:"
73 | echo "===="
74 | cat "$valid_test.json"
75 |
76 | echo "Go-TOML Output for $test:"
77 | echo "===="
78 | cat "$valid_test.toml" | ./test_program_bin
79 | fi
80 |
81 | if [ -e "$invalid_test.toml" ]; then
82 | echo "Invalid Test TOML for $test:"
83 | echo "===="
84 | cat "$invalid_test.toml"
85 |
86 | echo "Go-TOML Output for $test:"
87 | echo "===="
88 | echo "go-toml Output:"
89 | cat "$invalid_test.toml" | ./test_program_bin
90 | fi
91 | fi
92 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/token.go:
--------------------------------------------------------------------------------
1 | package toml
2 |
3 | import (
4 | "fmt"
5 | "strconv"
6 | "unicode"
7 | )
8 |
9 | // Define tokens
10 | type tokenType int
11 |
12 | const (
13 | eof = -(iota + 1)
14 | )
15 |
16 | const (
17 | tokenError tokenType = iota
18 | tokenEOF
19 | tokenComment
20 | tokenKey
21 | tokenString
22 | tokenInteger
23 | tokenTrue
24 | tokenFalse
25 | tokenFloat
26 | tokenInf
27 | tokenNan
28 | tokenEqual
29 | tokenLeftBracket
30 | tokenRightBracket
31 | tokenLeftCurlyBrace
32 | tokenRightCurlyBrace
33 | tokenLeftParen
34 | tokenRightParen
35 | tokenDoubleLeftBracket
36 | tokenDoubleRightBracket
37 | tokenDate
38 | tokenKeyGroup
39 | tokenKeyGroupArray
40 | tokenComma
41 | tokenColon
42 | tokenDollar
43 | tokenStar
44 | tokenQuestion
45 | tokenDot
46 | tokenDotDot
47 | tokenEOL
48 | )
49 |
50 | var tokenTypeNames = []string{
51 | "Error",
52 | "EOF",
53 | "Comment",
54 | "Key",
55 | "String",
56 | "Integer",
57 | "True",
58 | "False",
59 | "Float",
60 | "Inf",
61 | "NaN",
62 | "=",
63 | "[",
64 | "]",
65 | "{",
66 | "}",
67 | "(",
68 | ")",
69 | "]]",
70 | "[[",
71 | "Date",
72 | "KeyGroup",
73 | "KeyGroupArray",
74 | ",",
75 | ":",
76 | "$",
77 | "*",
78 | "?",
79 | ".",
80 | "..",
81 | "EOL",
82 | }
83 |
84 | type token struct {
85 | Position
86 | typ tokenType
87 | val string
88 | }
89 |
90 | func (tt tokenType) String() string {
91 | idx := int(tt)
92 | if idx < len(tokenTypeNames) {
93 | return tokenTypeNames[idx]
94 | }
95 | return "Unknown"
96 | }
97 |
98 | func (t token) Int() int {
99 | if result, err := strconv.Atoi(t.val); err != nil {
100 | panic(err)
101 | } else {
102 | return result
103 | }
104 | }
105 |
106 | func (t token) String() string {
107 | switch t.typ {
108 | case tokenEOF:
109 | return "EOF"
110 | case tokenError:
111 | return t.val
112 | }
113 |
114 | return fmt.Sprintf("%q", t.val)
115 | }
116 |
117 | func isSpace(r rune) bool {
118 | return r == ' ' || r == '\t'
119 | }
120 |
121 | func isAlphanumeric(r rune) bool {
122 | return unicode.IsLetter(r) || r == '_'
123 | }
124 |
125 | func isKeyChar(r rune) bool {
126 | // Keys start with the first character that isn't whitespace or [ and end
127 | // with the last non-whitespace character before the equals sign. Keys
128 | // cannot contain a # character."
129 | return !(r == '\r' || r == '\n' || r == eof || r == '=')
130 | }
131 |
132 | func isKeyStartChar(r rune) bool {
133 | return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '[')
134 | }
135 |
136 | func isDigit(r rune) bool {
137 | return unicode.IsNumber(r)
138 | }
139 |
140 | func isHexDigit(r rune) bool {
141 | return isDigit(r) ||
142 | (r >= 'a' && r <= 'f') ||
143 | (r >= 'A' && r <= 'F')
144 | }
145 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/tomltree_create.go:
--------------------------------------------------------------------------------
1 | package toml
2 |
3 | import (
4 | "fmt"
5 | "reflect"
6 | "time"
7 | )
8 |
9 | var kindToType = [reflect.String + 1]reflect.Type{
10 | reflect.Bool: reflect.TypeOf(true),
11 | reflect.String: reflect.TypeOf(""),
12 | reflect.Float32: reflect.TypeOf(float64(1)),
13 | reflect.Float64: reflect.TypeOf(float64(1)),
14 | reflect.Int: reflect.TypeOf(int64(1)),
15 | reflect.Int8: reflect.TypeOf(int64(1)),
16 | reflect.Int16: reflect.TypeOf(int64(1)),
17 | reflect.Int32: reflect.TypeOf(int64(1)),
18 | reflect.Int64: reflect.TypeOf(int64(1)),
19 | reflect.Uint: reflect.TypeOf(uint64(1)),
20 | reflect.Uint8: reflect.TypeOf(uint64(1)),
21 | reflect.Uint16: reflect.TypeOf(uint64(1)),
22 | reflect.Uint32: reflect.TypeOf(uint64(1)),
23 | reflect.Uint64: reflect.TypeOf(uint64(1)),
24 | }
25 |
26 | // typeFor returns a reflect.Type for a reflect.Kind, or nil if none is found.
27 | // supported values:
28 | // string, bool, int64, uint64, float64, time.Time, int, int8, int16, int32, uint, uint8, uint16, uint32, float32
29 | func typeFor(k reflect.Kind) reflect.Type {
30 | if k > 0 && int(k) < len(kindToType) {
31 | return kindToType[k]
32 | }
33 | return nil
34 | }
35 |
36 | func simpleValueCoercion(object interface{}) (interface{}, error) {
37 | switch original := object.(type) {
38 | case string, bool, int64, uint64, float64, time.Time:
39 | return original, nil
40 | case int:
41 | return int64(original), nil
42 | case int8:
43 | return int64(original), nil
44 | case int16:
45 | return int64(original), nil
46 | case int32:
47 | return int64(original), nil
48 | case uint:
49 | return uint64(original), nil
50 | case uint8:
51 | return uint64(original), nil
52 | case uint16:
53 | return uint64(original), nil
54 | case uint32:
55 | return uint64(original), nil
56 | case float32:
57 | return float64(original), nil
58 | case fmt.Stringer:
59 | return original.String(), nil
60 | default:
61 | return nil, fmt.Errorf("cannot convert type %T to Tree", object)
62 | }
63 | }
64 |
65 | func sliceToTree(object interface{}) (interface{}, error) {
66 | // arrays are a bit tricky, since they can represent either a
67 | // collection of simple values, which is represented by one
68 | // *tomlValue, or an array of tables, which is represented by an
69 | // array of *Tree.
70 |
71 | // holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice
72 | value := reflect.ValueOf(object)
73 | insideType := value.Type().Elem()
74 | length := value.Len()
75 | if length > 0 {
76 | insideType = reflect.ValueOf(value.Index(0).Interface()).Type()
77 | }
78 | if insideType.Kind() == reflect.Map {
79 | // this is considered as an array of tables
80 | tablesArray := make([]*Tree, 0, length)
81 | for i := 0; i < length; i++ {
82 | table := value.Index(i)
83 | tree, err := toTree(table.Interface())
84 | if err != nil {
85 | return nil, err
86 | }
87 | tablesArray = append(tablesArray, tree.(*Tree))
88 | }
89 | return tablesArray, nil
90 | }
91 |
92 | sliceType := typeFor(insideType.Kind())
93 | if sliceType == nil {
94 | sliceType = insideType
95 | }
96 |
97 | arrayValue := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, length)
98 |
99 | for i := 0; i < length; i++ {
100 | val := value.Index(i).Interface()
101 | simpleValue, err := simpleValueCoercion(val)
102 | if err != nil {
103 | return nil, err
104 | }
105 | arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue))
106 | }
107 | return &tomlValue{value: arrayValue.Interface(), position: Position{}}, nil
108 | }
109 |
110 | func toTree(object interface{}) (interface{}, error) {
111 | value := reflect.ValueOf(object)
112 |
113 | if value.Kind() == reflect.Map {
114 | values := map[string]interface{}{}
115 | keys := value.MapKeys()
116 | for _, key := range keys {
117 | if key.Kind() != reflect.String {
118 | if _, ok := key.Interface().(string); !ok {
119 | return nil, fmt.Errorf("map key needs to be a string, not %T (%v)", key.Interface(), key.Kind())
120 | }
121 | }
122 |
123 | v := value.MapIndex(key)
124 | newValue, err := toTree(v.Interface())
125 | if err != nil {
126 | return nil, err
127 | }
128 | values[key.String()] = newValue
129 | }
130 | return &Tree{values: values, position: Position{}}, nil
131 | }
132 |
133 | if value.Kind() == reflect.Array || value.Kind() == reflect.Slice {
134 | return sliceToTree(object)
135 | }
136 |
137 | simpleValue, err := simpleValueCoercion(object)
138 | if err != nil {
139 | return nil, err
140 | }
141 | return &tomlValue{value: simpleValue, position: Position{}}, nil
142 | }
143 |
--------------------------------------------------------------------------------
/vendor/github.com/pelletier/go-toml/tomltree_write.go:
--------------------------------------------------------------------------------
1 | package toml
2 |
3 | import (
4 | "bytes"
5 | "fmt"
6 | "io"
7 | "math"
8 | "reflect"
9 | "sort"
10 | "strconv"
11 | "strings"
12 | "time"
13 | )
14 |
15 | // encodes a string to a TOML-compliant string value
16 | func encodeTomlString(value string) string {
17 | var b bytes.Buffer
18 |
19 | for _, rr := range value {
20 | switch rr {
21 | case '\b':
22 | b.WriteString(`\b`)
23 | case '\t':
24 | b.WriteString(`\t`)
25 | case '\n':
26 | b.WriteString(`\n`)
27 | case '\f':
28 | b.WriteString(`\f`)
29 | case '\r':
30 | b.WriteString(`\r`)
31 | case '"':
32 | b.WriteString(`\"`)
33 | case '\\':
34 | b.WriteString(`\\`)
35 | default:
36 | intRr := uint16(rr)
37 | if intRr < 0x001F {
38 | b.WriteString(fmt.Sprintf("\\u%0.4X", intRr))
39 | } else {
40 | b.WriteRune(rr)
41 | }
42 | }
43 | }
44 | return b.String()
45 | }
46 |
47 | func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) {
48 | switch value := v.(type) {
49 | case uint64:
50 | return strconv.FormatUint(value, 10), nil
51 | case int64:
52 | return strconv.FormatInt(value, 10), nil
53 | case float64:
54 | // Ensure a round float does contain a decimal point. Otherwise feeding
55 | // the output back to the parser would convert to an integer.
56 | if math.Trunc(value) == value {
57 | return strings.ToLower(strconv.FormatFloat(value, 'f', 1, 32)), nil
58 | }
59 | return strings.ToLower(strconv.FormatFloat(value, 'f', -1, 32)), nil
60 | case string:
61 | return "\"" + encodeTomlString(value) + "\"", nil
62 | case []byte:
63 | b, _ := v.([]byte)
64 | return tomlValueStringRepresentation(string(b), indent, arraysOneElementPerLine)
65 | case bool:
66 | if value {
67 | return "true", nil
68 | }
69 | return "false", nil
70 | case time.Time:
71 | return value.Format(time.RFC3339), nil
72 | case nil:
73 | return "", nil
74 | }
75 |
76 | rv := reflect.ValueOf(v)
77 |
78 | if rv.Kind() == reflect.Slice {
79 | var values []string
80 | for i := 0; i < rv.Len(); i++ {
81 | item := rv.Index(i).Interface()
82 | itemRepr, err := tomlValueStringRepresentation(item, indent, arraysOneElementPerLine)
83 | if err != nil {
84 | return "", err
85 | }
86 | values = append(values, itemRepr)
87 | }
88 | if arraysOneElementPerLine && len(values) > 1 {
89 | stringBuffer := bytes.Buffer{}
90 | valueIndent := indent + ` ` // TODO: move that to a shared encoder state
91 |
92 | stringBuffer.WriteString("[\n")
93 |
94 | for i, value := range values {
95 | stringBuffer.WriteString(valueIndent)
96 | stringBuffer.WriteString(value)
97 | if i != len(values)-1 {
98 | stringBuffer.WriteString(`,`)
99 | }
100 | stringBuffer.WriteString("\n")
101 | }
102 |
103 | stringBuffer.WriteString(indent + "]")
104 |
105 | return stringBuffer.String(), nil
106 | }
107 | return "[" + strings.Join(values, ",") + "]", nil
108 | }
109 | return "", fmt.Errorf("unsupported value type %T: %v", v, v)
110 | }
111 |
112 | func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) {
113 | simpleValuesKeys := make([]string, 0)
114 | complexValuesKeys := make([]string, 0)
115 |
116 | for k := range t.values {
117 | v := t.values[k]
118 | switch v.(type) {
119 | case *Tree, []*Tree:
120 | complexValuesKeys = append(complexValuesKeys, k)
121 | default:
122 | simpleValuesKeys = append(simpleValuesKeys, k)
123 | }
124 | }
125 |
126 | sort.Strings(simpleValuesKeys)
127 | sort.Strings(complexValuesKeys)
128 |
129 | for _, k := range simpleValuesKeys {
130 | v, ok := t.values[k].(*tomlValue)
131 | if !ok {
132 | return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
133 | }
134 |
135 | repr, err := tomlValueStringRepresentation(v.value, indent, arraysOneElementPerLine)
136 | if err != nil {
137 | return bytesCount, err
138 | }
139 |
140 | if v.comment != "" {
141 | comment := strings.Replace(v.comment, "\n", "\n"+indent+"#", -1)
142 | start := "# "
143 | if strings.HasPrefix(comment, "#") {
144 | start = ""
145 | }
146 | writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment, "\n")
147 | bytesCount += int64(writtenBytesCountComment)
148 | if errc != nil {
149 | return bytesCount, errc
150 | }
151 | }
152 |
153 | var commented string
154 | if v.commented {
155 | commented = "# "
156 | }
157 | writtenBytesCount, err := writeStrings(w, indent, commented, k, " = ", repr, "\n")
158 | bytesCount += int64(writtenBytesCount)
159 | if err != nil {
160 | return bytesCount, err
161 | }
162 | }
163 |
164 | for _, k := range complexValuesKeys {
165 | v := t.values[k]
166 |
167 | combinedKey := k
168 | if keyspace != "" {
169 | combinedKey = keyspace + "." + combinedKey
170 | }
171 | var commented string
172 | if t.commented {
173 | commented = "# "
174 | }
175 |
176 | switch node := v.(type) {
177 | // node has to be of those two types given how keys are sorted above
178 | case *Tree:
179 | tv, ok := t.values[k].(*Tree)
180 | if !ok {
181 | return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
182 | }
183 | if tv.comment != "" {
184 | comment := strings.Replace(tv.comment, "\n", "\n"+indent+"#", -1)
185 | start := "# "
186 | if strings.HasPrefix(comment, "#") {
187 | start = ""
188 | }
189 | writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment)
190 | bytesCount += int64(writtenBytesCountComment)
191 | if errc != nil {
192 | return bytesCount, errc
193 | }
194 | }
195 | writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n")
196 | bytesCount += int64(writtenBytesCount)
197 | if err != nil {
198 | return bytesCount, err
199 | }
200 | bytesCount, err = node.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine)
201 | if err != nil {
202 | return bytesCount, err
203 | }
204 | case []*Tree:
205 | for _, subTree := range node {
206 | writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[[", combinedKey, "]]\n")
207 | bytesCount += int64(writtenBytesCount)
208 | if err != nil {
209 | return bytesCount, err
210 | }
211 |
212 | bytesCount, err = subTree.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine)
213 | if err != nil {
214 | return bytesCount, err
215 | }
216 | }
217 | }
218 | }
219 |
220 | return bytesCount, nil
221 | }
222 |
223 | func writeStrings(w io.Writer, s ...string) (int, error) {
224 | var n int
225 | for i := range s {
226 | b, err := io.WriteString(w, s[i])
227 | n += b
228 | if err != nil {
229 | return n, err
230 | }
231 | }
232 | return n, nil
233 | }
234 |
235 | // WriteTo encode the Tree as Toml and writes it to the writer w.
236 | // Returns the number of bytes written in case of success, or an error if anything happened.
237 | func (t *Tree) WriteTo(w io.Writer) (int64, error) {
238 | return t.writeTo(w, "", "", 0, false)
239 | }
240 |
241 | // ToTomlString generates a human-readable representation of the current tree.
242 | // Output spans multiple lines, and is suitable for ingest by a TOML parser.
243 | // If the conversion cannot be performed, ToString returns a non-nil error.
244 | func (t *Tree) ToTomlString() (string, error) {
245 | var buf bytes.Buffer
246 | _, err := t.WriteTo(&buf)
247 | if err != nil {
248 | return "", err
249 | }
250 | return buf.String(), nil
251 | }
252 |
253 | // String generates a human-readable representation of the current tree.
254 | // Alias of ToString. Present to implement the fmt.Stringer interface.
255 | func (t *Tree) String() string {
256 | result, _ := t.ToTomlString()
257 | return result
258 | }
259 |
260 | // ToMap recursively generates a representation of the tree using Go built-in structures.
261 | // The following types are used:
262 | //
263 | // * bool
264 | // * float64
265 | // * int64
266 | // * string
267 | // * uint64
268 | // * time.Time
269 | // * map[string]interface{} (where interface{} is any of this list)
270 | // * []interface{} (where interface{} is any of this list)
271 | func (t *Tree) ToMap() map[string]interface{} {
272 | result := map[string]interface{}{}
273 |
274 | for k, v := range t.values {
275 | switch node := v.(type) {
276 | case []*Tree:
277 | var array []interface{}
278 | for _, item := range node {
279 | array = append(array, item.ToMap())
280 | }
281 | result[k] = array
282 | case *Tree:
283 | result[k] = node.ToMap()
284 | case *tomlValue:
285 | result[k] = node.value
286 | }
287 | }
288 | return result
289 | }
290 |
--------------------------------------------------------------------------------
/vendor/github.com/petar/GoLLRB/AUTHORS:
--------------------------------------------------------------------------------
1 | Petar Maymounkov
2 | Vadim Vygonets
3 | Ian Smith
4 | Martin Bruse
5 |
--------------------------------------------------------------------------------
/vendor/github.com/petar/GoLLRB/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2010, Petar Maymounkov
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification,
5 | are permitted provided that the following conditions are met:
6 |
7 | (*) Redistributions of source code must retain the above copyright notice, this list
8 | of conditions and the following disclaimer.
9 |
10 | (*) Redistributions in binary form must reproduce the above copyright notice, this
11 | list of conditions and the following disclaimer in the documentation and/or
12 | other materials provided with the distribution.
13 |
14 | (*) Neither the name of Petar Maymounkov nor the names of its contributors may be
15 | used to endorse or promote products derived from this software without specific
16 | prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/vendor/github.com/petar/GoLLRB/llrb/avgvar.go:
--------------------------------------------------------------------------------
1 | // Copyright 2010 Petar Maymounkov. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package llrb
6 |
7 | import "math"
8 |
9 | // avgVar maintains the average and variance of a stream of numbers
10 | // in a space-efficient manner.
11 | type avgVar struct {
12 | count int64
13 | sum, sumsq float64
14 | }
15 |
16 | func (av *avgVar) Init() {
17 | av.count = 0
18 | av.sum = 0.0
19 | av.sumsq = 0.0
20 | }
21 |
22 | func (av *avgVar) Add(sample float64) {
23 | av.count++
24 | av.sum += sample
25 | av.sumsq += sample * sample
26 | }
27 |
28 | func (av *avgVar) GetCount() int64 { return av.count }
29 |
30 | func (av *avgVar) GetAvg() float64 { return av.sum / float64(av.count) }
31 |
32 | func (av *avgVar) GetTotal() float64 { return av.sum }
33 |
34 | func (av *avgVar) GetVar() float64 {
35 | a := av.GetAvg()
36 | return av.sumsq/float64(av.count) - a*a
37 | }
38 |
39 | func (av *avgVar) GetStdDev() float64 { return math.Sqrt(av.GetVar()) }
40 |
--------------------------------------------------------------------------------
/vendor/github.com/petar/GoLLRB/llrb/iterator.go:
--------------------------------------------------------------------------------
1 | package llrb
2 |
3 | type ItemIterator func(i Item) bool
4 |
5 | //func (t *Tree) Ascend(iterator ItemIterator) {
6 | // t.AscendGreaterOrEqual(Inf(-1), iterator)
7 | //}
8 |
9 | func (t *LLRB) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator) {
10 | t.ascendRange(t.root, greaterOrEqual, lessThan, iterator)
11 | }
12 |
13 | func (t *LLRB) ascendRange(h *Node, inf, sup Item, iterator ItemIterator) bool {
14 | if h == nil {
15 | return true
16 | }
17 | if !less(h.Item, sup) {
18 | return t.ascendRange(h.Left, inf, sup, iterator)
19 | }
20 | if less(h.Item, inf) {
21 | return t.ascendRange(h.Right, inf, sup, iterator)
22 | }
23 |
24 | if !t.ascendRange(h.Left, inf, sup, iterator) {
25 | return false
26 | }
27 | if !iterator(h.Item) {
28 | return false
29 | }
30 | return t.ascendRange(h.Right, inf, sup, iterator)
31 | }
32 |
33 | // AscendGreaterOrEqual will call iterator once for each element greater or equal to
34 | // pivot in ascending order. It will stop whenever the iterator returns false.
35 | func (t *LLRB) AscendGreaterOrEqual(pivot Item, iterator ItemIterator) {
36 | t.ascendGreaterOrEqual(t.root, pivot, iterator)
37 | }
38 |
39 | func (t *LLRB) ascendGreaterOrEqual(h *Node, pivot Item, iterator ItemIterator) bool {
40 | if h == nil {
41 | return true
42 | }
43 | if !less(h.Item, pivot) {
44 | if !t.ascendGreaterOrEqual(h.Left, pivot, iterator) {
45 | return false
46 | }
47 | if !iterator(h.Item) {
48 | return false
49 | }
50 | }
51 | return t.ascendGreaterOrEqual(h.Right, pivot, iterator)
52 | }
53 |
54 | func (t *LLRB) AscendLessThan(pivot Item, iterator ItemIterator) {
55 | t.ascendLessThan(t.root, pivot, iterator)
56 | }
57 |
58 | func (t *LLRB) ascendLessThan(h *Node, pivot Item, iterator ItemIterator) bool {
59 | if h == nil {
60 | return true
61 | }
62 | if !t.ascendLessThan(h.Left, pivot, iterator) {
63 | return false
64 | }
65 | if !iterator(h.Item) {
66 | return false
67 | }
68 | if less(h.Item, pivot) {
69 | return t.ascendLessThan(h.Left, pivot, iterator)
70 | }
71 | return true
72 | }
73 |
74 | // DescendLessOrEqual will call iterator once for each element less than the
75 | // pivot in descending order. It will stop whenever the iterator returns false.
76 | func (t *LLRB) DescendLessOrEqual(pivot Item, iterator ItemIterator) {
77 | t.descendLessOrEqual(t.root, pivot, iterator)
78 | }
79 |
80 | func (t *LLRB) descendLessOrEqual(h *Node, pivot Item, iterator ItemIterator) bool {
81 | if h == nil {
82 | return true
83 | }
84 | if less(h.Item, pivot) || !less(pivot, h.Item) {
85 | if !t.descendLessOrEqual(h.Right, pivot, iterator) {
86 | return false
87 | }
88 | if !iterator(h.Item) {
89 | return false
90 | }
91 | }
92 | return t.descendLessOrEqual(h.Left, pivot, iterator)
93 | }
94 |
--------------------------------------------------------------------------------
/vendor/github.com/petar/GoLLRB/llrb/llrb-stats.go:
--------------------------------------------------------------------------------
1 | // Copyright 2010 Petar Maymounkov. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package llrb
6 |
7 | // GetHeight() returns an item in the tree with key @key, and it's height in the tree
8 | func (t *LLRB) GetHeight(key Item) (result Item, depth int) {
9 | return t.getHeight(t.root, key)
10 | }
11 |
12 | func (t *LLRB) getHeight(h *Node, item Item) (Item, int) {
13 | if h == nil {
14 | return nil, 0
15 | }
16 | if less(item, h.Item) {
17 | result, depth := t.getHeight(h.Left, item)
18 | return result, depth + 1
19 | }
20 | if less(h.Item, item) {
21 | result, depth := t.getHeight(h.Right, item)
22 | return result, depth + 1
23 | }
24 | return h.Item, 0
25 | }
26 |
27 | // HeightStats() returns the average and standard deviation of the height
28 | // of elements in the tree
29 | func (t *LLRB) HeightStats() (avg, stddev float64) {
30 | av := &avgVar{}
31 | heightStats(t.root, 0, av)
32 | return av.GetAvg(), av.GetStdDev()
33 | }
34 |
35 | func heightStats(h *Node, d int, av *avgVar) {
36 | if h == nil {
37 | return
38 | }
39 | av.Add(float64(d))
40 | if h.Left != nil {
41 | heightStats(h.Left, d+1, av)
42 | }
43 | if h.Right != nil {
44 | heightStats(h.Right, d+1, av)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/vendor/github.com/petar/GoLLRB/llrb/util.go:
--------------------------------------------------------------------------------
1 | // Copyright 2010 Petar Maymounkov. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package llrb
6 |
7 | type Int int
8 |
9 | func (x Int) Less(than Item) bool {
10 | return x < than.(Int)
11 | }
12 |
13 | type String string
14 |
15 | func (x String) Less(than Item) bool {
16 | return x < than.(String)
17 | }
18 |
--------------------------------------------------------------------------------
/vendor/github.com/peterbourgon/diskv/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011-2012 Peter Bourgon
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/vendor/github.com/peterbourgon/diskv/README.md:
--------------------------------------------------------------------------------
1 | # What is diskv?
2 |
3 | Diskv (disk-vee) is a simple, persistent key-value store written in the Go
4 | language. It starts with an incredibly simple API for storing arbitrary data on
5 | a filesystem by key, and builds several layers of performance-enhancing
6 | abstraction on top. The end result is a conceptually simple, but highly
7 | performant, disk-backed storage system.
8 |
9 | [![Build Status][1]][2]
10 |
11 | [1]: https://drone.io/github.com/peterbourgon/diskv/status.png
12 | [2]: https://drone.io/github.com/peterbourgon/diskv/latest
13 |
14 |
15 | # Installing
16 |
17 | Install [Go 1][3], either [from source][4] or [with a prepackaged binary][5].
18 | Then,
19 |
20 | ```bash
21 | $ go get github.com/peterbourgon/diskv
22 | ```
23 |
24 | [3]: http://golang.org
25 | [4]: http://golang.org/doc/install/source
26 | [5]: http://golang.org/doc/install
27 |
28 |
29 | # Usage
30 |
31 | ```go
32 | package main
33 |
34 | import (
35 | "fmt"
36 | "github.com/peterbourgon/diskv"
37 | )
38 |
39 | func main() {
40 | // Simplest transform function: put all the data files into the base dir.
41 | flatTransform := func(s string) []string { return []string{} }
42 |
43 | // Initialize a new diskv store, rooted at "my-data-dir", with a 1MB cache.
44 | d := diskv.New(diskv.Options{
45 | BasePath: "my-data-dir",
46 | Transform: flatTransform,
47 | CacheSizeMax: 1024 * 1024,
48 | })
49 |
50 | // Write three bytes to the key "alpha".
51 | key := "alpha"
52 | d.Write(key, []byte{'1', '2', '3'})
53 |
54 | // Read the value back out of the store.
55 | value, _ := d.Read(key)
56 | fmt.Printf("%v\n", value)
57 |
58 | // Erase the key+value from the store (and the disk).
59 | d.Erase(key)
60 | }
61 | ```
62 |
63 | More complex examples can be found in the "examples" subdirectory.
64 |
65 |
66 | # Theory
67 |
68 | ## Basic idea
69 |
70 | At its core, diskv is a map of a key (`string`) to arbitrary data (`[]byte`).
71 | The data is written to a single file on disk, with the same name as the key.
72 | The key determines where that file will be stored, via a user-provided
73 | `TransformFunc`, which takes a key and returns a slice (`[]string`)
74 | corresponding to a path list where the key file will be stored. The simplest
75 | TransformFunc,
76 |
77 | ```go
78 | func SimpleTransform (key string) []string {
79 | return []string{}
80 | }
81 | ```
82 |
83 | will place all keys in the same, base directory. The design is inspired by
84 | [Redis diskstore][6]; a TransformFunc which emulates the default diskstore
85 | behavior is available in the content-addressable-storage example.
86 |
87 | [6]: http://groups.google.com/group/redis-db/browse_thread/thread/d444bc786689bde9?pli=1
88 |
89 | **Note** that your TransformFunc should ensure that one valid key doesn't
90 | transform to a subset of another valid key. That is, it shouldn't be possible
91 | to construct valid keys that resolve to directory names. As a concrete example,
92 | if your TransformFunc splits on every 3 characters, then
93 |
94 | ```go
95 | d.Write("abcabc", val) // OK: written to /abc/abc/abcabc
96 | d.Write("abc", val) // Error: attempted write to /abc/abc, but it's a directory
97 | ```
98 |
99 | This will be addressed in an upcoming version of diskv.
100 |
101 | Probably the most important design principle behind diskv is that your data is
102 | always flatly available on the disk. diskv will never do anything that would
103 | prevent you from accessing, copying, backing up, or otherwise interacting with
104 | your data via common UNIX commandline tools.
105 |
106 | ## Adding a cache
107 |
108 | An in-memory caching layer is provided by combining the BasicStore
109 | functionality with a simple map structure, and keeping it up-to-date as
110 | appropriate. Since the map structure in Go is not threadsafe, it's combined
111 | with a RWMutex to provide safe concurrent access.
112 |
113 | ## Adding order
114 |
115 | diskv is a key-value store and therefore inherently unordered. An ordering
116 | system can be injected into the store by passing something which satisfies the
117 | diskv.Index interface. (A default implementation, using Google's
118 | [btree][7] package, is provided.) Basically, diskv keeps an ordered (by a
119 | user-provided Less function) index of the keys, which can be queried.
120 |
121 | [7]: https://github.com/google/btree
122 |
123 | ## Adding compression
124 |
125 | Something which implements the diskv.Compression interface may be passed
126 | during store creation, so that all Writes and Reads are filtered through
127 | a compression/decompression pipeline. Several default implementations,
128 | using stdlib compression algorithms, are provided. Note that data is cached
129 | compressed; the cost of decompression is borne with each Read.
130 |
131 | ## Streaming
132 |
133 | diskv also now provides ReadStream and WriteStream methods, to allow very large
134 | data to be handled efficiently.
135 |
136 |
137 | # Future plans
138 |
139 | * Needs plenty of robust testing: huge datasets, etc...
140 | * More thorough benchmarking
141 | * Your suggestions for use-cases I haven't thought of
142 |
--------------------------------------------------------------------------------
/vendor/github.com/peterbourgon/diskv/compression.go:
--------------------------------------------------------------------------------
1 | package diskv
2 |
3 | import (
4 | "compress/flate"
5 | "compress/gzip"
6 | "compress/zlib"
7 | "io"
8 | )
9 |
10 | // Compression is an interface that Diskv uses to implement compression of
11 | // data. Writer takes a destination io.Writer and returns a WriteCloser that
12 | // compresses all data written through it. Reader takes a source io.Reader and
13 | // returns a ReadCloser that decompresses all data read through it. You may
14 | // define these methods on your own type, or use one of the NewCompression
15 | // helpers.
16 | type Compression interface {
17 | Writer(dst io.Writer) (io.WriteCloser, error)
18 | Reader(src io.Reader) (io.ReadCloser, error)
19 | }
20 |
21 | // NewGzipCompression returns a Gzip-based Compression.
22 | func NewGzipCompression() Compression {
23 | return NewGzipCompressionLevel(flate.DefaultCompression)
24 | }
25 |
26 | // NewGzipCompressionLevel returns a Gzip-based Compression with the given level.
27 | func NewGzipCompressionLevel(level int) Compression {
28 | return &genericCompression{
29 | wf: func(w io.Writer) (io.WriteCloser, error) { return gzip.NewWriterLevel(w, level) },
30 | rf: func(r io.Reader) (io.ReadCloser, error) { return gzip.NewReader(r) },
31 | }
32 | }
33 |
34 | // NewZlibCompression returns a Zlib-based Compression.
35 | func NewZlibCompression() Compression {
36 | return NewZlibCompressionLevel(flate.DefaultCompression)
37 | }
38 |
39 | // NewZlibCompressionLevel returns a Zlib-based Compression with the given level.
40 | func NewZlibCompressionLevel(level int) Compression {
41 | return NewZlibCompressionLevelDict(level, nil)
42 | }
43 |
44 | // NewZlibCompressionLevelDict returns a Zlib-based Compression with the given
45 | // level, based on the given dictionary.
46 | func NewZlibCompressionLevelDict(level int, dict []byte) Compression {
47 | return &genericCompression{
48 | func(w io.Writer) (io.WriteCloser, error) { return zlib.NewWriterLevelDict(w, level, dict) },
49 | func(r io.Reader) (io.ReadCloser, error) { return zlib.NewReaderDict(r, dict) },
50 | }
51 | }
52 |
53 | type genericCompression struct {
54 | wf func(w io.Writer) (io.WriteCloser, error)
55 | rf func(r io.Reader) (io.ReadCloser, error)
56 | }
57 |
58 | func (g *genericCompression) Writer(dst io.Writer) (io.WriteCloser, error) {
59 | return g.wf(dst)
60 | }
61 |
62 | func (g *genericCompression) Reader(src io.Reader) (io.ReadCloser, error) {
63 | return g.rf(src)
64 | }
65 |
--------------------------------------------------------------------------------
/vendor/github.com/peterbourgon/diskv/index.go:
--------------------------------------------------------------------------------
1 | package diskv
2 |
3 | import (
4 | "sync"
5 |
6 | "github.com/google/btree"
7 | )
8 |
9 | // Index is a generic interface for things that can
10 | // provide an ordered list of keys.
11 | type Index interface {
12 | Initialize(less LessFunction, keys <-chan string)
13 | Insert(key string)
14 | Delete(key string)
15 | Keys(from string, n int) []string
16 | }
17 |
18 | // LessFunction is used to initialize an Index of keys in a specific order.
19 | type LessFunction func(string, string) bool
20 |
21 | // btreeString is a custom data type that satisfies the BTree Less interface,
22 | // making the strings it wraps sortable by the BTree package.
23 | type btreeString struct {
24 | s string
25 | l LessFunction
26 | }
27 |
28 | // Less satisfies the BTree.Less interface using the btreeString's LessFunction.
29 | func (s btreeString) Less(i btree.Item) bool {
30 | return s.l(s.s, i.(btreeString).s)
31 | }
32 |
33 | // BTreeIndex is an implementation of the Index interface using google/btree.
34 | type BTreeIndex struct {
35 | sync.RWMutex
36 | LessFunction
37 | *btree.BTree
38 | }
39 |
40 | // Initialize populates the BTree tree with data from the keys channel,
41 | // according to the passed less function. It's destructive to the BTreeIndex.
42 | func (i *BTreeIndex) Initialize(less LessFunction, keys <-chan string) {
43 | i.Lock()
44 | defer i.Unlock()
45 | i.LessFunction = less
46 | i.BTree = rebuild(less, keys)
47 | }
48 |
49 | // Insert inserts the given key (only) into the BTree tree.
50 | func (i *BTreeIndex) Insert(key string) {
51 | i.Lock()
52 | defer i.Unlock()
53 | if i.BTree == nil || i.LessFunction == nil {
54 | panic("uninitialized index")
55 | }
56 | i.BTree.ReplaceOrInsert(btreeString{s: key, l: i.LessFunction})
57 | }
58 |
59 | // Delete removes the given key (only) from the BTree tree.
60 | func (i *BTreeIndex) Delete(key string) {
61 | i.Lock()
62 | defer i.Unlock()
63 | if i.BTree == nil || i.LessFunction == nil {
64 | panic("uninitialized index")
65 | }
66 | i.BTree.Delete(btreeString{s: key, l: i.LessFunction})
67 | }
68 |
69 | // Keys yields a maximum of n keys in order. If the passed 'from' key is empty,
70 | // Keys will return the first n keys. If the passed 'from' key is non-empty, the
71 | // first key in the returned slice will be the key that immediately follows the
72 | // passed key, in key order.
73 | func (i *BTreeIndex) Keys(from string, n int) []string {
74 | i.RLock()
75 | defer i.RUnlock()
76 |
77 | if i.BTree == nil || i.LessFunction == nil {
78 | panic("uninitialized index")
79 | }
80 |
81 | if i.BTree.Len() <= 0 {
82 | return []string{}
83 | }
84 |
85 | btreeFrom := btreeString{s: from, l: i.LessFunction}
86 | skipFirst := true
87 | if len(from) <= 0 || !i.BTree.Has(btreeFrom) {
88 | // no such key, so fabricate an always-smallest item
89 | btreeFrom = btreeString{s: "", l: func(string, string) bool { return true }}
90 | skipFirst = false
91 | }
92 |
93 | keys := []string{}
94 | iterator := func(i btree.Item) bool {
95 | keys = append(keys, i.(btreeString).s)
96 | return len(keys) < n
97 | }
98 | i.BTree.AscendGreaterOrEqual(btreeFrom, iterator)
99 |
100 | if skipFirst && len(keys) > 0 {
101 | keys = keys[1:]
102 | }
103 |
104 | return keys
105 | }
106 |
107 | // rebuildIndex does the work of regenerating the index
108 | // with the given keys.
109 | func rebuild(less LessFunction, keys <-chan string) *btree.BTree {
110 | tree := btree.New(2)
111 | for key := range keys {
112 | tree.ReplaceOrInsert(btreeString{s: key, l: less})
113 | }
114 | return tree
115 | }
116 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/AUTHORS:
--------------------------------------------------------------------------------
1 | # This source code refers to The Go Authors for copyright purposes.
2 | # The master list of authors is in the main Go distribution,
3 | # visible at http://tip.golang.org/AUTHORS.
4 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/CONTRIBUTORS:
--------------------------------------------------------------------------------
1 | # This source code was written by the Go contributors.
2 | # The master list of contributors is in the main Go distribution,
3 | # visible at http://tip.golang.org/CONTRIBUTORS.
4 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009 The Go Authors. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are
5 | met:
6 |
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above
10 | copyright notice, this list of conditions and the following disclaimer
11 | in the documentation and/or other materials provided with the
12 | distribution.
13 | * Neither the name of Google Inc. nor the names of its
14 | contributors may be used to endorse or promote products derived from
15 | this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/PATENTS:
--------------------------------------------------------------------------------
1 | Additional IP Rights Grant (Patents)
2 |
3 | "This implementation" means the copyrightable works distributed by
4 | Google as part of the Go project.
5 |
6 | Google hereby grants to You a perpetual, worldwide, non-exclusive,
7 | no-charge, royalty-free, irrevocable (except as stated in this section)
8 | patent license to make, have made, use, offer to sell, sell, import,
9 | transfer and otherwise run, modify and propagate the contents of this
10 | implementation of Go, where such license applies only to those patent
11 | claims, both currently owned or controlled by Google and acquired in
12 | the future, licensable by Google that are necessarily infringed by this
13 | implementation of Go. This grant does not include claims that would be
14 | infringed only as a consequence of further modification of this
15 | implementation. If you or your agent or exclusive licensee institute or
16 | order or agree to the institution of patent litigation against any
17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging
18 | that this implementation of Go or any code incorporated within this
19 | implementation of Go constitutes direct or contributory patent
20 | infringement, or inducement of patent infringement, then any patent
21 | rights granted to you under this License for this implementation of Go
22 | shall terminate as of the date such litigation is filed.
23 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/context/context.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // Package context defines the Context type, which carries deadlines,
6 | // cancelation signals, and other request-scoped values across API boundaries
7 | // and between processes.
8 | // As of Go 1.7 this package is available in the standard library under the
9 | // name context. https://golang.org/pkg/context.
10 | //
11 | // Incoming requests to a server should create a Context, and outgoing calls to
12 | // servers should accept a Context. The chain of function calls between must
13 | // propagate the Context, optionally replacing it with a modified copy created
14 | // using WithDeadline, WithTimeout, WithCancel, or WithValue.
15 | //
16 | // Programs that use Contexts should follow these rules to keep interfaces
17 | // consistent across packages and enable static analysis tools to check context
18 | // propagation:
19 | //
20 | // Do not store Contexts inside a struct type; instead, pass a Context
21 | // explicitly to each function that needs it. The Context should be the first
22 | // parameter, typically named ctx:
23 | //
24 | // func DoSomething(ctx context.Context, arg Arg) error {
25 | // // ... use ctx ...
26 | // }
27 | //
28 | // Do not pass a nil Context, even if a function permits it. Pass context.TODO
29 | // if you are unsure about which Context to use.
30 | //
31 | // Use context Values only for request-scoped data that transits processes and
32 | // APIs, not for passing optional parameters to functions.
33 | //
34 | // The same Context may be passed to functions running in different goroutines;
35 | // Contexts are safe for simultaneous use by multiple goroutines.
36 | //
37 | // See http://blog.golang.org/context for example code for a server that uses
38 | // Contexts.
39 | package context // import "golang.org/x/net/context"
40 |
41 | // Background returns a non-nil, empty Context. It is never canceled, has no
42 | // values, and has no deadline. It is typically used by the main function,
43 | // initialization, and tests, and as the top-level Context for incoming
44 | // requests.
45 | func Background() Context {
46 | return background
47 | }
48 |
49 | // TODO returns a non-nil, empty Context. Code should use context.TODO when
50 | // it's unclear which Context to use or it is not yet available (because the
51 | // surrounding function has not yet been extended to accept a Context
52 | // parameter). TODO is recognized by static analysis tools that determine
53 | // whether Contexts are propagated correctly in a program.
54 | func TODO() Context {
55 | return todo
56 | }
57 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/context/go17.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build go1.7
6 |
7 | package context
8 |
9 | import (
10 | "context" // standard library's context, as of Go 1.7
11 | "time"
12 | )
13 |
14 | var (
15 | todo = context.TODO()
16 | background = context.Background()
17 | )
18 |
19 | // Canceled is the error returned by Context.Err when the context is canceled.
20 | var Canceled = context.Canceled
21 |
22 | // DeadlineExceeded is the error returned by Context.Err when the context's
23 | // deadline passes.
24 | var DeadlineExceeded = context.DeadlineExceeded
25 |
26 | // WithCancel returns a copy of parent with a new Done channel. The returned
27 | // context's Done channel is closed when the returned cancel function is called
28 | // or when the parent context's Done channel is closed, whichever happens first.
29 | //
30 | // Canceling this context releases resources associated with it, so code should
31 | // call cancel as soon as the operations running in this Context complete.
32 | func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
33 | ctx, f := context.WithCancel(parent)
34 | return ctx, CancelFunc(f)
35 | }
36 |
37 | // WithDeadline returns a copy of the parent context with the deadline adjusted
38 | // to be no later than d. If the parent's deadline is already earlier than d,
39 | // WithDeadline(parent, d) is semantically equivalent to parent. The returned
40 | // context's Done channel is closed when the deadline expires, when the returned
41 | // cancel function is called, or when the parent context's Done channel is
42 | // closed, whichever happens first.
43 | //
44 | // Canceling this context releases resources associated with it, so code should
45 | // call cancel as soon as the operations running in this Context complete.
46 | func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
47 | ctx, f := context.WithDeadline(parent, deadline)
48 | return ctx, CancelFunc(f)
49 | }
50 |
51 | // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
52 | //
53 | // Canceling this context releases resources associated with it, so code should
54 | // call cancel as soon as the operations running in this Context complete:
55 | //
56 | // func slowOperationWithTimeout(ctx context.Context) (Result, error) {
57 | // ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
58 | // defer cancel() // releases resources if slowOperation completes before timeout elapses
59 | // return slowOperation(ctx)
60 | // }
61 | func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
62 | return WithDeadline(parent, time.Now().Add(timeout))
63 | }
64 |
65 | // WithValue returns a copy of parent in which the value associated with key is
66 | // val.
67 | //
68 | // Use context Values only for request-scoped data that transits processes and
69 | // APIs, not for passing optional parameters to functions.
70 | func WithValue(parent Context, key interface{}, val interface{}) Context {
71 | return context.WithValue(parent, key, val)
72 | }
73 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/context/go19.go:
--------------------------------------------------------------------------------
1 | // Copyright 2017 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build go1.9
6 |
7 | package context
8 |
9 | import "context" // standard library's context, as of Go 1.7
10 |
11 | // A Context carries a deadline, a cancelation signal, and other values across
12 | // API boundaries.
13 | //
14 | // Context's methods may be called by multiple goroutines simultaneously.
15 | type Context = context.Context
16 |
17 | // A CancelFunc tells an operation to abandon its work.
18 | // A CancelFunc does not wait for the work to stop.
19 | // After the first call, subsequent calls to a CancelFunc do nothing.
20 | type CancelFunc = context.CancelFunc
21 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/context/pre_go19.go:
--------------------------------------------------------------------------------
1 | // Copyright 2014 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // +build !go1.9
6 |
7 | package context
8 |
9 | import "time"
10 |
11 | // A Context carries a deadline, a cancelation signal, and other values across
12 | // API boundaries.
13 | //
14 | // Context's methods may be called by multiple goroutines simultaneously.
15 | type Context interface {
16 | // Deadline returns the time when work done on behalf of this context
17 | // should be canceled. Deadline returns ok==false when no deadline is
18 | // set. Successive calls to Deadline return the same results.
19 | Deadline() (deadline time.Time, ok bool)
20 |
21 | // Done returns a channel that's closed when work done on behalf of this
22 | // context should be canceled. Done may return nil if this context can
23 | // never be canceled. Successive calls to Done return the same value.
24 | //
25 | // WithCancel arranges for Done to be closed when cancel is called;
26 | // WithDeadline arranges for Done to be closed when the deadline
27 | // expires; WithTimeout arranges for Done to be closed when the timeout
28 | // elapses.
29 | //
30 | // Done is provided for use in select statements:
31 | //
32 | // // Stream generates values with DoSomething and sends them to out
33 | // // until DoSomething returns an error or ctx.Done is closed.
34 | // func Stream(ctx context.Context, out chan<- Value) error {
35 | // for {
36 | // v, err := DoSomething(ctx)
37 | // if err != nil {
38 | // return err
39 | // }
40 | // select {
41 | // case <-ctx.Done():
42 | // return ctx.Err()
43 | // case out <- v:
44 | // }
45 | // }
46 | // }
47 | //
48 | // See http://blog.golang.org/pipelines for more examples of how to use
49 | // a Done channel for cancelation.
50 | Done() <-chan struct{}
51 |
52 | // Err returns a non-nil error value after Done is closed. Err returns
53 | // Canceled if the context was canceled or DeadlineExceeded if the
54 | // context's deadline passed. No other values for Err are defined.
55 | // After Done is closed, successive calls to Err return the same value.
56 | Err() error
57 |
58 | // Value returns the value associated with this context for key, or nil
59 | // if no value is associated with key. Successive calls to Value with
60 | // the same key returns the same result.
61 | //
62 | // Use context values only for request-scoped data that transits
63 | // processes and API boundaries, not for passing optional parameters to
64 | // functions.
65 | //
66 | // A key identifies a specific value in a Context. Functions that wish
67 | // to store values in Context typically allocate a key in a global
68 | // variable then use that key as the argument to context.WithValue and
69 | // Context.Value. A key can be any type that supports equality;
70 | // packages should define keys as an unexported type to avoid
71 | // collisions.
72 | //
73 | // Packages that define a Context key should provide type-safe accessors
74 | // for the values stores using that key:
75 | //
76 | // // Package user defines a User type that's stored in Contexts.
77 | // package user
78 | //
79 | // import "golang.org/x/net/context"
80 | //
81 | // // User is the type of value stored in the Contexts.
82 | // type User struct {...}
83 | //
84 | // // key is an unexported type for keys defined in this package.
85 | // // This prevents collisions with keys defined in other packages.
86 | // type key int
87 | //
88 | // // userKey is the key for user.User values in Contexts. It is
89 | // // unexported; clients use user.NewContext and user.FromContext
90 | // // instead of using this key directly.
91 | // var userKey key = 0
92 | //
93 | // // NewContext returns a new Context that carries value u.
94 | // func NewContext(ctx context.Context, u *User) context.Context {
95 | // return context.WithValue(ctx, userKey, u)
96 | // }
97 | //
98 | // // FromContext returns the User value stored in ctx, if any.
99 | // func FromContext(ctx context.Context) (*User, bool) {
100 | // u, ok := ctx.Value(userKey).(*User)
101 | // return u, ok
102 | // }
103 | Value(key interface{}) interface{}
104 | }
105 |
106 | // A CancelFunc tells an operation to abandon its work.
107 | // A CancelFunc does not wait for the work to stop.
108 | // After the first call, subsequent calls to a CancelFunc do nothing.
109 | type CancelFunc func()
110 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/sync/AUTHORS:
--------------------------------------------------------------------------------
1 | # This source code refers to The Go Authors for copyright purposes.
2 | # The master list of authors is in the main Go distribution,
3 | # visible at http://tip.golang.org/AUTHORS.
4 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/sync/CONTRIBUTORS:
--------------------------------------------------------------------------------
1 | # This source code was written by the Go contributors.
2 | # The master list of contributors is in the main Go distribution,
3 | # visible at http://tip.golang.org/CONTRIBUTORS.
4 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/sync/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009 The Go Authors. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are
5 | met:
6 |
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above
10 | copyright notice, this list of conditions and the following disclaimer
11 | in the documentation and/or other materials provided with the
12 | distribution.
13 | * Neither the name of Google Inc. nor the names of its
14 | contributors may be used to endorse or promote products derived from
15 | this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/sync/PATENTS:
--------------------------------------------------------------------------------
1 | Additional IP Rights Grant (Patents)
2 |
3 | "This implementation" means the copyrightable works distributed by
4 | Google as part of the Go project.
5 |
6 | Google hereby grants to You a perpetual, worldwide, non-exclusive,
7 | no-charge, royalty-free, irrevocable (except as stated in this section)
8 | patent license to make, have made, use, offer to sell, sell, import,
9 | transfer and otherwise run, modify and propagate the contents of this
10 | implementation of Go, where such license applies only to those patent
11 | claims, both currently owned or controlled by Google and acquired in
12 | the future, licensable by Google that are necessarily infringed by this
13 | implementation of Go. This grant does not include claims that would be
14 | infringed only as a consequence of further modification of this
15 | implementation. If you or your agent or exclusive licensee institute or
16 | order or agree to the institution of patent litigation against any
17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging
18 | that this implementation of Go or any code incorporated within this
19 | implementation of Go constitutes direct or contributory patent
20 | infringement, or inducement of patent infringement, then any patent
21 | rights granted to you under this License for this implementation of Go
22 | shall terminate as of the date such litigation is filed.
23 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/sync/errgroup/errgroup.go:
--------------------------------------------------------------------------------
1 | // Copyright 2016 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // Package errgroup provides synchronization, error propagation, and Context
6 | // cancelation for groups of goroutines working on subtasks of a common task.
7 | package errgroup
8 |
9 | import (
10 | "sync"
11 |
12 | "golang.org/x/net/context"
13 | )
14 |
15 | // A Group is a collection of goroutines working on subtasks that are part of
16 | // the same overall task.
17 | //
18 | // A zero Group is valid and does not cancel on error.
19 | type Group struct {
20 | cancel func()
21 |
22 | wg sync.WaitGroup
23 |
24 | errOnce sync.Once
25 | err error
26 | }
27 |
28 | // WithContext returns a new Group and an associated Context derived from ctx.
29 | //
30 | // The derived Context is canceled the first time a function passed to Go
31 | // returns a non-nil error or the first time Wait returns, whichever occurs
32 | // first.
33 | func WithContext(ctx context.Context) (*Group, context.Context) {
34 | ctx, cancel := context.WithCancel(ctx)
35 | return &Group{cancel: cancel}, ctx
36 | }
37 |
38 | // Wait blocks until all function calls from the Go method have returned, then
39 | // returns the first non-nil error (if any) from them.
40 | func (g *Group) Wait() error {
41 | g.wg.Wait()
42 | if g.cancel != nil {
43 | g.cancel()
44 | }
45 | return g.err
46 | }
47 |
48 | // Go calls the given function in a new goroutine.
49 | //
50 | // The first call to return a non-nil error cancels the group; its error will be
51 | // returned by Wait.
52 | func (g *Group) Go(f func() error) {
53 | g.wg.Add(1)
54 |
55 | go func() {
56 | defer g.wg.Done()
57 |
58 | if err := f(); err != nil {
59 | g.errOnce.Do(func() {
60 | g.err = err
61 | if g.cancel != nil {
62 | g.cancel()
63 | }
64 | })
65 | }
66 | }()
67 | }
68 |
--------------------------------------------------------------------------------