From d3eadee95154634d2257fd64ae4eeea76eed9c2a Mon Sep 17 00:00:00 2001 From: Matthew Welch Date: Sat, 6 Jul 2019 23:00:00 -0700 Subject: [PATCH] Initial commit --- .gitignore | 2 + README.md | 1 + app.py | 98 ++++++++++++ nginx.conf | 8 + scripts/__pycache__/database.cpython-37.pyc | Bin 0 -> 4302 bytes scripts/__pycache__/func.cpython-37.pyc | Bin 0 -> 1329 bytes scripts/database.py | 160 ++++++++++++++++++++ scripts/func.py | 67 ++++++++ static/icon.png | Bin 0 -> 2999 bytes templates/base.html | 15 ++ templates/comicList.html | 5 + templates/comicView.html | 7 + templates/index.html | 1 + templates/publisherList.html | 3 + templates/publisherView.html | 27 ++++ templates/seriesList.html | 3 + templates/seriesView.html | 7 + test.py | 142 +++++++++++++++++ yourapplication.fcgi | 8 + 19 files changed, 554 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 app.py create mode 100644 nginx.conf create mode 100644 scripts/__pycache__/database.cpython-37.pyc create mode 100644 scripts/__pycache__/func.cpython-37.pyc create mode 100644 scripts/database.py create mode 100644 scripts/func.py create mode 100644 static/icon.png create mode 100644 templates/base.html create mode 100644 templates/comicList.html create mode 100644 templates/comicView.html create mode 100644 templates/index.html create mode 100644 templates/publisherList.html create mode 100644 templates/publisherView.html create mode 100644 templates/seriesList.html create mode 100644 templates/seriesView.html create mode 100644 test.py create mode 100644 yourapplication.fcgi diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bf6d7e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/.idea +/__pycache__ diff --git a/README.md b/README.md new file mode 100644 index 0000000..84a69bd --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +rpiWebApp diff --git a/app.py b/app.py new file mode 100644 index 0000000..40a11ec --- /dev/null +++ b/app.py @@ -0,0 +1,98 @@ +from flask import Flask +from flask import render_template +from flask import request +from flask import g +import threading +from urllib import parse +import scripts.func as func +from scripts import database + +app = Flask(__name__) + + +def get_comics(): + with app.app_context(): + func.get_comics() + + +def verify_paths(): + with app.app_context(): + database.verify_paths() + + +with app.app_context(): + database.initialize_db() + thread = threading.Thread(target=get_comics, args=()) + thread.daemon = True + thread.start() + thread2 = threading.Thread(target=verify_paths, args=()) + thread2.daemon = True + thread2.start() + + +@app.teardown_appcontext +def close_connection(exception): + db = getattr(g, '_database', None) + if db is not None: + db.close() + + +def update_comic_db(sender, **kw): + try: + database.add_comics(kw["meta"]) + except Exception as e: + print(e) + + +func.comic_loaded.connect(update_comic_db) + + +@app.route('/') +def hello_world(): + return render_template("index.html", title="Hello World") + + +@app.route("/movies") +def movies(): + return "No Movies" + + +@app.route("/music") +def music(): + return "No music" + + +@app.route("/games") +def games(): + return "No Games" + + +@app.route("/comics") +def comics(): + polling = request.args.get("polling") + + if polling: + try: + return render_template("publisherList.html", comics=database.get_publishers()) + except Exception as e: + print(e) + return "Sucks to be you" + try: + return render_template("publisherView.html", title="Comics", comics=database.get_publishers()) + except Exception as e: + print(e) + + +@app.route("/comics/") +def comics_publisher(publisher): + publisher = parse.unquote(publisher) + series = request.args.get("series") + series_year = request.args.get("seriesYear") + comic = request.args.get("comic") + if series: + return render_template("comicView.html", title="Comics", comics=database.db_get_comics_in_series(series, publisher, series_year)) + return render_template("seriesView.html", title="Comics", comics=database.db_get_series_by_publisher(publisher)) + + +if __name__ == '__main__': + app.run() diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..a9dd980 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,8 @@ +server_name rpi.narnian.us; +#location / { try_files $uri @rpiWebApp; } +location / { + include fastcgi_params; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param SCRIPT_NAME ""; + fastcgi_pass unix:/run/matt/rpiWebApp/fcgi.sock; +} diff --git a/scripts/__pycache__/database.cpython-37.pyc b/scripts/__pycache__/database.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c22418d0ef15f51ca311132026350fbb42655c58 GIT binary patch literal 4302 zcmb_f&2!tv6~_YLw?xab>%@-hZsZS%GaOCYW;&hJAE6~G;Y6lVlB#TuTn>nZC|Dps zFTh$-$&+(${sigRKcxRak9+OO_sn#rm*&025(Je_FD*I1+kLy(-M7EDzxVd}@^Vpw z-(P;X_xf*TP5TE{Wkm{F?`k=gOA z@B|8E(1drX5r$)@9dXwmobPUZakw8kJUo11MbWYI?r=M>$3w@DKy&sj4+h*ChKC1E zKXfA}Jme#nzH|E2^&^KLS+;Y?tjOwHp|i>QHcp5?0*?vL7Chkwydo_kj4&qljGi)`MmITIB4&_Z>SD z`R!V#_Po}v^9*zV>vY!ttHw)E`PU!+XWPJ9u)H=J9fme{N3bWerEQMRL>AW8V|~Ov z%)?6~OC(QL2w#SBvKQEZit;}V=emGxBFNXq&pY$U^7F`L#u!I8FF z^;)M+!QkCGZS2tIUWe9SHrkywU9*FsYlmxeqgYrQS<&%Yp;Ld^q5I9o@AvCfP)62Z zkGlick6Ta$xVug`ue<0NYZPYL#b#OUIH%DX#j)fdZsa-h4@Tp@=Z41)pR0y}kCQi= zo%&bx7JhT)SkRtQFzalgF6Y?_#(uP*{!`$ABhE)2I6hBRJ zH{D3`QtGt?bRd>pAH31>+;a!mQ!fy98dDk_mZZF#Sa56hi?sfkQIQ^Jne)Zhfmm(SEwq+IvA`KJ5*y5U`{NU)Ni8 z8l8=tC+k4!p0iGC&28EJ$@-tC>l|0G)2W!!Iu4;u6WQ2FyLleGlgFo`cZ>4l9!>+6 zk9ipIt41%yU7S-ljKb$IkYdnPQY0qfH$aovi;-j<9%*kM)-cefv$ zPxVNf=#1Rf-jMg?0(f(3Ovr@+I{o&n#Z)~q6JxZ^uub+?GOJ`x$-I&UC5uXylw4AB zS;?}J*OXjQ^170%O5RZNrjkEX@|KbxDfzLIx0Sr3U|1RdP+q z`$zXNzPw#J(4q$rhaNI>LM|Z%k+nxj#K|;2AlMS|5C4Xr^>?T@n(cb4gTX&YJA9QU z!KF%L2B}iX>Plb`fle4asx%22a4-upTvRE>h$@A^pgxfNRi!b1SE;1_DxFb&6(^Te zKkE|rhw&Df9Xm=!uhN8Q#B5RFCj?Y9PK~`kr1&fTtQ4|s!MMk11Ohi!_fTAeQW4g%3D2j|kQRHVR ziu?>kQA!1BQC`Flb3KWnxON4@lp@AZl#?D3Ly=P$ii|{1pA*I*eHQf?gqeB2~A;eURg^?R7B$D6nL z7$Nb(r<>`o&Y!B_7$ckTmvr_xSjL~zz1DWUMW4S~WI7cTyCqobY$b7o%pW-s_=V?H zjP6PxQ*g^my429XEO)}Omrf7j%wS>NJ+v#%4DxzDgEx&l;oG2H06EDFzJwNtlu32~ zfMR4Mr;jEC(76ZD%J>Mku>!v{(Pr^d#)mtA5#BtE=J`XlG23v_faI(*C-C&P@K0d6 zbY{RYs`HOfYjleVS%kub9SZpqY`x;)Wdv#7a|m6O!6sSJi;xJd621f4BsD;1ME;Uq zO`$MLg(lhn!Ww!t8qM!Aa5#A@Hk;=aWf10SX%kfbBh|Z&Z|d|}XGdjn63K3iWZ*mC zvL<%pIPX;}R-~WwupQDvNa@}|C*_a`8KgH~gQijznIpWIb2LKUZ+Q+%-J9}zYvgW9 z5)I`=U9vPUU{AbV%7jp6N%E9SFOWMUhfb|X?yz*G{NrK3#-8&O<9dh$vxN6meMvWs Od@lb>cy8s(`Qncy$ap3I literal 0 HcmV?d00001 diff --git a/scripts/__pycache__/func.cpython-37.pyc b/scripts/__pycache__/func.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..950d87fd304aae0d3d98a13a96e2ed93bce05232 GIT binary patch literal 1329 zcmb_c&2M8h5Vzm+`^Z3XYsma^zp&Pw|yg@0>U>FX@UREu6456VHcd=FM-MFB^?2g7xDcA3e(mLcf>7 z+vURH3n2XiFpfBmQGzMP<=Kgy#HH@~?8bx=(2>|neClH)+*gPOB3OppTVYz^KCSYA z)_6$kyh0niO1F58Zu2^CyhgOi-BZ-sx`iyLg>5~`5*aZSUC0*#6ZB{t3qAE9SI z4c&#aa2Mp|>wEWE;7x*V)(-=Isf^a`i&R?fmVe&N3YXbd#H@K;#xo62Ri@VU#$ z8)p#|Xjv=#B3RZ}Xae^!Dlqr1i2B(yF1NT3_U#qo!5arGXxUsLfEMZjukcf}z|Z&3 z(enrA=&kq0lOq7Ga-uMN!JHgKV>PFp$HS*uC_U^kV=lz?@FngGb92CRp9KGcR884YEWr3ZOBZDG30#e~gbGm;5lJIa~4 zxP1W0ZH1*-dXr=`4KqR#Vc2b1RBOjNnYQGb#aFi3>G!&w)6r4)$#Lhb|Kxicij?bX zX)Y`&Ls@c}$<%tef@%~z2bj(EOsx}*WIEzw<&^4rr<~El&5T-~~^`clX)e2RKzQxiKm1V{fE|s?4M8-l}JW-9(8r;2sUy=F%d#wNpCRfYD~JKjnuG4qasR$%`|HErKdx=}o}P9)f5W}5ciqZ+?8CCY@UtZ2vsipy&WwH!SRL1K P=+qq_S4r80yY2l2H@1F| literal 0 HcmV?d00001 diff --git a/scripts/database.py b/scripts/database.py new file mode 100644 index 0000000..73b2232 --- /dev/null +++ b/scripts/database.py @@ -0,0 +1,160 @@ +from flask import Flask +from flask import g +import sqlite3 +import os, time + +from comicapi.issuestring import IssueString + +DATABASE = "/var/lib/rpiWebApp/database.db" + + +def get_db(): + db = getattr(g, '_database', None) + if db is None: + db = g._database = sqlite3.connect(DATABASE) + return db + + +def initialize_db(): + get_db().execute("""CREATE TABLE IF NOT EXISTS "comics" ( + "path" TEXT UNIQUE, + "tagOrigin" TEXT, + "series" TEXT, + "issue" REAL, + "issueText" TEXT, + "title" TEXT, + "publisher" TEXT, + "month" INTEGER, + "year" INTEGER, + "day" INTEGER, + "seriesYear" INTEGER, + "issueCount" INTEGER, + "volume" TEXT, + "genre" TEXT, + "language" TEXT, + "comments" TEXT, + "volumeCount" INTEGER, + "criticalRating" TEXT, + "country" TEXT, + "alternateSeries" TEXT, + "alternateNumber" TEXT, + "alternateCount" INTEGER, + "imprint" TEXT, + "notes" TEXT, + "webLink" TEXT, + "format" TEXT, + "manga" TEXT, + "blackAndWhite" TEXT, + "pageCount" TEXT, + "maturityRating" TEXT, + "storyArc" TEXT, + "seriesGroup" TEXT, + "scanInfo" TEXT, + "characters" TEXT, + "teams" TEXT, + "locations" TEXT, + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE +)""") + get_db().execute("""CREATE TABLE IF NOT EXISTS "credits" ( + "id" INTEGER NOT NULL, + "role" TEXT, + "name" TEXT, + "primary" INTEGER NOT NULL +)""") + get_db().execute("CREATE INDEX IF NOT EXISTS path_index ON comics(path);") + get_db().commit() + + +def table_exists(table_name): + cursor = get_db().execute("SELECT name FROM sqlite_master WHERE type='table' AND name='{}'".format(table_name)) + get_db().commit() + if cursor.rowcount == 0: + return False + return True + + +def add_comics(meta): + data = [] + for info in meta: + issue = IssueString(info[1].issue).asFloat() + data.append((info[0], info[1].tagOrigin, info[1].series, (issue or -1), info[1].issue, info[1].title, info[1].publisher, + info[1].month, info[1].year, info[1].day, info[1].seriesYear, info[1].issueCount, info[1].volume, info[1].genre, + info[1].language, info[1].comments, info[1].volumeCount, info[1].criticalRating, info[1].country, + info[1].alternateSeries, info[1].alternateNumber, info[1].alternateCount, info[1].imprint, + info[1].notes, info[1].webLink, info[1].format, info[1].manga, info[1].blackAndWhite, + info[1].pageCount, info[1].maturityRating, info[1].storyArc, info[1].seriesGroup, info[1].scanInfo, + info[1].characters, info[1].teams, info[1].locations)) + get_db().executemany( + """INSERT into comics(path, tagOrigin, series, issue, issueText, title, publisher, + month, year, day, seriesYear, issueCount, volume, genre, language, comments, volumeCount, + criticalRating, country, alternateSeries, alternateNumber, alternateCount, imprint, + notes, webLink, format, manga, blackAndWhite, pageCount, maturityRating, storyArc, + seriesGroup, scanInfo, characters, teams, locations) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""", + data) + get_db().commit() + + +def db_get_all_comics(): + original_factory = get_db().row_factory + + def dict_factory(cursor, row): + d = {} + for idx, col in enumerate(cursor.description): + d[col[0]] = row[idx] + return d + get_db().row_factory = dict_factory + result = get_db().execute("SELECT series, issue, title FROM comics ORDER BY series, issue").fetchall() + get_db().commit() + get_db().row_factory = original_factory + return result + + +def db_get_series_by_publisher(publisher): + series = [] + rows = get_db().execute("SELECT DISTINCT series, seriesYear, publisher FROM comics WHERE publisher LIKE ? ORDER BY series, seriesYear", [publisher]).fetchall() + for row in rows: + series.append(row) + return series + + +def db_get_comics_in_series(series, publisher, series_year): + comics = [] + rows = get_db().execute("SELECT series, issue, title FROM comics WHERE series LIKE ? AND publisher LIKE ? AND seriesYear LIKE ? ORDER BY series, issue", [series, publisher, series_year]).fetchall() + get_db().commit() + for row in rows: + comics.append(row) + return comics + + +def get_publishers(): + publishers = [] + rows = get_db().execute("SELECT DISTINCT publisher FROM comics ORDER BY publisher").fetchall() + + for row in rows: + publishers.append(row[0]) + return publishers + + +def comic_path_in_db(path): + try: + result = get_db().execute("SELECT path FROM comics WHERE path LIKE ?", [path]) + get_db().commit() + + if result.fetchone(): + return True + except Exception as e: + print(path) + print(e) + return False + + +def verify_paths(): + while True: + paths = get_db().execute("SELECT path FROM comics").fetchall() + get_db().commit() + for path in paths: + if not os.path.exists(path[0]): + get_db().execute("DELETE FROM comics WHERE path LIKE ?", [path[0]]) + get_db().commit() + time.sleep(60*60*24*5) diff --git a/scripts/func.py b/scripts/func.py new file mode 100644 index 0000000..fe4fea1 --- /dev/null +++ b/scripts/func.py @@ -0,0 +1,67 @@ +from comicapi import comicarchive +from blinker import Namespace +import os, sys + +from scripts import database + +rpi_signals = Namespace() +comic_loaded = rpi_signals.signal("comic-loaded") + +# Directories + +COMICS_DIRECTORY = "/usb/storage/media/Comics/" +MOVIES_DIRECTORY = "/usb/storage/media/Videos/Movies/" +TV_SHOWS_DIRECTORY = "/usb/storage/media/Videos/TV/" +VIDEOS_DIRECTORY = "/usb/storage/media/Videos/Videos/" +GAMES_DIRECTORY = "/usb/storage/media/games/" +MUSIC_DIRECTORY = "/usb/storage/media/Music/" + +############# + + +def get_comics(): + meta = [] + i = 0 + for root, dirs, files in os.walk(COMICS_DIRECTORY): + for f in files: + if f.endswith(".cbr"): + path = os.path.join(root, f) + if not database.comic_path_in_db(path): + archive = comicarchive.ComicArchive(path, default_image_path="/usb/www/matthew/rpiWebApp/static/icon.png") + meta.append((path, archive.readCIX())) + i += 1 + if i > 20: + comic_loaded.send("anonymous", meta=meta.copy()) + meta.clear() + i = 0 + comic_loaded.send("anonymous", meta=meta) + + +def bytestring_path(path): + """Given a path, which is either a bytes or a unicode, returns a str + path (ensuring that we never deal with Unicode pathnames). + """ + # Pass through bytestrings. + if isinstance(path, bytes): + return path + + # Try to encode with default encodings, but fall back to UTF8. + try: + return path.encode(_fsencoding()) + except (UnicodeError, LookupError): + return path.encode('utf8') + + +def _fsencoding(): + """Get the system's filesystem encoding. On Windows, this is always + UTF-8 (not MBCS). + """ + encoding = sys.getfilesystemencoding() or sys.getdefaultencoding() + if encoding == 'mbcs': + # On Windows, a broken encoding known to Python as "MBCS" is + # used for the filesystem. However, we only use the Unicode API + # for Windows paths, so the encoding is actually immaterial so + # we can avoid dealing with this nastiness. We arbitrarily + # choose UTF-8. + encoding = 'utf8' + return encoding diff --git a/static/icon.png b/static/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6a5417d287a5f6d2cccd74868b5f395a0e1bd8a7 GIT binary patch literal 2999 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 + + + + {{ title }} + + {% block head %} + {% endblock %} + + +{% block content %} +

