lib/github: fixes GithubAPI::get documentation
[nit.git] / lib / github / api.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
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 # Nit object oriented interface to Github api.
16 #
17 # This modules reifies Github API elements as Nit classes.
18 #
19 # For most use-cases you need to use the `GithubAPI` client.
20 module api
21
22 import github_curl
23
24 # Interface to Github REST API.
25 #
26 # Used by all `GithubEntity` to perform requests.
27 #
28 # Usage:
29 #
30 # ~~~
31 # # Get Github authentification token.
32 # var token = get_github_oauth
33 # assert not token.is_empty
34 #
35 # # Init the client.
36 # var api = new GithubAPI(token)
37 # ~~~
38 #
39 # The API client allows to get Github API entities:
40 #
41 # ~~~
42 # var repo = api.load_repo("privat/nit")
43 # assert repo isa Repo
44 # assert repo.name == "nit"
45 #
46 # var user = api.load_user("Morriar")
47 # assert user isa User
48 # assert user.login == "Morriar"
49 # ~~~
50 class GithubAPI
51
52 # Github API OAuth token.
53 #
54 # This token is used to authenticate the application on Github API.
55 # Be aware that there is [rate limits](https://developer.github.com/v3/rate_limit/)
56 # associated to the key.
57 var auth: String
58
59 # Github API base url.
60 #
61 # Default is `https://api.github.com` and should not be changed.
62 var api_url = "https://api.github.com"
63
64 # User agent used for HTTP requests.
65 #
66 # Default is `nit_github_api`.
67 #
68 # See <https://developer.github.com/v3/#user-agent-required>
69 var user_agent = "nit_github_api"
70
71 # Curl instance.
72 #
73 # Internal Curl instance used to perform API calls.
74 private var ghcurl: GithubCurl is noinit
75
76 # Verbosity level.
77 #
78 # * `0`: only errors (default)
79 # * `1`: verbose
80 var verbose_lvl = 0 is public writable
81
82 init do
83 ghcurl = new GithubCurl(auth, user_agent)
84 end
85
86 # Execute a GET request on Github API.
87 #
88 # This method returns raw json data.
89 # See other `load_*` methods to use more expressive types.
90 #
91 # var api = new GithubAPI(get_github_oauth)
92 # var obj = api.get("repos/privat/nit")
93 # assert obj isa JsonObject
94 # assert obj["name"] == "nit"
95 #
96 # Returns `null` in case of `error`.
97 #
98 # obj = api.get("foo/bar/baz")
99 # assert obj == null
100 # assert api.was_error
101 # var err = api.last_error
102 # assert err isa GithubError
103 # assert err.name == "GithubAPIError"
104 # assert err.message == "Not Found"
105 fun get(path: String): nullable Jsonable do
106 path = sanitize_uri(path)
107 var res = ghcurl.get_and_parse("{api_url}/{path}")
108 if res isa Error then
109 last_error = res
110 was_error = true
111 return null
112 end
113 was_error = false
114 return res
115 end
116
117 # Display a message depending on `verbose_lvl`.
118 fun message(lvl: Int, message: String) do
119 if lvl <= verbose_lvl then print message
120 end
121
122 # Escape `uri` in an acceptable format for Github.
123 private fun sanitize_uri(uri: String): String do
124 # TODO better URI escape.
125 return uri.replace(" ", "%20")
126 end
127
128 # Last error occured during Github API communications.
129 var last_error: nullable Error = null is public writable
130
131 # Does the last request provoqued an error?
132 var was_error = false is protected writable
133
134 # Load the json object from Github.
135 # See `GithubEntity::load_from_github`.
136 private fun load_from_github(key: String): JsonObject do
137 message(1, "Get {key} (github)")
138 var res = get(key)
139 if was_error then return new JsonObject
140 return res.as(JsonObject)
141 end
142
143 # Get the Github user with `login`.
144 #
145 # Returns `null` if the user cannot be found.
146 #
147 # var api = new GithubAPI(get_github_oauth)
148 # var user = api.load_user("Morriar")
149 # assert user.login == "Morriar"
150 fun load_user(login: String): nullable User do
151 var user = new User(self, login)
152 user.load_from_github
153 if was_error then return null
154 return user
155 end
156
157 # Get the Github repo with `full_name`.
158 #
159 # Returns `null` if the repo cannot be found.
160 #
161 # var api = new GithubAPI(get_github_oauth)
162 # var repo = api.load_repo("privat/nit")
163 # assert repo.name == "nit"
164 # assert repo.owner.login == "privat"
165 fun load_repo(full_name: String): nullable Repo do
166 var repo = new Repo(self, full_name)
167 repo.load_from_github
168 if was_error then return null
169 return repo
170 end
171 end
172
173 # Something returned by the Github API.
174 #
175 # Mainly a Nit wrapper around a JSON objet.
176 abstract class GithubEntity
177
178 # Github API instance.
179 var api: GithubAPI
180
181 # FIXME constructor should be private
182
183 # Key used to access this entity from Github api base.
184 fun key: String is abstract
185
186 # JSON representation of `self`.
187 #
188 # This is the same json structure than used by Github API.
189 var json: JsonObject is noinit, protected writable
190
191 # Load `json` from Github API.
192 private fun load_from_github do
193 json = api.load_from_github(key)
194 end
195
196 redef fun to_s do return json.to_json
197 end
198
199 # A Github user.
200 #
201 # Should be accessed from `GithubAPI::load_user`.
202 #
203 # See <https://developer.github.com/v3/users/>.
204 class User
205 super GithubEntity
206
207 redef var key is lazy do return "users/{login}"
208
209 # Github login.
210 var login: String
211
212 # Init `self` from a `json` object.
213 init from_json(api: GithubAPI, json: JsonObject) do
214 init(api, json["login"].to_s)
215 self.json = json
216 end
217
218 # Github User page url.
219 fun html_url: String do return json["html_url"].to_s
220
221 # Avatar image url for this user.
222 fun avatar_url: String do return json["avatar_url"].to_s
223 end
224
225 # A Github repository.
226 #
227 # Should be accessed from `GithubAPI::load_repo`.
228 #
229 # See <https://developer.github.com/v3/repos/>.
230 class Repo
231 super GithubEntity
232
233 redef var key is lazy do return "repos/{full_name}"
234
235 # Repo full name on Github.
236 var full_name: String
237
238 # Init `self` from a `json` object.
239 init from_json(api: GithubAPI, json: JsonObject) do
240 init(api, json["full_name"].to_s)
241 self.json = json
242 end
243
244 # Repo short name on Github.
245 fun name: String do return json["name"].to_s
246
247 # Github User page url.
248 fun html_url: String do return json["html_url"].to_s
249
250 # Get the repo owner.
251 fun owner: User do
252 return new User.from_json(api, json["owner"].as(JsonObject))
253 end
254 end