Add Shuffle.us support for detecting hidden offline gambling

This commit is contained in:
barelyprofessional
2026-03-13 20:22:05 -05:00
parent 986027f5c5
commit 0454a5bbdd
3 changed files with 90 additions and 2 deletions

View File

@@ -963,7 +963,8 @@ public class BotServices
.GetMultipleValuesAsync([
BuiltIn.Keys.ShuffleBmjUsername, BuiltIn.Keys.ShuffleDotUsBmjUsername,
BuiltIn.Keys.KiwiFarmsGreenColor, BuiltIn.Keys.KiwiFarmsRedColor,
BuiltIn.Keys.ShuffleBmjUserId, BuiltIn.Keys.ShuffleBmjVipLevel
BuiltIn.Keys.ShuffleBmjUserId, BuiltIn.Keys.ShuffleBmjVipLevel,
BuiltIn.Keys.ShuffleDotUsBmjUserId, BuiltIn.Keys.ShuffleDotUsBmjVipLevel
]).Result;
_logger.Trace("Shuffle bet has arrived");
bool offlineBet = false;
@@ -991,6 +992,30 @@ public class BotServices
if (betOwner != settings[BuiltIn.Keys.ShuffleBmjUserId].Value) return;
offlineBet = true;
}
if (bet.Username == null && bet.VipLevel == settings[BuiltIn.Keys.ShuffleDotUsBmjVipLevel].Value && !CheckBmjIsLive().Result && isDotUs)
{
_logger.Info($"Checking for potential Shuffle.us offline bet {bet.Id}");
string? betOwner;
try
{
betOwner = _shuffleDotUs?.GetBetUser(bet.Id).Result;
}
catch (Exception e)
{
_logger.Error($"Caught an error when trying to get {bet.Id}");
_logger.Error(e);
return;
}
if (betOwner == null)
{
_logger.Error($"Failed to get the bet owner for {bet.Id}");
return;
}
_logger.Info($"Got user ID {betOwner}");
if (betOwner != settings[BuiltIn.Keys.ShuffleDotUsBmjUserId].Value) return;
offlineBet = true;
}
if (bet.Username == settings[BuiltIn.Keys.ShuffleBmjUsername].Value)
{
UpdateBossmanLastSighting($"betting {bet.Amount} {bet.Currency} on {bet.GameName} at Shuffle.com").Wait(_cancellationToken);
@@ -999,14 +1024,20 @@ public class BotServices
{
UpdateBossmanLastSighting($"betting {bet.Amount} {bet.Currency} on {bet.GameName} at Shuffle.us").Wait(_cancellationToken);
}
else if (offlineBet)
else if (offlineBet && !isDotUs)
{
UpdateBossmanLastSighting($"betting {bet.Amount} {bet.Currency} on {bet.GameName} at Shuffle.com OFFLINE").Wait(_cancellationToken);
}
else if (offlineBet && isDotUs)
{
UpdateBossmanLastSighting($"betting {bet.Amount} {bet.Currency} on {bet.GameName} at Shuffle.us OFFLINE").Wait(_cancellationToken);
}
else
{
return;
}
if (offlineBet) bet.Username = "OFFLINE GAMBLING NIGGER";
_logger.Info($"ALERT BMJ IS BETTING: isDotUs => {isDotUs}");
if (CheckBmjIsLive().Result) return;

View File

@@ -1,4 +1,5 @@
using System.Net;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Net.WebSockets;
using System.Text.Json;
@@ -163,6 +164,58 @@ public class ShuffleDotUs : IDisposable
_logger.Error("--- End of JSON Payload ---");
}
}
public async Task<string> GetBetUser(string betId)
{
var gql = "query GetBetInfo($betId: String!) {\n bet(id: $betId) {\n id\n completedAt\n account {\n id\n user {\n username\n vipLevel\n __typename\n }\n __typename\n }\n game {\n id\n name\n slug\n edge\n accentColor\n image {\n key\n __typename\n }\n gameAndGameCategories {\n gameCategoryName\n gameId\n main\n __typename\n }\n provider {\n id\n name\n __typename\n }\n originalGame\n __typename\n }\n gameSeed {\n ...GameSeedFields\n __typename\n }\n gameSeedNonce\n shuffleOriginalActions {\n id\n updatedAt\n createdAt\n action {\n dice {\n ...DiceFields\n __typename\n }\n plinko {\n multiplier\n results\n risk\n rows\n __typename\n }\n mines {\n minesResult\n minesCount\n winMultiplier\n selected\n __typename\n }\n limbo {\n resultRaw\n resultValue\n userValue\n __typename\n }\n keno {\n results\n risk\n multiplier\n selected\n __typename\n }\n hilo {\n card\n guess\n winMultiplier\n actionType\n __typename\n }\n blackjack {\n mainPlayerHand\n mainPlayerActions\n splitPlayerHand\n splitPlayerActions\n dealerHand\n perfectPairWin\n twentyOnePlusThreeWin\n twentyOnePlusThreeAmount\n perfectPairAmount\n insuranceStatus\n originalMainBetAmount\n mainHandOutcome\n splitHandOutcome\n __typename\n }\n roulette {\n resultRaw\n resultValue\n userInput {\n parityValues {\n amount\n parity\n __typename\n }\n colorValues {\n amount\n color\n __typename\n }\n halfValues {\n amount\n half\n __typename\n }\n columnValues {\n amount\n column\n __typename\n }\n dozenValues {\n amount\n dozen\n __typename\n }\n straightValues {\n amount\n straightNumber\n __typename\n }\n splitValues {\n amount\n firstNumber\n secondNumber\n __typename\n }\n streetValues {\n amount\n street\n __typename\n }\n cornerValues {\n amount\n firstNumber\n secondNumber\n thirdNumber\n fourthNumber\n __typename\n }\n doubleStreetValues {\n amount\n firstStreet\n secondStreet\n __typename\n }\n __typename\n }\n __typename\n }\n wheel {\n resultRaw\n resultSegment\n risk\n segments\n __typename\n }\n tower {\n towerResult\n towerDifficulty\n winMultiplier\n selected\n __typename\n }\n chicken {\n chickenResult\n chickenDifficulty\n winMultiplier\n selectedLane\n __typename\n }\n __typename\n }\n __typename\n }\n amount\n originalAmount\n payout\n currency\n usdRate\n createdAt\n afterBalance\n multiplier\n replayUrl\n __typename\n }\n}\n\nfragment GameSeedFields on GameSeed {\n id\n clientSeed\n seed\n hashedSeed\n status\n currentNonce\n createdAt\n __typename\n}\n\nfragment DiceFields on DiceActionModel {\n userDiceDirection\n userValue\n resultValue\n resultRaw\n __typename\n}";
_logger.Debug($"Grabbing details for Shuffle bet {betId}");
var jsonBody = new Dictionary<string, object>
{
{ "operationName", "GetBetInfo" },
{ "query", gql },
{ "variables", new Dictionary<string, string> { { "betId", betId } } },
{ "extensions", new Dictionary<string, Dictionary<string, string>> {
{
"clientLibrary", new Dictionary<string, string>()
{
{"name", "@apollo/client"},
{"version", "4.1.4"}
}
} } },
};
_logger.Debug("Created dictionary object for the JSON payload, should serialize to following value:");
_logger.Debug(JsonSerializer.Serialize(jsonBody));
var handler = new HttpClientHandler { AutomaticDecompression = DecompressionMethods.All };
if (_proxy != null)
{
handler.UseProxy = false;
handler.Proxy = new WebProxy(_proxy);
_logger.Debug($"Configured to use proxy {_proxy}");
}
using var client = new HttpClient(handler);
client.DefaultRequestHeaders.Referrer = new Uri($"https://shuffle.us/?md-id={betId}&modal=bet");
client.DefaultRequestHeaders.TryAddWithoutValidation("Origin", "https://shuffle.us");
client.DefaultRequestHeaders.UserAgent.Clear();
client.DefaultRequestHeaders.UserAgent.TryParseAdd("Mozilla/5.0 (X11; Linux x86_64; rv:147.0) Gecko/20100101 Firefox/147.0");
client.DefaultRequestHeaders.AcceptLanguage.Clear();
client.DefaultRequestHeaders.AcceptLanguage.TryParseAdd("en-US");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/graphql-response+json"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var postBody = JsonContent.Create(jsonBody, new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.PostAsync("https://shuffle.us/main-api/graphql/api/graphql", postBody, _cancellationToken);
var responseContent = await response.Content.ReadFromJsonAsync<JsonElement>(cancellationToken: _cancellationToken);
_logger.Debug("Shuffle returned following JSON");
_logger.Debug(responseContent.GetRawText);
var user = responseContent.GetProperty("data").GetProperty("bet").GetProperty("account").GetProperty("id");
if (user.ValueKind == JsonValueKind.Null)
{
_logger.Debug("user was null");
throw new ShuffleUserNotFoundException();
}
return user.GetString() ?? throw new InvalidOperationException();
}
public async Task<ShuffleUserModel> GetShuffleUser(string username)
{

View File

@@ -560,6 +560,10 @@ public static class BuiltIn
public static string ShuffleBmjVipLevel = "Shuffle.BmjVipLevel";
[BuiltInSetting("Whether OpenAI moderation is enabled", SettingValueType.Boolean, "false", BooleanRegex)]
public static string OpenAiModerationEnabled = "OpenAI.ModerationEnabled";
[BuiltInSetting("Bossman's current VIP level on .us for reducing GraphQL hits", SettingValueType.Text, "PLATINUM_1")]
public static string ShuffleDotUsBmjVipLevel = "ShuffleDotUs.BmjVipLevel";
[BuiltInSetting("Bossman's super secret user ID on .us", SettingValueType.Text, "e2faee09-8ebb-4a22-8793-59aefc8191e5")]
public static string ShuffleDotUsBmjUserId = "ShuffleDotUs.BmjUserId";
}
}