// SPDX-License-Identifier: MIT // Copyright (c) 2026 Incoprea // Audit a daily UTC notice schedule // Not compiled or tested in-world // Setup: Add a saved plain-text notecard named Config. Use 24-hour UTC times such as 09:30|Workshop opens. Touch as owner; reset to scan again. // Stop / restore: Remove or disable. This auditor never changes object settings or inventory. // Notes: Reads at most 40 short lines, skips blanks and # comments, and times out each asynchronous request after 20 seconds. Validates format only; it does not schedule broadcasts. Messages must fit a conservative 120-character limit. // License: see LICENSE in this distribution. // Original Incoprea example. MIT. integer numberOK(string value) { integer i; if(value=="" || llStringLength(value)>6)return FALSE; for(i=0;i23 || llList2Integer(clock,1)>59) { issue("Invalid HH:MM time."); return; } string message=llList2String(p,1); if(message=="" || llStringLength(message)>120)issue("Message must be 1-120 characters."); if(llListFindList(times,[time])!=-1)issue("Duplicate scheduled time."); else times += [time]; } default { touch_start(integer touches) { if(llDetectedKey(0)!=llGetOwner())return; if(pending!=NULL_KEY || finished) { llOwnerSay("Reset before starting another audit."); return; } if(llGetInventoryType("Config")!=INVENTORY_NOTECARD) { llOwnerSay("Add a saved Config notecard."); return; } requestLine(); } dataserver(key query,string data) { if(query!=pending || pending==NULL_KEY)return; if(data==EOF) { finish(); return; } data=llStringTrim(data,STRING_TRIM); if(data!="" && llGetSubString(data,0,0)!="#") { ++scannedRows; check(data); } ++lineNumber; if(lineNumber>=40) { llOwnerSay("40-line cap reached; report may be partial."); finish(); return; } requestLine(); } timer() { pending=NULL_KEY; finished=TRUE; llSetTimerEvent(0); llOwnerSay("Audit timed out; partial checks only. Reset to retry."); } changed(integer flags) { if(flags & (CHANGED_OWNER|CHANGED_INVENTORY))llResetScript(); } }