Skip to content

Commit 694d8a1

Browse files
authored
Merge branch 'develop' into fix/replace-dead-links-in-chatgpt-response
2 parents 7802e81 + 08b2646 commit 694d8a1

75 files changed

Lines changed: 3179 additions & 295 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitattributes

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
# This will do normalization to LF on index (staging area)
2-
* text=auto
1+
# Normalize to LF in the index AND in the working tree on all platforms.
2+
# Spotless enforces LF, so without eol=lf, Windows/WSL checkouts get CRLF and
3+
# every spotlessApply rewrites every file.
4+
* text=auto eol=lf
35

46
# Explicit for linux files
57
*.sh text eol=lf

application/build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ dependencies {
4848

4949
implementation 'net.dv8tion:JDA:5.6.1'
5050

51-
implementation 'org.apache.logging.log4j:log4j-core:2.25.0'
52-
runtimeOnly 'org.apache.logging.log4j:log4j-slf4j2-impl:2.25.0'
51+
implementation 'org.apache.logging.log4j:log4j-core:2.26.0'
52+
runtimeOnly 'org.apache.logging.log4j:log4j-slf4j2-impl:2.26.0'
5353

5454
implementation 'club.minnced:discord-webhooks:0.8.4'
5555

@@ -69,7 +69,7 @@ dependencies {
6969
implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion"
7070
implementation "com.sigpwned:jackson-modules-java17-sealed-classes:2.19.0.0"
7171

72-
implementation 'com.github.freva:ascii-table:1.9.0'
72+
implementation 'com.github.freva:ascii-table:1.12.1'
7373

7474
implementation 'io.github.url-detector:url-detector:0.1.23'
7575

application/config.json.template

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@
162162
"logInfoChannelWebhook": "<put_your_webhook_here>",
163163
"logErrorChannelWebhook": "<put_your_webhook_here>",
164164
"openaiApiKey": "<check pins in #tjbot_discussion for the key>",
165+
"tavilyApiKey": "<create an account on https://www.tavily.com/ to get an API key for free>",
165166
"sourceCodeBaseUrl": "https://github.com/Together-Java/TJ-Bot/blob/master/application/src/main/java/",
166167
"jshell": {
167168
"baseUrl": "<put_jshell_rest_api_url_here>",
@@ -195,9 +196,45 @@
195196
"pollIntervalInMinutes": 10
196197
},
197198
"quoteBoardConfig": {
198-
"minimumReactionsToTrigger": 5,
199+
"minimumScoreToTrigger": 5.0,
199200
"channel": "quotes",
200-
"reactionEmoji": "⭐"
201+
"botEmoji": "⭐",
202+
"defaultEmojiScore": 0.5,
203+
"emojiScores": {
204+
"😬": -0.5,
205+
"💔": -0.5,
206+
"😐": -0.5,
207+
"😊": -0.5,
208+
"🖕": -0.5,
209+
"👎": -0.5,
210+
"💩": -0.5,
211+
"🤢": -0.5,
212+
"🤮": -0.5,
213+
"🤬": -0.5,
214+
"😡": -0.5,
215+
"😒": -0.5,
216+
"🤨": -0.5,
217+
218+
"🇷🇺": 0.0,
219+
"🇵🇸": 0.0,
220+
"🇮🇱": 0.0,
221+
"🏳️‍🌈": 0.0,
222+
223+
"⭐": 1.0,
224+
225+
"youtube:1464573182206804010": 0.0
226+
},
227+
"allowChannels": [
228+
"chit-chat",
229+
"career-talk",
230+
"geek-speek",
231+
"expert-java-talk",
232+
"ai-talk"
233+
]
234+
},
235+
"roleApplicationSystem": {
236+
"submissionsChannelPattern": "staff-applications",
237+
"defaultQuestion": "What makes you a good addition to the team?"
201238
},
202239
"memberCountCategoryPattern": "Info",
203240
"topHelpers": {

application/src/main/java/org/togetherjava/tjbot/config/Config.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@ public final class Config {
4848
private final RSSFeedsConfig rssFeedsConfig;
4949
private final String selectRolesChannelPattern;
5050
private final String memberCountCategoryPattern;
51+
private final RoleApplicationSystemConfig roleApplicationSystemConfig;
5152
private final QuoteBoardConfig quoteBoardConfig;
5253
private final TopHelpersConfig topHelpers;
5354
private final DynamicVoiceChatConfig dynamicVoiceChatConfig;
55+
private final String tavilyApiKey;
5456

5557
@SuppressWarnings("ConstructorWithTooManyParameters")
5658
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
@@ -106,9 +108,12 @@ private Config(@JsonProperty(value = "token", required = true) String token,
106108
required = true) String selectRolesChannelPattern,
107109
@JsonProperty(value = "quoteBoardConfig",
108110
required = true) QuoteBoardConfig quoteBoardConfig,
111+
@JsonProperty(value = "roleApplicationSystem",
112+
required = true) RoleApplicationSystemConfig roleApplicationSystemConfig,
109113
@JsonProperty(value = "topHelpers", required = true) TopHelpersConfig topHelpers,
110114
@JsonProperty(value = "dynamicVoiceChatConfig",
111-
required = true) DynamicVoiceChatConfig dynamicVoiceChatConfig) {
115+
required = true) DynamicVoiceChatConfig dynamicVoiceChatConfig,
116+
@JsonProperty(value = "tavilyApiKey", required = true) String tavilyApiKey) {
112117
this.token = Objects.requireNonNull(token);
113118
this.githubApiKey = Objects.requireNonNull(githubApiKey);
114119
this.databasePath = Objects.requireNonNull(databasePath);
@@ -144,8 +149,10 @@ private Config(@JsonProperty(value = "token", required = true) String token,
144149
this.rssFeedsConfig = Objects.requireNonNull(rssFeedsConfig);
145150
this.selectRolesChannelPattern = Objects.requireNonNull(selectRolesChannelPattern);
146151
this.quoteBoardConfig = Objects.requireNonNull(quoteBoardConfig);
152+
this.roleApplicationSystemConfig = roleApplicationSystemConfig;
147153
this.topHelpers = Objects.requireNonNull(topHelpers);
148154
this.dynamicVoiceChatConfig = Objects.requireNonNull(dynamicVoiceChatConfig);
155+
this.tavilyApiKey = Objects.requireNonNull(tavilyApiKey);
149156
}
150157

151158
/**
@@ -460,6 +467,15 @@ public String getMemberCountCategoryPattern() {
460467
return memberCountCategoryPattern;
461468
}
462469

470+
/**
471+
* The configuration related to the application form.
472+
*
473+
* @return the application form config
474+
*/
475+
public RoleApplicationSystemConfig getRoleApplicationSystemConfig() {
476+
return roleApplicationSystemConfig;
477+
}
478+
463479
/**
464480
* Gets the RSS feeds configuration.
465481
*
@@ -486,4 +502,16 @@ public TopHelpersConfig getTopHelpers() {
486502
public DynamicVoiceChatConfig getDynamicVoiceChatConfig() {
487503
return dynamicVoiceChatConfig;
488504
}
505+
506+
/**
507+
* Gets the API key for Tavily ({@link <a href="https://www.tavily.com">tavily.com</a>}), a
508+
* search engine API tailored for LLMs. It is used by the ChatGPT command to power the AI-driven
509+
* web search tool, allowing the assistant to fetch up-to-date information from the web when
510+
* answering user questions.
511+
*
512+
* @return the Tavily API key
513+
*/
514+
public String getTavilyApiKey() {
515+
return tavilyApiKey;
516+
}
489517
}

application/src/main/java/org/togetherjava/tjbot/config/QuoteBoardConfig.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,46 @@
66

77
import org.togetherjava.tjbot.features.basic.QuoteBoardForwarder;
88

9+
import java.util.List;
10+
import java.util.Map;
911
import java.util.Objects;
1012

1113
/**
1214
* Configuration for the quote board feature, see {@link QuoteBoardForwarder}.
1315
*/
1416
@JsonRootName("quoteBoardConfig")
1517
public record QuoteBoardConfig(
16-
@JsonProperty(value = "minimumReactionsToTrigger", required = true) int minimumReactions,
17-
@JsonProperty(required = true) String channel,
18-
@JsonProperty(value = "reactionEmoji", required = true) String reactionEmoji) {
18+
@JsonProperty(value = "minimumScoreToTrigger", required = true) float minimumScoreToTrigger,
19+
@JsonProperty(value = "channel", required = true) String channel,
20+
@JsonProperty(value = "botEmoji", required = true) String botEmoji,
21+
@JsonProperty(value = "defaultEmojiScore", required = true) float defaultEmojiScore,
22+
@JsonProperty(value = "emojiScores", required = true) Map<String, Float> emojiScores,
23+
@JsonProperty(value = "allowChannels", required = true) List<String> allowChannels) {
1924

2025
/**
2126
* Creates a QuoteBoardConfig.
2227
*
23-
* @param minimumReactions the minimum amount of reactions
28+
* @param minimumScoreToTrigger the minimum amount of reaction score for a message to be quoted
2429
* @param channel the pattern for the board channel
25-
* @param reactionEmoji the emoji with which users should react to
30+
* @param botEmoji the emoji with which the bot will mark quoted messages
31+
* @param defaultEmojiScore the default score of an emoji if it's not in the emojiScores map
32+
* @param emojiScores a map of each emoji's custom score
2633
*/
2734
public QuoteBoardConfig {
28-
if (minimumReactions <= 0) {
29-
throw new IllegalArgumentException("minimumReactions must be greater than zero");
35+
if (minimumScoreToTrigger <= 0) {
36+
throw new IllegalArgumentException("minimumScoreToTrigger must be greater than zero");
3037
}
3138
Objects.requireNonNull(channel);
3239
if (channel.isBlank()) {
3340
throw new IllegalArgumentException("channel must not be empty or blank");
3441
}
35-
Objects.requireNonNull(reactionEmoji);
36-
if (reactionEmoji.isBlank()) {
42+
Objects.requireNonNull(botEmoji);
43+
if (botEmoji.isBlank()) {
3744
throw new IllegalArgumentException("reactionEmoji must not be empty or blank");
3845
}
46+
Objects.requireNonNull(emojiScores);
3947
LogManager.getLogger(QuoteBoardConfig.class)
4048
.debug("Quote-Board configs loaded: minimumReactions={}, channel='{}', reactionEmoji='{}'",
41-
minimumReactions, channel, reactionEmoji);
49+
minimumScoreToTrigger, channel, botEmoji);
4250
}
4351
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.togetherjava.tjbot.config;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import net.dv8tion.jda.api.interactions.components.text.TextInput;
5+
6+
import java.util.Objects;
7+
8+
/**
9+
* Represents the configuration for an application form, including roles and application channel
10+
* pattern.
11+
*
12+
* @param submissionsChannelPattern the pattern used to identify the submissions channel where
13+
* applications are sent
14+
* @param defaultQuestion the default question that will be asked in the role application form
15+
*/
16+
public record RoleApplicationSystemConfig(
17+
@JsonProperty(value = "submissionsChannelPattern",
18+
required = true) String submissionsChannelPattern,
19+
@JsonProperty(value = "defaultQuestion", required = true) String defaultQuestion) {
20+
21+
/**
22+
* Constructs an instance of {@link RoleApplicationSystemConfig} with the provided parameters.
23+
* <p>
24+
* This constructor ensures that {@code submissionsChannelPattern} and {@code defaultQuestion}
25+
* are not null and that the length of the {@code defaultQuestion} does not exceed the maximum
26+
* allowed length.
27+
*/
28+
public RoleApplicationSystemConfig {
29+
Objects.requireNonNull(submissionsChannelPattern);
30+
Objects.requireNonNull(defaultQuestion);
31+
32+
if (defaultQuestion.length() > TextInput.MAX_LABEL_LENGTH) {
33+
throw new IllegalArgumentException(
34+
"defaultQuestion length is too long! Cannot be greater than %d"
35+
.formatted(TextInput.MAX_LABEL_LENGTH));
36+
}
37+
}
38+
}

application/src/main/java/org/togetherjava/tjbot/features/Features.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import org.togetherjava.tjbot.features.bookmarks.LeftoverBookmarksListener;
2020
import org.togetherjava.tjbot.features.chatgpt.ChatGptCommand;
2121
import org.togetherjava.tjbot.features.chatgpt.ChatGptService;
22+
import org.togetherjava.tjbot.features.chatgpt.tools.web.FetchUrlTool;
23+
import org.togetherjava.tjbot.features.chatgpt.tools.web.WebSearchTool;
2224
import org.togetherjava.tjbot.features.code.CodeMessageAutoDetection;
2325
import org.togetherjava.tjbot.features.code.CodeMessageHandler;
2426
import org.togetherjava.tjbot.features.code.CodeMessageManualDetection;
@@ -51,6 +53,7 @@
5153
import org.togetherjava.tjbot.features.moderation.QuarantineCommand;
5254
import org.togetherjava.tjbot.features.moderation.RejoinModerationRoleListener;
5355
import org.togetherjava.tjbot.features.moderation.ReportCommand;
56+
import org.togetherjava.tjbot.features.moderation.ThisIsScamCommand;
5457
import org.togetherjava.tjbot.features.moderation.TransferQuestionCommand;
5558
import org.togetherjava.tjbot.features.moderation.UnbanCommand;
5659
import org.togetherjava.tjbot.features.moderation.UnmuteCommand;
@@ -67,8 +70,11 @@
6770
import org.togetherjava.tjbot.features.moderation.scam.ScamHistoryStore;
6871
import org.togetherjava.tjbot.features.moderation.temp.TemporaryModerationRoutine;
6972
import org.togetherjava.tjbot.features.projects.ProjectsThreadCreatedListener;
73+
import org.togetherjava.tjbot.features.purge.PurgeCommand;
74+
import org.togetherjava.tjbot.features.purge.PurgeMessagesByUserCommand;
7075
import org.togetherjava.tjbot.features.reminder.RemindRoutine;
7176
import org.togetherjava.tjbot.features.reminder.ReminderCommand;
77+
import org.togetherjava.tjbot.features.roleapplication.CreateRoleApplicationCommand;
7278
import org.togetherjava.tjbot.features.rss.RSSHandlerRoutine;
7379
import org.togetherjava.tjbot.features.system.BotCore;
7480
import org.togetherjava.tjbot.features.system.LogLevelCommand;
@@ -85,6 +91,7 @@
8591

8692
import java.util.ArrayList;
8793
import java.util.Collection;
94+
import java.util.List;
8895

8996
/**
9097
* Utility class that offers all features that should be registered by the system, such as commands.
@@ -185,6 +192,7 @@ public static Collection<Feature> createFeatures(JDA jda, Database database, Con
185192

186193
// Message context commands
187194
features.add(new TransferQuestionCommand(config, chatGptService));
195+
features.add(new ThisIsScamCommand(config, actionsStore));
188196

189197
// User context commands
190198

@@ -215,10 +223,16 @@ public static Collection<Feature> createFeatures(JDA jda, Database database, Con
215223
features.add(new HelpThreadCommand(config, helpSystemHelper, metrics));
216224
features.add(new ReportCommand(config));
217225
features.add(new BookmarksCommand(bookmarksSystem));
218-
features.add(new ChatGptCommand(chatGptService, helpSystemHelper));
226+
227+
features.add(new ChatGptCommand(chatGptService, helpSystemHelper,
228+
List.of(new WebSearchTool(config.getTavilyApiKey()), new FetchUrlTool())));
229+
219230
features.add(new JShellCommand(jshellEval));
220231
features.add(new MessageCommand());
221232
features.add(new RewriteCommand(chatGptService));
233+
features.add(new CreateRoleApplicationCommand(config));
234+
features.add(new PurgeCommand(modAuditLogWriter));
235+
features.add(new PurgeMessagesByUserCommand(modAuditLogWriter));
222236

223237
FeatureBlacklist<Class<?>> blacklist = blacklistConfig.normal();
224238
return blacklist.filterStream(features.stream(), Object::getClass).toList();

0 commit comments

Comments
 (0)