Examples

Here you will find some example scripts to give you an idea on using the shell.

Recursive function call

# Demonstrate recursive function calls

const MAX_COUNT int <= 10;

function recursive void(count int)
{
  if (%count, -ls, %MAX_COUNT) {
    ++ count;
    print "Count value: %count";
    call recursive(%count) => void;
  };
};

call recursive(0) => void;

print "Done.";

pause;

Date and time utilities

# Time and Date related utilities

function clock void() {
    sys { timedate.cpl };
};

function time void() {
    local curtime string;
    fmtdatetime "%H:%M:%S" curtime;
    print "%curtime";
};

function date void() {
    local curdate string;
    fmtdatetime "%Y-%m-%d" curdate;
    print "%curdate";
};

function datetime void() {
    local curdatetime string;
    fmtdatetime "%Y-%m-%d %H:%M:%S" curdatetime;
    print "%curdatetime";
};

function seconds void()
{
    local curseconds string;
    fmtdatetime "%S" curseconds;
    print "%curseconds";
};

function secs void() { call seconds() => void; };

function rsecs void()
{
    local curseconds string;
    local intsecs int;

    fmtdatetime "%S" curseconds;
    set intsecs <= %curseconds;

    - intsecs 60 %intsecs;

    print %intsecs;
};

function weekday void(date string) {
    local dayname string;
    
    if (%date, -eq, "") {
        fmtdatetime "%Y-%m-%d" date;
    };
    
    sys {php -r "echo date('l', strtotime('%date'));"} dayname;
    
    print "%dayname";
};

function synchronize_datetime void()
{
    sys {w32tm /resync};
};

Get Internet IP address from a service

# Get Internet IP address of this machine

const SERVICE_URL string <= "https://www.example.tld/ip.php";

global ipaddr string;

sys {curl "%SERVICE_URL" --silent} ipaddr;

print "IP address: %ipaddr";

Upgrade composer dependencies of various projects

# Upgrade composer dependencies

require "array";
require "auto";

array arrProjects string 5 (
    "public_html/project-1", 
    "public_html/project-2",
    "public_html/project-3",
    "public_html/project-4",
    "public_html/project-5"
);

function upgrade_dependencies void(folder string)
{
    print "Upgrading %folder...";
    
    aut_run "composer" "update --working-dir %folder" "%folder" void;
};

print "Upgrading projects...";

for (i, 0, %arrProjects.length, -inc) {
    call upgrade_dependencies(%arrProjects[%i]) => void;
};

print "Done.";

Generate a testing password via external program

# Quickly generate BCRYPT password via PHP

require "strings";
require "auto";

const C_TEST_PASSWORD string <= "test";

global expression string;
global exprlen int;

set expression <= "%2";

s_getlen "%expression" exprlen;
if (%exprlen, -ls, 3) {
    set expression <= "%C_TEST_PASSWORD";
};

if ("%2", -eq, "--verbose") {
    print "Generating password for: %expression";
};

function genenrate_password void()
{
    local output string;
    
    sys {php -r "echo password_hash('%expression', PASSWORD_BCRYPT);"} output;
    print "%output";
    
    aut_clpbsetstring "%output";
    print "Copied to clipboard!";
};

call genenrate_password() => void;

if (%DNYAS_IS_INTERACTIVE_MODE, -eq, false) {
    pause;
};

Parse commandline arguments of a script

# Commandline argument parser

function cmd_has bool(search string)
{
    result false;

    if (%argc, -gr, 1) {
        for (i, 1, %argc, -inc) {
            if ("%argv[%i]", -eq, "%search") {
                result true;
            };
        };
    };
};

function cmd_pair string(key string)
{
    result "";

    if (%argc, -gr, 1) {
        for (i, 1, %argc, -inc) {
            if ("%argv[%i]", -eq, "%key") {
                local varIncr int;

                set varIncr <= %i;
                ++ varIncr;

                if (%varIncr, -ls, %argc) {
                    result "%argv[%varIncr]";
                };
            };
        };
    };
};

Show environment variables via GUI

# Show environment variables via GUI

hideconsole;

require "strings";
require "forms";

global wndstyles int;
global frmMain int;
global bres bool;
global envcont string;

bitop "or" (%WS_OVERLAPPED, %WS_SYSMENU, %WS_VISIBLE) wndstyles;

wnd_spawnform "frmMain" "Windows Environment Variables" 200 300 500 350 %wndstyles frmMain;

wnd_isformvalid frmMain bres;

if (%bres, -eq, false) {
    print "Failed to create form.";
    pause;
    exit;
};

wnd_spawnlistview "frmMain" "lvVariables" 10 10 467 295;
wnd_lvaddcategory "frmMain" "lvVariables" "Name" 225 true;
wnd_lvaddcategory "frmMain" "lvVariables" "Value" 220 true;

sys {set} envcont;

s_tokenize "%envcont" "%CR%LF" splittedvars;

global szVarName string;
global szVarValue string;
global numTokenIndex int;

for (i, 0, %splittedvars.count, -inc) {
    s_find "%splittedvars[%i]" "=" numTokenIndex;
    
    if (%numTokenIndex, -gr, 0) {
        s_substr "%splittedvars[%i]" 0 %numTokenIndex szVarName;

        ++ numTokenIndex;
        s_substr "%splittedvars[%i]" %numTokenIndex -1 szVarValue;

        wnd_lvsetitemtext "frmMain" "lvVariables" "%szVarName" 0 bres;
        wnd_lvsetsubitemtext "frmMain" "lvVariables" 0 "%szVarValue" 1 bres;
    };
};

while (%bres, -eq, true) {
    wnd_process;

    wnd_isformvalid frmMain bres;
};

