From 89f5a68ee687c07402800e05b82a0b2025a48667 Mon Sep 17 00:00:00 2001 From: Wiktor Przybylski Date: Sun, 22 May 2022 00:57:16 +0200 Subject: [PATCH] HSWro retrofitting --- Dockerfile | 8 ++ Gemfile | 7 ++ Gemfile.lock | 66 ++++++++++++++ assets/clean.svg | 16 ++++ assets/dead.svg | 1 + assets/gift.svg | 9 ++ assets/glider.svg | 1 + assets/hswro.svg | 51 +++++++++++ assets/money.svg | 1 + assets/person.svg | 4 + assets/warning.svg | 32 +++++++ main.rb | 223 ++++++++++++++++++++++++++++++++++++++++++--- 12 files changed, 405 insertions(+), 14 deletions(-) create mode 100644 Dockerfile create mode 100644 assets/clean.svg create mode 100644 assets/dead.svg create mode 100644 assets/gift.svg create mode 100644 assets/glider.svg create mode 100755 assets/hswro.svg create mode 100644 assets/money.svg create mode 100644 assets/person.svg create mode 100644 assets/warning.svg diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0a35d2e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM ruby:latest +RUN mkdir /code +WORKDIR /code +ADD Gemfile /code/ +ADD . /code/ +RUN bundle install + +CMD bundle exec ruby main.rb diff --git a/Gemfile b/Gemfile index 111df68..c151347 100644 --- a/Gemfile +++ b/Gemfile @@ -8,3 +8,10 @@ gem 'color' gem 'excon' gem 'rmagick' gem 'json' +gem 'matrix' +gem 'thin' +gem 'puma' +gem 'reel' +gem 'http' +gem 'webrick' +gem 'rest-client' diff --git a/Gemfile.lock b/Gemfile.lock index 3d5400b..ebd9661 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -11,14 +11,47 @@ GEM specs: addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) + celluloid (0.18.0) + timers (~> 4) + celluloid-io (0.17.3) + celluloid (>= 0.17.2) + nio4r (>= 1.1) + timers (>= 4.1.1) chunky_png (1.3.11) color (1.8) css_parser (1.7.1) addressable + daemons (1.4.1) + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) + eventmachine (1.2.7) excon (0.73.0) + ffi (1.15.5) + ffi-compiler (1.0.1) + ffi (>= 1.0.0) + rake + http (5.0.1) + addressable (~> 2.3) + http-cookie (~> 1.0) + http-form_data (~> 2.2) + llhttp-ffi (~> 0.3.0) + http-accept (1.7.0) + http-cookie (1.0.4) + domain_name (~> 0.5) + http-form_data (2.3.0) + http_parser.rb (0.8.0) json (2.3.0) + llhttp-ffi (0.3.1) + ffi-compiler (~> 1.0) + rake (~> 13.0) + matrix (0.4.2) + mime-types (3.4.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2023.0218.1) mustermann (1.1.1) ruby2_keywords (~> 0.0.1) + netrc (0.11.0) + nio4r (2.5.8) pdf-core (0.7.0) prawn (2.2.2) pdf-core (~> 0.7.0) @@ -27,9 +60,23 @@ GEM css_parser (~> 1.6) prawn (>= 0.11.1, < 3) public_suffix (4.0.5) + puma (5.6.4) + nio4r (~> 2.0) rack (2.2.2) rack-protection (2.0.8.1) rack + rake (13.0.6) + reel (0.6.1) + celluloid (>= 0.15.1) + celluloid-io (>= 0.15.0) + http (>= 0.6.0.pre) + http_parser.rb (>= 0.6.0) + websocket-driver (>= 0.5.1) + rest-client (2.1.0) + http-accept (>= 1.7.0, < 2.0) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 4.0) + netrc (~> 0.8) rmagick (4.1.2) rqrcode (1.1.2) chunky_png (~> 1.0) @@ -41,8 +88,20 @@ GEM rack (~> 2.0) rack-protection (= 2.0.8.1) tilt (~> 2.0) + thin (1.8.1) + daemons (~> 1.0, >= 1.0.9) + eventmachine (~> 1.0, >= 1.0.4) + rack (>= 1, < 3) tilt (2.0.10) + timers (4.3.3) ttfunk (1.6.2.1) + unf (0.1.4) + unf_ext + unf_ext (0.0.8.1) + webrick (1.7.0) + websocket-driver (0.7.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) PLATFORMS ruby @@ -50,12 +109,19 @@ PLATFORMS DEPENDENCIES color excon + http json + matrix prawn prawn-qrcode! prawn-svg + puma + reel + rest-client rmagick sinatra + thin + webrick BUNDLED WITH 1.17.2 diff --git a/assets/clean.svg b/assets/clean.svg new file mode 100644 index 0000000..ad67235 --- /dev/null +++ b/assets/clean.svg @@ -0,0 +1,16 @@ + + + + + + clean + + + + + + \ No newline at end of file diff --git a/assets/dead.svg b/assets/dead.svg new file mode 100644 index 0000000..d5b858e --- /dev/null +++ b/assets/dead.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/gift.svg b/assets/gift.svg new file mode 100644 index 0000000..ad56649 --- /dev/null +++ b/assets/gift.svg @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/assets/glider.svg b/assets/glider.svg new file mode 100644 index 0000000..4e6c879 --- /dev/null +++ b/assets/glider.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/hswro.svg b/assets/hswro.svg new file mode 100755 index 0000000..4738929 --- /dev/null +++ b/assets/hswro.svg @@ -0,0 +1,51 @@ + +image/svg+xml + + + + + + diff --git a/assets/money.svg b/assets/money.svg new file mode 100644 index 0000000..6dcd317 --- /dev/null +++ b/assets/money.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/person.svg b/assets/person.svg new file mode 100644 index 0000000..4096627 --- /dev/null +++ b/assets/person.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/warning.svg b/assets/warning.svg new file mode 100644 index 0000000..ffc5471 --- /dev/null +++ b/assets/warning.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + diff --git a/main.rb b/main.rb index 65a7403..3e47f8a 100644 --- a/main.rb +++ b/main.rb @@ -7,6 +7,7 @@ require 'prawn/qrcode' require 'prawn-svg' require 'color' require 'excon' +require 'rest-client' require 'rmagick' require 'json' require 'zlib' @@ -28,7 +29,7 @@ include Prawn::Measurements # end # end -module Excon +module RestClient class Response def json!() # Convenience function @@ -37,11 +38,26 @@ module Excon end end -BACKEND_URL = 'https://inventory.waw.hackerspace.pl/api/1/' +BACKEND_URL = 'http://inventory.lokal.hswro.org/api/1/' CODE_PREFIX = "HTTP://I/" +WIKI_PREFIX = "http://wiki.hswro.org/" + +$templates = { + "prywatne" => { "name" => "Ten przedmiot jest własnością prywatną", "image" => "assets/person.svg"}, + "hsowe" => { "name" => "Ten przedmiot należy do HSWro", "image" => "assets/hswro.svg"}, + "hackuj" => { "name" => "Hackuj ile dusza zapragnie", "image" => "assets/glider.svg"}, + "zepsute" => { "name" => "Ten przedmiot jest zepsuty", "image" => "assets/dead.svg"}, + "eksploatuje" => { "name" => "Ten przedmiot eksploatuje materiały", "image" => "assets/money.svg"}, + "niehackuj" => { "name" => "Nie hackuj tego przedmiotu", "image" => "assets/glider.svg"}, + "blaty" => { "name" => "Utrzymuj czystość na blatach", "image" => "assets/clean.svg"}, + +# meme + "bhp" => { "name" => "Gdy ci smutno, gdy ci źle, użyj pasty BHP", "image" => "assets/hswro.svg"}, + +} def api(uri) - Excon.get(BACKEND_URL + uri + "/").json! + RestClient.get(BACKEND_URL + uri + ".json", :debug => true).json! end def render_identicode(data, id, extent) @@ -68,13 +84,55 @@ def render_identicode(data, id, extent) end DYMO_LABEL_SIZE = [89, 36] -ZEBRA_LABEL_SIZE = [100, 60] +ZEBRA_LABEL_SIZE = [50, 30] -def render_label(item_or_label_id, size: DYMO_LABEL_SIZE) - item = api("items/#{item_or_label_id}") +NORMAL_LABEL_MARGIN = [2, 2, 2, 6] +DRAWER_LABEL_MARGIN = [15, 2, 2, 3] + +IS_DRAWER = false + +def get_item_from_api(item) + return api("items/#{item}") +end + +def prepare_normal_label(item) + result = item + result['qr'] = CODE_PREFIX + item['short_id'] + return result +end + +def prepare_custom_hs(text) + return {"name" => text, "image" => "assets/hswro.svg"} +end + +def prepare_custom_item(name, owner) + return {"name" => name, "owner" => owner} +end + +def prepare_templated(template) + return $templates[template] +end + +def prepare_gifted(item) + donor = item['props']['donor'] ? item['props']['donor'] : "" + result = {"name" => "Przedmiot podarował: #{donor}", "image" => "assets/gift.svg"} + return result +end + +def prepare_wiki(item) + wikiaddr = item['props']['wiki'] ? WIKI_PREFIX + item['props']['wiki'] : "" + result = {"name" => "Wiki: #{item['props']['wiki']}", "qr" => wikiaddr} + return result +end + + + + +def render_label(item, size: ZEBRA_LABEL_SIZE) + labelmargin = IS_DRAWER ? DRAWER_LABEL_MARGIN : NORMAL_LABEL_MARGIN pdf = Prawn::Document.new(page_size: size.map { |x| mm2pt(x) }, - margin: [2, 2, 2, 6].map { |x| mm2pt(x) }) do + margin: labelmargin.map { |x| mm2pt(x) }) do font_families.update("DejaVuSans" => { normal: "fonts/DejaVuSans.ttf", italic: "fonts/DejaVuSans-Oblique.ttf", @@ -84,14 +142,27 @@ def render_label(item_or_label_id, size: DYMO_LABEL_SIZE) font 'DejaVuSans' + + # Width of right side +# qr_size = [bounds.height / 2, 27].max qr_size = [bounds.height / 2, 27].max + image_size = [bounds.height / 2, 27].max # Right side +# bounding_box([bounds.right - qr_size, bounds.top], width: qr_size) do bounding_box([bounds.right - qr_size, bounds.top], width: qr_size) do - print_qr_code CODE_PREFIX + item['short_id'], stroke: false, - foreground_color: '000000', - extent: bounds.width, margin: 0, pos: bounds.top_left + + + if item['qr'] + print_qr_code item['qr'], stroke: false, + foreground_color: '000000', + extent: bounds.width, margin: 0, pos: bounds.top_left + end + + if item['image'] + svg IO.read(item['image']), width: image_size, position: :right + end owner_text = item["owner"] ? "owner: #{item['owner']}\n\n" : "" metadata_text = owner_text # todo: creation date? @@ -113,15 +184,27 @@ end set :bind, '0.0.0.0' +##################################################### + get '/api/1/preview/:id.pdf' do headers["Content-Type"] = "application/pdf; charset=utf8" - render_label params["id"] + render_label(prepare_normal_label(get_item_from_api(params["id"]))) +end + +get '/api/1/preview/:id/gift.pdf' do + headers["Content-Type"] = "application/pdf; charset=utf8" + render_label(prepare_gifted(get_item_from_api(params["id"]))) +end + +get '/api/1/preview/:id/wiki.pdf' do + headers["Content-Type"] = "application/pdf; charset=utf8" + render_label(prepare_wiki(get_item_from_api(params["id"]))) end get '/api/1/preview/:id.png' do headers["Content-Type"] = "image/png" img = Magick::ImageList.new() - img = img.from_blob(render_label(params["id"])){ self.density = 200 }.first + img = img.from_blob(render_label(prepare_normal_label(get_item_from_api(params["id"])))){ self.density = 200 }.first img.format = 'png' img.background_color = 'white' img.to_blob @@ -129,7 +212,119 @@ end post '/api/1/print/:id' do temp = Tempfile.new('labelmaker') - temp.write(render_label(params["id"])) + temp.write(render_label(prepare_normal_label(get_item_from_api(params["id"])))) temp.close - system("lpr -P DYMO_LabelWriter_450 #{temp.path}") + system("lpr -P Zebra #{temp.path}") +end + +post '/api/1/print/:id/wiki' do + temp = Tempfile.new('labelmaker') + temp.write(render_label(prepare_wiki(get_item_from_api(params["id"])))) + temp.close + system("lpr -P Zebra #{temp.path}") +end + +get '/api/1/test/:id' do + get_item_from_api(params["id"]) + prepare_wiki(get_item_from_api(params["id"])) +end + +##################################################### + +get '/api/1/list/templates' do + headers["Content-Type"] = "application/json" + $templates.to_json +end + +get '/api/1/preview/templates/:id' do + headers["Content-Type"] = "application/pdf; charset=utf8" + render_label(prepare_templated(params['id'])) +end + +get '/api/1/templates/preview/:id' do + headers["Content-Type"] = "application/pdf; charset=utf8" + render_label(prepare_templated(params['id'])) +end + +get '/api/1/templates/print/:id' do + temp = Tempfile.new('labelmaker') + temp.write(render_label(prepare_templated(params['id']))) + temp.close + system("lpr -P Zebra #{temp.path}") +end + +get '/api/1/nametag/preview/:id' do + headers["Content-Type"] = "application/pdf; charset=utf8" + render_label(prepare_custom_hs(params['id'])) +end + +get '/api/1/nametag/print/:id' do + temp = Tempfile.new('labelmaker') + temp.write(render_label(prepare_custom_hs(params['id']))) + temp.close + system("lpr -P Zebra #{temp.path}") +end + +get '/api/1/customitem/preview/:owner/:name' do + headers["Content-Type"] = "application/pdf; charset=utf8" + render_label(prepare_custom_item(params["name"],params["owner"])) +end + +get '/api/1/customitem/print/:owner/:name' do + temp = Tempfile.new('labelmaker') + temp.write(render_label(prepare_custom_item(params["name"],params["owner"]))) + temp.close + system("lpr -P Zebra #{temp.path}") +end + +get '/api/1/gift/preview' do + test = {"name" => "Przedmiot podarował: lynx, małpa, franek", "image" => "assets/gift.svg"} + headers["Content-Type"] = "application/pdf; charset=utf8" + render_label(false,"img",test) +end + +get '/api/1/testgift/print' do + test = {"name" => "Przedmiot podarował: lynx, małpa, franek", "image" => "assets/gift.svg"} + temp = Tempfile.new('labelmaker') + temp.write(render_label(false, "img",test)) + temp.close + system("lpr -P Zebra #{temp.path}") +end + + + +# TESTY + +get '/api/1/dupatest/preview' do + test = {"owner" => "test", "short_id" => "test", "name" => "test", "image" => "assets/glider.svg"} + headers["Content-Type"] = "application/pdf; charset=utf8" + render_label(false,"img",test) +end + +get '/api/1/testgift/preview' do + test = {"name" => "Przedmiot podarował: lynx, małpa, franek", "image" => "assets/gift.svg"} + headers["Content-Type"] = "application/pdf; charset=utf8" + render_label(false,"img",test) +end + +get '/api/1/testgift/print' do + test = {"name" => "Przedmiot podarował: lynx, małpa, franek", "image" => "assets/gift.svg"} + temp = Tempfile.new('labelmaker') + temp.write(render_label(false, "img",test)) + temp.close + system("lpr -P Zebra #{temp.path}") +end + +get '/api/1/testshow' do + test = {"owner" => "grzegorz_brzęczyszczykiewicz", "short_id" => "wszczebrzeszyniechrzaszczbrzmiwtrzcinie", "name" => "pchnąć w tę łódź jeża lub ośm skrzyń fig"} + headers["Content-Type"] = "application/pdf; charset=utf8" + render_label(false, "qr", test) +end + +get '/api/1/testprint' do + test = {"owner" => "grzegorz_brzęczyszczykiewicz", "short_id" => "wszczebrzeszyniechrzaszczbrzmiwtrzcinie", "name" => "pchnąć w tę łódź jeża lub ośm skrzyń fig"} + temp = Tempfile.new('labelmaker') + temp.write(render_label(false,"qr",test)) + temp.close + system("lpr -P Zebra #{temp.path}") end