diff options
author | rafa_99 <raroma09@gmail.com> | 2021-08-30 14:38:01 +0100 |
---|---|---|
committer | rafa_99 <raroma09@gmail.com> | 2021-08-30 14:38:01 +0100 |
commit | b731bcbf8eada98e647b3d7a5944f65cba78edb7 (patch) | |
tree | cf8e0ce5f4c52e46e971acbd4857c2ca038b83df |
Initial development of queryt files
-rw-r--r-- | Makefile | 18 | ||||
-rw-r--r-- | libs/curl.c | 43 | ||||
-rw-r--r-- | libs/curl.h | 3 | ||||
-rw-r--r-- | libs/string.c | 28 | ||||
-rw-r--r-- | libs/string.h | 10 | ||||
-rw-r--r-- | queryt.c | 10 | ||||
-rw-r--r-- | utils.c | 196 | ||||
-rw-r--r-- | utils.h | 8 | ||||
-rw-r--r-- | video.c | 49 | ||||
-rw-r--r-- | video.h | 24 |
10 files changed, 389 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0d54b70 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +# queryt - youtube query tool +# See LICENSE file for copyright and license details. + +# Source Code +SRC = queryt.c utils.c libs/curl.c libs/string.c video.c + +# Compiled Code +CLEAN = queryt + +# MakeOPTS +build: clean + cc -o queryt ${SRC} -lcurl + +debug: clean + cc -g -o queryt ${SRC} -lcurl + +clean: + rm -rf ${CLEAN} diff --git a/libs/curl.c b/libs/curl.c new file mode 100644 index 0000000..bf6cb93 --- /dev/null +++ b/libs/curl.c @@ -0,0 +1,43 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <curl/curl.h> +#include <curl/easy.h> +#include "curl.h" +#include "string.h" + +size_t downloadCallback(char *ptr, size_t size, size_t nmemb, String *output) +{ + output->length += nmemb; + output->string = realloc(output->string, output->length + 1); + strcat(output->string, ptr); + return size*nmemb; +} + +char* downloadPage(char *page) +{ + char *str = NULL; + + if ( page != NULL && strlen(page) > 0 ) + { + // Initializing cURL and Temporary String Structure + CURL *curl; + String s = newString(""); + curl = curl_easy_init(); + + // Saving cURL'ed webpage into String Structure + curl_easy_setopt(curl, CURLOPT_URL, page); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, downloadCallback); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s); + curl_easy_perform(curl); + + str = (char *) calloc(s.length + 1, sizeof(char)); + strcpy(str, s.string); + + // Cleanup + curl_easy_cleanup(curl); + freeString(&s); + } + + return str; +} diff --git a/libs/curl.h b/libs/curl.h new file mode 100644 index 0000000..3aa59a2 --- /dev/null +++ b/libs/curl.h @@ -0,0 +1,3 @@ +#pragma once + +char* downloadPage(char *page); diff --git a/libs/string.c b/libs/string.c new file mode 100644 index 0000000..9917e4f --- /dev/null +++ b/libs/string.c @@ -0,0 +1,28 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "string.h" + +String newString(char *string) +{ + String s; + if (string != NULL && strlen(string) > 0) + { + s.length = strlen(string); + s.string = (char *)calloc(s.length + 1, sizeof(char)); + strcpy(s.string, string); + } + else + { + s.length = 0; + s.string = (char *)calloc(1, sizeof(char)); + } + + return s; +} + +void freeString(String *s) +{ + s->length = 0; + free(s->string); +} diff --git a/libs/string.h b/libs/string.h new file mode 100644 index 0000000..84a1519 --- /dev/null +++ b/libs/string.h @@ -0,0 +1,10 @@ +#pragma once + +typedef struct string +{ + char *string; + int length; +} String; + +String newString(char *string); +void freeString(String *s); diff --git a/queryt.c b/queryt.c new file mode 100644 index 0000000..6f6db4e --- /dev/null +++ b/queryt.c @@ -0,0 +1,10 @@ +#include <stdio.h> +#include <stdlib.h> +#include "video.h" +#include "utils.h" + +int main(int argc, char **argv) +{ + //ToDo + return 0; +} @@ -0,0 +1,196 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "utils.h" +#include "libs/curl.h" +#include "libs/string.h" + +int tokenCount(char *string, char *delimiter) +{ + int totalCount = 0; + + if (string != NULL && delimiter != NULL) + { + char *auxString = (char *)calloc(strlen(string) + 1, sizeof(char)); + strcpy(auxString, string); + + char *token = strtok(auxString, delimiter); + + while (token != NULL) + { + totalCount++; + token = strtok(NULL, delimiter); + } + + free(auxString); + } + + return totalCount; +} + +char **tokenizer(char *string, char *delimiter) +{ + char **tokens = NULL; + + if (string != NULL && delimiter != NULL) + { + char *auxString = (char *)calloc(strlen(string) + 1, sizeof(char)); + strcpy(auxString, string); + + tokens = (char **)calloc(tokenCount(auxString, delimiter), sizeof(char *)); + char *tempToken = strtok(auxString, delimiter); + + for (int i = 0; tempToken != NULL; i++) + { + tokens[i] = (char *)calloc(strlen(tempToken) + 1, sizeof(char)); + strcpy(tokens[i], tempToken); + tempToken = strtok(NULL, delimiter); + } + + free(auxString); + } + else + { + tokens = (char **)calloc(1, sizeof(char)); + } + + return tokens; +} + +void freeTokens(char **tokens, int size) +{ + if ( size > 0 ) + { + for ( int i = 0; i < size; i++ ) + { + free(tokens[i]); + } + } + free(tokens); +} + +char *queryNormalizer(char *query) +{ + char *norm = NULL; + if (query != NULL && strlen(query) > 0) + { + // Declaring Initial Query Size + int querySize = strlen(query); + + // Calculating Normalized Query Size Allocation + for (int i = 0; i < strlen(query); i++) + { + if (query[i] == '+' || query[i] == '#' || query[i] == '&') + { + querySize += 2; + } + } + + // Allocating Memory + norm = (char *)calloc(querySize + 1, sizeof(char)); + + // Creating New Normalized Query + for (int i = 0, added = 0; i < strlen(query); i++) + { + switch (query[i]) + { + case '+': + /* fall through */ + case '#': + /* fall through */ + case '&': + for (int j = 0; j < 3; j++) + { + switch (j) + { + case 0: + norm[i + j + added] = '%'; + break; + case 1: + norm[i + j + added] = '2'; + break; + case 2: + switch (query[i]) + { + case '+': + norm[i + j + added] = 'B'; + break; + case '#': + norm[i + j + added] = '3'; + break; + case '&': + norm[i + j + added] = '6'; + } + } + } + added += 2; + break; + case ' ': + norm[i + added] = '+'; + break; + default: + norm[i + added] = query[i]; + } + } + } + return norm; +} + +int* jsonDataLimits(int tokenCount, char **tokens, char *topDelimiter, char *bottomDelimiter) +{ + int *limits = (int *) calloc(2, sizeof(int)); + + for (int i = 0; i < tokenCount + 1 && (limits[0] == 0 || limits[1] == 0); i++) + { + if (tokens[i] != NULL && strcmp(tokens[i], topDelimiter) == 0 && strcmp(tokens[i + 1], "=") == 0) + { + limits[0] = i + 2; + } + else if (tokens[i] != NULL && limits[1] == 0 && limits[0] > 0 && strstr(tokens[i], bottomDelimiter) != NULL) + { + limits[1] = i; + } + } + + return limits; +} + +char *curlToJSON(char *url) +{ + char *json = NULL; + + if (url != NULL && strlen(url) > 0) + { + // Setting Up Vars + char jsonVar[] = "ytInitialData", unneededHtml[] = ";</script><script", *htmlPage = downloadPage(url), **tokens = tokenizer(htmlPage, " "); + int numberOfTokens = tokenCount(htmlPage, " "), *limits = jsonDataLimits(numberOfTokens, tokens, jsonVar, unneededHtml); + json = (char *)calloc(1, sizeof(char)); + + // Pre Clearing Unused Memory + free(htmlPage); + + // Creating the JSON String + for (int i = limits[0]; i <= limits[1]; i++) + { + if (i < limits[1]) + { + json = realloc(json, (strlen(json) + strlen(tokens[i]) + 2)); + strcat(json, tokens[i]); + strcat(json, " "); + } + else + { + // Last byte doesn't need a extra space + json = realloc(json, (strlen(json) + strlen(tokens[i]) + 1)); + strcat(json, tokens[i]); + } + } + + json[strlen(json) - strlen(unneededHtml)] = '\0'; + + freeTokens(tokens, numberOfTokens); + free(limits); + } + + return json; +} @@ -0,0 +1,8 @@ +#pragma once + +int tokenCount(char *string, char *delimiter); +char** tokenizer(char *string, char *delimiter); +void freeTokens(char **tokens, int size); +char* queryNormalizer(char *query); +int* jsonDataLimits(int tokenCount, char **tokens, char *topDelimiter, char *bottomDelimiter); +char* curlToJSON(char *url); @@ -0,0 +1,49 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "video.h" + +Video createVideo(char *title, char *author, char *id, char *description, time_t duration) +{ + Video video; + + if (title != NULL && strlen(title) > 0) + { + video.title = (char *) calloc(TITLE + 1, sizeof(char)); + strcpy(video.title, title); + } + + if (author != NULL && strlen(author) > 0) + { + video.author = (char *) calloc(AUTHOR + 1, sizeof(char)); + strcpy(video.author, author); + } + + if (id != NULL && strlen(id) > 0) + { + video.id = (char *) calloc(VIDEOID + 1, sizeof(char)); + strcpy(video.id, id); + } + + if (description != NULL && strlen(description) > 0) + { + video.description = (char *) calloc(DESCRIPTION + 1, sizeof(char)); + strcpy(video.description, description); + } + else + { + video.description = (char *) calloc(1, sizeof(char)); + } + + video.duration = duration; + + return video; +} + +void freeVideo(Video *v) +{ + free(v->title); + free(v->author); + free(v->id); + free(v->description); +} @@ -0,0 +1,24 @@ +#pragma once +#include <time.h> + +#define TITLE 100 +#define AUTHOR 120 +#define VIDEOID 11 +#define DESCRIPTION 5000 + +/* + * title -> max 100 characters + * author -> max 120 characters combined + * video id -> max 11 characters + * video description -> max 5000 characters + * thumbnail -> https://i.ytimg.com/vi/[id]/hq720.jpg + */ +typedef struct video +{ + char *title, *author, *id, *description; + time_t duration; +} Video; + + +Video createVideo(char *title, char *author, char *id, char *description, time_t duration); +void freeVideo(Video *v); |