Compare commits
No commits in common. "e8e2ef20d55f69fef9604c13256f63b9d023efa1" and "89e68e3f8e15b9ceb545d15cdce9bcb0b6a5fde0" have entirely different histories.
e8e2ef20d5
...
89e68e3f8e
@ -4,18 +4,9 @@ from werkzeug.security import generate_password_hash
|
|||||||
#CONTENT_BASE_DIR = os.getenv("CONTENT_BASE_DIR", "/library") #docker
|
#CONTENT_BASE_DIR = os.getenv("CONTENT_BASE_DIR", "/library") #docker
|
||||||
#CONTENT_BASE_DIR = os.getenv("CONTENT_BASE_DIR", "/home/drudoo/ComicsTest/Comics") #linux
|
#CONTENT_BASE_DIR = os.getenv("CONTENT_BASE_DIR", "/home/drudoo/ComicsTest/Comics") #linux
|
||||||
CONTENT_BASE_DIR = os.getenv("CONTENT_BASE_DIR", "/Comics/ComicRack") #windows
|
CONTENT_BASE_DIR = os.getenv("CONTENT_BASE_DIR", "/Comics/ComicRack") #windows
|
||||||
#CONTENT_BASE_DIR = os.getenv("CONTENT_BASE_DIR", "testlibrary") #windows test library
|
|
||||||
|
|
||||||
THUMBNAIL_DIR = os.getenv("THUMBNAIL_DIR",'thumbnails')
|
|
||||||
|
|
||||||
WIN_DRIVE_LETTER = 'B'
|
WIN_DRIVE_LETTER = 'B'
|
||||||
DEFAULT_SEARCH_NUMBER = 10
|
DEFAULT_SEARCH_NUMBER = 10
|
||||||
|
|
||||||
DEBUG = True
|
|
||||||
|
|
||||||
def _print(arg):
|
|
||||||
if DEBUG:
|
|
||||||
print(arg)
|
|
||||||
|
|
||||||
TEENYOPDS_ADMIN_PASSWORD = os.getenv("TEENYOPDS_ADMIN_PASSWORD", None)
|
TEENYOPDS_ADMIN_PASSWORD = os.getenv("TEENYOPDS_ADMIN_PASSWORD", None)
|
||||||
users = {}
|
users = {}
|
||||||
|
113
main.py
113
main.py
@ -34,7 +34,7 @@ def startpage():
|
|||||||
#result = "Hello, World!"
|
#result = "Hello, World!"
|
||||||
conn = sqlite3.connect('app.db')
|
conn = sqlite3.connect('app.db')
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
cursor.execute("select * from comics LIMIT " + str(config.DEFAULT_SEARCH_NUMBER) + ";")
|
cursor.execute("select * from comics;")
|
||||||
result = cursor.fetchall()
|
result = cursor.fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
return render_template("start.html", result=result)
|
return render_template("start.html", result=result)
|
||||||
@ -61,72 +61,58 @@ def import2sql():
|
|||||||
try:
|
try:
|
||||||
comiccount = comiccount + 1
|
comiccount = comiccount + 1
|
||||||
s = zipfile.ZipFile(f)
|
s = zipfile.ZipFile(f)
|
||||||
filelist = zipfile.ZipFile.namelist(s)
|
filemodtime = os.path.getmtime(f)
|
||||||
if filelist[0] == 'ComicInfo.xml':
|
#s = gzip.GzipFile(f)
|
||||||
filemodtime = os.path.getmtime(f)
|
Bs_data = BeautifulSoup(s.open('ComicInfo.xml').read(), "xml")
|
||||||
#s = gzip.GzipFile(f)
|
#print(Bs_data.select('Series')[0].text, file=sys.stderr)
|
||||||
Bs_data = BeautifulSoup(s.open('ComicInfo.xml').read(), "xml")
|
#print(Bs_data.select('Title')[0].text, file=sys.stderr)
|
||||||
|
CVDB=re.findall('(?<=\[CVDB)(.*)(?=].)', Bs_data.select('Notes')[0].text)
|
||||||
|
#list.append('CVDB'+CVDB[0] + ': ' + Bs_data.select('Series')[0].text + "(" + Bs_data.select('Volume')[0].text + ") : " + Bs_data.select('Number')[0].text )
|
||||||
|
#print(list, file=sys.stdout)
|
||||||
|
|
||||||
|
ISSUE=Bs_data.select('Number')[0].text
|
||||||
|
SERIES=Bs_data.select('Series')[0].text
|
||||||
|
VOLUME=Bs_data.select('Volume')[0].text
|
||||||
|
PUBLISHER=Bs_data.select('Publisher')[0].text
|
||||||
|
try:
|
||||||
|
TITLE=Bs_data.select('Title')[0].text
|
||||||
|
except:
|
||||||
|
TITLE="" #sometimes title is blank.
|
||||||
|
PATH=f
|
||||||
|
UPDATED=filemodtime
|
||||||
|
#print(UPDATED,file=sys.stdout)
|
||||||
|
#sql="INSERT OR REPLACE INTO COMICS (CVDB,ISSUE,SERIES,VOLUME, PUBLISHER, TITLE, FILE,PATH,UPDATED) VALUES ("+CVDB[0]+",'"+ISSUE+"','"+SERIES+"','"+VOLUME+"','"+PUBLISHER+"','"+TITLE+"','"+file+"','" + f + "','" + UPDATED + "')"
|
||||||
|
#print(sql,file=sys.stdout)
|
||||||
|
#conn.execute(sql);
|
||||||
|
|
||||||
|
# CREATE TABLE IF MISSING
|
||||||
|
# create table COMICS (CVDB, ISSUE, SERIES,VOLUME,PUBLISHER,TITLE,FILE,PATH,UPDATED,PRIMARY KEY(CVDB))
|
||||||
|
try:
|
||||||
|
query = "SELECT UPDATED FROM COMICS WHERE CVDB = '" + str(CVDB[0]) + "';"
|
||||||
|
savedmodtime = conn.execute(query).fetchone()[0]
|
||||||
|
except:
|
||||||
|
savedmodtime = 0
|
||||||
|
#print(savedmodtime)
|
||||||
|
#print(float(savedmodtime))
|
||||||
|
#print(type(savedmodtime))
|
||||||
|
#print(type(filemodtime))
|
||||||
|
if savedmodtime < filemodtime:
|
||||||
|
#print(str(savedmodtime) + " is less than " + str(filemodtime))
|
||||||
|
|
||||||
#print(Bs_data.select('Series')[0].text, file=sys.stderr)
|
#print(str(CVDB[0]) + " - s: " + str(savedmodtime))
|
||||||
#print(Bs_data.select('Title')[0].text, file=sys.stderr)
|
#print(str(CVDB[0]) + " - f: " + str(filemodtime))
|
||||||
CVDB=re.findall('(?<=\[CVDB)(.*)(?=].)', Bs_data.select('Notes')[0].text)
|
conn.execute("INSERT OR REPLACE INTO COMICS (CVDB,ISSUE,SERIES,VOLUME, PUBLISHER, TITLE, FILE,PATH,UPDATED) VALUES (?,?,?,?,?,?,?,?,?)", (CVDB[0], ISSUE, SERIES, VOLUME, PUBLISHER, TITLE, file, f, UPDATED))
|
||||||
|
conn.commit()
|
||||||
|
#print("Adding: " + str(CVDB[0]))
|
||||||
#list.append('CVDB'+CVDB[0] + ': ' + Bs_data.select('Series')[0].text + "(" + Bs_data.select('Volume')[0].text + ") : " + Bs_data.select('Number')[0].text )
|
importcount = importcount + 1
|
||||||
#print(list, file=sys.stdout)
|
else:
|
||||||
|
# print("Skipping: " + str(CVDB[0]))
|
||||||
ISSUE=Bs_data.select('Number')[0].text
|
skippedcount = skippedcount + 1
|
||||||
SERIES=Bs_data.select('Series')[0].text
|
except:
|
||||||
VOLUME=Bs_data.select('Volume')[0].text
|
|
||||||
PUBLISHER=Bs_data.select('Publisher')[0].text
|
|
||||||
try:
|
|
||||||
TITLE=Bs_data.select('Title')[0].text
|
|
||||||
except:
|
|
||||||
TITLE="" #sometimes title is blank.
|
|
||||||
PATH=f
|
|
||||||
UPDATED=filemodtime
|
|
||||||
#print(UPDATED,file=sys.stdout)
|
|
||||||
#sql="INSERT OR REPLACE INTO COMICS (CVDB,ISSUE,SERIES,VOLUME, PUBLISHER, TITLE, FILE,PATH,UPDATED) VALUES ("+CVDB[0]+",'"+ISSUE+"','"+SERIES+"','"+VOLUME+"','"+PUBLISHER+"','"+TITLE+"','"+file+"','" + f + "','" + UPDATED + "')"
|
|
||||||
#print(sql,file=sys.stdout)
|
|
||||||
#conn.execute(sql);
|
|
||||||
|
|
||||||
# CREATE TABLE IF MISSING
|
|
||||||
# create table COMICS (CVDB, ISSUE, SERIES,VOLUME,PUBLISHER,TITLE,FILE,PATH,UPDATED,PRIMARY KEY(CVDB))
|
|
||||||
try:
|
|
||||||
query = "SELECT UPDATED FROM COMICS WHERE CVDB = '" + str(CVDB[0]) + "';"
|
|
||||||
savedmodtime = conn.execute(query).fetchone()[0]
|
|
||||||
except:
|
|
||||||
savedmodtime = 0
|
|
||||||
#print(savedmodtime)
|
|
||||||
#print(float(savedmodtime))
|
|
||||||
#print(type(savedmodtime))
|
|
||||||
#print(type(filemodtime))
|
|
||||||
if savedmodtime < filemodtime:
|
|
||||||
#print(str(savedmodtime) + " is less than " + str(filemodtime))
|
|
||||||
|
|
||||||
#print(str(CVDB[0]) + " - s: " + str(savedmodtime))
|
|
||||||
#print(str(CVDB[0]) + " - f: " + str(filemodtime))
|
|
||||||
|
|
||||||
cover = s.open(filelist[1]).read()
|
|
||||||
c = open(config.THUMBNAIL_DIR + "/" + str(CVDB[0]) + ".jpg", 'wb+')
|
|
||||||
c.write(cover)
|
|
||||||
c.close()
|
|
||||||
|
|
||||||
conn.execute("INSERT OR REPLACE INTO COMICS (CVDB,ISSUE,SERIES,VOLUME, PUBLISHER, TITLE, FILE,PATH,UPDATED) VALUES (?,?,?,?,?,?,?,?,?)", (CVDB[0], ISSUE, SERIES, VOLUME, PUBLISHER, TITLE, file, f, UPDATED))
|
|
||||||
conn.commit()
|
|
||||||
#print("Adding: " + str(CVDB[0]))
|
|
||||||
importcount = importcount + 1
|
|
||||||
else:
|
|
||||||
# print("Skipping: " + str(CVDB[0]))
|
|
||||||
skippedcount = skippedcount + 1
|
|
||||||
except Exception as e:
|
|
||||||
errorcount = errorcount + 1
|
errorcount = errorcount + 1
|
||||||
comics_with_errors.append(f)
|
comics_with_errors.append(f)
|
||||||
print(e)
|
|
||||||
#print(f,file=sys.stdout)
|
#print(f,file=sys.stdout)
|
||||||
print(comics_with_errors)
|
|
||||||
conn.close()
|
conn.close()
|
||||||
elapsed = timeit.default_timer() - start_time
|
elapsed = timeit.default_timer() - start_time
|
||||||
elapsed_time = "IMPORTED IN: " + str(round(elapsed,2)) + "s"
|
elapsed_time = "IMPORTED IN: " + str(round(elapsed,2)) + "s"
|
||||||
@ -139,10 +125,6 @@ def send_content(path):
|
|||||||
print('content')
|
print('content')
|
||||||
return send_from_directory(config.CONTENT_BASE_DIR, path)
|
return send_from_directory(config.CONTENT_BASE_DIR, path)
|
||||||
|
|
||||||
@app.route("/image/<path:path>")
|
|
||||||
def image(path):
|
|
||||||
return send_from_directory(config.THUMBNAIL_DIR,path)
|
|
||||||
|
|
||||||
@app.route("/catalog")
|
@app.route("/catalog")
|
||||||
@app.route("/catalog/")
|
@app.route("/catalog/")
|
||||||
@app.route("/catalog/<path:path>")
|
@app.route("/catalog/<path:path>")
|
||||||
@ -153,7 +135,6 @@ def catalog(path=""):
|
|||||||
#print(request.root_url)
|
#print(request.root_url)
|
||||||
c = fromdir(request.root_url, request.url, config.CONTENT_BASE_DIR, path)
|
c = fromdir(request.root_url, request.url, config.CONTENT_BASE_DIR, path)
|
||||||
elapsed = timeit.default_timer() - start_time
|
elapsed = timeit.default_timer() - start_time
|
||||||
print("-----------------------------------------------------------------------------------------------------------------------")
|
|
||||||
print("RENDERED IN: " + str(round(elapsed,2))+"s")
|
print("RENDERED IN: " + str(round(elapsed,2))+"s")
|
||||||
|
|
||||||
return c.render()
|
return c.render()
|
||||||
|
@ -125,97 +125,73 @@ def fromdir(root_url, url, content_base_path, content_relative_path):
|
|||||||
else:
|
else:
|
||||||
with open('test.json') as fi:
|
with open('test.json') as fi:
|
||||||
data=json.load(fi)
|
data=json.load(fi)
|
||||||
config._print("--> LOADED 2 FILE") # try and get this as low as possible.
|
print("--> LOADED 2 FILE") # try and get this as low as possible.
|
||||||
for e in data:
|
for e in data:
|
||||||
for key, value in e.items():
|
for key, value in e.items():
|
||||||
config._print(key)
|
#print(key)
|
||||||
searchArr.append(key)
|
searchArr.append(key)
|
||||||
for i in searchArr:
|
for i in searchArr:
|
||||||
config._print("i (in searchArr): " + i)
|
#print(i)
|
||||||
config._print("quote i: " + quote(f""+i))
|
|
||||||
if quote(f""+i) in c.url:
|
if quote(f""+i) in c.url:
|
||||||
conn = sqlite3.connect('app.db')
|
conn = sqlite3.connect('app.db')
|
||||||
|
#print(data)
|
||||||
for e in data:
|
for e in data:
|
||||||
config._print("e (in data): " + str(e))
|
|
||||||
for key, value in e.items():
|
for key, value in e.items():
|
||||||
config._print("key: " + key)
|
print(key)
|
||||||
if key == i:
|
if key == i:
|
||||||
config._print("key <" + str(key) + "> matches <" + str(i) + ">")
|
|
||||||
query="SELECT * FROM COMICS where "
|
query="SELECT * FROM COMICS where "
|
||||||
for h in value:
|
for i in value:
|
||||||
first=True
|
first=True
|
||||||
for j,k in h.items():
|
for j,k in i.items():
|
||||||
|
|
||||||
if j == 'SQL':
|
if j == 'SQL':
|
||||||
query = query + k
|
query = query + k
|
||||||
if k != '' and j != "SQL":
|
if k != '' and j != "SQL":
|
||||||
config._print(j)
|
print(j,k)
|
||||||
config._print(k)
|
if not first:
|
||||||
config._print(query)
|
|
||||||
if not first and j != 'limit':
|
|
||||||
query = query + "and "
|
query = query + "and "
|
||||||
config._print(query)
|
|
||||||
if type(k) == list:
|
if type(k) == list:
|
||||||
config._print(k)
|
print(k)
|
||||||
if j == "series" or j == "title":
|
if j == "series" or j == "title":
|
||||||
firstS = True
|
firstS = True
|
||||||
query = query + "("
|
query = query + "("
|
||||||
config._print(query)
|
|
||||||
for l in k:
|
for l in k:
|
||||||
if not firstS:
|
if not firstS:
|
||||||
query = query + "or "
|
query = query + "or "
|
||||||
config._print(query)
|
|
||||||
query = query + j + " like '%" + l + "%' "
|
query = query + j + " like '%" + l + "%' "
|
||||||
config._print(query)
|
|
||||||
if firstS:
|
if firstS:
|
||||||
firstS = False
|
firstS = False
|
||||||
query = query + ") "
|
query = query + ") "
|
||||||
config._print(query)
|
|
||||||
else:
|
else:
|
||||||
query = query + j + " in ("
|
query = query + j + " in ("
|
||||||
config._print(query)
|
|
||||||
firstL = True
|
firstL = True
|
||||||
for l in k:
|
for l in k:
|
||||||
if not firstL:
|
if not firstL:
|
||||||
query = query + ","
|
query = query + ","
|
||||||
config._print(query)
|
query = query + "'" + l + "'"
|
||||||
query = query + "'" + str(l) + "'"
|
|
||||||
config._print(query)
|
|
||||||
if firstL:
|
if firstL:
|
||||||
firstL = False
|
firstL = False
|
||||||
query = query + ") "
|
query = query + ") "
|
||||||
config._print(query)
|
|
||||||
|
|
||||||
elif j != 'limit':
|
|
||||||
query = query + j + " like '%" + str(k) + "%' "
|
|
||||||
config._print(query)
|
|
||||||
elif j == 'limit':
|
|
||||||
config.DEFAULT_SEARCH_NUMBER = k
|
|
||||||
else:
|
else:
|
||||||
print(">>>>>>>>>>>ERROR THIS SHOULD NOT HAPPEN<<<<<<<<<<<")
|
query = query + j + " like '%" + k + "%' "
|
||||||
if first:
|
if first:
|
||||||
first = False
|
first = False
|
||||||
|
query = query + " order by series asc, cast(issue as unsigned) asc "
|
||||||
query = query + " order by series asc, cast(issue as unsigned) asc "
|
if config.DEFAULT_SEARCH_NUMBER != 0:
|
||||||
if config.DEFAULT_SEARCH_NUMBER != 0:
|
query = query + "LIMIT " + str(config.DEFAULT_SEARCH_NUMBER) + ";"
|
||||||
query = query + "LIMIT " + str(config.DEFAULT_SEARCH_NUMBER) + ";"
|
else:
|
||||||
else:
|
query = query + ";"
|
||||||
query = query + ";"
|
print("----> " + query)
|
||||||
break
|
|
||||||
else:
|
|
||||||
config._print("key <" + str(key) + "> DOES NOT match <" + str(i) + ">")
|
|
||||||
|
|
||||||
config._print("----> " + query)
|
|
||||||
|
|
||||||
sql = query
|
sql = query
|
||||||
#sql="SELECT * from COMICS where SERIES like '%" + i+ "%' or Title like '%" + i+ "%';"
|
#sql="SELECT * from COMICS where SERIES like '%" + i+ "%' or Title like '%" + i+ "%';"
|
||||||
#config._print(sql)
|
#print(sql)
|
||||||
s = conn.execute(sql)
|
s = conn.execute(sql)
|
||||||
#list=[]
|
#list=[]
|
||||||
for r in s:
|
for r in s:
|
||||||
#config._print(r)
|
#print(r)
|
||||||
tUrl=f""+r[7].replace('\\','/').replace(config.WIN_DRIVE_LETTER + ':','').replace(config.CONTENT_BASE_DIR,"/content")
|
tUrl=f""+r[7].replace('\\','/').replace(config.WIN_DRIVE_LETTER + ':','').replace(config.CONTENT_BASE_DIR,"/content")
|
||||||
#config._print(tUrl)
|
print(tUrl)
|
||||||
tTitle=r[6]
|
tTitle=r[6]
|
||||||
link3 = Link(
|
link3 = Link(
|
||||||
#href=quote(f"/content/DC Comics/Earth Cities/Gotham City/Batgirl/Annual/(2012) Batgirl Annual/Batgirl Annual #001 - The Blood That Moves Us [December, 2012].cbz"),
|
#href=quote(f"/content/DC Comics/Earth Cities/Gotham City/Batgirl/Annual/(2012) Batgirl Annual/Batgirl Annual #001 - The Blood That Moves Us [December, 2012].cbz"),
|
||||||
@ -224,7 +200,7 @@ def fromdir(root_url, url, content_base_path, content_relative_path):
|
|||||||
rpath=path,
|
rpath=path,
|
||||||
type="application/x-cbz",
|
type="application/x-cbz",
|
||||||
)
|
)
|
||||||
#config._print(link3.href)
|
print(link3.href)
|
||||||
c.add_entry(
|
c.add_entry(
|
||||||
Entry(
|
Entry(
|
||||||
title=tTitle,
|
title=tTitle,
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import zipfile
|
import zipfile
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
|
|
||||||
from extras import get_size
|
from extras import get_size
|
||||||
import config
|
|
||||||
|
|
||||||
class Entry(object):
|
class Entry(object):
|
||||||
valid_keys = (
|
valid_keys = (
|
||||||
@ -64,8 +62,7 @@ class Entry(object):
|
|||||||
data=BeautifulSoup(s.open('ComicInfo.xml').read(), "xml")
|
data=BeautifulSoup(s.open('ComicInfo.xml').read(), "xml")
|
||||||
#self.cover=s.open('P00001.jpg').read()
|
#self.cover=s.open('P00001.jpg').read()
|
||||||
self.authors = data.select('Writer')[0].text.split(",")
|
self.authors = data.select('Writer')[0].text.split(",")
|
||||||
self.cover = "/image/" + re.findall('(?<=\[CVDB)(.*)(?=].)', data.select('Notes')[0].text)[0] + ".jpg"
|
print(self.authors)
|
||||||
|
|
||||||
#print(data)
|
#print(data)
|
||||||
#print(kwargs["links"][0])
|
#print(kwargs["links"][0])
|
||||||
#print(data.select('Series')[0].text)
|
#print(data.select('Series')[0].text)
|
||||||
|
@ -34,9 +34,6 @@
|
|||||||
</author>
|
</author>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if entry.updated %} <updated>{{ entry.updated }}</updated> {% endif %}
|
{% if entry.updated %} <updated>{{ entry.updated }}</updated> {% endif %}
|
||||||
<link rel="http://opds-spec.org/image"
|
|
||||||
href="{{ entry.cover }}"
|
|
||||||
type="image/jpg"/>
|
|
||||||
{% for link in entry.links %}
|
{% for link in entry.links %}
|
||||||
<link rel="{{ link.rel }}"
|
<link rel="{{ link.rel }}"
|
||||||
href="{{ link.href }}"
|
href="{{ link.href }}"
|
||||||
|
78
test.json
78
test.json
@ -1,12 +1,11 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
"Amazons": [
|
"SQL TEST": [
|
||||||
{
|
{
|
||||||
"SQL": "(series = 'Nubia & the Amazons' and issue in ('1','2','3','4','5','6')) or (series like 'Trial of the Amazons%' and issue in ('1','2')) or (series = 'Wonder Woman' and issue in ('785','786','787'))"
|
"SQL": "(series like '%Aqua%' or series like '%girl%') and issue in ('1','2','5','10') and title not like '%Annual%'"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},{
|
||||||
{
|
|
||||||
"Letter 44": [
|
"Letter 44": [
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "",
|
||||||
@ -16,9 +15,8 @@
|
|||||||
"issue": ""
|
"issue": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},{
|
||||||
{
|
"Man 2020,2019": [
|
||||||
"Man 2020 or 2019": [
|
|
||||||
{
|
{
|
||||||
"title": "Man",
|
"title": "Man",
|
||||||
"volume": [
|
"volume": [
|
||||||
@ -30,19 +28,17 @@
|
|||||||
"issue": ""
|
"issue": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},{
|
||||||
{
|
"DC (BAT)": [
|
||||||
"DC BAT": [
|
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "",
|
||||||
"volume": "",
|
"volume": "",
|
||||||
"publisher": "DC Comics",
|
"publisher": "DC Comics",
|
||||||
"series": "Bat",
|
"series": "%bat%",
|
||||||
"issue": ""
|
"issue": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},{
|
||||||
{
|
|
||||||
"Marvel": [
|
"Marvel": [
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "",
|
||||||
@ -52,78 +48,48 @@
|
|||||||
"issue": ""
|
"issue": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},{
|
||||||
{
|
|
||||||
"Girl": [
|
"Girl": [
|
||||||
{
|
{
|
||||||
"title": [
|
"title": ["girl","man","World"],
|
||||||
"girl",
|
|
||||||
"man",
|
|
||||||
"World"
|
|
||||||
],
|
|
||||||
"volume": "",
|
"volume": "",
|
||||||
"publisher": "",
|
"publisher": "",
|
||||||
"series": "girl",
|
"series": "girl",
|
||||||
"issue": ""
|
"issue": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},{
|
||||||
{
|
|
||||||
"number 1": [
|
"number 1": [
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "",
|
||||||
"volume": "",
|
"volume": "",
|
||||||
"publisher": "",
|
"publisher": "",
|
||||||
"series": "",
|
"series": "",
|
||||||
"issue": [
|
"issue": ["1"]
|
||||||
"1"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
|
,
|
||||||
{
|
{
|
||||||
"Aquaman": [
|
"Aquaman": [
|
||||||
{
|
{
|
||||||
"title": [
|
"title": ["Tyrant King", "The Deluge Act Three", "Warhead Part One"],
|
||||||
"Tyrant King",
|
|
||||||
"The Deluge Act Three",
|
|
||||||
"Warhead Part One",
|
|
||||||
"Black Mantra"
|
|
||||||
],
|
|
||||||
"volume": "",
|
"volume": "",
|
||||||
"publisher": "",
|
"publisher": "",
|
||||||
"series": "",
|
"series": "",
|
||||||
"issue": ""
|
"issue": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
|
,
|
||||||
{
|
{
|
||||||
"2020-2022 DC Comics": [
|
"Girl series": [
|
||||||
{
|
{
|
||||||
"title": "",
|
"title": "",
|
||||||
"volume": [
|
"volume": "",
|
||||||
"2020",
|
|
||||||
"2022"
|
|
||||||
],
|
|
||||||
"publisher": "DC Comics",
|
|
||||||
"series": [
|
|
||||||
"Batman",
|
|
||||||
"Detective Comics"
|
|
||||||
],
|
|
||||||
"issue": "",
|
|
||||||
"limit": 50
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"New Series 2023": [
|
|
||||||
{
|
|
||||||
"title": "",
|
|
||||||
"volume": "2023",
|
|
||||||
"publisher": "",
|
"publisher": "",
|
||||||
"series": "",
|
"series": "girl",
|
||||||
"issue": "1",
|
"issue": "2"
|
||||||
"limit": 30
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user