Hello - I apologize in advance for the rather lengthy post, but before anything, there are three things I want to address. You can skip to the bottom if you just want an updated script, but I really hope you can take the time to read through this as I believe it will be quite informative and helpful. I've underlined key points to try to make them stand out:
First, I'm going to make a quick assumption:
I take it that the
FLoODPro. $+ %netsplitchan $+ .address
item being referenced within the
/hadd
command of the first
if statement of the
on QUIT event is a leftover "working draft" name that was actually meant to be the same item as the one being created/overwritten by the
/hadd
in the first place - (i.e.,
NetsplitStored. $+ %netsplitchan $+ .host
), and is never created anywhere via external means. This assumption, whether true or not, won't really matter for the rest of my post, but for educational purposes, I think it's worth pointing out that if it
is true,
$hget(eXp,FLoODPro. $+ %netsplitchan $+ .address)
will return
$null
every time, and as a consequence, the
NetsplitStored. $+ %netsplitchan $+ .host
item will only ever hold one address, rather than a space-separated list of addresses as you probably intended.
Second, I feel it's important to note that the parentheses around both of the
if statements' condition groups in the
on QUIT event are mismatched - you've closed them after the
*.* *.* iswm $1-2
sub-condition in both cases, and then attempted to again at the end of the group without ever having reopened them.
This will be practically unnoticeable at the first
if statement: mIRC's lax requirements regarding parentheses around conditions mean that
no syntax error will be raised to complain about the lack of an opening "(" parenthesis to match the closing ")" parenthesis, and the fact that
most text can be appended directly to the end of the $N
identifiers without the use of the $+
concatenator means that
mIRC will interpret the $3)
either as:
- whatever the value of
$3
is with a ")" character tacked on the end, or $null
if it has no value,
and then determine whether or not the end result of that is
$null
,
$false
, or
0
via the
!
operator.
The same cannot be said of the second
if statement, however, and the unmatched/unopened ")" parenthesis can and
should cause the script to fail because mIRC will attempt to evaluate
$null)
as an identifier, which is (hopefully) nonexistent. If the
Identifier Warning option is disabled in the script editor's
Options menu,
it, and any other non-existent identifiers, will be interpreted as $null
and the script will appear to work. However, if that option is instead enabled (which I strongly suggest it be in order to promote more carefully written code and highlight and prevent potential hard-to-detect bugs),
mIRC will instead raise an error (specifically, "No such identifier: $null)" in this case) after either:
- jumping to the first available
:error
label in the call stack if one were present, (which of course there isn't, but that's beside the point), then executing any error handling code there, or - halting the script outright.
Again, I would strongly urge you, for the reasons stated above, to enable the
Identifier Warning option in your scripts editor if you haven't already. (Unfortunately, it is disabled by default.)
One last thing to keep in mind in regards to that second
if statement is that its usage and placement are unideal. The first two sub-conditions, i.e.,
*.* *.* iswm $1-2
and
!$3
are obviously redundant given how those same conditions are already checked in the first
if statement, so you could at the very least achieve the same results by simply performing the variable existence check within that
if statement's block:
if (*.* *.* iswm $1-2) && (!$3) {
; add item to hash table
if ($eval($+(%,Netsplit-Detected.,$network),2) == $null) {
set -z $+(%,Netsplit-Detected.,$network) 20
}
}
But better yet, the
/set
and
/var
commands both contain an
i
switch that
will ensure that a variable only gets created and initialized if it doesn't already exist, so that additional
if statement could be omitted entirely:
(On a side note, mIRC will not attempt to evaluate a variable while it's being created via the /set
and /var
commands, and giving one a dynamic name during that time is straightforward and doesn't require the kinds of workarounds needed when referencing them later on.)if (*.* *.* iswm $1-2) && (!$3) {
; add item to hash table
set -iz $+( %Netsplit-Detected. , $network ) 20
}
Note that this is
neither a shorthand for, nor exact replacement of, the previous method. The
i
switch works by checking for the
existence of a variable and preventing mIRC from assigning a new value to one that already does exist,
even if its value is $null
. For your particular use case here, this should be perfectly suitable since the variable will get unset/deleted once it reaches
0
, but there might be other cases where you may need or prefer to use the other method; it depends.
I also am a bit curious what the purpose of this variable is in the first place; it seems like it's meant to serve as a timer of sorts, but it's not used anywhere in your script currently. Are you using it elsewhere already or have plans for it in this script later on?
Anyway, third and finally, your current approach would store lists of addresses within hash table items named after the channels you and the users with those addresses occupy in common, and this in all likelihood would probably be fine most of the time, especially if you only ever find yourself in fairly small channels. However, if you do happen to be in a larger channel, say, with a few hundred members inside, then this approach could prove to be problematic because
the length of the address list could exceed mIRC's large line length limit (as given by
$maxlenl
plus a little more), causing the script to fail when adding/updating a hash table item. For this reason almost entirely, I would suggest doing the reverse and store lists of channels within hash table items whose names are based on users' addresses instead. That way, it's
very unlikely (maybe even impossible) that you would ever come anywhere near that limit. You may also want to consider naming and dedicating the table itself to netsplit-affected user storage for a given network, rather than using an all-purpose table name and encoding that information in the
So now, with all that said, let's get back to the original question.
The easiest way to determine whether or not a person is rejoining a channel after being part of a netsplit using your script would be to use
$istok()
in conjunction with the relevant hash table item's value; exactly
what you would look for, of course, depends on whether or not you decide to take my suggestion to store lists of channels in hash tables named after users' addresses rather than the reverse.
If you don't implement my suggestion and keep your hash table structured the way you have it, then, as long as you modify the
/hadd
in your
on QUIT event to reference the same item in the
$hget()
as the one being created or updated (i.e.,
NetsplitStored. $+ %netsplitchan $+ .host
), and fix the parentheses for your
if statements' condition groups, you should just have to check, in your
on JOIN event:
if ($istok( $hget( eXp , $+( NetsplitStored. , # , .host ) ) , $wildsite , 32 )) {
(Note that $wildsite
is equivalent to $address( $nick , 2 )
.)If, however, you do take my suggestion to store lists of channels in items named after users' addresses instead, the idea would essentially be the same, except that you would check if the
channel is a token in the item rather than the
$wildsite
.
Here's how I would write the script, including the recommendations I've provided above:
alias -l comchanlist {
!var %placeholder = $str( - $+ $chr(32) , $comchan( $1 , 0 ) )
; Note: []s (evaluation-prioritizing brackets) are needed around
; the $1 below because the meaning and values of most of the $N
; identifiers is overridden in $regsubex's subsitition parameter.
;
!return $regsubex( %placeholder , /-/g , $comchan( [ $1 ] , \n ) )
}
alias -l netsplit_users {
!return $+( eXp_ , $network , _Netsplit_Users )
}
; -----------------------------------------------------------------------------
on ^!*:JOIN:#: {
; Note: $wildsite is equivalent to $address( $nick , 2 )
;
!if ($istok( $hget( $netsplit_users , $wildsite ) , # , 32 )) {
!halt
}
}
on ^!*:QUIT: {
; Note: this wildcard matching technique is not exactly robust,
; but it should work well enough for this particular situation.
;
!if ($0 == 2) && (*.& *.& iswm $1-) {
!hadd -mu1800 $netsplit_users $wildsite $comchanlist( $nick )
; Note: I don't know what the purpose of this variable is,
; but I've included it, regardless, in case you need it for something.
;
!set -iz $+( %Netsplit-Detected. , $network ) 20
}
; Do you really intend to halt ALL pre-processed QUIT events here,
; or just the ones that are triggered by netsplit-affected users?
; (In other words, should this actually be scoped to the if statement above?)
;
!halt
}
The
!
prefixes in front of the (built-in) commands help to preserve the integrity of the script by
ensuring that mIRC's versions of those commands get called in the event that you, for some reason, ever decide to override them with an alias or happen to load a script that does so. This prefix is not actually necessary before certain commands or keywords like
if
and
/var
, as these cannot be overridden, but I like to include it in such cases, anyway, for visual consistency.
This script also avoids an unnecessary loop by taking advantage of a combination of
$regsubex()
and
$str()
in the
comchanlist
alias. Essentially, the way this alias works is it first creates a series of space-separated
-
characters repeated "
$comchan( $1 , 0 )
" times, (where
$1
is the nickname you want to check) using the
$str()
identifier, uses
$regsubex()
to substitute the
Nth instance of those dashes with the
Nth
$comchan()
value, and then returns the final result.
I hope this helps. Let me know if you have any other questions.