Skip to content

Temporarily fix Twitch4J Oauth timeout #94

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 11, 2025
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
30 changes: 24 additions & 6 deletions bot/main/talium/TwitchBot.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import jakarta.annotation.PreDestroy;
import jakarta.persistence.PreRemove;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.ConfigurableApplicationContext;
import talium.tipeeeStream.DonationRepo;
import talium.tipeeeStream.TipeeeConfig;
Expand All @@ -22,6 +23,11 @@
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import talium.twitchCommands.triggerEngine.TriggerProvider;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

@SpringBootApplication
@EnableJpaRepositories
public class TwitchBot {
Expand All @@ -33,6 +39,13 @@ public static void main(String[] args) {
startup();
}

private static final ScheduledExecutorService TWITCH4J_PERIODIC_RESTART_EXECUTOR;

static {
ThreadFactory namedThreadFactory = new BasicThreadFactory.Builder().namingPattern("TWITCH4J_PERIODIC_RESTART_EXECUTOR").build();
TWITCH4J_PERIODIC_RESTART_EXECUTOR = Executors.newSingleThreadScheduledExecutor(namedThreadFactory);
}

private static ConfigurableApplicationContext ctx;
private static BotInput twitch;
private static BotInput tipeee;
Expand Down Expand Up @@ -66,6 +79,11 @@ public static void startup() {
//TODO remove all templates that were once registered automatically, but are no longer

time.close();

TWITCH4J_PERIODIC_RESTART_EXECUTOR.scheduleAtFixedRate(() -> {
logger.info("Starting periodic Twitch reconnect");
reconnectTwitch();
}, 120, 120, TimeUnit.MINUTES);
}

@PreDestroy
Expand Down Expand Up @@ -98,17 +116,17 @@ private static void stopInput(BotInput input) {
}

public static boolean reconnectTwitch() {
twitch.shutdown();
var twitch = new Twitch4JInput(
ctx.getBean(TwitchConfig.class),
ctx.getBean(OauthAccountRepo.class)
);
try {
twitch.shutdown();
var twitch = new Twitch4JInput(
ctx.getBean(TwitchConfig.class),
ctx.getBean(OauthAccountRepo.class)
);
twitch.startup();
TwitchBot.twitch = twitch;
return true;
} catch (Exception e) {
TwitchBot.twitch = twitch;
logger.error("Exception reconnecting twitch: {}", e.getMessage());
return false;
}
}
Expand Down
54 changes: 40 additions & 14 deletions bot/main/talium/twitch4J/Twitch4JInput.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@
import com.github.twitch4j.chat.events.channel.ChannelMessageEvent;
import com.github.twitch4j.helix.TwitchHelix;
import org.apache.commons.lang.RandomStringUtils;
import talium.Registrar;
import talium.oauthConnector.OAuthEndpoint;
import talium.oauthConnector.OauthAccount;
import talium.oauthConnector.OauthAccountRepo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import talium.Out;
import talium.Registrar;
import talium.eventSystem.EventDispatcher;
import talium.eventSystem.Subscriber;
import talium.inputSystem.BotInput;
import talium.inputSystem.HealthManager;
import talium.inputSystem.InputStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import talium.oauthConnector.OAuthEndpoint;
import talium.oauthConnector.OauthAccount;
import talium.oauthConnector.OauthAccountRepo;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
Expand Down Expand Up @@ -74,19 +74,45 @@ public void startup() {
logger.warn(STR."Head to \{OAuthEndpoint.getOauthSetupUrl()} to Setup a new Oauth connection");
HealthManager.reportStatus(Twitch4JInput.class, InputStatus.INJURED);
creds = createNewOauth();
//check if still empty after oauth
if (creds.isEmpty()) {
logger.error("Could neither load old credentials, nor create new once, aborting input startup!");
HealthManager.reportStatus(Twitch4JInput.class, InputStatus.DEAD);
return;
} else {
logger.warn("Created new Oauth. Warning resolved!");
HealthManager.reportStatus(Twitch4JInput.class, InputStatus.STARTING);
}
}
//check if still empty after oauth
if (creds.isEmpty()) {
logger.error("Could neither load old credentials, nor create new once, aborting input startup!");
oAuth2Credential = creds.get();

Optional<Boolean> credentialValid = iProvider.isCredentialValid(oAuth2Credential);
if (credentialValid.isEmpty()) {
logger.error("Failed to check if credential is valid");
HealthManager.reportStatus(Twitch4JInput.class, InputStatus.DEAD);
return;
}
if (!credentialValid.get()) {
logger.warn("Oauth credential is not valid");
Optional<OAuth2Credential> newCredential = iProvider.refreshCredential(oAuth2Credential);
if (newCredential.isEmpty()) {
logger.error("Failed to refresh credential for unknown reason");
HealthManager.reportStatus(Twitch4JInput.class, InputStatus.DEAD);
return;
}
oAuth2Credential = newCredential.get();
}
if (iProvider.getAdditionalCredentialInformation(oAuth2Credential).isEmpty()) {
logger.warn("Oauth additional credentials could not be found: {}", oAuth2Credential);
HealthManager.reportStatus(Twitch4JInput.class, InputStatus.DEAD);
return;
} else {
logger.warn("Created new Oauth. Warning resolved!");
HealthManager.reportStatus(Twitch4JInput.class, InputStatus.STARTING);
}
oAuth2Credential = creds.get();

logger.info("Using Valid Credential: {}", oAuth2Credential);
TwitchClient twitchClient = TwitchClientBuilder.builder()
.withClientId(config.app_clientID())
.withClientSecret(config.app_clientSecret())
.withRedirectUrl(OAuthEndpoint.getRedirectUrl("twitch"))
.withEnableHelix(true)
.withEnableChat(true)
.withDefaultAuthToken(oAuth2Credential)
Expand Down Expand Up @@ -173,7 +199,7 @@ public static void convertTwitchMessage(ChannelMessageEvent messageEvent) {
try {
EventDispatcher.dispatch(ChatMessage.fromChannelMessageEvent(messageEvent));
} catch (ChatMessage.ChatMessageMalformedExceptions e) {
logger.error("Error converting Twitch message", e);
logger.error("Error converting Twitch message", e);
}
}
}
5 changes: 2 additions & 3 deletions bot/resources/logback.xml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,8 @@
</appender>

<logger name="logback" level="INFO"/>
<logger name="talium.inputs" level="WARN"/>
<logger name="talium.system" level="INFO"/>
<logger name="talium.coinsWatchtime" level="WARN"/>
<logger name="talium.twitch4J" level="INFO"/>
<logger name="talium.coinsWatchtime" level="INFO"/>
<logger name="talium.ASCIIProgressbar" level="INFO"/>

<logger name="talium.TwitchBot" level="INFO" additivity="false">
Expand Down
2 changes: 1 addition & 1 deletion wiki
Submodule wiki updated from cc4b90 to 1c694c