Check if internet is available

# Check if internet is available

require "array";
require "strings";

array arrDomains string 3 (
    "https://www.google.com", 
    "https://www.microsoft.com", 
    "https://store.steampowered.com"
);

global checkresult bool;

function check_availability bool(domain string)
{
    local response string;
    local httprespos int;

    result false;

    print "Checking via domain: %domain";

    sys {curl "%domain" -X HEAD -I --silent} response;

    s_find "%response" "HTTP/1.1 200 OK" httprespos;
    
    if (%httprespos, -eq, 0) {
        result true;
    };
};

global resultcount int;
set resultcount <= 0;

for (i, 0, %arrDomains.length, -inc) {
    call check_availability("%arrDomains[%i]") => checkresult;

    if (%checkresult, -eq, true) {
        ++ resultcount;
    };
};

if (%resultcount, -gr, 0) {
    print "Internet is available (%resultcount/%arrDomains.length succeeded).";
} else {
    print "All connection attempts failed.";
};

if (%DNYAS_IS_INTERACTIVE_MODE, -eq, false) {
    pause;
};

Speak text entered via GUI input box

# Speak text entered via GUI input box

require "input";
require "speech";

global inputspeakrun bool;
set inputspeakrun <= true;

global slastphrase string;
set slastphrase <= "Hello World!";

spk_setvoice "Microsoft Zira Desktop";
spk_setvolume 100;

function prompt_and_speak void()
{
    local text string;

    inputbox "Speech Prompt" "Enter a text to speak" "%slastphrase" 700 500 text;
    
    if (%text, -nt, "") {
        set slastphrase <= "%text";
        spk_speakasync "%text";
    } else {
        set inputspeakrun <= false;
    };
};

while (%inputspeakrun, -eq, true) {
    call prompt_and_speak() => void;
    sleep 10;
};

unset inputspeakrun;
unset slastphrase;

Heroes of the Storm Chat Hotkeys

# Send chat messages to Heroes of the Storm via hotkeys
#
# This script features binding chat messages to the keys F5, F6, F7, F8 and F9 by default.
# Key F5 - F8 are subject to single chat messages where key F9 will be subject to a switching
# toggle. That means you can specify a dynamic amount of chat messages that will be iterated on
# and once the end is reached, it will be starting over from the beginning again.

# You can edit the chat messages via the GUI (except switching toggles). The script does also check
# if the current foreground window is the window of the game in order to prevent that the chat messages 
# are inserted elsewhere.
#
# Chat messages are stored in the text file defined via the constant CONFIG_NAME. If it does not exist
# then the script will create a sample file that can be edited afterwards.
#

hideconsole;

require "array";
require "auto";
require "fileio";
require "forms";
require "strings";

const WND_CLASS string <= "Heroes of the Storm";
const CONFIG_NAME string <= "hots_messages.txt";
const FORM_TEXT string <= "HotS Chat Hotkey Manager";
const KEY_CODE_1 int <= 116; #F5
const KEY_CODE_2 int <= 117; #F6
const KEY_CODE_3 int <= 118; #F7
const KEY_CODE_4 int <= 119; #F8
const KEY_CODE_5 int <= 120; #F9
const CONFIG_TOGGLE_SECTION_START int <= 4;

global bres bool;
global brun bool;
global currentpath string;
global configpath string;
global keytoggle1 bool;
global keytoggle2 bool;
global keytoggle3 bool;
global keytoggle4 bool;
global keytoggle5 bool;
global switchcount int;
global switchmsg string;
global lasttimeactive bool;

set bres <= false;
set brun <= true;
set currentpath <= "";
set configpath <= "";
set keytoggle1 <= false;
set keytoggle2 <= false;
set keytoggle3 <= false;
set keytoggle4 <= false;
set keytoggle5 <= false;
set switchcount <= %CONFIG_TOGGLE_SECTION_START;
set switchmsg <= "";
set lasttimeactive <= true;

array arrConfigItems string 0 ();

getscriptpath currentpath;

set configpath <= {%currentpath%CONFIG_NAME};

function GameWindowActive bool()
{
    local targetwnd int;
    local wndfg int;

    result false;
    
    aut_findwindow "%WND_CLASS" \0 targetwnd;
    
    if (%targetwnd, -gr, 0) {
        aut_getfgwindow wndfg;
        
        if (%wndfg, -eq, %targetwnd) {
            result true;
        };
    };
};

function cbHotKeyToggles_OnSelect void(newItem string)
{
};

function btnSaveMessages_OnClick void()
{
    local currentitem string;
    local checkexists bool;
    local hfile int;
    local fopres  bool;

    wnd_gettextboxtext frmMain txtMsg1 currentitem;
    array_item_set "currentitem" arrConfigItems 0;

    wnd_gettextboxtext frmMain txtMsg2 currentitem;
    array_item_set "currentitem" arrConfigItems 1;

    wnd_gettextboxtext frmMain txtMsg3 currentitem;
    array_item_set "currentitem" arrConfigItems 2;

    wnd_gettextboxtext frmMain txtMsg4 currentitem;
    array_item_set "currentitem" arrConfigItems 3;

    set checkexists <= true;

    fexists "%configpath" checkexists;
    if (%checkexists, -eq, true) {
        fremove "%configpath" fopres;
    };
    
    fopen "%configpath" true hfile;
    if (%hfile, -nt, %FIO_INVALID_HANDLE) {
        for (i, 0, %arrConfigItems.length, -inc) {
            if ("%arrConfigItems[%i]", -nt, "") {
                fwriteline %hfile "%arrConfigItems[%i]";
            };
        };
        
        fclose %hfile;
    };

    print "Saved chat messages to: %configpath";
};

