-
-
Save m4dEngi/97eff07de541ab90f3fe077fee46af73 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using ArchiSteamFarm; | |
using ArchiSteamFarm.Plugins; | |
using System.Composition; | |
using SteamKit2; | |
using System.Collections.Generic; | |
using HtmlAgilityPack; | |
using SteamKit2.Internal; | |
using System.Linq; | |
using System.Threading.Tasks; | |
namespace m4dengi.SpringCleanPlugin | |
{ | |
// this class is used to bypass plugin api limitations | |
// and expose SteamClient instance associated with bot to plugin | |
class CallHack : ClientMsgHandler | |
{ | |
public override void HandleMsg(IPacketMsg packetMsg) | |
{ | |
//stub | |
} | |
public void PlayGames(List<uint> appIDs) | |
{ | |
var gamesPlayedMsg = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed); | |
foreach (uint appID in appIDs) | |
{ | |
gamesPlayedMsg.Body.games_played.Add(new CMsgClientGamesPlayed.GamePlayed { game_id = new GameID(appID) }); | |
} | |
Client.Send(gamesPlayedMsg); | |
} | |
public async Task<SteamApps.FreeLicenseCallback> RequestFreeLicense(List<uint> appIDs) | |
{ | |
SteamApps apps = Client.GetHandler<SteamApps>(); | |
return await apps.RequestFreeLicense(appIDs); | |
} | |
} | |
[Export(typeof(IPlugin))] | |
public sealed class SpringCleanPlugin : IPlugin, IBot, IBotSteamClient, IBotCommand | |
{ | |
public string Name => nameof(SpringCleanPlugin); | |
public Version Version => typeof(SpringCleanPlugin).Assembly.GetName().Version; | |
private static Dictionary<Bot, CallHack> extHandlers = new Dictionary<Bot, CallHack>(); | |
private async Task<List<uint>> FetchSpringGamesList(Bot bot) | |
{ | |
List<uint> gamesList = new List<uint>(); | |
HtmlDocument springCleanPage = await bot.ArchiWebHandler.UrlGetToHtmlDocumentWithSession(ArchiWebHandler.SteamStoreURL, "/springcleaning"); | |
HtmlNodeCollection appTaskCollection = springCleanPage.DocumentNode.SelectNodes("//div[contains(@class, 'spring_cleaning_task_ctn')]"); | |
if (appTaskCollection.Count != 0) | |
{ | |
foreach (HtmlNode node in appTaskCollection) | |
{ | |
HtmlNode gameAppLinkNode = node.SelectSingleNode(".//div[@data-sg-appid]"); | |
if (gameAppLinkNode != null) | |
{ | |
string appStoreId = gameAppLinkNode.Attributes["data-sg-appid"].Value; | |
if (!string.IsNullOrEmpty(appStoreId)) | |
{ | |
uint appIDToAdd = uint.Parse(appStoreId); | |
gamesList.Add(appIDToAdd); | |
} | |
} | |
} | |
} | |
return gamesList; | |
} | |
private async Task ApplyGenericTagsToAppID(Bot bot, uint appID, string tagName, uint tagID) | |
{ | |
bool success = await bot.ArchiWebHandler.UrlPostWithSession(ArchiWebHandler.SteamStoreURL, "/tagdata/tagapp", new Dictionary<string, string>() { { "appid", appID.ToString() }, { "tag", tagName }, { "tagid", tagID.ToString() } }); | |
await Task.Delay(TimeSpan.FromSeconds(2)); | |
} | |
private async Task<string> SpringClean(Bot bot, int delay = 30) | |
{ | |
if (!bot.IsConnectedAndLoggedOn) | |
{ | |
return null; | |
} | |
await Task.Delay(TimeSpan.FromSeconds(delay)); | |
bot.ArchiLogger.LogGenericInfo("Applying generic tags to TF2"); | |
await ApplyGenericTagsToAppID(bot, 440, "Multiplayer", 3859); | |
await ApplyGenericTagsToAppID(bot, 440, "Free+to+Play", 113); | |
bot.ArchiLogger.LogGenericInfo("Loading spring clean tasks"); | |
List<uint> gamesToPlay = await FetchSpringGamesList(bot); | |
if (gamesToPlay.Count != 0) | |
{ | |
bot.ArchiLogger.LogGenericInfo(string.Format("Got {0} games to 'play' : {1}", gamesToPlay.Count, string.Join(',', gamesToPlay))); | |
if (gamesToPlay.Count != 0 && gamesToPlay.Count < 32) | |
{ | |
await bot.Actions.Pause(false); | |
var result = await extHandlers[bot].RequestFreeLicense(gamesToPlay); | |
bot.ArchiLogger.LogGenericInfo("Got RequestFreeLicense response : " + result.Result); | |
if (result.Result == EResult.OK) | |
{ | |
bot.ArchiLogger.LogGenericInfo("Granted appIDs count : " + result.GrantedApps.Count); | |
} | |
extHandlers[bot].PlayGames(gamesToPlay); | |
} | |
} | |
else | |
{ | |
return "Got no games from spring cleaning event page"; | |
} | |
bot.ArchiLogger.LogGenericInfo("Done."); | |
return "Ok"; | |
} | |
public void OnBotSteamCallbacksInit(Bot bot, CallbackManager callbackManager) | |
{ | |
// stub | |
} | |
public IReadOnlyCollection<ClientMsgHandler> OnBotSteamHandlersInit(Bot bot) | |
{ | |
if (!extHandlers.ContainsKey(bot)) | |
{ | |
extHandlers.Add(bot, new CallHack()); | |
} | |
return new List<ClientMsgHandler> { extHandlers[bot] }; | |
} | |
public void OnLoaded() | |
{ | |
ASF.ArchiLogger.LogGenericInfo("SpringCleanPlugin loaded. Expect weird behaviour and unexpected consequences."); | |
} | |
public void OnBotDestroy(Bot bot) | |
{ | |
extHandlers.Remove(bot); | |
} | |
public void OnBotInit(Bot bot) | |
{ | |
// stub | |
} | |
public async Task<string> OnBotCommand(Bot bot, ulong steamID, string message, string[] args) | |
{ | |
switch (args[0].ToUpperInvariant()) | |
{ | |
case "SPRINGCLEAN" when bot.HasPermission(steamID, BotConfig.EPermission.Operator): | |
if (args.Length > 1) | |
{ | |
HashSet<Bot> bots = Bot.GetBots(args[1]); | |
int delayCtr = bots.Count(b => b.IsConnectedAndLoggedOn); | |
IList<string> results = await Utilities.InParallel(bots.Where(x => x.IsConnectedAndLoggedOn).Select(b => { --delayCtr; return SpringClean(b, delayCtr * 30); })); | |
List<string> responses = new List<string>(results.Where(result => !string.IsNullOrEmpty(result))); | |
return responses.Count > 0 ? string.Join(Environment.NewLine, responses) : null; | |
} | |
else | |
{ | |
return await SpringClean(bot); | |
} | |
default: | |
return null; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment