Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ When the shop and/or vote plugins are installed on your Azuriom website, the int
* `%azlink_vote_sites_[id]_url%`: URL of vote site with given ID
* `%azlink_vote_top_[position]_name%`: name of player at given position in vote ranking
* `%azlink_vote_top_[position]_votes%`: vote count of player at given position in ranking
* `%azlink_vote_goal_progress%`: number of votes currently counted toward the monthly vote goal
* `%azlink_vote_goal_target%`: total number of votes required to reach the monthly vote goal

### Shop Placeholders
* `%azlink_shop_goal_progress%`: current progress of the shop goal this month
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public class VotePlaceholderProvider implements PlaceholderProvider, Runnable, L
private final Map<Integer, VoteSite> voteSites = new HashMap<>();
private final Map<String, VoteUser> users = new HashMap<>();
private final List<TopVoteUser> topVotes = new ArrayList<>();
private volatile VoteGoal goal;

private volatile boolean pendingRefresh = true;
private volatile Instant lastUpdate = Instant.MIN;
Expand Down Expand Up @@ -64,7 +65,9 @@ public List<String> availablePlaceholders() {
"%azlink_vote_sites_[id]_name%",
"%azlink_vote_sites_[id]_url%",
"%azlink_vote_top_[position]_name%",
"%azlink_vote_top_[position]_votes%"
"%azlink_vote_top_[position]_votes%",
"%azlink_vote_goal_target%",
"%azlink_vote_goal_progress%"
);
}

Expand Down Expand Up @@ -94,6 +97,8 @@ public String evaluatePlaceholder(String[] parts, OfflinePlayer player) {
return topPlaceholder(parts);
case "sites":
return sitePlaceholder(parts);
case "goal":
return goalPlaceholder(parts);
default:
return null;
}
Expand Down Expand Up @@ -134,6 +139,23 @@ private String userCanPlaceholder(String[] parts, OfflinePlayer player) throws N
return null;
}

private String goalPlaceholder(String[] parts) throws NumberFormatException {
VoteGoal currentGoal = this.goal;

if (currentGoal == null) {
return "0";
}

switch (parts[1]) {
case "target":
return Integer.toString(currentGoal.target);
case "progress":
return Integer.toString(currentGoal.progress);
Comment on lines +145 to +153
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

goalPlaceholder returns "0" whenever goal is null, even if the requested sub-key is invalid (e.g., %azlink_vote_goal_typo% would yield 0 instead of returning null). This makes invalid placeholders harder to detect and is inconsistent with other placeholder handlers. Consider switching on parts[1] first and only returning "0" for the known keys (target/progress) when goal is missing, while still returning null for unknown keys.

Suggested change
if (currentGoal == null) {
return "0";
}
switch (parts[1]) {
case "target":
return Integer.toString(currentGoal.target);
case "progress":
return Integer.toString(currentGoal.progress);
String key = parts.length > 1 ? parts[1] : "";
switch (key) {
case "target":
return currentGoal != null ? Integer.toString(currentGoal.target) : "0";
case "progress":
return currentGoal != null ? Integer.toString(currentGoal.progress) : "0";

Copilot uses AI. Check for mistakes.
default:
return null;
}
}

private String sitePlaceholder(String[] parts) throws NumberFormatException {
if (parts[1].equals("count")) {
return Integer.toString(voteSites.size());
Expand Down Expand Up @@ -229,6 +251,7 @@ private void refreshData() {
this.voteSites.clear();
this.users.clear();
this.topVotes.clear();
this.goal = response.goal;

for (VoteSite site : response.sites) {
this.voteSites.put(site.id, site);
Expand Down Expand Up @@ -260,6 +283,12 @@ public static class VoteResponse {
public List<VoteUser> users = new ArrayList<>();
@SerializedName("top_votes")
public List<TopVoteUser> topVotes = new ArrayList<>();
public VoteGoal goal;
}

public static class VoteGoal {
public int target;
public int progress;
}

public static class VoteUser {
Expand Down
Loading