Skip to content

Commit 8baf07a

Browse files
authored
Added invoice notifications (#96)
2 parents c6502b0 + 3a032a9 commit 8baf07a

File tree

7 files changed

+85
-1
lines changed

7 files changed

+85
-1
lines changed

src/main/java/pro/cloudnode/smp/bankaccounts/BankAccounts.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
import com.google.gson.JsonParser;
55
import com.zaxxer.hikari.HikariConfig;
66
import com.zaxxer.hikari.HikariDataSource;
7+
import net.kyori.adventure.text.Component;
78
import org.bukkit.NamespacedKey;
89
import org.bukkit.OfflinePlayer;
910
import org.bukkit.command.CommandExecutor;
1011
import org.bukkit.command.CommandSender;
1112
import org.bukkit.command.PluginCommand;
13+
import org.bukkit.entity.Player;
1214
import org.bukkit.event.Listener;
1315
import org.bukkit.plugin.java.JavaPlugin;
1416
import org.bukkit.scheduler.BukkitTask;
@@ -162,6 +164,12 @@ public static void reload() {
162164
getInstance().getLogger().warning("Update details: https://modrinth.com/plugin/bankaccounts/version/" + latestVersion);
163165
}));
164166
getInstance().startInterestTimer();
167+
if (getInstance().invoiceNotificationTask != null) {
168+
final int taskId = getInstance().invoiceNotificationTask.getTaskId();
169+
getInstance().getServer().getScheduler().cancelTask(taskId);
170+
getInstance().invoiceNotificationTask = null;
171+
}
172+
getInstance().setupInvoiceNotificationTimer();
165173
}
166174

