Bladeren bron

feature: improved wikipedia infobox by searching first

frosty 1 week geleden
bovenliggende
commit
c802a4784a
1 gewijzigde bestanden met toevoegingen van 91 en 4 verwijderingen
  1. 91 4
      src/Infobox/Wikipedia.c

+ 91 - 4
src/Infobox/Wikipedia.c

@@ -182,23 +182,110 @@ InfoBox fetch_wiki_data(char *api_url) {
   return info;
 }
 
-char *construct_wiki_url(const char *search_term) {
+static xmlNode *find_node_recursive(xmlNode *node, const char *target_name) {
+  for (xmlNode *cur = node; cur; cur = cur->next) {
+    if (cur->type == XML_ELEMENT_NODE && strcmp((const char *)cur->name, target_name) == 0) {
+      return cur;
+    }
+    xmlNode *found = find_node_recursive(cur->children, target_name);
+    if (found)
+      return found;
+  }
+  return NULL;
+}
+
+static char *get_first_search_result(const char *search_term) {
   CURL *curl = curl_easy_init();
   if (!curl)
     return NULL;
 
   char *escaped_term = curl_easy_escape(curl, search_term, 0);
+  const char *search_base =
+      "https://en.wikipedia.org/w/api.php?action=query&list=search&srsearch=";
+  const char *search_suffix =
+      "&format=xml&origin=*&srlimit=1";
+
+  char *search_url = malloc(strlen(search_base) + strlen(escaped_term) +
+                           strlen(search_suffix) + 1);
+  if (!search_url) {
+    curl_free(escaped_term);
+    curl_easy_cleanup(curl);
+    return NULL;
+  }
+
+  strcpy(search_url, search_base);
+  strcat(search_url, escaped_term);
+  strcat(search_url, search_suffix);
+
+  curl_free(escaped_term);
+
+  struct WikiMemoryStruct chunk = {malloc(1), 0};
+  if (!chunk.memory) {
+    free(search_url);
+    curl_easy_cleanup(curl);
+    return NULL;
+  }
+
+  curl_easy_setopt(curl, CURLOPT_URL, search_url);
+  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WikiWriteMemoryCallback);
+  curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk);
+  curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
+  apply_proxy_settings(curl);
+
+  char *first_title = NULL;
+  if (curl_easy_perform(curl) == CURLE_OK && chunk.size > 0) {
+    xmlDocPtr doc = xmlReadMemory(chunk.memory, chunk.size, "noname.xml", NULL, 0);
+    if (doc) {
+      xmlNode *root = xmlDocGetRootElement(doc);
+      xmlNode *search_node = find_node_recursive(root, "search");
+      if (search_node) {
+        for (xmlNode *sr = search_node->children; sr; sr = sr->next) {
+          if (sr->type == XML_ELEMENT_NODE &&
+              strcmp((const char *)sr->name, "p") == 0) {
+            xmlChar *title = xmlGetProp(sr, (const xmlChar *)"title");
+            if (title) {
+              first_title = strdup((const char *)title);
+              xmlFree(title);
+              break;
+            }
+          }
+        }
+      }
+      xmlFreeDoc(doc);
+    }
+  }
+
+  free(chunk.memory);
+  free(search_url);
+  curl_easy_cleanup(curl);
+
+  return first_title;
+}
+
+char *construct_wiki_url(const char *search_term) {
+  char *first_title = get_first_search_result(search_term);
+  if (!first_title)
+    return NULL;
+
+  CURL *curl = curl_easy_init();
+  if (!curl) {
+    free(first_title);
+    return NULL;
+  }
+
+  char *escaped_title = curl_easy_escape(curl, first_title, 0);
   const char *base = "https://en.wikipedia.org/w/"
                      "api.php?action=query&prop=extracts|pageimages&exintro&"
                      "explaintext&pithumbsize=400&format=xml&origin=*&titles=";
 
-  char *full_url = malloc(strlen(base) + strlen(escaped_term) + 1);
+  char *full_url = malloc(strlen(base) + strlen(escaped_title) + 1);
   if (full_url) {
     strcpy(full_url, base);
-    strcat(full_url, escaped_term);
+    strcat(full_url, escaped_title);
   }
 
-  curl_free(escaped_term);
+  curl_free(escaped_title);
   curl_easy_cleanup(curl);
+  free(first_title);
   return full_url;
 }