diff options
author | awy <awy@awy.one> | 2025-08-23 23:59:30 +0300 |
---|---|---|
committer | awy <awy@awy.one> | 2025-08-23 23:59:30 +0300 |
commit | 5a0107ba1e9388a3d4ade7faa06a1c94786ae3d2 (patch) | |
tree | 50938c25191f646990147158b1a4ead8c22a2028 /src/sttorrent.c | |
parent | b3526d31b40dbdf37ea4b314c8e9aa94d39b7f8c (diff) |
add sttorrent
Diffstat (limited to 'src/sttorrent.c')
-rw-r--r-- | src/sttorrent.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/src/sttorrent.c b/src/sttorrent.c new file mode 100644 index 0000000..7a5a73c --- /dev/null +++ b/src/sttorrent.c @@ -0,0 +1,169 @@ +/* Copyright (C) 2025 awy <awy@awy.one> + + sttorrent 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 3 of the License, or (at your option) any later version. + + sttorrent 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 received a copy of the GNU General Public + License along with sttorrent. If not, see + <https://www.gnu.org/licenses/>. */ + +#include <curl/curl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "cjson/cJSON.h" + +struct MemoryStruct { + char *memory; + size_t size; +}; + +static size_t +WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) +{ + size_t realsize = size * nmemb; + struct MemoryStruct *mem = (struct MemoryStruct *)userp; + + mem->memory = realloc(mem->memory, mem->size + realsize + 1); + if(mem->memory == NULL) { + /* out of memory! */ + puts("not enough memory (realloc returned NULL)"); + return 0; + } + + memcpy(&(mem->memory[mem->size]), contents, realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + + return realsize; +} + +int +get_session_id(char id[75]) +{ + CURL* handle; + CURLcode res; + struct MemoryStruct chunk; + + chunk.memory = malloc(1); + chunk.size = 0; + + handle = curl_easy_init(); + + if (!handle) { return 1; } + + curl_easy_setopt(handle, CURLOPT_URL, "http://localhost:9091/transmission/rpc"); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *)&chunk); + curl_easy_setopt(handle, CURLOPT_HEADERDATA, (void *)&chunk); + + res = curl_easy_perform(handle); + + if (res != CURLE_OK) { return 1; } + int nl = 0; + int idx = 0; + char buff[128] = {'\0'}; + + for (size_t i = 0; i < chunk.size; i++) { + if (nl > 3) { break; } + if (chunk.memory[i] == '\n') { + nl++; + } + if (nl == 3) { + buff[idx] = chunk.memory[i+1]; + idx++; + } + } + /* cleanup \r\n garbage at the end of the buff*/ + buff[strcspn(buff, "\r\n")] = 0; + strcpy(id, buff); + curl_easy_cleanup(handle); + if (chunk.memory) + free(chunk.memory); + return 0; +} + +int +main(void) +{ + char id[75]; + CURL* handle; + CURLcode res; + cJSON *torrents; + int status_count[7] = {0}; + struct MemoryStruct chunk; + struct curl_slist *headers = NULL; + const char *json = "{\"method\":\"torrent-get\",\"arguments\":{\"fields\":[\"status\", \"percentDone\"]}}"; + + curl_global_init(CURL_GLOBAL_ALL); + /* To get status from transmission we need to send + two CURL requests, first one to obtain session id. */ + get_session_id(id); + + chunk.memory = malloc(1); + chunk.size = 0; + + handle = curl_easy_init(); + + if (!handle) { return 1; } + + curl_easy_setopt(handle, CURLOPT_URL, "localhost:9091/transmission/rpc"); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void *)&chunk); + headers = curl_slist_append(headers, "Content-Type: application/json"); + headers = curl_slist_append(headers, "Accept: application/json"); + headers = curl_slist_append(headers, id); + curl_easy_setopt(handle, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(handle, CURLOPT_POST, 1L); + curl_easy_setopt(handle, CURLOPT_POSTFIELDS, json); + + res = curl_easy_perform(handle); + + if (res != CURLE_OK) { return 1; } + + /* JSON parsing */ + torrents = cJSON_Parse(chunk.memory); + + /* Cleanup */ + curl_easy_cleanup(handle); + if (chunk.memory) + free(chunk.memory); + curl_global_cleanup(); + + torrents = cJSON_GetObjectItem(torrents, "arguments"); + torrents = cJSON_GetObjectItem(torrents, "torrents"); + + if (cJSON_GetArraySize(torrents) == 0) { return 0; } + + /* Counting statuses */ + for (int i = 0; i < cJSON_GetArraySize(torrents); i++) { + cJSON *val = cJSON_GetArrayItem(torrents, i); + cJSON *status = cJSON_GetObjectItem(val, "status"); + if (status) { + int s = status->valueint; + status_count[s]++; + } + } + + for (int i = 0; i < 7; i++) { + if (status_count[i] == 0) { continue; } + switch (i) { + case 0: printf(" "); break; + case 3: printf(" "); break; + case 4: printf(" "); break; + case 5: printf(" "); break; + case 6: printf(" "); break; + default: break; + } + printf("%d", status_count[i]); + } + + return 0; +} |