:return:
        a delegator function that calls the ``cls`` constructor whose arguments being
        a seed tuple followed by supplied ``*args`` and ``**kwargs``, then returns
        a looping function that uses the object's ``listener`` to wait for messages
        and invokes instance method ``open``, ``on_message``, and ``on_close`` accordingly.
        By default, a thread wrapping that looping function is spawned.

def create_open(cls, *args, **kwargs):
    """
    :return:
        a delegator function that calls the ``cls`` constructor whose arguments being
        a seed tuple followed by supplied ``*args`` and ``**kwargs``, then returns
        a looping function that uses the object's ``listener`` to wait for messages
        and invokes instance method ``open``, ``on_message``, and ``on_close`` accordingly.
        By default, a thread wrapping that looping function is spawned.
    """
    def f(seed_tuple):
        j = cls(seed_tuple, *args, **kwargs)

        def wait_loop():
            bot, msg, seed = seed_tuple
            try:
                handled = j.open(msg, seed)
                if not handled:
                    j.on_message(msg)

                while 1:
                    msg = j.listener.wait()
                    j.on_message(msg)

            # These exceptions are "normal" exits.
            except (exception.IdleTerminate, exception.StopListening) as e:
                j.on_close(e)

            # Any other exceptions are accidents. **Print it out.**
            # This is to prevent swallowing exceptions in the case that on_close()
            # gets overridden but fails to account for unexpected exceptions.
            except Exception as e:
                traceback.print_exc()
                j.on_close(e)

        return wait_loop
    return f