-
Notifications
You must be signed in to change notification settings - Fork 0
/
LoginListener.java
142 lines (129 loc) · 6.59 KB
/
LoginListener.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
*
* Copyright (C) 2022 Vasiliy Petukhov <void.pointer@ya.ru>
*
* Everyone is permitted to copy and distribute verbatim or modified
* copies of this license document, and changing it is allowed as long
* as the name is changed.
*
* DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
* TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
*
* 0. You just DO WHAT THE FUCK YOU WANT TO.
*/
package voidpointer.spigot.voidwhitelist.listener;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.plugin.Plugin;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import voidpointer.spigot.framework.di.Autowired;
import voidpointer.spigot.framework.localemodule.LocaleLog;
import voidpointer.spigot.framework.localemodule.annotation.AutowiredLocale;
import voidpointer.spigot.voidwhitelist.TimesAutoWhitelisted;
import voidpointer.spigot.voidwhitelist.Whitelistable;
import voidpointer.spigot.voidwhitelist.config.WhitelistConfig;
import voidpointer.spigot.voidwhitelist.message.KickReason;
import voidpointer.spigot.voidwhitelist.message.WhitelistMessage;
import voidpointer.spigot.voidwhitelist.storage.AutoWhitelistService;
import voidpointer.spigot.voidwhitelist.task.KickTaskScheduler;
import java.util.Date;
import java.util.Optional;
import static org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result.KICK_WHITELIST;
import static voidpointer.spigot.voidwhitelist.message.KickReason.EXPIRED;
import static voidpointer.spigot.voidwhitelist.message.KickReason.NOT_ALLOWED;
import static voidpointer.spigot.voidwhitelist.net.CachedProfileFetcher.removeCachedProfile;
@RequiredArgsConstructor
public final class LoginListener implements Listener {
@AutowiredLocale private static LocaleLog locale;
@Autowired(mapId="whitelistService")
private static AutoWhitelistService autoWhitelistService;
@Autowired private static WhitelistConfig whitelistConfig;
@Autowired private static KickTaskScheduler kickTaskScheduler;
@EventHandler(priority=EventPriority.NORMAL, ignoreCancelled=true)
public void onAsyncPreLogin(final AsyncPlayerPreLoginEvent event) {
/* This listener disallows login if the connecting user is not on the whitelist,
* and due to either configuration or exceeding auto-whitelist.max-repeats limit
* we cannot automatically add the user to the whitelist. */
if (!whitelistConfig.isWhitelistEnabled())
return;
Optional<Whitelistable> user = autoWhitelistService.find(event.getUniqueId()).join();
Optional<KickReason> optionalKickReason = getKickReasonFor(user.orElse(null));
if (!optionalKickReason.isPresent())
return;
if (!whitelistConfig.isAutoWhitelistEnabled()
|| whitelistConfig.getStrategyPredicate().negate().test(event.getUniqueId())
|| (whitelistConfig.getAutoLimit() == 0)) {
disallow(event, optionalKickReason.get());
return;
}
val timesAutoWhitelisted = autoWhitelistService.getTimesAutoWhitelisted(event.getUniqueId()).join();
if (user.isPresent() && timesAutoWhitelisted.isPresent()
&& timesAutoWhitelisted.get().isExceeded(whitelistConfig.getAutoLimit())) {
disallow(event, optionalKickReason.get());
return;
}
final Optional<Date> autoDuration = whitelistConfig.getAutoDuration();
if (!autoDuration.isPresent()) {
locale.warn("Could not apply auto-whitelist to user {0} because of invalid duration {1}",
event.getUniqueId(), whitelistConfig.getRawAutoDuration());
disallow(event, optionalKickReason.get());
return;
}
autoWhitelistService.add(event.getUniqueId(), event.getName(), autoDuration.get(),
timesAutoWhitelisted.map(TimesAutoWhitelisted::get).orElse(0) + 1).thenApplyAsync(whitelistable -> {
if (!whitelistable.isPresent()) {
locale.warn("Automatic whitelisting of {0} failed", event.getUniqueId());
return whitelistable;
}
locale.info("Automatically whitelisted {0} ({1}) until {2}", event.getUniqueId(), event.getName(),
autoDuration.get());
return whitelistable;
});
}
private Optional<KickReason> getKickReasonFor(final @Nullable Whitelistable whitelistable) {
if (whitelistable == null)
return Optional.of(NOT_ALLOWED);
else if (!whitelistable.isAllowedToJoin())
return Optional.of(EXPIRED);
else
return Optional.empty();
}
private void disallow(final AsyncPlayerPreLoginEvent event, final KickReason reason) {
event.disallow(KICK_WHITELIST, locale.localize(WhitelistMessage.of(reason)).getRawMessage());
}
@EventHandler(priority=EventPriority.MONITOR, ignoreCancelled=true)
public void scheduleKickOnJoin(final PlayerJoinEvent event) {
if (!whitelistConfig.isWhitelistEnabled())
return;
autoWhitelistService.find(event.getPlayer().getUniqueId()).thenAcceptAsync(whitelistable -> {
if (!whitelistable.isPresent()) {
locale.severe("No Whitelistable entity found for a player that passed PreLogin check {0}",
event.getPlayer().getUniqueId());
return;
}
updateWhitelistableName(event.getPlayer(), whitelistable.get());
kickTaskScheduler.schedule(whitelistable.get());
}).whenCompleteAsync((res, th) -> {
if (th != null)
locale.warn("Couldn't schedule a KickTask on join event", th);
});
}
public void register(final @NonNull Plugin plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
private void updateWhitelistableName(final Player player, final Whitelistable whitelistable) {
assert player.getUniqueId().equals(whitelistable.getUniqueId())
: "UUID of the updating player must match Whitelistable";
whitelistable.setName(player.getName());
autoWhitelistService.update(whitelistable).thenAcceptAsync(updatedOptional ->
updatedOptional.ifPresent(updated -> removeCachedProfile(updated.getUniqueId())));
}
}