Hello, using on text is correct to access the user reply, the problem is that if you listen only for one specific random 4 letters (a single %variable), it only works for one user at a time.
To access the last line of a query window outside on text, you would use $line() but i don't think it's relevant here.

In any case it would probably be better to make the length of the password longer to avoid people getting lucky, or worse, brute forcing you (see %length in code).

To allow it to work for multiple users at the same time with different passwords, you'll need to store data per nickname

Code
on *:TEXT:voiceme:?: {
  var %i = 0,%length 3,%mytext 
  while (%i <= %length) {
    %mytext = %mytext $+ $rand(a,z)
    inc %i
  }
  .msg $nick Please reply with this text and I will give you voice: %mytext
  set %botvoiceme $+ $nick %mytext
}

on *:TEXT:*:?: {
  if ($nick ison #mychan) {
    if ($eval($+(%,botvoiceme,$nick),2) == $1-) {
       mode #mychan +v $nick 
       unset %botvoiceme $+ $nick
       .msg $nick Congrats! You have voice (+v) and can chat in channel. 
    }
  }
  else {
    //echo -a $nick not in channel
    .ignore -pu300 $nick
  }
}
Something like that, it uses dynamic variables: https://en.wikichip.org/wiki/mirc/variables#Dynamic_Variable_Names

Atm the variables to store the data are global and only destroyed when the user complete the action, if he doesn't or if the bot disconnect in the middle, the variable will be still there and it would be possible to complete the action at any time in the future, you would want to maybe make the variable destroy themselves after a few seconds with set -u60 %botvoicele $+ $nick %mytext for 60 seconds, for example.


#mircscripting @ irc.swiftirc.net == the best mIRC help channel