diff --git a/Makefile b/Makefile index 7dfbf9f..aebbbe4 100644 --- a/Makefile +++ b/Makefile @@ -27,7 +27,7 @@ tvdb: tvdb.o install: tvdb strip tvdb - cp tvdb /mod/bin/tvdb + cp tvdb /mod/webif/lib/bin/tvdb clean: @-touch core diff --git a/tvdb.c b/tvdb.c index 881401a..21a6865 100644 --- a/tvdb.c +++ b/tvdb.c @@ -6,6 +6,9 @@ #include #include +#define CACHE "/mod/var/tvdb" +#define SERIESDB CACHE "/series.db" + #define EXEC(xx) if (sqlite3_exec(db, xx, NULL, NULL, &error) != SQLITE_OK) \ do { \ printf("Failed: %s - %s (%s)\n", xx, error, sqlite3_errmsg(db)); \ @@ -13,6 +16,13 @@ exit(0); \ } while (0) +struct series { + unsigned long id; + char *imdb; + char *name; + char *overview; +}; + struct episode { unsigned long id; char *name; @@ -23,7 +33,7 @@ struct episode { #define HANDLE(str, c, n) \ do { \ - if (!strncmp(p, str, (n + 1))) \ + if (!memcmp(p, str, (n + 1))) \ { \ *p = c; \ memmove(p + 1, p + (n + 1), l - (p - txt) - (n + 1)); \ @@ -38,32 +48,42 @@ unescape(char *txt) char *p = txt; int l = strlen(txt); - //printf("PRE: [%s]\n", txt); while ((p = strchr(p, '&'))) { HANDLE(""", '"', 5); HANDLE("&", '&', 4); p++; } + + p = txt; + while ((p = memchr(p, '\xe2', l - (p - txt)))) + { + HANDLE("\xe2\x80\x99", '\'', 2); + HANDLE("\xe2\x80\x93", '-', 2); + HANDLE("\xe2\x80\x9c", '"', 2); + HANDLE("\xe2\x80\x9d", '"', 2); + p++; + } + if ((p = strpbrk(txt, "\n\r"))) *p = '\0'; - //printf("PST: [%s]\n", txt); - //printf("\n"); } int main(int argc, char **argv) { - char buf[0x400], *p, *q; + char buf[0x1000], *p, *q; + struct series s; struct episode e; char *error; sqlite3_stmt *stmt; sqlite3 *db; FILE *fp; + int epcnt = 0; - if (argc != 3) + if (argc != 2) { - printf("Syntax: %s \n", argv[0]); + printf("Syntax: %s \n", argv[0]); return 0; } @@ -75,19 +95,107 @@ main(int argc, char **argv) sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); - if (sqlite3_open_v2(argv[2], &db, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | - SQLITE_OPEN_PRIVATECACHE, NULL) + if (sqlite3_open_v2(SERIESDB, &db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK) { - printf("Failed to open database: %s\n", sqlite3_errmsg(db)); + printf("Failed to open series database: %s\n", + sqlite3_errmsg(db)); return 0; } EXEC("pragma journal_mode = off"); EXEC("pragma synchronous = off"); + EXEC( - "create table if not exists episode(" + "create table if not exists series(" + "[series_id] integer primary key, " + "[imdb_id] text, " + "[name] text, " + "[overview] text, " + "[dat] text" + ")" + ); + + if (sqlite3_prepare_v2(db, + "insert or replace into series " + "values(?,?,?,?,date('now'))", + -1, &stmt, NULL) != SQLITE_OK) + { + fprintf(stderr, + "Problem preparing series statement %s", + sqlite3_errmsg(db)); + exit(1); + } + + while (fgets(buf, sizeof(buf), fp)) + { + p = buf; + while ((*p++) != '<') + ; + if (!strncmp(p, "Series>", 7)) + { + memset(&s, '\0', sizeof(s)); + continue; + } + + if (!strncmp(p, "id>", 3)) + { + s.id = strtoul(p + 3, (char **)NULL, 10); + continue; + } + if (!strncmp(p, "IMDB_ID>", 8)) + { + s.imdb = strdup(p + 8); + if ((q = strstr(s.imdb, ""))) + *q = '\0'; + continue; + } + if (!strncmp(p, "SeriesName>", 11)) + { + s.name = strdup(p + 11); + if ((q = strstr(s.name, ""))) + *q = '\0'; + unescape(s.name); + continue; + } + if (!strncmp(p, "Overview>", 9)) + { + s.overview = strdup(p + 9); + if ((q = strstr(s.overview, ""))) + *q = '\0'; + unescape(s.overview); + } + + if (!strncmp(p, "/Series>", 7)) + { + if (s.id && s.name && s.overview) + { + sqlite3_bind_int(stmt, 1, s.id); + sqlite3_bind_text(stmt, 2, + s.imdb ? s.imdb : "", -1, NULL); + sqlite3_bind_text(stmt, 3, s.name, -1, NULL); + sqlite3_bind_text(stmt, 4, s.overview, + -1, NULL); + sqlite3_step(stmt); + } + break; + } + } + sqlite3_finalize(stmt); + + if (!s.id) + { + printf("No series found.\n"); + return 0; + } + + /* Attach the Episode database for this series. */ + sprintf(buf, "attach '%s/%lu.db' as episode", CACHE, s.id); + EXEC(buf); + + EXEC( + "create table if not exists episode.episode(" "[episode_id] integer primary key, " "[series] integer, " "[episode] integer, " @@ -97,7 +205,7 @@ main(int argc, char **argv) ); if (sqlite3_prepare_v2(db, - "insert or replace into episode " + "insert or replace into episode.episode " "values(?,?,?,?,?)", -1, &stmt, NULL) != SQLITE_OK) { @@ -141,8 +249,9 @@ main(int argc, char **argv) if (!strncmp(p, "/Episode>", 8)) { /* End of episode */ - if (e.id) + if (e.id && e.name && e.overview) { + epcnt++; sqlite3_bind_int(stmt, 1, e.id); sqlite3_bind_int(stmt, 2, e.series); sqlite3_bind_int(stmt, 3, e.episode); @@ -155,6 +264,7 @@ main(int argc, char **argv) } if (e.name) free(e.name); if (e.overview) free(e.overview); + memset(&e, '\0', sizeof(e)); } } @@ -162,6 +272,8 @@ main(int argc, char **argv) sqlite3_finalize(stmt); sqlite3_close(db); + /*printf("Episodes: %d\n", epcnt);*/ + return 0; }