Skip to content
This repository was archived by the owner on Jan 9, 2023. It is now read-only.

Commit 6dce15b

Browse files
committed
Fully support Twitch Sub Mystery Gift
Expand testing options to handle subMysertyGift
1 parent 3192837 commit 6dce15b

11 files changed

+161
-68
lines changed

Profiles/Factorio - Advanced Usage Example.json

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,39 @@
22
"name": "Factorio - Advanced Usage Example",
33
"description": "Example of some more complicated uses",
44
"reactions": [
5+
{
6+
"platform": "twitch_account",
7+
"type": "subscription",
8+
"filteredActions": [
9+
{
10+
"condition": "[ALL]",
11+
"manipulator": "",
12+
"action": "[BESTNAME] subscribed themselves"
13+
}
14+
]
15+
},
16+
{
17+
"platform": "twitch_account",
18+
"type": "subscriptionGift",
19+
"filteredActions": [
20+
{
21+
"condition": "[ALL]",
22+
"manipulator": "",
23+
"action": "[BESTNAME] was subscribed by [gifter_display_name]"
24+
}
25+
]
26+
},
27+
{
28+
"platform": "twitch_account",
29+
"type": "subMysteryGift",
30+
"filteredActions": [
31+
{
32+
"condition": "[ALL]",
33+
"manipulator": "",
34+
"action": "subMysterGift donator enabled: [BESTNAME] subscribed [amount] users"
35+
}
36+
]
37+
},
538
{
639
"valueType": "money",
740
"filteredActions": [
@@ -37,5 +70,8 @@
3770
}
3871
]
3972
}
40-
]
73+
],
74+
"options": {
75+
"twitchMysterSubGiftMode": "donator"
76+
}
4177
}

Profiles/Factorio - Print All.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,8 @@
3232
}
3333
]
3434
}
35-
]
35+
],
36+
"options": {
37+
"twitchMysterSubGiftMode": "donator"
38+
}
3639
}

Profiles/Factorio - Print Most Fancy.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,8 @@
9292
"description": "Say thanks for small value stuff",
9393
"effect": "Ta for $[VALUE] [BESTNAME]"
9494
}
95-
]
95+
],
96+
"options": {
97+
"twitchMysterSubGiftMode": "donator"
98+
}
9699
}

README.md

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@
33

44
A Python exe for integrating Streamlabs and any game supporting Rcon. It receives the Streamlabs events and uses configurable logic to send an approperiate RCON command to the game server to do something. Its currently being used with Factorio, but should be compatible with any other Rcon interfaced game.
55

6-
At present only really tested with Twitch, but should work with mixer and youtube based on API spec.
6+
At present only really tested with Twitch, but should work with mixer and youtube based on API spec. The tool runs fully on your pc removing any risk of sharing access keys or donators details.
77

88