Hello World!

+{% endblock %} + + diff --git a/templates/comicList.html b/templates/comicList.html new file mode 100644 index 0000000..cd833fc --- /dev/null +++ b/templates/comicList.html @@ -0,0 +1,5 @@ +{% for comic in comics %} +
  • + {{ comic[0] }} {% if comic[1] > 0 %}{{ "#{0:g}".format(comic[1]) }}{% endif %} {% if comic[2] != None %}{{ comic[2] }} {% endif %} +
  • +{% endfor %} diff --git a/templates/comicView.html b/templates/comicView.html new file mode 100644 index 0000000..0840532 --- /dev/null +++ b/templates/comicView.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} + +{% block content %} +
      + {% include "comicList.html" %} +
    +{% endblock %} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..94d9808 --- /dev/null +++ b/templates/index.html @@ -0,0 +1 @@ +{% extends "base.html" %} diff --git a/templates/publisherList.html b/templates/publisherList.html new file mode 100644 index 0000000..f0e9b6d --- /dev/null +++ b/templates/publisherList.html @@ -0,0 +1,3 @@ +{% for publisher in comics %} +
  • {{ publisher }}
  • +{% endfor %} diff --git a/templates/publisherView.html b/templates/publisherView.html new file mode 100644 index 0000000..8599678 --- /dev/null +++ b/templates/publisherView.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} + +{% block content %} + + + + + + +
      + {% include "publisherList.html" %} +
    +{% endblock %} diff --git a/templates/seriesList.html b/templates/seriesList.html new file mode 100644 index 0000000..d95d7ef --- /dev/null +++ b/templates/seriesList.html @@ -0,0 +1,3 @@ +{% for comic in comics %} +
  • {{ comic[0] }} {{ comic[1] }}
  • +{% endfor %} diff --git a/templates/seriesView.html b/templates/seriesView.html new file mode 100644 index 0000000..31e5e1f --- /dev/null +++ b/templates/seriesView.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} + +{% block content %} +
      + {% include "seriesList.html" %} +
    +{% endblock %} diff --git a/test.py b/test.py new file mode 100644 index 0000000..03ba372 --- /dev/null +++ b/test.py @@ -0,0 +1,142 @@ +import threading +import time +import os +import sqlite3 +from comicapi import comicarchive +from comicapi.issuestring import IssueString +from urllib import parse + +os.environ["UNRAR_LIB_PATH"] = 'C:\\Program Files (x86)\\UnrarDLL\\UnRAR.dll' + +COMICS_DIRECTORY = "F:\\comics" + +print(b'\xE2\x80\x93'.decode("utf-8", "replace")) +#os._exit(0) + +def get_comics(): + meta = [] + i = 0 + for root, dirs, files in os.walk(COMICS_DIRECTORY): + for f in files: + if f.endswith(".cbr"): + path = os.path.join(root, f) + print(path) + if not og_comic_path_in_db(path): + archive = comicarchive.ComicArchive(path, default_image_path="C:\\Users\\Matthew\\Documents\\MyPrograms\\Websites\\rpi web interface\\rpiWebApp\\static\\icon.png") + meta.append((path, archive.readCIX())) + return meta + +''' +thread = threading.Thread(target=get_comics, args=()) +thread.daemon = True +print('start') +thread.start() +time.sleep(3)''' + + +DATABASE = "C:\\Users\\Matthew\\Documents\\MyPrograms\\Websites\\rpi web interface\\database.db" + +db = sqlite3.connect(DATABASE) + + +def get_db(): + global db + return db + + +def initialize_db(): + get_db().execute("""CREATE TABLE IF NOT EXISTS "comics" ( + "path" TEXT UNIQUE, + "tagOrigin" TEXT, + "series" TEXT, + "issue" REAL, + "issueText" TEXT, + "title" TEXT, + "publisher" TEXT, + "month" INTEGER, + "year" INTEGER, + "day" INTEGER, + "issueCount" INTEGER, + "volume" TEXT, + "genre" TEXT, + "language" TEXT, + "comments" TEXT, + "volumeCount" INTEGER, + "criticalRating" TEXT, + "country" TEXT, + "alternateSeries" TEXT, + "alternateNumber" TEXT, + "alternateCount" INTEGER, + "imprint" TEXT, + "notes" TEXT, + "webLink" TEXT, + "format" TEXT, + "manga" TEXT, + "blackAndWhite" TEXT, + "pageCount" TEXT, + "maturityRating" TEXT, + "storyArc" TEXT, + "seriesGroup" TEXT, + "scanInfo" TEXT, + "characters" TEXT, + "teams" TEXT, + "locations" TEXT, + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE +)""") + get_db().execute("""CREATE TABLE IF NOT EXISTS "credits" ( + "id" INTEGER NOT NULL, + "role" TEXT, + "name" TEXT, + "primary" INTEGER NOT NULL +)""") + get_db().execute("CREATE INDEX IF NOT EXISTS path_index ON comics(path);") + get_db().commit() + + +def add_comics(meta): + data = [] + for info in meta: + issue = IssueString(info[1].issue).asFloat() + data.append((info[0], info[1].tagOrigin, info[1].series, (issue or -1), info[1].issue, info[1].title, info[1].publisher, + info[1].month, info[1].year, info[1].day, info[1].issueCount, info[1].volume, info[1].genre, + info[1].language, info[1].comments, info[1].volumeCount, info[1].criticalRating, info[1].country, + info[1].alternateSeries, info[1].alternateNumber, info[1].alternateCount, info[1].imprint, + info[1].notes, info[1].webLink, info[1].format, info[1].manga, info[1].blackAndWhite, + info[1].pageCount, info[1].maturityRating, info[1].storyArc, info[1].seriesGroup, info[1].scanInfo, + info[1].characters, info[1].teams, info[1].locations)) + get_db().executemany( + """INSERT into comics(path, tagOrigin, series, issue, issueText, title, publisher, + month, year, day, issueCount, volume, genre, language, comments, volumeCount, + criticalRating, country, alternateSeries, alternateNumber, alternateCount, imprint, + notes, webLink, format, manga, blackAndWhite, pageCount, maturityRating, storyArc, + seriesGroup, scanInfo, characters, teams, locations) + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""", + data) + get_db().commit() + + +def og_comic_path_in_db(path): + result = get_db().execute("SELECT EXISTS(SELECT * FROM comics WHERE path=?) LIMIT 1;", (path,)) + if result.fetchone()[0] == 1: + return True + return False + + +def comic_path_in_db(path): + result = get_db().execute("SELECT path FROM comics WHERE path LIKE ?", [path.encode("utf8")]) + if result.fetchone(): + return True + return False + + +#initialize_db() +#add_comics(get_comics()) + + +#for row in get_db().execute('SELECT * FROM comics ORDER BY series'): +# print(row) + + +#test_path = "/usb/storage/media/Comics/Marvel/Marvel Super Hero Adventures - Spider-Man – Web Designers 2019/Marvel Super Hero Adventures - Spider-Man – Web Designers #001 (2019).cbr" + +#print(comic_path_in_db(test_path)) diff --git a/yourapplication.fcgi b/yourapplication.fcgi new file mode 100644 index 0000000..66ffa80 --- /dev/null +++ b/yourapplication.fcgi @@ -0,0 +1,8 @@ +#!/usr/bin/python3 +from flup.server.fcgi import WSGIServer +from app import app + + +if __name__ == '__main__': + app.debug = True + WSGIServer(app, bindAddress='/run/matt/rpiWebApp/fcgi.sock').run()