function btnExitScript_OnClick void()
{
    wnd_freeform frmMain;
};

function LoadMessages void()
{
    local filecontent string;
    local chatcfgexists bool;
    local cntnumber int;

    fexists "%configpath" chatcfgexists;
    if (%chatcfgexists, -eq, false) {
        sys {echo -= Go0d Luck ^& Have Fun =->>"%configpath"};
        sys {echo -= ! G0od Game ! =->>"%configpath"};
        sys {echo -= NiCe jOb =->>"%configpath"};
        sys {echo -= Let us rush the core =->>"%configpath"};
        sys {echo -= Please add more switching messages =->>"%configpath"};
    };

    sys {type "%configpath"} filecontent;

    s_tokenize "%filecontent" "%CR%LF" splittedmsgs;
    
    array_item_insert arrConfigItems 0 "%splittedmsgs[0]";
    array_item_insert arrConfigItems 1 "%splittedmsgs[1]";
    array_item_insert arrConfigItems 2 "%splittedmsgs[2]";
    array_item_insert arrConfigItems 3 "%splittedmsgs[3]";
    
    if (%splittedmsgs.count, -gre, %CONFIG_TOGGLE_SECTION_START) {
        for (i, %CONFIG_TOGGLE_SECTION_START, %splittedmsgs.count, -inc) {
            array_item_insert arrConfigItems %i "%splittedmsgs[%i]";
        };
    };

    set cntnumber <= %splittedmsgs.count;
    -= cntnumber 4;

    set switchmsg <= "(You have %cntnumber switching items)";
};

function CreateWindow void()
{
    local wndstyles int;
    local cbselindex int;
    
    bitop "or" (%WS_OVERLAPPED, %WS_SYSMENU, %WS_VISIBLE) wndstyles;

    wnd_spawnform frmMain "%FORM_TEXT" 500 400 635 330 %wndstyles bres;

    wnd_spawnlabel frmMain "lblKey1" 20 10 20 30 "F5: ";
    wnd_spawnlabel frmMain "lblKey2" 20 50 20 30 "F6: ";
    wnd_spawnlabel frmMain "lblKey3" 20 90 20 30 "F7: ";
    wnd_spawnlabel frmMain "lblKey4" 20 130 20 30 "F8: ";
    wnd_spawnlabel frmMain "lblKey5" 20 170 20 30 "F9: ";
    
    wnd_spawntextbox frmMain "txtMsg1" 50 10 550 20 "";
    wnd_spawntextbox frmMain "txtMsg2" 50 50 550 20 "";
    wnd_spawntextbox frmMain "txtMsg3" 50 90 550 20 "";
    wnd_spawntextbox frmMain "txtMsg4" 50 130 550 20 "";
    wnd_spawncombobox frmMain "cbHotKeyToggles" 50 170 550 1500;

    wnd_spawnlabel frmMain "lblWndStatus" 20 215 350 30 "";

    wnd_spawnbutton frmMain "btnSaveMessages" 20 255 200 30 "Save";
    wnd_spawnbutton frmMain "btnExitScript" 400 255 200 30 "Exit";

    wnd_settextboxtext frmMain txtMsg1 "%arrConfigItems[0]";
    wnd_settextboxtext frmMain txtMsg2 "%arrConfigItems[1]";
    wnd_settextboxtext frmMain txtMsg3 "%arrConfigItems[2]";
    wnd_settextboxtext frmMain txtMsg4 "%arrConfigItems[3]";
    
    for (cbcnt, %CONFIG_TOGGLE_SECTION_START, %arrConfigItems.length, -inc) {
        wnd_cbadditem frmMain cbHotKeyToggles "%arrConfigItems[%cbcnt]";
    };

    wnd_cbgetcount frmMain cbHotKeyToggles cbselindex;

    wnd_cbadditem frmMain cbHotKeyToggles "%switchmsg";
    wnd_cbselectitem frmMain cbHotKeyToggles %cbselindex;
};

function SendText void(texttosend string)
{
    local kres bool;

    print "Sending text: %texttosend ...";
    
    aut_sendkeystrokes {\VK_RETURN;} false false false kres;
    sleep 1;
    
    aut_sendkeystrokes %texttosend false false false kres;

    sleep 1;
    aut_sendkeystrokes {\VK_RETURN;} false false false kres;
};

function CheckKey1 void()
{
    local kdres bool;
    
    aut_iskeydown %KEY_CODE_1 kdres;
    
    if (%kdres, -eq, true) {
        if (%keytoggle1, -eq, false) {
            call SendText("%arrConfigItems[0]") => void;
        
            set keytoggle1 <= true;
        };
    } else {
        if (%keytoggle1, -eq, true) {
            set keytoggle1 <= false;
        };
    };
};

function CheckKey2 void()
{
    local kdres bool;
    
    aut_iskeydown %KEY_CODE_2 kdres;
    
    if (%kdres, -eq, true) {
        if (%keytoggle2, -eq, false) {
            call SendText("%arrConfigItems[1]") => void;
        
            set keytoggle2 <= true;
        };
    } else {
        if (%keytoggle2, -eq, true) {
            set keytoggle2 <= false;
        };
    };
};

function CheckKey3 void()
{
    local kdres bool;
    
    aut_iskeydown %KEY_CODE_3 kdres;
    
    if (%kdres, -eq, true) {
        if (%keytoggle3, -eq, false) {
            call SendText("%arrConfigItems[2]") => void;
        
            set keytoggle3 <= true;
        };
    } else {
        if (%keytoggle3, -eq, true) {
            set keytoggle3 <= false;
        };
    };
};

