Exemple #1
0
    """<message text>

    Sends out a Instance-wide notice.
    """
    permissions.checkPermissions(irc, source, ["global.global"])
    message = " ".join(args)
    global_conf = conf.conf.get('global') or {}
    template = string.Template(global_conf.get('format', DEFAULT_FORMAT))

    for name, ircd in world.networkobjects.items():
        if ircd.connected.is_set(
        ):  # Only attempt to send to connected networks
            for channel in ircd.pseudoclient.channels:
                subst = {
                    'sender': irc.getFriendlyName(source),
                    'network': irc.name,
                    'fullnetwork': irc.getFullNetworkName(),
                    'current_channel': channel,
                    'current_network': ircd.name,
                    'current_fullnetwork': ircd.getFullNetworkName(),
                    'text': message
                }

                # Disable relaying or other plugins handling the global message.
                ircd.msg(channel,
                         template.safe_substitute(subst),
                         loopback=False)


utils.add_cmd(g, "global", featured=True)
Exemple #2
0
# foxy.py: some fun stuff for the foxy
from pylinkirc import utils
from pylinkirc.log import log

import random


def pet(irc, source, args):
    if irc.pseudoclient.nick == "py-foxy":
        # if <= 25, purrs
        # if 26-49, whines
        # if 50-74, scratches
        # if 75-100, kills
        result = random.randrange(1, 100)
        mynick = irc.pseudoclient.nick
        myuid = irc.nickToUid(mynick)
        if result in range(0, 25):
            irc.reply('\x01ACTION purrs\x01')
        elif result in range(26, 50):
            irc.reply('\x01ACTION whines\x01')
        elif result in range(51, 75):
            irc.reply('\x01ACTION scratches %s\x01' %
                      (irc.getFriendlyName(source)))
        elif result in range(76, 100):
            irc.proto.kill(myuid, source,
                           '* kills %s' % (irc.getFriendlyName(source)))


