#include "assets.h" #include "json_curl.h" #include "output.h" #include "quotes.h" #include "tda.h" #include "yahoo.h" #include #include #include #include #include #include #define ASSETS_MAX 100 int load_assets_stock(struct asset **assets, lua_State *L) { lua_getglobal(L, "stock"); lua_pushnil(L); int n = 0; while (lua_next(L, -2)) { struct asset *asset = calloc(1, sizeof(*asset)); asset->symbol = strdup(lua_tostring(L, -2)); asset->amt = lua_tonumber(L, -1); asset->type = STOCK; assets[n++] = asset; lua_pop(L, 1); } lua_pop(L, 1); return n; } int load_assets_crypto(struct asset **assets, lua_State *L) { lua_getglobal(L, "crypto"); lua_pushnil(L); int n = 0; while (lua_next(L, -2)) { struct asset *asset = calloc(1, sizeof(*asset)); asset->symbol = strdup(lua_tostring(L, -2)); asset->amt = lua_tonumber(L, -1); asset->type = CRYPTO; assets[n++] = asset; lua_pop(L, 1); } lua_pop(L, 1); return n; } static int read_token(const char *path, char *buf, size_t bufsize) { FILE *f = fopen(path, "r"); if (!f) return 0; int ret = 0; if (fgets(buf, bufsize, f)) { ret = 1; char *nl = strchr(buf, '\n'); if (nl) *nl = '\0'; } fclose(f); return ret; } static int write_token(const char *path, char *buf) { FILE *f = fopen(path, "w"); if (!f) return 0; int ret = 0; if (fputs(buf, f) != EOF && fputc('\n', f) != EOF) ret = 1; fclose(f); return ret; } int load_tda(struct asset **assets, lua_State *L, struct tda_session **sessptr) { int ret = -1; struct tda_session *sess = NULL; size_t token_size = 2048; char *token = malloc(token_size); if (!token) goto out; lua_getglobal(L, "tda"); lua_getfield(L, -1, "account_id"); const char *account_id = lua_tostring(L, -1); lua_getfield(L, -2, "client_id"); const char *client_id = lua_tostring(L, -1); lua_getfield(L, -3, "token_path"); const char *token_path = lua_tostring(L, -1); if (read_token(token_path, token, token_size) && (sess = tda_init(client_id, account_id, token))) { if (write_token(token_path, sess->refresh_token)) { ret = tda_load_assets(sess, assets); } else { tda_cleanup(sess); sess = NULL; } } lua_pop(L, 4); free(token); out: *sessptr = sess; return ret; } int main() { lua_State *L = luaL_newstate(); luaL_openlibs(L); luaL_dofile(L, "config.lua"); lua_pushcfunction(L, push_field_lua); lua_setglobal(L, "get_asset_field"); if (curl_global_init(CURL_GLOBAL_DEFAULT) != 0) return 1; struct tda_session *tda; struct asset **assets = calloc(ASSETS_MAX, sizeof(*assets)); int n_assets = load_tda(assets, L, &tda); n_assets += load_assets_stock(assets + n_assets, L); n_assets += load_assets_crypto(assets + n_assets, L); struct quote **quotes; char *symbols; int n_quotes; yahoo_get_quote_symbols(assets, n_assets, &symbols); n_quotes = yahoo_get_quotes(symbols, "es); free(symbols); add_quotes_to_assets(assets, n_assets, quotes, n_quotes); for (int i = 0; i < n_quotes; ++i) quote_free(quotes[i]); free(quotes); tda_get_quote_symbols(assets, n_assets, &symbols); n_quotes = tda_get_quotes(tda, symbols, "es); free(symbols); add_quotes_to_assets(assets, n_assets, quotes, n_quotes); for (int i = 0; i < n_quotes; ++i) quote_free(quotes[i]); free(quotes); qsort(assets, n_assets, sizeof(*assets), asset_cmp); n_assets += add_totals(assets, n_assets); output(assets, n_assets, L); for (int i = 0; i < n_assets; ++i) asset_free(assets[i]); free(assets); tda_cleanup(tda); curl_global_cleanup(); lua_close(L); return 0; }