#!/usr/bin/env python3
#
# Random commands that used to be in sopeltest.py but are to small to get a
# file of their own.
#
# Copyright © 2019-2021 by luk3yx
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
#
import random, string, subprocess, time, unicodedata
# A quick "reply" function
def reply(irc, hostmask, channel, *msg):
mention = hostmask[0]
if not hostmask[0].endswith('>'):
mention += ':'
if isinstance(channel, list):
channel = channel[0]
irc.msg(channel, mention, *map(str, msg))
en_chars = string.ascii_uppercase + string.ascii_lowercase + \
'1234567890!@#$%^&*(),\''
alt_chars = 'ÅıÇδϩӈÔ˚Ò˜Ø∏Œ®Í†¨√∑≈ÁΩå∫ç∂´ƒ©˙ˆ∆˚¬µ˜øπœ®ß†¨√∑≈\Ω¡™£¢∞§¶•ªº' \
'⁄€‹›fifl‡°·‚≤æ'
@register_command('altcode', requires_admin = True)
def altcode_cmd(irc, hostmask, is_admin, args):
"""
Usage: .altcode [encode|decode]
"""
assert is_admin
assert len(en_chars) == len(alt_chars), 'Internal error!'
res = args[1]
if res.startswith('encode '):
res = res[7:]
it = zip(en_chars, alt_chars)
elif res.startswith('decode ') or any(i in res for i in alt_chars):
it = zip(alt_chars, en_chars)
else:
it = zip(en_chars, alt_chars)
for en, alt in it:
res = res.replace(en, alt)
reply(irc, hostmask, args, res)
# Random capitalisation
def randcaps(text):
res = ''.join(random.choice((str.upper, str.lower))(i) for i in text)
return res.replace('S', 'Z').replace('O', '0')
# .silly
@register_command('silly', 'sillycaps')
def silly_cmd(irc, hostmask, is_admin, args):
""" Makes the capitalisation in a string... strange. """
if args[1].strip():
reply(irc, hostmask, args, randcaps(args[1]))
else:
irc.msg(args[0], randcaps('{}nvalid syntax! Syntax:{}').format(
'I', ' .silly '))
# .c0mmandz
@register_command('c0mmandz')
def bonkerzhelp(irc, hostmask, is_admin, args):
irc.msg(args[0], randcaps('Hello! You must be bonkers too!'))
time.sleep(0.75)
irc.msg(args[0], 'So snap out of it and do .commands.')
# .upper and .lower
@register_command('upper', 'uppercase')
def upper_cmd(irc, hostmask, is_admin, args):
""" Makes a string uppercase. """
reply(irc, hostmask, args, args[1].upper().replace('.', '!'))
@register_command('lower', 'lowercase')
def lower_cmd(irc, hostmask, is_admin, args):
""" Makes a string lowercase. """
reply(irc, hostmask, args, args[1].lower().replace('!', '.'))
@register_command('rev', 'reverse')
def rev_cmd(irc, hostmask, is_admin, args):
""" Reverses a string. """
if '\u202e' in args[1]:
irc.msg(args[0], "I don't think so {}™.".format(hostmask[0]))
else:
reply(irc, hostmask, args, args[1][::-1])
@register_command('ping')
def ping(irc, hostmask, is_admin, args):
if not random.randint(0, 9):
irc.me(args[0], 'slaps {} with a frying pan'.format(hostmask[0]))
else:
reply(irc, hostmask, args, 'pong')
# .roulette
roulette_objs = ('trout', '... feather?', 'water molecule', 'troutgun',
'anvil', 'sheet of paper')
@register_command('roulette', 'r')
def roulette_cmd(irc, hostmask, is_admin, args):
""" A Russian roulette-style game. """
if random.randint(1, 6) == 1:
obj = random.choice(roulette_objs)
if not obj.startswith('.'):
obj = ' ' + obj
irc.me(args[0], 'slaps {} around a bit with a large{}'.format(
hostmask[0], obj))
else:
reply(irc, hostmask, args, '\x1dClick!\x1d')
# .choice
def choice_cmd(irc, hostmask, is_admin, args):
choices = map(str.strip, args[-1].split(',' if ',' in args[-1] else ' '))
# Deduplication
choices = {choice.casefold(): choice for choice in choices}
choices = tuple(choices.values())
if len(choices) < 2:
if not choices or not choices[0]:
reply(irc, hostmask, args, 'Invalid syntax! Usage: .choice '
'')
else:
reply(irc, hostmask, args,
'I need more than one option to choose from!')
return
choice = random.choice(choices)
reply(irc, hostmask, args, 'Your options: ' + ', '.join(choices)
+ '. My (random) choice: ' + choice)
# Only register .choice on lurklite.
if register_command.__module__.startswith('lurklite.'):
register_command('choice', 'choose')(choice_cmd)
def get_fortune():
n = subprocess.check_output('/usr/games/fortune').decode('utf-8')
# Avoid bad and possibly offensive fortunes
# This is only targeted at the fortunes provided by Ubuntu.
i = 0
while ('ugly' in n or 'tall, dark' in n or 'pass away' in n or
'blond' in n or 'cigarette' in n or 'appeal' in n):
n = subprocess.check_output('/usr/games/fortune').decode('utf-8')
i += 1
assert i < 100
return n.strip().replace('\t', ' ')
@register_command('f', 'fortune')
def fortune_cmd(irc, hostmask, is_admin, args):
reply(irc, hostmask, args, get_fortune())
@register_command('coin', 'coinflip')
def coinflip_cmd(irc, hostmask, is_admin, args):
if random.randint(0, 6000) == 0:
msg = 'The coin landed on its side!'
elif random.randint(0, 1):
msg = 'Heads'
else:
msg = 'Tails'
reply(irc, hostmask, args, msg)
def get_char_name(char):
# Hack to get the name of control characters. U+2400 is "SYMBOL FOR NULL"
# and this function will remove the leading "SYMBOL FOR " prefix when a
# null byte is passed to it.
if char <= '\x1f':
char = chr(ord(char) + 0x2400)
return unicodedata.name(char)[11:]
return unicodedata.name(char, 'Unknown')
@register_command('chr', 'unicode', 'u')
def unicode_cmd(irc, hostmask, is_admin, args):
chars = args[1]
if len(chars) > 10:
msg = f'You must provide 1-10 characters, not {len(chars)}.'
elif not chars:
msg = 'Usage: .unicode '
else:
msg = ', '.join(f'U+{ord(char):04X} - {get_char_name(char)}'
for char in chars)
reply(irc, hostmask, args, msg)