update rook hooks & templates
This commit is contained in:
parent
258df4621f
commit
677dab8abd
15 changed files with 402 additions and 0 deletions
92
manyfold/root/.config/janus-server/config.js
Normal file
92
manyfold/root/.config/janus-server/config.js
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
var fs = require('fs');
|
||||
|
||||
module.exports = {
|
||||
/* Socket port to listen on */
|
||||
port: 5566,
|
||||
|
||||
/* SSL configurations */
|
||||
|
||||
/*
|
||||
************************************************************************
|
||||
*** The following options REQUIRE a redis database to function ! ***
|
||||
************************************************************************
|
||||
*/
|
||||
multiprocess: {
|
||||
enabled: false, // requires redis for IPC
|
||||
processes: 1
|
||||
},
|
||||
partyList: false,
|
||||
redis: {
|
||||
host: "127.0.0.1",
|
||||
port: 6379,
|
||||
//password: null
|
||||
},
|
||||
|
||||
|
||||
/*
|
||||
************************************************************************
|
||||
*** The following options REQUIRE a MySQL database to function ! ***
|
||||
************************************************************************
|
||||
*/
|
||||
|
||||
//// If you want to track how many users are online, set UserList: true.
|
||||
//Userlist: false,
|
||||
|
||||
///* Controls how many results a request for 'users_online' receives. */
|
||||
//maxUserResults: 100,
|
||||
|
||||
///* MySQL database connection info for janus-mysql-auth and janus-mysql-userlist */
|
||||
//MySQL_Hostname: 'localhost',
|
||||
//MySQL_Database: 'janusvr',
|
||||
//MySQL_Username: 'janusvr',
|
||||
//MySQL_Password: 'janusvr',
|
||||
|
||||
///* Authentication mode:
|
||||
// 'none' - Will not attempt to authenticate users,
|
||||
// anyone can connect with any unused userId.
|
||||
// 'optional' - Anyone can connect, but if userId has been registered
|
||||
// a password must be provided.
|
||||
// 'required' - Only users with userids and passwords are allowed to connect.
|
||||
//*/
|
||||
//authMode: "none",
|
||||
//
|
||||
//popularRooms: {
|
||||
// halfLife: 7 * 24 * 60 * 60 * 1000, // set halflife to 7 days
|
||||
// updateInterval: 3000, // interval between weight updates on the popular rooms
|
||||
// masterToken: "changethis"
|
||||
//},
|
||||
|
||||
/*
|
||||
************************************************************************
|
||||
*** The previous options REQUIRE a MySQL database to function ! ***
|
||||
************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Plugins must be installed from npm, or manually created in node_module/ to be loaded. */
|
||||
/* hookPlugins are called while parsing messages */
|
||||
hookPlugins: {
|
||||
logon: {
|
||||
plugins: [
|
||||
//" janus-mysql-auth"
|
||||
]
|
||||
},
|
||||
enter_room: {
|
||||
plugins: [
|
||||
// "janus-mysql-popular"
|
||||
]
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/* methodPlugins add new commands to the server */
|
||||
methodPlugins: {
|
||||
// ping: { plugin: "janus-method-ping" }
|
||||
},
|
||||
|
||||
/* intervalPlugins are called in intervals specified in seconds. */
|
||||
intervalPlugins: [
|
||||
//{ plugin: "janus-mysql-userlist-official", interval: 6 }
|
||||
],
|
||||
};
|
||||
76
manyfold/root/bin/random_thumbnail.sh
Executable file
76
manyfold/root/bin/random_thumbnail.sh
Executable file
|
|
@ -0,0 +1,76 @@
|
|||
#!/bin/sh
|
||||
|
||||
test -n "$2" || { echo "Usage: $0 <input.jpg> <output.jpg> [blurtimes]"; exit 0; }
|
||||
|
||||
# --- Configuration ---
|
||||
# Define the size of the rectangle to crop (Width x Height)
|
||||
CROP_SIZE="128x128"
|
||||
CROP_WIDTH=128
|
||||
CROP_HEIGHT=128
|
||||
BLURTIMES=0
|
||||
|
||||
test -n "$3" && BLURTIMES=$3
|
||||
|
||||
# Input and Output filenames
|
||||
INPUT_FILE="$1" # <-- **CHANGE THIS** to your actual input file name
|
||||
OUTPUT_FILE="$2"
|
||||
|
||||
# --- Pre-Check: Ensure the input file exists ---
|
||||
if [ ! -f "$INPUT_FILE" ]; then
|
||||
echo "🚨 Error: Input file '$INPUT_FILE' not found."
|
||||
echo "Please update the INPUT_FILE variable in the script."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- 1. Get the dimensions of the input image ---
|
||||
# The 'identify' command returns image info; we use awk/cut to extract just the dimensions.
|
||||
# Example output format: "1920x1080"
|
||||
IMAGE_GEOMETRY=$(identify -format "%wx%h" "$INPUT_FILE")
|
||||
IMAGE_WIDTH=$(echo "$IMAGE_GEOMETRY" | cut -dx -f1)
|
||||
IMAGE_HEIGHT=$(echo "$IMAGE_GEOMETRY" | cut -dx -f2)
|
||||
|
||||
echo "Input Image: $INPUT_FILE (${IMAGE_GEOMETRY})"
|
||||
echo "Crop Area: $CROP_SIZE"
|
||||
|
||||
# --- 2. Calculate the maximum possible starting coordinates ---
|
||||
# To ensure the 16x16 crop doesn't go off the edge:
|
||||
# Max_X_Start = Image_Width - Crop_Width
|
||||
# Max_Y_Start = Image_Height - Crop_Height
|
||||
MAX_X=$((IMAGE_WIDTH - CROP_WIDTH))
|
||||
MAX_Y=$((IMAGE_HEIGHT - CROP_HEIGHT))
|
||||
|
||||
# Check if the image is too small to crop
|
||||
if [ $MAX_X -lt 0 ] || [ $MAX_Y -lt 0 ]; then
|
||||
echo "🚨 Error: Image dimensions ($IMAGE_GEOMETRY) are smaller than the crop size ($CROP_SIZE)."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- 3. Generate Random Coordinates ---
|
||||
# $RANDOM generates a pseudo-random integer (0 to 32767).
|
||||
# We use the modulo operator (%) to limit it to the required range (0 to MAX_X or MAX_Y).
|
||||
|
||||
# Random X-coordinate (0 to MAX_X)
|
||||
RANDOM_X=$((RANDOM % (MAX_X + 1)))
|
||||
|
||||
# Random Y-coordinate (0 to MAX_Y)
|
||||
RANDOM_Y=$((RANDOM % (MAX_Y + 1)))
|
||||
|
||||
# --- 4. Assemble the ImageMagick Geometry String ---
|
||||
# The final geometry string is: <Width>x<Height>+<X_Offset>+<Y_Offset>
|
||||
CROP_GEOMETRY="${CROP_SIZE}+${RANDOM_X}+${RANDOM_Y}"
|
||||
|
||||
echo "Random Start Coordinate: X=${RANDOM_X}, Y=${RANDOM_Y}"
|
||||
echo "ImageMagick Crop String: ${CROP_GEOMETRY}"
|
||||
|
||||
# --- 5. Execute the ImageMagick Command ---
|
||||
# 'convert' is the core command.
|
||||
# -crop: Specifies the geometry string for cropping.
|
||||
# -quality 100: (Optional) Ensures best quality for the output JPEG.
|
||||
test -f $OUTPUT_FILE && rm $OUTPUT_FILE
|
||||
magick "$INPUT_FILE" \
|
||||
-crop "$CROP_GEOMETRY" \
|
||||
-blur 0x$BLURTIMES \
|
||||
-quality 100 \
|
||||
"$OUTPUT_FILE"
|
||||
|
||||
echo "✅ thumbnail generated"
|
||||
116
manyfold/root/hook.d/boot/import_instances.rb
Executable file
116
manyfold/root/hook.d/boot/import_instances.rb
Executable file
|
|
@ -0,0 +1,116 @@
|
|||
#!/usr/bin/env ruby
|
||||
require 'yaml' # For reading input
|
||||
require 'json' # <--- REQUIRED FOR OUTPUT
|
||||
require 'fileutils'
|
||||
require 'pathname'
|
||||
require 'net/http'
|
||||
require 'uri'
|
||||
require 'erb'
|
||||
|
||||
if ! ENV['IMPORT_INSTANCES']
|
||||
exit 0 # nothing to do
|
||||
end
|
||||
|
||||
INPUT_ROOT_DIR = '/root/instances'
|
||||
OUTPUT_ROOT_DIR = '/mnt/instances'
|
||||
|
||||
FileUtils.mkdir_p(OUTPUT_ROOT_DIR)
|
||||
|
||||
puts "scanning yaml-files in /root/instances"
|
||||
|
||||
# 2. Iterate over all 'room.yaml' files recursively
|
||||
Dir.glob(File.join(INPUT_ROOT_DIR, '**', 'room.yaml')).each do |input_file_path|
|
||||
|
||||
begin
|
||||
input_data = YAML.load_file(input_file_path)
|
||||
rescue StandardError => e
|
||||
puts " ❌ Error reading or parsing YAML: #{e.message}"
|
||||
next
|
||||
end
|
||||
|
||||
relative_path = Pathname.new(input_file_path).relative_path_from(Pathname.new(INPUT_ROOT_DIR))
|
||||
path_components = relative_path.to_s.split(File::SEPARATOR)
|
||||
|
||||
unless path_components.length >= 4
|
||||
puts " ⚠️ Skipping: Path structure too shallow. Expected SERVER/AUTHOR/ROOM_NAME/room.yaml"
|
||||
next
|
||||
end
|
||||
|
||||
server_name = path_components[0]
|
||||
author_name = path_components[1]
|
||||
room_name = path_components[2]
|
||||
|
||||
begin
|
||||
u = input_data['url']
|
||||
r = Net::HTTP.new(URI.parse(u).host, URI.parse(u).port)
|
||||
r.use_ssl = (URI.parse(u).scheme == 'https')
|
||||
|
||||
a = r.request(Net::HTTP::Head.new(URI.parse(u).request_uri))
|
||||
|
||||
if a.code.to_i != 200
|
||||
puts " ⚠️ Skipping:HTTP code #{a.code} received :/"
|
||||
next
|
||||
end
|
||||
|
||||
# 5. Construct the final data structure (Hash)
|
||||
output_data = {}
|
||||
output_data['homepage'] = input_data['url']
|
||||
output_data['name'] = input_data['title']
|
||||
output_data['description'] = input_data['description']
|
||||
output_data['image'] = input_data['thumbnail']
|
||||
output_data['tags'] = [server_name]
|
||||
|
||||
output_dir = File.join(OUTPUT_ROOT_DIR, author_name, room_name)
|
||||
output_file_path = File.join(output_dir, 'datapackage.json')
|
||||
|
||||
begin
|
||||
|
||||
url = URI(input_data['thumbnail'])
|
||||
output_path = output_dir+"/.xrforge/thumbnail.jpg"
|
||||
|
||||
Net::HTTP.start(url.host, url.port, use_ssl: url.scheme == "https") do |http|
|
||||
request = Net::HTTP::Get.new(url)
|
||||
http.request(request) do |response|
|
||||
raise "Download failed: #{response.code}" unless response.is_a?(Net::HTTPSuccess)
|
||||
|
||||
File.open(output_path, "wb") do |file|
|
||||
response.read_body do |chunk|
|
||||
file.write(chunk)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if a.code.to_i != 200
|
||||
puts " ⚠️ Skipping:HTTP code #{a.code} receivedfor thumbnail :/"
|
||||
next
|
||||
end
|
||||
|
||||
# write datapackage.json
|
||||
FileUtils.mkdir_p(output_dir) # Create directory (including parents)
|
||||
File.write(output_file_path, JSON.pretty_generate(output_data))
|
||||
puts " ✅ HTTP 200: Wrote #{output_file_path}"
|
||||
|
||||
# write janusxr.html + scene.jml
|
||||
templateDir = File.dirname(__FILE__)+"/../../templates/"
|
||||
FileUtils.mkdir_p(output_dir+"/.xrforge") # Create directory (including parents)
|
||||
data = output_data
|
||||
data['title'] = output_data['name']
|
||||
$links = []
|
||||
janusweb_src = ENV['DEV'] ? "/mnt/janusweb/janusweb.js" : "/mnt/janusweb/janusweb.min.js"
|
||||
jml = ERB.new( File.read( templateDir+"JML/portalAR.erb" ) ).result(binding)
|
||||
html = ERB.new( File.read( templateDir+"JML/client.html") ).result(binding)
|
||||
File.write(output_dir+"/.xrforge/scene.jml", jml )
|
||||
puts " ✅ Wrote #{output_dir}/.xrforge/scene.jml"
|
||||
File.write(output_dir+"/.xrforge/janusxr.html", html )
|
||||
puts " ✅ Wrote #{output_dir}/.xrforge/janusxr.html"
|
||||
|
||||
rescue StandardError => e
|
||||
puts " ❌ Error writing output file: #{e.message}"
|
||||
end
|
||||
rescue StandardError => e
|
||||
# Optionally handle error quietly or output e.message
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
url: https://vesta.janusxr.org/spyduck/lains-bedroom-serial-experiments-lain
|
||||
title: "Lain's Bedroom"
|
||||
description: "Recreation of the protagonist's bedroom from Serial Experiments Lain"
|
||||
thumbnail: https://vesta.janusxr.org/assets/thumbs/spyduck/c59d083f4c3e9fcde3f525d28d8acd69.jpg
|
||||
62
manyfold/root/templates/JML/client.html
Normal file
62
manyfold/root/templates/JML/client.html
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title><%=data['title']%> - JanusXR</title>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no, maximum-scale=1.0, width=device-width" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
||||
<!--
|
||||
<meta name="theme-color" content="#2f363b">
|
||||
<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-06-12" content="Avy/Fo2QM5trR+WVHnaVz0t3LVltGxx3yvpSYSCC2oklwuDEYUEK6YdnxYv4p687MJGB61q//htZUvSIZPg93goAAABOeyJvcmlnaW4iOiJodHRwczovL3dlYi5qYW51c3ZyLmNvbTo0NDMiLCJmZWF0dXJlIjoiV2ViVlIiLCJleHBpcnkiOjE0OTczMTIwMDB9">
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:site" content="@bai0" />
|
||||
<meta name="twitter:title" content="JanusWeb" />
|
||||
<meta name="twitter:description" content="The World Within The Web" />
|
||||
<meta name="twitter:image" content="https://janusxr.org/backgrounds/wallpapers/generic.png" />
|
||||
<meta name="twitter:image:alt" content="JanusWeb" />
|
||||
<meta property="og:app_id" content="1197654320349894" />
|
||||
<meta property="og:url" content="https://web.janusxr.org/" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="JanusWeb" />
|
||||
<meta property="og:description" content="The World Within The Web" />
|
||||
<meta property="og:image" content="https://janusxr.com/backgrounds/wallpapers/generic.png" />
|
||||
-->
|
||||
</head>
|
||||
<body>
|
||||
<janus-viewer homepage="/" autostart="false" showavatar="false">
|
||||
<%=jml%>
|
||||
</janus-viewer>
|
||||
<!-- archive.org hints -->
|
||||
<% $links.each do |link| %>
|
||||
<a href="<%=link%>"></a>
|
||||
<% end %>
|
||||
|
||||
<!-- map URL query args to room-attributes -->
|
||||
<script>
|
||||
args = new URLSearchParams(document.location.search)
|
||||
for( const [k,v] of args.entries()) document.querySelector("Room").setAttribute(k,v)
|
||||
</script>
|
||||
<script src="<%=janusweb_src%>"></script>
|
||||
<script>
|
||||
let serveruri = "ws://"+document.location.hostname+":5566"
|
||||
let corsproxy = document.location.origin.replace(/:[0-9].*/,'')+":5577/"
|
||||
if( document.location.protocol.match(/https/) ){
|
||||
corsproxy = corsproxy.replace(/\/\//,"//cors.").replace(/:[0-9].*/,"/")
|
||||
serveruri = serveruri.replace(/ws:\/\//,"wss://presence.").replace(/:[0-9].*/,"")
|
||||
}
|
||||
elation.config.set("engine.assets.corsproxy", corsproxy )
|
||||
elation.config.set("janusweb.network.host", serveruri )
|
||||
elation.janusweb.init({
|
||||
uiconfig: `/janusweb/media/assets/webui/${ args.get("networking") == "false" ? "preview" : "default"}.json`,
|
||||
// for more opts see getClientArgs() in
|
||||
// https://github.com/jbaicoianu/janusweb/blob/master/scripts/client.js
|
||||
})
|
||||
.then( (client) => {
|
||||
elation.janusweb.init = function(){} // prevent multi-inits
|
||||
})
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
9
manyfold/root/templates/JML/header.erb
Normal file
9
manyfold/root/templates/JML/header.erb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<!-- Hi there! Below is autogenerated JanusXR Markup (JML). -->
|
||||
<!-- If you want to tweak it, then first disable autogeneration -->
|
||||
<!-- How? remove the 'autogenerate' attribute from the <Room> tag below -->
|
||||
<!-- Please note: the tags will **no longer** reflect this JML -->
|
||||
<!-- -->
|
||||
<!-- JML info: -->
|
||||
<!-- https://coderofsalvation.github.io/janus-guide/#/examples/markup -->
|
||||
<!-- https://janusxr.org/docs/build/introtojml/index.html -->
|
||||
|
||||
8
manyfold/root/templates/JML/portalAR.erb
Normal file
8
manyfold/root/templates/JML/portalAR.erb
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<fireboxroom>
|
||||
<Assets>
|
||||
</Assets>
|
||||
<Room pos="0 0 0" skybox="true" showavatar="false" use_local_asset="room_plane">
|
||||
<link url="<%=data['url']%> col="1.0 0.0 1.0" title="<%=data['title']%> pos="0 0 5" scale="1.8 3.2 1"/>
|
||||
<Paragraph pos="2.8 1 -3.21" fwd="0 0 1" lighting="false" rotation="180 -45 180" col="0.5 0.8 0.5" scale="2 2 2" font_size="50" locked="false"><%=data['description']%></Paragraph>
|
||||
</Room>
|
||||
</fireboxroom>
|
||||
10
manyfold/root/templates/JML/room.erb
Normal file
10
manyfold/root/templates/JML/room.erb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<FireBoxRoom>
|
||||
<Assets>
|
||||
<%=assets%>
|
||||
<assetimage id="home" src="/view/home.png"/>
|
||||
</Assets>
|
||||
<Room autogenerate="true" <%=use_local_asset%> <%=private%> <%=showavatar%> <%=startpos%>>
|
||||
<%=objects%>
|
||||
<link url="/models" col="1.0 0.0 1.0" title="back to home" pos="0 0 -5" scale="1.8 3.2 1" image_id="home"/>
|
||||
</Room>
|
||||
</FireBoxRoom>
|
||||
10
manyfold/root/templates/JML/room.xrforge.erb
Normal file
10
manyfold/root/templates/JML/room.xrforge.erb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<FireBoxRoom>
|
||||
<Assets>
|
||||
<%=assets%>
|
||||
<assetimage id="home" src="/view/home.png"/>
|
||||
</Assets>
|
||||
<Room autogenerate="true" <%=use_local_asset%> <%=private%> <%=showavatar%> <%=startpos%>>
|
||||
<%=objects%>
|
||||
<link url="/models" col="1.0 0.0 1.0" title="back to home" pos="0 0 -5" scale="1.8 3.2 1" image_id="home"/>
|
||||
</Room>
|
||||
</FireBoxRoom>
|
||||
15
manyfold/root/templates/audiovisual/audiovisual.xml
Normal file
15
manyfold/root/templates/audiovisual/audiovisual.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<fireboxroom>
|
||||
<assets>
|
||||
<assetimage id="image" src="lobby.png"/>
|
||||
<assetvideo auto_play="true" id="video" loop="true" src="video.mp4"/>
|
||||
<assetobject id="rplane" src="roundedplane.glb"/>
|
||||
</assets>
|
||||
<room use_local_asset="room5" pos="0 0 -10">
|
||||
<Object cull_face="none" id="rplane" js_id="video" lighting="false" pos="0 6.5 5.5" scale="4 4 1" video_id="video"/>
|
||||
<Object cull_face="none" id="rplane" js_id="text_rplane" lighting="false" pos="2.69 1.84 -3.37" rotation="0 45 0" scale="1.6 1 1"/>
|
||||
<Paragraph pos="2.8 1 -3.21" fwd="0 0 1" lighting="false" rotation="180 -45 180" col="0.5 0.8 0.5" scale="2 2 2" font_size="50" locked="false">
|
||||
This is a template for audiovisual experiences. Use it for beautiful spatial music/video releases, by just upload/replacing an audio- or video-file.
|
||||
</Paragraph>
|
||||
</room>
|
||||
</fireboxroom>
|
||||
<title>Audiovisual</title>
|
||||
BIN
manyfold/root/templates/audiovisual/lobby.png
Normal file
BIN
manyfold/root/templates/audiovisual/lobby.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 821 KiB |
BIN
manyfold/root/templates/audiovisual/roundedplane.glb
Normal file
BIN
manyfold/root/templates/audiovisual/roundedplane.glb
Normal file
Binary file not shown.
BIN
manyfold/root/templates/audiovisual/video.mp4
Normal file
BIN
manyfold/root/templates/audiovisual/video.mp4
Normal file
Binary file not shown.
BIN
manyfold/root/templates/audiovisual/video.webm
Normal file
BIN
manyfold/root/templates/audiovisual/video.webm
Normal file
Binary file not shown.
BIN
manyfold/root/templates/thumbnailseed.jpg
Normal file
BIN
manyfold/root/templates/thumbnailseed.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
Loading…
Add table
Reference in a new issue