say command
 

News:

29 December 2022 - PtokaX 0.5.3.0 (20th anniversary edition) released...
11 April 2017 - PtokaX 0.5.2.2 released...
8 April 2015 Anti child and anti pedo pr0n scripts are not allowed anymore on this board!
28 September 2015 - PtokaX 0.5.2.1 for Windows 10 IoT released...
3 September 2015 - PtokaX 0.5.2.1 released...
16 August 2015 - PtokaX 0.5.2.0 released...
1 August 2015 - Crowdfunding for ADC protocol support in PtokaX ended. Clearly nobody want ADC support...
30 June 2015 - PtokaX 0.5.1.0 released...
30 April 2015 Crowdfunding for ADC protocol support in PtokaX
26 April 2015 New support hub!
20 February 2015 - PtokaX 0.5.0.3 released...
13 April 2014 - PtokaX 0.5.0.2 released...
23 March 2014 - PtokaX testing version 0.5.0.1 build 454 is available.
04 March 2014 - PtokaX.org sites were temporary down because of DDOS attacks and issues with hosting service provider.

Main Menu

say command

Started by Fangs404, 28 April, 2005, 00:32:53

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Fangs404

this is a fun little command that ops can use to make people say things in mainchat.  ynhub had the feature, and it was really funny sometimes, so i thought i'd write a script that does the same thing.

example:
type "!say nick message"
and you'll see
"[17:31] message"
in the mainchat.

-- Say v1.0
-- by Fangs404
-- last modified 4/27/05
-- tested with PtokaX 0.3.3.0 build 17.03

sBot = frmHub:GetHubBotName()
tPrefixes = frmHub:GetPrefixes()

function ChatArrival(user, sData)
	local s,e,sCmd,sNick,sMsg = string.find(sData, "^%b<>%s*(%S+)%s*(%S*)%s*(.*)|")
	if (not user.bOperator) or (not isSayCmd(sCmd)) then
		return
	end
	if sNick == "" then
		SendToNick(user.sName, "<"..sBot.."> ".."Please provide a nick to use the say command.")
		return 1
	elseif sMsg == "" then
		SendToNick(user.sName, "<"..sBot.."> ".."Please enter a message for "..sNick.." to say.")
		return 1
	end
	SendToAll("<"..sNick.."> "..sMsg)
	return 1
end

function isSayCmd(sCmd)
	for index in tPrefixes do
		if sCmd == (tPrefixes[index].."say") then
			return 1
		end
	end
	return
end

Fangs404

#1
fixed up some stuff and reorganized the code.

-- Say v1.1
-- by Fangs404
-- last modified 4/27/05
-- tested with PtokaX 0.3.3.0 build 17.03

sBot = frmHub:GetHubBotName()
tPrefixes = frmHub:GetPrefixes()

function ChatArrival(user, sData)
	local s,e,sCmd,sNick,sMsg = string.find(sData, "^%b<>%s*(%S+)%s*(%S*)%s*(.*)|")
	if (not user.bOperator) or (not isSayCmd(sCmd)) then
		return
	end
	if (not isValidSayCmd(user, sNick, sMsg)) then
		return 1
	end
	SendToAll(sNick, sMsg)
	return 1
end

function isValidSayCmd(user, sNick, sMsg)
	if string.len(sNick) == 0 then
		user:SendData(sBot, "Please provide a nick to use the say command.")
		return
	elseif string.len(sMsg) == 0 then
		user:SendData(sBot, "Please enter a message for "..sNick.." to say.")
		return
	end
	return 1
end

function isSayCmd(sCmd)
	for index in tPrefixes do
		if sCmd == (tPrefixes[index].."say") then
			return 1
		end
	end
	return
end

Fangs404

#2
yay for more generic code.  :)

-- Say v1.2
-- by Fangs404
-- last modified 4/28/05
-- tested with PtokaX 0.3.3.0 build 17.03

sBot = frmHub:GetHubBotName()
tPrefixes = frmHub:GetPrefixes()

function ChatArrival(user, sData)
	local s,e,sCmd,sNick,sMsg = string.find(sData, "^%b<>%s*(%S+)%s*(%S*)%s*(.*)|")
	if (not user.bOperator) or (not isValidCmd(sCmd, "say")) then
		return
	end
	if (not isValidSayCmd(user, sNick, sMsg)) then
		return 1
	end
	SendToAll(sNick, sMsg)
	return 1
end

function isValidSayCmd(user, sNick, sMsg)
	if string.len(sNick) == 0 then
		user:SendData(sBot, "Please provide a nick to use the say command.")
		return
	elseif string.len(sMsg) == 0 then
		user:SendData(sBot, "Please enter a message for "..sNick.." to say.")
		return
	end
	return 1
end

function isValidCmd(sCurCmd, sNeedCmd)
	for index in tPrefixes do
		if sCurCmd == (tPrefixes[index]..sNeedCmd) then
			return 1
		end
	end
	return
end

wegface

Nice one Fangs! Just what i was after. Good fun. That was best thing about Ynhub hahahahaa.

Herodes

