001//
002// MIT License
003//
004// Copyright (c) 2021 Alexander Söderberg & Contributors
005//
006// Permission is hereby granted, free of charge, to any person obtaining a copy
007// of this software and associated documentation files (the "Software"), to deal
008// in the Software without restriction, including without limitation the rights
009// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
010// copies of the Software, and to permit persons to whom the Software is
011// furnished to do so, subject to the following conditions:
012//
013// The above copyright notice and this permission notice shall be included in all
014// copies or substantial portions of the Software.
015//
016// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
017// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
018// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
019// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
020// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
021// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
022// SOFTWARE.
023//
024package cloud.commandframework.pircbotx.arguments;
025
026import cloud.commandframework.arguments.CommandArgument;
027import cloud.commandframework.arguments.parser.ArgumentParseResult;
028import cloud.commandframework.arguments.parser.ArgumentParser;
029import cloud.commandframework.captions.CaptionVariable;
030import cloud.commandframework.context.CommandContext;
031import cloud.commandframework.exceptions.parsing.NoInputProvidedException;
032import cloud.commandframework.exceptions.parsing.ParserException;
033import cloud.commandframework.pircbotx.PircBotXCommandManager;
034import io.leangen.geantyref.TypeToken;
035import org.checkerframework.checker.nullness.qual.NonNull;
036import org.checkerframework.checker.nullness.qual.Nullable;
037import org.pircbotx.PircBotX;
038import org.pircbotx.User;
039import org.pircbotx.exception.DaoException;
040
041import java.util.LinkedList;
042import java.util.List;
043import java.util.Queue;
044import java.util.function.BiFunction;
045
046/**
047 * {@link CommandArgument Command argument} that parses PircBotX {@link User users}
048 *
049 * @param <C> Command sender type
050 * @since 1.1.0
051 */
052public final class UserArgument<C> extends CommandArgument<C, User> {
053
054    private UserArgument(
055            final boolean required,
056            final @NonNull String name,
057            final @Nullable BiFunction<CommandContext<C>, String, List<String>> suggestionsProvider
058    ) {
059        super(
060                required,
061                name,
062                new UserArgumentParser<>(),
063                "",
064                TypeToken.get(User.class),
065                suggestionsProvider,
066                new LinkedList<>()
067        );
068    }
069
070    /**
071     * Create a new user argument builder
072     *
073     * @param name Argument name
074     * @param <C>  Command sender type
075     * @return Builder instance
076     */
077    public static <C> @NonNull Builder<C> newBuilder(final @NonNull String name) {
078        return new Builder<>(name);
079    }
080
081    /**
082     * Create a new required user argument
083     *
084     * @param name Argument name
085     * @param <C>  Command sender type
086     * @return Argument instance
087     */
088    public static <C> @NonNull CommandArgument<C, User> of(final @NonNull String name) {
089        return UserArgument.<C>newBuilder(name).asRequired().build();
090    }
091
092    /**
093     * Create a optional user argument
094     *
095     * @param name Argument name
096     * @param <C>  Command sender type
097     * @return Argument instance
098     */
099    public static <C> @NonNull CommandArgument<C, User> optional(final @NonNull String name) {
100        return UserArgument.<C>newBuilder(name).asOptional().build();
101    }
102
103
104    public static final class Builder<C> extends CommandArgument.Builder<C, User> {
105
106        private Builder(
107                final @NonNull String name
108        ) {
109            super(
110                    TypeToken.get(User.class),
111                    name
112            );
113        }
114
115        @Override
116        public @NonNull CommandArgument<@NonNull C, @NonNull User> build() {
117            return new UserArgument<>(
118                    this.isRequired(),
119                    this.getName(),
120                    this.getSuggestionsProvider()
121            );
122        }
123
124    }
125
126
127    public static final class UserArgumentParser<C> implements ArgumentParser<C, User> {
128
129        @Override
130        public @NonNull ArgumentParseResult<@NonNull User> parse(
131                final @NonNull CommandContext<@NonNull C> commandContext,
132                final @NonNull Queue<@NonNull String> inputQueue
133        ) {
134            final String input = inputQueue.peek();
135            if (input == null) {
136                return ArgumentParseResult.failure(new NoInputProvidedException(
137                        UserArgumentParser.class,
138                        commandContext
139                ));
140            }
141            final PircBotX pircBotX = commandContext.get(PircBotXCommandManager.PIRCBOTX_META_KEY);
142            final User user;
143            try {
144                user = pircBotX.getUserChannelDao().getUser(input);
145                inputQueue.remove();
146            } catch (final DaoException exception) {
147                return ArgumentParseResult.failure(
148                        new UserParseException(
149                                commandContext,
150                                input
151                        )
152                );
153            }
154            return ArgumentParseResult.success(user);
155        }
156
157    }
158
159
160    public static final class UserParseException extends ParserException {
161
162        private static final long serialVersionUID = -1758590697299611905L;
163
164        private UserParseException(
165                final @NonNull CommandContext<?> context,
166                final @NonNull String input
167        ) {
168            super(
169                    UserArgumentParser.class,
170                    context,
171                    PircBotXCommandManager.ARGUMENT_PARSE_FAILURE_USER_KEY,
172                    CaptionVariable.of(
173                            "input",
174                            input
175                    )
176            );
177        }
178
179    }
180
181}