docs: private void registerAbilities() {
      try {
        // Collect all classes that implement AbilityExtension declared in the bot
        List<AbilityExtension> extensions = stream(getClass().getMethods())
            .filter(checkReturnType(AbilityExtension.class))
            .map(returnExtension(this))
            .collect(Collectors.toList());
  
        // Add the bot itself as it is an AbilityExtension
        extensions.add(this);
  
        // Extract all abilities from every single extension instance
        abilities = extensions.stream()
            .flatMap(ext -> stream(ext.getClass().getMethods())
                .filter(checkReturnType(Ability.class))
                .map(returnAbility(ext)))
            // Abilities are immutable, build it respectively
            .collect(ImmutableMap::<String, Ability>builder,
                (b, a) -> b.put(a.name(), a),
                (b1, b2) -> b1.putAll(b2.build()))
            .build();
  
        // Extract all replies from every single extension instance
        Stream<Reply> extensionReplies = extensions.stream()
            .flatMap(ext -> stream(ext.getClass().getMethods())
                .filter(checkReturnType(Reply.class))
                .map(returnReply(ext)));
  
        // Replies can be standalone or attached to abilities, fetch those too
        Stream<Reply> abilityReplies = abilities.values().stream()
            .flatMap(ability -> ability.replies().stream());
  
        // Now create the replies registry (list)
        replies = Stream.concat(abilityReplies, extensionReplies).collect(
            ImmutableList::<Reply>builder,
            Builder::add,
            (b1, b2) -> b1.addAll(b2.build()))
            .build();
      } catch (IllegalStateException e) {
        BotLogger.error(TAG, "Duplicate names found while registering abilities. Make sure that the abilities declared don't clash with the reserved ones.", e);
        throw propagate(e);
      }
    }