Skip to content

Commit

Permalink
Version 2.0
Browse files Browse the repository at this point in the history
Upgrade by @Talon-1
  • Loading branch information
ValwareIRC authored Jan 4, 2025
1 parent 797aa10 commit 6b38fda
Showing 1 changed file with 174 additions and 85 deletions.
259 changes: 174 additions & 85 deletions Better Typing Notifications/better_typing_notifs.mrc
Original file line number Diff line number Diff line change
@@ -1,107 +1,196 @@
;; Valware © 2024
;; https://github.com/ValwareIRC
;; Talon © 2025
;;
;; Better Typing Notifications
;; v1.2
;; Please allow this script to run on load,
;; this is so that it can create its own
;; directory to manage typing notifications
;; using files to remember what's going on

on *:LOAD:{
ensureDir
}
on *:START:{
ensureDir
}
;; Better Channel Typing Notifications
;; v2.0
;; Screenshot: https://i.ibb.co/9q05t9w/Screenshot-from-2024-08-17-04-42-21.png

alias -l ensureDir {
set %unableToCreateDir $false
if ($isdir($mircdirTypingNotifs)) return $true
echo -at ~~ ^__^ Thank you so much for checking out the Typing Notifications script.
echo -at ~~ Just gotta make a directory! La la la...
.mkdir " $+ $mircdirTypingNotifs $+ "
if (!$isdir($mircdirTypingNotifs)) {
set %unableToCreateDir $true
echo -at ~~ Oh no! It seems that I,the Typing Notifications script, cannot create the directory.
echo -at ~~ I only need it for tidiness. Please could you create it? It needs to be called:
echo -at ~~  $+ $mircdirTypingNotifs
echo -at ~~ ~~**~~
return $false
}
else {
set %unableToCreateDir $false
echo -at ~~ Created! Yay, can't wait for you to see how it works! =]
return $true
}
}
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; Changes:
; - Uses a temporary hash table now instead of individual ini files. This does
; NOT require any cleanup as it's just a temp table in memory.
; - Logs typers by connection id instead of by server name
; - Removed echo-message CAP necessity, now just spoofs TAGMSG's for yourself if
; sending typing notifications is checked in: alt+o->IRC->Options
;
; Fixes:
; - Ensures TAGMSG belongs to a channel and not a query
; - Did not clear typer instantly on an action message (missing event for it)
; - No longer expunges typers info on nickchange. (Like force-nickchange for not
; identifying to services for example) IRCv3 vaguely specifies do this
; on a recieved msg/part/quit, got a done TAGMSG, +30s from paused TAGMSG, or
; +6s from the last active TAGMSG.
; - Runaway global variable "%i" since it was never declared in the NICK event.
;
; New:
; - Made identifier $GetTypers(#,N).<active|paused> to support the ability to
; return various info: full lists of active/paused typers, counts of
; active/paused typers, and the ability to grab individual typers from the
; active/paused list by index. See Documentation comments below.
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

;; Make sure the second editbox is open
on *:ACTIVE:#:{
if ($len($editbox($active,1)) == 0) {
editbox -ovq1 $active
;################################################################################
; Aliases
;################################################################################

;== Identifier to return typers of a given channel (left as global-alias just incase you may want to use it elsewhere)
; $GetTypers(#,N)
;
; Properties: active, paused
;
; The N parameter is optional, if $null returns tokenized list of nicknames.
; Properties are also optional, if none specified, defaults to active.
;
; Examples:
; $GetTypers(#) Returns tokenized list of nicknames of active typers by a comma (IE: foo, bar, baz)
; $GetTypers(#).paused Returns tokenized list of nicknames of paused typers by a comma (IE: foo, bar, baz)
;
; $GetTypers(#,0) Returns total number of active typers
; $GetTypers(#,1) Returns the first nickname that is actively typing.
;
; $GetTypers(#,0).paused Returns total number of paused typers
; $GetTypers(#,1).paused Returns the first nickname that is paused.
;
alias GetTypers {
;== Find total entries and iterate over them
var %x = $hfind(IRCv3Typers,$+($cid,.,$$1,.*),0,w) , %count = 0 , %query = $iif(!$prop,active,$prop) , %ret
while (%x) {
var %item = $hfind(IRCv3Typers,$+($cid,.,$1,.*),%x,w) , %nick = $gettok(%item,-1,46) , %value = $hget(IRCv3Typers,%item)

;== Test if the value is what we're looking for (active/paused)
if (%value == %query) {
;== If we're only passed one parameter, we must want a tokenized list. Append to it.
if ($0 == 1) { var %ret = $addtok(%ret,$chr(32) $+ %nick,44) }

;== Else increase our count variable. If we passed a 2nd argument > 0, return the nick in this spot if current count matches.
else {
inc %count
if (%count == $2) { return %nick }
}
}
dec %x
}
}

alias AddTyping {
if ($readini($server $+ -typing.ini,$2,$3) != $null) return
writeini TypingNotifs/ $+ $1 $+ -typing.ini $2 $3 active
}
;== If we passed a 2nd argument == 0, return the total count of nicks.
if ($2 == 0) { return %count }

alias RemoveTyping {
remini TypingNotifs/ $+ $1 $+ -typing.ini $2 $3
;== Lastly if all other returns don't trigger, we must want the tokenized list or we exceeded the total count of nicks in the 2nd parameter, in which case %ret will also be $null so returning this is fine
return %ret
}

alias GetTyping {
set %string [none]
var %i 1
while (%i <= $ini(TypingNotifs/ $+ $server $+ -typing.ini, $1, 0)) {
set %string %string $+ , $ini(TypingNotifs/ $+ $server $+ -typing.ini, $1, %i)
inc %i
}
set %string $replace(%string,$me,(You))
editbox -o $1 Typing: $iif($len($right(%string,-8)) <= 0,(none),$right(%string,-8))
;== Local helper-alias to update the 2nd editbox...
alias -l ShowTypers {
var %typers = $GetTypers($1), %paused = $GetTypers($1).paused

;=-=-=-= Uncomment line below to retain replacing $me with (You) =-=-=-=
;var %typers = $replace(%typers,$me,(You)) , %paused = $replace(%paused,$me,(You))
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

;== Modify the contents of the 2nd Editbox (set blank if no typers)
editbox -o $$1 $iif(%typers,Typing:) %typers

;== Comment above one and uncomment this one AND the if below to show both active and paused!
;editbox -o $$1 $iif(%typers,Typing:) %typers $+ $iif(%typers && %paused,$chr(44)) $iif(%paused,Paused:) %paused

;== Set a timer to update typers after 6 seconds IF we have paused typers (since it takes 5x as long to remove... 6 * 5 = 30s)
; Note: We can't just set it to 30, it might get reset to 6 from another typer, etc... we just have to keep re-starting it if we have typers..
;if (%paused) { $+(.timer,typers,.,$cid,.,$1) 1 6 ShowTypers $1 }
}

alias RemoveAndClear {
RemoveTyping $1-
GetTyping $2
;################################################################################
; Remotes
;################################################################################

;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;== Make sure the second editbox is open (Uncomment to re-enable auto 2nd editbox activation)
;on *:ACTIVE:#:{ if ($len($editbox($active,1)) == 0) { editbox -ovq1 $active } }
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

;== Spoof our own TAGMSG lines back to ourselves (queue a new parseline in)
;- NOTE: Must have alt+o->IRC->Options Send typing notifications checked to see ourself...
on *:PARSELINE:out:*: {
var %pl = $parseline
if ($parseutf) { %pl = $utfdecode(%pl) }

;== If any number of characters not a space, then " TAGMSG " and the next character IS of a chantype from $chantypes
; spoof our own inbound TAGMSG to mIRC by replacing the 1st "space" with " :<fulladdress> " (@+typing=... :Me!user@host TAGMSG <target>)
; also remove $cr and/or $lf from end of parsed line since this is off of an outbound (mirc would treat it as <chan>$chr(10) otherwise...)
if ($regex(%pl,/^[^ ]+ TAGMSG $+([,$chantypes,]/))) { .parseline -qtiu0 $remove($regsubex(%pl,/( )/,$+(\1,:,$address($me,5),\1)),$cr,$lf) | return }
}

;== Process +typing TAGMSGs
RAW TAGMSG:*:{
; User is typing. Show us and set a 6 second timer to remove it. If they typed between now and then, the timer restarts.
if ($msgtags(+typing).key == active) AddTyping $server $target $nick | .timer $+ $+($server,$target,$nick) 1 6 RemoveAndClear $server $target $nick
else if ($msgtags(+typing).key == paused) || ($msgtags(+typing).key == done) RemoveTyping $server $target $nick
GetTyping $target
}
;== Determine if the target is a channel
if ($target ischan) {

;== Determine timeout based on active/paused/done
var %key = $msgtags(+typing).key

if (%key == active) { var %timeout = 6 }
elseif (%key == paused) { var %timeout = 30 }
elseif (%key == done) { var %timeout = 0 }

on *:QUIT:{
var %i 0
while (%i <= $comchan($nick,0)) {
inc %i
if ($nick == $me) continue
RemoveTyping $server $comchan($nick,%i) $nick
;== If %timeout is != 0, Update the nickname that is typing's key and timeout (recieved active/paused)
if (%timeout) {
;==Add new entry by dynamic item name: ConnectionID.Target.Nick
hadd $+(-mu,%timeout) IRCv3Typers $+($cid,.,$target,.,$nick) %key

;== Set a timer to update typers after 6 seconds
$+(.timer,typers,.,$cid,.,$target) 1 6 ShowTypers $target
}

;== Else remove nickname that was typing (recieved a done) (If the table does exist... To avoid hdel no such table)
elseif ($hget(IRCv3Typers)) { hdel -w IRCv3Typers $+($cid,.,$target,.,$nick) }

;== Immediately show the new active typers
ShowTypers $target
}
}

on *:TEXT:*:#:RemoveTyping $server $chan $nick
on *:DISCONNECT:{
;; check if there are any other connections from our client before we start deleting stuff
remove TypingNotifs/ $+ $server $+ -typing.ini
}
on *:KICK:#:RemoveTyping $server $chan $knick
on *:PART:#:RemoveTyping $server $chan $nick
on *:NICK:{
while (%i <= $comchan($nick,0)) {
RemoveTyping $server $comchan($nick,%i) $nick
inc %i
;== Expunge all entries for connection ID if we got disconnected (Extra precaution, do it as well if we connected too)
on *:DISCONNECT: { if ($hget(IRCv3Typers)) { hdel -w IRCv3Typers $+($cid,.*) } }
on *:CONNECT: { if ($hget(IRCv3Typers)) { hdel -w IRCv3Typers $+($cid,.*) } }

;== Expunge typer on input/action/text/kick/part (if the table exists yet...) and update windows typer list
on *:INPUT:#: { if ($hget(IRCv3Typers)) { hdel -w IRCv3Typers $+($cid,.,$target,.,$me) } | ShowTypers # }
on *:ACTION:*:#: { if ($hget(IRCv3Typers)) { hdel -w IRCv3Typers $+($cid,.,$target,.,$nick) } | ShowTypers # }
on *:TEXT:*:#: { if ($hget(IRCv3Typers)) { hdel -w IRCv3Typers $+($cid,.,$target,.,$nick) } | ShowTypers # }
on *:KICK:#: { if ($hget(IRCv3Typers)) { hdel -w IRCv3Typers $+($cid,.,$target,.,$knick) } | ShowTypers # }
on *:PART:#: { if ($hget(IRCv3Typers)) { hdel -w IRCv3Typers $+($cid,.,$target,.,$nick) } | ShowTypers # }

;== Expunge entries for when a user or ourself quits
on *:QUIT: {
;== If we're the one quitting, expunge all entries for the connection (if the table exists yet...)
if ($nick == $me && $hget(IRCv3Typers)) { hdel -w IRCv3Typers $+($cid,.*) }

;== Else only expunge those records for the nickname that quit
else {
;== Find total entries and iterate over them (If we didn't need to update the list we could've just used hdel -w ...)
var %x = $hfind(IRCv3Typers,$+($cid,.*.,$nick),0,w)
while (%x) {
var %item = $hfind(IRCv3Typers,$+($cid,.*.,$nick),%x,w) , %target = $gettok(%item,2,46)

;== Expunge entry and update typers (no need to check if table exists, we know it does if hfind returns > 0)
hdel -w IRCv3Typers %item
ShowTypers %target
dec %x
}
}
}
on *:CONNECT:{
.remove TypingNotifs/ $+ $server $+ -typing.ini
}

on *:PARSELINE:out:*:{
tokenize 32 $parseline
if ($1 == CAP) && ($2 == REQ) && (echo-message !isin $3-) { parseline -ton cap req :echo-message $right($3-,-1) | haltdef }
;== Update typer on nickchange
on *:NICK: {
;== Find total entries and iterate over them
var %x = $hfind(IRCv3Typers,$+($cid,.*.,$nick),0,w)
while (%x) {
var %item = $hfind(IRCv3Typers,$+($cid,.*.,$nick),%x,w) , %target = $gettok(%item,2,46) , %value = $hget(IRCv3Typers,%item) , %timeout = $hget(IRCv3Typers,%item).unset , %ret

;== Add new entry for the new nickname with the time remaining until it is to be expunged
hadd $+(-mu,%timeout) IRCv3Typers $+($cid,.,%target,.,$newnick) %value

;== Expunge entry and update typers (no need to check if table exists, we know it does if hfind returns > 0)
hdel -w IRCv3Typers %item
ShowTypers %target
dec %x
}
}

0 comments on commit 6b38fda

Please sign in to comment.