202 lines
6.7 KiB
Lua
202 lines
6.7 KiB
Lua
local dir = require "opendirectory"
|
||
|
||
app.on('init', function()
|
||
print("scanning experiences (this make take a while..)")
|
||
app.opts.plugin_diskscan_dirname = app.opts.plugin_diskscan_dir:gsub("^[.]?[/]?","")
|
||
-- swap between internal / external version of diskscan_dir
|
||
if app.opts.plugin_diskscan_dir:match("^/zip/") then
|
||
if util.fileExist(app.opts.plugin_diskscan_dir) then
|
||
print("ℹ️ serving " .. app.opts.plugin_diskscan_dir .. " from local disk")
|
||
app.opts.plugin_diskscan_dir = app.opts.plugin_diskscan_dir:gsub("^/zip/","")
|
||
app.set('app.opts', app.opts)
|
||
end
|
||
else
|
||
if not util.fileExist(app.opts.plugin_diskscan_dir) then
|
||
if app.opts.plugin_diskscan_dirname == 'myverse' and util.cmdExist("unzip") then
|
||
print("ℹ️ unzipping example content to folder 'myverse'")
|
||
os.execute("unzip " .. argv[-1] .. ' "myverse/*"')
|
||
else
|
||
print("ℹ️ serving " .. app.opts.plugin_diskscan_dir .. " from internal (executable)")
|
||
app.opts.plugin_diskscan_dir = '/zip/' .. util.stripPath(app.opts.plugin_diskscan_dir)
|
||
end
|
||
app.set('app.opts', app.opts)
|
||
end
|
||
end
|
||
app.plugin.diskscan.scan(app.opts.plugin_diskscan_dir)
|
||
end)
|
||
|
||
-- this registers the plugin UI /funcs
|
||
return {
|
||
name = "Files",
|
||
tab = "<img src='img/drive.svg' class='icon invert'/> Files",
|
||
info = '',
|
||
opts = {
|
||
{
|
||
key='app.opts.plugin_diskscan_dir',
|
||
title='Directory',
|
||
info="Directory to scan for experiences (use '.' for current) ",
|
||
default="./myverse",
|
||
values=''
|
||
}
|
||
},
|
||
shouldHideFile = function(name)
|
||
return name == ".." -- parent
|
||
or name == "util" -- repository
|
||
or name:match("^%.[a-zA-Z0-9_-]") -- hidden
|
||
or name == "src" -- repository
|
||
or name == "result" -- repository
|
||
end,
|
||
|
||
scan = function(scandir)
|
||
local me = app.plugin.diskscan
|
||
local seen = {symlinks={}}
|
||
-- ensure rootdir as experience
|
||
app.addExperience({
|
||
path = scandir,
|
||
url = "/" .. util.stripPath(scandir),
|
||
name = scandir:gsub(".*/",""),
|
||
thumbnail = "",
|
||
title = util.dehyphenate( scandir:gsub(".*/","") ),
|
||
file = { ino = scandir },
|
||
id = scandir
|
||
},scandir)
|
||
me.scanDir(scandir, nil, seen )
|
||
-- deal with (circular) symlinks
|
||
foreach( seen.symlinks, function(ino,experience)
|
||
if not me.shouldHideFile(experience.name) then
|
||
local refItem = seen[experience.id_target]
|
||
if refItem then
|
||
print("ℹ️ ".. experience.path )
|
||
print("✅ └─ plugin/diskscan: detected symlink..creating portal")
|
||
experience.file = refItem.file
|
||
experience.portal = refItem
|
||
app.pub("scan_experience" .. (experience.dir and '' or '_file') , nil, experience)
|
||
app.addExperience(experience,ino)
|
||
end
|
||
end
|
||
end)
|
||
-- cleanup file handles
|
||
foreach( app.cache.items, function(k,v)
|
||
-- remove file attributes (which are closed already)
|
||
if v.file then
|
||
v.file.stat = nil
|
||
v.file.attr = nil
|
||
v.file.state = nil
|
||
end
|
||
end)
|
||
-- make sure to attach children-array to parents
|
||
me.addChildren()
|
||
|
||
-- sort & apply dirs to plugin options
|
||
table.sort( app.cache.dirs)
|
||
foreach( app.plugin, function(k,plugin)
|
||
foreach( plugin.opts, function(k,opt)
|
||
if opt.type == 'dir' then
|
||
opt.values = app.cache.dirs
|
||
end
|
||
end)
|
||
end)
|
||
end,
|
||
|
||
scanDir = function(scandir,parent,seen)
|
||
local me = app.plugin.diskscan
|
||
parent = parent or app.cache.items[scandir]
|
||
app.cache.dirs[ scandir ] = util.stripPath(scandir)
|
||
|
||
-- scan dirs
|
||
local scanFile = function(path,stat,state,name,kind,ino,off,attr,fullpath)
|
||
|
||
local experience = {
|
||
path = fullpath,
|
||
url = "/" .. util.stripPath(fullpath),
|
||
name = name,
|
||
title = util.dehyphenate( name ),
|
||
sidecarfile = {},
|
||
thumbnail = '',
|
||
tag = {},
|
||
id = ino,
|
||
file = {stat=stat,state=state,kind=kind,ino=ino,off=off,attr=attr,fullpath=fullpath,name=name,path=path}
|
||
}
|
||
experience.parent = parent
|
||
|
||
if (kind == unix.DT_LNK) then
|
||
experience.symlink = true
|
||
local stat, err = unix.stat(fullpath)
|
||
if stat then
|
||
experience.id_target = stat:ino() -- stat follows symlink by default
|
||
local realpath = unix.realpath(fullpath)
|
||
state,err = unix.opendir(realpath)
|
||
if not err then
|
||
experience.symlink = true
|
||
experience.dir = true
|
||
state:close()
|
||
end
|
||
seen.symlinks[ ino ] = experience
|
||
end
|
||
end
|
||
|
||
--local already_seen = seen[ino] and seen[ino].parent.file.ino == experience.parent.file.ino and true or false -- process once
|
||
--if already_seen and not experience.symlink then return end
|
||
|
||
me.checkSideCarThumbnail(experience)
|
||
|
||
-- found directory
|
||
if not me.shouldHideFile(name) and
|
||
( (kind == unix.DT_DIR and kind ~= unix.DT_LNK) or experience.dir )
|
||
then
|
||
print("✅ ".. fullpath )
|
||
experience.dir = true
|
||
app.pub("scan_experience", nil, experience)
|
||
app.addExperience(experience,ino)
|
||
-- scan children
|
||
me.scanDir(fullpath,experience,seen,symlinks)
|
||
end
|
||
|
||
---- found file
|
||
if not me.shouldHideFile(name) and
|
||
( (kind ~= unix.DT_DIR and kind ~= unix.DT_LNK) or not experience.dir )
|
||
then
|
||
trace("ℹ️ ".. fullpath)
|
||
experience.tag.file = true
|
||
app.pub("scan_experience_file", nil, experience)
|
||
local size = attr:size()
|
||
end
|
||
|
||
-- remember file/parent relationship
|
||
seen[ino] = experience
|
||
|
||
end
|
||
|
||
local dref, derr;
|
||
dref, derr = dir.foreach( scandir, scanFile )
|
||
if not derr then dref:close() end
|
||
|
||
end,
|
||
|
||
addChildren = function()
|
||
-- .children is a convenient
|
||
foreach( app.cache.items, function(k,exp)
|
||
exp.children = exp.children or {}
|
||
if exp.parent then
|
||
exp.parent.children = exp.parent.children or {}
|
||
table.insert(exp.parent.children, exp.id)
|
||
end
|
||
end)
|
||
end,
|
||
|
||
checkSideCarThumbnail = function(experience)
|
||
local fullpath = experience.path
|
||
local name = experience.name
|
||
-- check for directory thumbnail sidecarfile
|
||
local thumbExt = {"png","jpg","webp"}
|
||
foreach( thumbExt, function(k,ext)
|
||
local files = { fullpath .. '.' .. ext, fullpath .. '/' .. name .. '.' .. ext }
|
||
foreach( files, function(kk,thumbnailFile)
|
||
if util.fileExist( thumbnailFile ) then
|
||
experience.thumbnail = "/" .. util.stripPath(thumbnailFile)
|
||
print("✅ └─ plugin/diskscan: detected .".. ext:lower() .. " thumbnail file: " .. thumbnailFile)
|
||
end
|
||
end)
|
||
end)
|
||
end
|
||
}
|