function CheckKey4 void()
{
    local kdres bool;
    
    aut_iskeydown %KEY_CODE_4 kdres;
    
    if (%kdres, -eq, true) {
        if (%keytoggle4, -eq, false) {
            call SendText("%arrConfigItems[3]") => void;
        
            set keytoggle4 <= true;
        };
    } else {
        if (%keytoggle4, -eq, true) {
            set keytoggle4 <= false;
        };
    };
};

function CheckKey5 void()
{
    local kdres bool;
    local fixcount int;

    set fixcount <= %arrConfigItems.length;
    -- fixcount;
    
    aut_iskeydown %KEY_CODE_5 kdres;
    
    if (%kdres, -eq, true) {
        if (%keytoggle5, -eq, false) {
            call SendText("%arrConfigItems[%switchcount]") => void;
            
            ++ switchcount;
            if (%switchcount, -gre, %fixcount) {
                set switchcount <= %CONFIG_TOGGLE_SECTION_START;
            };
        
            set keytoggle5 <= true;
        };
    } else {
        if (%keytoggle5, -eq, true) {
            set keytoggle5 <= false;
        };
    };
};

function UpdateGameWindowStatus void()
{
    local iswndactive bool;
    local wndstatusmsg string;

    call GameWindowActive() => iswndactive;
    if (%iswndactive, -eq, true) {
        if (%lasttimeactive, -eq, false) {
            set wndstatusmsg <= "window found in foreground!";

            wnd_setcomptext "frmMain" "CLabel" "lblWndStatus" "Game Status: %wndstatusmsg";
            print "Game Status: %wndstatusmsg";

            set lasttimeactive <= true;
        };
    } else {
        if (%lasttimeactive, -eq, true) {
            set wndstatusmsg <= "window not in foreground...";

            wnd_setcomptext "frmMain" "CLabel" "lblWndStatus" "Game Status: %wndstatusmsg";
            print "Game Status: %wndstatusmsg";

            set lasttimeactive <= false;
        };
    };
};

call LoadMessages() => void;
call CreateWindow() => void;

print "%FORM_TEXT%CR%LF";

while (%brun, -eq, true) {
    call CheckKey1() => void;
    call CheckKey2() => void;
    call CheckKey3() => void;
    call CheckKey4() => void;
    call CheckKey5() => void;

    call UpdateGameWindowStatus() => void;

    wnd_process;
    wnd_isformvalid frmMain brun;

    sleep 1;
};

Create a phaser project with backend functionality

# Create a phaser project using Asatru PHP as backend web framework

require "auto";
require "input";
require "fileio";
require "strings";

const PROJECT_DEFAULT_NAME string <= "new-phaser-project";

global szProjectPath string;
global szProjectName string;
global szTempString string;
global hFile int;
global iStrLen int;
global bResult bool;

inputbox "Create Phaser project (1/2)" "Enter project path" "C:/projects" 400 500 szProjectPath;
if (%szProjectPath, -eq, "") {
    print "No path specified, aborting.";
    pause;
    exit;
};

inputbox "Create Phaser project (2/2)" "Enter project name" "%PROJECT_DEFAULT_NAME" 400 500 szProjectName;
if (%szProjectName, -eq, "") {
    print "No project name specified, aborting.";
    pause;
    exit;
};

s_replace "szProjectPath" {\} "/";

s_getlen "%szProjectPath" iStrLen;
-- iStrLen;
s_getchar "%szProjectPath" %iStrLen "szTempString";
if ("%szTempString", -nt, "/") {
    set szProjectPath <= "%szProjectPath/";
};

dexists "%szProjectPath%szProjectName" bResult;
if (%bResult, -eq, true) {
    print "Error: A project with the given name already exists!";
    pause;
    exit;
};

print "Creating project '%szProjectPath%szProjectName'...";

sys {composer create-project "danielbrendel/asatru-php" "%szProjectName" --ignore-platform-reqs --working-dir "%szProjectPath"};
sys {composer update --ignore-platform-reqs --working-dir "%szProjectPath%szProjectName"};
sys {cd /d "%szProjectPath%szProjectName" && npm install && npm i "phaser" && npm update};

fexists "%szProjectPath%szProjectName/app/resources/sass/app.scss" bResult;
if (%bResult, -eq, true) {
    fremove "%szProjectPath%szProjectName/app/resources/sass/app.scss" bResult;
};

fopen "%szProjectPath%szProjectName/app/resources/sass/app.scss" true hFile;
if (%hFile, -nt, %FILEIO_INVALID_HANDLE) {
    fwriteline %hFile "html, body {";
    fwriteline %hFile "    width: 100%;";
    fwriteline %hFile "    height: 100%;";
    fwriteline %hFile "    margin: 0 auto;";
    fwriteline %hFile "    overflow-y: hidden;";
    fwriteline %hFile "    background-color: rgb(0, 0, 0);";
    fwriteline %hFile "}";

    fclose %hFile;
};

fexists "%szProjectPath%szProjectName/app/resources/js/app.js" bResult;
if (%bResult, -eq, true) {
    fremove "%szProjectPath%szProjectName/app/resources/js/app.js" bResult;
};

fopen "%szProjectPath%szProjectName/app/resources/js/app.js" true hFile;
if (%hFile, -nt, %FILEIO_INVALID_HANDLE) {
    fwriteline %hFile "import './../sass/app.scss';";
    fwriteline %hFile "require('phaser');";

    fclose %hFile;
};

dcreate "%szProjectPath%szProjectName/public/game" bResult;
if (%bResult, -eq, false) {
    print "Error: Failed to create game directory!";
    pause;
    exit;
};

