def ctcp(function=None, *command_list):
    """Decorate a callable to trigger on CTCP commands (mostly, ``ACTION``).

    :param str command_list: one or more CTCP command(s) on which to trigger

    .. versionadded:: 7.1

        This is now ``ctcp`` instead of ``intent``, and it can be called
        without argument, in which case it will assume ``ACTION``.

    .. note::

        This used to be ``@intent``, for a long dead feature in the IRCv3 spec.
        It is now replaced by ``@ctcp``, which can be used without arguments.
        In that case, Sopel will assume it should trigger on ``ACTION``.

        As ``sopel.module`` will be removed in Sopel 9, so will ``@intent``.
    """
    default_commands = ('ACTION',) + command_list
    if function is None:
        return ctcp(*default_commands)  # called as ``@ctcp()``
    elif callable(function):
        # called as ``@ctcp`` or ``@ctcp(function)``
        # or even ``@ctcp(function, 'ACTION', ...)``
        return ctcp(*default_commands)(function)

    # function is not None, and it is not a callable
    # called as ``@ctcp('ACTION', ...)``
    ctcp_commands = (function,) + command_list

    def add_attribute(function):
        function._sopel_callable = True
        if not hasattr(function, "intents"):
            function.intents = []
        for name in ctcp_commands:
            if name not in function.intents:
                function.intents.append(name)
        return function
    return add_attribute