#!/bin/bash # blueprint.zip # github.com/teamblueprint/main # prpl.wtf # This should allow Blueprint to run in Docker. Please note that changing the $FOLDER variable after running # the Blueprint installation script will not change anything in any files besides blueprint.sh. FOLDER="/var/www/pterodactyl" #; # If the version below does not match your downloaded version, please let us know. VERSION="alpha-SLX" # Allow non-default Pterodactyl installation folders. if [[ $_FOLDER != "" ]]; then if [[ ( ! -f "$FOLDER/.blueprint/extensions/blueprint/private/db/version" ) && ( $FOLDER == "/var/www/pterodactyl" ) ]]; then sed -i -E "s|FOLDER=\"/var/www/pterodactyl\" #;|FOLDER=\"$_FOLDER\" #;|g" "$_FOLDER"/blueprint.sh else echo "Variable cannot be replaced right now." exit 2 fi fi # Check for panels that are using Docker, which should have better support in the future. if [[ -f "/.dockerenv" ]]; then DOCKER="y" else DOCKER="n" fi if [[ -d "$FOLDER/blueprint" ]]; then mv $FOLDER/blueprint $FOLDER/.blueprint; fi if [[ $VERSION != "" ]]; then # This function makes sure some placeholders get replaced with the current Blueprint version. if [[ ! -f "$FOLDER/.blueprint/extensions/blueprint/private/db/version" ]]; then sed -E -i "s*::v*$VERSION*g" $FOLDER/app/BlueprintFramework/Services/PlaceholderService/BlueprintPlaceholderService.php sed -E -i "s*::v*$VERSION*g" $FOLDER/.blueprint/extensions/blueprint/public/index.html touch $FOLDER/.blueprint/extensions/blueprint/private/db/version fi fi # Write environment variables. export BLUEPRINT__FOLDER=$FOLDER export BLUEPRINT__VERSION=$VERSION export BLUEPRINT__DEBUG="$FOLDER"/.blueprint/extensions/blueprint/private/debug/logs.txt export NODE_OPTIONS=--openssl-legacy-provider # Automatically navigate to the Pterodactyl directory when running the core. cd $FOLDER || return # Import libraries. source .blueprint/lib/bash_colors.sh || missinglibs+="[bash_colors]" source .blueprint/lib/parse_yaml.sh || missinglibs+="[parse_yaml]" source .blueprint/lib/db.sh || missinglibs+="[db]" source .blueprint/lib/telemetry.sh || missinglibs+="[telemetry]" source .blueprint/lib/updateAdminCacheReminder.sh || missinglibs+="[updateAdminCacheReminder]" source .blueprint/lib/grabenv.sh || missinglibs+="[grabenv]" source .blueprint/lib/throwError.sh || missinglibs+="[throwError]" source .blueprint/lib/logFormat.sh || missinglibs+="[logFormat]" # Fallback to these functions if "bash_colors.sh" is missing if [[ $missinglibs == *"[bash_colors]"* ]]; then log_reset() { echo -e "$1"; } log_reset_underline() { echo -e "$1"; } log_reset_reverse() { echo -e "$1"; } log_default() { echo -e "$1"; } log_defaultb () { echo -e "$1"; } log_bold() { echo -e "$1"; } log_bright() { echo -e "$1"; } log_underscore() { echo -e "$1"; } log_reverse() { echo -e "$1"; } log_black() { echo -e "$1"; } log_red() { echo -e "$1"; } log_green() { echo -e "$1"; } log_brown() { echo -e "$1"; } log_blue() { echo -e "$1"; } log_magenta() { echo -e "$1"; } log_cyan() { echo -e "$1"; } log_white() { echo -e "$1"; } log_yellow() { echo -e "$1"; } log_blackb() { echo -e "$1"; } log_redb() { echo -e "$1"; } log_greenb() { echo -e "$1"; } log_brownb() { echo -e "$1"; } log_blueb() { echo -e "$1"; } log_magentab() { echo -e "$1"; } log_cyanb() { echo -e "$1"; } log_whiteb() { echo -e "$1"; } log_yellowb() { echo -e "$1"; } fi # -config # usage: "cITEM=VALUE bash blueprint.sh -config" if [[ "$1" == "-config" ]]; then # cTELEMETRY_ID # Update the telemetry id. if [[ "$cTELEMETRY_ID" != "" ]]; then echo "$cTELEMETRY_ID" > .blueprint/extensions/blueprint/private/db/telemetry_id fi # cDEVELOPER # Enable/Disable developer mode. if [[ "$cDEVELOPER" != "" ]]; then if [[ "$cDEVELOPER" == "true" ]]; then dbAdd "blueprint.developerEnabled" else dbRemove "blueprint.developerEnabled" fi fi echo . exit 0 fi # Function that exits the script after logging a "red" message. throw() { throwError "$1"; exit 1; } depend() { # Check for incorrect node version. nodeVer=$(node -v) if [[ $nodeVer != "v17."* ]] \ && [[ $nodeVer != "v18."* ]] \ && [[ $nodeVer != "v19."* ]] \ && [[ $nodeVer != "v20."* ]] \ && [[ $nodeVer != "v21."* ]]; then DEPEND_MISSING=true fi # Check for required (both internal and external) dependencies. if \ ! [ -x "$(command -v unzip)" ] || # unzip ! [ -x "$(command -v node)" ] || # node ! [ -x "$(command -v yarn)" ] || # yarn ! [ -x "$(command -v zip)" ] || # zip ! [ -x "$(command -v curl)" ] || # curl ! [ -x "$(command -v php)" ] || # php ! [ -x "$(command -v git)" ] || # git ! [ -x "$(command -v grep)" ] || # grep ! [ -x "$(command -v sed)" ] || # sed ! [ -x "$(command -v awk)" ] || # awk ! [ "$(ls "node_modules/"*"cross-env"* 2> /dev/null)" ] || # cross-env ! [ "$(ls "node_modules/"*"webpack"* 2> /dev/null)" ] || # webpack ! [ "$(ls "node_modules/"*"react"* 2> /dev/null)" ] || # react [[ $missinglibs != "" ]]; then # internal DEPEND_MISSING=true fi # Exit when missing dependencies. if [[ $DEPEND_MISSING == true ]]; then PRINT FATAL "Some framework dependencies are not installed or detected." if [[ $nodeVer != "v18."* ]] \ && [[ $nodeVer != "v19."* ]] \ && [[ $nodeVer != "v20."* ]] \ && [[ $nodeVer != "v21."* ]]; then PRINT FATAL "Required dependency \"node\" is using an unsupported version." fi if ! [ -x "$(command -v unzip)" ]; then PRINT FATAL "Required dependency \"unzip\" is not installed or detected."; fi if ! [ -x "$(command -v node)" ]; then PRINT FATAL "Required dependency \"node\" is not installed or detected."; fi if ! [ -x "$(command -v yarn)" ]; then PRINT FATAL "Required dependency \"yarn\" is not installed or detected."; fi if ! [ -x "$(command -v zip)" ]; then PRINT FATAL "Required dependency \"zip\" is not installed or detected."; fi if ! [ -x "$(command -v curl)" ]; then PRINT FATAL "Required dependency \"curl\" is not installed or detected."; fi if ! [ -x "$(command -v php)" ]; then PRINT FATAL "Required dependency \"php\" is not installed or detected."; fi if ! [ -x "$(command -v git)" ]; then PRINT FATAL "Required dependency \"git\" is not installed or detected."; fi if ! [ -x "$(command -v grep)" ]; then PRINT FATAL "Required dependency \"grep\" is not installed or detected."; fi if ! [ -x "$(command -v sed)" ]; then PRINT FATAL "Required dependency \"sed\" is not installed or detected."; fi if ! [ -x "$(command -v awk)" ]; then PRINT FATAL "Required dependency \"awk\" is not installed or detected."; fi if ! [ "$(ls "node_modules/"*"cross-env"* 2> /dev/null)" ]; then PRINT FATAL "Required dependency \"cross-env\" is not installed or detected."; fi if ! [ "$(ls "node_modules/"*"webpack"* 2> /dev/null)" ]; then PRINT FATAL "Required dependency \"webpack\" is not installed or detected."; fi if ! [ "$(ls "node_modules/"*"react"* 2> /dev/null)" ]; then PRINT FATAL "Required dependency \"react\" is not installed or detected."; fi if [[ $missinglibs == *"[bash_colors]"* ]]; then PRINT FATAL "Required internal dependency \"internal:bash_colors\" is not installed or detected."; fi if [[ $missinglibs == *"[parse_yaml]"* ]]; then PRINT FATAL "Required internal dependency \"internal:parse_yaml\" is not installed or detected."; fi if [[ $missinglibs == *"[db]"* ]]; then PRINT FATAL "Required internal dependency \"internal:db\" is not installed or detected."; fi if [[ $missinglibs == *"[telemetry]"* ]]; then PRINT FATAL "Required internal dependency \"internal:telemetry\" is not installed or detected."; fi if [[ $missinglibs == *"[updateAdminCacheReminder]"* ]]; then PRINT FATAL "Required internal dependency \"internal:updateAdminCacheReminder\" is not installed or detected."; fi if [[ $missinglibs == *"[grabEnv]"* ]]; then PRINT FATAL "Required internal dependency \"internal:grabEnv\" is not installed or detected."; fi if [[ $missinglibs == *"[throwError]"* ]]; then PRINT FATAL "Required internal dependency \"internal:throwError\" is not installed or detected."; fi if [[ $missinglibs == *"[logFormat]"* ]]; then PRINT FATAL "Required internal dependency \"internal:logFormat\" is not installed or detected."; fi exit 1 fi } # Assign variables for extension flags. assignflags() { F_ignorePlaceholders=false F_ignoreAlphabetPlaceholders=false F_hasInstallScript=false F_hasRemovalScript=false F_hasExportScript=false F_developerIgnoreInstallScript=false F_developerIgnoreRebuild=false if [[ ( $flags == *"ignorePlaceholders,"* ) || ( $flags == *"ignorePlaceholders" ) ]]; then F_ignorePlaceholders=true ;fi if [[ ( $flags == *"ignoreAlphabetPlaceholders,"* ) || ( $flags == *"ignoreAlphabetPlaceholders" ) ]]; then F_ignoreAlphabetPlaceholders=true ;fi if [[ ( $flags == *"hasInstallScript,"* ) || ( $flags == *"hasInstallScript" ) ]]; then F_hasInstallScript=true ;fi if [[ ( $flags == *"hasRemovalScript,"* ) || ( $flags == *"hasRemovalScript" ) ]]; then F_hasRemovalScript=true ;fi if [[ ( $flags == *"hasExportScript,"* ) || ( $flags == *"hasExportScript" ) ]]; then F_hasExportScript=true ;fi if [[ ( $flags == *"developerIgnoreInstallScript,"* ) || ( $flags == *"developerIgnoreInstallScript" ) ]]; then F_developerIgnoreInstallScript=true ;fi if [[ ( $flags == *"developerIgnoreRebuild,"* ) || ( $flags == *"developerIgnoreRebuild" ) ]]; then F_developerIgnoreRebuild=true ;fi } # Adds the "blueprint" command to the /usr/local/bin directory and configures the correct permissions for it. touch /usr/local/bin/blueprint >> $BLUEPRINT__DEBUG echo -e "#!/bin/bash\nbash $FOLDER/blueprint.sh -bash \$@;" > /usr/local/bin/blueprint chmod u+x $FOLDER/blueprint.sh >> $BLUEPRINT__DEBUG chmod u+x /usr/local/bin/blueprint >> $BLUEPRINT__DEBUG if [[ $1 != "-bash" ]]; then if dbValidate "blueprint.setupFinished"; then PRINT FATAL "Installation process has already been finished before, consider using the 'blueprint' command." exit 2 else # Only run if Blueprint is not in the process of upgrading. if [[ $1 != "--post-upgrade" ]]; then log " ██\n██ ██\n ████\n"; # Blueprint "ascii" "logo". if [[ $DOCKER == "y" ]]; then PRINT WARNING "Docker is untested and you might run into issues." fi fi PRINT INFO "Searching and validating framework dependencies.." # Check if required programs are installed depend # Link directories. PRINT INFO "Linking directories and filesystems.." cd $FOLDER/public/extensions || throw 'cdMissingDirectory'; ln -s -T $FOLDER/.blueprint/extensions/blueprint/public blueprint 2>> $BLUEPRINT__DEBUG; cd $FOLDER || throw 'cdMissingDirectory' cd $FOLDER/public/assets/extensions || throw 'cdMissingDirectory'; ln -s -T $FOLDER/.blueprint/extensions/blueprint/assets blueprint 2>> $BLUEPRINT__DEBUG; cd $FOLDER || throw 'cdMissingDirectory' php artisan storage:link &>> $BLUEPRINT__DEBUG PRINT INFO "Replacing internal placeholders.." # Update folder placeholder on PlaceholderService and admin layout. sed -i "s!::f!$FOLDER!g" $FOLDER/app/BlueprintFramework/Services/PlaceholderService/BlueprintPlaceholderService.php sed -i "s!::f!$FOLDER!g" $FOLDER/resources/views/layouts/admin.blade.php # Copy "Blueprint" extension page logo from assets. cp $FOLDER/.blueprint/assets/logo.jpg $FOLDER/.blueprint/extensions/blueprint/assets/logo.jpg # Put application into maintenance. PRINT INFO "Put application into maintenance mode." php artisan down &>> $BLUEPRINT__DEBUG # Flush cache. PRINT INFO "Flushing view, config and route cache.." { php artisan view:clear php artisan config:clear php artisan route:cache } &>> $BLUEPRINT__DEBUG updateCacheReminder # Run migrations if Blueprint is not upgrading. if [[ $1 != "--post-upgrade" ]]; then PRINT INPUT "Would you like to migrate your database? (Y/n)" read -r YN if [[ ( $YN == "y"* ) || ( $YN == "Y"* ) || ( $YN == "" ) ]]; then PRINT INFO "Running database migrations.." php artisan migrate --force else PRINT INFO "Database migrations have been skipped." fi fi # Make sure all files have correct permissions. PRINT INFO "Changing Pterodactyl file ownership to 'www-data'.." chown -R www-data:www-data $FOLDER/* & chown -R www-data:www-data $FOLDER/.blueprint/* & wait # Rebuild panel assets. PRINT INFO "Rebuilding panel assets.." yarn run build:production # Put application into production. PRINT INFO "Put application into production." php artisan up &>> $BLUEPRINT__DEBUG # Sync some database values. PRINT INFO "Syncing Blueprint-related database values.." php artisan bp:sync # Finish installation if [[ $1 != "--post-upgrade" ]]; then PRINT SUCCESS "Blueprint has completed it's installation process." fi dbAdd "blueprint.setupFinished" # Let the panel know the user has finished installation. sed -i "s!NOTINSTALLED!INSTALLED!g" $FOLDER/app/BlueprintFramework/Services/PlaceholderService/BlueprintPlaceholderService.php exit 1 fi fi # -i, -install if [[ ( $2 == "-i" ) || ( $2 == "-install" ) ]]; then VCMD="y" if [[ $(( $# - 2 )) != 1 ]]; then PRINT FATAL "Expected 1 argument but got $(( $# - 2 )).";exit 2;fi if [[ ( $3 == "./"* ) || ( $3 == "../"* ) || ( $3 == "/"* ) ]]; then PRINT FATAL "Cannot import extensions from external paths.";exit 2;fi PRINT INFO "Searching and validating framework dependencies.." # Check if required programs are installed depend # The following code does some magic to allow for extensions with a # different root folder structure than expected by Blueprint. if [[ $3 == "test␀" ]]; then dev=true n="dev" mkdir -p ".blueprint/tmp/dev" cp -R ".blueprint/dev/"* ".blueprint/tmp/dev/" else dev=false n="$3" FILE="${n}.blueprint" if [[ ( $FILE == *".blueprint.blueprint" ) && ( $n == *".blueprint" ) ]]; then PRINT FATAL "Argument one in '-install' must not end with '.blueprint'.";exit 2; fi if [[ ! -f "$FILE" ]]; then PRINT FATAL "$FILE could not be found or detected.";exit 2;fi ZIP="${n}.zip" cp "$FILE" ".blueprint/tmp/$ZIP" cd ".blueprint/tmp" || throw 'cdMissingDirectory' unzip -o -qq "$ZIP" rm "$ZIP" if [[ ! -f "$n/*" ]]; then cd ".." || throw 'cdMissingDirectory' rm -R "tmp" mkdir -p "tmp" cd "tmp" || throw 'cdMissingDirectory' mkdir -p "./$n" cp "../../$FILE" "./$n/$ZIP" cd "$n" || throw 'cdMissingDirectory' unzip -o -qq "$ZIP" rm "$ZIP" cd ".." || throw 'cdMissingDirectory' fi fi # Return to the Pterodactyl installation folder. cd $FOLDER || throw 'cdMissingDirectory' # Get all strings from the conf.yml file and make them accessible as variables. if [[ ! -f ".blueprint/tmp/$n/conf.yml" ]]; then # Quit if the extension doesn't have a conf.yml file. rm -R ".blueprint/tmp/$n" PRINT FATAL "Extension configuration file not found or detected." exit 1 fi eval "$(parse_yaml .blueprint/tmp/"${n}"/conf.yml conf_)" # Add aliases for config values to make working with them easier. name="$conf_info_name" identifier="$conf_info_identifier" description="$conf_info_description" flags="$conf_info_flags" #(optional) version="$conf_info_version" target="$conf_info_target" author="$conf_info_author" #(optional) icon="$conf_info_icon" #(optional) website="$conf_info_website"; #(optional) admin_view="$conf_admin_view" admin_controller="$conf_admin_controller"; #(optional) admin_css="$conf_admin_css"; #(optional) admin_wrapper="$conf_admin_wrapper"; #(optional) dashboard_css="$conf_dashboard_css"; #(optional) dashboard_wrapper="$conf_dashboard_wrapper"; #(optional) dashboard_components="$conf_dashboard_components"; #(optional) data_directory="$conf_data_directory"; #(optional) data_public="$conf_data_public"; #(optional) database_migrations="$conf_database_migrations"; #(optional) # "prevent" folder "escaping" if [[ ( $icon == "/"* ) || ( $icon == *"/.."* ) || ( $icon == *"../"* ) || ( $icon == *"/../"* ) || ( $icon == *"\n"* ) ]] || [[ ( $admin_view == "/"* ) || ( $admin_view == *"/.."* ) || ( $admin_view == *"../"* ) || ( $admin_view == *"/../"* ) || ( $admin_view == *"\n"* ) ]] || [[ ( $admin_controller == "/"* ) || ( $admin_controller == *"/.."* ) || ( $admin_controller == *"../"* ) || ( $admin_controller == *"/../"* ) || ( $admin_controller == *"\n"* ) ]] || [[ ( $admin_css == "/"* ) || ( $admin_css == *"/.."* ) || ( $admin_css == *"../"* ) || ( $admin_css == *"/../"* ) || ( $admin_css == *"\n"* ) ]] || [[ ( $admin_wrapper == "/"* ) || ( $admin_wrapper == *"/.."* ) || ( $admin_wrapper == *"../"* ) || ( $admin_wrapper == *"/../"* ) || ( $admin_wrapper == *"\n"* ) ]] || [[ ( $dashboard_css == "/"* ) || ( $dashboard_css == *"/.."* ) || ( $dashboard_css == *"../"* ) || ( $dashboard_css == *"/../"* ) || ( $dashboard_css == *"\n"* ) ]] || [[ ( $dashboard_wrapper == "/"* ) || ( $dashboard_wrapper == *"/.."* ) || ( $dashboard_wrapper == *"../"* ) || ( $dashboard_wrapper == *"/../"* ) || ( $dashboard_wrapper == *"\n"* ) ]] || [[ ( $dashboard_components == "/"* ) || ( $dashboard_components == *"/.."* ) || ( $dashboard_components == *"../"* ) || ( $dashboard_components == *"/../"* ) || ( $dashboard_components == *"\n"* ) ]] || [[ ( $data_directory == "/"* ) || ( $data_directory == *"/.."* ) || ( $data_directory == *"../"* ) || ( $data_directory == *"/../"* ) || ( $data_directory == *"\n"* ) ]] || [[ ( $data_public == "/"* ) || ( $data_public == *"/.."* ) || ( $data_public == *"../"* ) || ( $data_public == *"/../"* ) || ( $data_public == *"\n"* ) ]] || [[ ( $database_migrations == "/"* ) || ( $database_migrations == *"/.."* ) || ( $database_migrations == *"../"* ) || ( $database_migrations == *"/../"* ) || ( $database_migrations == *"\n"* ) ]]; then rm -R ".blueprint/tmp/$n" PRINT FATAL "Config file paths cannot escape the extension bundle." exit 1 fi # prevent potentional problems during installation due to wrongly defined folders if [[ ( $dashboard_components == *"/" ) || ( $data_directory == *"/" ) || ( $data_public == *"/" ) || ( $database_migrations == *"/" ) ]]; then rm -R ".blueprint/tmp/$n" PRINT FATAL "Directory paths in conf.yml should not end with a slash." exit 1 fi # check if extension still has placeholder values if [[ ( $name == "␀name␀" ) || ( $identifier == "␀identifier␀" ) || ( $description == "␀description␀" ) ]] || [[ ( $version == "␀ver␀" ) || ( $target == "␀version␀" ) || ( $author == "␀author␀" ) ]]; then rm -R ".blueprint/tmp/$n" PRINT FATAL "Extension contains placeholder values which need to be replaced." exit 1 fi # Detect if extension is already installed and prepare the upgrading process. if [[ $(cat .blueprint/extensions/blueprint/private/db/installed_extensions) == *"$identifier,"* ]]; then PRINT INFO "Switching to update process as extension has already been installed." eval "$(parse_yaml .blueprint/extensions/"${identifier}"/private/.store/conf.yml old_)" DUPLICATE="y" if [[ ! -f ".blueprint/extensions/$identifier/private/.store/build/button.blade.php" ]]; then rm -R ".blueprint/tmp/$n" PRINT FATAL "Upgrading extension has failed due to missing essential .store files." exit 1 fi # Clean up some old extension files. if [[ $old_data_public != "" ]]; then # Clean up old public folder. rm -R ".blueprint/extensions/$identifier/public" mkdir ".blueprint/extensions/$identifier/public" fi fi # Assign variables to extension flags. PRINT INFO "Reading and assigning extension flags.." assignflags # Force http/https url scheme for extension website urls. if [[ $website != "" ]]; then if [[ ( $website != "https://"* ) && ( $website != "http://"* ) ]]; then website="http://${conf_info_website}" conf_info_website="${website}" fi # Change link icon depending on website url. websiteiconclass="bx-link-external" # git if [[ $website == *"://github.com/"* ]] || [[ $website == *"://www.github.com/"* ]] || [[ $website == *"://github.com" ]] || [[ $website == *"://www.github.com" ]] || [[ $website == *"://gitlab.com/"* ]] || [[ $website == *"://www.gitlab.com/"* ]] || [[ $website == *"://gitlab.com" ]] || [[ $website == *"://www.gitlab.com" ]]; then websiteiconclass="bx-git-branch";fi # marketplaces if [[ $website == *"://sourcexchange.net/"* ]] || [[ $website == *"://www.sourcexchange.net/"* ]] || [[ $website == *"://sourcexchange.net" ]] || [[ $website == *"://www.sourcexchange.net" ]] || [[ $website == *"://builtbybit.com/"* ]] || [[ $website == *"://www.builtbybit.com/"* ]] || [[ $website == *"://builtbybit.com" ]] || [[ $website == *"://www.builtbybit.com" ]] || [[ $website == *"://builtbyb.it/"* ]] || [[ $website == *"://www.builtbyb.it/"* ]] || [[ $website == *"://builtbyb.it" ]] || [[ $website == *"://www.builtbyb.it" ]]; then websiteiconclass="bx-store";fi # discord if [[ $website == *"://discord.com/"* ]] || [[ $website == *"://www.discord.com/"* ]] || [[ $website == *"://discord.com" ]] || [[ $website == *"://www.discord.com" ]] || [[ $website == *"://discord.gg/"* ]] || [[ $website == *"://www.discord.gg/"* ]] || [[ $website == *"://discord.gg" ]] || [[ $website == *"://www.discord.gg" ]]; then websiteiconclass="bxl-discord-alt";fi # patreon if [[ $website == *"://patreon.com/"* ]] || [[ $website == *"://www.patreon.com/"* ]] || [[ $website == *"://patreon.com" ]] || [[ $website == *"://www.patreon.com" ]]; then websiteiconclass="bxl-patreon";fi # reddit if [[ $website == *"://reddit.com/"* ]] || [[ $website == *"://www.reddit.com/"* ]] || [[ $website == *"://reddit.com" ]] || [[ $website == *"://www.reddit.com" ]]; then websiteiconclass="bxl-reddit";fi # trello if [[ $website == *"://trello.com/"* ]] || [[ $website == *"://www.trello.com/"* ]] || [[ $website == *"://trello.com" ]] || [[ $website == *"://www.trello.com" ]]; then websiteiconclass="bxl-trello";fi fi if [[ $dev == true ]]; then mv ".blueprint/tmp/$n" ".blueprint/tmp/$identifier" n=$identifier fi if ! $F_ignorePlaceholders; then # Prepare variables for placeholders PRINT INFO "Writing extension placeholders.." DIR=".blueprint/tmp/$n" INSTALLMODE="normal" installation_timestamp=$(date +%s) if [[ $dev == true ]]; then INSTALLMODE="developer"; fi EXTPUBDIR="$FOLDER/.blueprint/extensions/$identifier/public" if [[ $data_public == "" ]]; then EXTPUBDIR="null"; fi PLACE_PLACEHOLDERS() { local dir="$1" for file in "$dir"/*; do if [ -f "$file" ]; then file=${file// /\\ } sed -i "s~\^#version#\^~$version~g" "$file" sed -i "s~\^#author#\^~$author~g" "$file" sed -i "s~\^#name#\^~$name~g" "$file" sed -i "s~\^#identifier#\^~$identifier~g" "$file" sed -i "s~\^#path#\^~$FOLDER~g" "$file" sed -i "s~\^#datapath#\^~$FOLDER/.blueprint/extensions/$identifier/private~g" "$file" sed -i "s~\^#publicpath#\^~$EXTPUBDIR~g" "$file" sed -i "s~\^#installmode#\^~$INSTALLMODE~g" "$file" sed -i "s~\^#blueprintversion#\^~$VERSION~g" "$file" sed -i "s~\^#timestamp#\^~$installation_timestamp~g" "$file" sed -i "s~\^#componentroot#\^~@/blueprint/extensions/$identifier~g" "$file" if ! $F_ignoreAlphabetPlaceholders; then sed -i "s~__version__~$version~g" "$file" sed -i "s~__author__~$author~g" "$file" sed -i "s~__identifier__~$identifier~g" "$file" sed -i "s~__name__~$name~g" "$file" sed -i "s~__path__~$FOLDER~g" "$file" sed -i "s~__datapath__~$FOLDER/.blueprint/extensions/$identifier/private~g" "$file" sed -i "s~__publicpath__~$EXTPUBDIR~g" "$file" sed -i "s~__installmode__~$INSTALLMODE~g" "$file" sed -i "s~__blueprintversion__~$VERSION~g" "$file" sed -i "s~__timestamp__~$installation_timestamp~g" "$file" sed -i "s~__componentroot__~@/blueprint/extensions/$identifier~g" "$file" fi elif [ -d "$file" ]; then PLACE_PLACEHOLDERS "$file" fi done } PLACE_PLACEHOLDERS "$DIR" fi if [[ $name == "" ]]; then rm -R ".blueprint/tmp/$n"; PRINT FATAL "'info_name' is a required configuration option.";exit 1;fi if [[ $identifier == "" ]]; then rm -R ".blueprint/tmp/$n"; PRINT FATAL "'info_identifier' is a required configuration option.";exit 1;fi if [[ $description == "" ]]; then rm -R ".blueprint/tmp/$n"; PRINT FATAL "'info_description' is a required configuration option.";exit 1;fi if [[ $version == "" ]]; then rm -R ".blueprint/tmp/$n"; PRINT FATAL "'info_version' is a required configuration option.";exit 1;fi if [[ $target == "" ]]; then rm -R ".blueprint/tmp/$n"; PRINT FATAL "'info_target' is a required configuration option.";exit 1;fi if [[ $admin_view == "" ]]; then rm -R ".blueprint/tmp/$n"; PRINT FATAL "'admin_view' is a required configuration option.";exit 1;fi if [[ $icon == "" ]]; then PRINT WARNING "This extension does not come with an icon, consider adding one.";fi if [[ $target != "$VERSION" ]]; then PRINT WARNING "This extension is built for version $target, but your version is $VERSION.";fi if [[ $identifier != "$n" ]]; then rm -R ".blueprint/tmp/$n"; PRINT FATAL "Extension file name must be the same as your identifier. (example: identifier.blueprint)";exit 1;fi if ! [[ $identifier =~ [a-z] ]]; then rm -R ".blueprint/tmp/$n"; PRINT FATAL "Extension identifier should be lowercase and only contain characters a-z.";exit 1;fi if [[ $identifier == "blueprint" ]]; then rm -R ".blueprint/tmp/$n"; PRINT FATAL "Extensions can not have the identifier 'blueprint'.";exit 1;fi # Validate paths to files and directories defined in conf.yml. if [[ ( ! -f ".blueprint/tmp/$n/$icon" ) && ( ${icon} != "" ) ]] || # file: icon (optional) [[ ( ! -f ".blueprint/tmp/$n/$admin_view" ) ]] || # file: admin_view [[ ( ! -f ".blueprint/tmp/$n/$admin_controller" ) && ( ${admin_controller} != "" ) ]] || # file: admin_controller (optional) [[ ( ! -f ".blueprint/tmp/$n/$admin_css" ) && ( ${admin_css} != "" ) ]] || # file: admin_css (optional) [[ ( ! -f ".blueprint/tmp/$n/$admin_wrapper" ) && ( ${admin_wrapper} != "" ) ]] || # file: admin_wrapper (optional) [[ ( ! -f ".blueprint/tmp/$n/$dashboard_css" ) && ( ${dashboard_css} != "" ) ]] || # file: dashboard_css (optional) [[ ( ! -f ".blueprint/tmp/$n/$dashboard_wrapper" ) && ( ${dashboard_wrapper} != "" ) ]] || # file: dashboard_wrapper (optional) [[ ( ! -d ".blueprint/tmp/$n/$dashboard_components" ) && ( ${dashboard_components} != "" ) ]] || # folder: dashboard_components (optional) [[ ( ! -d ".blueprint/tmp/$n/$data_directory" ) && ( ${data_directory} != "" ) ]] || # folder: data_directory (optional) [[ ( ! -d ".blueprint/tmp/$n/$data_public" ) && ( ${data_public} != "" ) ]] || # folder: data_public (optional) [[ ( ! -d ".blueprint/tmp/$n/$data_migrations" ) && ( ${data_migrations} != "" ) ]];then # folder: data_migrations (optional) rm -R ".blueprint/tmp/$n" PRINT FATAL "Extension configuration points towards one or more files that do not exist." exit 1 fi # Validate custom script paths. if [[ $F_hasInstallScript == true || $F_hasRemovalScript == true || $F_hasExportScript == true ]]; then if [[ $data_directory == "" ]]; then rm -R ".blueprint/tmp/$n"; throw 'scriptsNoDataDir'; fi if [[ $F_hasInstallScript == true ]] && [[ ! -f ".blueprint/tmp/$n/$data_directory/install.sh" ]] || [[ $F_hasRemovalScript == true ]] && [[ ! -f ".blueprint/tmp/$n/$data_directory/remove.sh" ]] || [[ $F_hasExportScript == true ]] && [[ ! -f ".blueprint/tmp/$n/$data_directory/export.sh" ]]; then rm -R ".blueprint/tmp/$n" throw 'scriptsMissingFiles' fi fi # Place database migrations. if [[ $database_migrations != "" ]]; then PRINT INFO "Cloning database migration files.." cp -R ".blueprint/tmp/$n/$database_migrations/"* "database/migrations/" 2>> $BLUEPRINT__DEBUG fi # Create, link and connect components directory. if [[ $dashboard_components != "" ]]; then YARN="y" PRINT INFO "Cloning and linking components directory.." mkdir -p ".blueprint/extensions/$identifier/components" cd $FOLDER/resources/scripts/blueprint/extensions || throw 'cdMissingDirectory' ln -s -T $FOLDER/.blueprint/extensions/"$identifier"/components "$identifier" 2>> $BLUEPRINT__DEBUG cd $FOLDER || throw 'cdMissingDirectory' cp -R ".blueprint/tmp/$n/$dashboard_components/"* ".blueprint/extensions/$identifier/components/" 2>> $BLUEPRINT__DEBUG if [[ -f ".blueprint/tmp/$n/$dashboard_components/Components.yml" ]]; then # fetch component config eval "$(parse_yaml .blueprint/tmp/"$n"/"$dashboard_components"/Components.yml Components_)" if [[ $DUPLICATE == "y" ]]; then eval "$(parse_yaml .blueprint/extensions/"${identifier}"/private/.store/Components.yml OldComponents_)"; fi # define static variables to make stuff a bit easier im="\/\* blueprint\/import \*\/"; re="{/\* blueprint\/react \*/}"; co="resources/scripts/blueprint/components" s="import ${identifier^}Component from '"; e="';" PLACE_REACT() { if [[ ( $1 == "/"* ) || ( $1 == *"/.."* ) || ( $1 == *"../"* ) || ( $1 == *"/../"* ) || ( $1 == *"\n"* ) || ( $1 == *"@"* ) || ( $1 == *"\\"* ) ]]; then rm -R ".blueprint/tmp/$n" PRINT FATAL "Component file paths cannot escape the components folder." exit 1 fi if [[ $3 != "$1" ]]; then # remove old components sed -i "s~""${s}@/blueprint/extensions/${identifier}/$3${e}""~~g" "$co"/"$2" sed -i "s~""<${identifier^}Component />""~~g" "$co"/"$2" fi if [[ ! $1 == "" ]]; then # validate file name if [[ ${1} == *".tsx" ]] || [[ ${1} == *".ts" ]] || [[ ${1} == *".jsx" ]] || [[ ${1} == *".js" ]]; then rm -R ".blueprint/tmp/$n" PRINT FATAL "Component paths may not end with a file extension." exit 1 fi # validate path if [[ ! -f ".blueprint/tmp/$n/$dashboard_components/${1}.tsx" ]] && [[ ! -f ".blueprint/tmp/$n/$dashboard_components/${1}.ts" ]] && [[ ! -f ".blueprint/tmp/$n/$dashboard_components/${1}.jsx" ]] && [[ ! -f ".blueprint/tmp/$n/$dashboard_components/${1}.js" ]]; then rm -R ".blueprint/tmp/$n" PRINT FATAL "Components configuration points towards one or more files that do not exist." exit 1 fi # remove components sed -i "s~""${s}@/blueprint/extensions/${identifier}/$1${e}""~~g" "$co"/"$2" sed -i "s~""<${identifier^}Component />""~~g" "$co"/"$2" # add components sed -i "s~""$im""~""${im}${s}@/blueprint/extensions/${identifier}/$1${e}""~g" "$co"/"$2" sed -i "s~""$re""~""${re}\<${identifier^}Component /\>""~g" "$co"/"$2" fi } # place component items # -> PLACE_REACT "$Components_" "path/.tsx" "$OldComponents_" # navigation PLACE_REACT "$Components_Navigation_NavigationBar_BeforeNavigation" "Navigation/NavigationBar/BeforeNavigation.tsx" "$OldComponents_Navigation_NavigationBar_BeforeNavigation" PLACE_REACT "$Components_Navigation_NavigationBar_AdditionalItems" "Navigation/NavigationBar/AdditionalItems.tsx" "$OldComponents_Navigation_NavigationBar_AdditionalItems" PLACE_REACT "$Components_Navigation_NavigationBar_AfterNavigation" "Navigation/NavigationBar/AfterNavigation.tsx" "$OldComponents_Navigation_NavigationBar_AfterNavigation" PLACE_REACT "$Components_Navigation_SubNavigation_BeforeSubNavigation" "Navigation/SubNavigation/BeforeSubNavigation.tsx" "$OldComponents_Navigation_SubNavigation_BeforeSubNavigation" PLACE_REACT "$Components_Navigation_SubNavigation_AdditionalServerItems" "Navigation/SubNavigation/AdditionalServerItems.tsx" "$OldComponents_Navigation_SubNavigation_AdditionalServerItems" PLACE_REACT "$Components_Navigation_SubNavigation_AdditionalAccountItems" "Navigation/SubNavigation/AdditionalAccountItems.tsx" "$OldComponents_Navigation_SubNavigation_AdditionalAccountItems" PLACE_REACT "$Components_Navigation_SubNavigation_AfterSubNavigation" "Navigation/SubNavigation/AfterSubNavigation.tsx" "$OldComponents_Navigation_SubNavigation_AfterSubNavigation" # dashboard PLACE_REACT "$Components_Dashboard_ServerRow_BeforeEntryName" "Dashboard/ServerRow/BeforeEntryName.tsx" "$OldComponents_Dashboard_ServerRow_BeforeEntryName" PLACE_REACT "$Components_Dashboard_ServerRow_AfterEntryName" "Dashboard/ServerRow/AfterEntryName.tsx" "$OldComponents_Dashboard_ServerRow_AfterEntryName" PLACE_REACT "$Components_Dashboard_ServerRow_BeforeEntryDescription" "Dashboard/ServerRow/BeforeEntryDescription.tsx" "$OldComponents_Dashboard_ServerRow_BeforeEntryDescription" PLACE_REACT "$Components_Dashboard_ServerRow_AfterEntryDescription" "Dashboard/ServerRow/AfterEntryDescription.tsx" "$OldComponents_Dashboard_ServerRow_AfterEntryDescription" PLACE_REACT "$Components_Dashboard_ServerRow_ResourceLimits" "Dashboard/ServerRow/ResourceLimits.tsx" "$OldComponents_Dashboard_ServerRow_ResourceLimits" # server PLACE_REACT "$Components_Server_Terminal_BeforeContent" "Server/Terminal/BeforeContent.tsx" "$OldComponents_Server_Terminal_BeforeContent" PLACE_REACT "$Components_Server_Terminal_AfterContent" "Server/Terminal/AfterContent.tsx" "$OldComponents_Server_Terminal_AfterContent" PLACE_REACT "$Components_Server_Files_Browse_BeforeContent" "Server/Files/Browse/BeforeContent.tsx" "$OldComponents_Server_Files_Browse_BeforeContent" PLACE_REACT "$Components_Server_Files_Browse_FileButtons" "Server/Files/Browse/FileButtons.tsx" "$OldComponents_Server_Files_Browse_FileButtons" PLACE_REACT "$Components_Server_Files_Browse_DropdownItems" "Server/Files/Browse/DropdownItems.tsx" "$OldComponents_Server_Files_Browse_DropdownItems" PLACE_REACT "$Components_Server_Files_Browse_AfterContent" "Server/Files/Browse/AfterContent.tsx" "$OldComponents_Server_Files_Browse_AfterContent" PLACE_REACT "$Components_Server_Files_Edit_BeforeEdit" "Server/Files/Edit/BeforeEdit.tsx" "$OldComponents_Server_Files_Edit_BeforeEdit" PLACE_REACT "$Components_Server_Files_Edit_AfterEdit" "Server/Files/Edit/AfterEdit.tsx" "$OldComponents_Server_Files_Edit_AfterEdit" PLACE_REACT "$Components_Server_Databases_BeforeContent" "Server/Databases/BeforeContent.tsx" "$OldComponents_Server_Databases_BeforeContent" PLACE_REACT "$Components_Server_Databases_AfterContent" "Server/Databases/AfterContent.tsx" "$OldComponents_Server_Databases_AfterContent" PLACE_REACT "$Components_Server_Schedules_List_BeforeContent" "Server/Schedules/List/BeforeContent.tsx" "$OldComponents_Server_Schedules_List_BeforeContent" PLACE_REACT "$Components_Server_Schedules_List_AfterContent" "Server/Schedules/List/AfterContent.tsx" "$OldComponents_Server_Schedules_List_AfterContent" PLACE_REACT "$Components_Server_Schedules_Edit_BeforeEdit" "Server/Schedules/Edit/BeforeEdit.tsx" "$OldComponents_Server_Schedules_Edit_BeforeEdit" PLACE_REACT "$Components_Server_Schedules_Edit_AfterEdit" "Server/Schedules/Edit/AfterEdit.tsx" "$OldComponents_Server_Schedules_Edit_AfterEdit" PLACE_REACT "$Components_Server_Users_BeforeContent" "Server/Users/BeforeContent.tsx" "$OldComponents_Server_Users_BeforeContent" PLACE_REACT "$Components_Server_Users_AfterContent" "Server/Users/AfterContent.tsx" "$OldComponents_Server_Users_AfterContent" PLACE_REACT "$Components_Server_Backups_BeforeContent" "Server/Backups/BeforeContent.tsx" "$OldComponents_Server_Backups_BeforeContent" PLACE_REACT "$Components_Server_Backups_DropdownItems" "Server/Backups/DropdownItems.tsx" "$OldComponents_Server_Backups_DropdownItems" PLACE_REACT "$Components_Server_Backups_AfterContent" "Server/Backups/AfterContent.tsx" "$OldComponents_Server_Backups_AfterContent" PLACE_REACT "$Components_Server_Network_BeforeContent" "Server/Network/BeforeContent.tsx" "$OldComponents_Server_Network_BeforeContent" PLACE_REACT "$Components_Server_Network_AfterContent" "Server/Network/AfterContent.tsx" "$OldComponents_Server_Network_AfterContent" PLACE_REACT "$Components_Server_Startup_BeforeContent" "Server/Startup/BeforeContent.tsx" "$OldComponents_Server_Startup_BeforeContent" PLACE_REACT "$Components_Server_Startup_AfterContent" "Server/Startup/AfterContent.tsx" "$OldComponents_Server_Startup_AfterContent" PLACE_REACT "$Components_Server_Settings_BeforeContent" "Server/Settings/BeforeContent.tsx" "$OldComponents_Server_Settings_BeforeContent" PLACE_REACT "$Components_Server_Settings_AfterContent" "Server/Settings/AfterContent.tsx" "$OldComponents_Server_Settings_AfterContent" # account PLACE_REACT "$Components_Account_Overview_BeforeContent" "Account/Overview/BeforeContent.tsx" "$OldComponents_Account_Overview_BeforeContent" PLACE_REACT "$Components_Account_Overview_AfterContent" "Account/Overview/AfterContent.tsx" "$OldComponents_Account_Overview_AfterContent" PLACE_REACT "$Components_Account_API_BeforeContent" "Account/API/BeforeContent.tsx" "$OldComponents_Account_API_BeforeContent" PLACE_REACT "$Components_Account_API_AfterContent" "Account/API/AfterContent.tsx" "$OldComponents_Account_API_AfterContent" PLACE_REACT "$Components_Account_SSH_BeforeContent" "Account/SSH/BeforeContent.tsx" "$OldComponents_Account_SSH_BeforeContent" PLACE_REACT "$Components_Account_SSH_AfterContent" "Account/SSH/AfterContent.tsx" "$OldComponents_Account_SSH_AfterContent" else # warn about missing components.yml file PRINT WARNING "Could not find '$dashboard_components/Components.yml', component extendability might be limited." fi fi # Create and link public directory. if [[ $data_public != "" ]]; then PRINT INFO "Cloning and linking public directory.." mkdir -p ".blueprint/extensions/$identifier/public" cd $FOLDER/public/extensions || throw 'cdMissingDirectory' ln -s -T $FOLDER/.blueprint/extensions/"$identifier"/public "$identifier" 2>> $BLUEPRINT__DEBUG cd $FOLDER || throw 'cdMissingDirectory' cp -R ".blueprint/tmp/$n/$data_public/"* ".blueprint/extensions/$identifier/public/" 2>> $BLUEPRINT__DEBUG fi if [[ $admin_controller == "" ]]; then controller_type="default" else controller_type="custom" fi # Prepare build files. cp ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php" ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak" 2>> $BLUEPRINT__DEBUG if [[ $controller_type == "default" ]]; then # use default controller when admin_controller is left blank cp ".blueprint/extensions/blueprint/private/build/extensions/controller.php" ".blueprint/extensions/blueprint/private/build/extensions/controller.php.bak" 2>> $BLUEPRINT__DEBUG fi cp ".blueprint/extensions/blueprint/private/build/extensions/route.php" ".blueprint/extensions/blueprint/private/build/extensions/route.php.bak" 2>> $BLUEPRINT__DEBUG cp ".blueprint/extensions/blueprint/private/build/extensions/button.blade.php" ".blueprint/extensions/blueprint/private/build/extensions/button.blade.php.bak" 2>> $BLUEPRINT__DEBUG # Start creating data directory. PRINT INFO "Cloning and linking private directory.." mkdir -p ".blueprint/extensions/$identifier/private" mkdir -p ".blueprint/extensions/$identifier/private/.store" if [[ $data_directory != "" ]]; then cp -R ".blueprint/tmp/$n/$data_directory/"* ".blueprint/extensions/$identifier/private/"; fi cp ".blueprint/tmp/$n/conf.yml" ".blueprint/extensions/$identifier/private/.store/conf.yml" #backup conf.yml if [[ -f ".blueprint/tmp/$n/$dashboard_components/Components.yml" ]]; then cp ".blueprint/tmp/$n/$dashboard_components/Components.yml" ".blueprint/extensions/$identifier/private/.store/Components.yml" #backup Components.yml fi # End creating data directory. # Link and create assets folder PRINT INFO "Linking and writing assets directory.." if [[ $DUPLICATE != "y" ]]; then # Create assets folder if the extension is not updating. mkdir .blueprint/extensions/"$identifier"/assets fi cd $FOLDER/public/assets/extensions || throw 'cdMissingDirectory' ln -s -T $FOLDER/.blueprint/extensions/"$identifier"/assets "$identifier" 2>> $BLUEPRINT__DEBUG cd $FOLDER || throw 'cdMissingDirectory' if [[ $icon == "" ]]; then # use random placeholder icon if extension does not # come with an icon. icnNUM=$(( 1 + RANDOM % 9 )) cp ".blueprint/assets/defaultExtensionLogo$icnNUM.jpg" ".blueprint/extensions/$identifier/assets/icon.jpg" else cp ".blueprint/tmp/$n/$icon" ".blueprint/extensions/$identifier/assets/icon.jpg" fi; ICON="/assets/extensions/$identifier/icon.jpg" CONTENT=$(cat .blueprint/tmp/"$n"/"$admin_view") if [[ $admin_css != "" ]]; then PRINT INFO "Cloning and linking admin css.." updateCacheReminder sed -i "s~@import url(/assets/extensions/$identifier/admin.style.css);~~g" ".blueprint/extensions/blueprint/assets/admin.extensions.css" echo -e "@import url(/assets/extensions/$identifier/admin.style.css);" >> ".blueprint/extensions/blueprint/assets/admin.extensions.css" cp ".blueprint/tmp/$n/$admin_css" ".blueprint/extensions/$identifier/assets/admin.style.css" fi if [[ $dashboard_css != "" ]]; then PRINT INFO "Cloning and linking dashboard css.." YARN="y" sed -i "s~@import url(./imported/$identifier.css);~~g" "resources/scripts/blueprint/css/extensions.css" echo -e "@import url(./imported/$identifier.css);" >> "resources/scripts/blueprint/css/extensions.css" cp ".blueprint/tmp/$n/$dashboard_css" "resources/scripts/blueprint/css/imported/$identifier.css" fi if [[ $name == *"~"* ]]; then PRINT WARNING "'name' contains '~' and may result in an error.";fi if [[ $description == *"~"* ]]; then PRINT WARNING "'description' contains '~' and may result in an error.";fi if [[ $version == *"~"* ]]; then PRINT WARNING "'version' contains '~' and may result in an error.";fi if [[ $CONTENT == *"~"* ]]; then PRINT WARNING "'CONTENT' contains '~' and may result in an error.";fi if [[ $ICON == *"~"* ]]; then PRINT WARNING "'ICON' contains '~' and may result in an error.";fi if [[ $identifier == *"~"* ]]; then PRINT WARNING "'identifier' contains '~' and may result in an error.";fi # Replace $name variables. sed -i "s~␀title␀~$name~g" ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak" sed -i "s~␀name␀~$name~g" ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak" sed -i "s~␀name␀~$name~g" ".blueprint/extensions/blueprint/private/build/extensions/button.blade.php.bak" # Replace $description variables. sed -i "s~␀description␀~$description~g" ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak" # Replace $version variables. sed -i "s~␀version␀~$version~g" ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak" sed -i "s~␀version␀~$version~g" ".blueprint/extensions/blueprint/private/build/extensions/button.blade.php.bak" # Replace $ICON variables. sed -i "s~␀icon␀~$ICON~g" ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak" # Replace $website variables. if [[ $website != "" ]]; then sed -i "s~␀website␀~$website~g" ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak" sed -i "s~~~g" ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak" sed -i "s~␀weblinkicon␀~$websiteiconclass~g" ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak" fi # Replace $identifier variables. if [[ $controller_type == "default" ]]; then sed -i "s~␀id␀~$identifier~g" ".blueprint/extensions/blueprint/private/build/extensions/controller.php.bak" fi sed -i "s~␀id␀~$identifier~g" ".blueprint/extensions/blueprint/private/build/extensions/route.php.bak" sed -i "s~␀id␀~$identifier~g" ".blueprint/extensions/blueprint/private/build/extensions/button.blade.php.bak" # Place extension admin view content into template. echo -e "$CONTENT\n@endsection" >> ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak" # Read final results. ADMINVIEW_RESULT=$(<.blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak) ADMINROUTE_RESULT=$(<.blueprint/extensions/blueprint/private/build/extensions/route.php.bak) ADMINBUTTON_RESULT=$(<.blueprint/extensions/blueprint/private/build/extensions/button.blade.php.bak) if [[ $controller_type == "default" ]]; then ADMINCONTROLLER_RESULT=$(<.blueprint/extensions/blueprint/private/build/extensions/controller.php.bak) fi ADMINCONTROLLER_NAME="${identifier}ExtensionController.php" # Place admin extension view. PRINT INFO "Cloning admin view.." mkdir -p "resources/views/admin/extensions/$identifier" touch "resources/views/admin/extensions/$identifier/index.blade.php" echo "$ADMINVIEW_RESULT" > "resources/views/admin/extensions/$identifier/index.blade.php" # Place admin extension view controller. PRINT INFO "Cloning admin controller.." mkdir -p "app/Http/Controllers/Admin/Extensions/$identifier" touch "app/Http/Controllers/Admin/Extensions/$identifier/$ADMINCONTROLLER_NAME" if [[ $controller_type == "default" ]]; then # Use custom view controller. touch "app/Http/Controllers/Admin/Extensions/$identifier/$ADMINCONTROLLER_NAME" echo "$ADMINCONTROLLER_RESULT" > "app/Http/Controllers/Admin/Extensions/$identifier/$ADMINCONTROLLER_NAME" else # Use default extension controller. cp .blueprint/tmp/"$n"/"$admin_controller" "app/Http/Controllers/Admin/Extensions/$identifier/$ADMINCONTROLLER_NAME" fi if [[ $DUPLICATE != "y" ]]; then # Place admin route if extension is not updating. PRINT INFO "Editing admin routes.." { echo " // $identifier:start"; echo "$ADMINROUTE_RESULT"; echo // "$identifier":stop; } >> "routes/admin.php" else # Replace old extensions page button if extension is updating. OLDBUTTON_RESULT=$(<.blueprint/extensions/"$identifier"/private/.store/build/button.blade.php) sed -i "s~$OLDBUTTON_RESULT~~g" "resources/views/admin/extensions.blade.php" fi sed -i "s~~$ADMINBUTTON_RESULT\n~g" "resources/views/admin/extensions.blade.php" # Place dashboard wrapper if [[ $dashboard_wrapper != "" ]]; then PRINT INFO "Cloning and injecting dashboard wrapper.." if [[ $DUPLICATE == "y" ]]; then sed -n -i "//{p; :a; N; //!ba; s/.*\n//}; p" "resources/views/templates/wrapper.blade.php" sed -i "s~~~g" "resources/views/templates/wrapper.blade.php" sed -i "s~~~g" "resources/views/templates/wrapper.blade.php" fi touch ".blueprint/tmp/$n/$dashboard_wrapper.BLUEPRINTBAK" cat <(echo "") ".blueprint/tmp/$n/$dashboard_wrapper" > ".blueprint/tmp/$n/$dashboard_wrapper.BLUEPRINTBAK" cp ".blueprint/tmp/$n/$dashboard_wrapper.BLUEPRINTBAK" ".blueprint/tmp/$n/$dashboard_wrapper" rm ".blueprint/tmp/$n/$dashboard_wrapper.BLUEPRINTBAK" echo -e "\n" >> ".blueprint/tmp/$n/$dashboard_wrapper" sed -i "/<\!-- wrapper:insert -->/r .blueprint/tmp/$n/$dashboard_wrapper" "resources/views/templates/wrapper.blade.php" fi # Place admin wrapper if [[ $admin_wrapper != "" ]]; then PRINT INFO "Cloning and injecting admin wrapper.." if [[ $DUPLICATE == "y" ]]; then sed -n -i "//{p; :a; N; //!ba; s/.*\n//}; p" "resources/views/layouts/admin.blade.php" sed -i "s~~~g" "resources/views/layouts/admin.blade.php" sed -i "s~~~g" "resources/views/layouts/admin.blade.php" fi touch ".blueprint/tmp/$n/$admin_wrapper.BLUEPRINTBAK" cat <(echo "") ".blueprint/tmp/$n/$admin_wrapper" > ".blueprint/tmp/$n/$admin_wrapper.BLUEPRINTBAK" cp ".blueprint/tmp/$n/$admin_wrapper.BLUEPRINTBAK" ".blueprint/tmp/$n/$admin_wrapper" rm ".blueprint/tmp/$n/$admin_wrapper.BLUEPRINTBAK" echo -e "\n" >> ".blueprint/tmp/$n/$admin_wrapper" sed -i "/<\!-- wrapper:insert -->/r .blueprint/tmp/$n/$admin_wrapper" "resources/views/layouts/admin.blade.php" fi # Create backup of generated values. mkdir -p ".blueprint/extensions/$identifier/private/.store/build" cp ".blueprint/extensions/blueprint/private/build/extensions/button.blade.php.bak" ".blueprint/extensions/$identifier/private/.store/build/button.blade.php" cp ".blueprint/extensions/blueprint/private/build/extensions/route.php.bak" ".blueprint/extensions/$identifier/private/.store/build/route.php" # Remove temporary build files. PRINT INFO "Cleaning up build files.." rm ".blueprint/extensions/blueprint/private/build/extensions/admin.blade.php.bak" if [[ $controller_type == "default" ]]; then rm ".blueprint/extensions/blueprint/private/build/extensions/controller.php.bak" fi rm ".blueprint/extensions/blueprint/private/build/extensions/route.php.bak" rm ".blueprint/extensions/blueprint/private/build/extensions/button.blade.php.bak" rm -R ".blueprint/tmp/$n" if [[ $database_migrations != "" ]]; then PRINT INPUT "Would you like to migrate your database? (Y/n)" read -r YN if [[ ( $YN == "y"* ) || ( $YN == "Y"* ) || ( $YN == "" ) ]]; then PRINT INFO "Running database migrations.." php artisan migrate --force else PRINT INFO "Database migrations have been skipped." fi fi if [[ $YARN == "y" ]]; then if ! [[ ( $F_developerIgnoreRebuild == true ) && ( $dev == true ) ]]; then PRINT INFO "Rebuilding panel assets.." yarn run build:production fi fi # Flush cache. PRINT INFO "Flushing view, config and route cache.." { php artisan view:clear php artisan config:clear php artisan route:cache } &>> $BLUEPRINT__DEBUG chown -R www-data:www-data "$FOLDER/.blueprint/extensions/$identifier/private" chmod --silent -R +x ".blueprint/extensions/"* 2>> $BLUEPRINT__DEBUG if [[ ( $F_developerIgnoreInstallScript == false ) || ( $dev != true ) ]]; then if $F_hasInstallScript; then PRINT WARNING "Extension uses a custom installation script, proceed with caution." chmod +x ".blueprint/extensions/$identifier/private/install.sh" # Run script while also parsing some useful variables for the install script to use. EXTENSION_IDENTIFIER="$identifier" \ EXTENSION_TARGET="$target" \ EXTENSION_VERSION="$version" \ PTERODACTYL_DIRECTORY="$FOLDER" \ BLUEPRINT_VERSION="$VERSION" \ BLUEPRINT_DEVELOPER="$dev" \ bash ".blueprint/extensions/$identifier/private/install.sh" echo -e "\e[0m\x1b[0m\033[0m" fi fi if [[ $DUPLICATE != "y" ]]; then PRINT INFO "Adding '$identifier' to active extensions list.." echo "${identifier}," >> ".blueprint/extensions/blueprint/private/db/installed_extensions" fi if [[ $dev != true ]]; then if [[ $DUPLICATE == "y" ]]; then PRINT SUCCESS "$identifier has been updated." else PRINT SUCCESS "$identifier has been installed." fi sendTelemetry "FINISH_EXTENSION_INSTALLATION" >> $BLUEPRINT__DEBUG elif [[ $dev == true ]]; then PRINT SUCCESS "$identifier has been built." sendTelemetry "BUILD_DEVELOPMENT_EXTENSION" >> $BLUEPRINT__DEBUG fi exit 0 # success fi # -r, -remove if [[ ( $2 == "-r" ) || ( $2 == "-remove" ) ]]; then VCMD="y" if [[ $(( $# - 2 )) != 1 ]]; then PRINT FATAL "Expected 1 argument but got $(( $# - 2 )).";exit 2;fi # Check if the extension is installed. if [[ $(cat ".blueprint/extensions/blueprint/private/db/installed_extensions") != *"$3,"* ]]; then PRINT FATAL "'$3' is not installed or detected." exit 2 fi if [[ -f ".blueprint/extensions/$3/private/.store/conf.yml" ]]; then eval "$(parse_yaml ".blueprint/extensions/$3/private/.store/conf.yml" conf_)" # Add aliases for config values to make working with them easier. name="$conf_info_name"; identifier="$conf_info_identifier" description="$conf_info_description" flags="$conf_info_flags" #(optional) version="$conf_info_version" target="$conf_info_target" author="$conf_info_author" #(optional) icon="$conf_info_icon" #(optional) website="$conf_info_website"; #(optional) admin_view="$conf_admin_view" admin_controller="$conf_admin_controller"; #(optional) admin_css="$conf_admin_css"; #(optional) admin_wrapper="$conf_admin_wrapper"; #(optional) dashboard_css="$conf_dashboard_css"; #(optional) dashboard_wrapper="$conf_dashboard_wrapper"; #(optional) dashboard_components="$conf_dashboard_components"; #(optional) data_directory="$conf_data_directory"; #(optional) data_public="$conf_data_public"; #(optional) database_migrations="$conf_database_migrations"; #(optional) else PRINT FATAL "Backup conf.yml could not be found." PRINT FATAL "Extension configuration file not found or detected." exit 1 fi PRINT INPUT "Do you want to proceed with this transaction? Some files might not be removed properly. (y/N)" read -r YN if [[ ( $YN == "n"* ) || ( $YN == "N"* ) || ( $YN == "" ) ]]; then PRINT INFO "Extension removal cancelled.";exit 1;fi PRINT INFO "Searching and validating framework dependencies.." depend # Assign variables to extension flags. PRINT INFO "Reading and assigning extension flags.." assignflags if $F_hasRemovalScript; then PRINT WARNING "Extension uses a custom removal script, proceed with caution." chmod +x ".blueprint/extensions/$identifier/private/remove.sh" # Run script while also parsing some useful variables for the uninstall script to use. EXTENSION_IDENTIFIER="$identifier" \ EXTENSION_TARGET="$target" \ EXTENSION_VERSION="$version" \ PTERODACTYL_DIRECTORY="$FOLDER" \ BLUEPRINT_VERSION="$VERSION" \ bash ".blueprint/extensions/$identifier/private/remove.sh" echo -e "\e[0m\x1b[0m\033[0m" fi # Remove admin button PRINT INFO "Editing 'extensions' admin page.." OLDBUTTON_RESULT=$(cat ".blueprint/extensions/$identifier/private/.store/build/button.blade.php") sed -i "s~$OLDBUTTON_RESULT~~g" "resources/views/admin/extensions.blade.php" # Remove admin routes PRINT INFO "Removing admin routes.." sed -n -i "/\/\/ $identifier:start/{p; :a; N; /\/\/ $identifier:stop/!ba; s/.*\n//}; p" "routes/admin.php" sed -i "s~// $identifier:start~~g" "routes/admin.php" sed -i "s~// $identifier:stop~~g" "routes/admin.php" # Remove admin view PRINT INFO "Removing admin view directory.." rm -r "resources/views/admin/extensions/$identifier" # Remove admin controller PRINT INFO "Removing admin controller directory.." rm -r "app/Http/Controllers/Admin/Extensions/$identifier" # Remove admin css if [[ $admin_css != "" ]]; then PRINT INFO "Removing and unlinking admin css.." updateCacheReminder sed -i "s~@import url(/assets/extensions/$identifier/admin.style.css);~~g" ".blueprint/extensions/blueprint/assets/admin.extensions.css" fi # Remove admin wrapper if [[ $admin_wrapper != "" ]]; then PRINT INFO "Removing admin wrapper.." sed -n -i "//{p; :a; N; //!ba; s/.*\n//}; p" "resources/views/layouts/admin.blade.php" sed -i "s~~~g" "resources/views/layouts/admin.blade.php" sed -i "s~~~g" "resources/views/layouts/admin.blade.php" fi # Remove dashboard wrapper if [[ $dashboard_wrapper != "" ]]; then PRINT INFO "Removing dashboard wrapper.." sed -n -i "//{p; :a; N; //!ba; s/.*\n//}; p" "resources/views/templates/wrapper.blade.php" sed -i "s~~~g" "resources/views/templates/wrapper.blade.php" sed -i "s~~~g" "resources/views/templates/wrapper.blade.php" fi # Remove dashboard css if [[ $dashboard_css != "" ]]; then PRINT INFO "Removing and unlinking dashboard css.." sed -i "s~@import url(./imported/$identifier.css);~~g" "resources/scripts/blueprint/css/extensions.css" rm "resources/scripts/blueprint/css/imported/$identifier.css" YARN="y" fi # Remove dashboard components if [[ $dashboard_components != "" ]]; then PRINT INFO "Removing and unlinking dashboard components.." rm -r $FOLDER/.blueprint/extensions/"$identifier"/components rm -r $FOLDER/resources/scripts/blueprint/extensions/"$identifier" # fetch component config eval "$(parse_yaml .blueprint/extensions/"$identifier"/components/Components.yml Components_)" # define static variables to make stuff a bit easier im="\/\* blueprint\/import \*\/"; re="{/\* blueprint\/react \*/}"; co="resources/scripts/blueprint/components" s="import ${identifier^}Component from '"; e="';" REMOVE_REACT() { if [[ ! $1 == "" ]]; then # remove components sed -i "s~""${s}@/blueprint/extensions/${identifier}/$1${e}""~~g" "$co"/"$2" sed -i "s~""<${identifier^}Component />""~~g" "$co"/"$2" fi } # remove component items # -> REMOVE_REACT "$Components_" "path/.tsx" "$OldComponents_" # navigation REMOVE_REACT "$Components_Navigation_NavigationBar_BeforeNavigation" "Navigation/NavigationBar/BeforeNavigation.tsx" REMOVE_REACT "$Components_Navigation_NavigationBar_AdditionalItems" "Navigation/NavigationBar/AdditionalItems.tsx" REMOVE_REACT "$Components_Navigation_NavigationBar_AfterNavigation" "Navigation/NavigationBar/AfterNavigation.tsx" REMOVE_REACT "$Components_Navigation_SubNavigation_BeforeSubNavigation" "Navigation/SubNavigation/BeforeSubNavigation.tsx" REMOVE_REACT "$Components_Navigation_SubNavigation_AdditionalServerItems" "Navigation/SubNavigation/AdditionalServerItems.tsx" REMOVE_REACT "$Components_Navigation_SubNavigation_AdditionalAccountItems" "Navigation/SubNavigation/AdditionalAccountItems.tsx" REMOVE_REACT "$Components_Navigation_SubNavigation_AfterSubNavigation" "Navigation/SubNavigation/AfterSubNavigation.tsx" # dashboard REMOVE_REACT "$Components_Dashboard_ServerRow_BeforeEntryName" "Dashboard/ServerRow/BeforeEntryName.tsx" REMOVE_REACT "$Components_Dashboard_ServerRow_AfterEntryName" "Dashboard/ServerRow/AfterEntryName.tsx" REMOVE_REACT "$Components_Dashboard_ServerRow_BeforeEntryDescription" "Dashboard/ServerRow/BeforeEntryDescription.tsx" REMOVE_REACT "$Components_Dashboard_ServerRow_AfterEntryDescription" "Dashboard/ServerRow/AfterEntryDescription.tsx" REMOVE_REACT "$Components_Dashboard_ServerRow_ResourceLimits" "Dashboard/ServerRow/ResourceLimits.tsx" # server REMOVE_REACT "$Components_Server_Terminal_BeforeContent" "Server/Terminal/BeforeContent.tsx" REMOVE_REACT "$Components_Server_Terminal_AfterContent" "Server/Terminal/AfterContent.tsx" REMOVE_REACT "$Components_Server_Files_Browse_BeforeContent" "Server/Files/Browse/BeforeContent.tsx" REMOVE_REACT "$Components_Server_Files_Browse_FileButtons" "Server/Files/Browse/FileButtons.tsx" REMOVE_REACT "$Components_Server_Files_Browse_DropdownItems" "Server/Files/Browse/DropdownItems.tsx" REMOVE_REACT "$Components_Server_Files_Browse_AfterContent" "Server/Files/Browse/AfterContent.tsx" REMOVE_REACT "$Components_Server_Files_Edit_BeforeEdit" "Server/Files/Edit/BeforeEdit.tsx" REMOVE_REACT "$Components_Server_Files_Edit_AfterEdit" "Server/Files/Edit/AfterEdit.tsx" REMOVE_REACT "$Components_Server_Databases_BeforeContent" "Server/Databases/BeforeContent.tsx" REMOVE_REACT "$Components_Server_Databases_AfterContent" "Server/Databases/AfterContent.tsx" REMOVE_REACT "$Components_Server_Schedules_List_BeforeContent" "Server/Schedules/List/BeforeContent.tsx" REMOVE_REACT "$Components_Server_Schedules_List_AfterContent" "Server/Schedules/List/AfterContent.tsx" REMOVE_REACT "$Components_Server_Schedules_Edit_BeforeEdit" "Server/Schedules/Edit/BeforeEdit.tsx" REMOVE_REACT "$Components_Server_Schedules_Edit_AfterEdit" "Server/Schedules/Edit/AfterEdit.tsx" REMOVE_REACT "$Components_Server_Users_BeforeContent" "Server/Users/BeforeContent.tsx" REMOVE_REACT "$Components_Server_Users_AfterContent" "Server/Users/AfterContent.tsx" REMOVE_REACT "$Components_Server_Backups_BeforeContent" "Server/Backups/BeforeContent.tsx" REMOVE_REACT "$Components_Server_Backups_DropdownItems" "Server/Backups/DropdownItems.tsx" REMOVE_REACT "$Components_Server_Backups_AfterContent" "Server/Backups/AfterContent.tsx" REMOVE_REACT "$Components_Server_Network_BeforeContent" "Server/Network/BeforeContent.tsx" REMOVE_REACT "$Components_Server_Network_AfterContent" "Server/Network/AfterContent.tsx" REMOVE_REACT "$Components_Server_Startup_BeforeContent" "Server/Startup/BeforeContent.tsx" REMOVE_REACT "$Components_Server_Startup_AfterContent" "Server/Startup/AfterContent.tsx" REMOVE_REACT "$Components_Server_Settings_BeforeContent" "Server/Settings/BeforeContent.tsx" REMOVE_REACT "$Components_Server_Settings_AfterContent" "Server/Settings/AfterContent.tsx" # account REMOVE_REACT "$Components_Account_Overview_BeforeContent" "Account/Overview/BeforeContent.tsx" REMOVE_REACT "$Components_Account_Overview_AfterContent" "Account/Overview/AfterContent.tsx" REMOVE_REACT "$Components_Account_API_BeforeContent" "Account/API/BeforeContent.tsx" REMOVE_REACT "$Components_Account_API_AfterContent" "Account/API/AfterContent.tsx" REMOVE_REACT "$Components_Account_SSH_BeforeContent" "Account/SSH/BeforeContent.tsx" REMOVE_REACT "$Components_Account_SSH_AfterContent" "Account/SSH/AfterContent.tsx" YARN="y" fi # Remove private folder PRINT INFO "Removing and unlinking private folder.." rm -R ".blueprint/extensions/$identifier/private" # Remove public folder if [[ $data_public != "" ]]; then PRINT INFO "Removing and unlinking public folder.." rm -R ".blueprint/extensions/$identifier/public" rm -R "public/extensions/$identifier" fi # Remove assets folder PRINT INFO "Removing and unlinking assets folder.." rm -R ".blueprint/extensions/$identifier/assets" rm -R "public/assets/extensions/$identifier" # Rebuild panel if [[ $YARN == "y" ]]; then PRINT INFO "Rebuilding panel assets.." yarn run build:production fi # Flush cache. PRINT INFO "Flushing view, config and route cache.." { php artisan view:clear php artisan config:clear php artisan route:cache } &>> $BLUEPRINT__DEBUG # Remove from installed list PRINT INFO "Removing '$identifier' from active extensions list.." sed -i "s~$identifier,~~g" ".blueprint/extensions/blueprint/private/db/installed_extensions" PRINT SUCCESS "'$identifier' has been removed." sendTelemetry "FINISH_EXTENSION_REMOVAL" >> $BLUEPRINT__DEBUG exit 0 # success fi # help, -help, --help, # h, -h, --h if [[ ( $2 == "help" ) || ( $2 == "-help" ) || ( $2 == "--help" ) || ( $2 == "h" ) || ( $2 == "-h" ) || ( $2 == "--h" ) || ( $2 == "" ) ]]; then VCMD="y" if dbValidate "blueprint.developerEnabled"; then help_dev_status="" help_dev_primary="\e[34;1m" help_dev_secondary="\e[34m" else help_dev_status=" (disabled)" help_dev_primary="\x1b[2;1m" help_dev_secondary="\x1b[2m" fi echo -e " \x1b[34;1mExtensions\x1b[0m\x1b[34m -install [name] -i install/update a blueprint extension -remove [name] -r remove a blueprint extension \x1b[0m ${help_dev_primary}Developer${help_dev_status}\x1b[0m${help_dev_secondary} -init -I initialize development files -build -b install/update your development files -export (expose) -e export/download your development files -wipe -w remove your development files \x1b[0m \x1b[34;1mMisc\x1b[0m\x1b[34m -version -v returns the blueprint version -help -h displays this menu -info -f show neofetch-like information about blueprint -debug [lines] print given amount of debug lines \x1b[0m \x1b[34;1mAdvanced\x1b[0m\x1b[34m -upgrade (dev) update/reset to a newer/development version -rerun-install rerun the blueprint installation script \x1b[0m " fi # -v, -version if [[ ( $2 == "-v" ) || ( $2 == "-version" ) ]]; then VCMD="y" echo -e ${VERSION} fi # -debug if [[ $2 == "-debug" ]]; then VCMD="y" if [[ $3 -lt 1 ]]; then PRINT FATAL "Provide the amount of debug lines to print as an argument, which must be greater than one (1)."; exit 2; fi echo -e "\x1b[30;47;1m --- DEBUG START --- \x1b[0m" echo -e "$(v="$(<.blueprint/extensions/blueprint/private/debug/logs.txt)";printf -- "%s" "$v"|tail -"$3")" echo -e "\x1b[30;47;1m --- DEBUG END --- \x1b[0m" fi # -init if [[ ( $2 == "-init" || $2 == "-I" ) ]]; then VCMD="y" # Check for developer mode through the database library. if ! dbValidate "blueprint.developerEnabled"; then PRINT FATAL "Developer mode is not enabled.";exit 2; fi # To prevent accidental wiping of your dev directory, you are unable to initialize another extension # until you wipe the contents of the .blueprint/dev directory. if [[ -n $(find .blueprint/dev -maxdepth 1 -type f -not -name ".gitkeep" -print -quit) ]]; then PRINT FATAL "Development directory contains files. To protect you against accidental data loss, you are unable to initialize another extension unless you clear the '.blueprint/dev' folder." exit 2 fi ask_template() { log_blue "[INPUT] Initial Template:" log_blue "$(curl 'https://raw.githubusercontent.com/teamblueprint/templates/main/repository' 2>> $BLUEPRINT__DEBUG)" read -r ASKTEMPLATE REDO_TEMPLATE=false # Template should not be empty if [[ ${ASKTEMPLATE} == "" ]]; then log_yellow "[WARNING] Template should not be empty." REDO_TEMPLATE=true fi # Unknown template. if [[ $(echo -e "$(curl "https://raw.githubusercontent.com/teamblueprint/templates/main/${ASKTEMPLATE}/TemplateConfiguration.yml" 2>> $BLUEPRINT__DEBUG)") == "404: Not Found" ]]; then log_yellow "[WARNING] Unknown template, please choose a valid option." REDO_TEMPLATE=true fi if [[ ${REDO_TEMPLATE} == true ]]; then # Ask again if response does not pass validation. ASKTEMPLATE="" ask_template fi } ask_name() { log_blue "[INPUT] Name (Generic Extension):" read -r ASKNAME REDO_NAME=false # Name should not be empty if [[ ${ASKNAME} == "" ]]; then log_yellow "[WARNING] Name should not be empty." REDO_NAME=true fi if [[ ${REDO_NAME} == true ]]; then # Ask again if response does not pass validation. ASKNAME="" ask_name fi } ask_identifier() { log_blue "[INPUT] Identifier (genericextension):" read -r ASKIDENTIFIER REDO_IDENTIFIER=false # Identifier should not be empty if [[ ${ASKIDENTIFIER} == "" ]]; then log_yellow "[WARNING] Identifier should not be empty." REDO_IDENTIFIER=true fi # Identifier should be a-z. if [[ ${ASKIDENTIFIER} =~ [a-z] ]]; then echo ok >> $BLUEPRINT__DEBUG else log_yellow "[WARNING] Identifier should only contain a-z characters." REDO_IDENTIFIER=true fi if [[ ${REDO_IDENTIFIER} == true ]]; then # Ask again if response does not pass validation. ASKIDENTIFIER="" ask_identifier fi } ask_description() { log_blue "[INPUT] Description (My awesome description):" read -r ASKDESCRIPTION REDO_DESCRIPTION=false # Description should not be empty if [[ ${ASKDESCRIPTION} == "" ]]; then log_yellow "[WARNING] Description should not be empty." REDO_DESCRIPTION=true fi if [[ ${REDO_DESCRIPTION} == true ]]; then # Ask again if response does not pass validation. ASKDESCRIPTION="" ask_description fi } ask_version() { log_blue "[INPUT] Version (indev):" read -r ASKVERSION REDO_VERSION=false # Version should not be empty if [[ ${ASKVERSION} == "" ]]; then log_yellow "[WARNING] Version should not be empty." REDO_VERSION=true fi if [[ ${REDO_VERSION} == true ]]; then # Ask again if response does not pass validation. ASKVERSION="" ask_version fi } ask_author() { PRINT INPUT "Author (prplwtf):" read -r ASKAUTHOR REDO_AUTHOR=false # Author should not be empty if [[ ${ASKAUTHOR} == "" ]]; then PRINT WARNING "Author should not be empty." REDO_AUTHOR=true fi if [[ ${REDO_AUTHOR} == true ]]; then # Ask again if response does not pass validation. ASKAUTHOR="" ask_author fi } ask_template ask_name ask_identifier ask_description ask_version ask_author tnum=${ASKTEMPLATE} log_bright "[INFO] Downloading templates from 'teamblueprint/templates'.." if [[ $(php artisan bp:latest) != "$VERSION" ]]; then log_yellow "[WARNING] Your Blueprint installation version is outdated, some templates might break or show random bugs."; fi cd .blueprint/tmp || throw 'cdMissingDirectory' git clone "https://github.com/teamblueprint/templates.git" cd ${FOLDER}/.blueprint || throw 'cdMissingDirectory' cp -R tmp/templates/* extensions/blueprint/private/build/templates/ rm -R tmp/templates cd ${FOLDER} || throw 'cdMissingDirectory' eval "$(parse_yaml .blueprint/extensions/blueprint/private/build/templates/"${tnum}"/TemplateConfiguration.yml t_)" log_bright "[INFO] Copying template contents to the tmp directory.." mkdir -p .blueprint/tmp/init cp -R .blueprint/extensions/blueprint/private/build/templates/"${tnum}"/contents/* .blueprint/tmp/init/ log_bright "[INFO] Applying variables.." sed -i "s~␀name␀~${ASKNAME}~g" .blueprint/tmp/init/conf.yml; #NAME sed -i "s~␀identifier␀~${ASKIDENTIFIER}~g" .blueprint/tmp/init/conf.yml; #IDENTIFIER sed -i "s~␀description␀~${ASKDESCRIPTION}~g" .blueprint/tmp/init/conf.yml; #DESCRIPTION sed -i "s~␀ver␀~${ASKVERSION}~g" .blueprint/tmp/init/conf.yml; #VERSION sed -i "s~␀author␀~${ASKAUTHOR}~g" .blueprint/tmp/init/conf.yml; #AUTHOR if [[ "${t_template_files_icon}" != "" ]]; then log_bright "[INFO] Rolling (and applying) extension placeholder icon.." icnNUM=$(( 1 + RANDOM % 9 )) cp .blueprint/assets/defaultExtensionLogo"${icnNUM}".jpg .blueprint/tmp/init/"${t_template_files_icon}" sed -i "s~␀icon␀~${t_template_files_icon}~g" .blueprint/tmp/init/conf.yml; #ICON fi log_bright "[INFO] Applying core variables.." sed -i "s~␀version␀~${VERSION}~g" .blueprint/tmp/init/conf.yml #BLUEPRINT-VERSION # Return files to folder. log_bright "[INFO] Copying output to extension development directory." cp -R .blueprint/tmp/init/* .blueprint/dev/ # Remove tmp files. log_bright "[INFO] Purging contents of tmp folder." rm -R .blueprint/tmp mkdir -p .blueprint/tmp # Wipe templates from disk. log_bright "[INFO] Wiping downloaded templates from disk.." rm -R .blueprint/extensions/blueprint/private/build/templates/* sendTelemetry "INITIALIZE_DEVELOPMENT_EXTENSION" >> $BLUEPRINT__DEBUG log_green "[SUCCESS] Your extension files have been generated and exported to '.blueprint/dev'." fi # -build if [[ ( $2 == "-build" || $2 == "-b" ) ]]; then VCMD="y" # Check for developer mode through the database library. if ! dbValidate "blueprint.developerEnabled"; then PRINT FATAL "Developer mode is not enabled.";exit 2; fi if [[ -z $(find .blueprint/dev -maxdepth 1 -type f -not -name ".gitkeep" -print -quit) ]]; then PRINT FATAL "Development directory is empty." exit 2 fi PRINT INFO "Starting developer extension installation.." blueprint -i test␀ fi # -export if [[ ( $2 == "-export" || $2 == "-e" ) ]]; then VCMD="y" # Check for developer mode through the database library. if ! dbValidate "blueprint.developerEnabled"; then PRINT FATAL "Developer mode is not enabled.";exit 2; fi if [[ -z $(find .blueprint/dev -maxdepth 1 -type f -not -name ".gitkeep" -print -quit) ]]; then PRINT FATAL "Development directory is empty." exit 2 fi PRINT INFO "Start packaging extension.." cd .blueprint || throw 'cdMissingDirectory' rm dev/.gitkeep 2>> $BLUEPRINT__DEBUG eval "$(parse_yaml dev/conf.yml conf_)"; identifier="${conf_info_identifier}" cp -R dev/* tmp/ cd tmp || throw 'cdMissingDirectory' # Assign variables to extension flags. flags="$conf_info_flags" PRINT INFO "Reading and assigning extension flags.." assignflags if $F_hasExportScript; then chmod +x "${conf_data_directory}""/export.sh" # Run script while also parsing some useful variables for the export script to use. EXTENSION_IDENTIFIER="$conf_info_identifier" \ EXTENSION_TARGET="$conf_info_target" \ EXTENSION_VERSION="$conf_info_version" \ PTERODACTYL_DIRECTORY="$FOLDER" \ BLUEPRINT_EXPORT_DIRECTORY="$FOLDER/.blueprint/tmp" \ BLUEPRINT_VERSION="$VERSION" \ bash "${conf_data_directory}""/export.sh" echo -e "\e[0m\x1b[0m\033[0m" fi zip -r extension.zip ./* cd ${FOLDER} || throw 'cdMissingDirectory' cp .blueprint/tmp/extension.zip "${identifier}.blueprint" rm -R .blueprint/tmp mkdir -p .blueprint/tmp if [[ $3 == "expose"* ]]; then PRINT INFO "Generating download url.. (expires after 2 minutes)" randstr=${RANDOM}${RANDOM}${RANDOM}${RANDOM}${RANDOM} mkdir .blueprint/extensions/blueprint/assets/exports/${randstr} cp "${identifier}".blueprint .blueprint/extensions/blueprint/assets/exports/${randstr}/"${identifier}".blueprint sendTelemetry "EXPOSE_DEVELOPMENT_EXTENSION" >> $BLUEPRINT__DEBUG PRINT SUCCESS "Extension has been exported to '$(grabAppUrl)/assets/extensions/blueprint/exports/${randstr}/${identifier}.blueprint' and '${FOLDER}/${identifier}.blueprint'." eval "$(sleep 120 && rm -R .blueprint/extensions/blueprint/assets/exports/${randstr} 2>> $BLUEPRINT__DEBUG)" & else sendTelemetry "EXPORT_DEVELOPMENT_EXTENSION" >> $BLUEPRINT__DEBUG PRINT SUCCESS "Extension has been exported to '${FOLDER}/${identifier}.blueprint'." fi fi # -wipe if [[ ( $2 == "-wipe" || $2 == "-w" ) ]]; then VCMD="y" # Check for developer mode through the database library. if ! dbValidate "blueprint.developerEnabled"; then PRINT FATAL "Developer mode is not enabled.";exit 2; fi if [[ -z $(find .blueprint/dev -maxdepth 1 -type f -not -name ".gitkeep" -print -quit) ]]; then PRINT FATAL "Development directory is empty." fi PRINT INPUT "You are about to wipe all of your development files, are you sure you want to continue? This cannot be undone. (y/N)" read -r YN if [[ ( ( ${YN} != "y"* ) && ( ${YN} != "Y"* ) ) || ( ( ${YN} == "" ) ) ]]; then PRINT INFO "Development files removal cancelled.";exit 1;fi PRINT INFO "Clearing development folder.." rm -R .blueprint/dev/* 2>> $BLUEPRINT__DEBUG rm -R .blueprint/dev/.* 2>> $BLUEPRINT__DEBUG PRINT SUCCESS "Development folder has been cleared." fi # -info if [[ ( $2 == "-info" || $2 == "-f" ) ]]; then VCMD="y" fetchversion() { if [[ $VERSION != "" ]]; then log_reset log_white $VERSION; else echo "none"; fi } fetchfolder() { if [[ $FOLDER != "" ]]; then log_reset log_white $FOLDER; else echo "none"; fi } fetchurl() { if [[ $(grabAppUrl) != "" ]]; then log_reset log_white "$(grabAppUrl)"; else echo "none"; fi } fetchlocale() { if [[ $(grabAppLocale) != "" ]]; then log_reset log_white "$(grabAppLocale)"; else echo "none"; fi } fetchtimezone() { if [[ $(grabAppTimezone) != "" ]]; then log_reset log_white "$(grabAppTimezone)"; else echo "none"; fi } fetchextensions() { log_reset log_white "$(echo "$(<.blueprint/extensions/blueprint/private/db/installed_extensions)" | tr -cd ',' | wc -c | tr -d ' ')"; } fetchdeveloper() { log_reset log_white "$(if dbValidate "blueprint.developerEnabled"; then echo "true"; else echo "false"; fi;)"; } fetchtelemetry() { log_reset log_white "$(telemetrykey=$(cat .blueprint/extensions/blueprint/private/db/telemetry_id); if [[ $telemetrykey == "KEY_NOT_UPDATED" ]]; then echo "false"; else echo "true"; fi;)"; } fetchnode() { if [[ $(node -v) != "" ]]; then log_reset log_white "$(node -v)"; else echo "none"; fi } fetchyarn() { if [[ $(yarn -v) != "" ]]; then log_reset log_white "$(yarn -v)"; else echo "none"; fi } log_bright " " log_blue log_bold " ⣿⣿ $(log_reset log_bold log_blue "Version:") $(fetchversion)" log_blue log_bold " ⣿⣿ ⣿⣿ $(log_reset log_bold log_blue "Folder:") $(fetchfolder)" log_blue log_bold " ⣿⣿⣿⣿ $(log_reset log_bold log_blue "URL:") $(fetchurl)" log_blue " $(log_reset log_bold log_blue "Locale:") $(fetchlocale)" log_blue " $(log_reset log_bold log_blue "Timezone:") $(fetchtimezone)" log_blue " $(log_reset log_bold log_blue "Extensions:") $(fetchextensions)" log_blue " $(log_reset log_bold log_blue "Developer:") $(fetchdeveloper)" log_blue " $(log_reset log_bold log_blue "Telemetry:") $(fetchtelemetry)" log_blue " $(log_reset log_bold log_blue "Node:") $(fetchnode)" log_blue " $(log_reset log_bold log_blue "Yarn:") $(fetchyarn)" log_bright " " fi # -rerun-install if [[ $2 == "-rerun-install" ]]; then VCMD="y" PRINT WARNING "This is an advanced feature, only proceed if you know what you are doing." dbRemove "blueprint.setupFinished" cd ${FOLDER} || throw 'cdMissingDirectory' bash blueprint.sh fi # -upgrade if [[ $2 == "-upgrade" ]]; then VCMD="y" PRINT WARNING "This is an advanced feature, only proceed if you know what you are doing." if [[ -n $(find .blueprint/dev -maxdepth 1 -type f -not -name ".gitkeep" -print -quit) ]]; then PRINT FATAL "Development directory contains files. To protect you against accidental data loss, you are unable to upgrade unless you clear the '.blueprint/dev' folder." exit 2 fi # Confirmation question for developer upgrade. if [[ $3 == "dev" ]]; then PRINT INPUT "Upgrading to the latest development build will update Blueprint to an unstable work-in-progress preview of the next version. Continue? (y/N)" read -r YN if [[ ( ${YN} != "y"* ) && ( ${YN} != "Y"* ) ]]; then PRINT INFO "Upgrade cancelled.";exit 1;fi YN="" fi # Confirmation question for both developer and stable upgrade. PRINT INPUT "Upgrading will wipe your .blueprint folder and will deactivate all active extensions. Continue? (y/N)" read -r YN if [[ ( ${YN} != "y"* ) && ( ${YN} != "Y"* ) ]]; then PRINT INFO "Upgrade cancelled.";exit 1;fi YN="" # Last confirmation question for both developer and stable upgrade. PRINT INPUT "This is the last warning before upgrading/wiping Blueprint. Type 'continue' to continue, all other input will be taken as 'no'." read -r YN if [[ ${YN} != "continue" ]]; then PRINT INFO "Upgrade cancelled.";exit 1;fi YN="" if [[ $3 == "dev" ]]; then PRINT INFO "Fetching and pulling latest commit.." else PRINT INFO "Fetching and pulling latest release.."; fi cp blueprint.sh .blueprint.sh.bak if [[ $3 == "dev" ]]; then bash tools/update.sh ${FOLDER} dev else bash tools/update.sh ${FOLDER}; fi chmod +x blueprint.sh sed -i -E "s|FOLDER=\"/var/www/pterodactyl\" #;|FOLDER=\"$FOLDER\" #;|g" $FOLDER/blueprint.sh mv $FOLDER/blueprint $FOLDER/.blueprint; bash blueprint.sh --post-upgrade # Ask user if they'd like to migrate their database. PRINT INPUT "Would you like to migrate your database? (Y/n)" read -r YN if [[ ( $YN == "y"* ) || ( $YN == "Y"* ) || ( $YN == "" ) ]]; then PRINT INFO "Running database migrations.." php artisan migrate --force else PRINT INFO "Database migrations have been skipped." fi YN="" # Post-upgrade checks. PRINT INFO "Validating update.." score=0 if dbValidate "blueprint.setupFinished"; then score=$((score+1)) else PRINT WARNING "'blueprint.setupFinished' could not be detected or found." fi # Finalize upgrade. if [[ ${score} == 1 ]]; then PRINT SUCCESS "Upgrade finished." rm .blueprint.sh.bak exit 0 # success elif [[ ${score} == 0 ]]; then PRINT FATAL "All checks have failed. The 'blueprint.sh' file has been reverted." rm blueprint.sh mv .blueprint.sh.bak blueprint.sh exit 1 # error else PRINT FATAL "Some checks have failed. The 'blueprint.sh' file has been reverted." rm blueprint.sh mv .blueprint.sh.bak blueprint.sh exit 1 # error fi fi # When the users attempts to run an invalid command. if [[ ${VCMD} != "y" && $1 == "-bash" ]]; then # This is logged as a "fatal" error since it's something that is making Blueprint run unsuccessfully. quit_red "[FATAL] '$2' is not a valid command or argument. Use argument '-help' for a list of commands." exit 1 fi