mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-15 13:53:19 -05:00
Add option to check if users leave or join Twitch chat
This commit is contained in:
@@ -713,6 +713,8 @@ AdvSceneSwitcher.condition.twitch.type.chat.properties.color="Color matches"
|
||||
AdvSceneSwitcher.condition.twitch.type.chat.properties.displayName="Display name matches"
|
||||
AdvSceneSwitcher.condition.twitch.type.chat.properties.loginName="User name matches"
|
||||
AdvSceneSwitcher.condition.twitch.type.chat.properties.badge="User has badge"
|
||||
AdvSceneSwitcher.condition.twitch.type.chat.userJoined="User joined the chat"
|
||||
AdvSceneSwitcher.condition.twitch.type.chat.userLeft="User left the chat"
|
||||
AdvSceneSwitcher.condition.twitch.categorySelectionDisabled="Cannot select category without selecting a Twitch account first!"
|
||||
AdvSceneSwitcher.condition.twitch.entry="Channel{{channel}}{{conditions}}{{pointsReward}}{{streamTitle}}{{regex}}{{category}}"
|
||||
AdvSceneSwitcher.condition.twitch.entry.account="Check using account{{account}}"
|
||||
@@ -1765,6 +1767,12 @@ AdvSceneSwitcher.tempVar.twitch.is_turbo.chatReceive.description="'true' if the
|
||||
AdvSceneSwitcher.tempVar.twitch.is_vip.chatReceive="Is chatter a VIP"
|
||||
AdvSceneSwitcher.tempVar.twitch.is_vip.chatReceive.description="'true' if the chatter is a VIP in the channel, 'false' otherwise."
|
||||
|
||||
AdvSceneSwitcher.tempVar.twitch.user_login.chatJoin="User login"
|
||||
AdvSceneSwitcher.tempVar.twitch.user_login.chatJoin.description="The user login of the person who joined the chat room."
|
||||
|
||||
AdvSceneSwitcher.tempVar.twitch.user_login.chatLeave="User login"
|
||||
AdvSceneSwitcher.tempVar.twitch.user_login.chatLeave.description="The user login of the person who left the chat room."
|
||||
|
||||
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid="Raid creator user ID"
|
||||
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_id.raid.description="The broadcaster ID that created the raid."
|
||||
AdvSceneSwitcher.tempVar.twitch.from_broadcaster_user_login.raid="Raid creator user login"
|
||||
|
||||
@@ -181,8 +181,6 @@ static void parseCommand(const std::string &rawCommandComponent,
|
||||
return;
|
||||
} else if (message.command.command == "PING" ||
|
||||
message.command.command == "001" ||
|
||||
message.command.command == "JOIN" ||
|
||||
message.command.command == "PART" ||
|
||||
message.command.command == "NOTICE" ||
|
||||
message.command.command == "CLEARCHAT" ||
|
||||
message.command.command == "HOSTTARGET" ||
|
||||
@@ -191,6 +189,18 @@ static void parseCommand(const std::string &rawCommandComponent,
|
||||
return;
|
||||
}
|
||||
message.command.parameters = commandParts[1];
|
||||
} else if (message.command.command == "JOIN") {
|
||||
if (commandParts.size() < 2) {
|
||||
return;
|
||||
}
|
||||
message.properties.joinedChannel = true;
|
||||
message.command.parameters = commandParts[1];
|
||||
} else if (message.command.command == "PART") {
|
||||
if (commandParts.size() < 2) {
|
||||
return;
|
||||
}
|
||||
message.properties.leftChannel = true;
|
||||
message.command.parameters = commandParts[1];
|
||||
} else if (message.command.command == "GLOBALUSERSTATE" ||
|
||||
message.command.command == "USERSTATE" ||
|
||||
message.command.command == "ROOMSTATE" ||
|
||||
@@ -504,12 +514,34 @@ void TwitchChatConnection::JoinChannel(const std::string &channelName)
|
||||
Send("JOIN #" + channelName);
|
||||
}
|
||||
|
||||
static bool nickMatchesTokenUser(const std::string &nick, TwitchToken &token)
|
||||
{
|
||||
auto tokenUserName = token.GetName();
|
||||
std::transform(tokenUserName.begin(), tokenUserName.end(),
|
||||
tokenUserName.begin(),
|
||||
[](unsigned char c) { return std::tolower(c); });
|
||||
return nick == tokenUserName;
|
||||
}
|
||||
|
||||
void TwitchChatConnection::HandleJoin(const IRCMessage &message)
|
||||
{
|
||||
if (!nickMatchesTokenUser(message.source.nick, _token)) {
|
||||
_messageDispatcher.DispatchMessage(message);
|
||||
return;
|
||||
}
|
||||
_joinedChannelName = std::get<std::string>(message.command.parameters);
|
||||
vblog(LOG_INFO, "Twitch chat join was successful!");
|
||||
}
|
||||
|
||||
void TwitchChatConnection::HandlePart(const IRCMessage &message)
|
||||
{
|
||||
if (!nickMatchesTokenUser(message.source.nick, _token)) {
|
||||
_messageDispatcher.DispatchMessage(message);
|
||||
return;
|
||||
}
|
||||
vblog(LOG_INFO, "Left Twitch chat!");
|
||||
}
|
||||
|
||||
void TwitchChatConnection::HandleNewMessage(const IRCMessage &message)
|
||||
{
|
||||
_messageDispatcher.DispatchMessage(message);
|
||||
@@ -571,7 +603,8 @@ void TwitchChatConnection::OnMessage(
|
||||
{
|
||||
static constexpr std::string_view authOKCommand = "001";
|
||||
static constexpr std::string_view pingCommand = "PING";
|
||||
static constexpr std::string_view joinOKCommand = "JOIN";
|
||||
static constexpr std::string_view joinCommand = "JOIN";
|
||||
static constexpr std::string_view partCommand = "PART";
|
||||
static constexpr std::string_view noticeCommand = "NOTICE";
|
||||
static constexpr std::string_view reconnectCommand = "RECONNECT";
|
||||
static constexpr std::string_view newMessageCommand = "PRIVMSG";
|
||||
@@ -596,8 +629,10 @@ void TwitchChatConnection::OnMessage(
|
||||
} else if (message.command.command == pingCommand) {
|
||||
Send("PONG " +
|
||||
std::get<std::string>(message.command.parameters));
|
||||
} else if (message.command.command == joinOKCommand) {
|
||||
} else if (message.command.command == joinCommand) {
|
||||
HandleJoin(message);
|
||||
} else if (message.command.command == partCommand) {
|
||||
HandlePart(message);
|
||||
} else if (message.command.command == newMessageCommand) {
|
||||
HandleNewMessage(message);
|
||||
} else if (message.command.command == whisperCommand) {
|
||||
|
||||
@@ -44,6 +44,8 @@ struct IRCMessage {
|
||||
std::string userId;
|
||||
std::string userType;
|
||||
bool isVIP = false;
|
||||
bool joinedChannel = false;
|
||||
bool leftChannel = false;
|
||||
} properties;
|
||||
|
||||
struct {
|
||||
@@ -95,6 +97,7 @@ private:
|
||||
void Authenticate();
|
||||
void JoinChannel(const std::string &);
|
||||
void HandleJoin(const IRCMessage &);
|
||||
void HandlePart(const IRCMessage &);
|
||||
void HandleNewMessage(const IRCMessage &);
|
||||
void HandleWhisper(const IRCMessage &);
|
||||
void HandleNotice(const IRCMessage &) const;
|
||||
|
||||
@@ -121,6 +121,10 @@ const static std::map<MacroConditionTwitch::Condition, std::string> conditionTyp
|
||||
"AdvSceneSwitcher.condition.twitch.type.polling.channel.category"},
|
||||
{MacroConditionTwitch::Condition::CHAT_MESSAGE_RECEIVED,
|
||||
"AdvSceneSwitcher.condition.twitch.type.chat.message"},
|
||||
{MacroConditionTwitch::Condition::CHAT_USER_JOINED,
|
||||
"AdvSceneSwitcher.condition.twitch.type.chat.userJoined"},
|
||||
{MacroConditionTwitch::Condition::CHAT_USER_LEFT,
|
||||
"AdvSceneSwitcher.condition.twitch.type.chat.userLeft"},
|
||||
};
|
||||
|
||||
const static std::map<MacroConditionTwitch::Condition, std::string> eventIdentifiers = {
|
||||
@@ -385,6 +389,12 @@ bool MacroConditionTwitch::CheckChatMessages(TwitchToken &token)
|
||||
continue;
|
||||
}
|
||||
|
||||
// Join and leave message don't have any message data
|
||||
if (message->properties.leftChannel ||
|
||||
message->properties.joinedChannel) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_chatMessagePattern.Matches(*message)) {
|
||||
continue;
|
||||
}
|
||||
@@ -443,6 +453,41 @@ bool MacroConditionTwitch::CheckChatMessages(TwitchToken &token)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionTwitch::CheckChatUserJoinOrLeave(TwitchToken &token)
|
||||
{
|
||||
if (!_chatConnection) {
|
||||
_chatConnection = TwitchChatConnection::GetChatConnection(
|
||||
token, _channel);
|
||||
if (!_chatConnection) {
|
||||
return false;
|
||||
}
|
||||
_chatBuffer = _chatConnection->RegisterForMessages();
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!_chatBuffer->Empty()) {
|
||||
auto message = _chatBuffer->ConsumeMessage();
|
||||
if (!message) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((_condition == Condition::CHAT_USER_JOINED &&
|
||||
!message->properties.joinedChannel) ||
|
||||
(_condition == Condition::CHAT_USER_LEFT &&
|
||||
!message->properties.leftChannel)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SetTempVarValue("user_login", message->source.nick);
|
||||
|
||||
if (_clearBufferOnMatch) {
|
||||
_eventBuffer->Clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void MacroConditionTwitch::SetTempVarValues(const ChannelLiveInfo &info)
|
||||
{
|
||||
SetTempVarValue("broadcaster_user_id", info.user_id);
|
||||
@@ -625,6 +670,14 @@ bool MacroConditionTwitch::CheckCondition()
|
||||
}
|
||||
return CheckChatMessages(*token);
|
||||
}
|
||||
case Condition::CHAT_USER_JOINED:
|
||||
case Condition::CHAT_USER_LEFT: {
|
||||
auto token = _token.lock();
|
||||
if (!token) {
|
||||
return false;
|
||||
}
|
||||
return CheckChatUserJoinOrLeave(*token);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -773,6 +826,10 @@ bool MacroConditionTwitch::ConditionIsSupportedByToken()
|
||||
{Condition::CATEGORY_POLLING, {}},
|
||||
{Condition::CHAT_MESSAGE_RECEIVED,
|
||||
{{"chat:read"}, {"chat:edit"}}},
|
||||
{Condition::CHAT_USER_JOINED,
|
||||
{{"chat:read"}, {"chat:edit"}}},
|
||||
{Condition::CHAT_USER_LEFT,
|
||||
{{"chat:read"}, {"chat:edit"}}},
|
||||
};
|
||||
|
||||
auto token = _token.lock();
|
||||
@@ -967,6 +1024,8 @@ void MacroConditionTwitch::SetupTempVars()
|
||||
};
|
||||
|
||||
if (_condition != Condition::CHAT_MESSAGE_RECEIVED &&
|
||||
_condition != Condition::CHAT_USER_JOINED &&
|
||||
_condition != Condition::CHAT_USER_LEFT &&
|
||||
_condition != Condition::RAID_INBOUND_EVENT &&
|
||||
_condition != Condition::RAID_OUTBOUND_EVENT) {
|
||||
setupTempVarHelper("broadcaster_user_id");
|
||||
@@ -1303,6 +1362,12 @@ void MacroConditionTwitch::SetupTempVars()
|
||||
setupTempVarHelper("is_turbo", ".chatReceive");
|
||||
setupTempVarHelper("is_vip", ".chatReceive");
|
||||
break;
|
||||
case Condition::CHAT_USER_JOINED:
|
||||
setupTempVarHelper("user_login", ".chatJoin");
|
||||
break;
|
||||
case Condition::CHAT_USER_LEFT:
|
||||
setupTempVarHelper("user_login", ".chatLeave");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1546,7 +1611,11 @@ void MacroConditionTwitchEdit::SetWidgetVisibility()
|
||||
_clearBufferOnMatch->setVisible(
|
||||
_entryData->IsUsingEventSubCondition() ||
|
||||
_entryData->GetCondition() ==
|
||||
MacroConditionTwitch::Condition::CHAT_MESSAGE_RECEIVED);
|
||||
MacroConditionTwitch::Condition::CHAT_MESSAGE_RECEIVED ||
|
||||
_entryData->GetCondition() ==
|
||||
MacroConditionTwitch::Condition::CHAT_USER_JOINED ||
|
||||
_entryData->GetCondition() ==
|
||||
MacroConditionTwitch::Condition::CHAT_USER_LEFT);
|
||||
|
||||
if (condition == MacroConditionTwitch::Condition::TITLE_POLLING) {
|
||||
RemoveStretchIfPresent(_layout);
|
||||
|
||||
@@ -74,6 +74,8 @@ public:
|
||||
|
||||
// Chat
|
||||
CHAT_MESSAGE_RECEIVED = 500000,
|
||||
CHAT_USER_JOINED = 500100,
|
||||
CHAT_USER_LEFT = 500200,
|
||||
|
||||
// Polling
|
||||
LIVE_POLLING = 1000000,
|
||||
@@ -110,6 +112,7 @@ private:
|
||||
bool CheckChannelGenericEvents();
|
||||
bool CheckChannelLiveEvents();
|
||||
bool CheckChatMessages(TwitchToken &token);
|
||||
bool CheckChatUserJoinOrLeave(TwitchToken &token);
|
||||
|
||||
void RegisterEventSubscription();
|
||||
void ResetSubscription();
|
||||
|
||||
Reference in New Issue
Block a user