167175
/**
@@ -247,6 +255,20 @@ private void startInterestTimer() {
247255
}, 0L, 20L*60);
248256
}
249257

258+
private @Nullable BukkitTask invoiceNotificationTask = null;
259+
260+
private void setupInvoiceNotificationTimer() {
261+
if (config().invoiceNotifyInterval() <= 0) return;
262+
this.invoiceNotificationTask = getServer().getScheduler().runTaskTimerAsynchronously(this, () -> {
263+
for (final @NotNull Player player : getServer().getOnlinePlayers()) {
264+
final @NotNull Optional<@NotNull Component> message = BankAccounts.getInstance().config().messagesInvoiceNotify(Invoice.countUnpaid(player));
265+
if (message.isEmpty()) continue;
266+
if (player.hasPermission(Permissions.INVOICE_NOTIFY) && Invoice.countUnpaid(player) > 0)
267+
player.sendMessage(message.get());
268+
}
269+
}, config().invoiceNotifyInterval() * 20L, config().invoiceNotifyInterval() * 20L);
270+
}
271+
250272
private void interestPayment(final @NotNull Account account, final @NotNull BigDecimal amount, final double rate, final @NotNull Account serverAccount) {
251273
if (account.balance == null) return;
252274
if (account.id.equals(serverAccount.id)) return;

src/main/java/pro/cloudnode/smp/bankaccounts/BankConfig.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,16 @@ public int invoicePerPage() {
437437
public @NotNull Pattern disallowedRegex() {
438438
return Pattern.compile(Objects.requireNonNull(config.getString("disallowed-regex")));
439439
}
440+
441+
// invoice.notify.join
442+
public boolean invoiceNotifyJoin() {
443+
return config.getBoolean("invoice.notify.join");
444+
}
445+
446+
// invoice.notify.interval
447+
public int invoiceNotifyInterval() {
448+
return config.getInt("invoice.notify.interval");
449+
}
440450

441451
// messages.command-usage
442452
public @NotNull Component messagesCommandUsage(final @NotNull String command, final @NotNull String arguments) {
@@ -1379,6 +1389,17 @@ public int invoicePerPage() {
13791389
);
13801390
}
13811391

1392+
// messages.invoice.notify
1393+
public @NotNull Optional<@NotNull Component> messagesInvoiceNotify(final int unpaid) {
1394+
final @NotNull String message = Objects.requireNonNull(config.getString("messages.invoice.notify"));
1395+
if (message.isBlank()) return Optional.empty();
1396+
return Optional.of(MiniMessage.miniMessage().deserialize(
1397+
message
1398+
.replace("<unpaid>", String.valueOf(unpaid)),
1399+
Formatter.choice("unpaid-choice", unpaid)
1400+
));
1401+
}
1402+
13821403
// messages.update-available
13831404
public @NotNull Component messagesUpdateAvailable(final @NotNull String version) {
13841405
return MiniMessage.miniMessage().deserialize(

src/main/java/pro/cloudnode/smp/bankaccounts/Invoice.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,19 @@ public void update() {
234234
return new @NotNull Invoice[0];
235235
}
236236
}
237+
238+
public static int countUnpaid(final @NotNull OfflinePlayer player) {
239+
try (final @NotNull Connection conn = BankAccounts.getInstance().getDb().getConnection();
240+
final @NotNull PreparedStatement stmt = conn.prepareStatement("SELECT COUNT(`id`) as `count` FROM `bank_invoices` WHERE `buyer` = ? AND `transaction` IS NULL")) {
241+
stmt.setString(1, player.getUniqueId().toString());
242+
243+
final @NotNull ResultSet rs = stmt.executeQuery();
244+
if (rs.next()) return rs.getInt("count");
245+
return 0;
246+
}
247+
catch (final @NotNull SQLException e) {
248+
BankAccounts.getInstance().getLogger().log(Level.SEVERE, "Could not count unpaid invoices for player: " + player.getUniqueId(), e);
249+
return 0;
250+
}
251+
}
237252
}

src/main/java/pro/cloudnode/smp/bankaccounts/Permissions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public final class Permissions {
2121
public static final @NotNull String INVOICE_CREATE_OTHER = "bank.invoice.create.other";
2222
public static final @NotNull String INVOICE_VIEW = "bank.invoice.view";
2323
public static final @NotNull String INVOICE_VIEW_OTHER = "bank.invoice.view.other";
24+
public static final @NotNull String INVOICE_NOTIFY = "bank.invoice.notify";
2425
public static final @NotNull String INVOICE_PAY_OTHER = "bank.invoice.pay.other";
2526
public static final @NotNull String INVOICE_PAY_ACCOUNT_OTHER = "bank.invoice.pay.account-other";
2627
public static final @NotNull String INVOICE_SEND = "bank.invoice.send";

src/main/java/pro/cloudnode/smp/bankaccounts/commands/InvoiceCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ public static boolean create(final @NotNull CommandSender sender, @NotNull Strin
199199
invoice.insert();
200200

201201
final @NotNull Optional<@NotNull Player> onlineRecipient = invoice.buyer().isPresent() ? Optional.ofNullable(invoice.buyer().get().getPlayer()) : Optional.empty();
202-
onlineRecipient.ifPresent(player -> sendMessage(player, BankAccounts.getInstance().config().messagesInvoiceCreated(invoice)));
202+
onlineRecipient.ifPresent(player -> sendMessage(player, BankAccounts.getInstance().config().messagesInvoiceReceived(invoice)));
203203
return sendMessage(sender, BankAccounts.getInstance().config().messagesInvoiceCreated(invoice));
204204
}
205205

src/main/java/pro/cloudnode/smp/bankaccounts/events/Join.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package pro.cloudnode.smp.bankaccounts.events;
22

3+
import net.kyori.adventure.text.Component;
34
import org.bukkit.entity.Player;
45
import org.bukkit.event.EventHandler;
56
import org.bukkit.event.Listener;
67
import org.bukkit.event.player.PlayerJoinEvent;
78
import org.jetbrains.annotations.NotNull;
89
import pro.cloudnode.smp.bankaccounts.Account;
910
import pro.cloudnode.smp.bankaccounts.BankAccounts;
11+
import pro.cloudnode.smp.bankaccounts.Invoice;
1012
import pro.cloudnode.smp.bankaccounts.Permissions;
1113

1214
import java.math.BigDecimal;
@@ -35,5 +37,11 @@ else if (BankAccounts.getInstance().config().integrationsVaultEnabled()) {
3537
player.sendMessage(BankAccounts.getInstance().config().messagesUpdateAvailable(latestVersion))
3638
), 20L);
3739
}
40+
if (player.hasPermission(Permissions.INVOICE_NOTIFY) && BankAccounts.getInstance().config().invoiceNotifyJoin() && Invoice.countUnpaid(player) > 0) {
41+
BankAccounts.getInstance().getServer().getScheduler().runTaskLater(BankAccounts.getInstance(), () -> {
42+
final @NotNull Optional<@NotNull Component> message = BankAccounts.getInstance().config().messagesInvoiceNotify(Invoice.countUnpaid(player));
43+
message.ifPresent(player::sendMessage);
44+
}, 20L);
45+
}
3846
}
3947
}

src/main/resources/config.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,15 @@ invoice:
266266
# Number of invoices to return per page
267267
per-page: 10
268268

269+
# Notifications for unpaid invoices (see messages.invoice.notify)
270+
notify:
271+
# Send message when a player joins
272+
join: true
273+
# Periodically send message while player is online
274+
# Interval between messages in seconds
275+
# Set to 0 or negative to disable
276+
interval: 300
277+
269278
# Advanced: do not edit unless you have good understanding of RegEx
270279
# Regular expression for disallowed characters user-provided text inputs
271280
# e.g. account name, transaction description, POS description, invoice description
@@ -602,6 +611,14 @@ messages:
602611
# Same placeholders as details
603612
footer: "<hover:show_text:'Click to see the previous page'><click:run_command:<cmd-prev>><green>← Previous</green></click></hover> <gray>Page <page></gray> <hover:show_text:'Click to see the next page'><click:run_command:<cmd-next>><green>Next →</green></click></hover>"
604613

614+
# You have unpaid invoices
615+
# Sent periodically and on login (as configured in invoice.notify)
616+
# Set to empty string to disable
617+
# Placeholders:
618+
# <unpaid> - number of unpaid invoices></yellow>."
619+
# <unpaid-choice> - choice placeholder for unpaid invoices; see https://docs.advntr.dev/minimessage/dynamic-replacements.html#insert-a-choice
620+
notify: "<click:run_command:/invoice list><hover:show_text:'Click to view unpaid invoices'><yellow>(!) You have <gray><unpaid></gray> unpaid invoice<unpaid-choice:'1#|1<s'>. <gray>Click to view.</gray></yellow></hover></click>"
621+
605622
# New version available
606623
# Placeholders:
607624
# <version> - New version

0 commit comments

Comments
 (0)