utils.add_cmd(pet, "pet")
Exemple #3
0
    Admin-only. Executes <code> in the current PyLink instance. This command performs backslash escaping of characters, so things like \\n and \\ will work.
    \x02**WARNING: THIS CAN BE DANGEROUS IF USED IMPROPERLY!**\x02"""
    irc.checkAuthenticated(source, allowOper=False)

    # Allow using \n in the code, while escaping backslashes correctly otherwise.
    args = bytes(' '.join(args), 'utf-8').decode("unicode_escape")
    if not args.strip():
        irc.reply('No code entered!')
        return

    log.info('(%s) Executing %r for %s', irc.name, args,
             irc.getHostmask(source))
    exec(args, globals(), locals())


utils.add_cmd(_exec, 'exec')


def _eval(irc, source, args):
    """<Python expression>

    Admin-only. Evaluates the given Python expression and returns the result.
    \x02**WARNING: THIS CAN BE DANGEROUS IF USED IMPROPERLY!**\x02"""
    irc.checkAuthenticated(source, allowOper=False)

    args = ' '.join(args)
    if not args.strip():
        irc.reply('No code entered!')
        return

    log.info('(%s) Evaluating %r for %s', irc.name, args,
Exemple #4
0
        # join() doesn't support prefixes.
        if prefixes:
            irc.sjoin(irc.sid, real_channel, [(joinmodes, u)])
        else:
            irc.join(u, real_channel)

        try:
            modes = irc.channels[real_channel].modes
        except KeyError:
            modes = []

        # Signal the join to other plugins
        irc.call_hooks([u, 'PYLINK_BOTSPLUGIN_JOIN', {'channel': real_channel, 'users': [u],
                                                     'modes': modes, 'parse_as': 'JOIN'}])
    irc.reply("Done.")
utils.add_cmd(joinclient, name='join')

@utils.add_cmd
def nick(irc, source, args):
    """[<target>] <newnick>

    Changes the nick of <target>, a PyLink client, to <newnick>. If <target> is not given, it defaults to the main PyLink client."""

    permissions.check_permissions(irc, source, ['bots.nick'])

    try:
        nick = args[0]
        newnick = args[1]
    except IndexError:
        try:
            nick = irc.pseudoclient.nick
Exemple #5
0
    if irc.is_channel(irc.called_in):
        irc.reply('Error: This command must be sent in private. '
                  '(Would you really type a password inside a channel?)')
        return
    try:
        username, password = args[0], args[1]
    except IndexError:
        irc.reply('Error: Not enough arguments.')
        return

    # Process new-style accounts.
    if check_login(username, password):
        _irc_try_login(irc, source, username)
        return

    # Process legacy logins (login:user).
    if username.lower() == conf.conf['login'].get(
            'user',
            '').lower() and password == conf.conf['login'].get('password'):
        realuser = conf.conf['login']['user']
        _irc_try_login(irc, source, realuser, skip_checks=True)
        return

    # Username not found or password incorrect.
    log.warning("(%s) Failed login to %r from %s", irc.name, username,
                irc.get_hostmask(source))
    raise utils.NotAuthorizedError('Bad username or password.')


utils.add_cmd(identify, aliases=('login', 'id'))
            else:
                irc.error("hash algorithm '%s' unavailable, see 'algorithms'" %
                          digest,
                          private=True)
        else:
            d = hashlib.new("sha256")
            d.update(b'%s' % password.encode('utf-8'))
            irc.reply(d.hexdigest(), private=True)
    except IndexError:
        irc.error(
            "Not enough arguments. Needs 1-2: password, digest (optional).",
            private=True)


def algorithms(irc, source, args):
    """algorithms [query]
    When given '.' gives all available algorithms, or will filter the available when given a starting few characters."""
    try:
        digest = args[0]
        pattern = re.compile(r"%s.*" % digest, re.I)
        avail_digests = filter(pattern.search,
                               list(hashlib.algorithms_available))
        avail_digests = " \xB7 ".join(avail_digests)
        irc.reply(avail_digests, private=True)
    except IndexError:
        irc.error("Not enough arguments. Needs 1: query.", private=True)


utils.add_cmd(algorithms, "algorithms")
utils.add_cmd(_hash, "hash")
Exemple #7
0
    config = bls._dict()
    if config.get("blacklists", {}):
        blacklist = args.blacklist
        if config.get('blacklists').get(blacklist, {}):
            record = args.record
            reply = " ".join(args.reply)
            config['blacklists'][blacklist]['records'][record] = reply
            bls.dump(config)
            irc.reply("Record added to %s. %d: %s" % (blacklist, record, reply))
        else:
            irc.error("Blacklist %s is not defined" % blacklist)
    else:
        irc.error("Could not retrieve blacklists")

    
utils.add_cmd(addrec, "radd", featured=True)

dnsbl_remrec = utils.IRCParser()
dnsbl_remrec.add_argument('blacklist')
dnsbl_remrec.add_argument('record', type=int)
def remrec(irc, source, args):
    """<blacklist> <record>
    Removes record from blacklist.
    """
    permissions.checkPermissions(irc, source, ["dnsbl.rrem"])
    args = dnsbl_remrec.parse_args(args)
    bls = Blacklists()
    config = bls._dict()
    try:
        del config['blacklists'][args.blacklist]['records'][args.record]
        bls.dump(config)
Exemple #8
0
@utils.add_cmd
# irc: The IRC object where the command was called.
# source: The UID/numeric of the calling user.
# args: A list of command args (excluding the command name) that the command was called with.
def randint(irc, source, args):
    # The docstring here is used as command help by the 'help' command, and formatted using the
    # same line breaks as the raw string. You shouldn't make this text or any one line too long,
    # to prevent flooding users or getting long lines cut off.

    # The same applies to message replies in general: plugins sending long strings of text should
    # be wary that long messages can get cut off. Automatic word-wrap may be added in the future:
    # https://github.com/GLolol/PyLink/issues/153
    """[<min> <max>]
    Returns a random number between <min> and <max>. <min> and <max> default
    to 1 and 10 respectively, if both aren't given."""
    try:
        rmin = args[0]
        rmax = args[1]
    except IndexError:
       rmin, rmax = 1, 10
    n = random.randint(rmin, rmax)

    # irc.reply() is intelligent and will automatically reply to the caller in
    # right context. If fantasy is loaded and you call the command via it,
    # it will send replies into the channel instead of in your PM.
    irc.reply(str(n))

# You can also bind a command function multiple times, and/or to different command names via a
# second argument.
utils.add_cmd(randint, "random")
Exemple #9
0
                remoteirc = world.networkobjects[relay_server]
                if remoteirc.proto.hasCap('can-track-servers'):
                    # Only ever show relay subservers once - this prevents infinite loops.
                    showall(remoteirc,
                            remoteirc.sid,
                            hops=hops,
                            is_relay_server=True)

        else:
            # Afterwards, decrement the hopcount.
            hops -= 1

    # Start the map at our PyLink server
    firstserver = hostsid
    showall(ircobj, firstserver)
    serverlist = irc.servers
    reply('Total %s users on %s local servers - average of %1.f per server' %
          (usercount, len(serverlist), usercount / len(serverlist)))


utils.add_cmd(_map, 'map')


@utils.add_cmd
def localmap(irc, source, args):
    """[<network>]

    Shows the network map for the given network, or the current network if not specified.
    This command does not expand Relay subservers."""
    _map(irc, source, args, show_relay=False)
