I don't use twitch, but nothing here seems specific only to twitch, as long as I'm correct with my guess that "mods" means the same thing as when the script has "if ($nick isop #) {".

My priorities in writing this code is not to make it efficient, but to keep it easily read and to keep it similar to the existing code.

1. I assume 'open' and 'close' a list means disabling the ability for anyone to type !join or other !commands to change the lists. You can easily do this by setting a variable to close the list, or unsetting the variable to open again. You would choose a variable name which is not likely used by any other script. You would insert as the first command of every event (except the event which turns the list on/off), a line which checks whether the list is open:

Code:
if (%list.status == closed) { Msg $chan Sorry $nick the list is closed | return }


This means your !join event now looks like:

Code:
on *:text:!join:#: { 
  if (%list.status == closed) { msg $chan Sorry $nick the list is closed | return }
  if ($read(list.txt,nw,$nick)) { msg $chan $nick is already on the list. | return }
  else write list.txt $nick 
  msg $chan Added $nick to the list
}


You can then open and close the list like:

Code:
on @*:text:!open *:#: {
if (%list.status != closed) { msg $chan The list is already open | return }
unset %list.status
msg $chan OK $chan the list is now open!
}


Code:
on @*:text:!close *:#: {
if (%list.status == closed) { msg $chan The list is already closed! | return }
set %list.status closed
msg $chan Sorry $chan the list is now closed!
}


The @ prefix means the above event does not trigger if not typed by an OP/Mod, so there is no need to check if $nick is an Op.

Since you already are using the code you pasted, you already know that the TEXT event cannot see any !commands typed into channel by the nick running the script. They can open and close and clear the list typing in the editbox of that channel /listopen or /listclose or /listclear after the script contains these lines:

Code:
alias listopen  { unset %list.status        | msg $chan List is now open! }
alias listclose { set   %list.status closed | msg $chan List is now closed! }
alias listclear { write -c list.txt | msg $chan list reset. }


2. Someone finding their own position will be similar to the !join event except telling them where they are on the list instead of deleting them. You can change the !word and messages in my examples to something you prefer:

Code:
on *:text:!findme:#: { 
  if (%list.status == closed) { Msg $chan Sorry $nick the list is closed | return }
  if ($read(list.txt,nw,$nick)) { msg $chan $nick you are on the list in position $readn $+ . | return }
  else msg $chan Sorry $nick you're not on the list. You can add yourself by typing: !join $nick
}


3. If I understand you, !next7 would be the same as !list7, except it also deletes the first 7 nicks from the list after showing the list of 7 nicks to the channel. I will make the event to allow 1 event to perform for both 3 and 7, or any other number from 1-10. For example, if you used "!next 7" to display and delete 7 names, but 1 of the 7 was in the channel but not responding, if the mod wants to grab 1 more name from the list, they can use "!next 1". Also, if one of the nicks on the first 3 lines have left the channel, you would want to skip them and grab the 4th person instead without listing the missing nick. The trigger will be "!next 3" or !next 7" or any number from 1-10. And again, the @ prefix avoids the need for coding to check if someone is an OP:

Code:
on @*:text:!next *:#: {
  if (%list.status == closed) { msg $chan Sorry $nick the list is closed | return }
  var %namecount = 0 , %line 1 , %max $int($2) , %names
  if (%max !isnum 1-10) { msg $chan must give number 1-10, like !next 7 | return }
  while (%namecount < %max) {
    var %t $read(list.txt,ntw,%line) 
    if ((%t != $null) && (%t ison $chan)) { var %names %names %t | inc %namecount }
    if (%t == $null) { break }
    else write -dl $+ %line list.txt
    ;else inc %line
  }
  msg $chan $calc($line(list.txt,0)) still on the list. Next $numtok(%names,32) names: %names
}


The above code can list+remove the next 7 names with: !next 7
or list+remove the next 3 names with: !next 3 (There must be a space between '!next' and the following number.) The only reason I used $calc() in this script is to force a blank value to become 0.

The above code can also be used to replace your !list7 and !list3 keywords. You would copy the entire event so you have 2 duplicate events in your script, and you only need to make 2 changes to make the 2nd duplicate become your !list event: You must alter the first line changing !next into !list. You must also delete the line beginning with "else write" and remove the semi-colon from the following line beginning with ";else". (Semi-colon at the beginning of an entire script line changes the entire line into a comment which does not execute.) The first change makes this event to respond to !list instead of !next. The second change makes it skip to the next line of list.txt instead of deleting the first line. Your syntax for list names at the top of the queue would change from "!list7" to "!list 7", and you would not need your old 2 events for the large and small groups. (A space must be between '!list' and the number.)

4. To remove yourself from the list will be similar to the way someone uses !join to add themselves:

Code:
on *:text:!listdel *:#: {
  if (%list.status == closed) { msg $chan Sorry $nick the list is closed | return }
  var %name $nick
  if (($nick isop $chan) && ($2)) { if ($2 ison $chan) { var %name $2 } | else { msg $chan $2 is not on channel | return } }
  elseif (($2) && ($2 != $nick)) msg chan sorry $nick you may not remove anyone else
  if ($read(list.txt,nw,%name)) { write -dl $+ $readn list.txt | msg $chan $nick has removed $iif($nick == %name,themself,%name) from the %list.status list now containing $calc($line(list.txt,0)) lines. | return }
  else msg $chan Sorry $nick you were not on the %list.status list
}



The above code has a section that lets an OP remove anyone by putting the nick after !listdel, duplicating the function of !del. They can remove the nick Fred with: !listdel Fred

If you remove the line beginning with "elseif", a non-OP who tries to remove someone else will find the nick is ignored, and they will be deleting themselves. smile

Note that if an OP types !listdel without a nick following it, they will delete themselves from the list.