Added some required field checking.
This commit is contained in:
parent
b7eafbf244
commit
b0e34a58ea
2 changed files with 96 additions and 27 deletions
|
|
@ -9,7 +9,9 @@ project(
|
||||||
curl = dependency('libcurl')
|
curl = dependency('libcurl')
|
||||||
|
|
||||||
cpp_flags = []
|
cpp_flags = []
|
||||||
c_flags = ['-DPOSIXLY_CORRECT', '-Wno-c99-extensions']
|
c_flags = ['-DPOSIXLY_CORRECT',
|
||||||
|
'-D_DEFAULT_SOURCE',
|
||||||
|
'-Wno-c99-extensions']
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
curl
|
curl
|
||||||
|
|
|
||||||
115
omdb.c
115
omdb.c
|
|
@ -16,6 +16,13 @@
|
||||||
#define OMDB_URL "http://www.omdbapi.com"
|
#define OMDB_URL "http://www.omdbapi.com"
|
||||||
#define PROJECT_NAME "omdb"
|
#define PROJECT_NAME "omdb"
|
||||||
|
|
||||||
|
const char *TITLE_LOOKUP_KEYS[] = {
|
||||||
|
"Actors", "Awards", "BoxOffice", "Country", "DVD", "Director",
|
||||||
|
"Genre", "Language", "Metascore", "Plot", "Production",
|
||||||
|
"Rated", "Ratings", "Released", "Response", "Runtime", "Title",
|
||||||
|
"Type", "Website", "Writer", "Year", "imdbID", "imdbRating",
|
||||||
|
"imdbVotes", NULL};
|
||||||
|
|
||||||
/* Default to plain output. */
|
/* Default to plain output. */
|
||||||
static enum _output_format {
|
static enum _output_format {
|
||||||
OUTPUT_JSON,
|
OUTPUT_JSON,
|
||||||
|
|
@ -23,27 +30,49 @@ static enum _output_format {
|
||||||
OUTPUT_FANCY
|
OUTPUT_FANCY
|
||||||
} output_format = OUTPUT_PLAIN;
|
} output_format = OUTPUT_PLAIN;
|
||||||
|
|
||||||
static struct option opts[] = {{"id", no_argument, NULL, 'i'},
|
static struct option opts[] = {{"api-key", required_argument, NULL, 'k'},
|
||||||
|
{"id", no_argument, NULL, 'i'},
|
||||||
{"json", no_argument, NULL, 'j'},
|
{"json", no_argument, NULL, 'j'},
|
||||||
{"api-key", required_argument, NULL, 'k'},
|
{"full-plot", no_argument, NULL, 'f'},
|
||||||
{"search-type", required_argument, NULL, 't'},
|
{"search-type", required_argument, NULL, 't'},
|
||||||
|
{"year", required_argument, NULL, 'y'},
|
||||||
{NULL, 0, NULL, 0}};
|
{NULL, 0, NULL, 0}};
|
||||||
|
|
||||||
void print_usage(void) {
|
void print_usage(void) {
|
||||||
printf(
|
printf(
|
||||||
PROJECT_NAME
|
PROJECT_NAME
|
||||||
" [ikt] <TITLE-OR-ID>\n"
|
" <OPTIONS> <TITLE-OR-ID>\n"
|
||||||
"\t-i/--id: Search by ID rather than title. (optional)\n"
|
"\t-i/--id: Search by ID rather than title. (optional)\n"
|
||||||
"\t-j/--json: Output full JSON response.\n"
|
"\t-j/--json: Output full JSON response.\n"
|
||||||
"\t-k/--api-key: OMDB API Key. (required)\n"
|
"\t-k/--api-key: OMDB API Key. (required)\n"
|
||||||
"\t-t/--search-type: Search type. (optional) [movie, series, episode]\n");
|
"\t-f/--full-plot: Output long plot description.\n"
|
||||||
|
"\t-t/--search-type: Search type. (optional) [movie, series, episode]\n"
|
||||||
|
"\t-y/--year: Year of release.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
CURLU *init_curl_url(const char *restrict ustr) {
|
||||||
|
/* Just validate and add options directly to the request now. */
|
||||||
|
CURLU *url = curl_url();
|
||||||
|
CURLUcode ures;
|
||||||
|
|
||||||
|
if (url == NULL) {
|
||||||
|
fputs("Out of memory.\n", stderr);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ures = curl_url_set(url, CURLUPART_URL, ustr, 0)) != CURLUE_OK) {
|
||||||
|
fprintf(stderr, "Couldn't set url: %s\n", curl_url_strerror(ures));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set a URL query parameter. */
|
/* Set a URL query parameter. */
|
||||||
void set_param(CURLU *restrict url, const char *restrict key,
|
void set_param(CURLU *restrict url, const char *restrict key,
|
||||||
char *restrict value) {
|
char *restrict value) {
|
||||||
CURLUcode err;
|
CURLUcode err;
|
||||||
char param[2048];
|
char param[256];
|
||||||
|
|
||||||
snprintf(param, sizeof param, "%s=%s", key, value);
|
snprintf(param, sizeof param, "%s=%s", key, value);
|
||||||
|
|
||||||
|
|
@ -79,22 +108,61 @@ int print_title_json(const cJSON *const json) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print some title information in plain text. */
|
/* Return 0 if all required fields for a title / id check are present. */
|
||||||
int print_title_plain(const cJSON *json) {
|
int verify_title_fields(const cJSON *restrict json) {
|
||||||
cJSON *title = cJSON_GetObjectItem(json, "title");
|
const char **key = TITLE_LOOKUP_KEYS;
|
||||||
cJSON *imdb_rating = cJSON_GetObjectItem(json, "imdbRating");
|
|
||||||
|
|
||||||
if (title == NULL || imdb_rating == NULL) {
|
while (*key != NULL) {
|
||||||
printf("Could not find title or rating in response.\n");
|
|
||||||
|
if (cJSON_GetObjectItem(json, *key) == NULL) {
|
||||||
|
fprintf(stderr, "Missing field '%s' in JSON.\n", *key);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Found: '%s' with rating of %s\n", title->valuestring,
|
key++;
|
||||||
imdb_rating->valuestring);
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Print some title information in plain text. */
|
||||||
|
int print_title_plain(const cJSON *restrict json) {
|
||||||
|
if (verify_title_fields(json) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
cJSON *title = cJSON_GetObjectItem(json, "Title");
|
||||||
|
cJSON *rated = cJSON_GetObjectItem(json, "Rated");
|
||||||
|
cJSON *released = cJSON_GetObjectItem(json, "Released");
|
||||||
|
|
||||||
|
printf("%s [%s]\n", title->valuestring, rated->valuestring);
|
||||||
|
printf("Released on %s\n", released->valuestring);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_title_fancy(const cJSON *restrict json) {
|
||||||
|
/* Bad looking, but attempts to fetch, and show the poster if possible. */
|
||||||
|
cJSON *poster = cJSON_GetObjectItem(json, "Poster");
|
||||||
|
if (poster != NULL) {
|
||||||
|
|
||||||
|
struct fetch *f = fetch_init();
|
||||||
|
CURLU *url = init_curl_url(poster->valuestring);
|
||||||
|
|
||||||
|
if (url != NULL) {
|
||||||
|
|
||||||
|
struct response *resp = fetch(f, url);
|
||||||
|
|
||||||
|
if (resp != NULL) {
|
||||||
|
process_image_mem((const unsigned char *)resp->data, resp->size);
|
||||||
|
response_cleanup(resp);
|
||||||
|
fetch_cleanup(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return print_title_plain(json);
|
||||||
|
}
|
||||||
|
|
||||||
int handle_response(struct response *restrict resp) {
|
int handle_response(struct response *restrict resp) {
|
||||||
cJSON *json = NULL;
|
cJSON *json = NULL;
|
||||||
|
|
||||||
|
|
@ -143,20 +211,13 @@ int main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Just validate and add options directly to the request now. */
|
/* Just validate and add options directly to the request now. */
|
||||||
CURLU *url = curl_url();
|
CURLU *url = init_curl_url(OMDB_URL);
|
||||||
CURLUcode ures;
|
|
||||||
|
|
||||||
if (url == NULL) {
|
if (url == NULL) {
|
||||||
fputs("Out of memory.\n", stderr);
|
fputs("Can't set url for retrieval.\n", stderr);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ures = curl_url_set(url, CURLUPART_URL, OMDB_URL, 0)) != CURLUE_OK) {
|
while ((ch = getopt_long(argc, argv, "hijk:ft:y:", opts, NULL)) != -1) {
|
||||||
fprintf(stderr, "Couldn't set url: %s\n", curl_url_strerror(ures));
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((ch = getopt_long(argc, argv, "hijk:t:", opts, NULL)) != -1) {
|
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'i':
|
case 'i':
|
||||||
/* Lookup by ID */
|
/* Lookup by ID */
|
||||||
|
|
@ -170,10 +231,16 @@ int main(int argc, char **argv) {
|
||||||
k_flag = true;
|
k_flag = true;
|
||||||
set_param(url, "apikey", optarg);
|
set_param(url, "apikey", optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'f':
|
||||||
|
set_param(url, "plot", "full");
|
||||||
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
/* Type: movie, series, episode */
|
/* Type: movie, series, episode */
|
||||||
strlcpy(search_mode, optarg, sizeof search_mode);
|
strlcpy(search_mode, optarg, sizeof search_mode);
|
||||||
break;
|
break;
|
||||||
|
case 'y':
|
||||||
|
set_param(url, "year", optarg);
|
||||||
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
fprintf(stderr, "Invalid option'%c'.\n", optopt);
|
fprintf(stderr, "Invalid option'%c'.\n", optopt);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
@ -209,7 +276,7 @@ int main(int argc, char **argv) {
|
||||||
struct fetch *f = fetch_init(); /* Check this */
|
struct fetch *f = fetch_init(); /* Check this */
|
||||||
struct response *resp = fetch(f, url);
|
struct response *resp = fetch(f, url);
|
||||||
handle_response(resp);
|
handle_response(resp);
|
||||||
process_image("./test.jpg");
|
/* process_image("./test.jpg"); */
|
||||||
free(resp->data);
|
free(resp->data);
|
||||||
free(resp);
|
free(resp);
|
||||||
curl_url_cleanup(url);
|
curl_url_cleanup(url);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue