xrforge-v2/src/plugin/diskscan.lua

202 lines
6.7 KiB
Lua
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}