mIRC Home    About    Download    Register    News    Help

Print Thread
Joined: Mar 2021
Posts: 48
R
Robert Offline OP
Ameglian cow
OP Offline
Ameglian cow
R
Joined: Mar 2021
Posts: 48
Can someone fixed or rewrite this code for me please? It's not work

Here is my code:

Code
on *:JOIN:#:{
  if ($istok(#test1 #test2 #test3,$chan,32)) {
    if ($nick == $me) { halt }
    if ($nick isop $chan) { return }
    var %host = $ial($nick).host
    var %file = autoopip.txt
    if ($read(%file,w,$+(*,%host,*))) {
      var %str $read(%file,$readn)
      if ($+(*,%host,*) iswm $gettok(%str,1,59)) {
      var %chanop $gettok(%str,2,59)
        mode %chanop +o $nick | .notice @ $+ $chan $chan - $me ( $+ $me $+ ) opped: $nick
      }
    }
  }
}

in the file autoopip.txt there are identical IPs/hosts but different #room names as follows:
188.26.59.16;#test1
161.184.143.251;#test2
id-586239.lymington.irccloud.com;#test1
id-586239.lymington.irccloud.com;#test2
id-586239.lymington.irccloud.com;#test3
id-455146.ilkley.irccloud.com;#test3
id-455146.ilkley.irccloud.com;#test2

Joined: Jan 2004
Posts: 2,127
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
You don't need to check if $nick is already an @op of $chan during ON JOIN, because that never happens.

But you do need to check if yourself has privileges to op them. If you want to trigger only if you are @op in the channel, you can replace *:JOIN: with @*:JOIN: or if you have & or ~ status without also having @ status, you can instead do:

if (!$nick($chan,$me,a,rvh)) return

For $nick == $me, you can just RETURN since a HALT might interfere with other scripts which intercept the JOIN event. However, in this case you can skip checking if the $nick == $me because the @*:JOIN: prevents this from triggering when you join, because you can't be already-op when you join, the same way they can't be already-op when they join.

It's best practice to be in the habit of using the 'nt' switches with $read except when you specifically want to evaluate %word and $word found in the match text, or when you specifically want to treat a numeric line#1 as if it's the number of lines in the text file.

Using $read with the 'w' switch returns the matchtext, which the if() statement puts into $v1, so you can save doing a 2nd disk read by instead creating %str like: var %str $v1

When you are reading the file, it returns the first match, so this always returns the #test1 line for the 1st host, and the #test3 line for the 2nd host. You can change the script to keep reading multiple times to find more than 1 line having their address, by starting the search at different lines in the file, but it would be simpler for you to have each address appear 1 time like hostname.irccloud;#test3 #test2

This code is triggered with someone joining all channels, but then it checks if it's in a list of channels once it's triggered. It's faster to instead limit the triggering to just the list of channels, by changing :#: to :#test1,#test2,#test3: without any spaces.

Your code makes it possible for false matches. If I own website irccloud.co then I can create address id-586239.lymington.irccloud.co and this will match $read(%file,w,$+(*,%host,*)) and $+(*,%host,*) will be a wildcard match for $gettok(%str,1,59). If the purpose of your wildcard is to match the line where the host is immediately followed by the semicolon then $read(%file,ntw,$+(%host,;?*)) Notice how this does not match a line with nothing after the semi-colon

It's wasted effor to test for whether $+(*,%host,*) matches the string which matched the same wildcard scan of the disk file, because this would always match except if %host contains the illegal semicolon

Your code also blindly attempts to +o someone in multiple channels without checking to see if they're actually in all of them, which is guaranteed to send an erroneous +o command to the first of the channels they join. One you modify the disk file to have all the channels on the same line, you would then parse it to op them just in the channel that $nick is currently joining. The line beginning with 'mode' would instead be replaced by:

if ($istok(%chanop,$chan,32)) mode $chan +o $nick | .notice @ $+ $chan $chan - $me ( $+ $me $+ ) opped: $nick

If you want to have it attempt to op them in all listed channels to cover the situation where they joined #test3 before you joined it, but are joining #test2 after you joined the channel, you can have it loop through the channel list just in case:

