update rook hooks & templates

This commit is contained in:
Leon van Kammen 2026-01-19 19:57:29 +01:00
parent 258df4621f
commit 677dab8abd
15 changed files with 402 additions and 0 deletions

View 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 }
],
};

View 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"

View 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

View file

@ -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

View 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>

View 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 -->

View 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>

View 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>

View 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>

View 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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB