/* * greddit - a very simple GLib-friendly reddit client * Copyright (c) 2009 Thomas Thurman * thomas@thurman.org.uk * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have be able to view the GNU General Public License at * http://www.gnu.org/copyleft/gpl.html ; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include "greddit.h" #define REDDIT_FRONT_PAGE_IN_JSON "http://www.reddit.com/.json" /** * Comparison function for sorting GRedditPost objects by * score. */ static int greddit_post_compare (gconstpointer a, gconstpointer b) { GRedditPost* grpa = (GRedditPost*) a; GRedditPost* grpb = (GRedditPost*) b; if (grpa->score == grpb->score) return 0; else if (grpa->score < grpb->score) return 1; else return -1; } typedef struct { size_t size; char *content; } GRedditIncomingData; static size_t greddit_eat_data (void *buffer, size_t size, size_t nmemb, void *targetp) { GRedditIncomingData *target = (GRedditIncomingData*) targetp; target->content = g_realloc (target->content, target->size + size*nmemb); g_memmove (target->content + target->size, buffer, size*nmemb); target->size += size*nmemb; return size*nmemb; } GSList * greddit_get_posts (void) { JsonParser *parser = json_parser_new (); GSList *result = NULL; GList *posts, *cursor; CURL *curl = curl_easy_init (); GRedditIncomingData json; json.size = 0; json.content = NULL; /* set curl_easy_setopt (curl, CURLOPT_VERBOSE, 1); for debugging here */ curl_easy_setopt (curl, CURLOPT_URL, REDDIT_FRONT_PAGE_IN_JSON); curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, greddit_eat_data); curl_easy_setopt (curl, CURLOPT_WRITEDATA, &json); if (curl_easy_perform (curl) != CURLE_OK) { fprintf (stderr, "Warning: curl error\n"); return NULL; } if (json.content==NULL) { fprintf (stderr, "Warning: empty document\n"); return NULL; } if (!json_parser_load_from_data (parser, json.content, -1, NULL)) { fprintf (stderr, "Warning: malformed JSON:\n%s\n", json.content); g_free (json.content); return NULL; } g_free (json.content); posts = json_array_get_elements (json_node_get_array (json_object_get_member (json_node_get_object (json_object_get_member (json_node_get_object (json_parser_get_root (parser)), "data") ), "children") ) ); for (cursor=posts; cursor; cursor=cursor->next) { JsonNode *wrapper = (JsonNode *) cursor->data; JsonObject *post = json_node_get_object (json_object_get_member (json_node_get_object (wrapper), "data")); GRedditPost *p = g_new(GRedditPost, 1); p->id = g_strdup (json_node_get_string (json_object_get_member (post, "id"))); p->url = g_strdup (json_node_get_string (json_object_get_member (post, "url"))); p->title = g_strdup (json_node_get_string (json_object_get_member (post, "title"))); p->author = g_strdup (json_node_get_string (json_object_get_member (post, "author"))); p->subreddit = g_strdup (json_node_get_string (json_object_get_member (post, "subreddit"))); p->score = json_node_get_int (json_object_get_member (post, "score")); result = g_slist_insert_sorted (result, p, greddit_post_compare); } g_list_free (posts); g_object_unref (parser); curl_easy_cleanup (curl); return result; } void greddit_free_posts (GSList *posts) { GSList *cursor; for (cursor=posts; cursor; cursor=cursor->next) { GRedditPost *grp = (GRedditPost*) cursor->data; g_free (grp->id); g_free (grp->url); g_free (grp->title); g_free (grp->author); g_free (grp->subreddit); } g_slist_free (posts); } /* eof greddit.c */