var %i 1 | while ($gettok(%chanop,%i,32)) {
var %chan $v1
if ( ($nick(%chan,$nick,r) && ($me isop %chan)) {
mode %chan +o $nick | .notice @ $+ %chan %chan - $me ( $+ $me $+ ) opped: $nick
}
inc %i
}

If you wanted the channels to be listed on multiple rows so that sometimes people could be voiced instead of op'ed, you can have the lines be hostname;#test1 o #test2 v
and then the code will need to change to handle the different modes, which I won't take the trouble to change unless that's what you're needing, since it would be simpler to have a different %file for each purpose.

Below is sanitized code. I could have made it be shorter since %file and %host and %str are used 1 time, but I left them that way to be more readible
Code
on @*:JOIN:#test1,#test2,#test3:{
  var %host = $ial($nick).host , %file = autoopip.txt
  if ($read(%file,ntw,$+(%host,;?*))) {
    var %str $v1 , %chanop $gettok(%str,2,59)
    if ($istok(%chanop,$chan,32)) mode $chan +o $nick | .notice @ $+ $chan $chan - $me ( $+ $me $+ ) opped: $nick
  }
}

Joined: Mar 2021
Posts: 48
R
Robert Offline OP
Ameglian cow
OP Offline
Ameglian cow
R
Joined: Mar 2021
Posts: 48
Thank you for your early reply and help. However it still doesn't work. Can you make it work?

Note:
In autoopip.txt have 3 ip/host same address:

188.26.59.16;#freeirc
id-586239.lymington.irccloud.com;#test1 <----- same address
id-586239.lymington.irccloud.com;#test2 <----- same address
161.184.143.251;#freeirc
id-455146.ilkley.irccloud.com;#test1 <----- same address
id-455146.ilkley.irccloud.com;#test2 <----- same address
id-455146.ilkley.irccloud.com;#test3 <----- same address

Joined: Jan 2004
Posts: 2,127
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
Yes it does work, but I'm guessing you tried to go directly to using the new code without reading my post, such as where I said...

Originally Posted by maroon
When you are reading the file, it returns the first match, so this always returns the #test1 line for the 1st host, and the #test3 line for the 2nd host. You can change the script to keep reading multiple times to find more than 1 line having their address, by starting the search at different lines in the file, but it would be simpler for you to have each address appear 1 time like hostname.irccloud;#test3 #test2

So that means you need a different format for your text file. For your last example, it should instead have each hostname on ONE line, like:

188.26.59.16;#freeirc
id-586239.lymington.irccloud.com;#test1 #test2 <----- same address
161.184.143.251;#freeirc
id-455146.ilkley.irccloud.com;#test1 #test2 #test3 <----- same address

Joined: Mar 2021
Posts: 48
R
Robert Offline OP
Ameglian cow
OP Offline
Ameglian cow
R
Joined: Mar 2021
Posts: 48
Here is my Final Code and it's work perfectly: Two lines only
Code
ON !*:JOIN:#freeirc,#Official: {
  var %read = $read(autoopip.txt,nw,* $+ $ial($nick).host $+ $chr(59) $+ $chan)
 
  if (%read) { mode $chan +o $nick | .notice @ $+ $chan $chan - $me ( $+ $me $+ ) opped: $nick }
}

Joined: Dec 2008
Posts: 1,515
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2008
Posts: 1,515
Originally Posted by Robert
Here is my Final Code and it's work perfectly: Two lines only
Code
ON !*:JOIN:#freeirc,#Official: {
  var %read = $read(autoopip.txt,nw,* $+ $ial($nick).host $+ $chr(59) $+ $chan)
 
  if (%read) { mode $chan +o $nick | .notice @ $+ $chan $chan - $me ( $+ $me $+ ) opped: $nick }
}

This is the code i gave you, thanks for the credits tired


Need Online mIRC help or an mIRC Scripting Freelancer? -> https://irc.chathub.org <-
Joined: Jan 2012
Posts: 299
Fjord artisan
Offline
Fjord artisan
Joined: Jan 2012
Posts: 299
It seems that this question about help with the script was sent to all the famous mIRC forums on the Internet in the hope of getting some solution from 3-5 scripts from different scripters masters, and then the best variant is selected and begins to be assembled from separate pieces one most working script )))


🌐 http://forum.epicnet.ru 📜 irc.epicnet.ru 6667 #Code | mIRC scripts, help, discuss, examples
Joined: Jan 2004
Posts: 2,127
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
Well, your code is not quite 'perfect', though the imperfections will likely not be noticed except in rare cases. You dropped the 't' switch from my code, which means the code now does extra checking to see if line#1 is numeric before continuing to the normal task. Shorter code is not always the best and the fastest.

Your code took away the @ prefix I used and replaced it with the ! prefix. My original post said that since neither you nor anyone else can be @op during the event where they are joining the channel, the @ prefix I used has the effect of also including the ! prefix since the @ prefix prevents the event from ever triggering whenever yourself is joining any channel.

