Skip to content
Merged
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
17 changes: 17 additions & 0 deletions .github/ci-config.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Placeholder config used only by CI (see .github/workflows/ci.yml).
# The real config-local.properties is gitignored and never committed.
# These values are dummies so the Maven build's copy-config step has a file to copy.

## Discord Settings
discord.apiToken=ci-placeholder
discord.guildID=0
discord.channelID=0

## Steam Settings
steam.api=ci-placeholder

## Leetify API
leetify.apiToken=ci-placeholder

## Carthage settings
carthage.url=http://localhost/
60 changes: 60 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: CI

on:
push:
branches: [master]
pull_request:
workflow_dispatch:

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
name: Unit tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
cache: maven

# config-local.properties is gitignored and holds secrets, so it is not in
# the repo. The build's copy-config step only needs the file to exist, so a
# placeholder is enough to compile and run the tests in CI.
- name: Generate placeholder config
run: cp .github/ci-config.properties src/main/resources/config-local.properties

- name: Run tests
run: mvn -B -ntp -P local test

build:
name: Build package
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
cache: maven

- name: Generate placeholder config
run: cp .github/ci-config.properties src/main/resources/config-local.properties

- name: Build shaded jar
run: mvn -B -ntp -P local -DskipTests package

- name: Upload jar
uses: actions/upload-artifact@v4
with:
name: CounterStrikeBot-jar
path: target/CounterStrikeBot-*.jar
if-no-files-found: error
5 changes: 3 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

<groupId>ch.yoinc</groupId>
<artifactId>CounterStrikeBot</artifactId>
<version>3.6</version>
<version>3.7</version>

<name>CounterStrikeBot</name>
<url>https://github.com/yoinc-development/CounterStrikeBot</url>
Expand Down Expand Up @@ -67,7 +67,8 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.12.0</version>
<version>5.23.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.kronos</groupId>
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/ch/yoinc/http/LeetifyConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ public List<LeetifyMatchResponse> getPlayerMatchHistory(String steam64ID, String
return gson.fromJson(response.body(), new TypeToken<List<LeetifyMatchResponse>>() {
}.getType());
}
System.out.println("[CSBot - LeetifyConnection - " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd.MM.yyyy - HH:mm:ss")) + "] getPlayerMatchHistory for " + parameter + " returned status " + response.statusCode() + ", body: " + response.body());
if(response.statusCode() != 404) {
System.out.println("[CSBot - LeetifyConnection - " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd.MM.yyyy - HH:mm:ss")) + "] getPlayerMatchHistory for " + parameter + " returned status " + response.statusCode() + ", body: " + response.body());
}
} catch (IOException | InterruptedException ex) {
System.out.println("[CSBot - LeetifyConnection - " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd.MM.yyyy - HH:mm:ss")) + "] IOException / InterruptedException thrown: " + ex.getMessage());
}
Expand Down
180 changes: 66 additions & 114 deletions src/main/java/ch/yoinc/tasks/LeetifyTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.Locale;

