summaryrefslogtreecommitdiff
path: root/yahoo.c
blob: 7b5492256be6427ebd8aae6e9acc816105f1aff5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "assets.h"
#include "json_curl.h"
#include "quotes.h"
#include "yahoo.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <json-c/json.h>

int yahoo_get_quote_symbols(struct asset **assets, int n, char **bufptr)
{
	size_t bufsize = 1024;
	char *buf = malloc(bufsize);
	if (!buf) return -1;
	int len = 0;

	for (int i = 0; i < n; ++i) {
		if (assets[i]->type == CRYPTO) {
			int c;
retry:
			if (strcmp(assets[i]->symbol, "BTC") == 0) {
				c = snprintf(buf + len, bufsize - len, "%s-USD,",
					assets[i]->symbol);
			} else {
				c = snprintf(buf + len, bufsize - len, "%s-USD,%s-BTC,",
					assets[i]->symbol, assets[i]->symbol);
			}

			if (c < 0)
				continue;
			if ((unsigned)c >= bufsize - len) {
				char *tmpbuf = realloc(buf, (bufsize *= 2));
				if (tmpbuf) {
					buf = tmpbuf;
				} else {
					free(buf);
					return -1;
				}

				goto retry;
			}

			len += c;
		}
	}

	buf[--len] = '\0';
	*bufptr = buf;
	return len;
}

static json_object *fetch_quotes(const char *symbols)
{
	CURL *curl = curl_easy_init();
	if (!curl) return NULL;

	char base[] = "https://query1.finance.yahoo.com/v7/finance/quote?symbols=";
	size_t len_symbols = strlen(symbols);
	char uri[sizeof(base) + len_symbols];
	memcpy(uri, base, sizeof(base) - 1);
	memcpy(uri + sizeof(base) - 1, symbols, len_symbols + 1);

	json_object *json = json_curl_perform(curl, uri);
	curl_easy_cleanup(curl);
	return json;
}

int yahoo_get_quotes(const char *symbols, struct quote ***quotes_ptr)
{
	json_object *tmp, *json = fetch_quotes(symbols);
	json_object_object_get_ex(json, "quoteResponse", &tmp);
	json_object_object_get_ex(tmp, "result", &tmp);

	int n = json_object_array_length(tmp);
	struct quote **quotes = calloc(n, sizeof(**quotes));
	*quotes_ptr = quotes;

	for (int i = 0; i < n; ++i) {
		struct quote *q = calloc(1, sizeof(*q));
		json_object *q_tmp, *q_json = json_object_array_get_idx(tmp, i);

		json_object_object_get_ex(q_json, "quoteType", &q_tmp);
		json_object_object_get_ex(q_json,
			(strcmp(json_object_get_string(q_tmp), "CRYPTOCURRENCY") == 0) ?
				"fromCurrency" : "symbol",
			&q_tmp);
		q->symbol = strdup(json_object_get_string(q_tmp));

		json_object_object_get_ex(q_json, "currency", &q_tmp);
		q->currency = strdup(json_object_get_string(q_tmp));

		json_object_object_get_ex(q_json, "regularMarketPrice", &q_tmp);
		q->price = json_object_get_double(q_tmp);

		json_object_object_get_ex(q_json, "regularMarketChangePercent",
			&q_tmp);
		q->change_percent = json_object_get_double(q_tmp);

		quotes[i] = q;
	}

	json_object_put(json);
	return n;
}