- / and /book/:title

This commit is contained in:
Alex Ling 2020-02-12 17:52:33 +00:00
parent cc031c9aef
commit 9eedac280e
6 changed files with 118 additions and 17 deletions

9
public/css/mango.css Normal file
View File

@ -0,0 +1,9 @@
.uk-card-body {
padding: 20px;
}
.uk-card-media-top img {
max-height: 350px;
}
.acard:hover {
text-decoration: none;
}

View File

@ -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

View File

@ -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
View 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>

View File

@ -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
View 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>