1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
include_once '../../includes/easyparliament/init.php'; |
4
|
|
|
include_once './api_functions.php'; |
5
|
|
|
|
6
|
|
|
# XXX: Need to override error handling! XXX |
7
|
|
|
|
8
|
|
|
if ($q_method = get_http_var('method')) { |
9
|
|
|
if (get_http_var('docs')) { |
10
|
|
|
$key = 'DOCS'; |
11
|
|
|
} else { |
12
|
|
|
$key = get_http_var('key'); |
13
|
|
|
if (!$key) { |
14
|
|
|
api_error('No API key provided. Please see https://www.theyworkforyou.com/api/key for more information.'); |
15
|
|
|
exit; |
16
|
|
|
} |
17
|
|
|
$check = api_check_key($key); |
18
|
|
|
if (!$check) { |
19
|
|
|
api_error('Invalid API key.'); |
20
|
|
|
exit; |
21
|
|
|
} elseif ($check === 'disabled') { |
22
|
|
|
api_error('Your API key has been disabled.'); |
23
|
|
|
exit; |
24
|
|
|
} |
25
|
|
|
} |
26
|
|
|
$match = 0; |
27
|
|
|
foreach ($methods as $method => $data) { |
28
|
|
|
if (strtolower($q_method) == strtolower($method)) { |
29
|
|
|
if (isset($data['superuser']) && $data['superuser']) { |
30
|
|
|
$super_check = api_is_superuser_key($key); |
31
|
|
|
if (!$super_check) { |
32
|
|
|
if (get_http_var('docs')) { |
33
|
|
|
api_front_page(); |
34
|
|
|
} else { |
35
|
|
|
api_error('Invalid API key.'); |
36
|
|
|
exit; |
37
|
|
|
} |
38
|
|
|
} |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
api_log_call($key); |
42
|
|
|
$match++; |
43
|
|
|
if (get_http_var('docs')) { |
44
|
|
|
$_GET['verbose'] = 1; |
45
|
|
|
ob_start(); |
46
|
|
|
} |
47
|
|
|
foreach ($data['parameters'] as $parameter) { |
48
|
|
|
if ($q_param = trim(get_http_var($parameter))) { |
49
|
|
|
$match++; |
50
|
|
|
include_once 'api_' . $method . '.php'; |
51
|
|
|
api_call_user_func_or_error('api_' . $method . '_' . $parameter, [$q_param], 'API call not yet functional', 'api'); |
52
|
|
|
break; |
53
|
|
|
} |
54
|
|
|
} |
55
|
|
|
if ($match == 1 && (get_http_var('output') || !get_http_var('docs'))) { |
56
|
|
|
if ($data['required']) { |
57
|
|
|
api_error('No parameter provided to function "' . |
58
|
|
|
_htmlspecialchars($q_method) . |
59
|
|
|
'". Possible choices are: ' . |
60
|
|
|
join(', ', $data['parameters'])); |
61
|
|
|
} else { |
62
|
|
|
include_once 'api_' . $method . '.php'; |
63
|
|
|
api_call_user_func_or_error('api_' . $method, [], 'API call not yet functional', 'api'); |
64
|
|
|
break; |
65
|
|
|
} |
66
|
|
|
} |
67
|
|
|
break; |
68
|
|
|
} |
69
|
|
|
} |
70
|
|
|
if (!$match) { |
71
|
|
|
api_log_call($key); |
72
|
|
|
$msg = 'Unknown function "' . _htmlspecialchars($q_method) . |
73
|
|
|
'". Possible functions are: ' . |
74
|
|
|
join(', ', array_keys($methods)); |
75
|
|
|
if (get_http_var('output')) { |
76
|
|
|
api_error($msg); |
77
|
|
|
} else { |
78
|
|
|
api_front_page($msg); |
79
|
|
|
} |
80
|
|
|
} else { |
81
|
|
|
if (get_http_var('docs')) { |
82
|
|
|
$explorer = ob_get_clean(); |
83
|
|
|
api_documentation_front($method, $explorer); |
84
|
|
|
} |
85
|
|
|
} |
86
|
|
|
} elseif (get_http_var('docs')) { |
87
|
|
|
api_front_page(); |
88
|
|
|
} else { |
89
|
|
|
$subscription = new MySociety\TheyWorkForYou\Subscription($THEUSER); |
90
|
|
|
MySociety\TheyWorkForYou\Renderer::output('static/api-index', [ |
91
|
|
|
'subscription' => $subscription->stripe, |
92
|
|
|
]); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
function api_documentation_front($method, $explorer) { |
96
|
|
|
global $PAGE, $this_page, $DATA, $THEUSER; |
97
|
|
|
$this_page = 'api_doc_front'; |
98
|
|
|
$DATA->set_page_metadata($this_page, 'title', "$method function"); |
99
|
|
|
$PAGE->page_start(); |
100
|
|
|
$PAGE->stripe_start(); |
101
|
|
|
include_once 'api_' . $method . '.php'; |
102
|
|
|
print '<p align="center"><strong>https://www.theyworkforyou.com/api/' . $method . '</strong></p>'; |
103
|
|
|
api_call_user_func_or_error('api_' . $method . '_front', [], 'No documentation yet', 'html'); |
104
|
|
|
if ($method != 'getQuota') { |
105
|
|
|
api_documentation_explorer($method, $explorer); |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
$subscription = new MySociety\TheyWorkForYou\Subscription($THEUSER); |
109
|
|
|
$sidebar = api_sidebar($subscription); |
110
|
|
|
$PAGE->stripe_end([$sidebar]); |
111
|
|
|
$PAGE->page_end(); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
function api_documentation_explorer($method, $explorer) { |
115
|
|
|
global $methods; |
116
|
|
|
?> |
117
|
|
|
<h4>Explorer</h4> |
118
|
|
|
<p>Try out this function without writing any code!</p> |
119
|
|
|
<form method="get" action="?#output"> |
120
|
|
|
<p> |
121
|
|
|
<?php foreach ($methods[$method]['parameters'] as $parameter) { |
122
|
|
|
print $parameter . ': <input type="text" name="' . $parameter . '" value="'; |
123
|
|
|
if ($val = get_http_var($parameter)) { |
124
|
|
|
print _htmlspecialchars($val); |
125
|
|
|
} |
126
|
|
|
print '" size="30"><br>'; |
127
|
|
|
} |
128
|
|
|
?> |
129
|
|
|
Output: |
130
|
|
|
<input id="output_json" type="radio" name="output" value="json"<?php if (get_http_var('output') == 'json' || !get_http_var('output')) { |
131
|
|
|
print ' checked'; |
132
|
|
|
}?>> |
133
|
|
|
<label for="output_json" class="inline">JSON</label> |
134
|
|
|
<input id="output_js" type="radio" name="output" value="js"<?php if (get_http_var('output') == 'js') { |
135
|
|
|
print ' checked'; |
136
|
|
|
}?>> |
137
|
|
|
<label for="output_js" class="inline">JS</label> |
138
|
|
|
<input id="output_xml" type="radio" name="output" value="xml"<?php if (get_http_var('output') == 'xml') { |
139
|
|
|
print ' checked'; |
140
|
|
|
}?>> |
141
|
|
|
<label for="output_xml" class="inline">XML</label> |
142
|
|
|
<input id="output_php" type="radio" name="output" value="php"<?php if (get_http_var('output') == 'php') { |
143
|
|
|
print ' checked'; |
144
|
|
|
}?>> |
145
|
|
|
<label for="output_php" class="inline">Serialised PHP</label> |
146
|
|
|
<input id="output_rabx" type="radio" name="output" value="rabx"<?php if (get_http_var('output') == 'rabx') { |
147
|
|
|
print ' checked'; |
148
|
|
|
}?>> |
149
|
|
|
<label for="output_rabx" class="inline">RABX</label> |
150
|
|
|
|
151
|
|
|
<input type="submit" value="Go"> |
152
|
|
|
</p> |
153
|
|
|
</form> |
154
|
|
|
<?php |
155
|
|
|
if ($explorer) { |
156
|
|
|
$qs = []; |
157
|
|
|
foreach ($methods[$method]['parameters'] as $parameter) { |
158
|
|
|
if (get_http_var($parameter)) { |
159
|
|
|
$qs[] = _htmlspecialchars(rawurlencode($parameter) . '=' . urlencode(get_http_var($parameter))); |
160
|
|
|
} |
161
|
|
|
} |
162
|
|
|
print '<h4><a name="output"></a>Output</h4>'; |
163
|
|
|
print '<p>URL for this: <strong>https://www.theyworkforyou.com/api/'; |
164
|
|
|
print $method . '?' . join('&', $qs) . '&output=' . _htmlspecialchars(get_http_var('output')) . '</strong></p>'; |
165
|
|
|
print '<pre>' . _htmlspecialchars($explorer) . '</pre>'; |
166
|
|
|
} |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
function api_front_page($error = '') { |
170
|
|
|
global $PAGE, $methods, $this_page, $THEUSER; |
171
|
|
|
$this_page = 'api_front'; |
172
|
|
|
$PAGE->page_start(); |
173
|
|
|
$PAGE->stripe_start(); |
174
|
|
|
if ($error) { |
175
|
|
|
print "<p style='color: #cc0000'>$error</p>"; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
$subscription = new MySociety\TheyWorkForYou\Subscription($THEUSER); |
179
|
|
|
|
180
|
|
|
?> |
181
|
|
|
|
182
|
|
|
<p> |
183
|
|
|
Welcome to TheyWorkForYou’s API section. The API (Application Programming |
184
|
|
|
Interface) is a way of querying our database for information. |
185
|
|
|
</p> |
186
|
|
|
|
187
|
|
|
<?php if ($subscription->stripe) { ?> |
188
|
|
|
<p align="center"><big> |
189
|
|
|
<a href="/api/key">Manage your keys and payments</a> |
190
|
|
|
</big></p> |
191
|
|
|
<?php } else { ?> |
192
|
|
|
<p align="center"><big> |
193
|
|
|
To use the API you need to <a href="/api/key">get an API key</a>. |
194
|
|
|
</big></p> |
195
|
|
|
<?php } ?> |
196
|
|
|
|
197
|
|
|
<p> |
198
|
|
|
The documentation for each individual API function is linked from this |
199
|
|
|
page: you can read what each function does, and test it out, without |
200
|
|
|
needing an API key or to write any code. |
201
|
|
|
</p> |
202
|
|
|
|
203
|
|
|
<p> |
204
|
|
|
<strong>Important note:</strong> Politicians’ contact details can’t be |
205
|
|
|
obtained via this API. If that’s what you’re looking for, see |
206
|
|
|
<a href="https://everypolitician.org/">EveryPolitician</a> instead. |
207
|
|
|
APIs and datasets for other mySociety services can be found on our |
208
|
|
|
data portal, <a href="https://data.mysociety.org">data.mysociety.org</a>. |
209
|
|
|
</p> |
210
|
|
|
|
211
|
|
|
<h3 id="plans">Pricing</h3> |
212
|
|
|
|
213
|
|
|
<ul> |
214
|
|
|
<li>£20 per month for 1,000 calls per month (free for charitable usage)<br/> |
215
|
|
|
<li>£50 per month for 5,000 calls<br/> |
216
|
|
|
<li>£100 per month for 10,000 calls<br/> |
217
|
|
|
<li>£300 per month for unlimited calls |
218
|
|
|
</ul> |
219
|
|
|
|
220
|
|
|
<p>In addition, we offer a 50% discount on the above rates for charitable usage. |
221
|
|
|
This means direct use by registered charities, or individuals pursuing a |
222
|
|
|
non-profit project on an unpaid basis.</p> |
223
|
|
|
|
224
|
|
|
<p>Please read our full <a href="/api/terms">terms of usage</a>, including |
225
|
|
|
licence and attribution requirements.</p> |
226
|
|
|
|
227
|
|
|
<?php if ($subscription->stripe) { ?> |
228
|
|
|
<p align="center"><big> |
229
|
|
|
<a href="/api/key">Manage your keys and payments</a> |
230
|
|
|
</big></p> |
231
|
|
|
<?php } else { ?> |
232
|
|
|
<p align="center"><big> |
233
|
|
|
To use the API you need to <a href="/api/key">get an API key</a>. |
234
|
|
|
</big></p> |
235
|
|
|
<?php } ?> |
236
|
|
|
|
237
|
|
|
|
238
|
|
|
<hr> |
239
|
|
|
|
240
|
|
|
<h2>Technical documentation</h2> |
241
|
|
|
<p> |
242
|
|
|
All requests are made by GETting a particular URL with a number of |
243
|
|
|
parameters. <em>key</em> is required; <em>output</em> is optional, and |
244
|
|
|
defaults to <kbd>js</kbd>. |
245
|
|
|
</p> |
246
|
|
|
<p align="center"> |
247
|
|
|
<strong>https://www.theyworkforyou.com/api/<em>function</em>?key=<em>key</em>&output=<em>output</em>&<em>other_variables</em></strong> |
248
|
|
|
</p> |
249
|
|
|
<p> |
250
|
|
|
The current version of the API is <em>1.0.0</em>. If we make changes to |
251
|
|
|
the API functions, we’ll increase the version number and make it an |
252
|
|
|
argument so you can still use the old version. |
253
|
|
|
</p> |
254
|
|
|
|
255
|
|
|
<table> |
256
|
|
|
<tr valign="top"> |
257
|
|
|
<td width="60%"> |
258
|
|
|
|
259
|
|
|
<h3>Outputs</h3> |
260
|
|
|
<p>The <em>output</em> argument can take any of the following values: |
261
|
|
|
<ul> |
262
|
|
|
<li><strong>xml</strong>. XML. The root element is twfy.</li> |
263
|
|
|
<li><strong>php</strong>. Serialized PHP, that can be turned back into useful information with the unserialize() command. Quite useful in Python as well, using e.g. <a href="https://pypi.org/project/phpserialize/">phpserialize</a>.</li> |
264
|
|
|
<li><strong>json</strong>. JSON data.</li> |
265
|
|
|
<li><strong>js</strong>. A JavaScript object, with data in ISO-8859-1. You can |
266
|
|
|
provide a callback function with the <em>callback</em> variable, and then that |
267
|
|
|
function will be called with the data as its argument.</li> |
268
|
|
|
<li><strong>rabx</strong>. “RPC over Anything But XML”.</li> |
269
|
|
|
</ul> |
270
|
|
|
|
271
|
|
|
</td><td> |
272
|
|
|
|
273
|
|
|
<h3>Errors</h3> |
274
|
|
|
|
275
|
|
|
<p>If there’s an error, either in the arguments provided or in trying to perform the request, |
276
|
|
|
this is returned as a top-level error string, ie. in XML it returns |
277
|
|
|
<code><twfy><error>ERROR</error></twfy></code>; |
278
|
|
|
in JS <code>{"error":"ERROR"}</code>; |
279
|
|
|
and in PHP and RABX a serialised array containing one entry with key <code>error</code>. |
280
|
|
|
|
281
|
|
|
</td></tr></table> |
282
|
|
|
|
283
|
|
|
<h3>Bindings</h3> |
284
|
|
|
|
285
|
|
|
<p>These help you interface with the API more easily in a particular language:</p> |
286
|
|
|
<ul> |
287
|
|
|
<li><a href="https://github.com/rubenarakelyan/twfyapi-aspnet/">ASP.net</a> (thanks to Ruben Arakelyan)</li> |
288
|
|
|
<li><a href="https://github.com/rhinocratic/twfy">Clojure</a> (thanks to Andrew Baxter)</li> |
289
|
|
|
<li><a href="https://github.com/jamtho/twfy">Common Lisp</a> (thanks to James Thompson)</li> |
290
|
|
|
<li><a href="https://github.com/rubenarakelyan/twfyapi-js">JavaScript</a> (thanks to Ruben Arakelyan)</li> |
291
|
|
|
<li><a href="https://sourceforge.net/projects/twfyjavaapi">Java</a> (thanks to Mitch Kent)</li> |
292
|
|
|
<li><a href="https://github.com/ifraixedes/node-theyworkforyou-api">Node</a> (thanks to Ivan Fraixedes)</li> |
293
|
|
|
<li><a href="https://metacpan.org/pod/WebService::TWFY::API">Perl</a> (thanks to Spiros Denaxas)</li> |
294
|
|
|
<li><a href="https://github.com/rubenarakelyan/twfyapi/">PHP</a> (thanks to Ruben Arakelyan)</li> |
295
|
|
|
<li><a href="https://code.google.com/archive/p/twfython/">Python</a> (thanks to Paul Doran)</li> |
296
|
|
|
<li><a href="https://github.com/conjugateprior/twfy">R</a> (thanks to Will Lowe)</li> |
297
|
|
|
<li><a href="https://github.com/bruce/twfy">Ruby</a> (thanks to Bruce Williams and Martin Owen)</li> |
298
|
|
|
</ul> |
299
|
|
|
|
300
|
|
|
<p>If anyone wishes to write bindings for the API in any language, please |
301
|
|
|
do so, let us know and we’ll link to it here. You might want to |
302
|
|
|
<a href="https://groups.google.com/a/mysociety.org/forum/#!forum/theyworkforyou">join our mailing list</a> |
303
|
|
|
to discuss things.</p> |
304
|
|
|
|
305
|
|
|
<h3>Example</h3> |
306
|
|
|
|
307
|
|
|
<ul> |
308
|
|
|
<li><a href="javascript:function foo(r) {if (r.twfy.url)window.location=r.twfy.url;};(function () {var s=document.createElement('script');s.setAttribute('src','https://www.theyworkforyou.com/api/convertURL?key=Gbr9QgCDzHExFzRwPWGAiUJ5&callback=foo&url='+encodeURIComponent(window.location));s.setAttribute('type','text/javascript');document.getElementsByTagName('head')[0].appendChild(s);})()">Hansard prettifier</a> - drag this bookmarklet to your bookmarks bar, or bookmark it. Then if you ever find yourself on the official site, clicking this will try and take you to the equivalent page on TheyWorkForYou. (Tested in IE, Firefox, Opera.)</li> |
309
|
|
|
</ul> |
310
|
|
|
|
311
|
|
|
<h3>Bulk Analysis</h3> |
312
|
|
|
|
313
|
|
|
<p> |
314
|
|
|
If you are doing analysis over long periods of time, or generating statistical data then you might find our <a href="https://parser.theyworkforyou.com/">raw data</a> |
315
|
|
|
more suitable that using the API. |
316
|
|
|
</p> |
317
|
|
|
|
318
|
|
|
<?php |
319
|
|
|
$sidebar = api_sidebar($subscription); |
320
|
|
|
$PAGE->stripe_end([$sidebar]); |
321
|
|
|
$PAGE->page_end(); |
322
|
|
|
} |
323
|
|
|
|