Compare commits

..

2 commits

Author SHA1 Message Date
f83261584f re-add index.html viewer 2025-11-11 08:13:35 +01:00
4d69db1b47 add tags 2025-11-10 21:25:39 +01:00
16 changed files with 567 additions and 714 deletions

View file

@ -48,7 +48,7 @@ $ manyfold/cli/manyfold run -v ./experiences:/mnt/experiences
| environment variable | default | info | | environment variable | default | info |
|-----------------------|--------------|------------------------| |-----------------------|--------------|------------------------|
| `APPNAME` | `manyfold` | manyfold instance name | | `APPNAME` | `XRForge` | manyfold instance name |
| `HOMEPAGE` | `/models` | show '/models' URL as homepage (use `/` for manyfold default) | | `HOMEPAGE` | `/models` | show '/models' URL as homepage (use `/` for manyfold default) |
| `THEME` | `default` | bootstrap theme | | `THEME` | `default` | bootstrap theme |
| `AFRAME_VERSION` | `1.7.0` | AFRAME version | | `AFRAME_VERSION` | `1.7.0` | AFRAME version |
@ -58,7 +58,6 @@ $ manyfold/cli/manyfold run -v ./experiences:/mnt/experiences
| `DEV` | `` | enable development mode (disables caching, sets `bin/dev` as entrypoint) | | `DEV` | `` | enable development mode (disables caching, sets `bin/dev` as entrypoint) |
| `NO_PUBLIC_ONLY` | `` | disable public only models | | `NO_PUBLIC_ONLY` | `` | disable public only models |
| `NO_OVERLAYFS` | `` | disable the filesystem overlay mechanism | | `NO_OVERLAYFS` | `` | disable the filesystem overlay mechanism |
| `NO_DEFAULTDB` | `` | disable the default xrforge db (activates manyfold installer) |
| `NO_ASSETS` | `` | disable downloading assets from xrfragment.org repository | | `NO_ASSETS` | `` | disable downloading assets from xrfragment.org repository |
| `NO_DELETEBIGFILES` | `` | disable deleting big files which are older than 5 days and bigger than ($currentyear-2020) MB's | | `NO_DELETEBIGFILES` | `` | disable deleting big files which are older than 5 days and bigger than ($currentyear-2020) MB's |
| `NO_PACKAGEALL` | `` | don't package all experiences every hour to /usr/src/app/public/experiences.zip | | `NO_PACKAGEALL` | `` | don't package all experiences every hour to /usr/src/app/public/experiences.zip |
@ -83,6 +82,8 @@ $ manyfold/cli/manyfold run -v ./experiences:/mnt/experiences
> please modify the password in the settings screen of the webinterface. > please modify the password in the settings screen of the webinterface.
It's also possible to enforce a default sqlite3 db via the `-v ./manyfold.sql:/manyfold/manyfold.sql` container flag.
# Filesystem overlay-mechanism # Filesystem overlay-mechanism
The server-image will boot `manyfold/cli/manyfold.sh boot` and check for directory `/manyfold` (in the container). The server-image will boot `manyfold/cli/manyfold.sh boot` and check for directory `/manyfold` (in the container).

View file

