summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrafa_99 <raroma09@gmail.com>2021-08-30 14:38:01 +0100
committerrafa_99 <raroma09@gmail.com>2021-08-30 14:38:01 +0100
commitb731bcbf8eada98e647b3d7a5944f65cba78edb7 (patch)
treecf8e0ce5f4c52e46e971acbd4857c2ca038b83df
Initial development of queryt files
-rw-r--r--Makefile18
-rw-r--r--libs/curl.c43
-rw-r--r--libs/curl.h3
-rw-r--r--libs/string.c28
-rw-r--r--libs/string.h10
-rw-r--r--queryt.c10
-rw-r--r--utils.c196
-rw-r--r--utils.h8
-rw-r--r--video.c49
-rw-r--r--video.h24
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;
+}
diff --git a/utils.c b/utils.c
new file mode 100644
index 0000000..76a9eea
--- /dev/null
+++ b/utils.c
@@ -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;
+}
diff --git a/utils.h b/utils.h
new file mode 100644
index 0000000..ac55ffa
--- /dev/null
+++ b/utils.h
@@ -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);
diff --git a/video.c b/video.c
new file mode 100644
index 0000000..1091175
--- /dev/null
+++ b/video.c
@@ -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);
+}
diff --git a/video.h b/video.h
new file mode 100644
index 0000000..59ee2ae
--- /dev/null
+++ b/video.h
@@ -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);