Exemple #10
0
        options = parser.parse_args(args)
    else:
        irc.reply("Syntax: rr {ADD|SHOW|DEL} <args...>")
        irc.reply("See 'help rr' for more info.")
    if options.command == "cf_add":
        response = cf_add(options)
        if response:
            result = response["result"]
            irc.reply("Record Added. %(name)s as %(content)s" % result,
                      private=False)
            irc.reply("Record ID: %(id)s" % result, private=False)

    elif options.command == "cf_show":
        response = cf_show(options)
        count = response.get("result_info", {}).get("count", 0)
        result = response.get("result", [])
        irc.reply("Found %d records" % count, private=False)
        for res in result:
            irc.reply("\x02Name\x02: %(name)s \x02Content\x02: %(content)s" %
                      res,
                      private=False)
            irc.reply("\x02ID\x02: %(id)s" % res, private=False)

    elif options.command == "cf_rem":
        response = cf_rem(options)
        result = response["result"]
        irc.reply("Record Removed. ID: %(id)s" % result, private=False)


utils.add_cmd(rr, "rr", featured=True)
Exemple #11
0
# ctcp.py: Handles basic CTCP requests.
import random
import datetime

from pylinkirc import utils
from pylinkirc.log import log


def handle_ctcpversion(irc, source, args):
    """
    Handles CTCP version requests.
    """
    irc.msg(source, '\x01VERSION %s\x01' % irc.version(), notice=True)


utils.add_cmd(handle_ctcpversion, '\x01version')
utils.add_cmd(handle_ctcpversion, '\x01version\x01')


def handle_ctcpping(irc, source, args):
    """
    Handles CTCP ping requests.
    """
    # CTCP PING 23152511
    pingarg = ' '.join(args).strip('\x01')
    irc.msg(source, '\x01PING %s\x01' % pingarg, notice=True)


utils.add_cmd(handle_ctcpping, '\x01ping')

Exemple #12
0
def randint(irc, source, args):
    # The 'help' command uses command functions' docstrings as help text, and formats them
    # in the following manner:
    # - Any newlines immediately adjacent to text on both sides are replaced with a space. This
    #   means that the first descriptive paragraph ("Returns a random...given.") shows up as one
    #   line, even though it is physically written on two.
    # - Double line breaks are treated as breaks between two paragraphs, and will be shown
    #   as distinct lines in IRC.
    # As of PyLink 2.0, long paragraphs are automatically word-wrapped by irc.reply().
    """[<min> <max>]

    Returns a random number between <min> and <max>. <min> and <max> default to 1 and 10
    respectively, if both aren't given.

    Example second paragraph here."""
    try:
        rmin = args[0]
        rmax = args[1]
    except IndexError:
        rmin, rmax = 1, 10
    n = random.randint(rmin, rmax)

    # irc.reply() is intelligent and will automatically reply to the caller in
    # right context. If fantasy is loaded and you call the command via it,
    # it will send replies into the channel instead of in your PM.
    irc.reply(str(n))


# You can bind a command function to multiple names using the 'aliases' option.
utils.add_cmd(randint, "random", aliases=("randint", "getrandint"))
Exemple #13
0
    
    try:
        template = args[1]
    except IndexError:
        irc.error("no template given, using default")

    if lengtharg == 0 and template == "":
        irc.error("using default length and a default template")
        
    result = ""
    if isinstance(lengtharg, int):
        if lengtharg == "" and template == "":
            template = "[\c\\u\d]"
            template = template + "{%s}" % length
            result = sg("%s" % template).render()            
        if lengtharg == 0 and template == "":
            template = "[\c\\u\d\p]"
            template = template + "{%s}" % length
            result = sg("%s" % template).render()
        elif lengtharg > 0 and template == "":
            template = "[\c\\u\d\p]"        
            result = sg("%s{%s}" % (template, lengtharg)).render()
        elif lengtharg == 0 and template != "":
            result = sg("%s" % template).render()
        else:
            irc.error("part of your input was invalid")
        
    password = result
    irc.reply(password, private=True)
utils.add_cmd(passgen, "passgen")
    try:
        template = args[1]
    except IndexError:
        irc.error("no template given, using default")

    if lengtharg == 0 and template == "":
        irc.error("using default length and a default template")

    result = ""
    if isinstance(lengtharg, int):
        if lengtharg == "" and template == "":
            template = "[\c\\u\d]"
            template = template + "{%s}" % length
            result = sg("%s" % template).render()
        if lengtharg == 0 and template == "":
            template = "[\c\\u\d\p]"
            template = template + "{%s}" % length
            result = sg("%s" % template).render()
        elif lengtharg > 0 and template == "":
            template = "[\c\\u\d\p]"
            result = sg("%s{%s}" % (template, lengtharg)).render()
        elif lengtharg == 0 and template != "":
            result = sg("%s" % template).render()
        else:
            irc.error("part of your input was invalid")

    password = result
    irc.reply(password, private=True)