But now your code has the behavior where it will still trigger in those 2 channels if you are not @op at the time, which means it would be sending the +o mode command to the channel, which would fail because only someone already an @op can use that mode.

Your code also has the imperfection that it makes a slow disk read each time there is a join to the channel, in order to check for the rare case that there is a hostname match with these addresses. To be faster and eliminate all these disk reads, you can instead use a hashtable.

Depending on whether there is '=' in the match text that would prevent having your data be in .ini format (which is not the case here), you might instead need to have the hashtable saved to disk in a different format. If in .ini format your disk file would be lines like:

[hashtable]
188.26.59.16;#freeirc=1
id-586239.lymington.irccloud.com;#test1=1
id-586239.lymington.irccloud.com;#test2=1
161.184.143.251;#freeirc=1
id-455146.ilkley.irccloud.com;#test1=1
id-455146.ilkley.irccloud.com;#test2=1
id-455146.ilkley.irccloud.com;#test3=1

You would then read the hashtable into memory 1 time, and it would check the hashtable in memory during each JOIN instead of reading the disk file repeatedly. The more perfect code would be...

Code
ON @*:JOIN:#freeirc,#Official: {
if (!$hget(autoopip)) hload -mi autoopip autoopip.txt
if ($hget(autoopip,$ial($nick).host $+ $chr(59) $+ $chan)) { mode $chan +o $nick | .notice @ $+ $chan $chan - $me ( $+ $me $+ ) opped: $nick }
}

Your new perfect code is using 'w' for a wildcard search even though you are doing an exact match between the nick's host and the host stored in disk. If for some reason you do need to do a wildcard match where your search text continues to be literal text but the wildcards are instead the items in the list, that is something a hashtable can do which $read cannot do. In that scenario, you would do something like editing one of the lines of the text file to be like:

188.26.59.*;#freeirc=1

Then you would scan the hashtable like:

if ($hfind(autoopip,$ial($nick).host $+ $chr(59) $+ $chan,1,W)) { mode $chan +o $nick | .notice @ $+ $chan $chan - $me ( $+ $me $+ ) opped: $nick }

If you need to modify the text file, you can add/remove rows, then after saving your changes to disk, you can force the JOIN event to re-load the hashtable from disk by removing the hashtable from memory:

/hfree autoopip

You can also add new addresses to a hashtable that's already in memory then save those to disk:

/hadd autoopip 12.23.34.45;#freeirc
/hsave -i autoopip autoopip.txt

If the /hadd command fails, that's because the table didn't exist, which is a good safeguard when not using the /hadd -m switch

Joined: Mar 2021
Posts: 48
R
Robert Offline OP
Ameglian cow
OP Offline
Ameglian cow
R
Joined: Mar 2021
Posts: 48
Thanks westor for help. Epic say right :P

Here is the final Code:

Code
ON !@*:JOIN:#Test1,#Test2,#Test3: {
  var %hostop = $read(autoopip.txt,nw,* $+ $ial($nick).host $+ $chr(59) $+ $chan)
  var %identop = $read(autoopip.txt,nw,* $+ $ial($nick).user $+ $chr(59) $+ $chan)
 
  if (%hostop) || (%identop) { mode $chan +o $nick | .notice @ $+ $chan @ $+ $chan - $me ( $+ $me $+ ) opped: $nick }
}

Joined: Jan 2012
Posts: 299
Fjord artisan
Offline
Fjord artisan
Joined: Jan 2012
Posts: 299
This is not the final version yet! [Linked Image from i.ibb.co]

Now you must learn how to use the table hash in this script as uncle "maroon" recommends )))


🌐 http://forum.epicnet.ru 📜 irc.epicnet.ru 6667 #Code | mIRC scripts, help, discuss, examples
Joined: Jan 2004
Posts: 2,127
Hoopy frood
Offline
Hoopy frood
Joined: Jan 2004
Posts: 2,127
Yes grasshopper, hashtables are great. You can control when/if they're written to disk, so can avoid the need to clear the /set -e %variable from vars.ini should windows crash without getting a chance for ON EXIT to sanitize it. Plus the the /hadd -u999999999 item equivalent to /set -e %variable won't be written to disk unless you specifically use /hsave -u
I've seen cases where it can benchmark faster to use a hashtable instead of a local /var because you don't need to use the [ square braces ] to create compound itemnames in a hashtable that are built from combining $network,$chan,$nick etc

You can't quickly hunt down global variables based on their contents, but is easy to do with hashtables.

The big case where you can't use hashtables is when there is so much data that it can't fit in memory, such as in a !seen database that's been built up over years or is in busy channels


Link Copied to Clipboard