def func(command, description, link, params_string, returns="On success, the sent Message is returned.", return_type="Message"):
    """
    Live template for pycharm:

    y = func(command="$cmd$", description="$desc$", link="$lnk$", params_string="$first_param$", returns="$returns$", return_type="$returntype$")
    """
    description_with_tabs = "\t\t" + description.strip().replace("\n", "\n\t\t")
    param_list_args = []
    param_list_kwargs = []
    args = []
    args2 = []
    kwargs = []
    kwargs2 = []
    asserts = []
    str_args = ""
    str_kwargs = ""
    param_strings = params_string.split("\n")
    for param in param_strings:
        assert_commands, assert_comments, param_name, param_type, table, non_buildin_type, param_name_input = parse_param_types(param)
        param_required = table[2].strip()
        param_needed = None
        if param_required == "Yes":
            param_needed = True
        elif param_required == "Optional":
            param_needed = False
        param_description = table[3].strip()
        if param_needed:
            param_list_args.append(Param(param_name, param_type,param_needed, param_description))
            args.append(param_name)
            args2.append("{param_name}={param_name}".format(param_name=param_name))
            str_args += '\t\t:param {key}: {descr}\n\t\t:type  {key}: {type}\n\n'.format(key=param_name, descr=param_description, type=param_type)
            if assert_commands:
                asserts.append("assert({var} is not None)".format(var=param_name))
                asserts.append("assert({ass})".format(ass=" or ".join(assert_commands)) + (("  # {comment}".format(comment=", ".join(assert_comments))) if assert_comments else ""))
        else:
            param_list_kwargs.append(Param(param_name, param_type,param_needed, param_description))
            kwargs.append("{param_name}=None".format(param_name=param_name))
            kwargs2.append("{param_name}={param_name}".format(param_name=param_name))
            str_kwargs += '\t\t:keyword {key}: {descr}\n\t\t:type    {key}: {type}\n\n'.format(key=param_name, descr=param_description, type=param_type)
            if assert_commands:
                asserts.append("assert({var} is None or {ass})".format(var=param_name, ass=" or ".join(assert_commands)) + (("  # {comment}".format(comment=", ".join(assert_comments))) if assert_comments else ""))
    args.extend(kwargs)
    args2.extend(kwargs2)
    asserts_string = "\n\t\t" + "\n\t\t".join(asserts)
    text = ""
    if len(str_args)>0:
        text += '\n\t\tParameters:\n\n'
        text += str_args
    if len(str_kwargs)>0:
        text += '\n\t\tOptional keyword parameters:\n\n'
        text += str_kwargs
    do_args = ['"%s"' % command]
    do_args.extend(args2)
    result = '\tdef {funcname}(self, {params}):\n\t\t"""\n{description_with_tabs}\n\n\t\t{link}\n\n' \
           '{paramshit}\n' \
           '\t\tReturns:\n\n\t\t:return: {returns}\n\t\t:rtype:  {return_type}\n\t\t"""{asserts_with_tabs}\n\t\treturn self.do({do_args})\n\t# end def {funcname}'.format(
        funcname=convert_to_underscore(command),
        params=", ".join(args), description_with_tabs=description_with_tabs, link=link,
        returns=returns, return_type=return_type, command=command, do_args=", ".join(do_args),
        asserts_with_tabs=asserts_string,
        paramshit = text
    )
    result = result.replace("\t", "    ")
    return result