utils.add_cmd(passgen, "passgen")
Exemple #15
0
            irc.reply("Error: Invalid channel name %r." % channel)
            return
        irc.proto.join(u, channel)

        # Call a join hook manually so other plugins like relay can understand it.
        irc.callHooks([
            u, 'PYLINK_BOTSPLUGIN_JOIN', {
                'channel': channel,
                'users': [u],
                'modes': irc.channels[channel].modes,
                'parse_as': 'JOIN'
            }
        ])


utils.add_cmd(joinclient, name='join')


@utils.add_cmd
def nick(irc, source, args):
    """[<target>] <newnick>

    Admin-only. Changes the nick of <target>, a PyLink client, to <newnick>. If <target> is not given, it defaults to the main PyLink client."""
    irc.checkAuthenticated(source, allowOper=False)

    try:
        nick = args[0]
        newnick = args[1]
    except IndexError:
        try:
            nick = irc.pseudoclient.nick
        if digest:
            if digest in digests:
                d = hashlib.new("%s" % digest)
                d.update(password)
                irc.reply(d.hexdigest(), private=True)
            else:
                irc.error("hash algorithm '%s' unavailable, see 'algorithms'" % digest, private=True)
        else:
            d = hashlib.new("sha256")
            d.update(password)
            irc.reply(d.hexdigest(), private=True)
    except IndexError:
        irc.error("Not enough arguments. Needs 1-2: password, digest (optional).", private=True)


def algorithms(irc, source, args):
    """algorithms [query]
    When given '.' gives all available algorithms, or will filter the available when given a starting few characters."""
    try:
        digest = args[0]
        pattern = re.compile(r"%s.*" % digest, re.I)
        avail_digests = filter(pattern.search, list(hashlib.algorithms_available))
        avail_digests = " \xB7 ".join(avail_digests)
        irc.reply(avail_digests, private=True)
    except IndexError:
        irc.error("Not enough arguments. Needs 1: query.", private=True)


utils.add_cmd(algorithms, "algorithms", featured=True)
utils.add_cmd(_hash, "hash", featured=True)
Exemple #17
0
                          (min([results, args.maxresults]), results),
                          private=True)
            else:
                irc.reply("No results found.", private=True)
    else:
        # Target can be both a nick (of an online user) or a hostmask. irc.match_host() handles this
        # automatically.
        if irc.match_host(args.banmask, args.target):
            irc.reply('Yes, \x02%s\x02 matches \x02%s\x02.' %
                      (args.target, args.banmask))
        else:
            irc.reply('No, \x02%s\x02 does not match \x02%s\x02.' %
                      (args.target, args.banmask))


utils.add_cmd(checkban, aliases=('cban', 'trace'))


def checkbanre(irc, source, args):
    """<regular expression> [<target nick or hostmask>] [--channel #channel] [--maxresults <num>]

    CHECKBANRE provides a ban checker command based on regular expressions matched against
    users' "nick!user@host [gecos]" mask.

    If a target nick or hostmask is given, this command returns whether the given banmask will match it.
    Otherwise, it will display a list of connected users matching the banmask.

    If the --channel argument is given without a target mask, the returned results will only
    include users in the given channel.

    The --maxresults option configures how many responses will be shown."""
        return
    args = cf_add_parser.parse_args(args)

    body = {
        "type":    args.type,
        "name":    args.name,
        "content": args.content,
        "ttl":     args.ttl
    }

    response = cf.zones.dns_records.post(zone, data=body)
    result = response.get("result", [])
    irc.reply("Record Added. %(name)s as %(content)s" % result, private=False)
    irc.reply("Record ID: %(id)s" % result, private=False)

utils.add_cmd(cf_add, "cf-add", featured=True)

cf_show_parser = utils.IRCParser()
cf_show_parser.add_argument("-t", "--type", choices=["A", "AAAA", "CNAME"])
cf_show_parser.add_argument("subdomain", nargs='?')
cf_show_parser.add_argument("-c", "--content")
cf_show_parser.add_argument("-o", "--order", default="type")
def cf_show(irc, source, args):
    """[<subdomain>] [--type <type>] [--content <record content>] [--order <sort order>]

    Searches CloudFlare DNS records. The following options are supported:

    -t / --type : Type of record

    -c / --content : Content of record / IP