#include #include #include #include #include "imdb_search.h" #include "upcitemdb.h" // ANSI color codes #define RESET "\033[0m" #define RED "\033[31m" #define GREEN "\033[32m" #define YELLOW "\033[33m" #define BLUE "\033[34m" #define MAGENTA "\033[35m" #define CYAN "\033[36m" #define WHITE "\033[37m" #define PRINT_HEADER(title) \ printf(MAGENTA "\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" RESET); \ printf(CYAN " %s\n" RESET, title); \ printf(MAGENTA "┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅\n" RESET); #define PRINT_HEADER_SMALL(title) \ printf(MAGENTA "\n–––––––––––––––––––––––––––––––––––––––––\n" RESET); \ printf(CYAN " %s\n" RESET, title); \ #define DATABASE_FILE "selected_results.db" typedef struct { SearchResult result; Websearch_st web_data; char file_path[256]; char search_query[256]; char barcode[14]; } DataStruct; void clearInputBuffer() { fseek(stdin,0,SEEK_END); fflush(stdout); } void append_to_database(const char *entry) { FILE *db_file = fopen(DATABASE_FILE, "a"); if (db_file == NULL) { fprintf(stderr, "Failed to open database file for writing.\n"); return; } fprintf(db_file, "%s\n", entry); fclose(db_file); } // Helper function to check if a string consists of only digits int is_numeric(const char *str) { if (str == NULL) { return 0; } for (int i = 0; str[i] != '\0'; i++) { if (!isdigit((unsigned char)str[i])) { return 0; // Return false if a non-digit character is found } } return 1; // Return true if all characters are digits } #include #include #include #include // Ensure directory exists void ensure_directory_exists(const char *dir) { struct stat st = {0}; if (stat(dir, &st) == -1) { mkdir(dir, 0700); } } // Function implementations DataStruct createDataStruct(SearchResult *result, Websearch_st *web_data, char search_query[256], char barcode[14]) { barcode[13] = '\0'; DataStruct data; snprintf(data.file_path, sizeof(data.file_path), "local/%s.txt", result->tconst); data.result = *result; data.web_data = *web_data; strncpy(data.search_query, search_query, sizeof(data.search_query) - 1); strncpy(data.barcode, barcode, 13); data.barcode[13] = '\0'; return data; } void writeStructToFile(DataStruct *data) { char file_path[512]; snprintf(file_path, sizeof(file_path), "local/%s.txt", data->result.tconst); ensure_directory_exists("local"); FILE *file = fopen(file_path, "w"); if (!file) { perror("Failed to open file for writing"); return; } // Write SearchResult data fprintf(file, "tconst=%s\n", data->result.tconst); fprintf(file, "primaryTitle=%s\n", data->result.primaryTitle); fprintf(file, "selected=%s\n", data->result.selected); fprintf(file, "selected_id=%d\n", data->result.selected_id); fprintf(file, "score=%.2f\n", data->result.score); fprintf(file, "barcode=%s\n", data->barcode); fprintf(file, "searchQuery=%s\n", data->search_query); // Write associated TitleEntry data if (data->result.title) { TitleEntry *title = data->result.title; fprintf(file, "\n[TitleEntry]\n"); fprintf(file, "tconst=%s\n", title->tconst); fprintf(file, "primaryTitle=%s\n", title->primaryTitle); fprintf(file, "originalTitle=%s\n", title->originalTitle); fprintf(file, "titleType=%s\n", title->titleType); fprintf(file, "startYear=%d\n", title->startYear); fprintf(file, "endYear=%d\n", title->endYear); fprintf(file, "isAdult=%d\n", title->isAdult); fprintf(file, "runtimeMinutesgenres=%s\n", title->runtimeMinutesgenres); if (title->ratingInfo) { fprintf(file, "\n[RatingInfo]\n"); fprintf(file, "averageRating=%.1f\n", title->ratingInfo->averageRating); fprintf(file, "numVotes=%d\n", title->ratingInfo->numVotes); } } // Write Websearch_st data fprintf(file, "\n[WebSearch]\n"); fprintf(file, "title=%s\n", data->web_data.title); fprintf(file, "lowestRecordedPrice=%.2f\n", data->web_data.lowest_recorded_price); fprintf(file, "highestRecordedPrice=%.2f\n", data->web_data.highest_recorded_price); fprintf(file, "category=%s\n", data->web_data.category); fclose(file); printf("\nSaved result to " WHITE "%s\n" RESET, file_path); } // Function to read data from a file and populate DataStruct int readStructFromFile(const char *file_path, DataStruct *data) { FILE *file = fopen(file_path, "r"); if (!file) { perror("Failed to open file for reading"); return -1; // Return -1 to indicate error } char line[512]; TitleEntry *title = NULL; Websearch_st *web_data = NULL; while (fgets(line, sizeof(line), file)) { // Remove newline at the end of the line line[strcspn(line, "\n")] = '\0'; // Read the SearchResult fields if (strncmp(line, "tconst=", 7) == 0) { strncpy(data->result.tconst, line + 7, sizeof(data->result.tconst) - 1); } else if (strncmp(line, "primaryTitle=", 13) == 0) { strncpy(data->result.primaryTitle, line + 13, sizeof(data->result.primaryTitle) - 1); } else if (strncmp(line, "selected=", 9) == 0) { strncpy(data->result.selected, line + 9, sizeof(data->result.selected) - 1); } else if (strncmp(line, "selected_id=", 12) == 0) { data->result.selected_id = atoi(line + 12); } else if (strncmp(line, "score=", 6) == 0) { data->result.score = atof(line + 6); } else if (strncmp(line, "barcode=", 8) == 0) { strncpy(data->barcode, line + 8, sizeof(data->barcode) - 1); } else if (strncmp(line, "searchQuery=", 12) == 0) { strncpy(data->search_query, line + 12, sizeof(data->search_query) - 1); } // Read the TitleEntry fields (if they exist) if (strncmp(line, "[TitleEntry]", 12) == 0) { title = malloc(sizeof(TitleEntry)); // Allocate memory for TitleEntry memset(title, 0, sizeof(TitleEntry)); // Initialize the TitleEntry struct } else if (title) { if (strncmp(line, "tconst=", 7) == 0) { strncpy(title->tconst, line + 7, sizeof(title->tconst) - 1); } else if (strncmp(line, "primaryTitle=", 13) == 0) { strncpy(title->primaryTitle, line + 13, sizeof(title->primaryTitle) - 1); } else if (strncmp(line, "originalTitle=", 14) == 0) { strncpy(title->originalTitle, line + 14, sizeof(title->originalTitle) - 1); } else if (strncmp(line, "titleType=", 10) == 0) { strncpy(title->titleType, line + 10, sizeof(title->titleType) - 1); } else if (strncmp(line, "startYear=", 10) == 0) { title->startYear = atoi(line + 10); } else if (strncmp(line, "endYear=", 8) == 0) { title->endYear = atoi(line + 8); } else if (strncmp(line, "isAdult=", 8) == 0) { title->isAdult = atoi(line + 8); } else if (strncmp(line, "runtimeMinutesgenres=", 21) == 0) { strncpy(title->runtimeMinutesgenres, line + 21, sizeof(title->runtimeMinutesgenres) - 1); } else if (strncmp(line, "[RatingInfo]", 12) == 0) { // Allocate memory for RatingInfo title->ratingInfo = malloc(sizeof(RatingInfo)); memset(title->ratingInfo, 0, sizeof(RatingInfo)); } else if (title->ratingInfo) { if (strncmp(line, "averageRating=", 14) == 0) { title->ratingInfo->averageRating = atof(line + 14); } else if (strncmp(line, "numVotes=", 9) == 0) { title->ratingInfo->numVotes = atoi(line + 9); } } } // Read the Websearch_st fields if (strncmp(line, "[WebSearch]", 11) == 0) { web_data = malloc(sizeof(Websearch_st)); // Allocate memory for Websearch_st memset(web_data, 0, sizeof(Websearch_st)); // Initialize the Websearch_st struct } else if (web_data) { if (strncmp(line, "title=", 6) == 0) { strncpy(web_data->title, line + 6, sizeof(web_data->title) - 1); } else if (strncmp(line, "lowestRecordedPrice=", 20) == 0) { web_data->lowest_recorded_price = atof(line + 20); } else if (strncmp(line, "highestRecordedPrice=", 21) == 0) { web_data->highest_recorded_price = atof(line + 21); } else if (strncmp(line, "category=", 9) == 0) { strncpy(web_data->category, line + 9, sizeof(web_data->category) - 1); } } } // Close the file fclose(file); // Assign the read values to the DataStruct object if (title) { data->result.title = title; // Link the title data } if (web_data) { data->web_data = *web_data; // Copy the web data into the struct } return 0; // Return 0 to indicate success } void printDataStruct(DataStruct *data) { if (!data || !data->result.title || strlen(data->result.tconst) == 0 || strlen(data->result.primaryTitle) == 0){ printf("No valid dvd found!\n"); return; } printf(MAGENTA "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n"); printf(MAGENTA "┃ " WHITE "%s\n" RESET, data->result.primaryTitle); if (strlen(data->result.selected) > 0 && data->result.title->languageCount > 0 && data->result.selected_id < data->result.title->languageCount) printf(MAGENTA "┃ " WHITE "%s: " WHITE "%s\n" RESET, data->result.selected, data->result.title->languages[data->result.selected_id].title); printf(MAGENTA "┠────────────────────────────────────────────\n" RESET); // Year, ID, Genres if (data->result.title) { printf(MAGENTA "┃ " YELLOW "Primary title: " WHITE "%s\n", data->result.title->primaryTitle); printf(MAGENTA "┃ " YELLOW "Type: " WHITE "%s" YELLOW ", Genre: " WHITE "%s\n", data->result.title->titleType, data->result.title->runtimeMinutesgenres); printf(MAGENTA "┃ " YELLOW "Year: " WHITE "%d-%d" YELLOW ", Adult: " WHITE "%d" YELLOW " Languages: %d\n", data->result.title->startYear, data->result.title->endYear, data->result.title->isAdult, data->result.title->languageCount); } // Type, Rank, Selected printf(MAGENTA "┃ " YELLOW "tconst: " WHITE "%s" CYAN ", Score: " WHITE "%.2f" YELLOW ", Selected: " WHITE "%s" YELLOW " –> " WHITE "%d\n" RESET, data->result.tconst, data->result.score, data->result.selected, data->result.selected_id); // Rating and Votes if (data->result.title && data->result.title->ratingInfo != NULL) { printf(MAGENTA "┃ " YELLOW "Rating: " CYAN "%.1f" YELLOW ", Votes: " WHITE "%d\n" RESET, data->result.title->ratingInfo->averageRating, data->result.title->ratingInfo->numVotes); } printf(MAGENTA "┠────────────────────────────────────────────\n" RESET); // Web Data printf(MAGENTA "┃ " CYAN "Web Search:\n" RESET); printf(MAGENTA "┃ " YELLOW "Title: " RESET "%s\n", data->web_data.title); printf(MAGENTA "┃ " YELLOW "Price: " RESET "%.2f-%.2f\n", data->web_data.lowest_recorded_price, data->web_data.highest_recorded_price); printf(MAGENTA "┃ " YELLOW "Category: " RESET "%s\n", data->web_data.category); printf(MAGENTA "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" RESET); } #include // For stat #include #include #include #include int loadLocalMovies(DataStruct **movies, const char *directory) { struct dirent *entry; DIR *dp = opendir(directory); if (!dp) { perror("Failed to open directory"); return -1; } int count = 0; size_t capacity = 10; // Initial capacity for dynamic allocation *movies = malloc(capacity * sizeof(DataStruct)); if (!*movies) { perror("Failed to allocate memory for movies array"); closedir(dp); return -1; } while ((entry = readdir(dp)) != NULL) { // Skip "." and ".." entries if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } char file_path[512]; snprintf(file_path, sizeof(file_path), "%s/%s", directory, entry->d_name); // Use stat to determine if it is a regular file struct stat file_stat; if (stat(file_path, &file_stat) != 0) { perror("Failed to stat file"); continue; } if (S_ISREG(file_stat.st_mode)) { // Regular file FILE *file = fopen(file_path, "r"); if (!file) { perror("Failed to open file for reading"); continue; } DataStruct data; memset(&data, 0, sizeof(DataStruct)); // Parse the file contents into a DataStruct char line[512]; TitleEntry *title = NULL; Websearch_st *web_data = NULL; while (fgets(line, sizeof(line), file)) { // Remove newline at the end of the line line[strcspn(line, "\n")] = '\0'; // Read the SearchResult fields if (strncmp(line, "tconst=", 7) == 0) { strncpy(data.result.tconst, line + 7, sizeof(data.result.tconst) - 1); } else if (strncmp(line, "primaryTitle=", 13) == 0) { strncpy(data.result.primaryTitle, line + 13, sizeof(data.result.primaryTitle) - 1); } else if (strncmp(line, "selected=", 9) == 0) { strncpy(data.result.selected, line + 9, sizeof(data.result.selected) - 1); } else if (strncmp(line, "selected_id=", 12) == 0) { data.result.selected_id = atoi(line + 12); } else if (strncmp(line, "score=", 6) == 0) { data.result.score = atof(line + 6); } else if (strncmp(line, "barcode=", 8) == 0) { strncpy(data.barcode, line + 8, sizeof(data.barcode) - 1); } else if (strncmp(line, "searchQuery=", 12) == 0) { strncpy(data.search_query, line + 12, sizeof(data.search_query) - 1); } // Handle TitleEntry section if (strncmp(line, "[TitleEntry]", 12) == 0) { title = malloc(sizeof(TitleEntry)); memset(title, 0, sizeof(TitleEntry)); } else if (title) { if (strncmp(line, "tconst=", 7) == 0) { strncpy(title->tconst, line + 7, sizeof(title->tconst) - 1); } else if (strncmp(line, "primaryTitle=", 13) == 0) { strncpy(title->primaryTitle, line + 13, sizeof(title->primaryTitle) - 1); } else if (strncmp(line, "originalTitle=", 14) == 0) { strncpy(title->originalTitle, line + 14, sizeof(title->originalTitle) - 1); } else if (strncmp(line, "titleType=", 10) == 0) { strncpy(title->titleType, line + 10, sizeof(title->titleType) - 1); } else if (strncmp(line, "startYear=", 10) == 0) { title->startYear = atoi(line + 10); } else if (strncmp(line, "endYear=", 8) == 0) { title->endYear = atoi(line + 8); } else if (strncmp(line, "isAdult=", 8) == 0) { title->isAdult = atoi(line + 8); } else if (strncmp(line, "runtimeMinutesgenres=", 21) == 0) { strncpy(title->runtimeMinutesgenres, line + 21, sizeof(title->runtimeMinutesgenres) - 1); } else if (strncmp(line, "[RatingInfo]", 12) == 0) { title->ratingInfo = malloc(sizeof(RatingInfo)); memset(title->ratingInfo, 0, sizeof(RatingInfo)); } else if (title->ratingInfo) { if (strncmp(line, "averageRating=", 14) == 0) { title->ratingInfo->averageRating = atof(line + 14); } else if (strncmp(line, "numVotes=", 9) == 0) { title->ratingInfo->numVotes = atoi(line + 9); } } } // Handle Websearch_st section if (strncmp(line, "[WebSearch]", 11) == 0) { web_data = malloc(sizeof(Websearch_st)); memset(web_data, 0, sizeof(Websearch_st)); } else if (web_data) { if (strncmp(line, "title=", 6) == 0) { strncpy(web_data->title, line + 6, sizeof(web_data->title) - 1); } else if (strncmp(line, "lowestRecordedPrice=", 20) == 0) { web_data->lowest_recorded_price = atof(line + 20); } else if (strncmp(line, "highestRecordedPrice=", 21) == 0) { web_data->highest_recorded_price = atof(line + 21); } else if (strncmp(line, "category=", 9) == 0) { strncpy(web_data->category, line + 9, sizeof(web_data->category) - 1); } } } // Close the file fclose(file); // Link TitleEntry and Websearch_st to the main DataStruct if (title) { data.result.title = title; } if (web_data) { data.web_data = *web_data; } // Add DataStruct to the array if (count >= capacity) { capacity *= 2; DataStruct *new_movies = realloc(*movies, capacity * sizeof(DataStruct)); if (!new_movies) { perror("Failed to reallocate memory for movies array"); free(*movies); closedir(dp); return -1; } *movies = new_movies; } (*movies)[count++] = data; } } closedir(dp); return count; } /////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////// #include #include #include #define FILENAME "playlists.txt" #define MAX_ID_LENGTH 14 #define MAX_NAME_LENGTH 256 #define MAX_LINE 512 // Function to check if playlist ID exists int isValidPlaylistID(const char *playlist_id) { FILE *file = fopen(FILENAME, "r"); if (!file) { perror(RED "Error opening playlist file" RESET); return 0; // File not found or cannot be opened } char line[MAX_LINE]; while (fgets(line, sizeof(line), file)) { char id[14], name[257]; // Buffers for ID and name sscanf(line, "%13[^|]|%256[^\n]", id, name); // Parse ID and name if (strcmp(id, playlist_id) == 0) { fclose(file); return 1; // ID found in file } } fclose(file); return 0; // ID not found in file } // Function to display all playlists void list_playlists() { FILE *file = fopen(FILENAME, "r"); if (!file) { perror(RED "Error opening file" RESET); return; } printf(GREEN "Playlists:\n" RESET); printf(BLUE "----------------------------------------\n" RESET); char line[MAX_LINE]; int count = 0; while (fgets(line, sizeof(line), file)) { char id[MAX_ID_LENGTH], name[257]; // Increase ID buffer size if (sscanf(line, "%13[^|]|%256[^\n]", id, name) == 2) { // Parse ID and name printf(CYAN "[%d] " RESET, ++count); printf(YELLOW "ID: " RESET "%s\n", id); printf(MAGENTA " Name: " WHITE "%s\n" RESET, name); printf(BLUE "----------------------------------------\n" RESET); } } if (count == 0) { printf(RED "No playlists found.\n" RESET); } fclose(file); } // Function to add a playlist void add_playlist(char id[14]) { printf("[q] quit\n"); char name[MAX_NAME_LENGTH] = "\0"; // Display existing playlists (placeholder) printf("Existing Playlists:\n"); // list_playlists(); // Uncomment this if you have a function to list playlists list_playlists(); // Input Playlist ID while (1) { printf("Enter new Playlist ID (up to 13 characters): "); fgets(id, 14, stdin); // Read ID (13 + null terminator) id[strcspn(id, "\n")] = 0; // Remove trailing newline if (strlen(id) == 0) { printf("Error: Playlist ID cannot be empty.\n"); continue; } if (id[0] == 'q') return; // User requested to quit if (!isValidPlaylistID(id)) { break; // Valid ID, exit loop } else { printf("Error: Playlist ID '%s' already exists. Please enter a different ID.\n", id); } } // Input Playlist Name while (1) { printf("Enter Playlist Name (up to 256 characters): "); fgets(name, MAX_NAME_LENGTH, stdin); // Read name name[strcspn(name, "\n")] = 0; // Remove trailing newline if (strlen(name) == 0) { printf("Error: Playlist Name cannot be empty.\n"); continue; } if (name[0] == 'q') return; // User requested to quit break; // Valid name, exit loop } // Write to File FILE *file = fopen(FILENAME, "a"); // Open file in append mode if (!file) { perror("Error opening file"); return; } fprintf(file, "%s|%s\n", id, name); // Write ID and name separated by '|' fclose(file); printf("Playlist '%s' added with ID '%s'.\n", name, id); list_playlists(); } // Function to remove a playlist by ID void remove_playlist() { char id[64]; list_playlists(); printf("Remove Playlist ID (up to 10 characters): "); fgets(id, sizeof(id), stdin); id[strcspn(id, "\n")] = 0; // Remove trailing newline if (id[0] == 'q') return; FILE *file = fopen(FILENAME, "r"); if (!file) { perror("Error opening file"); return; } FILE *temp = fopen("temp.txt", "w"); // Temporary file for updated data if (!temp) { perror("Error creating temporary file"); fclose(file); return; } char line[MAX_LINE]; int found = 0; while (fgets(line, sizeof(line), file)) { char line_id[11]; // ID buffer (10 + null terminator) sscanf(line, "%10[^|]", line_id); // Extract the ID before the '|' if (line_id[0] == 'q') return; if (strcmp(line_id, id) != 0) { fputs(line, temp); // Copy line to temp if ID doesn't match } else { found = 1; } } fclose(file); fclose(temp); if (found) { remove(FILENAME); // Delete the original file rename("temp.txt", FILENAME); // Rename temp to original printf("Playlist with ID '%s' removed.\n", id); } else { remove("temp.txt"); // Cleanup temp if no match found printf("Playlist with ID '%s' not found.\n", id); } } void listMovies(DataStruct* movies, int count) { if (count > 0) { printf(GREEN "Loaded %d movies from the local directory:\n" RESET, count); for (int i = 0; i < count; i++) { printf(CYAN "[%d] " RESET, i + 1); printf(YELLOW "Title: " WHITE "%s\n" RESET, movies[i].result.primaryTitle); printf(MAGENTA " ID: " RESET "%s\n", movies[i].result.tconst); printf(RED "----------------------------------------\n" RESET); } } else { printf(RED "No movies found in the local directory.\n" RESET); } } #include #include #include #include // For unlink() int removeMovie(DataStruct *movies, int *movie_count) { listMovies(movies, *movie_count); if (*movie_count <= 0) { printf("No movies available to remove.\n"); return -1; } char tconst[256]; printf("Enter the tconst of the movie to remove: "); if (!fgets(tconst, sizeof(tconst), stdin)) { perror("Failed to read input"); return -1; } // Remove trailing newline tconst[strcspn(tconst, "\n")] = '\0'; int index = -1; for (int i = 0; i < *movie_count; i++) { if (strcmp(movies[i].result.tconst, tconst) == 0) { index = i; break; } } if (index == -1) { printf("No movie found with tconst '%s'.\n", tconst); return -1; } // Delete the associated file if (unlink(movies[index].file_path) == 0) { printf("File '%s' deleted successfully.\n", movies[index].file_path); } else { perror("Failed to delete file"); // Continue removing from memory even if file deletion fails } // Shift elements in the array to remove the movie for (int i = index; i < *movie_count - 1; i++) { movies[i] = movies[i + 1]; } (*movie_count)--; printf("Movie with tconst '%s' removed from memory and file system.\n", tconst); return 0; } // Function to get the playlist name from the file based on playlist ID int getPlaylistName(const char* playlist_id, char playlist_name_p[256]) { FILE *file = fopen("playlists.txt", "r"); if (!file) { perror("Failed to open playlists file"); return 1; // Return NULL if file can't be opened } static char playlist_name[256]; // Static variable to hold playlist name char line[512]; while (fgets(line, sizeof(line), file)) { char id[128], name[256]; // Split the line into ID and name using the delimiter '|' if (sscanf(line, "%127[^|]|%255[^\n]", id, name) == 2) { printf("-- %s %s --\n", id, name);; if (strcmp(id, playlist_id) == 0) { // Found the matching ID, return the playlist name strncpy(playlist_name, name, sizeof(playlist_name) - 1); playlist_name[sizeof(playlist_name) - 1] = '\0'; // Null-terminate fclose(file); strcpy(playlist_name_p, playlist_name); return 0; } } } fclose(file); return 1; // Return NULL if ID not found } void displayPlaylistContent(DataStruct* movies, int movie_count, char playlist_id[11]) { // Prompt user for playlist ID if(strlen(playlist_id) == 0) { list_playlists(); printf("Enter the " YELLOW "playlist ID" RESET ": "); scanf("%s", playlist_id); getchar(); // fix.. playlist_id[strcspn(playlist_id, "\n")] = '\0'; // Remove newline } // Construct playlist file path char playlist_path[512]; snprintf(playlist_path, sizeof(playlist_path), "playlists/%s.txt", playlist_id); // Open playlist file FILE *file = fopen(playlist_path, "r"); if (!file) { printf(RED "Error: Playlist with ID '%s' does not exist or could not be opened.\n" RESET, playlist_id); return; } char playlist_name[256] = "\0"; getPlaylistName(playlist_id, playlist_name); printf(CYAN "\n┌──────────────────────────────────────────────\n" RESET); \ printf(CYAN "│" RESET WHITE "%-24s " RESET "(%s)\n", playlist_name, playlist_id); printf(CYAN "│" GREEN "------------------------------" RESET "\n"); char tconst[256]; int movie_found = 0; // Read tconst entries from playlist file while (fgets(tconst, sizeof(tconst), file)) { tconst[strcspn(tconst, "\n")] = '\0'; // Remove newline // Search for the movie in the provided movies array int found = 0; for (int i = 0; i < movie_count; i++) { if (strcmp(movies[i].result.tconst, tconst) == 0) { printf(CYAN "│" RESET "%3d. " WHITE "%20s" RESET " (" CYAN "%s" RESET ")\n", i + 1, movies[i].result.primaryTitle, movies[i].result.tconst); found = 1; break; } } // If the tconst isn't found in the movies array if (!found) { printf(CYAN "│" YELLOW "Warning: Movie with tconst '%s' not found in the movies list.\n" RESET, tconst); } movie_found = 1; } fclose(file); if (!movie_found) { printf(CYAN "│" RED "This playlist is empty or contains invalid entries.\n" RESET); } else { printf(CYAN "│" GREEN "------------------------------" RESET "\n"); } printf(CYAN "└──────────────────────────────────────────────\n" RESET); \ } void displayRelevantInfo(DataStruct *data) { // Display Title Entry info with colors printf(MAGENTA "\n┌──────────────────────────────────────────────\n" RESET); if (data->result.title) { TitleEntry *title = data->result.title; printf(MAGENTA "│ " WHITE "%-28s" MAGENTA "%s %s" "\n" RESET, title->primaryTitle, title->languageCount > 0 && strlen(data->result.selected) > 0 ? " ||" : "", title->languageCount > 0 && strlen(data->result.selected) > 0 ? title->languages[data->result.selected_id].title : ""); printf(MAGENTA "├──────────────────────────────────────────────\n" RESET); printf(MAGENTA "│" RESET " Type: " WHITE "%s, " RESET "Rank: " WHITE "%.2f, " RESET "Rank_c: " WHITE "%d, " RESET "Selected: " WHITE "%s\n", title->titleType, data->result.score, data->result.selected_id, data->result.selected); // Display Year, ID, and Genres printf(MAGENTA "│" RESET " Year: " WHITE "%d-%d, " RESET "ID: " WHITE "%s, " RESET "Genres: " WHITE "%s\n", title->startYear, title->endYear, data->result.tconst, title->runtimeMinutesgenres); // Optionally display RatingInfo if it exists if (title->ratingInfo) { printf(MAGENTA "│" RESET " Rating: " WHITE "%.1f, " RESET "Votes: " WHITE "%d\n", title->ratingInfo->averageRating, title->ratingInfo->numVotes); } } else { // Display Search Query and Barcode printf(MAGENTA "│" RESET " Search Query: " WHITE "%s, " RESET "Barcode: " WHITE "%s\n", data->search_query, data->barcode); } printf(MAGENTA "└──────────────────────────────────────────────\n" RESET); } // Function to check if a tconst exists in a playlist int is_movie_in_playlist(const char *playlist_id, const char *tconst) { char filepath[256]; // Path to the playlist file char line[14]; // Construct the filepath for the playlist snprintf(filepath, sizeof(filepath), "playlists/%s.txt", playlist_id); // Open the playlist file for reading FILE *file = fopen(filepath, "r"); if (!file) { perror("Error opening playlist file"); return 0; // Return 0 if the file doesn't exist } // Read the file line by line and check for the tconst while (fgets(line, sizeof(line), file)) { trim_whitespace(line); if (strcmp(line, tconst) == 0) { fclose(file); return 1; // tconst found in the playlist } } // Close the file and return 0 if tconst not found fclose(file); return 0; } DataStruct* findMovieByBarcode(DataStruct* movies, int movie_count, char barcode[14]) { // Validate input and find the corresponding movie for (int i = 0; i < movie_count; i++) { if (strcmp(movies[i].barcode, barcode) == 0) { return &movies[i]; } } return NULL; } DataStruct* findMovieByTconst(DataStruct* movies, int movie_count, char tconst[13]) { // Validate input and find the corresponding movie for (int i = 0; i < movie_count; i++) { if (strcmp(movies[i].result.tconst, tconst) == 0) { return &movies[i]; break; } } return NULL; } void addMovieToPlaylist(DataStruct* movies, int movie_count, char tconst[13]) { // List all movies listMovies(movies, movie_count); if (movie_count == 0) { printf(RED "No movies available to add to a playlist.\n" RESET); return; } char input[256] = "\0"; DataStruct *selected_movie = NULL; while (!selected_movie) { // Get barcode or tconst if (strlen(tconst) == 0) { while(strlen(input) == 0) { printf("Enter the " YELLOW "barcode or tconst" RESET " of the movie: "); fgets(input, sizeof(input), stdin); trim_whitespace(input); if (input[0] == 'q') return; } } else { strcpy(input, tconst); } // Validate input and find the corresponding movie printf("TCON#%s#\n", input); selected_movie = findMovieByTconst(movies, movie_count, input); if (!selected_movie) { printf(RED "Error: No movie found with barcode or tconst '%s'.\n" RESET, input); input[0] = '\0'; } } displayRelevantInfo(selected_movie); // List playlists list_playlists(); // Ask for playlist ID or create a new one static char playlist_id[14] = "\0"; char playlist_id_new[14] = "\0"; while (!isValidPlaylistID(playlist_id_new)) { printf(YELLOW "[playlist id|new|q]\n" RESET); printf(WHITE "(%s): " RESET, playlist_id); fgets(playlist_id_new, sizeof(playlist_id_new), stdin); trim_whitespace(playlist_id_new); if (playlist_id_new[0] == 'q') return; if (is_movie_in_playlist(playlist_id_new, selected_movie->result.tconst)) { playlist_id_new[0] = '\0'; printf(RED "Movie already in the playlist.\n" RESET); int c; while ((c = getchar()) != '\n' && c != EOF) { } continue; } if (strlen(playlist_id_new) == 0 && isValidPlaylistID(playlist_id)) break; strcpy(playlist_id, playlist_id_new); if (isValidPlaylistID(playlist_id)) break; if (strcmp(playlist_id, "new") == 0) { add_playlist(playlist_id); } } if (!isValidPlaylistID(playlist_id)) { printf("Invalid Playlist: %s\n", playlist_id); addMovieToPlaylist(movies, movie_count, tconst); return; } char playlist_name[257]; if (strcmp(playlist_id, "new") == 0) { printf("Enter the " YELLOW "name of the new playlist" RESET ": "); fgets(playlist_name, sizeof(playlist_name), stdin); playlist_name[strcspn(playlist_name, "\n")] = '\0'; // Remove newline // Create a new playlist FILE *file = fopen(FILENAME, "a"); if (!file) { perror(RED "Error opening playlist file" RESET); return; } // Generate new ID int new_id = rand() % 10000; // Generate a random ID (for simplicity) snprintf(playlist_id, sizeof(playlist_id), "%04d", new_id); fprintf(file, "%s|%s\n", playlist_id, playlist_name); fclose(file); printf(GREEN "New playlist created with ID: %s\n" RESET, playlist_id); } // Write the tconst to the playlist file char playlist_path[512]; snprintf(playlist_path, sizeof(playlist_path), "playlists/%s.txt", playlist_id); ensure_directory_exists("playlists"); FILE *playlist_file = fopen(playlist_path, "a"); if (!playlist_file) { perror(RED "Error opening playlist file" RESET); return; } fprintf(playlist_file, "%s\n", selected_movie->result.tconst); fclose(playlist_file); printf(GREEN "Movie " WHITE "%s" RESET " (tconst: %s) " GREEN "added to playlist %s\n" RESET, selected_movie->result.primaryTitle, selected_movie->result.tconst, playlist_id); displayPlaylistContent(movies, movie_count, playlist_id); getchar(); // fix.. } // Function to remove a movie from a playlist void removeMovieFromPlaylist(DataStruct* movies, int movie_count) { list_playlists(); char playlist_id[14], tconst[256]; // Ask for the playlist ID to remove movie from printf("Enter the " YELLOW "playlist ID" RESET " to remove from: "); fgets(playlist_id, sizeof(playlist_id), stdin); trim_whitespace(playlist_id); int c; while ((c = getchar()) != '\n' && c != EOF) { } // Validate the playlist ID if (!isValidPlaylistID(playlist_id)) { printf(RED "Error: Playlist ID '%s' does not exist.\n" RESET, playlist_id); clearInputBuffer(); return; } displayPlaylistContent(movies, movie_count, playlist_id); // Ask for the tconst of the movie to be removed printf("Enter the " YELLOW "tconst" RESET " of the movie to remove: "); fgets(tconst, sizeof(tconst), stdin); tconst[strcspn(tconst, "\n")] = '\0'; // Remove newline // File path for the playlist (e.g., "playlists/1234.txt") char playlist_file_path[256]; snprintf(playlist_file_path, sizeof(playlist_file_path), "playlists/%s.txt", playlist_id); // Read the existing playlist file FILE *file = fopen(playlist_file_path, "r"); if (!file) { perror(RED "Error opening playlist file" RESET); return; } // Create a temporary file to store the updated playlist FILE *temp_file = fopen("temp_playlist.txt", "w"); if (!temp_file) { perror(RED "Error creating temporary file" RESET); fclose(file); return; } char line[MAX_LINE]; int found = 0; while (fgets(line, sizeof(line), file)) { // If the line doesn't match the tconst to be removed, write it to the temporary file if (strncmp(line, tconst, strlen(tconst)) != 0) { fputs(line, temp_file); } else { found = 1; } } fclose(file); fclose(temp_file); // If the movie was found and removed, replace the old playlist file with the updated one if (found) { remove(playlist_file_path); // Delete the old playlist file rename("temp_playlist.txt", playlist_file_path); // Rename temp file to original playlist file displayPlaylistContent(movies, movie_count, playlist_id); printf(GREEN "Movie with tconst '%s' removed from playlist '%s'.\n" RESET, tconst, playlist_id); } else { printf(RED "Error: Movie with tconst '%s' not found in playlist '%s'.\n" RESET, tconst, playlist_id); remove("temp_playlist.txt"); // Clean up temp file if no movie was removed } } int main() { DataStruct* movies = NULL; int movie_count = loadLocalMovies(&movies, "local"); listMovies(movies, movie_count); DataStruct* dvd; Websearch_st data_web; TitleEntry *titles; int title_count; RatingInfo *ratings = NULL; // Load the ratings from the file int ratings_count = 0; int is_imbd_data_loadad = 0; /* for (int i = 0; i < 3; i++) { if (titles[i].languages == NULL) continue; for (int j = 0; j < titles[i].languageCount; j++) { if (titles[i].languages[j].isOriginalTitle) printf("ORIGINAL: %s\n", titles[i].tconst); if (titles[i].languages[j].region == NULL) continue; if (strcmp(titles[i].languages[j].region, "DE") == 0) { printf("%d %d\n", i, titles[i].languageCount); break; } } } */ char barcode[14] = "\0"; char file_path[512] = "\0"; SearchResult* res = NULL; SearchResult* res_last = NULL; int search_locally = 0; while (1) { char search_query[256] = "\0"; // If empty, read the search query from stdin while (1) { clearInputBuffer(); printf(BLUE "\n─────────────────────────────────────────\n" RESET); printf(" %s%s" CYAN " DB Action on " YELLOW "%s %s\n" RESET, search_locally ? GREEN : YELLOW ,search_locally ? "Local" : "Global" ,barcode, res_last ? res_last->tconst : ""); // Prompt for input printf(" [list|add|rm|rm last|print|clear|local]\n"); printf(" [list|add|remove] [from] playlist[s]\n"); printf(" [search barcode]\n\n"); printf(" [\"search query\"|\"barcode\"]\n\n"); printf(WHITE "Enter search query: " RESET); fgets(search_query, sizeof(search_query), stdin); printf("\n"); // Remove the trailing newline character if it exists trim_whitespace(search_query); // Check if input is empty int sl = strlen(search_query); if (sl == 0) { printf("Input is empty, please enter a valid query.\n"); continue; } // Check if input is a barcode (14 digits) if (strcmp(search_query, "list playlists") == 0 || strcmp(search_query, "playlists") == 0) { PRINT_HEADER("List Playlists"); list_playlists(); } else if (strcmp(search_query, "remove from playlist") == 0) { PRINT_HEADER("Remove Movie from Playlist"); removeMovieFromPlaylist(movies, movie_count); } else if (strcmp(search_query, "list playlist") == 0 || strcmp(search_query, "playlist") == 0) { PRINT_HEADER("Display Playlist Content"); char empty_playlist_id[14] = ""; displayPlaylistContent(movies, movie_count, empty_playlist_id); } else if (strcmp(search_query, "add playlist") == 0) { PRINT_HEADER("Add Playlist"); char empty_playlist_id[14] = ""; add_playlist(empty_playlist_id); } else if (strcmp(search_query, "rm playlist") == 0) { PRINT_HEADER("Remove Playlist"); remove_playlist(); } else if (strcmp(search_query, "rm") == 0) { PRINT_HEADER("Remove Movie"); removeMovie(movies, &movie_count); } else if (strcmp(search_query, "local") == 0) { search_locally = !search_locally ; } else if (strcmp(search_query, "add") == 0) { PRINT_HEADER("Add Movie to Playlist"); char lt[13]; strcpy(lt,res_last != NULL ? res_last->tconst : "\0"); addMovieToPlaylist(movies, movie_count, lt); } else if (strcmp(search_query, "list") == 0) { PRINT_HEADER("List Movies"); listMovies(movies, movie_count); } else if (strcmp(search_query, "rm last") == 0) { PRINT_HEADER("Remove last added"); if (strlen(file_path) == 0) continue; if (remove(file_path) == 0) { printf("File deleted successfully.\n"); } else { perror("Error deleting file"); } } else if (strcmp(search_query, "print") == 0) { printDataStruct(dvd); } else if (strcmp(search_query, "clear") == 0) { Websearch_st data_web_new = {}; data_web = data_web_new; data_web.title[0] = '\0'; barcode[0] = '\0'; file_path[0] = '\0'; res = NULL; res_last = NULL; } else if (search_locally) { search_query[12] = '\0'; dvd = findMovieByTconst(movies, movie_count, search_query); printDataStruct(dvd); } else if ((sl == 13 && strspn(search_query, "0123456789") == 13) || (sl == 12 && strspn(search_query, "0123456789") == 12) || strcmp(search_query, "search barcode") == 0) { Websearch_st data_web_new = { "", 0.0, 0.0, "" }; if (strcmp(search_query, "search barcode") == 0) { if (!(strlen(dvd->barcode) ==12 || strlen(dvd->barcode) ==13)) { perror("Not a valid barcode\n"); search_query[0] = '\0'; continue; } printf("Make use of barcode: %s\n", dvd->barcode); strcpy(search_query, dvd->barcode); } else { data_web = data_web_new; data_web.title[0] = '\0'; barcode[0] = '\0'; file_path[0] = '\0'; res = NULL; res_last = NULL; strcpy(barcode, search_query); barcode[13] = '\0'; DataStruct* res_d = findMovieByBarcode(movies, movie_count, barcode); if (res_d) { res = &res_d->result; res_last = &res_d->result; data_web = res_d->web_data; dvd = res_d; printDataStruct(dvd); continue; } } printf("Recognized barcode %s...\n", barcode); PRINT_HEADER("Search Barcode in web.."); data_web_new = readUpcitemdb(barcode); print_json_response(&data_web_new); PRINT_HEADER_SMALL("Search web done: "); printf("%s\n", data_web_new.title); if (strlen(data_web_new.title) > 0) { data_web = data_web_new; strcpy(search_query, data_web.title); break; } } else if (sl > 0) { break; } } //continue; // !!! <--- if (!is_imbd_data_loadad) { PRINT_HEADER("Source imbd files"); fflush(stdout); PRINT_HEADER_SMALL("source ratings"); ratings_count = load_ratings(&ratings); if (ratings_count < 0) { fprintf(stderr, "Failed to load ratings.\n"); return 1; } //for (int i = 0; i < 22; i++) printf("%d %s %lf\n", i, ratings[i].tconst, ratings[i].averageRating); exit(1); PRINT_HEADER_SMALL("source titles"); if (load_titles(&titles, &title_count, ratings, ratings_count) != 0) { fprintf(stderr, "Failed to load titles.\n"); return 1; } PRINT_HEADER_SMALL("source languages"); for (int i = 0; i < title_count; i++) { pthread_mutex_init(&titles[i].lock, NULL); } if (load_languages_and_regions(titles, title_count) != 0) { fprintf(stderr, "Failed to load titles.\n"); return 1; } for (int i = 0; i < title_count; i++) { pthread_mutex_destroy(&titles[i].lock); } /* for (int i = 0; i < 12; i++) { if (titles[i].ratingInfo == NULL) continue; if (titles[i].languageCount == 0) continue; printf("%d %s %s %lf\n", i, titles[i].tconst, titles[i].languages[0].title, titles[i].ratingInfo->averageRating); } */ is_imbd_data_loadad = 1; PRINT_HEADER_SMALL("Donne sourcing imbd files"); } PRINT_HEADER("Search query: "); printf("Searching for: %s\n\n", search_query); fflush(stdout); // Call search_and_select function res = search_and_select(search_query, titles, title_count); if (res != NULL) { //saveToFile(res, &data_web, search_query, barcode, file_path); DataStruct dvd_ = createDataStruct(res, &data_web, search_query, barcode); dvd = &dvd_; printDataStruct(dvd); writeStructToFile(dvd); } else { snprintf(file_path, sizeof(file_path), ""); } // If search_and_select produced results, append to database PRINT_HEADER_SMALL("Add to DB"); if (strlen(search_query) > 0) { printf("Appending result to database: %s\n", search_query); append_to_database(search_query); movie_count = loadLocalMovies(&movies, "local"); res_last = res; } else { res_last = NULL; printf("No results to append.\n"); } printf(RESET); } printf(RESET); free(titles); // Free allocated memory free(movies); return 0; }