fopen "%szProjectPath%szProjectName/public/game/game.js" true hFile;
if (%hFile, -nt, %FILEIO_INVALID_HANDLE) {
    fwriteline %hFile "class MyGame extends Phaser.Scene {";
    fwriteline %hFile "        preload()";
    fwriteline %hFile "        {";
    fwriteline %hFile "        }";
    fwriteline %hFile "";
    fwriteline %hFile "        create()";
    fwriteline %hFile "        {";
    fwriteline %hFile "              this.txtHelloWorld = this.add.text(gameconfig.scale.width / 2 - 105, gameconfig.scale.height / 2, 'Hello World!', {color: 'rgb(255, 255, 255)',fontSize: '32px'});";
    fwriteline %hFile "              this.txtHelloWorld.postFX.addGlow(0x00FF00, 4, 0, true, 0.1, 10)";
    fwriteline %hFile "        }";
    fwriteline %hFile "";
    fwriteline %hFile "        update()";
    fwriteline %hFile "        {";
    fwriteline %hFile "        }";
    fwriteline %hFile "}";
    fwriteline %hFile "";
    fwriteline %hFile "const gameconfig = {";
    fwriteline %hFile "       type: Phaser.AUTO,";
    fwriteline %hFile "       scene: MyGame,";
    fwriteline %hFile "       physics: {";
    fwriteline %hFile "          default: 'arcade',";
    fwriteline %hFile "          arcade: {";
    fwriteline %hFile "                gravity: { y: 300 },";
    fwriteline %hFile "                debug: true";
    fwriteline %hFile "           }";
    fwriteline %hFile "       },";
    fwriteline %hFile "        scale: {";
    fwriteline %hFile "           mode: Phaser.Scale.FIT,";
    fwriteline %hFile "           autoCenter: Phaser.Scale.CENTER_BOTH,";
    fwriteline %hFile "           width: 1024,";
    fwriteline %hFile "           height: 768";
    fwriteline %hFile "     }";
    fwriteline %hFile "};";

    fclose %hFile;
};

fexists "%szProjectPath%szProjectName/app/views/layout.php" bResult;
if (%bResult, -eq, true) {
    fremove "%szProjectPath%szProjectName/app/views/layout.php" bResult;
};

fopen "%szProjectPath%szProjectName/app/views/layout.php" true hFile;
if (%hFile, -nt, %FILEIO_INVALID_HANDLE) {
    fwriteline %hFile "<!doctype html>";
    fwriteline %hFile "<html lang='en'>";
    fwriteline %hFile "    <head>";
    fwriteline %hFile "        <meta charset='utf-8'>";
    fwriteline %hFile "        <meta name='viewport' content='width=device-with, initial-scale=1.0'>";
    fwriteline %hFile "        ";
    fwriteline %hFile "        <title>Asatru PHP powered Phaser.js project</title>";
    fwriteline %hFile "";
    fwriteline %hFile "        <script src='js/app.js'></script>";
    fwriteline %hFile "        <script src='game/game.js'></script>";
    fwriteline %hFile "    </head>";
    fwriteline %hFile ""; 
    fwriteline %hFile "    <body>";
    fwriteline %hFile "        {%yield%}";
    fwriteline %hFile "    </body>";
    fwriteline %hFile "</html>";

    fclose %hFile;
};

fexists "%szProjectPath%szProjectName/app/views/index.php" bResult;
if (%bResult, -eq, true) {
    fremove "%szProjectPath%szProjectName/app/views/index.php" bResult;
};

fopen "%szProjectPath%szProjectName/app/views/index.php" true hFile;
if (%hFile, -nt, %FILEIO_INVALID_HANDLE) {
    fwriteline %hFile "<script>";
    fwriteline %hFile "    document.addEventListener('DOMContentLoaded', function() {";
    fwriteline %hFile "        const game = new Phaser.Game(gameconfig);";
    fwriteline %hFile "    });";
    fwriteline %hFile "</script>";

    fclose %hFile;
};

sys {cd /d "%szProjectPath%szProjectName" && npm run build};

fopen "%szProjectPath%szProjectName/launch.dnys" true hFile;
if (%hFile, -nt, %FILEIO_INVALID_HANDLE) {
    fwriteline %hFile "# Autogenerated project launcher script";
    fwriteline %hFile {require "auto";};
    fwriteline %hFile {const SERVER_PORT int <= 8000;};
    fwriteline %hFile {global project_path string;};
    fwriteline %hFile {getscriptpath project_path;};
    fwriteline %hFile {global server_url string;};
    fwriteline %hFile {set server_url <= "http://localhost";};
    fwriteline %hFile "if (%SERVER_PORT, -nt, 80) {";
    fwriteline %hFile {    set server_url <= "%server_url:%SERVER_PORT";};
    fwriteline %hFile "}";
    fwriteline %hFile {print "Launching project instance on %server_url";};
    fwriteline %hFile {aut_run "php" "asatru serve %SERVER_PORT" "%project_path" void;};
    fwriteline %hFile {aut_run "%server_url" "" "" void;};
    
    fclose %hFile;
};

print "%CR%LFJob done%CR%LF";

Fix XAMPP MySQL shutdown error

# Fix XAMPP MySQL error: Repeatedly unexpected MySQL shutdown
# More info: https://stackoverflow.com/a/61859561

require "array";
require "fileio";

const MYSQL_PATH string <= "C:/path/to/mysql";

global checkdir bool;
global enumres bool;

array arrExcludedFolders string 4 (
    "mysql", 
    "performance_schema", 
    "phpmyadmin", 
    "test"
);

print "Fixing files and folders...";

dexists "%MYSQL_PATH/data_old" checkdir;
if (%checkdir, -eq, true) {
    sys {rmdir /S /Q "%MYSQL_PATH/data_old"};
};