public class LeetifyTask implements ScheduledTask {

Expand All @@ -20,15 +21,13 @@ public class LeetifyTask implements ScheduledTask {

@Override
public void execute(JDA jda, Properties properties) {
dataService = new DataService(properties);
if (dataService == null) {
dataService = new DataService(properties);
}
if (leetifyConnection == null) {
leetifyConnection = new LeetifyConnection(properties);
}
dataService.setBotID(jda.getSelfUser().getId());
leetifyConnection = new LeetifyConnection(properties);

DiscordService discordService = new DiscordService();

String DEFAULT_LEETIFY_URL = "https://leetify.com/app/match-details/%s/overview";
String DEFAULT_MAP_LOGO_URL = "https://raw.githubusercontent.com/MurkyYT/cs2-map-icons/main/images/%s.png";
String DEFAULT_MAP_URL = "https://raw.githubusercontent.com/MurkyYT/cs2-map-icons/main/images/thumbs/%s_1_png.png";

List<InternalUser> internalUsers = dataService.getAllSteamUsers();

Expand All @@ -41,137 +40,83 @@ public void execute(JDA jda, Properties properties) {

for (String matchID : newlyPlayedMatches.keySet()) {
List<LeetifyMatchResponse> matches = newlyPlayedMatches.get(matchID);
EmbedBuilder matchEmbed = new EmbedBuilder();
LeetifyMatchResponse match = matches.getFirst();
boolean hasWon = match.stats.getFirst().rounds_won >= match.stats.getFirst().rounds_lost; //tie is a victory, change my mind
if (matches.size() > 1) {
LeetifyMatchResponse match = matches.getFirst();
String title = "";
Color color = Color.BLUE;
String imageUrl = "";
String thumbnailUrl = "";
String footer = "";

List<String> playerNames = new ArrayList<>();
for (LeetifyMatchResponse playerMatch : matches) {
playerNames.add(playerMatch.stats.getFirst().name);
}
String players = String.join(", ", playerNames);
String description = "";

switch (match.data_source) {
case "faceit":
title = "New Faceit Match";
color = Color.ORANGE;
description = players + " played a new Faceit match together.";
imageUrl = DEFAULT_MAP_URL.replace("%s", match.map_name);
thumbnailUrl = DEFAULT_MAP_LOGO_URL.replace("%s", match.map_name);
footer = "Finished at " + match.finished_at;
break;
case "wingman":
case "matchmaking_wingman":
title = "New Wingman Match";
color = Color.GREEN;
description = players + " played a new Wingman match together.";
imageUrl = DEFAULT_MAP_URL.replace("%s", match.map_name);
thumbnailUrl = DEFAULT_MAP_LOGO_URL.replace("%s", match.map_name);
footer = "Finished at " + match.finished_at;
break;
case "premier":
title = "New Premier Match";
color = Color.YELLOW;
description = players + " played a new Premier match together.";
imageUrl = DEFAULT_MAP_URL.replace("%s", match.map_name);
thumbnailUrl = DEFAULT_MAP_LOGO_URL.replace("%s", match.map_name);
footer = "Finished at " + match.finished_at;
break;
case "matchmaking":
title = "New Competitive Match";
color = Color.RED;
description = players + " played a new Competitive match together.";
imageUrl = DEFAULT_MAP_URL.replace("%s", match.map_name);
thumbnailUrl = DEFAULT_MAP_LOGO_URL.replace("%s", match.map_name);
footer = "Finished at " + match.finished_at;
break;
}

EmbedBuilder updateMessage = discordService.createEmbedBuilder(title, description, imageUrl, footer);
updateMessage
.setTitle(title, DEFAULT_LEETIFY_URL.replace("%s", matchID))
.setColor(color)
.setThumbnail(thumbnailUrl);
matchEmbed = switch (match.data_source) {
case "faceit" -> returnFilledEmbed("New Faceit Match",
Color.ORANGE, players + " played a Faceit match together and " + ((hasWon) ? "**won**." : "**lost**."),
match.map_name, matchID, "Finished at " + match.finished_at);
case "matchmaking_wingman" -> returnFilledEmbed("New Wingman Match",
Color.GREEN, players + " played a Wingman match together and " + ((hasWon) ? "**won**." : "**lost**."),
match.map_name, matchID, "Finished at " + match.finished_at);
case "matchmaking" -> returnFilledEmbed("New Competitive Match",
Color.YELLOW, players + " played a Competitive match together and " + ((hasWon) ? "**won**." : "**lost**."),
match.map_name, matchID, "Finished at " + match.finished_at);
default -> matchEmbed;
};

for (LeetifyMatchResponse playerMatch : matches) {
LeetifyPlayerStatsResponse stats = playerMatch.stats.getFirst();
updateMessage.addField(
matchEmbed.addField(
stats.name,
"Kills: " + stats.total_kills +
"\nDeaths: " + stats.total_deaths +
"\nADR: " + stats.dpr +
"\nRating: " + stats.leetify_rating +
"\nCT Rating: " + stats.ct_leetify_rating +
"\nT Rating: " + stats.t_leetify_rating,
"\nRating: " + formatRating(stats.leetify_rating) +
"\nCT Rating: " + formatRating(stats.ct_leetify_rating) +
"\nT Rating: " + formatRating(stats.t_leetify_rating),
true
);
}
Objects.requireNonNull(jda.getTextChannelById(properties.getProperty("discord.channelID"))).sendMessageEmbeds(updateMessage.build()).queue();
} else {
LeetifyMatchResponse match = matches.getFirst();
String title = "";
Color color = Color.BLUE;
String description = "";
String imageUrl = "";
String thumbnailUrl = "";
String footer = "";

switch (match.data_source) {
case "faceit":
title = "New Faceit Match";
color = Color.ORANGE;
description = match.stats.getFirst().name + " played a new Faceit match.";
imageUrl = DEFAULT_MAP_URL.replace("%s", match.map_name);
thumbnailUrl = DEFAULT_MAP_LOGO_URL.replace("%s", match.map_name);
footer = "Finished at " + match.finished_at;
break;
case "wingman":
case "matchmaking_wingman":
title = "New Wingman Match";
color = Color.GREEN;
description = match.stats.getFirst().name + " played a new Wingman match.";
imageUrl = DEFAULT_MAP_URL.replace("%s", match.map_name);
thumbnailUrl = DEFAULT_MAP_LOGO_URL.replace("%s", match.map_name);
footer = "Finished at " + match.finished_at;
break;
case "premier":
title = "New Premier Match";
color = Color.YELLOW;
description = match.stats.getFirst().name + " played a new Premier match.";
imageUrl = DEFAULT_MAP_URL.replace("%s", match.map_name);
thumbnailUrl = DEFAULT_MAP_LOGO_URL.replace("%s", match.map_name);
footer = "Finished at " + match.finished_at;
break;
case "matchmaking":
title = "New Competitive Match";
color = Color.RED;
description = match.stats.getFirst().name + " played a new Competitive match.";
imageUrl = DEFAULT_MAP_URL.replace("%s", match.map_name);
thumbnailUrl = DEFAULT_MAP_LOGO_URL.replace("%s", match.map_name);
footer = "Finished at " + match.finished_at;
break;
}
EmbedBuilder updateMessage = discordService.createEmbedBuilder(title, description, imageUrl, footer);
updateMessage
.setTitle(title, DEFAULT_LEETIFY_URL.replace("%s", matchID))
.setColor(color)
.setThumbnail(thumbnailUrl)
matchEmbed = switch (match.data_source) {
case "faceit" -> returnFilledEmbed("New Faceit Match", Color.ORANGE,
match.stats.getFirst().name + " played a Faceit match and " + ((hasWon) ? "**won**." : "**lost**."),
match.map_name, matchID, "Finished at " + match.finished_at);
case "matchmaking_wingman" -> returnFilledEmbed("New Wingman Match", Color.GREEN,
match.stats.getFirst().name + " played a Wingman match and " + ((hasWon) ? "**won**." : "**lost**."),
match.map_name, matchID, "Finished at " + match.finished_at);
case "matchmaking" -> returnFilledEmbed("New Competitive Match", Color.YELLOW,
match.stats.getFirst().name + " played a Competitive match and " + ((hasWon) ? "**won**." : "**lost**."),
match.map_name, matchID, "Finished at " + match.finished_at);
default -> matchEmbed;
};
matchEmbed
.addField("Kills", Integer.toString(match.stats.getFirst().total_kills), true)
.addField("Deaths", Integer.toString(match.stats.getFirst().total_deaths), true)
.addField("ADR", Double.toString(match.stats.getFirst().dpr), true)
.addField("Rating", Double.toString(match.stats.getFirst().leetify_rating), true)
.addField("CT Rating", Double.toString(match.stats.getFirst().ct_leetify_rating), true)
.addField("T Rating", Double.toString(match.stats.getFirst().t_leetify_rating), true);
Objects.requireNonNull(jda.getTextChannelById(properties.getProperty("discord.channelID"))).sendMessageEmbeds(updateMessage.build()).queue();
.addField("Rating", formatRating(match.stats.getFirst().leetify_rating), true)
.addField("CT Rating", formatRating(match.stats.getFirst().ct_leetify_rating), true)
.addField("T Rating", formatRating(match.stats.getFirst().t_leetify_rating), true);
}
Objects.requireNonNull(jda.getTextChannelById(properties.getProperty("discord.channelID"))).sendMessageEmbeds(matchEmbed.build()).queue();
}
}

private EmbedBuilder returnFilledEmbed(String title, Color color, String description, String map_name, String matchID, String footer) {
DiscordService discordService = new DiscordService();

String DEFAULT_LEETIFY_URL = "https://leetify.com/app/match-details/%s/overview";
String DEFAULT_MAP_LOGO_URL = "https://raw.githubusercontent.com/MurkyYT/cs2-map-icons/main/images/%s.png";
String DEFAULT_MAP_URL = "https://raw.githubusercontent.com/MurkyYT/cs2-map-icons/main/images/thumbs/%s_1_png.png";

EmbedBuilder returnEmbed = discordService.createEmbedBuilder(title, description, DEFAULT_MAP_URL.replace("%s", map_name), footer);
returnEmbed
.setTitle(title, DEFAULT_LEETIFY_URL.replace("%s", matchID))
.setColor(color)
.setThumbnail(DEFAULT_MAP_LOGO_URL.replace("%s", map_name));

return returnEmbed;
}

private HashMap<String, List<LeetifyMatchResponse>> setNewlyPlayedMatches(List<InternalUser> steamInternalUsers) {
HashMap<String, List<LeetifyMatchResponse>> results = new HashMap<>();

Expand Down Expand Up @@ -204,4 +149,11 @@ private HashMap<String, List<LeetifyMatchResponse>> setNewlyPlayedMatches(List<I
public String getTaskName() {
return "LeetifyTask";
}

private static String formatRating(Double rating) {
if (rating == null) {
return "n/a";
}
return String.format(Locale.US, "%.2f", rating * 100.0);
}
}
2 changes: 1 addition & 1 deletion src/main/java/ch/yoinc/tasks/TaskScheduler.java
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,6 @@ public void run() {
}
};

timer.schedule(timerTask, initialDelay, interval);
timer.scheduleAtFixedRate(timerTask, initialDelay, interval);
}
}
Loading
Loading