mirror of
https://github.com/hkalexling/Mango.git
synced 2025-08-02 19:05:32 -04:00
- /
and /book/:title
This commit is contained in:
parent
cc031c9aef
commit
9eedac280e
9
public/css/mango.css
Normal file
9
public/css/mango.css
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
.uk-card-body {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.uk-card-media-top img {
|
||||||
|
max-height: 350px;
|
||||||
|
}
|
||||||
|
.acard:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
require "zip"
|
require "zip"
|
||||||
require "mime"
|
require "mime"
|
||||||
|
require "json"
|
||||||
|
|
||||||
class Image
|
class Image
|
||||||
property data : Bytes
|
property data : Bytes
|
||||||
@ -12,13 +13,21 @@ end
|
|||||||
|
|
||||||
class Entry
|
class Entry
|
||||||
property zip_path : String
|
property zip_path : String
|
||||||
|
property book_title : String
|
||||||
property title : String
|
property title : String
|
||||||
property size : String
|
property size : String
|
||||||
|
property pages : Int32
|
||||||
|
property cover_url : String
|
||||||
|
|
||||||
def initialize(path : String)
|
JSON.mapping zip_path: String, book_title: String, title: String, \
|
||||||
|
size: String, pages: Int32, cover_url: String
|
||||||
|
|
||||||
|
def initialize(path, @book_title)
|
||||||
@zip_path = path
|
@zip_path = path
|
||||||
@title = File.basename path, ".zip"
|
@title = File.basename path, ".zip"
|
||||||
@size = (File.size path).humanize_bytes
|
@size = (File.size path).humanize_bytes
|
||||||
|
@pages = Zip::File.new(path).entries.size
|
||||||
|
@cover_url = "/api/page/#{@book_title}/#{title}/0"
|
||||||
end
|
end
|
||||||
def read_page(page_num)
|
def read_page(page_num)
|
||||||
Zip::File.open @zip_path do |file|
|
Zip::File.open @zip_path do |file|
|
||||||
@ -40,32 +49,27 @@ class Entry
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
def get_cover()
|
|
||||||
read_page 0
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Title
|
class Title
|
||||||
property dir : String
|
JSON.mapping dir: String, entries: Array(Entry), title: String
|
||||||
property entries : Array(Entry)
|
|
||||||
property title : String
|
|
||||||
|
|
||||||
def initialize(dir : String)
|
def initialize(dir : String)
|
||||||
@dir = dir
|
@dir = dir
|
||||||
@title = File.basename dir
|
@title = File.basename dir
|
||||||
@entries = (Dir.entries dir)
|
@entries = (Dir.entries dir)
|
||||||
.select! { |path| (File.extname path) == ".zip" }
|
.select! { |path| (File.extname path) == ".zip" }
|
||||||
.map { |path| Entry.new File.join dir, path }
|
.map { |path| Entry.new File.join(dir, path), @title }
|
||||||
.sort { |a, b| a.title <=> b.title }
|
.sort { |a, b| a.title <=> b.title }
|
||||||
end
|
end
|
||||||
def get_cover()
|
def get_entry(name)
|
||||||
@entries[0].get_cover
|
@entries.find { |e| e.title == name }
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Library
|
class Library
|
||||||
property dir : String
|
JSON.mapping dir: String, titles: Array(Title)
|
||||||
property titles : Array(Title)
|
|
||||||
|
|
||||||
def initialize(dir : String)
|
def initialize(dir : String)
|
||||||
@dir = dir
|
@dir = dir
|
||||||
@ -77,4 +81,7 @@ class Library
|
|||||||
.map { |path| Title.new File.join dir, path }
|
.map { |path| Title.new File.join dir, path }
|
||||||
.select! { |title| !title.entries.empty? }
|
.select! { |title| !title.entries.empty? }
|
||||||
end
|
end
|
||||||
|
def get_title(name)
|
||||||
|
@titles.find { |t| t.title == name }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
58
src/mango.cr
58
src/mango.cr
@ -14,17 +14,22 @@ macro layout(name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
macro send_img(env, img)
|
macro send_img(env, img)
|
||||||
send_file env, image.data, image.mime
|
send_file {{env}}, {{img}}.data, {{img}}.mime
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
get "/" do |env|
|
get "/" do |env|
|
||||||
image = library.titles[0].get_cover
|
titles = library.titles
|
||||||
unless image
|
layout "index"
|
||||||
"Failed to load image"
|
end
|
||||||
|
|
||||||
|
get "/book/:title" do |env|
|
||||||
|
title = library.get_title env.params.url["title"]
|
||||||
|
if title.nil?
|
||||||
|
env.response.status_code = 404
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
send_img env, image
|
layout "title"
|
||||||
end
|
end
|
||||||
|
|
||||||
get "/login" do |env|
|
get "/login" do |env|
|
||||||
@ -45,6 +50,49 @@ post "/login" do |env|
|
|||||||
env.redirect "/"
|
env.redirect "/"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
get "/api/page/:title/:entry/:page" do |env|
|
||||||
|
begin
|
||||||
|
title = env.params.url["title"]
|
||||||
|
entry = env.params.url["entry"]
|
||||||
|
page = env.params.url["page"].to_i
|
||||||
|
|
||||||
|
t = library.get_title title
|
||||||
|
raise "Title `#{title}` not found" if t.nil?
|
||||||
|
e = t.get_entry entry
|
||||||
|
raise "Entry `#{entry}` of `#{title}` not found" if e.nil?
|
||||||
|
img = e.read_page page
|
||||||
|
raise "Failed to load page #{page} of `#{title}/#{entry}`" if img.nil?
|
||||||
|
|
||||||
|
send_img env, img
|
||||||
|
rescue e
|
||||||
|
STDERR.puts e
|
||||||
|
env.response.status_code = 500
|
||||||
|
e.message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/api/book/:title" do |env|
|
||||||
|
begin
|
||||||
|
title = env.params.url["title"]
|
||||||
|
|
||||||
|
t = library.get_title title
|
||||||
|
raise "Title `#{title}` not found" if t.nil?
|
||||||
|
|
||||||
|
env.response.content_type = "application/json"
|
||||||
|
t.to_json
|
||||||
|
rescue e
|
||||||
|
STDERR.puts e
|
||||||
|
env.response.status_code = 500
|
||||||
|
e.message
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
get "/api/book" do |env|
|
||||||
|
env.response.content_type = "application/json"
|
||||||
|
library.to_json
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
add_handler AuthHandler.new storage
|
add_handler AuthHandler.new storage
|
||||||
|
|
||||||
Kemal.config.port = config.port
|
Kemal.config.port = config.port
|
||||||
|
18
src/views/index.ecr
Normal file
18
src/views/index.ecr
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<div class="uk-child-width-1-4@m" uk-grid>
|
||||||
|
<%- titles.each do |t| -%>
|
||||||
|
<div>
|
||||||
|
<a class="acard" href="/book/<%= t.title %>">
|
||||||
|
<div class="uk-card uk-card-default">
|
||||||
|
<div class="uk-card-media-top">
|
||||||
|
<img src="<%= t.entries[0].cover_url %>" alt="">
|
||||||
|
</div>
|
||||||
|
<div class="uk-card-body">
|
||||||
|
<div class="uk-card-badge uk-label">Badge</div>
|
||||||
|
<h3 class="uk-card-title"><%= t.title %></h3>
|
||||||
|
<p><%= t.entries.size %> entries</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<%- end -%>
|
||||||
|
</div>
|
@ -8,6 +8,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/css/uikit.min.css" />
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/css/uikit.min.css" />
|
||||||
|
<link rel="stylesheet" href="/css/mango.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -15,8 +16,10 @@
|
|||||||
<p class="uk-align-right uk-margin-right">Hello !</p>
|
<p class="uk-align-right uk-margin-right">Hello !</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="uk-section uk-section-default uk-section-small">
|
<div class="uk-section uk-section-default uk-section-small">
|
||||||
|
<div class="uk-container uk-container-small">
|
||||||
<%= content %>
|
<%= content %>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/js/uikit.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/js/uikit.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/js/uikit-icons.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/uikit@3.3.1/dist/js/uikit-icons.min.js"></script>
|
||||||
|
16
src/views/title.ecr
Normal file
16
src/views/title.ecr
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<h2 class=uk-title><%= title.title %></h2>
|
||||||
|
<div class="uk-child-width-1-4@m" uk-grid>
|
||||||
|
<%- title.entries.each do |e| -%>
|
||||||
|
<div>
|
||||||
|
<div class="uk-card uk-card-default">
|
||||||
|
<div class="uk-card-media-top">
|
||||||
|
<img src="<%= e.cover_url %>" alt="">
|
||||||
|
</div>
|
||||||
|
<div class="uk-card-body">
|
||||||
|
<div class="uk-card-badge uk-label">Badge</div>
|
||||||
|
<h3 class="uk-card-title"><%= e.title %></h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<%- end -%>
|
||||||
|
</div>
|
Loading…
x
Reference in New Issue
Block a user