mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-27 21:19:31 +01:00
bots, opercmds: handle cases where target nick is disambiguous
This commit is contained in:
parent
242267a4a2
commit
fc4a16eda1
@ -39,13 +39,16 @@ def quit(irc, source, args):
|
|||||||
irc.error("Not enough arguments. Needs 1-2: nick, reason (optional).")
|
irc.error("Not enough arguments. Needs 1-2: nick, reason (optional).")
|
||||||
return
|
return
|
||||||
|
|
||||||
u = irc.nick_to_uid(nick)
|
u = irc.nick_to_uid(nick, filterfunc=irc.is_internal_client)
|
||||||
|
if u is None:
|
||||||
|
irc.error("Unknown user %r" % nick)
|
||||||
|
return
|
||||||
|
|
||||||
if irc.pseudoclient.uid == u:
|
if irc.pseudoclient.uid == u:
|
||||||
irc.error("Cannot quit the main PyLink client!")
|
irc.error("Cannot quit the main PyLink client!")
|
||||||
return
|
return
|
||||||
|
|
||||||
quitmsg = ' '.join(args[1:]) or 'Client Quit'
|
quitmsg = ' '.join(args[1:]) or 'Client Quit'
|
||||||
|
|
||||||
if not irc.is_manipulatable_client(u):
|
if not irc.is_manipulatable_client(u):
|
||||||
irc.error("Cannot force quit a protected PyLink services client.")
|
irc.error("Cannot force quit a protected PyLink services client.")
|
||||||
@ -69,13 +72,13 @@ def joinclient(irc, source, args):
|
|||||||
try:
|
try:
|
||||||
# Check if the first argument is an existing PyLink client. If it is not,
|
# Check if the first argument is an existing PyLink client. If it is not,
|
||||||
# then assume that the first argument was actually the channels being joined.
|
# then assume that the first argument was actually the channels being joined.
|
||||||
u = irc.nick_to_uid(args[0])
|
u = irc.nick_to_uid(args[0], filterfunc=irc.is_internal_client)
|
||||||
|
|
||||||
if not irc.is_internal_client(u): # First argument isn't one of our clients
|
if u is None: # First argument isn't one of our clients
|
||||||
raise IndexError
|
raise IndexError
|
||||||
|
|
||||||
clist = args[1]
|
clist = args[1]
|
||||||
except IndexError: # No nick was given; shift arguments one to the left.
|
except IndexError: # No valid nick was given; shift arguments one to the left.
|
||||||
u = irc.pseudoclient.uid
|
u = irc.pseudoclient.uid
|
||||||
try:
|
try:
|
||||||
clist = args[0]
|
clist = args[0]
|
||||||
@ -114,7 +117,7 @@ def joinclient(irc, source, args):
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
modes = []
|
modes = []
|
||||||
|
|
||||||
# Call a join hook manually so other plugins like relay can understand it.
|
# Signal the join to other plugins
|
||||||
irc.call_hooks([u, 'PYLINK_BOTSPLUGIN_JOIN', {'channel': real_channel, 'users': [u],
|
irc.call_hooks([u, 'PYLINK_BOTSPLUGIN_JOIN', {'channel': real_channel, 'users': [u],
|
||||||
'modes': modes, 'parse_as': 'JOIN'}])
|
'modes': modes, 'parse_as': 'JOIN'}])
|
||||||
irc.reply("Done.")
|
irc.reply("Done.")
|
||||||
@ -138,7 +141,7 @@ def nick(irc, source, args):
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
irc.error("Not enough arguments. Needs 1-2: nick (optional), newnick.")
|
irc.error("Not enough arguments. Needs 1-2: nick (optional), newnick.")
|
||||||
return
|
return
|
||||||
u = irc.nick_to_uid(nick)
|
u = irc.nick_to_uid(nick, filterfunc=irc.is_internal_client)
|
||||||
|
|
||||||
if newnick in ('0', u): # Allow /nick 0 to work
|
if newnick in ('0', u): # Allow /nick 0 to work
|
||||||
newnick = u
|
newnick = u
|
||||||
@ -153,7 +156,7 @@ def nick(irc, source, args):
|
|||||||
|
|
||||||
irc.nick(u, newnick)
|
irc.nick(u, newnick)
|
||||||
irc.reply("Done.")
|
irc.reply("Done.")
|
||||||
# Ditto above: manually send a NICK change hook payload to other plugins.
|
# Signal the nick change to other plugins
|
||||||
irc.call_hooks([u, 'PYLINK_BOTSPLUGIN_NICK', {'newnick': newnick, 'oldnick': nick, 'parse_as': 'NICK'}])
|
irc.call_hooks([u, 'PYLINK_BOTSPLUGIN_NICK', {'newnick': newnick, 'oldnick': nick, 'parse_as': 'NICK'}])
|
||||||
|
|
||||||
@utils.add_cmd
|
@utils.add_cmd
|
||||||
@ -171,8 +174,8 @@ def part(irc, source, args):
|
|||||||
|
|
||||||
# First, check if the first argument is an existing PyLink client. If it is not,
|
# First, check if the first argument is an existing PyLink client. If it is not,
|
||||||
# then assume that the first argument was actually the channels being parted.
|
# then assume that the first argument was actually the channels being parted.
|
||||||
u = irc.nick_to_uid(nick)
|
u = irc.nick_to_uid(nick, filterfunc=irc.is_internal_client)
|
||||||
if not irc.is_internal_client(u): # First argument isn't one of our clients
|
if u is None: # First argument isn't one of our clients
|
||||||
raise IndexError
|
raise IndexError
|
||||||
|
|
||||||
except IndexError: # No nick was given; shift arguments one to the left.
|
except IndexError: # No nick was given; shift arguments one to the left.
|
||||||
@ -217,12 +220,11 @@ def msg(irc, source, args):
|
|||||||
|
|
||||||
# First, check if the first argument is an existing PyLink client. If it is not,
|
# First, check if the first argument is an existing PyLink client. If it is not,
|
||||||
# then assume that the first argument was actually the message TARGET.
|
# then assume that the first argument was actually the message TARGET.
|
||||||
sourceuid = irc.nick_to_uid(msgsource)
|
sourceuid = irc.nick_to_uid(msgsource, filterfunc=irc.is_internal_client)
|
||||||
if not irc.is_internal_client(sourceuid): # First argument isn't one of our clients
|
|
||||||
|
if sourceuid is None or not text: # First argument isn't one of our clients
|
||||||
raise IndexError
|
raise IndexError
|
||||||
|
|
||||||
if not text:
|
|
||||||
raise IndexError
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
try:
|
try:
|
||||||
sourceuid = irc.pseudoclient.uid
|
sourceuid = irc.pseudoclient.uid
|
||||||
@ -236,12 +238,26 @@ def msg(irc, source, args):
|
|||||||
irc.error('No text given.')
|
irc.error('No text given.')
|
||||||
return
|
return
|
||||||
|
|
||||||
if not irc.is_channel(target):
|
try:
|
||||||
# Convert nick of the message target to a UID, if the target isn't a channel
|
int_u = int(target)
|
||||||
real_target = irc.nick_to_uid(target)
|
except:
|
||||||
if real_target is None: # Unknown target user, if target isn't a valid channel name
|
int_u = None
|
||||||
|
|
||||||
|
if int_u and int_u in irc.users:
|
||||||
|
real_target = int_u # Some protocols use numeric UIDs
|
||||||
|
elif target in irc.users:
|
||||||
|
real_target = target
|
||||||
|
elif not irc.is_channel(target):
|
||||||
|
# Convert nick of the message target to a UID, if the target isn't a channel or UID
|
||||||
|
potential_targets = irc.nick_to_uid(target, multi=True)
|
||||||
|
if not potential_targets: # Unknown target user, if target isn't a valid channel name
|
||||||
irc.error('Unknown user %r.' % target)
|
irc.error('Unknown user %r.' % target)
|
||||||
return
|
return
|
||||||
|
elif len(potential_targets) > 1:
|
||||||
|
irc.error('Multiple users with the nick %r found: please select the right UID: %s' % (target, str(potential_targets)))
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
real_target = potential_targets[0]
|
||||||
else:
|
else:
|
||||||
real_target = target
|
real_target = target
|
||||||
|
|
||||||
|
@ -333,6 +333,29 @@ def jupe(irc, source, args):
|
|||||||
|
|
||||||
irc.reply("Done.")
|
irc.reply("Done.")
|
||||||
|
|
||||||
|
def _try_find_target(irc, nick):
|
||||||
|
"""
|
||||||
|
Tries to find the target UID for the given nick, raising LookupError if it doesn't exist or is ambiguous.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
int_u = int(nick)
|
||||||
|
except:
|
||||||
|
int_u = None
|
||||||
|
|
||||||
|
if int_u and int_u in irc.users:
|
||||||
|
return int_u # Some protocols use numeric UIDs
|
||||||
|
elif nick in irc.users:
|
||||||
|
return nick
|
||||||
|
|
||||||
|
potential_targets = irc.nick_to_uid(nick, multi=True)
|
||||||
|
if not potential_targets:
|
||||||
|
# Whatever we were told to kick doesn't exist!
|
||||||
|
raise LookupError("No such target %r." % nick)
|
||||||
|
elif len(potential_targets) > 1:
|
||||||
|
raise LookupError("Multiple users with the nick %r found: please select the right UID: %s" % (nick, str(potential_targets)))
|
||||||
|
else:
|
||||||
|
return potential_targets[0]
|
||||||
|
|
||||||
@utils.add_cmd
|
@utils.add_cmd
|
||||||
def kick(irc, source, args):
|
def kick(irc, source, args):
|
||||||
"""<channel> <user> [<reason>]
|
"""<channel> <user> [<reason>]
|
||||||
@ -347,16 +370,11 @@ def kick(irc, source, args):
|
|||||||
irc.error("Not enough arguments. Needs 2-3: channel, target, reason (optional).")
|
irc.error("Not enough arguments. Needs 2-3: channel, target, reason (optional).")
|
||||||
return
|
return
|
||||||
|
|
||||||
targetu = irc.nick_to_uid(target)
|
|
||||||
|
|
||||||
if channel not in irc.channels: # KICK only works on channels that exist.
|
if channel not in irc.channels: # KICK only works on channels that exist.
|
||||||
irc.error("Unknown channel %r." % channel)
|
irc.error("Unknown channel %r." % channel)
|
||||||
return
|
return
|
||||||
|
|
||||||
if not targetu:
|
targetu = _try_find_target(irc, target)
|
||||||
# Whatever we were told to kick doesn't exist!
|
|
||||||
irc.error("No such target nick %r." % target)
|
|
||||||
return
|
|
||||||
|
|
||||||
sender = irc.pseudoclient.uid
|
sender = irc.pseudoclient.uid
|
||||||
irc.kick(sender, channel, targetu, reason)
|
irc.kick(sender, channel, targetu, reason)
|
||||||
@ -379,17 +397,15 @@ def kill(irc, source, args):
|
|||||||
|
|
||||||
# Convert the source and target nicks to UIDs.
|
# Convert the source and target nicks to UIDs.
|
||||||
sender = irc.pseudoclient.uid
|
sender = irc.pseudoclient.uid
|
||||||
targetu = irc.nick_to_uid(target)
|
|
||||||
userdata = irc.users.get(targetu)
|
|
||||||
|
|
||||||
if targetu not in irc.users:
|
targetu = _try_find_target(irc, target)
|
||||||
# Whatever we were told to kick doesn't exist!
|
|
||||||
irc.error("No such nick %r." % target)
|
if irc.pseudoclient.uid == targetu:
|
||||||
return
|
|
||||||
elif irc.pseudoclient.uid == targetu:
|
|
||||||
irc.error("Cannot kill the main PyLink client!")
|
irc.error("Cannot kill the main PyLink client!")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
userdata = irc.users.get(targetu)
|
||||||
|
|
||||||
# Deliver a more complete kill reason if our target is a non-PyLink client.
|
# Deliver a more complete kill reason if our target is a non-PyLink client.
|
||||||
# We skip this for PyLink clients so that relayed kills don't get
|
# We skip this for PyLink clients so that relayed kills don't get
|
||||||
# "Killed (abc (...))" tacked on both here and by the receiving IRCd.
|
# "Killed (abc (...))" tacked on both here and by the receiving IRCd.
|
||||||
@ -473,23 +489,24 @@ def chghost(irc, source, args):
|
|||||||
"""<user> <new host>
|
"""<user> <new host>
|
||||||
|
|
||||||
Changes the visible host of the target user."""
|
Changes the visible host of the target user."""
|
||||||
chgfield(irc, source, args, 'host')
|
_chgfield(irc, source, args, 'host')
|
||||||
|
|
||||||
@utils.add_cmd
|
@utils.add_cmd
|
||||||
def chgident(irc, source, args):
|
def chgident(irc, source, args):
|
||||||
"""<user> <new ident>
|
"""<user> <new ident>
|
||||||
|
|
||||||
Changes the ident of the target user."""
|
Changes the ident of the target user."""
|
||||||
chgfield(irc, source, args, 'ident')
|
_chgfield(irc, source, args, 'ident')
|
||||||
|
|
||||||
@utils.add_cmd
|
@utils.add_cmd
|
||||||
def chgname(irc, source, args):
|
def chgname(irc, source, args):
|
||||||
"""<user> <new name>
|
"""<user> <new name>
|
||||||
|
|
||||||
Changes the GECOS (realname) of the target user."""
|
Changes the GECOS (realname) of the target user."""
|
||||||
chgfield(irc, source, args, 'name', 'GECOS')
|
_chgfield(irc, source, args, 'name', 'GECOS')
|
||||||
|
|
||||||
def chgfield(irc, source, args, human_field, internal_field=None):
|
def _chgfield(irc, source, args, human_field, internal_field=None):
|
||||||
|
"""Helper function for chghost/chgident/chgname."""
|
||||||
permissions.check_permissions(irc, source, ['opercmds.chg' + human_field])
|
permissions.check_permissions(irc, source, ['opercmds.chg' + human_field])
|
||||||
try:
|
try:
|
||||||
target = args[0]
|
target = args[0]
|
||||||
@ -499,10 +516,7 @@ def chgfield(irc, source, args, human_field, internal_field=None):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Find the user
|
# Find the user
|
||||||
targetu = irc.nick_to_uid(target)
|
targetu = _try_find_target(irc, target)
|
||||||
if targetu not in irc.users:
|
|
||||||
irc.error("No such nick %r." % target)
|
|
||||||
return
|
|
||||||
|
|
||||||
internal_field = internal_field or human_field.upper()
|
internal_field = internal_field or human_field.upper()
|
||||||
irc.update_client(targetu, internal_field, new)
|
irc.update_client(targetu, internal_field, new)
|
||||||
|
Loading…
Reference in New Issue
Block a user