99
Installation & Usage
1010
==========
11-
1. Get the [latest version zip](https://github.com/muppet9010/Streamlabs-Rcon-Integration).
12-
2. Create a free account at [Currency Layer website](https://currencylayer.com) and make a note of the API access key as needs to be entered in to the programs config later on.
13-
3. Unzip the files in to the desired folder.
14-
4. Open config.json in a text editor and add in your details.
15-
5. Run the program: Streamlabs Rcon Integration.exe
16-
6. Select the desired profile from the dropdown and click Start.
17-
7. The integration is now running between the Streamlabs account and the game using the selected profile.
11+
1. Install the current release of Python 3.7 with default options: https://www.python.org/downloads
12+
2. Get the [latest version zip](https://github.com/muppet9010/Streamlabs-Rcon-Integration).
13+
3. Create a free account at [Currency Layer website](https://currencylayer.com) and make a note of the API access key as needs to be entered in to the programs config later on.
14+
4. Unzip the files in to the desired folder.
15+
5. Open config.json in a text editor and add in your details.
16+
6. Run the program: Streamlabs Rcon Integration.exe
17+
7. Select the desired profile from the dropdown and click Start.
18+
8. The integration is now running between the Streamlabs account and the game using the selected profile.
1819

1920
Should a critical error occur the program may fail to load or close. Details can be found in the most recent log file within the Logs folder.
2021

@@ -55,6 +56,11 @@ Manipulator script's are special in that they support raw python code that will
5556

5657
The config has a `Rcon No Commands` option. When enabled it prints the RCON commands to the activity window rather than sending them. It also skips the RCON connection test which the Start button is clicked within the app. In effect not doing any RCON commands.
5758

59+
Profiles can have `options` specified for them to control specific program behavior:
60+
- twitchMysterSubGiftMode = when Twitch Subscription Mystery Gifts are given out by a viewer to random other viewers the event can either be reacted to for the donator or receiver. The programs default is the `donator` value if the setting isn't specified in the profile's options. The `money` valyeType will obey this setting and the other event type won't be triggered for Twitch Subscription Mystery Gifts to avoid duplicate reactions.
61+
- `donator` - react to it as one large donation using the `subMysteryGift` event reaction.
62+
- `receiver` - react to each viewer getting the gifted subscription using the `subscriptionGift` event reaction.
63+
5864

5965
Development Building
6066
=============

Source/Gui.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def _CreateBottomBar(self, parent):
7474
self.selectedTestEventPlatform = TK.StringVar()
7575
self.selectedTestEventPlatform.trace_variable(
7676
TK.W, self.OnTestEventPlatformChanged)
77-
orderedTestEventPlatforms = self.state.testEvents.GetPlatforms()
77+
orderedTestEventPlatforms = self.state.testEventUtils.GetPlatforms()
7878
self.testEventPlatformList = TK.OptionMenu(
7979
bottomBarContainer, self.selectedTestEventPlatform, *orderedTestEventPlatforms)
8080
self.testEventPlatformList.pack(side=TK.LEFT)
@@ -156,7 +156,7 @@ def OnTestEventPlatformChanged(self, *args):
156156
self.testEventTypeList["menu"].delete(0, TK.END)
157157
orderedTestEventTypes = []
158158
if self.selectedTestEventPlatform.get() != self.translations.GetTranslation("Gui SelectTestEventPlatform"):
159-
orderedTestEventTypes = self.state.testEvents.GetPlatformTypes(
159+
orderedTestEventTypes = self.state.testEventUtils.GetPlatformTypes(
160160
self.selectedTestEventPlatform.get())
161161
for testEventType in orderedTestEventTypes:
162162
self.testEventTypeList["menu"].add_command(
@@ -176,9 +176,9 @@ def OnTestEventTypeChanged(self, *args):
176176
amountEnabled = False
177177
quantityEnabled = False
178178
if self.selectedTestEventType.get() != self.translations.GetTranslation("Gui SelectTestEventType"):
179-
amountEnabled = self.state.testEvents.GetAttribute(self.selectedTestEventPlatform.get(
179+
amountEnabled = self.state.testEventUtils.GetAttribute(self.selectedTestEventPlatform.get(
180180
), self.selectedTestEventType.get(), "valueInput")
181-
quantityEnabled = self.state.testEvents.GetAttribute(self.selectedTestEventPlatform.get(
181+
quantityEnabled = self.state.testEventUtils.GetAttribute(self.selectedTestEventPlatform.get(
182182
), self.selectedTestEventType.get(), "quantityInput")
183183
if amountEnabled:
184184
self.testEventValueLabel.config(state=TK.NORMAL)

Source/Profiles.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ def __init__(self, profileData, profiles):
3838
self.reactionPriorities[1].append(reaction)
3939
elif "valueType" in reactionData:
4040
self.reactionPriorities[2].append(reaction)
41+
if "options" in profileData:
42+
self.options = Options(self, profileData["options"])
43+
else:
44+
self.options = Options(self, {})
4145

4246
def GetActionTextForEvent(self, event):
4347
for reaction in self.reactionPriorities[1]:
@@ -191,3 +195,15 @@ def __init__(self, actionData):
191195
self.name = actionData["name"]
192196
self.description = actionData["description"]
193197
self.effect = actionData["effect"]
198+
199+
200+
class Options:
201+
def __init__(self, profile, optionData):
202+
self.profile = profile
203+
self.logging = self.profile.profiles.state.logging
204+
self.twitchMysterSubGiftMode = "donator"
205+
if "twitchMysterSubGiftMode" in optionData:
206+
self.twitchMysterSubGiftMode = optionData["twitchMysterSubGiftMode"]
207+
if self.twitchMysterSubGiftMode not in ("donator", "receiver"):
208+
self.logging.LogQuit(self.profile.name +
209+
" : has invalid twitchMysterSubGiftMode option value: " + self.twitchMysterSubGiftMode)

Source/Streamlabs Rcon Integration.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from Profiles import Profiles
99
from Rcon import Rcon
1010
from Translations import Translations
11-
from TestEvents import TestEvents
11+
from TestEvents import TestEventUtils
1212

1313

1414
class State():
@@ -20,13 +20,14 @@ def __init__(self):
2020

2121
def Setup(self):
2222
self.donationsIdsProcessed = {}
23+
self.mysterySubGifts = {}
2324
self.translations = Translations(self)
2425
self.currency = Currency(self)
2526
StreamlabsEventUtils.LoadEventDefinitions()
2627
self.profiles = Profiles(self)
2728
self.streamlabs = Streamlabs(self)
2829
self.rcon = Rcon(self)
29-
self.testEvents = TestEvents()
30+
self.testEventUtils = TestEventUtils()
3031
self.guiWindow = GuiWindow(self)
3132
self.gui = self.guiWindow.gui
3233
self.gui.Setup()
@@ -171,18 +172,22 @@ def OnTestEventButtonHandler(self):
171172
try:
172173
testEventPlatform = self.gui.selectedTestEventPlatform.get()
173174
testEventType = self.gui.selectedTestEventType.get()
174-
testEventValue = self.gui.testEventValue.get()
175-
if TestEvents.GetAttribute(testEventPlatform, testEventType, "valueInput"):
175+
testEventValue = ""
176+
if TestEventUtils.GetAttribute(testEventPlatform, testEventType, "valueInput"):
176177
try:
178+
testEventValue = self.gui.testEventValue.get()
177179
testEventValue = float(testEventValue)
178180
except:
179181
self.RecordActivity(
180182
self.translations.GetTranslation("TestEvent ValueNotFloat") + str(testEventValue))
181183
return
182-
testEventQuantity = self.gui.testEventQuantity.get()
183-
if TestEvents.GetAttribute(testEventPlatform, testEventType, "quantityInput"):
184+
testEventQuantity = ""
185+
if TestEventUtils.GetAttribute(testEventPlatform, testEventType, "quantityInput"):
184186
try:
187+
testEventQuantity = self.gui.testEventQuantity.get()
185188
testEventQuantity = int(testEventQuantity)
189+
if testEventQuantity <= 0:
190+
raise ValueError()
186191
except:
187192
self.RecordActivity(
188193
self.translations.GetTranslation("TestEvent QuantityCountNotInt") + str(testEventQuantity))
@@ -196,10 +201,11 @@ def OnTestEventButtonHandler(self):
196201
self.RecordActivity(
197202
self.translations.GetTranslation("TestEvent PayloadCountNotInt") + str(testEventPayloadCount))
198203
return
199-
testEvent = self.testEvents.GenerateTestEvent(
204+
testEventArray = self.testEventUtils.GenerateTestEventArray(
200205
testEventPlatform, testEventType, testEventValue, testEventQuantity, testEventPayloadCount)
201-
if testEvent != None:
202-
self.OnStreamlabsEventHandler(testEvent)
206+
if len(testEventArray) > 0:
207+
for testEvent in testEventArray:
208+
self.OnStreamlabsEventHandler(testEvent)
203209
else:
204210
self.RecordActivity(
205211
self.translations.GetTranslation("TestEvent InvalidTestEvent") + testEventPlatform + " - " + testEventType)

Source/StreamlabsEvent.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@ def __init__(self, state, platformString, typeString, payload):
1919
self.rawMessage = {}
2020
self.errored = False
2121
self.ignored = False
22+
self.rawMessage = payload
23+
24+
if self.type == "donation" and self.platform == "":
25+
self.platform = "streamlabs"
26+
elif self.platform == "twitch_account" and self.type == "subscription" and "gifter" in self.rawMessage and self.rawMessage["gifter"] != None:
27+
self.type = "subscriptionGift"
2228

2329
if self.ShouldIgnoreEvent():
2430
self.ignored = True
2531
return
2632

27-
self.rawMessage = payload
28-
2933
self.id = self.rawMessage["_id"]
3034
if "display_name" in self.rawMessage.keys():
3135
self.bestName = self.rawMessage["display_name"]
@@ -36,10 +40,6 @@ def __init__(self, state, platformString, typeString, payload):
3640
elif "comment" in self.rawMessage.keys():
3741
self.bestComment = self.rawMessage["comment"]
3842

39-
if self.type == "donation" and self.platform == "":
40-
self.platform = "streamlabs"
41-
elif self.platform == "twitch_account" and self.type == "subscription" and "gifter" in self.rawMessage and self.rawMessage["gifter"] != None:
42-
self.type = "subscriptionGift"
4343
self.handlerName = StreamlabsEventUtils.MakeHandlerString(
4444
self.platform, self.type)
4545

@@ -83,6 +83,14 @@ def ShouldIgnoreEvent(self):
8383
return True
8484
if (self.platform == "widget"):
8585
return True
86+
if self.platform == "twitch_account":
87+
if self.state.profiles.currentProfile.options.twitchMysterSubGiftMode == "receiver" and self.type == "subMysteryGift":
88+
return True
89+
elif self.state.profiles.currentProfile.options.twitchMysterSubGiftMode == "donator" and self.type == "subscriptionGift":
90+
gifterName = self.rawMessage["gifter_display_name"]
91+
if gifterName in self.state.mysterySubGifts and self.state.mysterySubGifts[gifterName] > 0:
92+
self.state.mysterySubGifts[gifterName]-=1
93+
return True
8694
if self.id in self.state.donationsIdsProcessed:
8795
self.logging.DebugLog(
8896
"Streamlabs donation event being ignored as in processed list: " + self.id)
@@ -121,12 +129,14 @@ def PopulateNormalisedData(self):
121129
self.valueType = "money"
122130
subPlan = self.rawMessage["sub_plan"]
123131
subValue = StreamlabsEventUtils.GetTwitchSubscriptionValue(subPlan)
132+
amount = self.rawMessage["amount"]
124133
if subValue != None:
125-
self.value = subValue * self.rawMessage["amount"]
134+
self.value = subValue * amount
126135
else:
127136
self.state.RecordActivity(
128137
self.state.translations.GetTranslation("StreamlabsEvent UnrecognisedTwitchSubscriptionType") + subPlan)
129138
return False
139+
self.state.mysterySubGifts[self.bestName] = amount
130140
elif (self.handlerName == "youtube_account-subscription"):
131141
self.valueType = "money"
132142
self.value = 5

0 commit comments

Comments
 (0)