Simple Interactive Mode
 

Simple Interactive Mode

Started by amenay, 01 April, 2008, 00:35:29

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

amenay

--[[

	Simple Interactive Mode by amenay.

	Usage notes:
	
		Aside from the general security concerns involved with this sort of script (which any hub owner should be aware of), there are a couple usage
		notes mostly in respect to some of the behavioural aspects of the script.
		
		First, mind your endpipes, the behaviour here varies depending on what you're doing -- if you're defining something from a DC client use \124
		opposed to the HTML escape method of | (which you'll want to use to send messages containing non-delimiting endpipes to your client from
		the hub (See: ReadFile)
		Second,  if you're not familiar with the behaviour of variadic functions and the vararg expression (and how it's used alongside loadstring)
		then you might want to look it up a bit in the mailing list. In short, chunks compiled by loadstring (which are not function with traditional
		paremeters) can receive arguments through the vararg expression. (Example: foo = loadstring( "local tUser, sData = ... <chunk>" ) foo( tUser, sData ) ) 
	
--]]
	
do	
	_PROMPT = "Interactive mode >|";
	tInteractive = { };
	
	tSettings = {
		[1] = "^[" .. ( SetMan.GetString( 29 ):gsub( ( "%p" ), function ( p ) return "%" .. p end ) ) .. "]",
		[2] = "#SIM" or SetMan.GetString( 21 ), --BotName
		[3] = "", --BotDesc
		[4] = "", --BotEmail
		[5] = true, --BotbOp
		[6] = { ["amenay"] = true, ["AnotherTrustedNick"] = true } --Allowed Users by nick.
	}
	
	print = function( ... ) 
		local tBuff = { };
		for _, v in ipairs( { ... } ) do
			tBuff[ #tBuff + 1 ] = tostring( v );
		end
		local SendMethod = SendMethod or function( tUser, sData ) Core.SendToUser( tUser, "$To: " .. tUser.sNick .. " From: " .. tSettings[2] .. " $" .. sData ) end;
		for i, v in pairs( tInteractive ) do
			SendMethod( v, table.concat( tBuff, "\t\t" ) );
		end
	end
	
end

function OnStartup( )
	Core.RegBot( tSettings[2], tSettings[3], tSettings[4], true );
end

OnError = print;

function OnExit( )
	print( "Interactive mode interupted by script exit.|" );
end

function UserDisconnected( tUser, sData )
	if tInteractive[ tUser.uptr ] then
		tInteractive[ tUser.uptr ] = nil;
	end
end

OpDisconnected = UserDisconnected;
RegDisconnected = UserDisconnected;

function ToArrival( tUser, sData )

	local sToUser = sData:match( "^(%S+)", 6 );
	if sToUser == tSettings[2] then
		local nInitIndex = #sToUser + 18 + #tUser.sNick * 2;
		if tInteractive[ tUser.uptr ] then
			local sBody = sData:sub( nInitIndex, -2 );
			Core.SendToUser( tUser, "$To: " .. tUser.sNick .. " From: " .. tSettings[2] .." $" .. sBody .. "" );
			local foo = assert( loadstring( sBody ) );
			local bStatus, ret =  pcall( foo, tUser, sData );
			if tInteractive[ tUser.uptr ] then Core.SendToUser( tUser, "$To: " .. tUser.sNick .. " From: " .. tSettings[2] .." $" .. _PROMPT ) end;
			if bStatus then 
				return ret or bStatus;
			else
				return error( ret ), bStatus;
			end
		end
		
		if sData:match( tSettings[1], nInitIndex ) then
			local sCmd = sData:match( "^(%w+)", nInitIndex + 1 );
			if sCmd then
				sCmd = sCmd:lower( );
				if tCommandArrivals[ sCmd ] then
					if tCommandArrivals[ sCmd ].Permissions[ tUser.iProfile ] then
						local sMsg;
						if ( nInitIndex + #sCmd ) <= #sData + 1 then sMsg = sData:sub( nInitIndex + #sCmd + 2 ) end;
						return tCommandArrivals[ sCmd ]:Action( tUser, sMsg );
					else
						return Core.SendPmToUser( tUser, tSettings[2],  "*** Permission denied.|" ), true;
					end
				else
					return false;
				end
			end
		end
	end
	
end

--Commands

tCommandArrivals = {
	
	imode = {
		Permissions = {
			[0] = true, [1] = true;
		}
	}

};

function tCommandArrivals.imode:Action( tUser )
	if tSettings[6][ tUser.sNick ] then
		tInteractive[ tUser.uptr ] = tUser;
		return Core.SendPmToUser( tUser, tSettings[2], "*** Entering interactive mode. Type tInteractive[ Core.GetUser( \"" .. tUser.sNick ..
			"\" ).uptr ] = nil to end.|$To: " .. tUser.sNick .. " From: " .. tSettings[2] .. " $" .. _PROMPT ), true;
	end
end

-- Useful Functions

function EndSIM( tUser )
	tInteractive[ tUser.uptr ] = nil;
	Core.SendPmToUser( tUser, tSettings[2], "*** Leaving interactive mode.|" );
end

function ReadFile( sName ) --Reads this script by default.
	sName = sName or ScriptMan.GetScript( ).sName;
	local fData, sError = io.open( sName );
	if not sError then
		local sContents = "\n" .. fData:read( "*a" ):gsub( "|", "&#124;" );
		print( sContents );
	else
		error( sError );
	end
	fData:close( );
end


A script I've found infinitely useful in configuring hubs and testing other scripts -- works well as a drop-in debug solution as well. It's more for advanced users, and people that know some Lua than anything. Suggestions welcome.

amenay

Alright, so I've made this into a module to make it a bit easier to drop into other scripts. There are some notes in the rar covering a few features and eccentricities. I highly recommend this script to anyone attempting to debug/optimize a script or for observing behavior and testing new ideas. I've not really added much over the last few months, and just decided it had enough beef to put out there. I'm hoping to post a few snippets in the near future showing some of the tasks which can be accomplished with it, since some of them aren't quite so plain.

Questions and suggestions are highly welcome per usual.

PS: Use at your own risk.

SMF spam blocked by CleanTalk