diff --git a/TODO b/TODO index 3cc1d64..ef36ff5 100644 --- a/TODO +++ b/TODO @@ -23,7 +23,7 @@ while preserving the most-specific-match-first principle for precedence. top-down example: { station: oslo bass radio, - selector: { random{all songs}} + selector: { random{all songs}} # for random 10 in search() timeline: { program:morn {{ 5h-14h}, selector: morning songs}, program:midd {{14h-21h}, selector: midday songs}, diff --git a/web/config.lua b/web/config.lua index 338d4eb..cbf0959 100644 --- a/web/config.lua +++ b/web/config.lua @@ -4,9 +4,9 @@ default_station = "oslobass" -- file path for tracks -tracks_path = "/srv/mu" +tracks_path = "/tmp/mu" -- upload staging area. -- must be on same device as tracks_path, or error: "invalid cross-device link" -temp_dir = "/srv/tmp" +temp_dir = "/tmp" diff --git a/web/hangover.lua b/web/hangover.lua index b1e64ad..bc99806 100755 --- a/web/hangover.lua +++ b/web/hangover.lua @@ -14,6 +14,7 @@ local u = require "util" local io = require "io" local crypto = require "crypto" local meta = require "metadata" +local program= require "program" require "config" local user = "badface" -- XXX: basic auth/user db @@ -38,7 +39,7 @@ end -- Output: {fields=[id,title,artist], pages=3, result=[{id => 2, title => penis}, ...]} function get_db(web,...) if web.GET.id then - return json.encode{tracks:get(web.GET.id)} + return get_track(web, web.GET.id) end local query = web.GET.q or {} local limit = web.GET.maxresults or 25 @@ -66,11 +67,13 @@ function get_db(web,...) end function getfile(file) + t = {} t.user = user t.submitted = os.time() t.filename = file.name -- XXX: mayhap we shouldn't accept anything other than audio/? t.contenttype = string.gsub(string.gsub(file['content-type'], "audio",""), "/","") + t.extension = file.name:gmatch(".(%w+)$")() local dest,tname = u.open_temp_file(temp_dir.."/hangover_up@@@") local bytes = file.contents if not dest then @@ -82,7 +85,7 @@ function getfile(file) print("["..os.date("%c", t.submitted).. "] '"..t.filename.."' -> "..tname) print("'"..t.filename .. "'".." " .. os.difftime(os.time(), t.submitted).."s") t.md5 = crypto.digest("md5", bytes) - local destname = t.md5..t.contenttype -- krav's pathless filename + local destname = t.md5..t.extension-- krav's pathless filename t.path = tracks_path .. "/" .. destname local rc, err = os.rename(tname, t.path) if not rc then @@ -96,15 +99,14 @@ end -- Insert shit in database -- returns: trackid or error function post_db(web,...) - local id, file, t = web.POST.id, web.POST.file, {} + local id, file = web.POST.id, web.POST.file if file then -- someone is uploading a mix t, some = getfile(file) -- attempt id3 extraction / file metadata - tags, failure = gettags(t.path, t) + tags, failure = meta.gettags(t.path, t) if not tags then return failure end - print("'"..destname.. "'".." " .. os.difftime(os.time(), t.submitted).."s") -- add to database, tags and all id = tracks:add(tags) -- add to database, tags and all @@ -120,6 +122,13 @@ function post_db(web,...) return web:redirect("/#!database/edit/"..id) end +-- GET /db/:id: +function get_track(web,...) + local id = ... + return json.encode{tracks:get(id)} +end + + -- PUT /db/:id: -- Update function put_db(web,...) @@ -236,7 +245,7 @@ end -- GET /next/:station:?time=now -- returns the path to the next song to play. --- finds the current plan, specific program and in that +-- finds the current ostn, specific program and in that -- program selects the next song function get_next(web, ...) local station = ... or default_station @@ -294,8 +303,10 @@ hangover:dispatch_get(index, "/", "/post/(%d+)") -- the real red meat hangover:dispatch_get (get_db, "/db/?") +hangover:dispatch_get (get_track, "/db/(%d+)") hangover:dispatch_post (post_db,"/db/?") hangover:dispatch_put (put_db, "/db/(%d+)") +hangover:dispatch_post (put_db, "/db/(%d+)") hangover:dispatch_delete(del_db, "/db/(%d+)") hangover:dispatch_get (get_next, "/next/?", "/next/(%w+)") hangover:dispatch_get (get_end, "/end/?", "/end/(%w+)") diff --git a/web/js/hangover.js b/web/js/hangover.js index b8de1da..790350a 100644 --- a/web/js/hangover.js +++ b/web/js/hangover.js @@ -24,7 +24,7 @@ var sort_fields = function(fields) { if(f[default_field_sort[i]] == undefined) { f[default_field_sort[i]] = [fields[i]]; } else { - f[defualt_field_sort[i]].push(fields[i]); + f[default_field_sort[i]].push(fields[i]); } } else { // no default sort value @@ -53,6 +53,7 @@ $.Controller("search", { "click": function(el) { var query={q: $('#query', el.parent()).val()}; db.findAll(query, function(result) { + console.log(result[0]['result']); var r = result[0]; // what if (r['result'].length == undefined) { console.log("null result"); @@ -80,7 +81,7 @@ $.route.bind('change', function(ev, attr, how, newval, oldval) { switch(ev['target']['action']) { case "edit": db.findOne({id: ev['target']['id']}, function(result) { - var r = result[0]; // FIXME sort + var r = result[0]; // FIXME sort - extract keys $("#content").html($.View("tmpl/database_edit.ejs", {entry: r})); }); break; // edit diff --git a/web/lib/tokyo.lua b/web/lib/tokyo.lua index f97a8d6..55e16ce 100644 --- a/web/lib/tokyo.lua +++ b/web/lib/tokyo.lua @@ -7,10 +7,20 @@ local u = require "lib/util" module("tokyo", package.seeall) function tokyo:init(name) - local name = name or "db" local file = name .. ".tch" - local db = tokyocabinet.tdbnew() +-- fix this stupidity. if you spell the query type wrong, +-- you get no warnings, nothing. + -- the global database, get at it by passing nothing + if not db and not tokyo.op then + tokyo.db = tokyo_booter() + end + if not name then + return tokyo.db + end + + -- here if you just want a database + local db = tokyocabinet.tdbnew() if not db:open(file, db.OWRITER + db.OCREAT) then ecode = db:ecode() print("database open error: " .. db:errmsg(ecode)) @@ -28,44 +38,46 @@ function tokyo.put(db, pkey, cols) end end +-- create table mapping to magic constants +-- run only once plz +function tokyo_booter() + local db = tokyocabinet.tdbnew() + local q = tokyocabinet.tdbqrynew(db) + tokyo.op = { + -- string + equal = q.QCSTREQ, + inclusive = q.QCSTRINC, + begins = q.QCSTRBW, + ends = q.QCSTREW, + all = q.QCSTRAND, + one = q.QCSTROR, -- inclusive or + eqone = q.QCSTROREQ, -- equal or + regex = q.QCSTRRX, + -- numeric + eq = q.QCNUMEQ, + gt = q.QCNUMGT, + ge = q.QCNUMGE, + lt = q.QCNUMLT, + le = q.QCNUMLE, + tween = q.QCNUMBT, + numor = q.QCNUMOREQ, + -- fulltext + phrase = q.QCFTSPH, + alltokens = q.QCFTSAND, + onetoken = q.QCFTSOR, + compound = q.QCFTSEX, + -- flags + negate = q.QCNEGATE, + noindex = q.QCNOIDX, + } + tokyo.sort = { + lexic = q.QOSTRASC, + reverse = q.QOSTRDESC, + increasing= q.QONUMASC, + decreasing= q.QONUMDESC, + } + return db +end -db = tokyo:init() - --- fix this stupidity. if you spell the query type wrong, --- you get no warnings, nothing. -local q = tokyocabinet.tdbqrynew(db) -tokyo.op = { - -- string - equal = q.QCSTREQ, - inclusive = q.QCSTRINC, - begins = q.QCSTRBW, - ends = q.QCSTREW, - all = q.QCSTRAND, - one = q.QCSTROR, -- inclusive or - eqone = q.QCSTROREQ, -- equal or - regex = q.QCSTRRX, - -- numeric - eq = q.QCNUMEQ, - gt = q.QCNUMGT, - ge = q.QCNUMGE, - lt = q.QCNUMLT, - le = q.QCNUMLE, - tween = q.QCNUMBT, - numor = q.QCNUMOREQ, - -- fulltext - phrase = q.QCFTSPH, - alltokens = q.QCFTSAND, - onetoken = q.QCFTSOR, - compound = q.QCFTSEX, - -- flags - negate = q.QCNEGATE, - noindex = q.QCNOIDX, -} -tokyo.sort = { - lexic = q.QOSTRASC, - reverse = q.QOSTRDESC, - increasing= q.QONUMASC, - decreasing= q.QONUMDESC, -} return tokyo diff --git a/web/lib/tracks.lua b/web/lib/tracks.lua index 1edcb23..8dd7180 100644 --- a/web/lib/tracks.lua +++ b/web/lib/tracks.lua @@ -57,7 +57,7 @@ function tracks:ssearch(query, qop, order) for k,v in pairs(query) do q:addcond(k, qop, v) end - q:setorder(unpack(order)) + if order then q:setorder(unpack(order)) end local res = q:search() -- q:setlimit(limit, skip) -- we need the size so there is no use return res, #res @@ -137,7 +137,7 @@ function tracks:gsearch(q, qf, order) end end if #accu > 0 then - print("adding condition: " .. u.join(accu)) + print("search " .. f .. " for " .. u.join(accu)) q:addcond(f,db.op.onetoken,u.join(accu)) end table.insert(queries,q) @@ -188,9 +188,13 @@ function tracks.filter(result, fields, limit, skip) break end if(c > skip) then - local one = {} - for i,f in pairs(fields) do - one[f] = v[f] + if #fields == 0 then + one = v + else + local one = {} + for i,f in pairs(fields) do + one[f] = v[f] + end end res[k] = one end diff --git a/web/tmpl/tracks.ejs b/web/tmpl/tracks.ejs index 904779b..74794d0 100644 --- a/web/tmpl/tracks.ejs +++ b/web/tmpl/tracks.ejs @@ -1,28 +1,28 @@ - <% fields.forEach(function(f){ %> - - <% }); %> - - - - <% result.forEach(function(r){ %> - <% fields.forEach(function(f){ %> - + <% }); %> - - + + + + <% result.forEach(function(r){ %> + + <% fields.forEach(function(f){ %> + + <% }); %> + + <% }); %> -
<%= f %>
<%= r[f] %><%= f %>play
<%= r[f] %>play
- + - +