sys {move /Y "%MYSQL_PATH/data" "%MYSQL_PATH/data_old"};
sys {xcopy "%MYSQL_PATH/backup" "%MYSQL_PATH/data/" /E /V /I /Y};

function IsExcludeFolder bool(folderName string)
{
    result false;
    
    for (count, 0, %arrExcludedFolders.length, -inc) {
        if (%folderName, -eq, %arrExcludedFolders[%count]) {
            result true;
        };
    };
};

function CopyDbFolders int(baseObject string, iteratedObject string)
{
    local dirtype bool;
    local exclexists bool;
    
    fdisdir "%baseObject%iteratedObject" dirtype;
    if (%dirtype, -eq, true) {
        call IsExcludeFolder("%iteratedObject") => exclexists;
    
        if (%exclexists, -eq, false) {
            sys {xcopy "%baseObject%iteratedObject" "%MYSQL_PATH/data/%iteratedObject" /E /V /I /Y};
        };
    };

    result 1;
};

denum {%MYSQL_PATH/data_old/} "*.*" "CopyDbFolders" enumres;

sys {robocopy "%MYSQL_PATH/data_old" "%MYSQL_PATH/data" "ibdata1" /NDL /NJH /NJS /NC /NS /IS};

print "Done.";

Post status and media to Mastodon

# Post status with media to Mastodon

require "strings";

const MASTODONBOT_SERVER_INSTANCE string <= "https://mastodon.social";
const MASTODONBOT_ACCESS_TOKEN string <= "your-access-token-here";

const TARGET_FILE string <= {C:/path/to/image};
const STATUS_TEXT string <= "Here is a fancy media toot!";

global strResult string;
global iStrPos int;
global iStrStart int;
global iStrLen int;
global iLoop int;
global bLoop bool;
global strCurChar string;
global strFileIdent string;

sys {curl -X POST -F "file=@%TARGET_FILE" -H "Authorization: Bearer %MASTODONBOT_ACCESS_TOKEN" "%MASTODONBOT_SERVER_INSTANCE/api/v2/media" --silent} strResult;

s_getlen %strResult iStrLen;

s_find "%strResult" {"id":} iStrPos;
if (%iStrPos, -gre, 1) {
    set iStrStart <= %iStrPos;
    += iStrStart 6;

    set iLoop <= %iStrStart;
    set bLoop <= true;

    while (%bLoop, -eq, true) {
        s_getchar "%strResult" %iLoop strCurChar;
        
        if (%strCurChar, -eq, ",") {
            set bLoop <= false;
        } else {
            s_append strFileIdent %strCurChar;
        };
        
        ++ iLoop;
    };

    s_getlen %strFileIdent iStrLen;
    -- iStrLen;

    s_substr "%strFileIdent" 0 %iStrLen strFileIdent;

    sys {curl -X POST -F "status=%STATUS_TEXT" -F "media_ids[]=%strFileIdent" -F "visibility=public" -H "Authorization: Bearer %MASTODONBOT_ACCESS_TOKEN" "%MASTODONBOT_SERVER_INSTANCE/api/v1/statuses" --silent} strResult;

    s_find "%strResult" "%STATUS_TEXT" iStrPos;
    if (%iStrPos, -gre, 0) {
        print "Status with media was posted successfully";
    } else {
        print "Failed to post status with media.";
    };
} else {
    print "Error: File upload failed.";
};

pause;

Speech API convenience class

# Speech API convenience class

const SPEECH_DEFAULT_VOICE string <= "Microsoft Zira Desktop";

class CSpeechAPI {
    member mLocale string;
    
    method construct void()
    {
        set %this.mLocale <= "en";
        spk_setvoice "%SPEECH_DEFAULT_VOICE";
    };
    
    method setLocale bool(locale string)
    {
        result true;
    
        set %this.mLocale <= "%locale";
        
        if (%locale, -eq, "en") {
            spk_setvoice "Microsoft Zira Desktop";
        } elseif (%locale, -eq, "de") {
            spk_setvoice "Microsoft Hedda Desktop";
        } else {
            result false;
        };
    };
    
    method setVolume void(volume int)
    {
        spk_setvolume %volume;
    };
    
    method setPitch void(pitch int)
    {
        spk_setpitch %pitch;
    };
    
    method setSpeed void(speed int)
    {
        spk_setspeed %speed;
    };

    method speak void(message string, asynchronous bool)
    {
        if (%asynchronous, -nt, true) {
            spk_speak "%message";
        } else {
            spk_speakasync "%message";
        };
        
        spk_setvoice "%SPEECH_DEFAULT_VOICE";
    };
    
    method speak_s void(message string)
    {
        call @%this.speak("%message", 0) => void;
    };
    
    method speak_a void(message string)
    {
        call @%this.speak("%message", 1) => void;
    };
};

global gSpeech class;
set @gSpeech <= CSpeechAPI;
call @gSpeech.setVolume(100);
call @gSpeech.setPitch(0);
call @gSpeech.setSpeed(0);
call @gSpeech.setLocale("en");

Download YouTube Video Thumbnail

# Download YouTube video thumbnail to file

hideconsole;

require "input";
require "strings";
require "forms";

global wndstyles int;
global frmMain int;
global bFormRes bool;
global szVideoUrl string;
set szVideoUrl <= "";

function downloadToFile bool(url string, dest string)
{
    result false;
    
    local iSubStr int;
    local szIdent string;
    local szVideo string;
    
    s_find "%url" "?v=" iSubStr;

    if (%iSubStr, -gre, 0) {
        += iSubStr 3;
        s_substr "%url" "%iSubStr" "-1" "szIdent";
        
        set szVideo <= "https://img.youtube.com/vi/%szIdent/maxresdefault.jpg";
        
        sys { curl -o "%dest" "%szVideo"  --silent } szResponse;
        
        result true;
    };
};

