feat: add weekly curriculum cover image upload and display
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
type Request = { action: 'list' } | { action: 'content'; path: string } | { action: 'search'; query: string }
|
||||
|
||||
export function remoteModuleFilesScript(root: string, request: Request): string {
|
||||
const input = Buffer.from(JSON.stringify({ root, ...request })).toString('base64')
|
||||
return `python3 - '${input}' <<'PY'
|
||||
import base64, json, os, stat, sys
|
||||
args = json.loads(base64.b64decode(sys.argv[1]))
|
||||
root = os.path.realpath(args['root'])
|
||||
skip = {'.git', 'build', 'install', 'log', 'node_modules', 'docker'}
|
||||
extensions = {'.c', '.cc', '.cpp', '.cxx', '.h', '.hpp', '.hh', '.py', '.xml', '.urdf', '.xacro', '.yaml', '.yml', '.json', '.txt', '.md', '.cmake', '.launch', '.sh', '.bash', '.toml', '.ini', '.cfg', '.rviz'}
|
||||
placeholder = 'Binary or large file preview is not available.'
|
||||
def content(relative):
|
||||
if os.path.isabs(relative) or '..' in relative.split('/'):
|
||||
raise ValueError('Invalid module path')
|
||||
path = os.path.realpath(os.path.join(root, relative))
|
||||
if os.path.commonpath([root, path]) != root:
|
||||
raise ValueError('Invalid module path')
|
||||
info = os.stat(path)
|
||||
if not stat.S_ISREG(info.st_mode):
|
||||
raise ValueError('Not a regular file')
|
||||
if os.path.splitext(path)[1].lower() not in extensions or info.st_size > 1048576:
|
||||
return placeholder
|
||||
with open(path, 'rb') as fp:
|
||||
data = fp.read(1048577)
|
||||
if len(data) > 1048576 or b'\\x00' in data:
|
||||
return placeholder
|
||||
return data.decode('utf-8', errors='replace')
|
||||
def entries():
|
||||
def fail(error):
|
||||
raise error
|
||||
for current, dirs, files in os.walk(root, onerror=fail, followlinks=False):
|
||||
depth = len(os.path.relpath(current, root).split('/')) if current != root else 0
|
||||
dirs[:] = sorted(d for d in dirs if d not in skip and not os.path.islink(os.path.join(current, d)))
|
||||
if depth >= 10:
|
||||
dirs[:] = []
|
||||
continue
|
||||
for name in dirs:
|
||||
yield 'D', os.path.relpath(os.path.join(current, name), root)
|
||||
for name in sorted(files):
|
||||
path = os.path.join(current, name)
|
||||
if not os.path.islink(path) and os.path.isfile(path):
|
||||
yield 'F', os.path.relpath(path, root)
|
||||
if args['action'] == 'content':
|
||||
print(json.dumps({'content': content(args['path'])}))
|
||||
elif args['action'] == 'list':
|
||||
paths, folders = [], []
|
||||
for kind, path in entries():
|
||||
(folders if kind == 'D' else paths).append(path)
|
||||
print(json.dumps({'filePaths': paths, 'folders': folders}))
|
||||
else:
|
||||
query = args['query'].strip().lower()
|
||||
results = []
|
||||
if len(query) >= 2:
|
||||
for kind, path in entries():
|
||||
if kind != 'F':
|
||||
continue
|
||||
text = content(path)
|
||||
if text == placeholder:
|
||||
continue
|
||||
for number, line in enumerate(text.split('\\n'), 1):
|
||||
if query in line.lower():
|
||||
results.append({'file': path, 'lineNumber': number, 'lineText': (line.strip() or line)[:2000]})
|
||||
if len(results) >= 200:
|
||||
break
|
||||
if len(results) >= 200:
|
||||
break
|
||||
print(json.dumps(results))
|
||||
PY`
|
||||
}
|
||||
Reference in New Issue
Block a user