Allow referring to peers by nick
This commit is contained in:
parent
76704d4a11
commit
a140fde1c1
127
ethermess.py
127
ethermess.py
|
@ -54,12 +54,14 @@ def writeall(f, b):
|
||||||
while written < len(b):
|
while written < len(b):
|
||||||
written += f.write(b[written:])
|
written += f.write(b[written:])
|
||||||
|
|
||||||
|
class ReadallError(Exception): pass
|
||||||
|
|
||||||
def readall(f, length):
|
def readall(f, length):
|
||||||
read = bytearray()
|
read = bytearray()
|
||||||
while len(read) < length:
|
while len(read) < length:
|
||||||
data = f.read(length - len(read))
|
data = f.read(length - len(read))
|
||||||
if data == b'':
|
if data == b'':
|
||||||
raise ConnectionError('Could not satisfy read of %i bytes' % length)
|
raise ReadallError('Could not satisfy read of %i bytes' % length)
|
||||||
read.extend(data)
|
read.extend(data)
|
||||||
return bytes(read)
|
return bytes(read)
|
||||||
|
|
||||||
|
@ -67,18 +69,47 @@ def readall_u16(f):
|
||||||
u16_bytes = readall(f, 2)
|
u16_bytes = readall(f, 2)
|
||||||
return (u16_bytes[0] << 8) | u16_bytes[1]
|
return (u16_bytes[0] << 8) | u16_bytes[1]
|
||||||
|
|
||||||
|
class MACParseError(Exception): pass
|
||||||
|
|
||||||
def parse_mac(text):
|
def parse_mac(text):
|
||||||
parts = text.split(':')
|
parts = text.split(':')
|
||||||
if len(parts) != 6:
|
if len(parts) != 6:
|
||||||
raise ValueError('Invalid MAC format: %s' % text)
|
raise MACParseError('Invalid MAC format: %s' % text)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
parsed = bytes(int(field, 16) for field in parts)
|
parsed = bytes(int(field, 16) for field in parts)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError('Invalid MAC format %s' % text)
|
raise MACParseError('Invalid MAC format %s' % text)
|
||||||
|
|
||||||
return parsed
|
return parsed
|
||||||
|
|
||||||
|
class NoMatchesError(Exception): pass
|
||||||
|
class TooManyMatchesError(Exception): pass
|
||||||
|
|
||||||
|
def mac_from_name(text):
|
||||||
|
global peers
|
||||||
|
|
||||||
|
# Try to parse as a MAC address
|
||||||
|
try:
|
||||||
|
mac = parse_mac(text)
|
||||||
|
return mac
|
||||||
|
except MACParseError as err:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# It was not, try to find a matching nick
|
||||||
|
hits = 0
|
||||||
|
for peer_mac, peer in peers.items():
|
||||||
|
if text == peer.nick or text == '~' + peer.nick:
|
||||||
|
hits += 1
|
||||||
|
mac = peer_mac
|
||||||
|
|
||||||
|
if hits == 0:
|
||||||
|
raise NoMatchesError(text)
|
||||||
|
elif hits > 1:
|
||||||
|
raise TooManyMatchesError(text)
|
||||||
|
|
||||||
|
return mac
|
||||||
|
|
||||||
def format_mac(mac):
|
def format_mac(mac):
|
||||||
return ':'.join(mac[i:i+1].hex() for i in range(len(mac)))
|
return ':'.join(mac[i:i+1].hex() for i in range(len(mac)))
|
||||||
|
|
||||||
|
@ -129,45 +160,63 @@ def handle_user_command(backend, line):
|
||||||
|
|
||||||
if len(line) > 0 and line[0] == '/':
|
if len(line) > 0 and line[0] == '/':
|
||||||
command, _, rest = line.partition(' ')
|
command, _, rest = line.partition(' ')
|
||||||
if command == '/':
|
|
||||||
# Send quoted message
|
try:
|
||||||
if default_target_mac is None:
|
if command == '/':
|
||||||
print('--- Default target not set, set with /target')
|
# Send quoted message
|
||||||
|
# TODO: Validate message
|
||||||
|
if default_target_mac is None:
|
||||||
|
print('--- Default target not set, set with /target')
|
||||||
|
else:
|
||||||
|
queue_message(backend, default_target_mac, rest)
|
||||||
|
|
||||||
|
elif command == '/msg':
|
||||||
|
# Send message to target
|
||||||
|
target, _, message = rest.partition(' ')
|
||||||
|
mac = mac_from_name(target)
|
||||||
|
queue_message(backend, mac, message)
|
||||||
|
|
||||||
|
elif command == '/status':
|
||||||
|
# Request status
|
||||||
|
mac = mac_from_name(rest)
|
||||||
|
if mac in peers:
|
||||||
|
print('=== ~%s (%s) [%s]' % (peers[mac].nick, peers[mac].status.name, format_mac(mac)))
|
||||||
|
else:
|
||||||
|
send_status_request(backend, mac)
|
||||||
|
|
||||||
|
elif command == '/available' and rest == '':
|
||||||
|
# Set status to available
|
||||||
|
own_status = statuses.available
|
||||||
|
set_status_nick(backend, own_status, own_nick)
|
||||||
|
|
||||||
|
elif command == '/unavailable' and rest == '':
|
||||||
|
# Set status to unavailable
|
||||||
|
own_status = statuses.unavailable
|
||||||
|
set_status_nick(backend, own_status, own_nick)
|
||||||
|
|
||||||
|
elif command == '/nick':
|
||||||
|
# Change nick
|
||||||
|
# TODO: Validate nick
|
||||||
|
own_nick = rest
|
||||||
|
set_status_nick(backend, own_status, own_nick)
|
||||||
|
|
||||||
|
elif command == '/target':
|
||||||
|
# Set default target of messages
|
||||||
|
default_target_mac = mac_from_name(rest)
|
||||||
|
|
||||||
|
elif command == '/quit':
|
||||||
|
# Quit
|
||||||
|
return 'quit'
|
||||||
|
|
||||||
else:
|
else:
|
||||||
queue_message(backend, default_target_mac, rest)
|
# Display usage
|
||||||
|
print('--- / <message>; /msg <target> <message>; /status <target>; /available; /unavailable; /nick <nick>; /target <target>; /quit')
|
||||||
|
|
||||||
elif command == '/msg':
|
except NoMatchesError as err:
|
||||||
# Send message to target
|
print('--- name %s matches no peers' % err.args[0])
|
||||||
mac_str, _, message = rest.partition(' ')
|
|
||||||
mac = parse_mac(mac_str)
|
|
||||||
queue_message(backend, mac, message)
|
|
||||||
|
|
||||||
elif command == '/status':
|
except TooManyMatchesError as err:
|
||||||
# Request status
|
print('--- name %s matches several peers' % err.args[0])
|
||||||
mac = parse_mac(rest)
|
|
||||||
send_status_request(backend, mac)
|
|
||||||
|
|
||||||
elif command == '/available' and rest == '':
|
|
||||||
own_status = statuses.available
|
|
||||||
set_status_nick(backend, own_status, own_nick)
|
|
||||||
|
|
||||||
elif command == '/unavailable' and rest == '':
|
|
||||||
own_status = statuses.unavailable
|
|
||||||
set_status_nick(backend, own_status, own_nick)
|
|
||||||
|
|
||||||
elif command == '/nick':
|
|
||||||
own_nick = rest
|
|
||||||
set_status_nick(backend, own_status, own_nick)
|
|
||||||
|
|
||||||
elif command == '/target':
|
|
||||||
default_target_mac = parse_mac(rest)
|
|
||||||
|
|
||||||
elif command == '/quit':
|
|
||||||
return 'quit'
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Display usage
|
|
||||||
print('--- / <message>; /msg <MAC> <message>; /status <MAC>; /available; /unavailable; /nick <nick>; /target <MAC>; /quit')
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Send message
|
# Send message
|
||||||
|
|
Loading…
Reference in New Issue