xrforge-v2/src/plugin/diskscan.lua

178 lines
6 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
print("ℹ️ serving " .. app.opts.plugin_diskscan_dir .. " from internal (executable)")
app.opts.plugin_diskscan_dir = '/zip/' .. util.stripPath(app.opts.plugin_diskscan_dir)
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)
-- 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
-- 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
experience.portal3D = true -- can be viewed as 3d portal
app.pub("scan_experience", nil, experience)
app.addExperience(experience,ino)
-- 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)
-- 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
}