async def validate_filter(ctx, _filter: str, filter_context: FilterContext) -> bool: """Returns whether the filter was considered valid. If invalid, an appropriate response is sent where the command was called. Requires a filter context to determine filter validity.""" try: expansion = expand(_filter) except ValueError as err: # E.g. parenthesis inequality. await ctx.respond(f"{str(err)}", embed=filters_embed(filter_context), ephemeral=True) return False invalid_gates = set(get_invalid_gates(_filter)) if invalid_gates: invalids_formatted = "`" + "`, `".join(invalid_gates) + "`" await ctx.respond(f"✗ Invalid positioning of gate(s) {invalids_formatted} in expansion `{expansion}`.", embed=filters_embed(filter_context), ephemeral=True) return False invalid_keys = set(get_invalid_keys(_filter, filter_context)) if invalid_keys: invalids_formatted = "`" + "`, `".join(invalid_keys) + "`" await ctx.respond(f"✗ Invalid key(s) {invalids_formatted} in expansion `{expansion}`.", embed=filters_embed(filter_context), ephemeral=True) return False invalid_filters = set(get_invalid_filters(_filter, filter_context)) if invalid_filters: keys = [] invalids_strs = [] for key, value in invalid_filters: invalids_strs.append(f"{key}:{value}") keys.append(key) invalids_formatted = "`" + "`, `".join(invalids_strs) + "`" # `keys` will have at least one element, else `invalid_filters` would be falsy. await ctx.respond(f"✗ Invalid value(s) for key(s) {invalids_formatted} in expansion `{expansion}`.", embed=filter_embed(keys[0], filter_context), ephemeral=True) return False invalid_words = set(get_invalid_words(_filter)) if invalid_words: invalids_formatted = "`" + "`, `".join(invalid_words) + "`" await ctx.respond(f"✗ Invalid word(s) {invalids_formatted} in expansion `{expansion}`.", embed=filters_embed(filter_context), ephemeral=True) return False parts = get_missing_gate(_filter) if parts: left_part, right_part = parts await ctx.respond(f"✗ Missing gate between `{left_part}` and `{right_part}` in expansion `{expansion}`.", embed=filters_embed(filter_context), ephemeral=True) return False if not hasattr(ctx.channel, "guild"): # Prevents excessive discord rate limiting (5 DMs per second globally). await ctx.respond("✗ Cannot subscribe in DM channels.", ephemeral=True) return False return True
def test_invalid_filter_types_multiple(): assert (list( get_invalid_filters( "type:undefined or type:nominate or user:someone and type:\"something else\"", filter_context)) == [("type", "undefined"), ("type", "something else")])
def test_invalid_filter_types_escaped(): assert list( get_invalid_filters("type:\"kudosu gain\" or type:\"something else\"", filter_context)) == [("type", "something else")]
def test_invalid_filter_types_alias(): assert list( get_invalid_filters("type:nom or type:nomnom or type:qual", filter_context)) == [("type", "nomnom")]
def test_invalid_filter_types(): assert list( get_invalid_filters("type:undefined or user:someone or type:qualify", filter_context)) == [("type", "undefined")]
def test_invalid_filter_ids(): assert (list( get_invalid_filters( "user-id:test or mapset-id:\"test two\" or user-id:12381031", filter_context)) == [("user-id", "test"), ("mapset-id", "test two")])
def test_invalid_filter_modes(): assert list( get_invalid_filters("mode:test or mode:osu or mode:catch", filter_context)) == [("mode", "test")]
def test_invalid_filter_freetext(): assert list( get_invalid_filters( "content:\"askjda kjsfh jgniqweunf\" or user:kjfhakjshd", filter_context)) == []