haven't tested ... but wouldn't this do exactly the same thing ?
function ChatArrival( user, data )
	
	local s,e, nick, msg = string.find( data, "^%b<>%s*[%"..table.concat(frmHub:GetPrefixes(), "%").."]say%s+(%S+)%s+(.+)|$")
	if nick then
		SendToAll( nick, msg )
		return 1;
	end

end

Fangs404

#5
QuoteOriginally posted by Herodes
haven't tested ... but wouldn't this do exactly the same thing ?
function ChatArrival( user, data )
	
	local s,e, nick, msg = string.find( data, "^%b<>%s*[%"..table.concat(frmHub:GetPrefixes(), "%").."]say%s+(%S+)%s+(.+)|$")
	if nick then
		SendToAll( nick, msg )
		return 1;
	end

end

that does work, but it's not generic enough for me to be able to put in error messages.  i need to make sure that the op has typed !say rather than !topic, and your code doesn't allow for that.

local s,e,sCmd,sNick,sMsg = string.find(sData, "^%b<>%s+(["..table.concat(frmHub:GetPrefixes()).."])(%S+)%s+(%S+)%s+(.+)|")

seems like it should work, but it won't assign the command to sCmd.

Herodes

Just trying to give a concept with the script lines posted .. there is no use for 3 global functions for this kind of script..

This is a more "generic" version ..
function ChatArrival( user, data )
	
	local s,e, args = string.find( string.sub( data,1, -1),  "^%b<>%s+[%"..table.concat(frmHub:GetPrefixes(), "%").."]say%s+(.+)|$")
	if args then
		local s,e, nick, msg = string.find( args, "^(%S+)%s*(.*)")
		if (not nick) or (not msg) or (string.len(msg) == 0) then
			user:SendData( frmHub:GetHubBotName(), "Syntax Error Use : !say  " );
			return 1;
		end
		SendToAll( nick, msg ) return 1;
	end

end

Fangs404

i redid a lot of mine.  i'm going to keep it broken up into 2 separate functions because the isValidCmd function comes in handy in practically all scripts, so it's nice to keep it generic.

-- Say v1.3
-- by Fangs404
-- last modified 4/28/05
-- tested with PtokaX 0.3.3.0 build 17.03

sBot = frmHub:GetHubBotName()
tPrefixes = frmHub:GetPrefixes()

function ChatArrival(user, sData)
	local s,e,sCmd,sNick,sMsg = string.find(sData, "^%b<>%s*(%S*)%s*(%S*)%s*(.*)|")
	if user.bOperator and isValidCmd(sCmd, "say") then
		if sNick == "" then
			user:SendData(sBot, "Please provide a nick to use the say command.")
			return 1
		elseif sMsg == "" then
			user:SendData(sBot, "Please enter a message for "..sNick.." to say.")
			return 1
		end
		SendToAll(sNick, sMsg)
		return 1
	end
end

function isValidCmd(sCurCmd, sNeedCmd)
	for index in tPrefixes do
		if sCurCmd == (tPrefixes[index]..sNeedCmd) then
			return 1
		end
	end
end

Herodes

QuoteOriginally posted by Fangs404
i redid a lot of mine.  i'm going to keep it broken up into 2 separate functions because the isValidCmd function comes in handy in practically all scripts, so it's nice to keep it generic.
Though it is a simple way of doing it by using the isValidCmd function, it is much more simple to use a regexp to do it.

The way i propose uses :
- one Api call,
- one lua table lib function call,
- one string.find with regexp.
- two concatations ( .. )

The isValidCmd function uses:
- two global vars ( tPrefixes , isValidCmd [function] ),
- an iterator ( for ... do ... end )
- an expression ( == )
- a concatation ( .. )

The trade off is minimal but I like to keep it compact ..

Fangs404

#9
QuoteOriginally posted by Herodes
Though it is a simple way of doing it by using the isValidCmd function, it is much more simple to use a regexp to do it.

The way i propose uses :
- one Api call,
- one lua table lib function call,
- one string.find with regexp.
- two concatations ( .. )

The isValidCmd function uses:
- two global vars ( tPrefixes , isValidCmd [function] ),
- an iterator ( for ... do ... end )
- an expression ( == )
- a concatation ( .. )

The trade off is minimal but I like to keep it compact ..
this is an interesting point.  in terms of run time and big O, ours require the same big O - O(N).  keep in mind that behind the scenes, the table.concat function is just a simple loop that combines the elements together.

in terms of space, though, my way requires only one global variable and one function call, the method to retrieve the prefixes only occurs once in my code per session.

theoretically, though, our methods will have essentially the same runtime and space requirements.

Herodes

QuoteOriginally posted by Fangs404
in terms of run time and big O, ours require the same big O - O(N).
hmm .. could you be more clear on that ..
QuoteOriginally posted by Fangs404
keep in mind that behind the scenes, the table.concat function is just a simple loop that combines the elements together.
yep.. done in pure C .. so its impossible that a for .. do *multiple concatations" end is quicker..
QuoteOriginally posted by Fangs404
in terms of space, though, my way requires only one global variable and one function call, the method to retrieve the prefixes only occurs once in my code per session.
Nowhere near in fact. There are no global variables to take up space in the mem in the way I propose, while in the isValidCmd method there are two ( a function and a table ). also the pattern for the pattern matching is also compiled once per session .. exactly as yours.