function btnSaveVideoThumbnail_OnClick void()
{
    local szTxtVideoUrl string;
    local szTxtDestPath string;
    local bDownloadResult bool;
    
    wnd_gettextboxtext frmMain txtVideoUrl szTxtVideoUrl;
    wnd_gettextboxtext frmMain txtSaveDest szTxtDestPath;
    
    call downloadToFile("%szTxtVideoUrl", "%szTxtDestPath") => bDownloadResult;
    
    if (%bDownloadResult, -eq, true) {
        wnd_setcomptext "frmMain" "CLabel" "lblResult" "Success!";
    } else {
        wnd_setcomptext "frmMain" "CLabel" "lblResult" "Error...";
    };
};

bitop "or" (%WS_OVERLAPPED, %WS_SYSMENU, %WS_VISIBLE) wndstyles;

wnd_spawnform "frmMain" "Download YouTube Thumbnail" 200 300 500 250 %wndstyles frmMain;

wnd_isformvalid frmMain bFormRes;

if (%bFormRes, -eq, false) {
    print "Failed to create form.";
    pause;
    exit;
};

wnd_spawnlabel frmMain "lblVideoUrl" 20 10 50 20 "URL: ";
wnd_spawntextbox frmMain "txtVideoUrl" 20 35 450 20 "https://www.youtube.com/watch?v=012345";

wnd_spawnlabel frmMain "lblSaveDest" 20 75 50 20 "Dest: ";
wnd_spawntextbox frmMain "txtSaveDest" 20 100 450 20 "%USERPROFILE%\Desktop\maxresdefault.jpg";

wnd_spawnbutton frmMain "btnSaveVideoThumbnail" 20 155 200 30 "Save";

wnd_spawnlabel frmMain "lblResult" 230 160 100 20 " ";

while (%bFormRes, -eq, true) {
    wnd_process;

    wnd_isformvalid frmMain bFormRes;
};

Sample IRC Chat Client

# Sample IRC chat client

hideconsole;

require "strings";
require "forms";
require "irc";
require "ini";
require "auto";

const FORM_TITLE string <= "IRC Chat Client";

global INI_Server string;
global INI_Port string;
global INI_OAuthToken string;
global INI_Caps string;
global INI_Username string;
global INI_Channel string;
global INI_Verbose string;

global frmMain int;
global bres bool;
global wndstyles int;
global join_ok bool;
global serverIdent string;
global scriptpath string;
global verbose bool;

set join_ok <= false;
set serverIdent <= "";

getscriptpath scriptpath;

ini_read "%scriptpath/settings.ini" "settings" "server" INI_Server;
ini_read "%scriptpath/settings.ini" "settings" "port" INI_Port;
ini_read "%scriptpath/settings.ini" "settings" "oauth" INI_OAuthToken;
ini_read "%scriptpath/settings.ini" "settings" "caps" INI_Caps;
ini_read "%scriptpath/settings.ini" "settings" "username" INI_Username;
ini_read "%scriptpath/settings.ini" "settings" "channel" INI_Channel;
ini_read "%scriptpath/settings.ini" "settings" "verbose" INI_Verbose;

set verbose <= %INI_Verbose;

function Util_FilterChatMessage string(content string)
{
    local raute int;
    local result string;
    
    set result <= "";
    
    result "%result";
    
    s_find "%content" "PRIVMSG #" raute;
    if (%raute, -gr, 0) {
        local subtoken string;
        
        s_substr "%content" %raute -1 subtoken;
        
        if ("%subtoken", -nt, "") {
            local colon int;
            
            s_find "%subtoken" ":" colon;
            if (%colon, -gr, 0) {
                ++ colon;
                
                s_substr "%subtoken" %colon -1 result;
                
                result "%result";
            };
        };
    };
};

function Util_FilterChatSender string(content string)
{
    local colon int;
    local exclamation int;
    local result string;
    
    set result <= "";
    
    result "%result";
    
    s_find "%content" ":" colon;
    s_find "%content" "!" exclamation;
    
    if (%colon, -eq, 0) {
        if (%exclamation, -gr, 1) {
            local tokenlen int;
            
            set tokenlen <= %exclamation;
            
            ++ colon;
            -= tokenlen %colon;
            
            s_substr "%content" %colon %tokenlen result;
            
            result "%result";
        };
    };
};

function ProcessIrcThread bool()
{
    local threadircvalid bool;
    
    set threadircvalid <= true;
    
    while (%threadircvalid, -eq, true) {
        irc_process irc;
        irc_isvalid irc threadircvalid;
    };
    
};

function irc_OnConnected void()
{
    wnd_setformtitle "frmMain" "%FORM_TITLE - Connected to %INI_Server";
    wnd_appendtextboxtext "frmMain" "txtChat" "Connected to server";
    
    aut_addtimer tmrKeyCheck 100;
    
    irc_send irc "PASS oauth:%INI_OAuthToken";

    if (%INI_Caps, -nt, "") {
        irc_send irc "CAP REQ :%INI_Caps";
    };

    irc_send irc "NICK %INI_Username";    
    irc_send irc "JOIN #%INI_Channel";
};

