Use a REST API: Difference between revisions
(→{{header|Go}}: Added second version which allows for creating events.) |
|||
Line 568: | Line 568: | ||
console.log('Event: ', result); |
console.log('Event: ', result); |
||
})</lang> |
})</lang> |
||
=={{header|Phix}}== |
|||
Uses eventzillaapi.net instead of meetup.com, since unlike the latter it can be done for free. |
|||
Unfortunately the API (V2) does not support creating events, so instead this shows how to use |
|||
a post method to toggle sales (but see note below). |
|||
<!--<lang Phix>(notonline)--> |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
-- demo\rosetta\Using_a_REST_API.exw |
|||
-- ================================= |
|||
--</span> |
|||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> |
|||
<span style="color: #008080;">include</span> <span style="color: #000000;">libcurl</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> |
|||
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">\</span><span style="color: #000000;">json</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">base_url</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"https://www.eventzillaapi.net/api/v2/"</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">curl</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pErrorBuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">NULL</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">get_api_key</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">inifile</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">file_exists</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inifile</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #004080;">object</span> <span style="color: #000000;">lines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inifile</span><span style="color: #0000FF;">,</span><span style="color: #004600;">GT_LF_STRIPPED</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #004080;">sequence</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])=</span><span style="color: #000000;">40</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">lines</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inifile</span> <span style="color: #0000FF;">&</span> <span style="color: #008000;">" not found or invalid"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">query</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">url</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">req</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">method</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"GET"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000080;font-style:italic;">-- initialize curl handle if required</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">curl</span><span style="color: #0000FF;">=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">curl</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">curl_easy_init</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">pErrorBuffer</span><span style="color: #0000FF;">=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">pErrorBuffer</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate</span><span style="color: #0000FF;">(</span><span style="color: #000000;">CURL_ERROR_SIZE</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CURLOPT_ERRORBUFFER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">pErrorBuffer</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">else</span> |
|||
<span style="color: #000000;">curl_easy_reset</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #000080;font-style:italic;">-- generate the POST data string |
|||
-- eg {"command","returnBalances", |
|||
-- "nonce","1515249747606"} |
|||
-- --> "command=returnBalances&nonce=1515249747606"</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">post_data</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">req</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">by</span> <span style="color: #000000;">2</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #000000;">post_data</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">"&"</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">name</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">req</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">req</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #000000;">post_data</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">name</span><span style="color: #0000FF;">&</span><span style="color: #008000;">"="</span><span style="color: #0000FF;">&</span><span style="color: #000000;">v</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">method</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"POST"</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CURLOPT_URL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">base_url</span><span style="color: #0000FF;">&</span><span style="color: #000000;">url</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CURLOPT_POSTFIELDS</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">post_data</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">else</span> |
|||
<span style="color: #000000;">url</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">base_url</span><span style="color: #0000FF;">&</span><span style="color: #000000;">url</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">post_data</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">url</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">"?"</span><span style="color: #0000FF;">&</span><span style="color: #000000;">post_data</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">CURLOPT_URL</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">url</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CURLOPT_HTTPGET</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">true</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #000080;font-style:italic;">-- generate the extra headers</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">api_key</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_api_key</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"api_key.txt"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">atom</span> <span style="color: #000000;">headers</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">curl_slist_append</span><span style="color: #0000FF;">(</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"x-api-key: "</span><span style="color: #0000FF;">&</span><span style="color: #000000;">api_key</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">api_key</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">""</span> <span style="color: #000080;font-style:italic;">-- (generally good idea, avoid showing in ex.err) |
|||
-- (obvs. inlining get_api_key() call works too.)</span> |
|||
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CURLOPT_HTTPHEADER</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">headers</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">curl_easy_setopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">CURLOPT_SSL_VERIFYPEER</span><span style="color: #0000FF;">,</span> <span style="color: #004600;">false</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000080;font-style:italic;">-- run the query</span> |
|||
<span style="color: #004080;">object</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">curl_easy_perform_ex</span><span style="color: #0000FF;">(</span><span style="color: #000000;">curl</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">headers</span><span style="color: #0000FF;">!=</span><span style="color: #004600;">NULL</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">curl_slist_free_all</span><span style="color: #0000FF;">(</span><span style="color: #000000;">headers</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #004080;">integer</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000080;font-style:italic;">-- better error/retry handling probably required...</span> |
|||
<span style="color: #0000FF;">?{</span><span style="color: #008000;">"error"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">peek_string</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pErrorBuffer</span><span style="color: #0000FF;">),</span><span style="color: #7060A8;">curl_easy_strerror</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)}</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #004080;">object</span> <span style="color: #000000;">jres</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">parse_json</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">jres</span><span style="color: #0000FF;">={</span><span style="color: #000000;">JSON_INVALID</span><span style="color: #0000FF;">}</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000080;font-style:italic;">-- ditto...</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #004600;">false</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">jres</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #000080;font-style:italic;">-- as per the task description (but I would swap the args and call query() direct).</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">get_events</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">details</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">url</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">query</span><span style="color: #0000FF;">(</span><span style="color: #000000;">url</span><span style="color: #0000FF;">,</span><span style="color: #000000;">details</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">toggle_sales</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">details</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">string</span> <span style="color: #000000;">url</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #000000;">query</span><span style="color: #0000FF;">(</span><span style="color: #000000;">url</span><span style="color: #0000FF;">,</span><span style="color: #000000;">details</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"POST"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #004080;">object</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">get_events</span><span style="color: #0000FF;">({</span><span style="color: #008000;">"status"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"live"</span><span style="color: #0000FF;">},</span><span style="color: #008000;">"events"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000080;font-style:italic;">--object res = get_events({},"events")</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">print_json</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"2138822407"</span><span style="color: #0000FF;">,</span> <span style="color: #000080;font-style:italic;">-- (see note)</span> |
|||
<span style="color: #000000;">status</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"true"</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">!={-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">`message`</span><span style="color: #0000FF;">,</span><span style="color: #008000;">`No events found`</span><span style="color: #0000FF;">}}</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">extract_json_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"events_live"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000080;font-style:italic;">-- res = extract_json_field(res,"events")</span> |
|||
<span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"%d"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">extract_json_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"id"</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #000000;">status</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">extract_json_field</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">],</span><span style="color: #008000;">"status"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"id:%s, status:%s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #000000;">status</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #000000;">status</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">iff</span><span style="color: #0000FF;">(</span><span style="color: #000000;">status</span><span style="color: #0000FF;">=</span><span style="color: #008000;">"Live"</span><span style="color: #0000FF;">?</span><span style="color: #008000;">"false"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"true"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">toggle_sales</span><span style="color: #0000FF;">({</span><span style="color: #008000;">"eventid"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">id</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"status"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">status</span><span style="color: #0000FF;">},</span><span style="color: #008000;">"events/togglesales"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">print_json</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">))</span> |
|||
<!--</lang>--> |
|||
Note that toggling sales off makes the (manually created) event invisible to the API, even without |
|||
the {"status","live"} filter, hence I had to hard-code the event id to permit a second run to turn |
|||
it back on. Also as shown omitting said filter changes the field name on the returned results... |
|||
{{out}} |
|||
<pre> |
|||
{ |
|||
"pagination":[ |
|||
{ |
|||
"offset":0, |
|||
"limit":20, |
|||
"total":1, |
|||
"category":"" |
|||
} |
|||
], |
|||
"events_live":[ |
|||
{ |
|||
"id":2138822407, |
|||
"title":"Phix Programming in the park party", |
|||
"description":"Learn how to program while wearing gloves", |
|||
"currency":"GBP", // nb: unicode pound symbol replaced manually |
|||
"start_date":"2021-12-30T00:00:00", |
|||
"start_time":"14:00", |
|||
"end_date":"2021-12-30T00:00:00", |
|||
"end_time":"14:10", |
|||
"time_zone":"(GMT+0000) United Kingdom Time", |
|||
"tickets_sold":0, |
|||
"tickets_total":4, |
|||
"status":"Live", |
|||
"show_remaining":false, |
|||
"twitter_hashtag":"", |
|||
"utc_offset":"+00:00", |
|||
"invite_code":"", |
|||
"url":"https://events.eventzilla.net/e/phix-programming-in-the-park-party-2138822407", |
|||
"logo_url":"", |
|||
"bgimage_url":"https://s3.amazonaws.com/ezusrevent/party-small13.jpg", |
|||
"venue":"Acacia gardens, London, England, United Kingdom", |
|||
"dateid":2138353105, |
|||
"categories":"Class, Training, or Workshop", |
|||
"language":"en", |
|||
"description_html":"<p>Learn how to program while wearing gloves</p>", |
|||
"timezone_code":"GMT" |
|||
} |
|||
] |
|||
} |
|||
id:2138822407, status:Live |
|||
{ |
|||
"eventstatus":"unpublished" |
|||
} |
|||
</pre> |
|||
Second/alternate run: |
|||
<pre> |
|||
{ |
|||
"message":"No events found" |
|||
} |
|||
{ |
|||
"eventstatus":"published" |
|||
} |
|||
</pre> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
Revision as of 14:58, 24 December 2021
To:
- Create a 'get' function for the API, that can be used to get a list of events for example.
- Create a 'post' function for the API, that can be used to create a new venue or event for example.
Using the Meetup.com API.
Both functions take two parameters, 'details' and 'url'. Details is an object containing required and optional arguments specified by the API's requirement (Example, open events requires at least one detail). The 'url' supplied informs the get/post method what part of the API to ping (Example, valid URLs for 'get' could be ['/2/open_events' http://www.meetup.com/meetup_api/docs/2/open_events/] or ['/comments' http://www.meetup.com/meetup_api/docs/comments/]).
Some posting features are paid, such as creating an event. [Editing member details http://www.meetup.com/meetup_api/docs/2/member/#edit] for example, is an example of a free 'post' API.
An API key is assumed to be supplied through an api_key.txt
file.
Solutions should be implemented without any meetup.com helper libraries, to make it easier to translate to languages which don't have such helper libraries. However, examples that do use helper libraries may be provided as an addition.
This task was created through Google Code-in.
Go
Using the standard library
Note that this version doesn't include code to submit events to Meetup.
<lang go>package main
import ( "bytes" "encoding/json" "fmt" "io/ioutil" "log" "net/http" "net/url" "os" "strings" "time" )
var key string
func init() { // Read an API key from the specified file. // See www.meetup.com/meetup_api/auth for other ways to authenticate. const keyFile = "api_key.txt" f, err := os.Open(keyFile) if err != nil { log.Fatal(err) } keydata, err := ioutil.ReadAll(f) if err != nil { log.Fatal(err) } key = strings.TrimSpace(string(keydata)) }
type EventResponse struct { Results []Result // … other fields … }
type Result struct { ID string Status string Name string EventURL string `json:"event_url"` Description string Time EventTime // … other fields … }
// EventTime is a time.Time that will be marshalled/unmarshalled to/from JSON // as a UTC time in milliseconds since the epoch as returned by the Meetup API. type EventTime struct{ time.Time }
func (et *EventTime) UnmarshalJSON(data []byte) error { var msec int64 if err := json.Unmarshal(data, &msec); err != nil { return err } et.Time = time.Unix(0, msec*int64(time.Millisecond)) return nil }
func (et EventTime) MarshalJSON() ([]byte, error) { msec := et.UnixNano() / int64(time.Millisecond) return json.Marshal(msec) }
// String formats a Result suitable for debugging output. func (r *Result) String() string { var b bytes.Buffer fmt.Fprintln(&b, "ID:", r.ID) fmt.Fprintln(&b, "URL:", r.EventURL) fmt.Fprintln(&b, "Time:", r.Time.Format(time.UnixDate)) d := r.Description const limit = 65 if len(d) > limit { d = d[:limit-1] + "…" } fmt.Fprintln(&b, "Description:", d) return b.String() }
func main() { v := url.Values{ //"topic": []string{"tech"}, //"city": []string{"Barcelona"}, "topic": []string{"photo"}, "time": []string{",1w"}, "key": []string{key}, } u := url.URL{ Scheme: "http", Host: "api.meetup.com", Path: "2/open_events.json", RawQuery: v.Encode(), } //log.Println("API URL:", u.String())
resp, err := http.Get(u.String()) if err != nil { log.Fatal(err) } defer resp.Body.Close() log.Println("HTTP Status:", resp.Status)
body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) }
//log.Printf("Body: %q\n", body) var buf bytes.Buffer if err = json.Indent(&buf, body, "", " "); err != nil { log.Fatal(err) } //log.Println("Indented:", buf.String())
var evresp EventResponse json.Unmarshal(body, &evresp) //log.Printf("%#v\n", evresp)
fmt.Println("Got", len(evresp.Results), "events") if len(evresp.Results) > 0 { fmt.Println("First event:\n", &evresp.Results[0]) } }</lang>
- Output:
2014/12/28 19:16:01 HTTP Status: 200 OK Got 200 events First event: ID: 219254566 URL: http://www.meetup.com/Bay-Area-Photography-Shoots-and-Workshops/events/219254566/ Time: Sun Dec 28 16:00:00 EST 2014 Description: <p><b>Beginners Lighting:</b> join us for this exciting workshop…
Using a third party library
Note that this code is untested as you need a paid subscription to create events which I don't have.
<lang go>package main
import (
"fmt" "github.com/Guitarbum722/meetup-client" "io/ioutil" "log" "net/url" "strconv" "strings" "time"
)
var key string
func init() {
// Read an API key from the specified file. const keyFile = "api_key.txt" keydata, err := ioutil.ReadFile(keyFile) if err != nil { log.Fatal(err) } key = strings.TrimSpace(string(keydata))
}
func eventOptions(et map[string][]string, vals url.Values) {
for k, v := range et { if len(v) < 1 { break } switch k { case meetup.GroupID: vals.Add(meetup.GroupID, strings.Join(v, ",")) case meetup.GroupURLName: vals.Add(meetup.GroupURLName, strings.Join(v, ",")) case meetup.EventName: vals.Add(meetup.EventName, strings.Join(v, ",")) case meetup.Description: vals.Add(meetup.Description, strings.Join(v, ",")) case meetup.EventTime: vals.Add(meetup.EventTime, strings.Join(v, ",")) default: // empty } }
}
func check(err error) {
if err != nil { log.Fatal(err) }
}
func main() {
// create client c := meetup.NewClient(&meetup.ClientOpts{APIKey: key})
// get basic information for a particular group const urlName = "Meetup-API-Testing" groups, err := c.GroupByURLName([]string{urlName}) check(err) g := groups.Groups[0] fmt.Printf("Basic information for the %q group:\n", g.URLName) fmt.Printf(" ID : %d\n", g.ID) fmt.Printf(" Member count : %d\n", g.MemberCount) fmt.Printf(" Organizer : %s\n", g.Organizer.Name) fmt.Println()
// get a list of upcoming events for this group events, err := c.EventsByGroup(urlName, []string{meetup.EventUpcoming}, false) check(err) for _, event := range events.Events { fmt.Printf("Upcoming events for the %q group\n", g.URLName) fmt.Printf(" ID : %s\n", event.ID) fmt.Printf(" Name : %s\n", event.Name) fmt.Printf(" Link : %s\n", event.Link) fmt.Printf(" Venue : %s\n", event.Venue.Name) fmt.Println() }
// create an event for this group d := time.Date(2020, time.April, 1, 18, 0, 0, 0, time.UTC) eventDate := strconv.FormatInt((d.UnixNano() / 1000000), 10) event, err := c.CreateEvent(eventOptions, map[string][]string{ meetup.GroupID: {strconv.Itoa(g.ID)}, meetup.GroupURLName: {urlName}, meetup.EventName: {"Test Meetup integration"}, meetup.Description: {"This is an event test."}, meetup.EventTime: {eventDate}, }) check(err) fmt.Printf("The ID for the %q event is %s\n\n", event.Name, event.ID)
// delete the event just posted err = c.DeleteEvent(event.ID) check(err) fmt.Printf("The %q event has been cancelled.\n", event.Name)
}</lang>
Java
EventGetter.java
<lang java>package src;
import java.io.BufferedReader; import java.io.FileReader; import java.net.URI;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.utils.URIBuilder; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils;
public class EventGetter {
String city = "";
String topic = "";
public String getEvent(String path_code,String key) throws Exception{ String responseString = "";
URI request = new URIBuilder() //We build the request URI .setScheme("http") .setHost("api.meetup.com") .setPath(path_code) //List of parameters : .setParameter("topic", topic) .setParameter("city", city) //End of params .setParameter("key", key) .build();
HttpGet get = new HttpGet(request); //Assign the URI to the get request System.out.println("Get request : "+get.toString());
CloseableHttpClient client = HttpClients.createDefault(); CloseableHttpResponse response = client.execute(get); responseString = EntityUtils.toString(response.getEntity());
return responseString; }
public String getApiKey(String key_path){ String key = "";
try{ BufferedReader reader = new BufferedReader(new FileReader(key_path)); //Read the file where the API Key is key = reader.readLine().toString(); //Store key reader.close(); } catch(Exception e){System.out.println(e.toString());}
return key; //Return the key value. }
}</lang>
Main.java <lang java>/*
* In this class, You can see the diferent * ways of asking for events. * */
package src;
import java.util.Iterator;
import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; import org.json.simple.parser.JSONParser;
public class Main { public static void main(String[] args) {
String key_path = "API_key/api_key.txt"; //Path to API Key (api_key.txt) String key = ""; String path_code = "/2/open_events"; //PathCode for get-events //More PathCodes : http://www.meetup.com/meetup_api/docs/ String events = "";
EventGetter eventGetter = new EventGetter(); key = eventGetter.getApiKey(key_path);
/* * 1-PARAMETER EXAMPLE : */ eventGetter.topic = "photo"; //Set the parameter "topic" to "photo"
try { events = eventGetter.getEvent(path_code, key); //Store the event response into a String } catch (Exception e) {e.printStackTrace();} DecodeJSON(events); //Print JSON-parsed events info
/* * 2-PARAMETER EXAMPLE : */ eventGetter.topic = "tech"; //Set parameters eventGetter.city = "Barcelona"; try{ events = eventGetter.getEvent(path_code, key); }catch(Exception e){e.printStackTrace();} //System.out.println(events); //Print the events list (JSON)
/*
* MULTIPLE-TOPICS EXAMPLE :
* Separate topics by commas
*/
eventGetter.topic = "tech,photo,art"; //multiple topic separated by commas
eventGetter.city = "Barcelona";
try{
events = eventGetter.getEvent(path_code, key);
}catch(Exception e){e.printStackTrace();}
}
public static void DecodeJSON(String events){
try{ JSONParser parser = new JSONParser(); JSONObject obj = (JSONObject) parser.parse(events); JSONArray results = (JSONArray) obj.get("results"); System.out.println("Results : ");
Iterator i = results.iterator(); while(i.hasNext()){ JSONObject event = (JSONObject) i.next(); System.out.println("Name : "+event.get("name"));
if(event.containsKey("venue")){ JSONObject venue = (JSONObject) event.get("venue"); System.out.println("Location (city) : "+venue.get("city")); System.out.println("Location (adress) : "+venue.get("adress_1")); }
System.out.println("Url : "+event.get("event_url"));
System.out.println("Time : "+event.get("time"));
i.next();
}
} catch(Exception e){e.printStackTrace();} }
}</lang>
JavaScript
Made on node js. Run using 'node filename.js'
<lang javascript>var fs = require('fs'); var request = require('request');
var meetup = function() {
var key = fs.readFileSync('api_key.txt', 'utf-8'); var url = "https://api.meetup.com";
var composeURL = function(root, object) { return root + '?' + JSON.stringify(object).replace(/":"/g, '=').replace(/","/g, '&').slice(2, -2) }
var get = function(params, callback, path) { params.key = key;
request.get(composeURL(url + (path || '/2/open_events'), params), function(err, res, body) { if ( err ) { console.error(err); return false; }
callback(JSON.parse(body)['results']); }) }
var post = function(details, callback, path) { details.key = key;
request.post({ headers: { 'content-type' : 'application/x-www-form-urlencoded' }, url: url + (path || '/2/event'), form: details }, function(err, res, body) { callback(body); }) }
var parseEvent = function(mEvent) { /* * A simple function that converts JSON to * string in a pretty way **/ var name = mEvent['name'] || ; var desc = mEvent['desc'] || ; var url = mEvent['url'] || ;
if ( mEvent['venue'] ) { var city = mEvent['venue']['city'] || ; var lat = mEvent['venue']['lat'] || ; var lon = mEvent['venue']['lon'] || ; } if ( mEvent['group'] ) var group = mEvent['group']['name'] || ;
var parsed = ;
if ( name ) parsed += 'Name: ' + name + '\n'; if ( desc ) parsed += 'Description: ' + desc + '\n'; if ( url ) parsed += 'Url: ' + url + '\n'; if ( city ) parsed += 'City: ' + city + '\n'; if ( lat ) parsed += 'Latitude: ' + lat + '\n'; if ( lon ) parsed += 'Longitude: ' + lon + '\n'; if ( group ) parsed += 'Group: ' + group + '\n';
return parsed;
};
var parseEvents = function(results) { console.log('a'); for ( var i = 0; i < results.length; i++ ) { console.log( parseEvent(results[i]) ); } }
return { get: get, parseEvents: parseEvents, post: post }
}
meetup().get({
// More Info: http://www.meetup.com/meetup_api/docs/2/open_events/ topic: 'photo', city: 'nyc'
}, function(results) {
meetup().parseEvents(results);
});
/*
* Getting group ID and group urlname * * The URL name is simply the part after meetup.com/ on a meetup group. * Example, ID of meetup.com/foodie-programmers is 'foodie-programmers'. * * Running the code below with the group name will give the group ID, an integer.
meetup().get({
'group_urlname': 'foodie-programmers'
}, function(group) {
console.log(group.id);
}, '/2/groups');
* Using the above group_id and the group_urlname manually, * you can post events to a group with the below code
- /
meetup().post({
// More Info: http://www.meetup.com/meetup_api/docs/:urlname/venues/#create name: 'Finding Nemo', address_1: 'p sherman 42 wallaby way sydney', city: 'sydney', country: 'australia', // state: needed if in US or CA.
}, function(venue) {
console.log('Venue: ', venue, venue.id); // Prints a venue ID that can be used to create a event
}, '/' + 'Template:Foodie-programmers' + '/venues'); // This needs a valid urlname for the group
meetup().post({
// More Info: http://www.meetup.com/meetup_api/docs/2/groups/ group_id: 42, // Group ID goes here group_urlname: 'foodie-programmers', name: 'Tomato Python Fest', description: 'Code vegetables in Python! Special speech by Guido Van Ossum', duration: 1000 * 60 * 60 * 2, // Duration in milliseconds time: 1419879086343, // Milliseconds since epoch why: 'We should do this because... Less than 250 characters', hosts: 'up to 5 comma separated member ids', venue_id: 42, // Integer, ID of venue. Venue can be created with the above. lat: 42, // Latitude, Integer lon: 42, // Longitude, Integer simple_html_description: 'Event description in simple html. Less than 50000 characters.'
}, function(result) {
console.log('Event: ', result);
})</lang>
Phix
Uses eventzillaapi.net instead of meetup.com, since unlike the latter it can be done for free. Unfortunately the API (V2) does not support creating events, so instead this shows how to use a post method to toggle sales (but see note below).
-- -- demo\rosetta\Using_a_REST_API.exw -- ================================= -- without js include libcurl.e include builtins\json.e constant base_url = "https://www.eventzillaapi.net/api/v2/" atom curl = NULL, pErrorBuffer = NULL function get_api_key(string inifile) if file_exists(inifile) then object lines = get_text(inifile,GT_LF_STRIPPED) if sequence(lines) and length(lines)=1 and length(lines[1])=40 then return lines[1] end if end if crash(inifile & " not found or invalid") end function function query(string url, sequence req, string method="GET") -- initialize curl handle if required if curl=NULL then curl = curl_easy_init() if pErrorBuffer=NULL then pErrorBuffer = allocate(CURL_ERROR_SIZE) end if curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, pErrorBuffer) else curl_easy_reset(curl) end if -- generate the POST data string -- eg {"command","returnBalances", -- "nonce","1515249747606"} -- --> "command=returnBalances&nonce=1515249747606" string post_data = "" for i=1 to length(req) by 2 do if i>1 then post_data &= "&" end if string name = req[i], v = req[i+1] post_data &= name&"="&v end for if method="POST" then curl_easy_setopt(curl, CURLOPT_URL, base_url&url) curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_data) else url = base_url&url if length(post_data) then url &= "?"&post_data end if curl_easy_setopt(curl, CURLOPT_URL, url) curl_easy_setopt(curl, CURLOPT_HTTPGET, true) end if -- generate the extra headers string api_key = get_api_key("api_key.txt") atom headers = curl_slist_append(NULL, "x-api-key: "&api_key) api_key = "" -- (generally good idea, avoid showing in ex.err) -- (obvs. inlining get_api_key() call works too.) curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers) curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false) -- run the query object res = curl_easy_perform_ex(curl) if headers!=NULL then curl_slist_free_all(headers) end if if integer(res) then -- better error/retry handling probably required... ?{"error",res,peek_string(pErrorBuffer),curl_easy_strerror(res)} return false end if object jres = parse_json(res) if jres={JSON_INVALID} then -- ditto... return false end if return jres end function -- as per the task description (but I would swap the args and call query() direct). function get_events(sequence details, string url) return query(url,details) end function function toggle_sales(sequence details, string url) return query(url,details,"POST") end function object res = get_events({"status","live"},"events") --object res = get_events({},"events") puts(1,print_json("",res)) string id = "2138822407", -- (see note) status = "true" if res!={-1,{`message`,`No events found`}} then res = extract_json_field(res,"events_live") -- res = extract_json_field(res,"events") id = sprintf("%d",extract_json_field(res[2],"id")) status = extract_json_field(res[2],"status") printf(1,"id:%s, status:%s\n",{id,status}) status = iff(status="Live"?"false","true") end if res = toggle_sales({"eventid",id,"status",status},"events/togglesales") puts(1,print_json("",res))
Note that toggling sales off makes the (manually created) event invisible to the API, even without the {"status","live"} filter, hence I had to hard-code the event id to permit a second run to turn it back on. Also as shown omitting said filter changes the field name on the returned results...
- Output:
{ "pagination":[ { "offset":0, "limit":20, "total":1, "category":"" } ], "events_live":[ { "id":2138822407, "title":"Phix Programming in the park party", "description":"Learn how to program while wearing gloves", "currency":"GBP", // nb: unicode pound symbol replaced manually "start_date":"2021-12-30T00:00:00", "start_time":"14:00", "end_date":"2021-12-30T00:00:00", "end_time":"14:10", "time_zone":"(GMT+0000) United Kingdom Time", "tickets_sold":0, "tickets_total":4, "status":"Live", "show_remaining":false, "twitter_hashtag":"", "utc_offset":"+00:00", "invite_code":"", "url":"https://events.eventzilla.net/e/phix-programming-in-the-park-party-2138822407", "logo_url":"", "bgimage_url":"https://s3.amazonaws.com/ezusrevent/party-small13.jpg", "venue":"Acacia gardens, London, England, United Kingdom", "dateid":2138353105, "categories":"Class, Training, or Workshop", "language":"en", "description_html":"<p>Learn how to program while wearing gloves</p>", "timezone_code":"GMT" } ] } id:2138822407, status:Live { "eventstatus":"unpublished" }
Second/alternate run:
{ "message":"No events found" } { "eventstatus":"published" }
Python
eventGetter.py <lang python>#http://docs.python-requests.org/en/latest/ import requests import json
city = None topic = None
def getEvent(url_path, key) :
responseString = "" params = {'city':city, 'key':key,'topic':topic} r = requests.get(url_path, params = params) print(r.url) responseString = r.text return responseString
def getApiKey(key_path):
key = "" f = open(key_path, 'r') key = f.read() return key
def submitEvent(url_path,params):
r = requests.post(url_path, data=json.dumps(params)) print(r.text+" : Event Submitted")</lang>
main.py <lang python>import eventGetter as eg import json
def main():
url_path = "https://api.meetup.com" #Url to meetup API key_path = "api_key.txt" #Path to api_key.txt path_code = "" #var to store the url_path + the specific api path key = eg.getApiKey(key_path) #1-parameter get events example : print("1-PARAMETER EXAMPLE") path_code = url_path+"/2/open_events" eg.topic = "photo" response = eg.getEvent(path_code, key) decodeJSON(response)
#2-parameter get events example : print("\n") print("2-PARAMETER EXAMPLE") path_code = url_path+"/2/open_events" eg.topic = "photo" eg.city = "nyc" response = eg.getEvent(path_code, key) decodeJSON(response)
#Get GEO Example : print("\n") print("Get GEO Example") path_code = url_path+"/2/open_events" eg.topic = "photo" eg.city = None exclude = None response = eg.getEvent(path_code, key) decodeGEO(response)
#Exclude topics Example print("\n") print("EXCLUDE-TOPICS EXAMPLE") path_code = url_path+"/2/open_events" eg.topic = "photo" eg.city = None exclude = "club" response = eg.getEvent(path_code, key) decodeJSONExcluding(response, exclude)
def decodeJSON(response):
j = json.loads(response.encode('ascii','ignore').decode()) #This is a Python Dict (JSON array) i = 0 results = j['results'] while i<len(results): event = results[i] print("Event "+str(i)) print("Event name : "+event['name']) print("Event URL : "+event['event_url']) try : print("City : "+str(event['venue']['city'])) except KeyError : print("This event has no location assigned") try : print("Group : "+str(event['group']['name'])) except KeyError : print("This event is not related to any group") i+=1
def decodeJSONExcluding(response, exclude):
j = json.loads(response.encode('ascii','ignore').decode()) #This is a Python Dict (JSON array) i = 0 results = j['results'] while i<len(results): event = results[i] if 'description' in event : if exclude not in str(event['description']) : print("Event "+str(i)) print("Event name : "+event['name']) print("Event URL : "+event['event_url']) try : print("City : "+str(event['venue']['city'])) except KeyError : print("This event has no location assigned") try : print("Group : "+str(event['group']['name'])) except KeyError : print("This event is not related to any group") else : print("Event number "+str(i)+" is excluded by its keywords") i+=1
def decodeGEO(response):
j = json.loads(response.encode('ascii','ignore').decode()) #This is a Python Dict (JSON array) i = 0 results = j['results'] while i<len(results): event = results[i] print("Event "+str(i)) print("Event name : "+event['name']) try : print("Lat : "+str(event['venue']['lat'])) print("Lon : "+str(event['venue']['lon'])) except KeyError : print("This event has no location assigned") i+=1
main()</lang>