mirror of
https://github.com/hkalexling/Mango.git
synced 2026-05-01 00:00:55 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a17ca07d8 |
+1
-1
@@ -3,7 +3,7 @@ FROM crystallang/crystal:0.36.1-alpine AS builder
|
|||||||
WORKDIR /Mango
|
WORKDIR /Mango
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN apk add --no-cache yarn yaml sqlite-static libarchive-dev libarchive-static acl-static expat-static zstd-static lz4-static bzip2-static libjpeg-turbo-dev libpng-dev tiff-dev
|
RUN apk add --no-cache yarn yaml-static sqlite-static libarchive-dev libarchive-static acl-static expat-static zstd-static lz4-static bzip2-static libjpeg-turbo-dev libpng-dev tiff-dev
|
||||||
RUN make static || make static
|
RUN make static || make static
|
||||||
|
|
||||||
FROM library/alpine
|
FROM library/alpine
|
||||||
|
|||||||
@@ -46,18 +46,6 @@ class Entry
|
|||||||
file.close
|
file.close
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_slim_json : String
|
|
||||||
JSON.build do |json|
|
|
||||||
json.object do
|
|
||||||
{% for str in ["zip_path", "title", "size", "id"] %}
|
|
||||||
json.field {{str}}, @{{str.id}}
|
|
||||||
{% end %}
|
|
||||||
json.field "title_id", @book.id
|
|
||||||
json.field "pages" { json.number @pages }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_json(json : JSON::Builder)
|
def to_json(json : JSON::Builder)
|
||||||
json.object do
|
json.object do
|
||||||
{% for str in ["zip_path", "title", "size", "id"] %}
|
{% for str in ["zip_path", "title", "size", "id"] %}
|
||||||
|
|||||||
@@ -85,21 +85,6 @@ class Library
|
|||||||
titles + titles.flat_map &.deep_titles
|
titles + titles.flat_map &.deep_titles
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_slim_json : String
|
|
||||||
JSON.build do |json|
|
|
||||||
json.object do
|
|
||||||
json.field "dir", @dir
|
|
||||||
json.field "titles" do
|
|
||||||
json.array do
|
|
||||||
self.titles.each do |title|
|
|
||||||
json.raw title.to_slim_json
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_json(json : JSON::Builder)
|
def to_json(json : JSON::Builder)
|
||||||
json.object do
|
json.object do
|
||||||
json.field "dir", @dir
|
json.field "dir", @dir
|
||||||
|
|||||||
@@ -57,41 +57,6 @@ class Title
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_slim_json : String
|
|
||||||
JSON.build do |json|
|
|
||||||
json.object do
|
|
||||||
{% for str in ["dir", "title", "id"] %}
|
|
||||||
json.field {{str}}, @{{str.id}}
|
|
||||||
{% end %}
|
|
||||||
json.field "signature" { json.number @signature }
|
|
||||||
json.field "titles" do
|
|
||||||
json.array do
|
|
||||||
self.titles.each do |title|
|
|
||||||
json.raw title.to_slim_json
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
json.field "entries" do
|
|
||||||
json.array do
|
|
||||||
@entries.each do |entry|
|
|
||||||
json.raw entry.to_slim_json
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
json.field "parents" do
|
|
||||||
json.array do
|
|
||||||
self.parents.each do |title|
|
|
||||||
json.object do
|
|
||||||
json.field "title", title.title
|
|
||||||
json.field "id", title.id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_json(json : JSON::Builder)
|
def to_json(json : JSON::Builder)
|
||||||
json.object do
|
json.object do
|
||||||
{% for str in ["dir", "title", "id"] %}
|
{% for str in ["dir", "title", "id"] %}
|
||||||
|
|||||||
+2
-47
@@ -1,7 +1,6 @@
|
|||||||
require "../mangadex/*"
|
require "../mangadex/*"
|
||||||
require "../upload"
|
require "../upload"
|
||||||
require "koa"
|
require "koa"
|
||||||
require "digest"
|
|
||||||
|
|
||||||
struct APIRouter
|
struct APIRouter
|
||||||
@@api_json : String?
|
@@api_json : String?
|
||||||
@@ -76,14 +75,12 @@ struct APIRouter
|
|||||||
Koa.path "page", schema: Int32, desc: "The page number to return (starts from 1)"
|
Koa.path "page", schema: Int32, desc: "The page number to return (starts from 1)"
|
||||||
Koa.response 200, schema: Bytes, media_type: "image/*"
|
Koa.response 200, schema: Bytes, media_type: "image/*"
|
||||||
Koa.response 500, "Page not found or not readable"
|
Koa.response 500, "Page not found or not readable"
|
||||||
Koa.response 304, "Page not modified (only available when `If-None-Match` is set)"
|
|
||||||
Koa.tag "reader"
|
Koa.tag "reader"
|
||||||
get "/api/page/:tid/:eid/:page" do |env|
|
get "/api/page/:tid/:eid/:page" do |env|
|
||||||
begin
|
begin
|
||||||
tid = env.params.url["tid"]
|
tid = env.params.url["tid"]
|
||||||
eid = env.params.url["eid"]
|
eid = env.params.url["eid"]
|
||||||
page = env.params.url["page"].to_i
|
page = env.params.url["page"].to_i
|
||||||
prev_e_tag = env.request.headers["If-None-Match"]?
|
|
||||||
|
|
||||||
title = Library.default.get_title tid
|
title = Library.default.get_title tid
|
||||||
raise "Title ID `#{tid}` not found" if title.nil?
|
raise "Title ID `#{tid}` not found" if title.nil?
|
||||||
@@ -93,15 +90,7 @@ struct APIRouter
|
|||||||
raise "Failed to load page #{page} of " \
|
raise "Failed to load page #{page} of " \
|
||||||
"`#{title.title}/#{entry.title}`" if img.nil?
|
"`#{title.title}/#{entry.title}`" if img.nil?
|
||||||
|
|
||||||
e_tag = Digest::SHA1.hexdigest img.data
|
|
||||||
if prev_e_tag == e_tag
|
|
||||||
env.response.status_code = 304
|
|
||||||
""
|
|
||||||
else
|
|
||||||
env.response.headers["ETag"] = e_tag
|
|
||||||
env.response.headers["Cache-Control"] = "public, max-age=86400"
|
|
||||||
send_img env, img
|
send_img env, img
|
||||||
end
|
|
||||||
rescue e
|
rescue e
|
||||||
Logger.error e
|
Logger.error e
|
||||||
env.response.status_code = 500
|
env.response.status_code = 500
|
||||||
@@ -113,14 +102,12 @@ struct APIRouter
|
|||||||
Koa.path "tid", desc: "Title ID"
|
Koa.path "tid", desc: "Title ID"
|
||||||
Koa.path "eid", desc: "Entry ID"
|
Koa.path "eid", desc: "Entry ID"
|
||||||
Koa.response 200, schema: Bytes, media_type: "image/*"
|
Koa.response 200, schema: Bytes, media_type: "image/*"
|
||||||
Koa.response 304, "Page not modified (only available when `If-None-Match` is set)"
|
|
||||||
Koa.response 500, "Page not found or not readable"
|
Koa.response 500, "Page not found or not readable"
|
||||||
Koa.tag "library"
|
Koa.tag "library"
|
||||||
get "/api/cover/:tid/:eid" do |env|
|
get "/api/cover/:tid/:eid" do |env|
|
||||||
begin
|
begin
|
||||||
tid = env.params.url["tid"]
|
tid = env.params.url["tid"]
|
||||||
eid = env.params.url["eid"]
|
eid = env.params.url["eid"]
|
||||||
prev_e_tag = env.request.headers["If-None-Match"]?
|
|
||||||
|
|
||||||
title = Library.default.get_title tid
|
title = Library.default.get_title tid
|
||||||
raise "Title ID `#{tid}` not found" if title.nil?
|
raise "Title ID `#{tid}` not found" if title.nil?
|
||||||
@@ -131,14 +118,7 @@ struct APIRouter
|
|||||||
raise "Failed to get cover of `#{title.title}/#{entry.title}`" \
|
raise "Failed to get cover of `#{title.title}/#{entry.title}`" \
|
||||||
if img.nil?
|
if img.nil?
|
||||||
|
|
||||||
e_tag = Digest::SHA1.hexdigest img.data
|
|
||||||
if prev_e_tag == e_tag
|
|
||||||
env.response.status_code = 304
|
|
||||||
""
|
|
||||||
else
|
|
||||||
env.response.headers["ETag"] = e_tag
|
|
||||||
send_img env, img
|
send_img env, img
|
||||||
end
|
|
||||||
rescue e
|
rescue e
|
||||||
Logger.error e
|
Logger.error e
|
||||||
env.response.status_code = 500
|
env.response.status_code = 500
|
||||||
@@ -146,11 +126,8 @@ struct APIRouter
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Koa.describe "Returns the book with title `tid`", <<-MD
|
Koa.describe "Returns the book with title `tid`"
|
||||||
Supply the `tid` query parameter to strip away "display_name", "cover_url", and "mtime" from the returned object to speed up the loading time
|
|
||||||
MD
|
|
||||||
Koa.path "tid", desc: "Title ID"
|
Koa.path "tid", desc: "Title ID"
|
||||||
Koa.query "slim"
|
|
||||||
Koa.response 200, schema: "title"
|
Koa.response 200, schema: "title"
|
||||||
Koa.response 404, "Title not found"
|
Koa.response 404, "Title not found"
|
||||||
Koa.tag "library"
|
Koa.tag "library"
|
||||||
@@ -160,11 +137,7 @@ struct APIRouter
|
|||||||
title = Library.default.get_title tid
|
title = Library.default.get_title tid
|
||||||
raise "Title ID `#{tid}` not found" if title.nil?
|
raise "Title ID `#{tid}` not found" if title.nil?
|
||||||
|
|
||||||
if env.params.query["slim"]?
|
|
||||||
send_json env, title.to_slim_json
|
|
||||||
else
|
|
||||||
send_json env, title.to_json
|
send_json env, title.to_json
|
||||||
end
|
|
||||||
rescue e
|
rescue e
|
||||||
Logger.error e
|
Logger.error e
|
||||||
env.response.status_code = 404
|
env.response.status_code = 404
|
||||||
@@ -172,22 +145,15 @@ struct APIRouter
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Koa.describe "Returns the entire library with all titles and entries", <<-MD
|
Koa.describe "Returns the entire library with all titles and entries"
|
||||||
Supply the `tid` query parameter to strip away "display_name", "cover_url", and "mtime" from the returned object to speed up the loading time
|
|
||||||
MD
|
|
||||||
Koa.query "slim"
|
|
||||||
Koa.response 200, schema: {
|
Koa.response 200, schema: {
|
||||||
"dir" => String,
|
"dir" => String,
|
||||||
"titles" => ["title"],
|
"titles" => ["title"],
|
||||||
}
|
}
|
||||||
Koa.tag "library"
|
Koa.tag "library"
|
||||||
get "/api/library" do |env|
|
get "/api/library" do |env|
|
||||||
if env.params.query["slim"]?
|
|
||||||
send_json env, Library.default.to_slim_json
|
|
||||||
else
|
|
||||||
send_json env, Library.default.to_json
|
send_json env, Library.default.to_json
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
Koa.describe "Triggers a library scan"
|
Koa.describe "Triggers a library scan"
|
||||||
Koa.tags ["admin", "library"]
|
Koa.tags ["admin", "library"]
|
||||||
@@ -651,32 +617,21 @@ struct APIRouter
|
|||||||
"height" => Int32,
|
"height" => Int32,
|
||||||
}],
|
}],
|
||||||
}
|
}
|
||||||
Koa.response 304, "Not modified (only available when `If-None-Match` is set)"
|
|
||||||
get "/api/dimensions/:tid/:eid" do |env|
|
get "/api/dimensions/:tid/:eid" do |env|
|
||||||
begin
|
begin
|
||||||
tid = env.params.url["tid"]
|
tid = env.params.url["tid"]
|
||||||
eid = env.params.url["eid"]
|
eid = env.params.url["eid"]
|
||||||
prev_e_tag = env.request.headers["If-None-Match"]?
|
|
||||||
|
|
||||||
title = Library.default.get_title tid
|
title = Library.default.get_title tid
|
||||||
raise "Title ID `#{tid}` not found" if title.nil?
|
raise "Title ID `#{tid}` not found" if title.nil?
|
||||||
entry = title.get_entry eid
|
entry = title.get_entry eid
|
||||||
raise "Entry ID `#{eid}` of `#{title.title}` not found" if entry.nil?
|
raise "Entry ID `#{eid}` of `#{title.title}` not found" if entry.nil?
|
||||||
|
|
||||||
file_hash = Digest::SHA1.hexdigest (entry.zip_path + entry.mtime.to_s)
|
|
||||||
e_tag = "W/#{file_hash}"
|
|
||||||
if e_tag == prev_e_tag
|
|
||||||
env.response.status_code = 304
|
|
||||||
""
|
|
||||||
else
|
|
||||||
sizes = entry.page_dimensions
|
sizes = entry.page_dimensions
|
||||||
env.response.headers["ETag"] = e_tag
|
|
||||||
env.response.headers["Cache-Control"] = "public, max-age=86400"
|
|
||||||
send_json env, {
|
send_json env, {
|
||||||
"success" => true,
|
"success" => true,
|
||||||
"dimensions" => sizes,
|
"dimensions" => sizes,
|
||||||
}.to_json
|
}.to_json
|
||||||
end
|
|
||||||
rescue e
|
rescue e
|
||||||
Logger.error e
|
Logger.error e
|
||||||
send_json env, {
|
send_json env, {
|
||||||
|
|||||||
+1
-2
@@ -30,8 +30,7 @@ struct MainRouter
|
|||||||
else
|
else
|
||||||
redirect env, "/"
|
redirect env, "/"
|
||||||
end
|
end
|
||||||
rescue e
|
rescue
|
||||||
Logger.error e
|
|
||||||
redirect env, "/login"
|
redirect env, "/login"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user