function irc_OnRecieve void(message string)
{
    local find int;
    local curdatetime string;
    local subtext string;
    
    fmtdatetime "%Y-%m-%d %H:%M:%S" curdatetime;
    
    if (%verbose, -eq, true) {
        wnd_appendtextboxtext "frmMain" "txtChat" "[%curdatetime] **System** %message";
    };
    
    s_find "%message" ":%INI_Username.tmi.twitch.tv 353" find;
    
    if (%find, -eq, 0) {
        set join_ok <= true;
        
        wnd_setformtitle "frmMain" "%FORM_TITLE - Joined #%INI_Channel";
        wnd_appendtextboxtext "frmMain" "txtChat" "[%curdatetime] **System** Successfully joined channel";
        
        s_find "%message" " :" find;
        if (%find, -gr, 1) {
            += find 2;
            s_substr "%message" %find -1 subtext;
            
            if (%subtext, -nt, "") {
                s_tokenize "%subtext" " " userlist;
                
                for (i, 0, %userlist.count, -inc) {
                    wnd_lbadditem "frmMain" "lstUsers" "%userlist[%i]";
                };
            };
        };
    };
    
    if (%join_ok, -eq, true) {
        s_find "%message" "PING" find;
        if (%find, -eq, 0) {
            local ping string;

            s_substr "%message" 5 -1 ping;
            set serverIdent <= "%ping";
            
            irc_send irc "PONG %ping";

            if (%verbose, -eq, true) {
                wnd_appendtextboxtext "frmMain" "txtChat" "Pong: %ping";
            };
        };
        
        s_find "%message" "PRIVMSG #" find;
        if (%find, -gr, 0) {
            local chatMsg string;
            local chatSender string;
            local cmdchar int;
            
            call Util_FilterChatMessage("%message") => chatMsg;
            call Util_FilterChatSender("%message") => chatSender;
            
            wnd_appendtextboxtext "frmMain" "txtChat" "[%curdatetime] (%chatSender) %chatMsg";
        };
        
        s_find "%message" ":tmi.twitch.tv 421" find;
        if (%find, -eq, 0) {
            local unknowncmd string;
            local unlen int;
            local unknwstartpos int;
            
            s_getlen "%INI_Username" unlen;
            
            set unknwstartpos <= 19;
            += unknwstartpos %unlen; 
            
            s_substr "%message" %unknwstartpos -1 unknowncmd;
            
            wnd_appendtextboxtext "frmMain" "txtChat" "[%curdatetime] (tmi.twitch.tv) %unknowncmd";
        };
    };
};

function irc_OnDisconnected void()
{
    wnd_setformtitle "frmMain" "%FORM_TITLE";
    wnd_appendtextboxtext "frmMain" "txtChat" "Disconnected from server";
};

function irc_OnError void(errorcode int)
{
    wnd_appendtextboxtext "frmMain" "txtChat" "Error occured: %errorcode";
};

function lstUsers_OnDoubleClick void(item int)
{
    local selusername string;

    wnd_lbgettext "frmMain" "lstUsers" %item selusername;

    if (%selusername, -nt, "") {
        wnd_settextboxtext "frmMain" "txtInput" "/PRIVMSG %selusername :";
    };
};

function lstUsers_OnSelectionChange void(newItem int)
{
};

function btnSend_OnClick void()
{
    local inputtext string;
    local curdatetime string;
    local cmdpos int;
    local cmdsubstr string;
    
    fmtdatetime "%Y-%m-%d %H:%M:%S" curdatetime;
    wnd_gettextboxtext "frmMain" "txtInput" inputtext;
    
    if (%inputtext, -nt, "") {
        s_find "%inputtext" "/" cmdpos;
        
        if (%cmdpos, -eq, 0) {
            s_substr "%inputtext" 1 -1 cmdsubstr;
            irc_send irc "%cmdsubstr";

            wnd_settextboxtext "frmMain" "txtInput" "";
            wnd_appendtextboxtext "frmMain" "txtChat" "[%curdatetime] (Command) %inputtext";
        } else {
            irc_send irc "PRIVMSG #%INI_Channel :%inputtext";

            wnd_settextboxtext "frmMain" "txtInput" "";
            wnd_appendtextboxtext "frmMain" "txtChat" "[%curdatetime] (%INI_Username) %inputtext";
        };
    };
};

function tmrKeyCheck_OnElapsed bool()
{
    local keyflag bool;
    local focushandle int;
    local textboxhandle int;
    
    aut_iskeydown 13 keyflag;
    if (%keyflag, -eq, true) {
        wnd_getcurrentfocus focushandle;
        wnd_getcomphandle "frmMain" "CTextbox" "txtInput" textboxhandle;
        
        if (%focushandle, -eq, %textboxhandle) {
            call btnSend_OnClick() => void;
        };
    };
    
    result true;
};

bitop "or" (%WS_OVERLAPPED, %WS_SYSMENU, %WS_VISIBLE) wndstyles;

wnd_spawnform "frmMain" "%FORM_TITLE" 200 300 767 354 %wndstyles frmMain;
wnd_isformvalid frmMain bres;

wnd_setformicon "frmMain" "app.ico";

wnd_spawntextbox "frmMain" "txtChat" 1 1 600 290 "";
wnd_settextboxmultiline "frmMain" "txtChat";
wnd_spawnlistbox "frmMain" "lstUsers" 601 1 150 323 "";
wnd_spawntextbox "frmMain" "txtInput" 1 292 512 20 "Hello from an AquaShell IRC client";
wnd_spawnbutton "frmMain" "btnSend" 512 292 90 20 "Send";

if (%bres, -eq, false) {
    print "Failed to create form.";
    pause;
    exit;
};

irc_spawn irc "%INI_Server" %INI_Port bres;

threadfunc ProcessIrcThread;

while (%bres, -eq, true) {
    wnd_process;
    aut_calctimers;

    wnd_isformvalid frmMain bres;
};

irc_release irc;
wnd_freeform frmMain;