# DCC channels.. by Ian Frechette  (shoot me now) (make it stop)
# Started 2-13-93
# To use.. 
# /load dccchan
# /makeid nickname
# /openport port        (to listen for connection on port) or
# /closeport port       (close listening port)
# /opencon host port    (to connect to existing dcc channel)
# /whoon                (list who is on the channel)
# /query /d_msg
# type to your hearts content
#
# /dpart to leave

@ RCS.dccchan = [$$Header: /home/cvs/ircii/script/dccchan,v 1.2 2001/08/12 15:44:17 mrg Exp $$]
@ dchan.portnum = 7000

# open listening connection on the specified port number
# the $dchan.portnum is default if not given.
alias openport {
	if (myuniquid)
	{
		if ([$0])
		{ @ dchan.portnum = [$0] }
		echo *** Opening listen on port $listen($dchan.portnum)
	}
	{
		echo *** Please use  /makeid <nick>   before opening port
	}
}

alias closeport {
	if ([$0])
	{
		if ([$0])
		{ @ dchan.portnum = [$0] }
		echo *** closing listen on port $dchan.portnum
		dcc close raw_listen $dchan.portnum
	}
	{
		echo *** Please specify portnumber. /closeport <portnum>
	}
}

# generate a unique_id  NICK_TIME   and nickname
alias makeid {
	if ([$0])
	{
		if (!myuniquid)
		{
			@ myuniquid = encode($0_$time())
			@ mynick = [$0]
		}
	echo *** Your nickname is $mynick and uniquid is $decode($myuniquid)
	}
	{
		echo *** Please supply a nickname. /makeid nickname
	}
}

# opencon  open a connection to another machine and port
# $0 == name of machine
# $1 == port number
alias opencon {
	if (myuniquid)
	{
		echo *** Opening a connection to $0 on port $1
		@ ctmp = connect($0 $1)
		if (ctmp)
		{
			eval @ co.$ctmp = [$ctmp $0]
			update_co $ctmp
			echo *** Connection to $0 established on port $1
		}
		{
			echo *** Failed to connect to $0 on port $1
		}
	}
	{
		echo *** Please use  /makeid <nick>   before opening port
	}
}

# strip ^M's from a line
alias sm @ function_return = strip(
 $*)

# strip the colon from the beginning of a line if there is 1.
alias sc @temp = [$*];if ([$[1]0] == [:]) { @function_return = mid(1 ${@temp -1} $temp) } { @ function_return = temp }


^on #-dcc_raw -45 * debug RAW: $*
^on ^dcc_raw *
^on #^dcc_raw 45 "% % N *" add_connection $0 $1
^on #^dcc_raw 45 "% % C*" remove_connection $sm($0)
^on #^dcc_raw 45 "% % D MEMBER *" add_member $sm($0 $4 $5)
^on #^dcc_raw 45 "% % D R_MEMBER *" rem_member $sm($0 $4)
^on #^dcc_raw 45 "% % D MSG *" do_msg $sm($0 $4-)
^on #^dcc_raw 45 "% % D NICK *" do_nick $sm($0 $4 $5)
^on #^dcc_raw 45 "% % D END *" # do nothing for now


# d_msg  - send a message to everyone else on channel
alias d_msg {
	toall MSG $myuniquid $*
	xecho -level DCC +> $*
}

#  do_msg -   display message and pass on to rest of tree
# $0 == id
# $1 == NICK_TIME
# $2- == content of message
alias do_msg {
	if (rstat[$0] > 0)
	{
		xecho -level DCC +$nicks[$1]+ $2-
		toallbutone $0 MSG $1 $2-
	}
}

# structure co.<connection id> stores <con id> and <host>
# Add a connection when someone connects to this node
alias add_connection {
	debug ADD_CONNECTION: $*
	eval @ co.$0 = [$0 $1]
	# rstat is registered status.  0 - no members,  >0 - members registered
	eval @ rstat.$0 = 0
	update_co $0
}

# update_co - update information for remote connection.. Basically
# just send it everything we know.
# $0 == id of link to fill in.
alias update_co {
	smsg $0 MEMBER $myuniquid $mynick
	foreach nicks ii {
		smsg $0 MEMBER $ii $nicks[$ii]
		debug SENDMEMBER: $ii $nicks[$ii]
	}
	# not used yet, but for future expandability
	smsg $0 END MEMBER
}