@ -1,6 +1,7 @@
#!/bin/sh #!/bin/sh
oci=$(which podman || which docker) oci=$(which podman || which docker)
test -n "$APPNAME" || export APPNAME=xrforge test -n "$APPNAME" || export APPNAME=XRForge
test -n "$TAGLINE" || export TAGLINE="Publish single-file XR experiences to immersive networks"
test -n "$UPLOAD_PATH" || export UPLOAD_PATH=/mnt/experiences test -n "$UPLOAD_PATH" || export UPLOAD_PATH=/mnt/experiences
test -n "$THEME" || export THEME=slate test -n "$THEME" || export THEME=slate
test -n "$HOMEPAGE" || export HOMEPAGE=/models test -n "$HOMEPAGE" || export HOMEPAGE=/models
@ -156,15 +157,30 @@ mount_rclone(){
test -n "$RCLONE_REMOTE" || libraries test -n "$RCLONE_REMOTE" || libraries
} }
set_theme(){ set_global(){
test -z "$THEME" && return 0 # nothing to do echocolor "[$APPNAME]" "setting $1 to '$2'"
echocolor "[$APPNAME]" "setting theme to '$THEME'" debug sqlite3 /config/manyfold.sqlite3 'CREATE TABLE IF NOT EXISTS "settings" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "var" varchar NOT NULL, "value" text, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);'
debug sqlite3 /config/manyfold.sqlite3 "UPDATE settings SET value = '"$THEME"' WHERE var == 'theme';" debug sqlite3 /config/manyfold.sqlite3 "
INSERT OR REPLACE INTO settings (id, var, value, created_at, updated_at)
VALUES (
(SELECT id FROM settings WHERE var = '$1'),
'$1',
$2,
COALESCE((SELECT created_at FROM settings WHERE var = '$1'), datetime('now')),
datetime('now')
);
"
} }
set_modelpath(){ set_admin(){
echocolor "[$APPNAME]" "enforcing modelpath" echocolor "[$APPNAME]" "adding xrforge admin"
debug sqlite3 /config/manyfold.sqlite3 "UPDATE settings SET value = replace('--- \"{creator}/{modelId}\"\n','\n',char(10)) WHERE var == 'model_path_template';" read -r -d '' QUERY <<EOF
INSERT INTO users VALUES(1,'xrforge@localhost','\$2a\$12\$u/j8LRzbPiJRHmi1eV/fvOXXiKxN2vBGtNd.Pt28w.wOnq3rnfpzO','2025-07-25 10:52:56.989975','2025-07-25 12:46:27.338917','xrforge','{"models":true,"creators":true,"collections":true,"per_page":12}','{"grid_width":200,"grid_depth":200,"show_grid":true,"enable_pan_zoom":false,"background_colour":"#000000","object_colour":"#ffffff","render_style":"original"}','{"threshold":2,"heatmap":true,"keypair":true,"sorting":"frequency"}','{"missing":"danger","empty":"info","nesting":"warning","inefficient":"info","duplicate":"warning","no_image":"silent","no_3d_model":"silent","non_manifold":"warning","inside_out":"warning","no_license":"silent","no_links":"silent","no_creator":"silent","no_tags":"silent"}','{"hide_presupported_versions":true}',NULL,'2025-07-25 12:46:27.325287',NULL,NULL,0,NULL,NULL,NULL,NULL,'71863vkppj6k',1,1,1);
EOF
debug sqlite3 /config/manyfold.sqlite3 "$QUERY"
debug sqlite3 /config/manyfold.sqlite3 'INSERT INTO users_roles VALUES(1,1);'
#debug sqlite3 /config/manyfold.sqlite3 'INSERT INTO users_roles VALUES(1,4);'
#debug sqlite3 /config/manyfold.sqlite3 "INSERT INTO sqlite_sequence VALUES('users',1);"
} }
set_homepage(){ set_homepage(){
@ -176,7 +192,7 @@ set_homepage(){
rename_app(){ rename_app(){
echocolor "[$APPNAME]" "renaming manyfold to $APPNAME" echocolor "[$APPNAME]" "renaming manyfold to $APPNAME"
sed -i 's/title: Manyfold/title: '$APPNAME'/g' /usr/src/app/config/locales/*.yml sed -i 's/title: Manyfold/title: '$APPNAME'/g' /usr/src/app/config/locales/*.yml
sed -i 's|powered_by_html:.*|powered_by_html: Radically opensource-powered by <a href="https://forgejo.isvery.ninja/coderofsalvation/xrforge">XR Forge</a>, <a href="https://manifold.app" target="_blank">Manyfold</a>, <a href="https://xrfragment.org">XR Fragments</a> and <a href="https://nixos.org" target="_blank">NIX</a>|g' /usr/src/app/config/locales/*.yml sed -i 's|powered_by_html:.*|powered_by_html: Radically opensource-powered by <a href="https://manifold.app" target="_blank">Manyfold</a>, <a href="https://xrfragment.org">XR Fragments</a> and <a href="https://nixos.org" target="_blank">NIX</a>|g' /usr/src/app/config/locales/*.yml
sed -i 's|Models|Experiences|g' /usr/src/app/config/locales/*.yml /usr/src/app/config/locales/*/*.yml sed -i 's|Models|Experiences|g' /usr/src/app/config/locales/*.yml /usr/src/app/config/locales/*/*.yml
sed -i 's|Model|Experience|g' /usr/src/app/config/locales/*.yml /usr/src/app/config/locales/*/*.yml sed -i 's|Model|Experience|g' /usr/src/app/config/locales/*.yml /usr/src/app/config/locales/*/*.yml
@ -222,28 +238,35 @@ get_xrfragment_assets(){
add_lib_to_db /mnt/templates add_lib_to_db /mnt/templates
} }
init_database(){
sleep 3
test -z "$THEME" || set_global theme "'$THEME'"
set_admin
set_global site_name "'$APPNAME'"
set_global site_tagline "'$TAGLINE'"
set_global model_tags_auto_tag_new "replace('--- \"build \"\\n','\\n',char(10))"
set_global model_path_template "replace('--- \"{creator}/{modelId} \"\\n','\\n',char(10))"
#set_global about "$ABOUT"
mount_rclone
set_upload_path &
force_public &
get_xrfragment_assets
mount_dir
scan_libraries &
}
# The new entrypoint of the docker # The new entrypoint of the docker
boot(){ boot(){
echocolor "[$APPNAME]" "booting..." echocolor "[$APPNAME]" "booting..."
test -z "$NO_OVERLAYFS" && overlayfs test -z "$NO_OVERLAYFS" && overlayfs
test -z "$NO_DEFAULTDB" && db default
start_syslog start_syslog
rename_app rename_app
set_homepage set_homepage
set_theme
set_modelpath
mount_rclone
set_upload_path
force_public
start_hook_daemon start_hook_daemon
get_xrfragment_assets
mount_dir
scan_libraries &
hook boot # emit unixy hook-event (/root/hook.d/boot/* scripts)
# enable development mode (disables template caching etc) # enable development mode (disables template caching etc)
test -n "$DEV" && { test -n "$DEV" && {
sed -i 's|^exec.*|exec s6-setuidgid $PUID:$PGID bin/dev|g' /usr/src/app/bin/docker-entrypoint.sh # sed -i 's|^exec.*|exec s6-setuidgid $PUID:$PGID bin/dev|g' /usr/src/app/bin/docker-entrypoint.sh
sed -i 's|config.enable_reloading = false|config.enable_reloading = true|g' /usr/src/app/config/environments/production.rb sed -i 's|config.enable_reloading = false|config.enable_reloading = true|g' /usr/src/app/config/environments/production.rb
apk add vim apk add vim
} }

View file

@ -1,362 +0,0 @@
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE IF NOT EXISTS "data_migrations" ("version" varchar NOT NULL PRIMARY KEY);
INSERT INTO data_migrations VALUES('20221214230757');
INSERT INTO data_migrations VALUES('20221220223040');
INSERT INTO data_migrations VALUES('20230221174212');
INSERT INTO data_migrations VALUES('20230308006000');
INSERT INTO data_migrations VALUES('20230612080306');
INSERT INTO data_migrations VALUES('20230613134254');
INSERT INTO data_migrations VALUES('20230617222353');
INSERT INTO data_migrations VALUES('20230628194944');
INSERT INTO data_migrations VALUES('20240319155526');
INSERT INTO data_migrations VALUES('20240322150022');
INSERT INTO data_migrations VALUES('20240615085913');
INSERT INTO data_migrations VALUES('20240731165647');
INSERT INTO data_migrations VALUES('20240802094448');
INSERT INTO data_migrations VALUES('20240805111500');
INSERT INTO data_migrations VALUES('20240830121749');
INSERT INTO data_migrations VALUES('20240830151650');
INSERT INTO data_migrations VALUES('20240904152358');
INSERT INTO data_migrations VALUES('20240909100000');
INSERT INTO data_migrations VALUES('20240923114515');
INSERT INTO data_migrations VALUES('20241013215000');
INSERT INTO data_migrations VALUES('20241021125322');
INSERT INTO data_migrations VALUES('20241118155027');
INSERT INTO data_migrations VALUES('20250121164452');
CREATE TABLE IF NOT EXISTS "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY);
INSERT INTO schema_migrations VALUES('20210130201037');
INSERT INTO schema_migrations VALUES('20210130203243');
INSERT INTO schema_migrations VALUES('20210205230918');
INSERT INTO schema_migrations VALUES('20210210153744');
INSERT INTO schema_migrations VALUES('20210212143001');
INSERT INTO schema_migrations VALUES('20210212143002');
INSERT INTO schema_migrations VALUES('20210212143003');
INSERT INTO schema_migrations VALUES('20210212143004');
INSERT INTO schema_migrations VALUES('20210212143005');
INSERT INTO schema_migrations VALUES('20210212143006');
INSERT INTO schema_migrations VALUES('20210220204055');
INSERT INTO schema_migrations VALUES('20210225232756');
INSERT INTO schema_migrations VALUES('20210225232841');
INSERT INTO schema_migrations VALUES('20210301230017');
INSERT INTO schema_migrations VALUES('20210302161202');
INSERT INTO schema_migrations VALUES('20210314185822');
INSERT INTO schema_migrations VALUES('20210318202638');
INSERT INTO schema_migrations VALUES('20210321164508');
INSERT INTO schema_migrations VALUES('20210330215825');
INSERT INTO schema_migrations VALUES('20220105233138');
INSERT INTO schema_migrations VALUES('20220106220519');
INSERT INTO schema_migrations VALUES('20220612220115');
INSERT INTO schema_migrations VALUES('20220612220116');
INSERT INTO schema_migrations VALUES('20220612220117');
INSERT INTO schema_migrations VALUES('20220614210023');
INSERT INTO schema_migrations VALUES('20220614211256');
INSERT INTO schema_migrations VALUES('20220614213902');
INSERT INTO schema_migrations VALUES('20220617122809');
INSERT INTO schema_migrations VALUES('20220619174307');
INSERT INTO schema_migrations VALUES('20220626152444');
INSERT INTO schema_migrations VALUES('20220702202932');
INSERT INTO schema_migrations VALUES('20221128165903');
INSERT INTO schema_migrations VALUES('20221210001132');
INSERT INTO schema_migrations VALUES('20221219204414');
INSERT INTO schema_migrations VALUES('20221220223340');
INSERT INTO schema_migrations VALUES('20230202210000');
INSERT INTO schema_migrations VALUES('20230202210001');
INSERT INTO schema_migrations VALUES('20230203150000');
INSERT INTO schema_migrations VALUES('20230221180921');
INSERT INTO schema_migrations VALUES('20230222155910');
INSERT INTO schema_migrations VALUES('20230303150029');
INSERT INTO schema_migrations VALUES('20230305180823');
INSERT INTO schema_migrations VALUES('20230307215826');
INSERT INTO schema_migrations VALUES('20230308004237');
INSERT INTO schema_migrations VALUES('20230308005021');
INSERT INTO schema_migrations VALUES('20230313000000');
INSERT INTO schema_migrations VALUES('20230313000001');
INSERT INTO schema_migrations VALUES('20230316184012');
INSERT INTO schema_migrations VALUES('20230324000000');
INSERT INTO schema_migrations VALUES('20230615135601');
INSERT INTO schema_migrations VALUES('20230628195018');
INSERT INTO schema_migrations VALUES('20230707082403');
INSERT INTO schema_migrations VALUES('20230710102250');
INSERT INTO schema_migrations VALUES('20230711111009');
INSERT INTO schema_migrations VALUES('20240122114207');
INSERT INTO schema_migrations VALUES('20240127143358');
INSERT INTO schema_migrations VALUES('20240131134832');
INSERT INTO schema_migrations VALUES('20240208143319');
INSERT INTO schema_migrations VALUES('20240209125409');
INSERT INTO schema_migrations VALUES('20240228130246');
INSERT INTO schema_migrations VALUES('20240306095646');
INSERT INTO schema_migrations VALUES('20240319155251');
INSERT INTO schema_migrations VALUES('20240319155903');
INSERT INTO schema_migrations VALUES('20240322143621');
INSERT INTO schema_migrations VALUES('20240410221112');
INSERT INTO schema_migrations VALUES('20240410222922');
INSERT INTO schema_migrations VALUES('20240418112821');
INSERT INTO schema_migrations VALUES('20240423102250');
INSERT INTO schema_migrations VALUES('20240610120318');
INSERT INTO schema_migrations VALUES('20240614085913');
INSERT INTO schema_migrations VALUES('20240701142651');
INSERT INTO schema_migrations VALUES('20240703103707');
INSERT INTO schema_migrations VALUES('20240703160732');
INSERT INTO schema_migrations VALUES('20240727113215');
INSERT INTO schema_migrations VALUES('20240727113216');
INSERT INTO schema_migrations VALUES('20240727113217');
INSERT INTO schema_migrations VALUES('20240731165646');
INSERT INTO schema_migrations VALUES('20240827155630');
INSERT INTO schema_migrations VALUES('20240904151944');
INSERT INTO schema_migrations VALUES('20240924122004');
INSERT INTO schema_migrations VALUES('20240926162407');
INSERT INTO schema_migrations VALUES('20241004194445');
INSERT INTO schema_migrations VALUES('20241007182824');
INSERT INTO schema_migrations VALUES('20241009122540');
INSERT INTO schema_migrations VALUES('20241015090803');
INSERT INTO schema_migrations VALUES('20241017093301');
INSERT INTO schema_migrations VALUES('20241017113112');
INSERT INTO schema_migrations VALUES('20241021124608');
INSERT INTO schema_migrations VALUES('20241025110218');
INSERT INTO schema_migrations VALUES('20241105121830');
INSERT INTO schema_migrations VALUES('20241122121621');
INSERT INTO schema_migrations VALUES('20241128162213');
INSERT INTO schema_migrations VALUES('20241128162214');
INSERT INTO schema_migrations VALUES('20250114105808');
INSERT INTO schema_migrations VALUES('20250121105010');
INSERT INTO schema_migrations VALUES('20250122171731');
INSERT INTO schema_migrations VALUES('20250222000000');
INSERT INTO schema_migrations VALUES('20250305171530');
INSERT INTO schema_migrations VALUES('20250407160721');
INSERT INTO schema_migrations VALUES('20250407160722');
INSERT INTO schema_migrations VALUES('20250408111644');
INSERT INTO schema_migrations VALUES('20250408145956');
INSERT INTO schema_migrations VALUES('20250409120155');
INSERT INTO schema_migrations VALUES('20250409125753');
INSERT INTO schema_migrations VALUES('20250423094525');
INSERT INTO schema_migrations VALUES('20250425104619');
INSERT INTO schema_migrations VALUES('20250520111046');
INSERT INTO schema_migrations VALUES('20250609210440');
INSERT INTO schema_migrations VALUES('20250620141805');
INSERT INTO schema_migrations VALUES('20250621223410');
INSERT INTO schema_migrations VALUES('20250629212656');
INSERT INTO schema_migrations VALUES('20250716093106');
INSERT INTO schema_migrations VALUES('20250724094951');
INSERT INTO schema_migrations VALUES('20250806142734');
CREATE TABLE IF NOT EXISTS "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
INSERT INTO ar_internal_metadata VALUES('environment','production','2025-07-25 10:52:31.380052','2025-07-25 10:52:31.380054');
CREATE TABLE IF NOT EXISTS "libraries" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "path" varchar NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "notes" varchar, "caption" varchar, "name" varchar, "tag_regex" text, "icon" text, "storage_service" varchar DEFAULT 'filesystem' NOT NULL, "s3_endpoint" varchar DEFAULT NULL, "s3_region" varchar DEFAULT NULL, "s3_bucket" varchar DEFAULT NULL, "s3_access_key_id" varchar DEFAULT NULL, "s3_secret_access_key" varchar DEFAULT NULL, "public_id" varchar, "s3_path_style" boolean DEFAULT 1 NOT NULL);
INSERT INTO libraries VALUES(6,'/mnt/experiences','2025-08-14','2025-08-14','','','experiences',NULL,'','filesystem','','','','','','experiences',1);
CREATE TABLE IF NOT EXISTS "tags" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "created_at" datetime, "updated_at" datetime, "taggings_count" integer DEFAULT 0);
CREATE TABLE IF NOT EXISTS "taggings" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "tag_id" integer, "taggable_type" varchar, "taggable_id" integer, "tagger_type" varchar, "tagger_id" integer, "context" varchar(128), "created_at" datetime, CONSTRAINT "fk_rails_9fcd2e236b"
FOREIGN KEY ("tag_id")
REFERENCES "tags" ("id")
);
CREATE TABLE IF NOT EXISTS "links" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "url" varchar, "linkable_type" varchar, "linkable_id" integer, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "synced_at" datetime(6));
INSERT INTO links VALUES(1,'https://xrfragment.org','Creator',1,'2025-08-14 12:57:19.685425','2025-08-14 12:57:19.685425',NULL);
CREATE TABLE IF NOT EXISTS "settings" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "var" varchar NOT NULL, "value" text, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
INSERT INTO settings VALUES(1,'default_library','6','2025-07-25 10:58:00.004576','2025-07-28 13:30:03.381376');
INSERT INTO settings VALUES(2,'site_name',replace('--- XRForge\n','\n',char(10)),'2025-07-25 10:59:04.496016','2025-07-25 10:59:04.496016');
INSERT INTO settings VALUES(3,'site_tagline',replace('--- Self-sovereign XR Experiences based on 3D files & URLs\n','\n',char(10)),'2025-07-25 10:59:04.519264','2025-07-25 10:59:04.519264');
INSERT INTO settings VALUES(4,'theme','vapor','2025-07-25 10:59:04.522670','2025-07-28 13:47:54.690364');
INSERT INTO settings VALUES(5,'about',replace('--- ''''\n','\n',char(10)),'2025-07-25 10:59:04.527612','2025-07-25 10:59:04.527612');
INSERT INTO settings VALUES(6,'rules',replace('--- ''''\n','\n',char(10)),'2025-07-25 10:59:04.531378','2025-07-25 10:59:04.531378');
INSERT INTO settings VALUES(7,'support_link',replace('--- https://forgejo.isvery.ninja/coderofsalvation/xrforge\n','\n',char(10)),'2025-07-25 10:59:04.533678','2025-07-25 10:59:04.533678');
INSERT INTO settings VALUES(8,'site_icon',replace('--- ''''\n','\n',char(10)),'2025-07-25 10:59:04.536228','2025-07-25 14:19:06.192651');
INSERT INTO settings VALUES(9,'model_path_template',replace('--- "{creator}/{modelId}"\n','\n',char(10)),'2025-07-28 15:57:18.598798','2025-07-28 15:57:18.598798');
INSERT INTO settings VALUES(10,'parse_metadata_from_path',replace('--- true\n','\n',char(10)),'2025-07-28 15:57:18.624917','2025-07-28 15:57:18.624917');
INSERT INTO settings VALUES(11,'safe_folder_names',replace('--- true\n','\n',char(10)),'2025-07-28 15:57:18.627224','2025-07-28 15:57:18.627224');
INSERT INTO settings VALUES(12,'model_ignored_files',replace('---\n- !ruby/regexp /^\.[^\.]+/\n- !ruby/regexp /.*\/@eaDir\/.*/\n- !ruby/regexp /__MACOSX/\n','\n',char(10)),'2025-07-28 15:57:18.633182','2025-07-28 15:57:18.633182');
INSERT INTO settings VALUES(13,'model_tags_filter_stop_words',replace('--- true\n','\n',char(10)),'2025-07-28 15:57:18.637858','2025-07-28 15:57:18.637858');
INSERT INTO settings VALUES(14,'model_tags_tag_model_directory_name',replace('--- false\n','\n',char(10)),'2025-07-28 15:57:18.640351','2025-07-28 15:57:18.640351');
INSERT INTO settings VALUES(15,'model_tags_stop_words_locale',replace('--- en\n','\n',char(10)),'2025-07-28 15:57:18.643185','2025-07-28 15:57:18.643185');
INSERT INTO settings VALUES(16,'model_tags_custom_stop_words',replace('---\n- png\n- jpeg\n- jpg\n- jpe\n- pjpeg\n- gif\n- bmp\n- tiff\n- tif\n- svg\n- webp\n- threeds\n- 3ds\n- amf\n- ldr\n- mpd\n- scad\n- dwg\n- dxf\n- threemf\n- 3mf\n- gltf\n- glb\n- iges\n- igs\n- mtl\n- obj\n- step\n- stp\n- stl\n- collada\n- dae\n- draco\n- drc\n- vrml\n- wrl\n- abc\n- blend\n- brep\n- cheetah3d\n- jas\n- fbx\n- fcstd\n- f3d\n- f3z\n- ipt\n- iam\n- maya\n- ma\n- mb\n- mix\n- modo\n- lxo\n- ply\n- sketchup\n- skp\n- sldprt\n- hfp\n- speedtree\n- spm\n- x3d\n- gcode\n- bgcode\n- lychee\n- lys\n- lyt\n- chitubox\n- ctb\n- mpeg\n- mpg\n- mpe\n- webm\n- mp4\n- m4v\n- html\n- xhtml\n- text\n- txt\n- pdf\n- md\n- doc\n- docx\n- bin\n- gbr\n- gerber\n- geb\n- gb\n- gbrjob\n- drl\n- kicad_pro\n- pro\n- kicad_mod\n- kicad_pcb\n- kicad_sym\n- kicad_sch\n- sch\n- kicad_wks\n- zip\n- gzip\n- gz\n- rar\n- sevenz\n- 7z\n- bz2\n','\n',char(10)),'2025-07-28 15:57:18.645648','2025-07-28 15:57:18.645648');
INSERT INTO settings VALUES(17,'model_tags_auto_tag_new',replace('--- "!new"\n','\n',char(10)),'2025-07-28 15:57:18.648518','2025-07-28 15:57:18.648518');
CREATE TABLE IF NOT EXISTS "problems" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "problematic_type" varchar, "problematic_id" integer, "category" integer, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "note" varchar DEFAULT NULL, "ignored" boolean DEFAULT 0 NOT NULL, "public_id" varchar, "in_progress" boolean DEFAULT 0 NOT NULL);
CREATE TABLE IF NOT EXISTS "favorites" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "favoritable_type" varchar NOT NULL, "favoritable_id" integer NOT NULL, "favoritor_type" varchar NOT NULL, "favoritor_id" integer NOT NULL, "scope" varchar DEFAULT 'printed' NOT NULL, "blocked" boolean DEFAULT 0 NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
CREATE TABLE IF NOT EXISTS "flipper_features" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "key" varchar NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
CREATE TABLE IF NOT EXISTS "flipper_gates" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "feature_key" varchar NOT NULL, "key" varchar NOT NULL, "value" text, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
CREATE TABLE IF NOT EXISTS "roles" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "resource_type" varchar, "resource_id" integer, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
INSERT INTO roles VALUES(1,'administrator',NULL,NULL,'2025-07-25 10:52:35.066502','2025-07-25 10:52:35.066502');
INSERT INTO roles VALUES(2,'moderator',NULL,NULL,'2025-07-25 10:52:35.079751','2025-07-25 10:52:35.079751');
INSERT INTO roles VALUES(3,'contributor',NULL,NULL,'2025-07-25 10:52:35.081798','2025-07-25 10:52:35.081798');
INSERT INTO roles VALUES(4,'member',NULL,NULL,'2025-07-25 10:52:35.083068','2025-07-25 10:52:35.083068');
CREATE TABLE IF NOT EXISTS "users_roles" ("user_id" integer, "role_id" integer);
INSERT INTO users_roles VALUES(1,4);
INSERT INTO users_roles VALUES(1,1);
CREATE TABLE IF NOT EXISTS "users" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "email" varchar DEFAULT '' NOT NULL, "encrypted_password" varchar DEFAULT '' NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "username" varchar NOT NULL, "pagination_settings" json DEFAULT '{"models":true,"creators":true,"collections":true,"per_page":12}', "renderer_settings" json DEFAULT '{"grid_width":200,"grid_depth":200,"show_grid":true,"enable_pan_zoom":false,"background_colour":"#000000","object_colour":"#ffffff","render_style":"original"}', "tag_cloud_settings" json DEFAULT '{"threshold":2,"heatmap":true,"keypair":true,"sorting":"frequency"}', "problem_settings" json DEFAULT '{"missing":"danger","empty":"info","nesting":"warning","inefficient":"info","duplicate":"warning","no_image":"silent","no_3d_model":"silent","non_manifold":"warning","inside_out":"warning","no_license":"silent","no_links":"silent","no_creator":"silent","no_tags":"silent"}', "file_list_settings" json DEFAULT '{"hide_presupported_versions":true}', "reset_password_token" varchar, "remember_created_at" datetime(6), "reset_password_sent_at" datetime(6), "interface_language" varchar, "failed_attempts" integer DEFAULT 0 NOT NULL, "locked_at" datetime(6), "auth_provider" varchar, "auth_uid" varchar, "sensitive_content_handling" varchar DEFAULT NULL, "public_id" varchar, "approved" boolean DEFAULT 1 NOT NULL, "quota" integer DEFAULT 1 NOT NULL, "quota_use_site_default" boolean DEFAULT 1 NOT NULL);
INSERT INTO users VALUES(1,'xrforge@localhost','$2a$12$u/j8LRzbPiJRHmi1eV/fvOXXiKxN2vBGtNd.Pt28w.wOnq3rnfpzO','2025-07-25 10:52:56.989975','2025-07-25 12:46:27.338917','xrforge','{"models":true,"creators":true,"collections":true,"per_page":12}','{"grid_width":200,"grid_depth":200,"show_grid":true,"enable_pan_zoom":false,"background_colour":"#000000","object_colour":"#ffffff","render_style":"original"}','{"threshold":2,"heatmap":true,"keypair":true,"sorting":"frequency"}','{"missing":"danger","empty":"info","nesting":"warning","inefficient":"info","duplicate":"warning","no_image":"silent","no_3d_model":"silent","non_manifold":"warning","inside_out":"warning","no_license":"silent","no_links":"silent","no_creator":"silent","no_tags":"silent"}','{"hide_presupported_versions":true}',NULL,'2025-07-25 12:46:27.325287',NULL,NULL,0,NULL,NULL,NULL,NULL,'71863vkppj6k',1,1,1);
CREATE TABLE IF NOT EXISTS "federails_followings" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "actor_id" integer NOT NULL, "target_actor_id" integer NOT NULL, "status" integer DEFAULT 0, "federated_url" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "uuid" varchar DEFAULT NULL, CONSTRAINT "fk_rails_2e62338faa"
FOREIGN KEY ("actor_id")
REFERENCES "federails_actors" ("id")
, CONSTRAINT "fk_rails_4a2870c181"
FOREIGN KEY ("target_actor_id")
REFERENCES "federails_actors" ("id")
);
CREATE TABLE IF NOT EXISTS "federails_activities" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "entity_type" varchar NOT NULL, "entity_id" integer NOT NULL, "action" varchar NOT NULL, "actor_id" integer NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "uuid" varchar DEFAULT NULL, CONSTRAINT "fk_rails_85ef6259df"
FOREIGN KEY ("actor_id")
REFERENCES "federails_actors" ("id")
);
INSERT INTO federails_activities VALUES(1,'Federails::Actor',2,'Create',1,'2025-08-14 12:57:19.593979','2025-08-14 12:57:19.737880','22e24c27-09ac-4f61-8897-1e176f16fcf7');
CREATE TABLE IF NOT EXISTS "caber_relations" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "subject_type" varchar, "subject_id" integer, "permission" varchar, "object_type" varchar NOT NULL, "object_id" integer NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
INSERT INTO caber_relations VALUES(1,'User',1,'own','Creator',1,'2025-08-14 12:57:19.679313','2025-08-14 12:57:19.679313');
INSERT INTO caber_relations VALUES(2,'Role',4,'view','Creator',1,'2025-08-14 12:57:19.762509','2025-08-14 12:57:19.762509');
CREATE TABLE IF NOT EXISTS "federails_moderation_reports" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "federated_url" varchar, "federails_actor_id" integer, "content" varchar, "object_type" varchar, "object_id" integer, "resolved_at" datetime(6), "resolution" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, CONSTRAINT "fk_rails_a5cda24d4c"
FOREIGN KEY ("federails_actor_id")
REFERENCES "federails_actors" ("id")
);
CREATE TABLE IF NOT EXISTS "federails_moderation_domain_blocks" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "domain" varchar NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
CREATE TABLE IF NOT EXISTS "comments" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "public_id" varchar NOT NULL, "commenter_type" varchar, "commenter_id" integer, "commentable_type" varchar NOT NULL, "commentable_id" integer NOT NULL, "comment" text, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "system" boolean DEFAULT 0 NOT NULL, "sensitive" boolean DEFAULT 0 NOT NULL, "federated_url" varchar, "federails_actor_id" integer, CONSTRAINT "fk_rails_3a181ceff0"
FOREIGN KEY ("federails_actor_id")
REFERENCES "federails_actors" ("id")
);
CREATE TABLE IF NOT EXISTS "oauth_applications" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "uid" varchar NOT NULL, "secret" varchar NOT NULL, "redirect_uri" text, "scopes" varchar DEFAULT '' NOT NULL, "confidential" boolean DEFAULT 1 NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "owner_id" bigint, "owner_type" varchar);
CREATE TABLE IF NOT EXISTS "oauth_access_grants" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "resource_owner_id" integer NOT NULL, "application_id" integer NOT NULL, "token" varchar NOT NULL, "expires_in" integer NOT NULL, "redirect_uri" text NOT NULL, "scopes" varchar DEFAULT '' NOT NULL, "created_at" datetime(6) NOT NULL, "revoked_at" datetime(6), CONSTRAINT "fk_rails_b4b53e07b8"
FOREIGN KEY ("application_id")
REFERENCES "oauth_applications" ("id")
, CONSTRAINT "fk_rails_330c32d8d9"
FOREIGN KEY ("resource_owner_id")
REFERENCES "users" ("id")
);
CREATE TABLE IF NOT EXISTS "oauth_access_tokens" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "resource_owner_id" integer, "application_id" integer NOT NULL, "token" varchar NOT NULL, "refresh_token" varchar, "expires_in" integer, "scopes" varchar, "created_at" datetime(6) NOT NULL, "revoked_at" datetime(6), "previous_refresh_token" varchar DEFAULT '' NOT NULL, CONSTRAINT "fk_rails_732cb83ab7"
FOREIGN KEY ("application_id")
REFERENCES "oauth_applications" ("id")
, CONSTRAINT "fk_rails_ee63f25419"
FOREIGN KEY ("resource_owner_id")
REFERENCES "users" ("id")
);
CREATE TABLE IF NOT EXISTS "federails_actors" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "federated_url" varchar, "username" varchar, "server" varchar, "inbox_url" varchar, "outbox_url" varchar, "followers_url" varchar, "followings_url" varchar, "profile_url" varchar, "entity_id" integer, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "entity_type" varchar DEFAULT NULL, "public_key" text, "private_key" text, "uuid" varchar, "extensions" json, "local" boolean DEFAULT 0 NOT NULL, "actor_type" varchar, "tombstoned_at" datetime(6));
INSERT INTO federails_actors VALUES(1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,'2025-07-25 10:52:57.029315','2025-07-25 10:52:57.029315','User',NULL,NULL,'eb64d114-1bc7-4cb3-8be6-350d23ccfb3e',NULL,1,NULL,NULL);
INSERT INTO federails_actors VALUES(2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,1,'2025-08-14 12:57:19.669133','2025-08-14 12:57:19.669133','Creator',NULL,NULL,'a544a58c-52be-4013-9415-440a9014b4c8',NULL,1,NULL,NULL);
CREATE TABLE IF NOT EXISTS "model_files" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "filename" varchar, "model_id" integer NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "presupported" boolean DEFAULT 0 NOT NULL, "y_up" boolean DEFAULT 0 NOT NULL, "digest" varchar, "notes" text, "caption" text, "size" bigint, "presupported_version_id" integer, "attachment_data" json, "public_id" varchar, "filename_lower" varchar GENERATED ALWAYS AS (LOWER(filename)) STORED, "previewable" boolean DEFAULT 0 NOT NULL, CONSTRAINT "fk_rails_b5ac05b6e3"
FOREIGN KEY ("presupported_version_id")
REFERENCES "model_files" ("id")
, CONSTRAINT "fk_rails_8e378ff647"
FOREIGN KEY ("model_id")
REFERENCES "models" ("id")
);
CREATE TABLE IF NOT EXISTS "altcha_solutions" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "algorithm" varchar, "challenge" varchar, "salt" varchar, "signature" varchar, "number" integer, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
CREATE TABLE IF NOT EXISTS "models" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "path" varchar NOT NULL, "library_id" integer NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "preview_file_id" integer, "creator_id" integer, "notes" text, "caption" text, "collection_id" integer, "slug" varchar, "license" varchar, "public_id" varchar, "name_lower" varchar GENERATED ALWAYS AS (LOWER(name)) STORED, "sensitive" boolean DEFAULT 0 NOT NULL, "indexable" varchar, "ai_indexable" varchar, CONSTRAINT "fk_rails_cdf016e15c"
FOREIGN KEY ("collection_id")
REFERENCES "collections" ("id")
, CONSTRAINT "fk_rails_aaa717f5bb"
FOREIGN KEY ("library_id")
REFERENCES "libraries" ("id")
, CONSTRAINT "fk_rails_3b8b50d3f3"
FOREIGN KEY ("creator_id")
REFERENCES "creators" ("id")
);
CREATE TABLE IF NOT EXISTS "creators" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "notes" text, "caption" text, "slug" varchar, "public_id" varchar, "name_lower" varchar GENERATED ALWAYS AS (LOWER(name)) STORED, "indexable" varchar, "ai_indexable" varchar);
INSERT INTO creators VALUES(1,'xrfragments','2025-08-14 12:57:19.593979','2025-08-14 12:57:19.593979','XR Fragments is an open specification for hyperlinking & deeplinking 3D fileformats .\nTurn 3D files into linkable AR/VR websites .\n3D files with XR Fragments enable interoperable, networkable and interactions via so-called extras and promote URL standards','deeplinking and adressing 3D objects using URI''s','xrfragments','bdb7rrdjwtdm','yes',NULL);
CREATE TABLE IF NOT EXISTS "collections" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "notes" text, "caption" text, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL, "collection_id" integer, "slug" varchar, "public_id" varchar, "name_lower" varchar GENERATED ALWAYS AS (LOWER(name)) STORED, "creator_id" integer, "indexable" varchar, "ai_indexable" varchar, CONSTRAINT "fk_rails_63724415e9"
FOREIGN KEY ("collection_id")
REFERENCES "collections" ("id")
, CONSTRAINT "fk_rails_ab2fec83b3"
FOREIGN KEY ("creator_id")
REFERENCES "creators" ("id")
);
CREATE TABLE IF NOT EXISTS "fasp_client_providers" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "uuid" varchar, "name" varchar, "base_url" varchar, "server_id" varchar, "public_key" varchar, "ed25519_signing_key" varchar, "status" integer, "capabilities" json, "privacy_policy" json, "sign_in_url" varchar, "contact_email" varchar, "fediverse_account" varchar, "created_at" datetime(6) NOT NULL, "updated_at" datetime(6) NOT NULL);
INSERT INTO sqlite_sequence VALUES('taggings',0);
INSERT INTO sqlite_sequence VALUES('users',1);
INSERT INTO sqlite_sequence VALUES('comments',0);
INSERT INTO sqlite_sequence VALUES('oauth_access_grants',0);
INSERT INTO sqlite_sequence VALUES('oauth_access_tokens',0);
INSERT INTO sqlite_sequence VALUES('federails_actors',2);
INSERT INTO sqlite_sequence VALUES('model_files',0);
INSERT INTO sqlite_sequence VALUES('models',0);
INSERT INTO sqlite_sequence VALUES('creators',1);
INSERT INTO sqlite_sequence VALUES('collections',0);
INSERT INTO sqlite_sequence VALUES('roles',4);
INSERT INTO sqlite_sequence VALUES('libraries',6);
INSERT INTO sqlite_sequence VALUES('settings',17);
INSERT INTO sqlite_sequence VALUES('caber_relations',2);
INSERT INTO sqlite_sequence VALUES('links',1);
INSERT INTO sqlite_sequence VALUES('federails_activities',1);
CREATE UNIQUE INDEX "index_tags_on_name" ON "tags" ("name");
CREATE UNIQUE INDEX "taggings_idx" ON "taggings" ("tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type");
CREATE INDEX "taggings_taggable_context_idx" ON "taggings" ("taggable_id", "taggable_type", "context");
CREATE INDEX "index_taggings_on_taggable_type" ON "taggings" ("taggable_type");
CREATE INDEX "index_taggings_on_context" ON "taggings" ("context");
CREATE INDEX "index_taggings_on_tagger_id_and_tagger_type" ON "taggings" ("tagger_id", "tagger_type");
CREATE INDEX "taggings_idy" ON "taggings" ("taggable_id", "taggable_type", "tagger_id", "context");
CREATE INDEX "index_links_on_linkable" ON "links" ("linkable_type", "linkable_id");
CREATE UNIQUE INDEX "index_settings_on_var" ON "settings" ("var");
CREATE INDEX "index_problems_on_problematic" ON "problems" ("problematic_type", "problematic_id");
CREATE INDEX "index_favorites_on_favoritor" ON "favorites" ("favoritor_type", "favoritor_id");
CREATE INDEX "index_favorites_on_scope" ON "favorites" ("scope");
CREATE INDEX "index_favorites_on_blocked" ON "favorites" ("blocked");
CREATE INDEX "fk_favorites" ON "favorites" ("favoritor_id", "favoritor_type");
CREATE INDEX "fk_favoritables" ON "favorites" ("favoritable_id", "favoritable_type");
CREATE UNIQUE INDEX "uniq_favorites__and_favoritables" ON "favorites" ("favoritable_type", "favoritable_id", "favoritor_type", "favoritor_id", "scope");
CREATE UNIQUE INDEX "index_problems_on_category_and_problematic_id_and_type" ON "problems" ("category", "problematic_id", "problematic_type");
CREATE UNIQUE INDEX "index_flipper_features_on_key" ON "flipper_features" ("key");
CREATE UNIQUE INDEX "index_flipper_gates_on_feature_key_and_key_and_value" ON "flipper_gates" ("feature_key", "key", "value");
CREATE INDEX "index_roles_on_resource" ON "roles" ("resource_type", "resource_id");
CREATE INDEX "index_users_roles_on_role_id" ON "users_roles" ("role_id");
CREATE INDEX "index_roles_on_name_and_resource_type_and_resource_id" ON "roles" ("name", "resource_type", "resource_id");
CREATE INDEX "index_users_roles_on_user_id_and_role_id" ON "users_roles" ("user_id", "role_id");
CREATE UNIQUE INDEX "index_users_on_email" ON "users" ("email");
CREATE UNIQUE INDEX "index_users_on_username" ON "users" ("username");
CREATE UNIQUE INDEX "index_users_on_reset_password_token" ON "users" ("reset_password_token");
CREATE INDEX "index_federails_followings_on_target_actor_id" ON "federails_followings" ("target_actor_id");
CREATE UNIQUE INDEX "index_federails_followings_on_actor_id_and_target_actor_id" ON "federails_followings" ("actor_id", "target_actor_id");
CREATE INDEX "index_federails_activities_on_entity" ON "federails_activities" ("entity_type", "entity_id");
CREATE INDEX "index_federails_activities_on_actor_id" ON "federails_activities" ("actor_id");
CREATE INDEX "index_caber_relations_on_subject" ON "caber_relations" ("subject_type", "subject_id");
CREATE INDEX "index_caber_relations_on_object" ON "caber_relations" ("object_type", "object_id");
CREATE UNIQUE INDEX "idx_on_subject_id_subject_type_object_id_object_typ_a279b094be" ON "caber_relations" ("subject_id", "subject_type", "object_id", "object_type");
CREATE INDEX "index_problems_on_public_id" ON "problems" ("public_id");
CREATE INDEX "index_libraries_on_public_id" ON "libraries" ("public_id");
CREATE UNIQUE INDEX "index_federails_activities_on_uuid" ON "federails_activities" ("uuid");
CREATE UNIQUE INDEX "index_federails_followings_on_uuid" ON "federails_followings" ("uuid");
CREATE INDEX "index_users_on_public_id" ON "users" ("public_id");
CREATE INDEX "index_users_on_approved" ON "users" ("approved");
CREATE INDEX "index_federails_moderation_reports_on_federails_actor_id" ON "federails_moderation_reports" ("federails_actor_id");
CREATE INDEX "index_federails_moderation_reports_on_object" ON "federails_moderation_reports" ("object_type", "object_id");
CREATE UNIQUE INDEX "index_federails_moderation_domain_blocks_on_domain" ON "federails_moderation_domain_blocks" ("domain");
CREATE UNIQUE INDEX "index_comments_on_public_id" ON "comments" ("public_id");
CREATE INDEX "index_comments_on_commenter" ON "comments" ("commenter_type", "commenter_id");
CREATE INDEX "index_comments_on_commentable" ON "comments" ("commentable_type", "commentable_id");
CREATE INDEX "index_comments_on_federails_actor_id" ON "comments" ("federails_actor_id");
CREATE UNIQUE INDEX "index_oauth_applications_on_uid" ON "oauth_applications" ("uid");
CREATE INDEX "index_oauth_access_grants_on_resource_owner_id" ON "oauth_access_grants" ("resource_owner_id");
CREATE INDEX "index_oauth_access_grants_on_application_id" ON "oauth_access_grants" ("application_id");
CREATE UNIQUE INDEX "index_oauth_access_grants_on_token" ON "oauth_access_grants" ("token");
CREATE INDEX "index_oauth_access_tokens_on_resource_owner_id" ON "oauth_access_tokens" ("resource_owner_id");
CREATE INDEX "index_oauth_access_tokens_on_application_id" ON "oauth_access_tokens" ("application_id");
CREATE UNIQUE INDEX "index_oauth_access_tokens_on_token" ON "oauth_access_tokens" ("token");
CREATE UNIQUE INDEX "index_oauth_access_tokens_on_refresh_token" ON "oauth_access_tokens" ("refresh_token");
CREATE INDEX "index_oauth_applications_on_owner_id_and_owner_type" ON "oauth_applications" ("owner_id", "owner_type");
CREATE UNIQUE INDEX "index_federails_actors_on_federated_url" ON "federails_actors" ("federated_url");
CREATE UNIQUE INDEX "index_federails_actors_on_entity" ON "federails_actors" ("entity_type", "entity_id");
CREATE UNIQUE INDEX "index_federails_actors_on_uuid" ON "federails_actors" ("uuid");
CREATE INDEX "index_model_files_on_model_id" ON "model_files" ("model_id");
CREATE INDEX "index_model_files_on_digest" ON "model_files" ("digest");
CREATE INDEX "index_model_files_on_presupported_version_id" ON "model_files" ("presupported_version_id");
CREATE UNIQUE INDEX "index_model_files_on_filename_and_model_id" ON "model_files" ("filename", "model_id");
CREATE INDEX "index_model_files_on_public_id" ON "model_files" ("public_id");
CREATE INDEX "index_model_files_on_filename_lower" ON "model_files" ("filename_lower");
CREATE INDEX "index_links_on_linkable_id_and_linkable_type_and_url" ON "links" ("linkable_id", "linkable_type", "url");
CREATE UNIQUE INDEX "index_altcha_solutions" ON "altcha_solutions" ("algorithm", "challenge", "salt", "signature", "number");
CREATE INDEX "index_models_on_library_id" ON "models" ("library_id");
CREATE INDEX "index_models_on_creator_id" ON "models" ("creator_id");
CREATE INDEX "index_models_on_preview_file_id" ON "models" ("preview_file_id");
CREATE INDEX "index_models_on_collection_id" ON "models" ("collection_id");
CREATE INDEX "index_models_on_slug" ON "models" ("slug");
CREATE UNIQUE INDEX "index_models_on_path_and_library_id" ON "models" ("path", "library_id");
CREATE INDEX "index_models_on_public_id" ON "models" ("public_id");
CREATE INDEX "index_models_on_name_lower" ON "models" ("name_lower");
CREATE UNIQUE INDEX "index_creators_on_name" ON "creators" ("name");
CREATE UNIQUE INDEX "index_creators_on_slug" ON "creators" ("slug");
CREATE INDEX "index_creators_on_public_id" ON "creators" ("public_id");
CREATE INDEX "index_creators_on_name_lower" ON "creators" ("name_lower");
CREATE INDEX "index_collections_on_collection_id" ON "collections" ("collection_id");
CREATE UNIQUE INDEX "index_collections_on_name" ON "collections" ("name");
CREATE UNIQUE INDEX "index_collections_on_slug" ON "collections" ("slug");
CREATE INDEX "index_collections_on_public_id" ON "collections" ("public_id");
CREATE INDEX "index_collections_on_name_lower" ON "collections" ("name_lower");
CREATE INDEX "index_collections_on_creator_id" ON "collections" ("creator_id");
CREATE INDEX "index_models_on_created_at" ON "models" ("created_at");
CREATE INDEX "index_models_on_updated_at" ON "models" ("updated_at");
CREATE INDEX "index_creators_on_created_at" ON "creators" ("created_at");
CREATE INDEX "index_creators_on_updated_at" ON "creators" ("updated_at");
CREATE INDEX "index_collections_on_created_at" ON "collections" ("created_at");
CREATE INDEX "index_collections_on_updated_at" ON "collections" ("updated_at");
CREATE INDEX "index_links_on_url" ON "links" ("url");
COMMIT;

View file

@ -2,5 +2,5 @@
test -z "$GODOT_VERSION" && exit 0 # nothing to do test -z "$GODOT_VERSION" && exit 0 # nothing to do
wget "https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}/Godot_v${GODOT_VERSION}_web_editor.zip" -O /root/godot.zip wget "https://github.com/godotengine/godot/releases/download/${GODOT_VERSION}/Godot_v${GODOT_VERSION}_web_editor.zip" -O /root/godot.zip
cd /usr/src/app/public/godot cd /usr/src/app/public/godot
unzip /root/godot.zip unzip -o /root/godot.zip
cp index.override.html index.html # make index.html autoload a manyfold zip-file (passed via HTTP query) cp index.override.html index.html # make index.html autoload a manyfold zip-file (passed via HTTP query)

View file

@ -0,0 +1,2 @@
#!/bin/sh
/manyfold/cli/manyfold.sh init_database

View file

@ -2,4 +2,4 @@
cd "$(dirname $1)" cd "$(dirname $1)"
echo "[v] scan (new) files of model" echo "[v] scan (new) files of model"
id="$(basename "$dir" | sed 's/\#//g')" id="$(basename "$dir" | sed 's/\#//g')"
#echo "Model.find(id).add_new_files_later()" | /usr/src/app/bin/rails console echo "Model.find(id).add_new_files_later()" | /usr/src/app/bin/rails console

View file

@ -1,5 +0,0 @@
#!/bin/sh
dir="$(dirname $1)"
cd "$dir"
echo "[package_experience.sh] zipping experience.zip"
zip -D ".xrforge/experience.zip * | tee -a .xrforge/log.txt

View file

View file

@ -19,6 +19,8 @@ begin
# Read and parse the JSON file # Read and parse the JSON file
data = JSON.parse( File.read( "datapackage.json" ) ) data = JSON.parse( File.read( "datapackage.json" ) )
#if data['keywords'].empty? || data['keywords'].include?('janusxr')
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" ) logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
XRForge.log("✅ starting build janusXR XR scene", logfile) XRForge.log("✅ starting build janusXR XR scene", logfile)
@ -61,15 +63,7 @@ begin
# Define the HTML content using a multi-line string (heredoc) # Define the HTML content using a multi-line string (heredoc)
# Ruby's heredoc allows for variable interpolation (using #{}) # Ruby's heredoc allows for variable interpolation (using #{})
jml = <<~HTML jml = <<~JML
<!DOCTYPE html>
<html>
<head>
<title>janusxr room</title>
</head>
<body>
<script src="https://web.janusvr.com/janusweb.js"></script>
<janus-viewer>
<FireBoxRoom> <FireBoxRoom>
<Assets> <Assets>
<assetobject id="experience" src="#{federate_drive_host}/#{model_file.gsub("#","%23")}"/> <assetobject id="experience" src="#{federate_drive_host}/#{model_file.gsub("#","%23")}"/>
@ -78,19 +72,36 @@ begin
<object pos="0 0 0" collision_id="experience" id="experience" /> <object pos="0 0 0" collision_id="experience" id="experience" />
</Room> </Room>
</FireBoxRoom> </FireBoxRoom>
JML
html = <<~HTML
<!DOCTYPE html>
<html>
<head>
<title>janusxr room</title>
</head>
<body>
<script src="https://web.janusvr.com/janusweb.js"></script>
<janus-viewer>
#{jml}
</janus-viewer> </janus-viewer>
</body> </body>
</html> </html>
HTML HTML
# Write the content to the specified file File.write('.xrforge/janusxr.html', html)
# File.write is the concise equivalent of 'echo "$jml" > filename' File.write('.xrforge/scene.jml', jml)
File.write('.xrforge/janusxr.html', jml)
XRForge.log("✅ written janusxr.html", logfile)
XRForge.log("✅ generated scene.jml", logfile)
XRForge.log("✅ generated janusxr.html", logfile)
XRForge.log(" ", logfile) XRForge.log(" ", logfile)
# tag it!
if ! data['keywords'].include?('janusxr')
data['keywords'].push('janusxr')
File.write(file_path, JSON.pretty_generate(data) )
end
rescue Errno::ENOENT rescue Errno::ENOENT
puts "File #{filename} not found" puts "File #{filename} not found"
rescue JSON::ParserError rescue JSON::ParserError

View file

@ -0,0 +1,86 @@
#!/usr/bin/env ruby
require 'json'
require_relative './../../xrforge.rb'
# Check if a filename is provided
if ARGV.length != 1
puts "Usage: #{$0} <path/to/experience/somefile.xxx>"
exit 1
end
filename = ARGV[0]
begin
# Change the directory
dir = File.dirname(filename)
Dir.chdir( File.dirname(filename) )
# Read and parse the JSON file
data = JSON.parse( File.read( "datapackage.json" ) )
#if data['keywords'].empty? || data['keywords'].include?('mml')
logfile = File.join( File.dirname(filename), ".xrforge/log.txt" )
XRForge.log("✅ starting build mml XR scene", logfile)
# Extract the desired field (assuming the field is named 'model_file')
thumb_file = data['image']
XRForge.log("✅ thumbnail sidecar-file '#{thumb_file}' detected", logfile)
# Get the base name of the thumbnail file without its extension
base_name = File.basename(thumb_file, File.extname(thumb_file))
model_file = nil # Initialize model_file to nil
# Loop over the list of extensions
XRForge::MODEL_EXT.each do |ext|
# Construct the filename with the current extension
filename = "#{base_name}#{ext}"
# Check if the file exists
if File.exist?(filename)
XRForge.log("✅ 3D file '#{filename}' detected", logfile)
model_file = "#{dir.gsub("/mnt/","")}/#{filename}" # Store the found filename
break # Stop the loop once a file is found
else
# Log a message for the file that was not found, but don't stop
XRForge.log("⚠️ 3D file '#{filename}' not detected", logfile)
end
end
# Check if a model file was found after the loop
if model_file
XRForge.log("✅ Final model file: '#{model_file}'", logfile)
else
XRForge.log("❌ No suitable 3D file found for XR Fragments- / MML-compatible experience", logfile)
end
# Get the value of the environment variable FEDERATE_DRIVE_HOST
federate_drive_host = ENV['FEDERATE_DRIVE_HOST']
# https://viewer.mml.io/main/v1/?url=https%3A%2F%2Ffoo.org%2Fbar.mml
mml = <<~MML
<m-model src="#{federate_drive_host}/#{model_file.gsub("#","%23")}" anim-loop="true" anim-enabled="true"></m-model>
MML
File.write('.xrforge/scene.mml', mml)
XRForge.log("✅ generated scene.mml", logfile)
XRForge.log(" ", logfile)
# tag it!
if ! data['keywords'].include?('mml')
data['keywords'].push('mml')
File.write(file_path, JSON.pretty_generate(data) )
end
rescue Errno::ENOENT
puts "File #{filename} not found"
rescue JSON::ParserError
puts "Error parsing JSON from #{filename}"
rescue => e
puts "An error occurred: #{e.message}"
end

View file

@ -108,14 +108,13 @@ class Components::ModelCard < Components::Base
div class: "col" do div class: "col" do
#open_button #open_button
#whitespace #whitespace
a alt: "start a meeting at this location", href: ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/janusxr.html", target: "_blank", class: "btn btn-secondary btn-sm" do
i class: "bi bi-telephone"
end
whitespace
status_badges @model status_badges @model
end end
div class: "col col-auto" do div class: "col col-auto" do
i class: "bi bi-telephone"
whitespace
link_to "meeting", ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/janusxr.html", {
target:"_blank",
}
whitespace whitespace
BurgerMenu do BurgerMenu do
#DropdownItem(icon: "app", label: "Open in Godot Web" , path: "/godot/?url="+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/package_godot.zip", aria_label: translate("components.model_card.edit_button.label", name: @model.name), target: "_blank" ) #DropdownItem(icon: "app", label: "Open in Godot Web" , path: "/godot/?url="+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/package_godot.zip", aria_label: translate("components.model_card.edit_button.label", name: @model.name), target: "_blank" )

View file

@ -0,0 +1,32 @@
Features can be toggled via tags:<br>
<br>
<table class="table">
<tr>
<td>
<a class="badge rounded-pill bg-secondary tag">menu</a>
</td>
<td>
This will generate a navigator-menu <b>into</b> your main 3D file.<br>
The links can be edited <%= link_to "here", edit_model_path(@model) %>
</td>
</tr>
<tr>
<td>
<a class="badge rounded-pill bg-secondary tag">janusxr</a>
</td>
<td>
This generates an JanusXR address.<br>
<a href="https://janusxr.org/" target="_blank">JanusXR</a> is an Open Immersive Web-layer since 2015, which allows existing webpages to become spatial.<br>
It is Free and Opensource, and allows you to meet others in this experience (avatars, chat and voice etc).<br>
</td>
</tr>
<tr>
<td>
<a class="badge rounded-pill bg-secondary tag">mml</a>
</td>
<td>
This generates an MML address.<br>
Metaverse Markup Language (<a href="https://mml.io" target="_blank">MML</a>) is an open markup language used to define experiences.
</td>
</tr>
</table>

View file

@ -81,12 +81,18 @@
</tr> </tr>
<% end %> <% end %>
<% if ENV['FEDERATE_DRIVE_HOST'].present? %> <% if ENV['FEDERATE_DRIVE_HOST'].present? %>
<% if @model.tags.where(name: "janusxr" ).any? %>
<tr> <tr>
<td> <td>
<i class="bi bi-people" role="img"></i> <i class="bi bi-eye-fill" role="img"></i>
</td> </td>
<td> <td>
<%= link_to "JanusXR Metaverse", ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/janusxr.html" %> <%
fediURL = ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/janusxr.html"
%>
<%= link_to "JanusXR address", fediURL, target:"_blank" %>
<a href="" target="_blank"><i class="bi bi-link-45deg"></i></a>
<label for="toggle_janusxr"><i class="bi bi-info-circle"></i></label> <label for="toggle_janusxr"><i class="bi bi-info-circle"></i></label>
<div class="toggle-box"> <div class="toggle-box">
<input type="checkbox" id="toggle_janusxr" hidden> <input type="checkbox" id="toggle_janusxr" hidden>
@ -94,19 +100,53 @@
<i class="bi bi-arrow-90deg-up"></i>&nbsp; <i class="bi bi-arrow-90deg-up"></i>&nbsp;
<small> <small>
This is the JanusXR address.<br> This is the JanusXR address.<br>
<a href="https://janusxr.org/" target="_blank">JanusXR</a> is an established Metaverse since 2015.<br> <a href="https://janusxr.org/" target="_blank">JanusXR</a> is an Open Immersive Web-layer since 2015, which allows existing webpages to become spatial.<br>
It is Free and Opensource, and allows you to meet others in this experience (avatars, chat and voice etc). It is Free and Opensource, and allows you to meet others in this experience (avatars, chat and voice etc).<br>
</small> </small>
</div> </div>
</div> </div>
</td> </td>
</tr> </tr>
<%
# lets generate a JanusXR spatial layer for the current scene
jmlfile = @model.library.path+"/"+@model.path+"/.xrforge/scene.jml"
jml = ""
if File.exist?(jmlfile)
jml = File.read(jmlfile)
end
%>
<!-- JML (https://janusxr.org) spatial markup
<%== jml %>
-->
<% end %>
<% if @model.tags.where(name: "mml" ).any? %>
<tr> <tr>
<td> <td>
<i class="bi bi-file-zip" role="img"></i> <i class="bi bi-eye-fill" role="img"></i>
</td>
<td>
<%= link_to "MML address", "https://viewer.mml.io/main/v1/?url="+URI.encode_www_form_component(ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/scene.mml"), target:"_blank" %>
<a href="<%= ENV['FEDERATE_DRIVE_HOST']+"/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/scene.mml" %>" target="_blank"><i class="bi bi-link-45deg"></i></a>
<label for="toggle_mml"><i class="bi bi-info-circle"></i></label>
<div class="toggle-box">
<input type="checkbox" id="toggle_mml" hidden>
<div class="hidden-tooltip">
<i class="bi bi-arrow-90deg-up"></i>&nbsp;
<small>
This is the MML address.<br>
Metaverse Markup Language (<a href="https://mml.io" target="_blank">MML</a>) is an open markup language used to define experiences.
</small>
</div>
</div>
</td> </td>
<td><%= link_to "zip archive", "/"+@model.library.name+"/"+@model.path.gsub("#","%23")+"/.xrforge/experience.zip" %></td>
</tr> </tr>
<% end %>
<tr> <tr>
<td> <td>
<i class="bi bi-journal-check" role="img"></i> <i class="bi bi-journal-check" role="img"></i>
@ -121,19 +161,7 @@
<small> <small>
This is the build log of XR Forge.<br> This is the build log of XR Forge.<br>
When you add files, they are processed, validated (for <a href="https://xrfragment.org" target="_blank">XR Fragment</a> compliance).<br> When you add files, they are processed, validated (for <a href="https://xrfragment.org" target="_blank">XR Fragment</a> compliance).<br>
But also features can be toggled via tags:<br> <% render 'models/tags_info' %>
<br>
<table class="table">
<tr>
<td>
<a class="badge rounded-pill bg-secondary tag">menu</a>
</td>
<td>
This will generate a navigator-menu <b>into</b> your main 3D file.<br>
The links can be edited <%= link_to "here", edit_model_path(@model) %>
</td>
</tr>
</table>
</small> </small>
</div> </div>
</div> </div>
@ -161,6 +189,7 @@
</td> </td>
</tr> </tr>
<% end %> <% end %>
<% if @model.collection %> <% if @model.collection %>
<tr> <tr>
<td><%= icon "collection", Collection.model_name.human(count: 100) %></td> <td><%= icon "collection", Collection.model_name.human(count: 100) %></td>
@ -202,7 +231,18 @@
</tr> </tr>
<tr> <tr>
<td><%= icon "tag", t(".tags") %></td> <td><%= icon "tag", t(".tags") %></td>
<td><%= render "tag_list", tags: @model.tags.order(taggings_count: :desc, name: :asc), filter: @filter %></td> <td><%= render "tag_list", tags: @model.tags.order(taggings_count: :desc, name: :asc), filter: @filter %>
<label for="toggle_tags"><i class="bi bi-info-circle"></i></label>
<div class="toggle-box">
<input type="checkbox" id="toggle_tags" hidden>
<div class="hidden-tooltip" style="max-height:400px">
<i class="bi bi-arrow-90deg-up"></i>&nbsp;
<small>
<% render 'models/tags_info' %>
</small>
</div>
</div>
</td>
</tr> </tr>
<% if SiteSettings.social_enabled? %> <% if SiteSettings.social_enabled? %>
<tr> <tr>

View file

@ -0,0 +1,25 @@
#!/bin/sh
set -e
if [ -f tmp/pids/server.pid ]; then
rm tmp/pids/server.pid
fi
echo "Preparing database..."
bundle exec rails db:prepare:with_data
echo "run boot 'hook'"
/manyfold/cli/manyfold.sh hook boot &
echo "Setting database file ownership (SQLite3 only)..."
bundle exec rake db:chown
echo "Cleaning up old cache files..."
bundle exec rake tmp:cache:clear
echo "Setting temporary directory permissions..."
chown -R $PUID:$PGID tmp log
echo "Launching application..."
export RAILS_PORT=$PORT
export RAILS_LOG_TO_STDOUT=true
exec s6-setuidgid $PUID:$PGID "$@"

View file

@ -40,5 +40,6 @@ Rails.application.config.to_prepare do
end end
end end
end end
end end
end end

File diff suppressed because one or more lines are too long