tvdb/tvdb.c

290 lines
5.6 KiB
C
Raw Normal View History

2015-03-08 00:16:18 +00:00
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sqlite3.h>
2015-03-09 20:48:47 +00:00
#define CACHE "/mod/var/tvdb"
#define SERIESDB CACHE "/series.db"
2015-03-08 00:16:18 +00:00
#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)); \
sqlite3_free(error); \
exit(0); \
} while (0)
2015-03-09 20:48:47 +00:00
struct series {
unsigned long id;
char *imdb;
char *name;
char *overview;
2015-10-12 14:46:17 +00:00
char *banner;
2015-03-09 20:48:47 +00:00
};
2015-03-08 00:16:18 +00:00
struct episode {
unsigned long id;
char *name;
char *overview;
unsigned long series;
unsigned long episode;
};
#define HANDLE(str, c, n) \
do { \
2015-03-09 20:48:47 +00:00
if (!memcmp(p, str, (n + 1))) \
2015-03-08 00:16:18 +00:00
{ \
*p = c; \
memmove(p + 1, p + (n + 1), l - (p - txt) - (n + 1)); \
l -= n; \
txt[l] = '\0'; \
} \
} while (0)
void
unescape(char *txt)
{
char *p = txt;
int l = strlen(txt);
while ((p = strchr(p, '&')))
{
HANDLE("&quot;", '"', 5);
HANDLE("&amp;", '&', 4);
p++;
}
2015-03-09 20:48:47 +00:00
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++;
}
2015-03-08 00:16:18 +00:00
if ((p = strpbrk(txt, "\n\r")))
*p = '\0';
}
int
main(int argc, char **argv)
{
2015-03-09 20:48:47 +00:00
char buf[0x1000], *p, *q;
struct series s;
2015-03-08 00:16:18 +00:00
struct episode e;
char *error;
sqlite3_stmt *stmt;
sqlite3 *db;
FILE *fp;
2015-03-09 20:48:47 +00:00
int epcnt = 0;
2015-03-08 00:16:18 +00:00
2015-03-09 20:48:47 +00:00
if (argc != 2)
2015-03-08 00:16:18 +00:00
{
2015-03-09 20:48:47 +00:00
printf("Syntax: %s <xml file>\n", argv[0]);
2015-03-08 00:16:18 +00:00
return 0;
}
if (!(fp = fopen(argv[1], "r")))
{
perror("open");
return 0;
}
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
2015-03-09 20:48:47 +00:00
if (sqlite3_open_v2(SERIESDB, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL)
2015-03-08 00:16:18 +00:00
!= SQLITE_OK)
{
2015-03-09 20:48:47 +00:00
printf("Failed to open series database: %s\n",
sqlite3_errmsg(db));
2015-03-08 00:16:18 +00:00
return 0;
}
EXEC("pragma journal_mode = off");
EXEC("pragma synchronous = off");
2015-03-09 20:48:47 +00:00
EXEC(
"create table if not exists series("
"[series_id] integer primary key, "
"[imdb_id] text, "
"[name] text, "
"[overview] text, "
2015-10-12 14:46:17 +00:00
"[banner] text, "
2015-03-09 20:48:47 +00:00
"[dat] text"
")"
);
if (sqlite3_prepare_v2(db,
"insert or replace into series "
2015-10-12 14:46:17 +00:00
"values(?,?,?,?,?,date('now'))",
2015-03-09 20:48:47 +00:00
-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, "</IMDB_ID>")))
*q = '\0';
continue;
}
if (!strncmp(p, "SeriesName>", 11))
{
s.name = strdup(p + 11);
if ((q = strstr(s.name, "</SeriesName>")))
*q = '\0';
unescape(s.name);
continue;
}
if (!strncmp(p, "Overview>", 9))
{
s.overview = strdup(p + 9);
if ((q = strstr(s.overview, "</Overview>")))
*q = '\0';
unescape(s.overview);
}
2015-10-12 14:46:17 +00:00
if (!strncmp(p, "banner>", 7))
{
s.banner = strdup(p + 7);
if ((q = strstr(s.banner, "</banner>")))
*q = '\0';
unescape(s.banner);
}
2015-03-09 20:48:47 +00:00
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);
2015-10-12 14:46:17 +00:00
sqlite3_bind_text(stmt, 5, s.banner, -1, NULL);
2015-03-09 20:48:47 +00:00
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);
2015-03-08 00:16:18 +00:00
EXEC(
2015-03-09 20:48:47 +00:00
"create table if not exists episode.episode("
2015-03-08 00:16:18 +00:00
"[episode_id] integer primary key, "
"[series] integer, "
"[episode] integer, "
"[name] text, "
"[overview] text"
")"
);
if (sqlite3_prepare_v2(db,
2015-03-09 20:48:47 +00:00
"insert or replace into episode.episode "
2015-03-08 00:16:18 +00:00
"values(?,?,?,?,?)",
-1, &stmt, NULL) != SQLITE_OK)
{
fprintf(stderr,
"Problem preparing statement %s", sqlite3_errmsg(db));
exit(1);
}
while (fgets(buf, sizeof(buf), fp))
{
p = buf;
while ((*p++) != '<')
;
if (!strncmp(p, "Episode>", 8))
{
/* New episode */
memset(&e, '\0', sizeof(e));
}
if (!strncmp(p, "id>", 3))
e.id = strtoul(p + 3, (char **)NULL, 10);
if (!strncmp(p, "Combined_episodenumber>", 23))
e.episode = strtoul(p + 23, (char **)NULL, 10);
if (!strncmp(p, "Combined_season>", 16))
e.series = strtoul(p + 16, (char **)NULL, 10);
if (!strncmp(p, "EpisodeName>", 12))
{
e.name = strdup(p + 12);
if ((q = strstr(e.name, "</EpisodeName>")))
*q = '\0';
unescape(e.name);
}
if (!strncmp(p, "Overview>", 9))
{
e.overview = strdup(p + 9);
if ((q = strstr(e.overview, "</Overview>")))
*q = '\0';
unescape(e.overview);
}
if (!strncmp(p, "/Episode>", 8))
{
/* End of episode */
2015-03-09 20:48:47 +00:00
if (e.id && e.name && e.overview)
2015-03-08 00:16:18 +00:00
{
2015-03-09 20:48:47 +00:00
epcnt++;
2015-03-08 00:16:18 +00:00
sqlite3_bind_int(stmt, 1, e.id);
sqlite3_bind_int(stmt, 2, e.series);
sqlite3_bind_int(stmt, 3, e.episode);
sqlite3_bind_text(stmt, 4, e.name, -1, NULL);
sqlite3_bind_text(stmt, 5, e.overview,
-1, NULL);
sqlite3_step(stmt);
sqlite3_reset(stmt);
sqlite3_clear_bindings(stmt);
}
if (e.name) free(e.name);
if (e.overview) free(e.overview);
2015-03-09 20:48:47 +00:00
memset(&e, '\0', sizeof(e));
2015-03-08 00:16:18 +00:00
}
}
fclose(fp);
sqlite3_finalize(stmt);
sqlite3_close(db);
2015-03-09 20:48:47 +00:00
/*printf("Episodes: %d\n", epcnt);*/
2015-03-08 00:16:18 +00:00
return 0;
}