# add_member    -  add a node to the database
# other nodes will send MEMBER
# $0 == id
# $1 == NICK_TIME   (nick encoded + time)  unique id
# $2 == nick 
alias add_member {
	if (member[$1])
	{
		debug ADD_MEMBER Dup.. removing $*
		# remove connection silently
		# if we told the rest of the net members would be removed
		# accidentally.. Just pretend this connection didn't happen
	# ARRRRG.. can't do this.. can't remove a dcc connection from 
	# inside an ON DCC.  If I delay with timer 0 close..  then it
	# defeats the purpose here which was to try to head off any
	# already pending garbage.
		timer 0 ^dcc close raw $co[$0]
		^assign -co.$0 }
	{
		debug ADD_MEMBER Adding: $*
		# needs to send MEMBER <nick> <time> to other members
		eval @ rstat.$0 = rstat.$0 + 1
		toallbutone $0 MEMBER $1-
		eval @ cons.$0.$1 = [$0]
		# struct member.NICK_TIME id
		eval @ member.$1 = [$0]
		eval @ nicks.$1 = [$2]
		echo *** Info: $2 \($decode($1)\) has joined the channel
	}
}

#  rem_member    remove a node/member from the database
# $0 == id
# $1 == NICK_TIME    (uniqid)
alias rem_member {
	debug REM_MEMBER $*
	if (rstat[$0]) 
	{
		echo *** Info: $nicks[$1] \($decode($1)\) has left the channel
		toallbutone $0 R_MEMBER $1
		^assign -member.$1
		^assign -nicks.$1
		^assign -cons.$0.$1
		if ((rstat[$0] = rstat[$0] - 1) == 0) {^assign -rstat.$0}
	}
}

# remove_connection    remove a connection
# $0 == id  of connection to remove
alias remove_connection {
	timer 0 ^dcc close raw $co[$0]
	debug REM_CONNECTION: ^dcc close raw $co[$0]
	# remove any members introduced by this connection
	# All of them.. all parts.  This should only happen
	# when a local connection closes.
	# The removal of rstat.$0 is handled within rem_member
	foreach cons.$0 ii {
		^assign -cons.$0.$ii
		^rem_member $0 $ii
	}
	# remove connection info
	^assign -co.$0
}


# alias toallbutone  - send message to all but one direction
# $0 omit
# $1 COMMAND
# $2-  args
alias toallbutone {
	foreach co ii {
		if (ii != [$0]) {smsg $ii $1 $2-}
	}
}

# alias toall  - send message to all connections
# $0 COMMAND
# $1-  args
alias toall {
	foreach co ii {
		smsg $ii $0-
	}
}

# alias smsg   Send a line through a given link
# smsg <id> <COMMAND> <args>
# send a message to a specific connection.
# $0 == id
# $1 == COMMAND
# $2- == args to command or text
alias smsg {
	dcc raw $co[$0] $1-
}


# output debugging information to window 1
# $* == line with any text
alias debug {
	if (ddebug) { xecho -window 1 $* }
}

# whoon  show who is on channel
# no args.
alias whoon {
	echo *** Current channel members online
	echo *** Nick                           Unique ID
	echo *** $[30]mynick $decode($myuniquid)
	foreach nicks ii {
		echo *** $[30]nicks[$ii] $decode($ii)
	}
}


# d_nick   Send a nick change request to update nickname.
# $0 == new nickname
alias d_nick {
	if ([$0])
	{
		toall NICK $myuniquid $0
		echo *** DCC Nickname changed from $mynick to $0
		@ mynick = [$0]
	}
	{ echo *** please specify a nickname.  /d_nick nickname }
}

# do_nick   Change the nickname information and send a notice to 
# all other channel members
# $0 == id
# $1 == uniquid
# $2 == New nickname
alias do_nick {
	if (rstat[$0] > 0)
	{
		xecho -level DCC *** Info: $nicks[$1] has changed their nick to $2
		if (nicks[$1]) {
			@ nicks[$1] = [$2]
			toallbutone $0 NICK $1 $2
		}
	}
}


# d_part  part the dcc channel.. close the connection
# No args..
alias d_part {
	xecho -level DCC *** Leaving channel.
	foreach co ii {
		debug D_PART: remove connection $ii
		remove_connection $ii
	}
}

# d_help
# provide help

if (RCS.ircIId != [])
{
	echo *** You cannote currently load both dccchan and ircIId
	echo *** certain functions are now corrupt
}
