diff options
-rwxr-xr-x | generatewebpages.py | 184 | ||||
-rw-r--r-- | index.txt | 74 |
2 files changed, 258 insertions, 0 deletions
diff --git a/generatewebpages.py b/generatewebpages.py new file mode 100755 index 0000000..4ac2b2d --- /dev/null +++ b/generatewebpages.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 + +""" +generatewebpages.py is part of animedb. +The purpose of this program is to generate all our html pages. +Copyright (C) 2018 Daniel Jones daniel@danieljon.es + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" + +import argparse; +import sqlite3; +import os; +from os import fdopen, remove; +from shutil import copyfile; +from tempfile import mkstemp; +from shutil import move; + +class Anime: + """ + every anime from the database will get an instance of this class + """ + colors = { + "Plan to Watch": "gray", + "On-Hold": "orange", + "Watching": "blue", + "Completed": "green", + }; + + def __init__(self, animeobj): + self.dbpos = animeobj[0]; + self.animeid = animeobj[1]; + self.title = animeobj[2]; + self.episodes = animeobj[3]; + self.type = animeobj[4]; + self.watched = animeobj[5]; + self.score = animeobj[6]; + self.status = animeobj[7]; + self.notes = animeobj[8]; + self.output = ""; # our final html string + + def setstatuscolor(self, status): + try: + self.statuscolor = Anime.colors[status]; + except KeyError: + self.statuscolor = "black"; + +def dbconnect(dbname): + """ + connect to our database and return the object + """ + try: + dbcon = sqlite3.connect(dbname); + except: + e = sys.exc_info()[0]; + exit(e); + return dbcon; + +def dbclose(db): + """ + close database + """ + db.close(); + +def dbcollectanimedata(db): + """ + collect anime data from the database + """ + animelist = []; + c = db.cursor(); + for anime in c.execute("SELECT * FROM anime;"): + animelist.append(anime); + return animelist; + +def replacestringinfile(file_path, string, substr): + """ + replaces contents in a file + """ + fh, abs_path = mkstemp(); + with fdopen(fh, "w") as new_file: + with open(file_path) as old_file: + for line in old_file: + new_file.write(str(line.replace(string, substr).encode("utf-8"))); + remove(file_path); + move(abs_path, file_path); + +def replacestring(string, substr, replacement): + return string.replace(substr, replacement); + +def insertanimedata(anime): + tmp = animetemplate; + tmp = replacestring(tmp, "{ANIME_UNDERLINED_TITLE}", anime.title.replace(" ", "_")); + tmp = replacestring(tmp, "{ANIME_ID}", str(anime.animeid)); + tmp = replacestring(tmp, "{ANIME_TITLE}", anime.title); + tmp = replacestring(tmp, "{TOTAL_EPISODES}", str(anime.episodes)); + tmp = replacestring(tmp, "{EPISODES_WATCHED}", str(anime.watched)); + tmp = replacestring(tmp, "{WATCH_STATUS_COLOR}", anime.statuscolor); + tmp = replacestring(tmp, "{WATCH_STATUS}", anime.status); + tmp = replacestring(tmp, "{RATING}", str(anime.score)); + tmp = replacestring(tmp, "{NOTES}", str(anime.notes)); + anime.output = tmp; + +# this template is used for every anime we display +animetemplate = ( + "<div class=\"box\">" + "<div class=\"anime\">" + "<div id=\"{ANIME_UNDERLINED_TITLE}\">" + "<img width=40% height=40% src=\"covers/{ANIME_ID}.jpg\" alt=\"{ANIME_TITLE} cover\">" + "<div class=\"viewing\">" + "{ANIME_TITLE} <br>" + "{TOTAL_EPISODES} episodes ({EPISODES_WATCHED} watched) <br>" + "status: <font color=\"{WATCH_STATUS_COLOR}\">{WATCH_STATUS}</font> <br>" + "rating: {RATING}/10 <br>" + "notes: {NOTES}<br>" + "</div>" + "</div>" + "</div>" + "</div>"); + +if __name__ == "__main__": + """ + parse arguments + connect to database + generate anime strings from template and database + close database + """ + + parser = argparse.ArgumentParser(); + parser.add_argument("-d", "--database", type=str, action="store", dest="dbfile", + default="userdb.db", required=False, + help="sqlite3 database file containing anime information"); + parser.add_argument("-o", "--output", type=str, action="store", dest="outdir", + default="output", required=False, + help="directory to output generated pages"); + args = parser.parse_args(); + + # if our database (file) doesn't exist, exit + if not os.path.isfile(args.dbfile): + exit("file doesn't exist {}".format(args.dbfile)); + + db = dbconnect(args.dbfile); + + # collect anime from database + animelist = dbcollectanimedata(db); + + # create an instance of Anime for each anime + formattedanimelist = []; + for anime in animelist: + formattedanimelist.append(Anime(anime)); + + # set the status color for each anime + for anime in formattedanimelist: + anime.setstatuscolor(anime.status); + + # insert anime data for each Anime instance + for anime in formattedanimelist: + insertanimedata(anime); + + # copy index.txt to output/index.html + copyfile("index.txt", "output/index.html"); + + # generate string containing all anime output strings + output = []; + for anime in formattedanimelist: + output.append(anime.output); + + # place output into index.html + replacestringinfile("output/index.html", "{CONTENT}", " ".join(output)); + + dbclose(db); + + diff --git a/index.txt b/index.txt new file mode 100644 index 0000000..3fd02d7 --- /dev/null +++ b/index.txt @@ -0,0 +1,74 @@ +<!DOCTYPE html> +<html lang="en"> +<head> +<meta content="text/html;charset=utf-8" http-equiv="Content-Type"> +<meta name="keywords" content="anime manga"> +<meta name="description" content="Anime tracking and rating for daniel_j"> +<meta name="author" content="Daniel Jones"> +<meta name="viewport" content="width=device-width, initial-scale=1.0"> +<meta http-equiv="Cache-control" content="public"> +<link rel="icon" type="image/png" href="https://danieljon.es/favicon.png"> +<title>Anime</title> +<style> +body +{ + margin-right: 5%; + margin-left: 5%; + background: #ffe6ff url(tile.png) repeat center center fixed; +} + +.middle{text-align: center;} + +.anime +{ + font-size: 80%; + padding: 20px; + overflow: hidden; +} + +.anime img +{ + margin-right: 15px; + float: left; +} + +.box +{ + margin: 5px; + float: left; + overflow: hidden; +} + +.content +{ + position: absolute; + background-color: #fafafa; + border-radius: 25px; + border: 2px; + box-shadow: 0px 1px 10px 0px rgba(0, 0, 0, 0.25); + width: 90%; + margin-top: 2%; + margin-bottom: 2%; + margin-left: auto; + margin-right: auto; +} +</style> +</head> +<body> +<div class="content"> +<div class="middle"> +<h2>Static anime progress</h2> +filter: <br> +<a href="/finished.html"><font color=green>finished</font></a> +<a href="/watching.html"><font color=red>watching</font></a> +<a href="/onhold.html"><font color=orange>on hold</font></a> <br> +<a href="/highestfirst.html">highest score first</a> +<a href="/lowestfirst.html">lowest score first</a> +</div> + +{CONTENT} + +</div> + +</body> +</html> |