(import-macros {: map : reduce : filter} :lib.macro) (tset package :path (.. package.path ";./vendor/lpeglj/?.lua")) (local io (require :io)) (local math (require :math)) (local fennel (require :vendor.fennel)) (local html (require :vendor.html)) (local json (require :vendor.json)) (local array (require :lib.array)) (local str (require :lib.string)) (local ozchai (require :parser.ozchai)) (local ipuer (require :parser.ipuer)) (local artoftea (require :parser.artoftea)) (when _G.unpack (tset table :unpack _G.unpack)) (local db (luna.db.open "file:var/db.sqlite?_journal=WAL&_sync=NORMAL")) (local query-synonyms { "шэн" "шен" "шен" "шэн" "доска" "чабань" "чабань" "доска" "термос" "бутылка" "бутылка" "термос"}) (fn unescape [s] (assert (= (type s) :string) "s must be string") (pick-values 1 (-> s (string.gsub "<" "<") (string.gsub ">" ">") (string.gsub """ "\"") (string.gsub "&" "&")))) (fn random-products [limit] (assert (< 0 limit) "limit must be > 0") (luna.db.query* db "SELECT site, title, description, image, url, price, weight, price_per AS \"price-per\", year FROM products ORDER BY RANDOM() LIMIT ?" [limit])) (fn all-tags [] (map (fn [_ v] (. v 1)) (luna.db.query db "SELECT title FROM tags ORDER BY creation_time" []))) (fn query-products [page query tags] (local tags (or tags [])) (var where-conds []) (var where-vars []) (when (< 0 (# tags)) (each [_ tag (pairs tags)] (table.insert where-conds "product_tags.tag = ?") (table.insert where-vars tag))) (when (and query (< 0 (# query))) (table.insert where-conds "search.title MATCH ?") (table.insert where-vars (array.join (map (fn [_ q] (if (. query-synonyms q) (.. "(" q "* OR " (. query-synonyms q) "*)") (.. q "*"))) (str.split query)) " AND "))) (local where-sql (array.join where-conds "\nAND ")) (local total (luna.db.query db (string.format "SELECT count(*) FROM search LEFT JOIN product_tags ON product_tags.product = search.fid WHERE search.`table` = 'products' AND %s" where-sql) where-vars)) {:results (luna.db.query* db (string.format "SELECT highlight(search, 0, '', '') AS \"title\", products.site, products.description, products.image, products.url, products.price, products.weight, products.price_per AS \"price-per\", products.year, products.archived, products.creation_time AS \"creation-time\" FROM search INNER JOIN products ON search.fid = products.url LEFT JOIN product_tags ON product_tags.product = products.url WHERE search.`table` = 'products' AND %s ORDER BY rank LIMIT 48 OFFSET ?" where-sql) (array.concat where-vars [(* (- page 1) 48)])) :total (if (< 0 (# total)) (. total 1 1) 0)}) (fn site-name-template [name] (if (= name "ipuer") [:a {:class "site-icon" :href "https://ipuer.ru" :alt "Логотип Институт чай пуэр"} [:img {:src "/static/ipuer.jpg"}] "Институт чая пуэр"] (= name "artoftea") [:a {:class "site-icon" :href "https://artoftea.ru" :alt "Логотип Art of tea"} [:img {:src "/static/artoftea.png"}] "Art of tea"] (= name "ozchai") [:a {:class "site-icon" :href "https://ozchai.ru" :alt "Логотип #OZCHAI"} [:img {:src "/static/ozchai.ico"}] "Чайная #OZCHAI"] (= name "clubcha") [:a {:class "site-icon" :href "https://clubcha.ru" :alt "Логотип Железный Феникс"} [:img {:src "/static/clubcha.png"}] "Железный Феникс"] (= name "chaekshop") [:a {:class "site-icon" :href "https://chaekshop.ru" :alt "Логотип Интернет-магазин фермерского китайского чая «Чаёк»"} [:img {:src "/static/chaekshop.svg"}] "Интернет-магазин «Чаёк»"] "")) (fn item-template [product] [:div {:class "tile"} [:a {:href product.url :style "display: block;" :rel "nofollow"} [:img {:src product.image :title product.title :alt product.title} ""]] (site-name-template product.site) [:a {:href product.url :style "text-decoration: none;" :rel "nofollow"} [:NO-ESCAPE (.. "