QuoteOriginally posted by Fangs404
theoretically, though, our methods will have essentially the same runtime and space requirements.
In fact that is the point y I am commenting this post right now .. mine uses cpu while giving up mem, while, the method you propose takes mem to provide for cpu time .. but since there isn't any large amount of data involved and that this data isn't needed later in the script logic, I think that the tip scales to using the cpu..

Fangs404

#11
QuoteOriginally posted by Herodes
hmm .. could you be more clear on that ..
big O is a programming concept that tells the programmer the approximate run-time cost a program or chunk of code will cost.  O(N) means it has a linear runtime - for loops always take a runtime of O(N).  nested for loops, though, will use O(N^2).  that's an extremely abbreviated version and is better taught in a classroom.  you can google it if you'd like to know more - google "big o."

Quoteyep.. done in pure C .. so its impossible that a for .. do *multiple concatations" end is quicker..
how is it impossible?  regardless of the programming language LUA is implemented in, there's no reason to expect a for loop to take longer than a concat operation which is, under the hood, almost guaranteed to be implemented with a for loop.

QuoteNowhere near in fact. There are no global variables to take up space in the mem in the way I propose, while in the isValidCmd method there are two ( a function and a table ). also the pattern for the pattern matching is also compiled once per session .. exactly as yours.
sure your function will be calculated once per session, but you call the GetPrefixes function each time.  i haven't looked at how LUA is implemented or compiled, but i'd be willing to bet that your function will be calling GetPrefixes every single time a new mainchat message appears.  mine only calls it once.  like i said, though, i could be wrong because i haven't tried it, yet.  it'd be really easy to test.

QuoteIn fact that is the point y I am commenting this post right now .. mine uses cpu while giving up mem, while, the method you propose takes mem to provide for cpu time .. but since there isn't any large amount of data involved and that this data isn't needed later in the script logic, I think that the tip scales to using the cpu..
again, this depends on how LUA is implemented.  in fact, i'm going to go test it right now.  i know for a fact because i've tested mine, that mine only calls GetPrefixes once (each time the script is reloaded).

Fangs404

#12
yeah, i was right.  your method calls GetPrefixes at each call, so yours does a lot more work than mine does to find out if it's a valid command.  i did this test by calling *say with * not listed in the accepted prefixes under the options menu.  then, i added in the * prefix, and without restarting the script, i tried *say , and it worked.

personally, i think the cost of calling GetPrefixes for every single mainchat message is greater than that of the memory used to store the few acceptable prefixes in a global variable and reference them.

Optimus

-- Say v1.3
-- by Fangs404
-- last modified 4/28/05
-- tested with PtokaX 0.3.3.0 build 17.03
-- Touched by Optimus for better performence

sBot = frmHub:GetHubBotName()
tPrefixes = {}

Main = function()
	for a,b in pairs(frmHub:GetPrefixes()) do tPrefixes[b] = 1 end
end

function ChatArrival(user, sData)
	local s,e,sPrefix,sCmd,sNick,sMsg = string.find(sData, "%b<>%s*(%S)(%S+)%s*(%S*)%s*(.*)|")
	if sPrefix and tPrefixes[sPrefix] then
		if user.bOperator and sCmd == "say" then
			if sNick == "" then
				user:SendData(sBot, "Please provide a nick to use the say command.")
			elseif sMsg == "" then
				user:SendData(sBot, "Please enter a message for "..sNick.." to say.")
			else
				SendToAll(sNick, sMsg)
			end return 1
		end
	end
end
I couldn't refuse to give it my own try, this is what i had in mind.

- Optimus

Herodes

hmm.. maybe its my personal taste to keep things as compact as possible .. I am convinced about the call-each-time issue .. but I really think it makes for making clear the objectives of scripts rather than their functions. good to have educated ppl in programming langs in here .. as it has always been ;)

Optimus

Well must be a matter of taste, i would prefer mine cause hashing the prefix is faster then looping it.

so i prefer the loop in main function and hash the rest of commands.

- Optimus

Herodes

Just hit me .. isn't this an even better way to do it ?
sBot = frmHub:GetHubBotName()

function Main()
	pCmd = "[%"..table.concat( frmHub:GetPrefixes(), "%").."]"
end

function ChatArrival(user, sData)
	if user.bOperator then
		local s,e, sPrefix, sCmd, sNick, sMsg = string.find( string.sub( sData, 1, -2 ), "%b<>%s*"..pCmd.."(%S+)%s*(%S*)%s*(.*)")
		if sCmd == "say" then
			if sNick == "" then 
				user:SendData(sBot, "Please provide a nick to use the say command."); return 1;
			elseif sMsg == "" then 
				user:SendData(sBot, "Please enter a message for "..sNick.." to say."); return 1;
			end
			SendToAll(sNick, sMsg); return 1;
		end
	end
end

Optimus

Yups verry nice

SMF spam blocked by CleanTalk