mirror of
https://github.com/JustArchiNET/ArchiSteamFarm
synced 2024-11-10 07:04:27 +00:00
Initial source drop
This commit is contained in:
parent
b36ab7220a
commit
aa1c1962de
70 changed files with 59852 additions and 0 deletions
22
ArchiSteamFarm.sln
Normal file
22
ArchiSteamFarm.sln
Normal file
|
@ -0,0 +1,22 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.23107.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArchiSteamFarm", "ArchiSteamFarm\ArchiSteamFarm.csproj", "{35AF7887-08B9-40E8-A5EA-797D8B60B30C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{35AF7887-08B9-40E8-A5EA-797D8B60B30C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{35AF7887-08B9-40E8-A5EA-797D8B60B30C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{35AF7887-08B9-40E8-A5EA-797D8B60B30C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{35AF7887-08B9-40E8-A5EA-797D8B60B30C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
6
ArchiSteamFarm/App.config
Normal file
6
ArchiSteamFarm/App.config
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
</configuration>
|
114
ArchiSteamFarm/ArchiHandler.cs
Normal file
114
ArchiSteamFarm/ArchiHandler.cs
Normal file
|
@ -0,0 +1,114 @@
|
|||
using SteamKit2;
|
||||
using SteamKit2.Internal;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class ArchiHandler : ClientMsgHandler {
|
||||
|
||||
internal sealed class PurchaseResponseCallback : CallbackMsg {
|
||||
internal enum EPurchaseResult {
|
||||
Unknown,
|
||||
OK,
|
||||
AlreadyOwned = 9,
|
||||
InvalidKey = 14,
|
||||
DuplicatedKey = 15,
|
||||
OnCooldown = 53
|
||||
}
|
||||
|
||||
internal EResult Result { get; private set; }
|
||||
internal EPurchaseResult PurchaseResult { get; private set; }
|
||||
internal int ErrorCode { get; private set; }
|
||||
internal byte[] ReceiptInfo { get; private set; }
|
||||
|
||||
internal PurchaseResponseCallback(CMsgClientPurchaseResponse body) {
|
||||
Result = (EResult) body.eresult;
|
||||
ErrorCode = body.purchase_result_details;
|
||||
ReceiptInfo = body.purchase_receipt_info;
|
||||
|
||||
if (Result == EResult.OK) {
|
||||
PurchaseResult = EPurchaseResult.OK;
|
||||
} else {
|
||||
PurchaseResult = (EPurchaseResult) ErrorCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class NotificationCallback : CallbackMsg {
|
||||
internal enum ENotificationType {
|
||||
Unknown = 0,
|
||||
Trading = 1,
|
||||
}
|
||||
|
||||
internal ENotificationType NotificationType { get; private set; }
|
||||
|
||||
internal NotificationCallback(CMsgClientUserNotifications.Notification body) {
|
||||
uint notificationType = body.user_notification_type;
|
||||
switch (notificationType) {
|
||||
case 1:
|
||||
NotificationType = (ENotificationType) notificationType;
|
||||
break;
|
||||
default:
|
||||
NotificationType = ENotificationType.Unknown;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void AcceptClanInvite(ulong clanID) {
|
||||
var request = new ClientMsg<CMsgClientClanInviteAction>((int) EMsg.ClientAcknowledgeClanInvite);
|
||||
request.Body.GroupID = clanID;
|
||||
request.Body.AcceptInvite = true;
|
||||
Client.Send(request);
|
||||
}
|
||||
|
||||
internal void DeclineClanInvite(ulong clanID) {
|
||||
var request = new ClientMsg<CMsgClientClanInviteAction>((int) EMsg.ClientAcknowledgeClanInvite);
|
||||
request.Body.GroupID = clanID;
|
||||
request.Body.AcceptInvite = false;
|
||||
Client.Send(request);
|
||||
}
|
||||
|
||||
internal void PlayGames(params ulong[] gameIDs) {
|
||||
var request = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed);
|
||||
foreach (ulong gameID in gameIDs) {
|
||||
if (gameID != 0) {
|
||||
request.Body.games_played.Add(new CMsgClientGamesPlayed.GamePlayed {
|
||||
game_id = new GameID(gameID),
|
||||
});
|
||||
}
|
||||
}
|
||||
Client.Send(request);
|
||||
}
|
||||
|
||||
// Will provide result in ClientPurchaseResponse, regardless if success or not
|
||||
internal void RedeemKey(string key) {
|
||||
var request = new ClientMsgProtobuf<CMsgClientRegisterKey>(EMsg.ClientRegisterKey);
|
||||
request.Body.key = key;
|
||||
Client.Send(request);
|
||||
}
|
||||
|
||||
public sealed override void HandleMsg(IPacketMsg packetMsg) {
|
||||
if (packetMsg != null) {
|
||||
switch (packetMsg.MsgType) {
|
||||
case EMsg.ClientPurchaseResponse:
|
||||
HandlePurchaseResponse(packetMsg);
|
||||
break;
|
||||
case EMsg.ClientUserNotifications:
|
||||
HandleUserNotifications(packetMsg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandlePurchaseResponse(IPacketMsg packetMsg) {
|
||||
var response = new ClientMsgProtobuf<CMsgClientPurchaseResponse>(packetMsg);
|
||||
Client.PostCallback(new PurchaseResponseCallback(response.Body));
|
||||
}
|
||||
|
||||
private void HandleUserNotifications(IPacketMsg packetMsg) {
|
||||
var response = new ClientMsgProtobuf<CMsgClientUserNotifications>(packetMsg);
|
||||
foreach (var notification in response.Body.notifications) {
|
||||
Client.PostCallback(new NotificationCallback(notification));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
82
ArchiSteamFarm/ArchiSteamFarm.csproj
Normal file
82
ArchiSteamFarm/ArchiSteamFarm.csproj
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{35AF7887-08B9-40E8-A5EA-797D8B60B30C}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ArchiSteamFarm</RootNamespace>
|
||||
<AssemblyName>ArchiSteamFarm</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="HtmlAgilityPack, Version=1.4.9.0, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\HtmlAgilityPack.1.4.9\lib\Net45\HtmlAgilityPack.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="protobuf-net, Version=2.0.0.668, Culture=neutral, PublicKeyToken=257b51d87d2e4d67, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\protobuf-net.2.0.0.668\lib\net40\protobuf-net.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="SteamKit2, Version=1.6.5.29095, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SteamKit2.1.6.5\lib\net40\SteamKit2.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ArchiHandler.cs" />
|
||||
<Compile Include="ArchiWebHandler.cs" />
|
||||
<Compile Include="Bot.cs" />
|
||||
<Compile Include="CardsFarmer.cs" />
|
||||
<Compile Include="CMsgClientClanInviteAction.cs" />
|
||||
<Compile Include="Logging.cs" />
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SteamItem.cs" />
|
||||
<Compile Include="SteamTradeOffer.cs" />
|
||||
<Compile Include="Trading.cs" />
|
||||
<Compile Include="Utilities.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
251
ArchiSteamFarm/ArchiWebHandler.cs
Normal file
251
ArchiSteamFarm/ArchiWebHandler.cs
Normal file
|
@ -0,0 +1,251 @@
|
|||
using HtmlAgilityPack;
|
||||
using SteamKit2;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal class ArchiWebHandler {
|
||||
private const int Timeout = 1000 * 15; // In miliseconds
|
||||
private readonly Bot Bot;
|
||||
private readonly string ApiKey;
|
||||
|
||||
private ulong SteamID;
|
||||
private string VanityURL;
|
||||
private readonly Dictionary<string, string> SteamCookieDictionary = new Dictionary<string, string>();
|
||||
|
||||
// This is required because home_process request must be done on final URL
|
||||
private string GetHomeProcess() {
|
||||
if (!string.IsNullOrEmpty(VanityURL)) {
|
||||
return "http://steamcommunity.com/id/" + VanityURL + "/home_process";
|
||||
} else if (SteamID != 0) {
|
||||
return "http://steamcommunity.com/profiles/" + SteamID + "/home_process";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal ArchiWebHandler(Bot bot, string apiKey) {
|
||||
Bot = bot;
|
||||
ApiKey = apiKey;
|
||||
}
|
||||
|
||||
internal void Init(SteamClient steamClient, string webAPIUserNonce, string vanityURL) {
|
||||
if (steamClient == null || steamClient.SteamID == null || string.IsNullOrEmpty(webAPIUserNonce) || string.IsNullOrEmpty(vanityURL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SteamID = steamClient.SteamID;
|
||||
VanityURL = vanityURL;
|
||||
|
||||
string sessionID = Convert.ToBase64String(Encoding.UTF8.GetBytes(SteamID.ToString(CultureInfo.InvariantCulture)));
|
||||
|
||||
// Generate an AES session key
|
||||
byte[] sessionKey = CryptoHelper.GenerateRandomBlock(32);
|
||||
|
||||
// RSA encrypt it with the public key for the universe we're on
|
||||
byte[] cryptedSessionKey = null;
|
||||
using (RSACrypto rsa = new RSACrypto(KeyDictionary.GetPublicKey(steamClient.ConnectedUniverse))) {
|
||||
cryptedSessionKey = rsa.Encrypt(sessionKey);
|
||||
}
|
||||
|
||||
// Copy our login key
|
||||
byte[] loginKey = new byte[20];
|
||||
Array.Copy(Encoding.ASCII.GetBytes(webAPIUserNonce), loginKey, webAPIUserNonce.Length);
|
||||
|
||||
// AES encrypt the loginkey with our session key
|
||||
byte[] cryptedLoginKey = CryptoHelper.SymmetricEncrypt(loginKey, sessionKey);
|
||||
|
||||
// Send the magic
|
||||
KeyValue authResult;
|
||||
Logging.LogGenericInfo(Bot.BotName, "Logging in to ISteamUserAuth...");
|
||||
using (dynamic iSteamUserAuth = WebAPI.GetInterface("ISteamUserAuth")) {
|
||||
iSteamUserAuth.Timeout = Timeout;
|
||||
|
||||
try {
|
||||
authResult = iSteamUserAuth.AuthenticateUser(
|
||||
steamid: SteamID,
|
||||
sessionkey: Encoding.ASCII.GetString(WebUtility.UrlEncodeToBytes(cryptedSessionKey, 0, cryptedSessionKey.Length)),
|
||||
encrypted_loginkey: Encoding.ASCII.GetString(WebUtility.UrlEncodeToBytes(cryptedLoginKey, 0, cryptedLoginKey.Length)),
|
||||
method: WebRequestMethods.Http.Post,
|
||||
secure: true
|
||||
);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(Bot.BotName, e);
|
||||
steamClient.Disconnect(); // We may get 403 if we use the same webAPIUserNonce twice
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (authResult == null) {
|
||||
steamClient.Disconnect(); // Try again
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo(Bot.BotName, "Success!");
|
||||
|
||||
string steamLogin = authResult["token"].AsString();
|
||||
string steamLoginSecure = authResult["tokensecure"].AsString();
|
||||
|
||||
SteamCookieDictionary.Clear();
|
||||
SteamCookieDictionary.Add("sessionid", sessionID);
|
||||
SteamCookieDictionary.Add("steamLogin", steamLogin);
|
||||
SteamCookieDictionary.Add("steamLoginSecure", steamLoginSecure);
|
||||
SteamCookieDictionary.Add("birthtime", "-473356799"); // ( ͡° ͜ʖ ͡°)
|
||||
|
||||
Bot.Trading.CheckTrades();
|
||||
}
|
||||
|
||||
internal List<SteamTradeOffer> GetTradeOffers() {
|
||||
KeyValue response;
|
||||
using (dynamic iEconService = WebAPI.GetInterface("IEconService")) {
|
||||
// Timeout
|
||||
iEconService.Timeout = Timeout;
|
||||
|
||||
try {
|
||||
response = iEconService.GetTradeOffers(
|
||||
key: ApiKey,
|
||||
get_received_offers: 1,
|
||||
active_only: 1,
|
||||
secure: true
|
||||
);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(Bot.BotName, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<SteamTradeOffer> result = new List<SteamTradeOffer>();
|
||||
foreach (KeyValue trade in response["trade_offers_received"].Children) {
|
||||
SteamTradeOffer tradeOffer = new SteamTradeOffer {
|
||||
tradeofferid = trade["tradeofferid"].AsString(),
|
||||
accountid_other = trade["accountid_other"].AsInteger(),
|
||||
message = trade["message"].AsString(),
|
||||
expiration_time = trade["expiration_time"].AsInteger(),
|
||||
trade_offer_state = (SteamTradeOffer.ETradeOfferState) trade["trade_offer_state"].AsInteger(),
|
||||
items_to_give = new List<SteamItem>(),
|
||||
items_to_receive = new List<SteamItem>(),
|
||||
is_our_offer = trade["is_our_offer"].AsBoolean(),
|
||||
time_created = trade["time_created"].AsInteger(),
|
||||
time_updated = trade["time_updated"].AsInteger(),
|
||||
from_real_time_trade = trade["from_real_time_trade"].AsBoolean()
|
||||
};
|
||||
foreach (KeyValue item in trade["items_to_give"].Children) {
|
||||
tradeOffer.items_to_give.Add(new SteamItem {
|
||||
appid = item["appid"].AsString(),
|
||||
contextid = item["contextid"].AsString(),
|
||||
assetid = item["assetid"].AsString(),
|
||||
currencyid = item["currencyid"].AsString(),
|
||||
classid = item["classid"].AsString(),
|
||||
instanceid = item["instanceid"].AsString(),
|
||||
amount = item["amount"].AsString(),
|
||||
missing = item["missing"].AsBoolean()
|
||||
});
|
||||
}
|
||||
foreach (KeyValue item in trade["items_to_receive"].Children) {
|
||||
tradeOffer.items_to_receive.Add(new SteamItem {
|
||||
appid = item["appid"].AsString(),
|
||||
contextid = item["contextid"].AsString(),
|
||||
assetid = item["assetid"].AsString(),
|
||||
currencyid = item["currencyid"].AsString(),
|
||||
classid = item["classid"].AsString(),
|
||||
instanceid = item["instanceid"].AsString(),
|
||||
amount = item["amount"].AsString(),
|
||||
missing = item["missing"].AsBoolean()
|
||||
});
|
||||
}
|
||||
result.Add(tradeOffer);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal async Task<bool> AcceptTradeOffer(ulong tradeID) {
|
||||
if (tradeID == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string sessionID;
|
||||
if (!SteamCookieDictionary.TryGetValue("sessionid", out sessionID)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
string referer = "https://steamcommunity.com/tradeoffer/" + tradeID + "/";
|
||||
string request = referer + "accept";
|
||||
|
||||
Dictionary<string, string> postData = new Dictionary<string, string>() {
|
||||
{"sessionid", sessionID},
|
||||
{"serverid", "1"},
|
||||
{"tradeofferid", tradeID.ToString()}
|
||||
};
|
||||
|
||||
return await Utilities.UrlPostRequest(request, postData, SteamCookieDictionary, referer).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal bool DeclineTradeOffer(ulong tradeID) {
|
||||
if (tradeID == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
KeyValue response;
|
||||
using (dynamic iEconService = WebAPI.GetInterface("IEconService")) {
|
||||
// Timeout
|
||||
iEconService.Timeout = Timeout;
|
||||
|
||||
try {
|
||||
response = iEconService.DeclineTradeOffer(
|
||||
key: ApiKey,
|
||||
tradeofferid: tradeID.ToString(),
|
||||
method: WebRequestMethods.Http.Post,
|
||||
secure: true
|
||||
);
|
||||
} catch (Exception e) {
|
||||
Logging.LogGenericException(Bot.BotName, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return response != null; // Steam API doesn't respond with any error code, assume any response is a success
|
||||
}
|
||||
|
||||
internal async Task LeaveClan(ulong clanID) {
|
||||
if (clanID == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
string sessionID;
|
||||
if (!SteamCookieDictionary.TryGetValue("sessionid", out sessionID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
string request = GetHomeProcess();
|
||||
Dictionary<string, string> postData = new Dictionary<string, string>() {
|
||||
{"sessionID", sessionID},
|
||||
{"action", "leaveGroup"},
|
||||
{"groupId", clanID.ToString()}
|
||||
};
|
||||
await Utilities.UrlPostRequest(request, postData, SteamCookieDictionary).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal async Task<HtmlDocument> GetBadgePage(int page) {
|
||||
HtmlDocument result = null;
|
||||
if (SteamID != 0 && page != 0) {
|
||||
result = await Utilities.UrlToHtmlDocument("http://steamcommunity.com/profiles/" + SteamID + "/badges?p=" + page, SteamCookieDictionary).ConfigureAwait(false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal async Task<HtmlDocument> GetGameCardsPage(ulong appID) {
|
||||
HtmlDocument result = null;
|
||||
if (SteamID != 0 && appID != 0) {
|
||||
result = await Utilities.UrlToHtmlDocument("http://steamcommunity.com/profiles/" + SteamID + "/gamecards/" + appID, SteamCookieDictionary).ConfigureAwait(false);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
336
ArchiSteamFarm/Bot.cs
Normal file
336
ArchiSteamFarm/Bot.cs
Normal file
|
@ -0,0 +1,336 @@
|
|||
using SteamKit2;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal class Bot {
|
||||
private const byte CallbackSleep = 100; // In miliseconds
|
||||
|
||||
private readonly Dictionary<string, string> Config = new Dictionary<string, string>();
|
||||
|
||||
internal readonly string BotName;
|
||||
private readonly string ConfigFile;
|
||||
private readonly string SentryFile;
|
||||
|
||||
private readonly CardsFarmer CardsFarmer;
|
||||
|
||||
internal ulong BotID { get; private set; }
|
||||
private string AuthCode, TwoFactorAuth;
|
||||
|
||||
internal ArchiHandler ArchiHandler { get; private set; }
|
||||
internal ArchiWebHandler ArchiWebHandler { get; private set; }
|
||||
internal CallbackManager CallbackManager { get; private set; }
|
||||
internal SteamClient SteamClient { get; private set; }
|
||||
internal SteamFriends SteamFriends { get; private set; }
|
||||
internal SteamUser SteamUser { get; private set; }
|
||||
internal Trading Trading { get; private set; }
|
||||
|
||||
// Config variables
|
||||
private bool Enabled { get { return bool.Parse(Config["Enabled"]); } }
|
||||
private string SteamLogin { get { return Config["SteamLogin"]; } }
|
||||
private string SteamPassword { get { return Config["SteamPassword"]; } }
|
||||
private string SteamNickname { get { return Config["SteamNickname"]; } }
|
||||
private string SteamApiKey { get { return Config["SteamApiKey"]; } }
|
||||
internal ulong SteamMasterID { get { return ulong.Parse(Config["SteamMasterID"]); } }
|
||||
internal ulong SteamMasterClanID { get { return ulong.Parse(Config["SteamMasterClanID"]); } }
|
||||
|
||||
internal Bot (string botName) {
|
||||
BotName = botName;
|
||||
CardsFarmer = new CardsFarmer(this);
|
||||
|
||||
ConfigFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".xml");
|
||||
SentryFile = Path.Combine(Program.ConfigDirectoryPath, BotName + ".bin");
|
||||
|
||||
ReadConfig();
|
||||
|
||||
if (!Enabled) {
|
||||
return;
|
||||
}
|
||||
Start();
|
||||
}
|
||||
|
||||
private void ReadConfig() {
|
||||
using (XmlReader reader = XmlReader.Create(ConfigFile)) {
|
||||
while (reader.Read()) {
|
||||
if (reader.NodeType != XmlNodeType.Element) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string key = reader.Name;
|
||||
if (string.IsNullOrEmpty(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
string value = reader.GetAttribute("value");
|
||||
if (string.IsNullOrEmpty(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Config.Add(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void Start() {
|
||||
if (SteamClient != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SteamClient = new SteamClient();
|
||||
|
||||
ArchiHandler = new ArchiHandler();
|
||||
SteamClient.AddHandler(ArchiHandler);
|
||||
|
||||
CallbackManager = new CallbackManager(SteamClient);
|
||||
CallbackManager.Subscribe<SteamClient.ConnectedCallback>(OnConnected);
|
||||
CallbackManager.Subscribe<SteamClient.DisconnectedCallback>(OnDisconnected);
|
||||
|
||||
SteamFriends = SteamClient.GetHandler<SteamFriends>();
|
||||
CallbackManager.Subscribe<SteamFriends.FriendsListCallback>(OnFriendsList);
|
||||
CallbackManager.Subscribe<SteamFriends.FriendMsgCallback>(OnFriendMsg);
|
||||
|
||||
SteamUser = SteamClient.GetHandler<SteamUser>();
|
||||
CallbackManager.Subscribe<SteamUser.AccountInfoCallback>(OnAccountInfo);
|
||||
CallbackManager.Subscribe<SteamUser.LoggedOffCallback>(OnLoggedOff);
|
||||
CallbackManager.Subscribe<SteamUser.LoggedOnCallback>(OnLoggedOn);
|
||||
CallbackManager.Subscribe<SteamUser.UpdateMachineAuthCallback>(OnMachineAuth);
|
||||
|
||||
CallbackManager.Subscribe<ArchiHandler.NotificationCallback>(OnNotification);
|
||||
CallbackManager.Subscribe<ArchiHandler.PurchaseResponseCallback>(OnPurchaseResponse);
|
||||
|
||||
ArchiWebHandler = new ArchiWebHandler(this, SteamApiKey);
|
||||
Trading = new Trading(this);
|
||||
|
||||
SteamClient.Connect();
|
||||
Task.Run(() => HandleCallbacks());
|
||||
}
|
||||
|
||||
internal void Stop() {
|
||||
if (SteamClient == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SteamClient.Disconnect();
|
||||
SteamClient = null;
|
||||
CallbackManager = null;
|
||||
}
|
||||
|
||||
internal void PlayGame(params ulong[] gameIDs) {
|
||||
ArchiHandler.PlayGames(gameIDs);
|
||||
}
|
||||
|
||||
private void HandleCallbacks() {
|
||||
TimeSpan timeSpan = TimeSpan.FromMilliseconds(CallbackSleep);
|
||||
while (CallbackManager != null) {
|
||||
CallbackManager.RunWaitCallbacks(timeSpan);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnConnected(SteamClient.ConnectedCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback.Result != EResult.OK) {
|
||||
Logging.LogGenericError(BotName, "Unable to connect to Steam: " + callback.Result);
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo(BotName, "Connected to Steam!");
|
||||
|
||||
byte[] sentryHash = null;
|
||||
if (File.Exists(SentryFile)) {
|
||||
byte[] sentryFileContent = File.ReadAllBytes(SentryFile);
|
||||
sentryHash = CryptoHelper.SHAHash(sentryFileContent);
|
||||
}
|
||||
|
||||
SteamUser.LogOn(new SteamUser.LogOnDetails {
|
||||
Username = SteamLogin,
|
||||
Password = SteamPassword,
|
||||
AuthCode = AuthCode,
|
||||
TwoFactorCode = TwoFactorAuth,
|
||||
SentryFileHash = sentryHash
|
||||
});
|
||||
}
|
||||
|
||||
private void OnDisconnected(SteamClient.DisconnectedCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericWarning(BotName, "Disconnected from Steam, reconnecting...");
|
||||
Thread.Sleep(TimeSpan.FromMilliseconds(CallbackSleep));
|
||||
SteamClient.Connect();
|
||||
}
|
||||
|
||||
private void OnFriendsList(SteamFriends.FriendsListCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var friend in callback.FriendList) {
|
||||
if (friend.Relationship != EFriendRelationship.RequestRecipient) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SteamID steamID = friend.SteamID;
|
||||
switch (steamID.AccountType) {
|
||||
case EAccountType.Clan:
|
||||
//ArchiHandler.AcceptClanInvite(steamID);
|
||||
break;
|
||||
default:
|
||||
if (steamID == SteamMasterID) {
|
||||
SteamFriends.AddFriend(steamID);
|
||||
} else {
|
||||
SteamFriends.RemoveFriend(steamID);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnFriendMsg(SteamFriends.FriendMsgCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback.EntryType != EChatEntryType.ChatMsg) {
|
||||
return;
|
||||
}
|
||||
|
||||
ulong steamID = callback.Sender;
|
||||
if (steamID != SteamMasterID) {
|
||||
return;
|
||||
}
|
||||
|
||||
string message = callback.Message;
|
||||
if (string.IsNullOrEmpty(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.Length == 17 && message[5] == '-' && message[11] == '-') {
|
||||
ArchiHandler.RedeemKey(message);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAccountInfo(SteamUser.AccountInfoCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SteamFriends.SetPersonaState(EPersonaState.Online);
|
||||
}
|
||||
|
||||
private void OnLoggedOff(SteamUser.LoggedOffCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo(BotName, "Logged off of Steam: " + callback.Result);
|
||||
}
|
||||
|
||||
private async void OnLoggedOn(SteamUser.LoggedOnCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (callback.ClientSteamID != 0) {
|
||||
BotID = callback.ClientSteamID;
|
||||
}
|
||||
|
||||
EResult result = callback.Result;
|
||||
switch (result) {
|
||||
case EResult.AccountLogonDenied:
|
||||
AuthCode = Program.GetSteamGuardCode(SteamLogin, false);
|
||||
break;
|
||||
case EResult.AccountLoginDeniedNeedTwoFactor:
|
||||
TwoFactorAuth = Program.GetSteamGuardCode(SteamLogin, true);
|
||||
break;
|
||||
case EResult.OK:
|
||||
Logging.LogGenericInfo(BotName, "Successfully logged on!");
|
||||
SteamFriends.SetPersonaName(SteamNickname);
|
||||
ArchiWebHandler.Init(SteamClient, callback.WebAPIUserNonce, callback.VanityURL);
|
||||
|
||||
ulong clanID = SteamMasterClanID;
|
||||
if (clanID != 0) {
|
||||
SteamFriends.JoinChat(clanID);
|
||||
}
|
||||
|
||||
await CardsFarmer.StartFarming().ConfigureAwait(false);
|
||||
break;
|
||||
default:
|
||||
Logging.LogGenericWarning(BotName, "Unable to login to Steam: " + callback.Result + " / " + callback.ExtendedResult + ", retrying...");
|
||||
Stop();
|
||||
Thread.Sleep(5000);
|
||||
Start();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMachineAuth(SteamUser.UpdateMachineAuthCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Logging.LogGenericInfo(BotName, "Updating sentryfile...");
|
||||
|
||||
int fileSize;
|
||||
byte[] sentryHash;
|
||||
|
||||
using (FileStream fileStream = File.Open(SentryFile, FileMode.OpenOrCreate, FileAccess.ReadWrite)) {
|
||||
fileStream.Seek(callback.Offset, SeekOrigin.Begin);
|
||||
fileStream.Write(callback.Data, 0, callback.BytesToWrite);
|
||||
fileSize = (int) fileStream.Length;
|
||||
|
||||
fileStream.Seek(0, SeekOrigin.Begin);
|
||||
using (SHA1CryptoServiceProvider sha = new SHA1CryptoServiceProvider()) {
|
||||
sentryHash = sha.ComputeHash(fileStream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Inform the steam servers that we're accepting this sentry file
|
||||
SteamUser.SendMachineAuthResponse(new SteamUser.MachineAuthDetails {
|
||||
JobID = callback.JobID,
|
||||
FileName = callback.FileName,
|
||||
BytesWritten = callback.BytesToWrite,
|
||||
FileSize = fileSize,
|
||||
Offset = callback.Offset,
|
||||
Result = EResult.OK,
|
||||
LastError = 0,
|
||||
OneTimePassword = callback.OneTimePassword,
|
||||
SentryFileHash = sentryHash,
|
||||
});
|
||||
}
|
||||
|
||||
private void OnNotification(ArchiHandler.NotificationCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (callback.NotificationType) {
|
||||
case ArchiHandler.NotificationCallback.ENotificationType.Trading:
|
||||
Trading.CheckTrades();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnPurchaseResponse(ArchiHandler.PurchaseResponseCallback callback) {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var purchaseResult = callback.PurchaseResult;
|
||||
SteamFriends.SendChatMessage(SteamMasterID, EChatEntryType.ChatMsg, "Status: " + purchaseResult);
|
||||
|
||||
if (purchaseResult == ArchiHandler.PurchaseResponseCallback.EPurchaseResult.OK) {
|
||||
await CardsFarmer.StartFarming().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
47
ArchiSteamFarm/CMsgClientClanInviteAction.cs
Normal file
47
ArchiSteamFarm/CMsgClientClanInviteAction.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
using SteamKit2;
|
||||
using SteamKit2.Internal;
|
||||
using System.IO;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
/// <summary>
|
||||
/// Message used to Accept or Decline a group(clan) invite.
|
||||
/// </summary>
|
||||
internal sealed class CMsgClientClanInviteAction : ISteamSerializableMessage, ISteamSerializable {
|
||||
EMsg ISteamSerializableMessage.GetEMsg() {
|
||||
return EMsg.ClientAcknowledgeClanInvite;
|
||||
}
|
||||
|
||||
public CMsgClientClanInviteAction() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Group invited to.
|
||||
/// </summary>
|
||||
internal ulong GroupID = 0;
|
||||
|
||||
/// <summary>
|
||||
/// To accept or decline the invite.
|
||||
/// </summary>
|
||||
internal bool AcceptInvite = true;
|
||||
|
||||
void ISteamSerializable.Serialize(Stream stream) {
|
||||
try {
|
||||
BinaryWriter binaryWriter = new BinaryWriter(stream);
|
||||
binaryWriter.Write(GroupID);
|
||||
binaryWriter.Write(AcceptInvite);
|
||||
} catch {
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
|
||||
void ISteamSerializable.Deserialize(Stream stream) {
|
||||
try {
|
||||
BinaryReader binaryReader = new BinaryReader(stream);
|
||||
GroupID = binaryReader.ReadUInt64();
|
||||
AcceptInvite = binaryReader.ReadBoolean();
|
||||
} catch {
|
||||
throw new IOException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
109
ArchiSteamFarm/CardsFarmer.cs
Normal file
109
ArchiSteamFarm/CardsFarmer.cs
Normal file
|
@ -0,0 +1,109 @@
|
|||
using HtmlAgilityPack;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal class CardsFarmer {
|
||||
private readonly Bot Bot;
|
||||
private bool NowFarming;
|
||||
private readonly AutoResetEvent AutoResetEvent = new AutoResetEvent(false);
|
||||
|
||||
internal CardsFarmer(Bot bot) {
|
||||
Bot = bot;
|
||||
}
|
||||
|
||||
internal async Task StartFarming() {
|
||||
// Find the number of badge pages
|
||||
HtmlDocument badgesDocument = await Bot.ArchiWebHandler.GetBadgePage(1).ConfigureAwait(false);
|
||||
if (badgesDocument == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var maxPages = 1;
|
||||
HtmlNodeCollection badgesPagesNodeCollection = badgesDocument.DocumentNode.SelectNodes("//a[@class='pagelink']");
|
||||
if (badgesPagesNodeCollection != null) {
|
||||
maxPages = (byte) (badgesPagesNodeCollection.Count / 2 + 1); // Don't do this at home
|
||||
}
|
||||
|
||||
// Find APPIDs we need to farm
|
||||
List<uint> appIDs = new List<uint>();
|
||||
for (var page = 1; page <= maxPages; page++) {
|
||||
if (page > 1) { // Because we fetched page number 1 already
|
||||
badgesDocument = await Bot.ArchiWebHandler.GetBadgePage(page).ConfigureAwait(false);
|
||||
if (badgesDocument == null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
HtmlNodeCollection badgesPageNodes = badgesDocument.DocumentNode.SelectNodes("//a[@class='btn_green_white_innerfade btn_small_thin']");
|
||||
if (badgesPageNodes == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (HtmlNode badgesPageNode in badgesPageNodes) {
|
||||
string steamLink = badgesPageNode.GetAttributeValue("href", null);
|
||||
if (steamLink == null) {
|
||||
page = maxPages; // Break from outer loop
|
||||
break;
|
||||
}
|
||||
|
||||
uint appID = (uint) Utilities.OnlyNumbers(steamLink);
|
||||
if (appID == 0) {
|
||||
page = maxPages; // Break from outer loop
|
||||
break;
|
||||
}
|
||||
|
||||
appIDs.Add(appID);
|
||||
}
|
||||
}
|
||||
|
||||
// Start farming
|
||||
while (appIDs.Count > 0) {
|
||||
uint appID = appIDs[0];
|
||||
if (await Farm(appID).ConfigureAwait(false)) {
|
||||
appIDs.Remove(appID);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool?> ShouldFarm(ulong appID) {
|
||||
bool? result = null;
|
||||
HtmlDocument gamePageDocument = await Bot.ArchiWebHandler.GetGameCardsPage(appID).ConfigureAwait(false);
|
||||
if (gamePageDocument != null) {
|
||||
HtmlNode gamePageNode = gamePageDocument.DocumentNode.SelectSingleNode("//span[@class='progress_info_bold']");
|
||||
if (gamePageNode != null) {
|
||||
result = !gamePageNode.InnerText.Contains("No card drops");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<bool> Farm(ulong appID) {
|
||||
if (NowFarming) {
|
||||
AutoResetEvent.Set();
|
||||
Thread.Sleep(1000);
|
||||
AutoResetEvent.Reset();
|
||||
}
|
||||
|
||||
bool success = true;
|
||||
bool? keepFarming = await ShouldFarm(appID).ConfigureAwait(false);
|
||||
while (keepFarming == null || keepFarming.Value) {
|
||||
if (!NowFarming) {
|
||||
NowFarming = true;
|
||||
Bot.PlayGame(appID);
|
||||
}
|
||||
if (AutoResetEvent.WaitOne(1000 * 60 * 5)) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
keepFarming = await ShouldFarm(appID).ConfigureAwait(false);
|
||||
}
|
||||
Bot.PlayGame(0);
|
||||
NowFarming = false;
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
38
ArchiSteamFarm/Logging.cs
Normal file
38
ArchiSteamFarm/Logging.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal static class Logging {
|
||||
private static void Log(string message) {
|
||||
Console.WriteLine(DateTime.Now + " " + message);
|
||||
}
|
||||
|
||||
internal static void LogGenericError(string botName, string message, [CallerMemberName] string previousMethodName = "") {
|
||||
Log("[!!] ERROR: " + previousMethodName + "() <" + botName + "> " + message);
|
||||
}
|
||||
|
||||
internal static void LogGenericException(string botName, Exception exception, [CallerMemberName] string previousMethodName = "") {
|
||||
Log("[!] EXCEPTION: " + previousMethodName + "() <" + botName + "> " + exception.Message);
|
||||
}
|
||||
|
||||
internal static void LogGenericWarning(string botName, string message, [CallerMemberName] string previousMethodName = "") {
|
||||
Log("[!] WARNING: " + previousMethodName + "() <" + botName + "> " + message);
|
||||
}
|
||||
|
||||
internal static void LogGenericInfo(string botName, string message, [CallerMemberName] string previousMethodName = "") {
|
||||
Log("[*] INFO: " + previousMethodName + "() <" + botName + "> " + message);
|
||||
}
|
||||
|
||||
internal static void LogGenericDebug(string botName, string message, [CallerMemberName] string previousMethodName = "") {
|
||||
Log("[#] DEBUG: " + previousMethodName + "() <" + botName + "> " + message);
|
||||
}
|
||||
|
||||
internal static void LogGenericDebug(string message, [CallerMemberName] string previousMethodName = "") {
|
||||
LogGenericDebug("DEBUG", message, previousMethodName);
|
||||
}
|
||||
|
||||
internal static void LogNullError(string nullObjectName, [CallerMemberName] string previousMethodName = "") {
|
||||
LogGenericError(nullObjectName + " is null!", previousMethodName);
|
||||
}
|
||||
}
|
||||
}
|
58
ArchiSteamFarm/Program.cs
Normal file
58
ArchiSteamFarm/Program.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal static class Program {
|
||||
internal const string ConfigDirectoryPath = "config";
|
||||
private static readonly HashSet<Bot> Bots = new HashSet<Bot>();
|
||||
internal static readonly object ConsoleLock = new object();
|
||||
|
||||
internal static void Exit(int exitCode = 0) {
|
||||
ShutdownAllBots();
|
||||
Environment.Exit(exitCode);
|
||||
}
|
||||
|
||||
internal static string GetSteamGuardCode(string botLogin, bool twoFactorAuthentication) {
|
||||
lock (ConsoleLock) {
|
||||
if (twoFactorAuthentication) {
|
||||
Console.Write("<" + botLogin + "> Please enter your 2 factor auth code from your authenticator app: ");
|
||||
} else {
|
||||
Console.Write("<" + botLogin + "> Please enter the auth code sent to your email : ");
|
||||
}
|
||||
return Console.ReadLine();
|
||||
}
|
||||
}
|
||||
|
||||
private static void ShutdownAllBots() {
|
||||
lock (Bots) {
|
||||
foreach (Bot bot in Bots) {
|
||||
bot.Stop();
|
||||
}
|
||||
Bots.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private static void Main(string[] args) {
|
||||
for (var i = 0; i < 4 && !Directory.Exists(ConfigDirectoryPath); i++) {
|
||||
Directory.SetCurrentDirectory("..");
|
||||
}
|
||||
|
||||
if (!Directory.Exists(ConfigDirectoryPath)) {
|
||||
Logging.LogGenericError("Main", "Config directory doesn't exist!");
|
||||
Console.ReadLine();
|
||||
Exit(1);
|
||||
}
|
||||
|
||||
lock (Bots) {
|
||||
foreach (var configFile in Directory.EnumerateFiles(ConfigDirectoryPath, "*.xml")) {
|
||||
string botName = Path.GetFileNameWithoutExtension(configFile);
|
||||
Bots.Add(new Bot(botName));
|
||||
}
|
||||
}
|
||||
|
||||
Thread.Sleep(Timeout.Infinite);
|
||||
}
|
||||
}
|
||||
}
|
36
ArchiSteamFarm/Properties/AssemblyInfo.cs
Normal file
36
ArchiSteamFarm/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("ArchiSteamFarm")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("ArchiSteamFarm")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("35af7887-08b9-40e8-a5ea-797d8b60b30c")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
13
ArchiSteamFarm/SteamItem.cs
Normal file
13
ArchiSteamFarm/SteamItem.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
namespace ArchiSteamFarm {
|
||||
internal sealed class SteamItem {
|
||||
// REF: https://developer.valvesoftware.com/wiki/Steam_Web_API/IEconService
|
||||
internal string appid { get; set; }
|
||||
internal string contextid { get; set; }
|
||||
internal string assetid { get; set; }
|
||||
internal string currencyid { get; set; }
|
||||
internal string classid { get; set; }
|
||||
internal string instanceid { get; set; }
|
||||
internal string amount { get; set; }
|
||||
internal bool missing { get; set; }
|
||||
}
|
||||
}
|
41
ArchiSteamFarm/SteamTradeOffer.cs
Normal file
41
ArchiSteamFarm/SteamTradeOffer.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
using SteamKit2;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class SteamTradeOffer {
|
||||
// REF: https://developer.valvesoftware.com/wiki/Steam_Web_API/IEconService
|
||||
internal enum ETradeOfferState {
|
||||
Unknown,
|
||||
Invalid,
|
||||
Active,
|
||||
Accepted,
|
||||
Countered,
|
||||
Expired,
|
||||
Canceled,
|
||||
Declined,
|
||||
InvalidItems,
|
||||
EmailPending,
|
||||
EmailCanceled
|
||||
}
|
||||
|
||||
internal string tradeofferid { get; set; }
|
||||
internal int accountid_other { get; set; }
|
||||
internal string message { get; set; }
|
||||
internal int expiration_time { get; set; }
|
||||
internal ETradeOfferState trade_offer_state { get; set; }
|
||||
internal List<SteamItem> items_to_give { get; set; }
|
||||
internal List<SteamItem> items_to_receive { get; set; }
|
||||
internal bool is_our_offer { get; set; }
|
||||
internal int time_created { get; set; }
|
||||
internal int time_updated { get; set; }
|
||||
internal bool from_real_time_trade { get; set; }
|
||||
|
||||
// Extra
|
||||
internal ulong OtherSteamID64 {
|
||||
get {
|
||||
return new SteamID((uint) accountid_other, EUniverse.Public, EAccountType.Individual).ConvertToUInt64();
|
||||
}
|
||||
private set { }
|
||||
}
|
||||
}
|
||||
}
|
74
ArchiSteamFarm/Trading.cs
Normal file
74
ArchiSteamFarm/Trading.cs
Normal file
|
@ -0,0 +1,74 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal sealed class Trading {
|
||||
private Bot Bot;
|
||||
private volatile byte ParsingTasks = 0;
|
||||
private SemaphoreSlim semaphore = new SemaphoreSlim(1);
|
||||
|
||||
internal Trading(Bot bot) {
|
||||
Bot = bot;
|
||||
}
|
||||
|
||||
internal void CheckTrades() {
|
||||
if (ParsingTasks < 2) {
|
||||
ParsingTasks++;
|
||||
Task.Run(() => ParseActiveTrades());
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ParseActiveTrades() {
|
||||
await semaphore.WaitAsync().ConfigureAwait(false);
|
||||
|
||||
List<SteamTradeOffer> tradeOffers = Bot.ArchiWebHandler.GetTradeOffers();
|
||||
if (tradeOffers != null) {
|
||||
List<Task> tasks = new List<Task>();
|
||||
foreach (SteamTradeOffer tradeOffer in tradeOffers) {
|
||||
if (tradeOffer.trade_offer_state == SteamTradeOffer.ETradeOfferState.Active) {
|
||||
Task task = Task.Run(async () => {
|
||||
await ParseTrade(tradeOffer).ConfigureAwait(false);
|
||||
});
|
||||
tasks.Add(task);
|
||||
}
|
||||
}
|
||||
|
||||
await Task.WhenAll(tasks).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
ParsingTasks--;
|
||||
semaphore.Release();
|
||||
}
|
||||
|
||||
private async Task ParseTrade(SteamTradeOffer tradeOffer) {
|
||||
if (tradeOffer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ulong tradeID;
|
||||
if (!ulong.TryParse(tradeOffer.tradeofferid, out tradeID)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ulong steamID = tradeOffer.OtherSteamID64;
|
||||
bool success = false;
|
||||
bool tradeAccepted = false;
|
||||
|
||||
if (tradeOffer.items_to_give.Count == 0 || steamID == Bot.SteamMasterID) {
|
||||
tradeAccepted = true;
|
||||
success = await Bot.ArchiWebHandler.AcceptTradeOffer(tradeID).ConfigureAwait(false);
|
||||
} else {
|
||||
success = Bot.ArchiWebHandler.DeclineTradeOffer(tradeID);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
Logging.LogGenericWarning(Bot.BotName, "Response to trade " + tradeID + " failed!");
|
||||
}
|
||||
|
||||
if (tradeAccepted && success) {
|
||||
// Do whatever we want with success
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
117
ArchiSteamFarm/Utilities.cs
Normal file
117
ArchiSteamFarm/Utilities.cs
Normal file
|
@ -0,0 +1,117 @@
|
|||
using HtmlAgilityPack;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ArchiSteamFarm {
|
||||
internal static class Utilities {
|
||||
internal static ulong OnlyNumbers(string inputString) {
|
||||
if (string.IsNullOrEmpty(inputString)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
string resultString;
|
||||
try {
|
||||
Regex regexObj = new Regex(@"[^\d]");
|
||||
resultString = regexObj.Replace(inputString, "");
|
||||
} catch (ArgumentException e) {
|
||||
Logging.LogGenericException("Utilities", e);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ulong result = ulong.Parse(resultString, CultureInfo.InvariantCulture);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static async Task<HttpResponseMessage> UrlToHttpResponse(string websiteAddress, Dictionary<string, string> cookieVariables) {
|
||||
HttpResponseMessage result = null;
|
||||
if (!string.IsNullOrEmpty(websiteAddress)) {
|
||||
try {
|
||||
using (HttpClientHandler clientHandler = new HttpClientHandler { UseCookies = false }) {
|
||||
using (HttpClient client = new HttpClient(clientHandler)) {
|
||||
client.Timeout = TimeSpan.FromSeconds(10);
|
||||
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, websiteAddress);
|
||||
if (cookieVariables != null) {
|
||||
StringBuilder cookie = new StringBuilder();
|
||||
foreach (KeyValuePair<string, string> cookieVariable in cookieVariables) {
|
||||
cookie.Append(cookieVariable.Key + "=" + cookieVariable.Value + ";");
|
||||
}
|
||||
requestMessage.Headers.Add("Cookie", cookie.ToString());
|
||||
}
|
||||
HttpResponseMessage responseMessage = await client.SendAsync(requestMessage).ConfigureAwait(false);
|
||||
if (responseMessage != null) {
|
||||
responseMessage.EnsureSuccessStatusCode();
|
||||
result = responseMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static async Task<HttpResponseMessage> UrlToHttpResponse(string websiteAddress) {
|
||||
return await UrlToHttpResponse(websiteAddress, null).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal static async Task<HtmlDocument> UrlToHtmlDocument(string websiteAddress, Dictionary<string, string> cookieVariables) {
|
||||
HtmlDocument result = null;
|
||||
if (!string.IsNullOrEmpty(websiteAddress)) {
|
||||
try {
|
||||
HttpResponseMessage responseMessage = await UrlToHttpResponse(websiteAddress, cookieVariables).ConfigureAwait(false);
|
||||
if (responseMessage != null) {
|
||||
string source = await responseMessage.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
if (!string.IsNullOrEmpty(source)) {
|
||||
source = WebUtility.HtmlDecode(source);
|
||||
result = new HtmlDocument();
|
||||
result.LoadHtml(source);
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static async Task<HtmlDocument> UrlToHtmlDocument(string websiteAddress) {
|
||||
return await UrlToHtmlDocument(websiteAddress, null).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal static async Task<bool> UrlPostRequest(string request, Dictionary<string, string> postData, Dictionary<string, string> cookieVariables, string referer = null) {
|
||||
bool result = false;
|
||||
if (!string.IsNullOrEmpty(request)) {
|
||||
try {
|
||||
using (HttpClientHandler clientHandler = new HttpClientHandler { UseCookies = false }) {
|
||||
using (HttpClient client = new HttpClient(clientHandler)) {
|
||||
client.Timeout = TimeSpan.FromSeconds(15);
|
||||
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, request);
|
||||
requestMessage.Content = new FormUrlEncodedContent(postData);
|
||||
if (cookieVariables != null && cookieVariables.Count > 0) {
|
||||
StringBuilder cookie = new StringBuilder();
|
||||
foreach (KeyValuePair<string, string> cookieVariable in cookieVariables) {
|
||||
cookie.Append(cookieVariable.Key + "=" + cookieVariable.Value + ";");
|
||||
}
|
||||
requestMessage.Headers.Add("Cookie", cookie.ToString());
|
||||
}
|
||||
if (referer != null) {
|
||||
requestMessage.Headers.Referrer = new Uri(referer);
|
||||
}
|
||||
HttpResponseMessage responseMessage = await client.SendAsync(requestMessage).ConfigureAwait(false);
|
||||
if (responseMessage != null) {
|
||||
result = responseMessage.IsSuccessStatusCode;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
16
ArchiSteamFarm/config/example.xml
Normal file
16
ArchiSteamFarm/config/example.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
|
||||
<!-- Every bot should have it's own unique .xml configuration file, this is example on which you can base on -->
|
||||
|
||||
<Enabled value="true"/> <!-- Master switch to turn account on and off -->
|
||||
|
||||
<!-- Steam -->
|
||||
<SteamLogin value="Foo"/> <!-- This is your steam login, the one you use for logging in to steam -->
|
||||
<SteamPassword value="Bar"/> <!-- This is your steam password, the one you use for logging in to steam -->
|
||||
<SteamNickname value="ArchiSteamFarmer"/> <!-- This is your steam nickname, the one you want to use for bot. Can be anything up to 32 characters -->
|
||||
<SteamApiKey value="FFFFFFFF"/> <!-- Get one at https://steamcommunity.com/dev/apikey -->
|
||||
<SteamMasterID value="76561198006963719"/> <!-- This is steamID of the master, aka the "root" user being able to execute any command -->
|
||||
<SteamMasterClanID value="0"/> <!-- If you want from the bot to join particular chat of given clan, set it here, otherwise leave at 0 -->
|
||||
|
||||
</configuration>
|
6
ArchiSteamFarm/packages.config
Normal file
6
ArchiSteamFarm/packages.config
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="HtmlAgilityPack" version="1.4.9" targetFramework="net45" />
|
||||
<package id="protobuf-net" version="2.0.0.668" targetFramework="net45" />
|
||||
<package id="SteamKit2" version="1.6.5" targetFramework="net45" />
|
||||
</packages>
|
BIN
packages/HtmlAgilityPack.1.4.9/HAPIcon.png
vendored
Normal file
BIN
packages/HtmlAgilityPack.1.4.9/HAPIcon.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 699 B |
BIN
packages/HtmlAgilityPack.1.4.9/HtmlAgilityPack.1.4.9.nupkg
vendored
Normal file
BIN
packages/HtmlAgilityPack.1.4.9/HtmlAgilityPack.1.4.9.nupkg
vendored
Normal file
Binary file not shown.
BIN
packages/HtmlAgilityPack.1.4.9/lib/Net20/HtmlAgilityPack.dll
vendored
Normal file
BIN
packages/HtmlAgilityPack.1.4.9/lib/Net20/HtmlAgilityPack.dll
vendored
Normal file
Binary file not shown.
2468
packages/HtmlAgilityPack.1.4.9/lib/Net20/HtmlAgilityPack.xml
vendored
Normal file
2468
packages/HtmlAgilityPack.1.4.9/lib/Net20/HtmlAgilityPack.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/HtmlAgilityPack.1.4.9/lib/Net40-client/HtmlAgilityPack.dll
vendored
Normal file
BIN
packages/HtmlAgilityPack.1.4.9/lib/Net40-client/HtmlAgilityPack.dll
vendored
Normal file
Binary file not shown.
2468
packages/HtmlAgilityPack.1.4.9/lib/Net40-client/HtmlAgilityPack.xml
vendored
Normal file
2468
packages/HtmlAgilityPack.1.4.9/lib/Net40-client/HtmlAgilityPack.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
2468
packages/HtmlAgilityPack.1.4.9/lib/Net40/HtmlAgilityPack.XML
vendored
Normal file
2468
packages/HtmlAgilityPack.1.4.9/lib/Net40/HtmlAgilityPack.XML
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/HtmlAgilityPack.1.4.9/lib/Net40/HtmlAgilityPack.dll
vendored
Normal file
BIN
packages/HtmlAgilityPack.1.4.9/lib/Net40/HtmlAgilityPack.dll
vendored
Normal file
Binary file not shown.
2468
packages/HtmlAgilityPack.1.4.9/lib/Net45/HtmlAgilityPack.XML
vendored
Normal file
2468
packages/HtmlAgilityPack.1.4.9/lib/Net45/HtmlAgilityPack.XML
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/HtmlAgilityPack.1.4.9/lib/Net45/HtmlAgilityPack.dll
vendored
Normal file
BIN
packages/HtmlAgilityPack.1.4.9/lib/Net45/HtmlAgilityPack.dll
vendored
Normal file
Binary file not shown.
BIN
packages/HtmlAgilityPack.1.4.9/lib/NetCore45/HtmlAgilityPack.dll
vendored
Normal file
BIN
packages/HtmlAgilityPack.1.4.9/lib/NetCore45/HtmlAgilityPack.dll
vendored
Normal file
Binary file not shown.
BIN
packages/HtmlAgilityPack.1.4.9/lib/NetCore45/HtmlAgilityPack.pri
vendored
Normal file
BIN
packages/HtmlAgilityPack.1.4.9/lib/NetCore45/HtmlAgilityPack.pri
vendored
Normal file
Binary file not shown.
1555
packages/HtmlAgilityPack.1.4.9/lib/NetCore45/HtmlAgilityPack.xml
vendored
Normal file
1555
packages/HtmlAgilityPack.1.4.9/lib/NetCore45/HtmlAgilityPack.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
Binary file not shown.
Binary file not shown.
BIN
packages/HtmlAgilityPack.1.4.9/lib/sl3-wp/_._
vendored
Normal file
BIN
packages/HtmlAgilityPack.1.4.9/lib/sl3-wp/_._
vendored
Normal file
Binary file not shown.
2299
packages/HtmlAgilityPack.1.4.9/lib/sl4/HtmlAgilityPack.XML
vendored
Normal file
2299
packages/HtmlAgilityPack.1.4.9/lib/sl4/HtmlAgilityPack.XML
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/HtmlAgilityPack.1.4.9/lib/sl4/HtmlAgilityPack.dll
vendored
Normal file
BIN
packages/HtmlAgilityPack.1.4.9/lib/sl4/HtmlAgilityPack.dll
vendored
Normal file
Binary file not shown.
2299
packages/HtmlAgilityPack.1.4.9/lib/sl5/HtmlAgilityPack.XML
vendored
Normal file
2299
packages/HtmlAgilityPack.1.4.9/lib/sl5/HtmlAgilityPack.XML
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/HtmlAgilityPack.1.4.9/lib/sl5/HtmlAgilityPack.dll
vendored
Normal file
BIN
packages/HtmlAgilityPack.1.4.9/lib/sl5/HtmlAgilityPack.dll
vendored
Normal file
Binary file not shown.
17
packages/HtmlAgilityPack.1.4.9/readme.txt
vendored
Normal file
17
packages/HtmlAgilityPack.1.4.9/readme.txt
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
----------------------------------------------------
|
||||
---------- Html Agility Pack Nuget Readme ----------
|
||||
----------------------------------------------------
|
||||
|
||||
----Silverlight 4 and Windows Phone 7.1+ projects-----
|
||||
To use XPATH features: System.Xml.Xpath.dll from the Silverlight 4 SDK must be referenced.
|
||||
This is normally found at
|
||||
%ProgramFiles(x86)%\Microsoft SDKs\Microsoft SDKs\Silverlight\v4.0\Libraries\Client
|
||||
or
|
||||
%ProgramFiles%\Microsoft SDKs\Microsoft SDKs\Silverlight\v4.0\Libraries\Client
|
||||
|
||||
----Silverlight 5 projects-----
|
||||
To use XPATH features: System.Xml.Xpath.dll from the Silverlight 5 SDK must be referenced.
|
||||
This is normally found at
|
||||
%ProgramFiles(x86)%\Microsoft SDKs\Microsoft SDKs\Silverlight\v5.0\Libraries\Client
|
||||
or
|
||||
%ProgramFiles%\Microsoft SDKs\Microsoft SDKs\Silverlight\v5.0\Libraries\Client
|
BIN
packages/SteamKit2.1.6.5/SteamKit2.1.6.5.nupkg
vendored
Normal file
BIN
packages/SteamKit2.1.6.5/SteamKit2.1.6.5.nupkg
vendored
Normal file
Binary file not shown.
BIN
packages/SteamKit2.1.6.5/lib/net40/SteamKit2.dll
vendored
Normal file
BIN
packages/SteamKit2.1.6.5/lib/net40/SteamKit2.dll
vendored
Normal file
Binary file not shown.
7751
packages/SteamKit2.1.6.5/lib/net40/SteamKit2.xml
vendored
Normal file
7751
packages/SteamKit2.1.6.5/lib/net40/SteamKit2.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
339
packages/SteamKit2.1.6.5/readme.txt
vendored
Normal file
339
packages/SteamKit2.1.6.5/readme.txt
vendored
Normal file
|
@ -0,0 +1,339 @@
|
|||
------------------------------------------------------------------------------
|
||||
v 1.6.5 Oct 17, 2015
|
||||
------------------------------------------------------------------------------
|
||||
* Added inventory service unified protobufs.
|
||||
* Added the ability to specify the client's prefered Cell ID in `LogOnDetails.CellID`. (pr #148)
|
||||
* `KeyValue` objects can now be serialized (both text and binary) to streams with `SaveToStream`.
|
||||
* Fixed an issue with `CDNClient` session initialization involving sessionid values.
|
||||
* Added setter for `KeyValue`'s indexer operator.
|
||||
* Added `ELeaderboardDisplayType` and various leaderboard retrieval functions to `SteamUserStats`. (pr #153)
|
||||
* Implemented machine id support for logon for when the Steam servers inevitably require it. (pr #152)
|
||||
* Fixed case where logging on with a different account could lead to an anonymous logon instead. (bug #160)
|
||||
* `SteamFriends.SetPersonaName` now supports `JobID`s and has a new associated callback: `PersonaChangeCallback`
|
||||
* Updated game-related GC messages and protobufs.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.6.4 Aug 03, 2015
|
||||
------------------------------------------------------------------------------
|
||||
* Added smarter server selection logic.
|
||||
* Added ability to load initial server list from Steam Directory Web API. See `SteamDirectory.Initialize`.
|
||||
* Added ability to persist internal server list. See Sample 7 for details.
|
||||
* Added `SteamFriends.InviteUserToChat`.
|
||||
* Added support in `SteamUser` for passwordless login with a login key.
|
||||
* Added `NumChatMembers`, `ChatRoomName` and `ChatMembers` to `ChatEnterCallback`.
|
||||
* Added new API for callback subscriptions, `CallbackManager.Subscribe`.
|
||||
* Added `SteamApps.RequestFreeLicense` to request Free On-Demand licences.
|
||||
* Exposed `ClientOSType` and `ClientLanguage` when logging in as a specific or as an anonymous user.
|
||||
* Fixed `KeyValue` binary deserialization returning a dummy parent node containing the actually deserialized `KeyValue`. You must change to the new `Try`-prefixed methods to adopt the fixed behavior.
|
||||
* Updated Steam enums and protobufs.
|
||||
* Updated game-related GC messages and protobufs.
|
||||
|
||||
DEPRECATIONS
|
||||
* `ICallbackMsg.IsType<>` and `ICallbackMsg.Handle<>` are deprecated and will be removed soon in a future version of SteamKit. Please use `CallbackManager.Subscribe` instead.
|
||||
* `Callback<T>` is deprecated and will be removed in a future version of SteamKit. Please use `CallbackManager.Subscribe` instead.
|
||||
* `KeyValue.ReadAsBinary` and `KeyValue.LoadAsBinary` are deprecated and will be removed in a future version of SteamKit. Use the `Try`-prefixed methods as outlined above.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.6.3 Jun 20, 2015
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Added support for parsing older representations of Steam3 Steam IDs such as those from Counter-Strike: Global Offensive, i.e. `[M:1:123(456)]`.
|
||||
* Steam IDs parsed from Steam3 string representations will now have the correct instance ID set.
|
||||
* KeyValues can now be serialized to binary, however all values will be serialized as the string type.
|
||||
* Improved reliability of TCP connections to the CM and UFS servers.
|
||||
* Added `UserInitiated` property to `SteamClient.DisconnectedCallback` and `UFSClient.DisconnectedCallback` to indicate whether a disconnect was caused by the user, or by another source (Steam servers, bad network connection).
|
||||
* Updated Steam protobufs.
|
||||
* Updated game-related GC messages and protobufs.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.6.2 Dec 16, 2014
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Fixed a crash when receiving a `ServiceMethod` message.
|
||||
* Fixed `ServiceMethodCallback.RpcName` having a leading '.' character (e.g. '.MethodName' instead of 'MethodName).
|
||||
* Fixed web responses in `CDNClient` not being closed, which could lead to running out of system resources.
|
||||
* Added error handling for `ClientMsgHandler`. Any unhandled exceptions will be logged to `DebugLog` and trigger `SteamClient` to disconnect.
|
||||
* Updated `EMsg` list.
|
||||
* Updated Steam protobufs.
|
||||
* Updated game-related GC messages and protobufs.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.6.1 Nov 30, 2014
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Added support for VZip when decompressing depot chunks.
|
||||
* Improved thread safety and error handling inside `TcpConnection`.
|
||||
* Added `DownloadDepotChunk` overload for consumers who insist on connecting to particular CDNs.
|
||||
* Updated `EResult` with the new field `NotModified`.
|
||||
* Updated `EMsg` list.
|
||||
* Updated `EOSType`.
|
||||
* The short names for Windows versions (e.g. `Win8` instead of `Windows8`) are preferred.
|
||||
* Addded `MacOS1010` for OS X 10.10 'Yosemite'
|
||||
* Removed various long-obsolete values from enums where the value was renamed.
|
||||
* Removed `EUniverse.RC`.
|
||||
* Updated game related GC messages and protobufs.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.6.0 Oct 11, 2014
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Updated EOSType for newer Linux and Windows versions.
|
||||
* A LoggedOnCallback with EResult.NoConnection is now posted when attempting to logon without being
|
||||
connected to the remote Steam server.
|
||||
* Fixed anonymous gameserver logon.
|
||||
* CDNClient.Server's constructor now accepts a DnsEndPoint.
|
||||
* Updated EResult with the following new fields: AccountLogonDeniedNeedTwoFactorCode, ItemDeleted,
|
||||
AccountLoginDeniedThrottle, TwoFactorCodeMismatch
|
||||
* Added public utility class for working with DateTime and unix epochs: DateUtils
|
||||
* Added GetSingleFileInfo, ShareFile and related callbacks for dealing with Steam cloud files with the
|
||||
SteamCloud handler.
|
||||
* Fixed a potential crash when failing to properly deserialize network messages.
|
||||
* Updated EMsg list.
|
||||
* Refactored the internals of tcp connections to Steam servers to be more resiliant and threadsafe.
|
||||
* CallbackMsg.Handle will now return a boolean indiciating that the passed in callback matches the
|
||||
generic type parameter.
|
||||
* Added support for logging into accounts with two-factor auth enabled. See the
|
||||
SteamUser.LogOnDetails.TwoFactorCode field.
|
||||
* Updated the bootstrap list of Steam CM servers that SteamKit will initially attempt to connect to.
|
||||
* Added SteamFriends.FriendMsgEchoCallback for echoed messages sent to other logged in client
|
||||
instances.
|
||||
* Updated game related GC messages and protobufs.
|
||||
|
||||
BREAKING CHANGES
|
||||
* JobCallback API has been merged with Callback. For help with transitioning code, please see the following
|
||||
wiki notes: https://github.com/SteamRE/SteamKit/wiki/JobCallback-Transition.
|
||||
* UFSClient.UploadFileResponseCallback.JobID has been renamed to RemoteJobID in order to not conflict with
|
||||
CallbackMsg's new JobID member.
|
||||
* UFSClient.UploadDetails.JobID has been renamed to RemoteJobID.
|
||||
* CDNClient has been refactored to support multiple authdepot calls for a single instance of the client
|
||||
and to support CDN servers.
|
||||
* The following EResult fields have been renamed:
|
||||
PSNAccountNotLinked -> ExternalAccountUnlinked
|
||||
InvalidPSNTicket -> PSNTicketInvalid
|
||||
PSNAccountAlreadyLinked -> ExternalAccountAlreadyLinked
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.5.1 Mar 15, 2014
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Added a parameterless public constructor to DepotManifest.ChunkData to support serialization.
|
||||
* SteamWorkshop.RequestPublishedFileDetails has been obsoleted and is no longer supported. This functionality will be
|
||||
dropped in a future SteamKit release. See the the PublishedFile WebAPI service for a functional replacement.
|
||||
* Added the request and response messages for the PublishedFile service.
|
||||
* Fixed an unhandled exception when requesting metadata-only PICS product info.
|
||||
* Exposed the following additional fields in the LoggedOnCallback: VanityURL, NumLoginFailuresToMigrate, NumDisconnectsToMigrate.
|
||||
* Exposed the HTTP url details for PICS product info, see: PICSProductInfoCallback.PICSProductInfo.HttpUri and UseHttp.
|
||||
* Added EEconTradeResponse.InitiatorPasswordResetProbation and InitiatorNewDeviceCooldown.
|
||||
* Fixed SteamGameServer.LogOn and LogOnAnonymous sending the wrong message.
|
||||
* Added support for token authentication for game server logon.
|
||||
* Added the request and response messages for the GameServers service.
|
||||
* Added the ability to specify server type for game servers, see: SteamGameServer.SendStatus.
|
||||
* Exposed a few more fields on TradeResultCallback: NumDaysSteamGuardRequired, NumDaysNewDeviceCooldown,
|
||||
DefaultNumDaysPasswordResetProbation, NumDaysPasswordResetProbation.
|
||||
* Fixed being unable to download depot manifests.
|
||||
* Added SteamID.SetFromSteam3String.
|
||||
* Obsoleted SteamApps.SendGuestPass. This functionality will be dropped in a future SteamKit release.
|
||||
* Updated EResult with the following new fields: UnexpectedError, Disabled, InvalidCEGSubmission, RestrictedDevice.
|
||||
* Updated EMsg list.
|
||||
* Updated game related GC messages.
|
||||
|
||||
BREAKING CHANGES
|
||||
* Fixed ServiceMethodResponse.RpcName containing a leading '.'.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.5.0 Oct 26, 2013
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Added DebugLog.ClearListeners().
|
||||
* Added WebAPI.AsyncInterface, a .NET TPL'd version of WebAPI.Interface.
|
||||
* Added SteamClient.ServerListCallback.
|
||||
* Added SteamUser.WebAPIUserNonceCallback, and a method to request it: SteamUser.RequestWebAPIUserNonce().
|
||||
* Added SteamUser.MarketingMessageCallback.
|
||||
* Added a new member to CMClient: CellID. This is the Steam server's recommended CellID.
|
||||
* Added the ability to specify AccountID in SteamUser.LogOnDetails.
|
||||
* Added a helper API to SteamUnifiedMessages for service messages.
|
||||
* Fixed issue where CallbackManager was not triggering for JobCallback<T>.
|
||||
* Fixed unhandled protobuf-net exception when (de)serializing messages with enums that are out of date.
|
||||
* Fixed a bug where all WebAPI.Interface requests would instantly timeout.
|
||||
* Fixed Manifest.HashFileName and Manifest.HashContent being swapped.
|
||||
* Updated Emsg list.
|
||||
* Updated game related GC messages.
|
||||
* Updated the following enums: EResult, EChatEntryType, EAccountFlags, EClanPermission, EFriendFlags, EOSType, EServerType,
|
||||
EBillingType, EChatMemberStateChange, EDepotFileFlag, EEconTradeResponse.
|
||||
* The following members of EChatRoomEnterResponse have been obsoleted: NoRankingDataLobby, NoRankingDataUser, RankOutOfRange.
|
||||
* EOSType.Win7 has been obsoleted and renamed to EOSType.Windows7.
|
||||
* EEconTradeResponse.InitiatorAlreadyTrading has been obsoleted and renamed to EEconTradeResponse.AlreadyTrading.
|
||||
* EEconTradeResponse.Error has been obsoleted and renamed to EEconTradeResponse.AlreadyHasTradeRequest.
|
||||
* EEconTradeResponse.Timeout has been obsoleted and renamed to EEconTradeResponse.NoResponse.
|
||||
* EChatEntryType.Emote has been obsoleted. Emotes are no longer supported by Steam.
|
||||
* SteamFriends.ProfileInfoCallback.RecentPlaytime has been obsoleted. This data is no longer sent by the Steam servers.
|
||||
* Updated to latest protobuf-net.
|
||||
|
||||
BREAKING CHANGES
|
||||
* SteamUser.LoggedOnCallback.Steam2Ticket is now exposed as a byte array, rather than a Steam2Ticket object.
|
||||
* The SteamKit2.Blob namespace and all related classes have been removed.
|
||||
* Support for Steam2 servers and the various classes within SteamKit have been removed.
|
||||
* CDNClient has been heavily refactored to be more developer friendly.
|
||||
* All DateTimes in callbacks are now DateTimeKind.Utc.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.4.1 Jul 15, 2013
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Added the ability to manipulate UFS (Steam cloud) files with UFSClient.
|
||||
* Added SteamScreenshots handler for interacting with user screenshots.
|
||||
* Added an optional parameter to SteamID.Render() to render SteamIDs to their Steam3 representations.
|
||||
* Added the ability to specify the timeout of WebAPI requests with Interface.Timeout.
|
||||
* The RSACrypto and KeyDictionary utility classes are now accessible to consumers.
|
||||
* Updated EMsg list.
|
||||
* Updated game related GC messages.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.4.0 Jun 08, 2013
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* KeyValues now correctly writes out strings in UTF8.
|
||||
* Fixed an exception that could occur with an invalid string passed to SteamID's constructor.
|
||||
* Added SteamFriends.ClanStateCallback.
|
||||
* Added EPersonaStateFlag. This value is now exposed in SteamFriends.PersonaStateCallback.
|
||||
* Added MsgClientCreateChat and MsgClientCreateChatResponse messages.
|
||||
* Added GlobalID base class for globally unique values (such as JobIDs, UGCHandles) in Steam.
|
||||
* Updated EMsg list.
|
||||
* Updated game related GC messages.
|
||||
* Added initial support for the Steam Cloud file system with UFSClient. This feature should be considered unstable and may
|
||||
have breaking changes in the future.
|
||||
|
||||
BREAKING CHANGES
|
||||
* STATIC_CALLBACKS builds of SteamKit have now been completely removed.
|
||||
* Message classes for unified messages have moved namespaces from SteamKit2.Steamworks to SteamKit2.Unified.Internal.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.3.1 Mar 10, 2013
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Fixed issue where the avatar hash of a clan was always null.
|
||||
* Introduced better handling of networking related cryptographic exceptions.
|
||||
* Updated EMsg list.
|
||||
* Exposed SteamClient.JobCallback<T> for external consumers.
|
||||
* STATIC_CALLBACK builds of SteamKit and related code has been obsoleted and will be removed in the next version.
|
||||
* Implemented GameID.ToString().
|
||||
* Implemented game pass sending and recieving with SteamApps.SendGuestPass(), SteamApps.GuestPassListCallback, and
|
||||
SteamApps.SendGuestPassCallback.
|
||||
* Implemented requesting Steam community profile info with SteamFriends.RequestProfileInfo(), and SteamFriends.ProfileInfoCallback
|
||||
* CMClient now exposes a ConnectionTimeout field to control the timeout when connecting to Steam. The default timeout is 5 seconds.
|
||||
* Updated the internal list of CM servers to help alleviate some issues with connecting to dead servers.
|
||||
* Implemented SteamClient.CMListCallback to retrieve the current list of CM servers.
|
||||
* Implemented initial support for unified messages through the SteamUnifiedMessages handler.
|
||||
|
||||
BREAKING CHANGES
|
||||
* CMClient.Connect has been refactored significantly. It is no longer possible to use unencrypted connections. The Connect function
|
||||
now accepts an IPEndPoint to allow consumers to specify which Steam server they wish to connect to. Along with this,
|
||||
CMClient.Servers is now exposed as a collection of IPEndPoints, instead of IPAddresses.
|
||||
* SteamApps.PackageInfoCallback now exposes the immediate child KeyValue for the data, to be more consistent with
|
||||
SteamApps.AppInfoCallback.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.3.0 Jan 16, 2013
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Fixed case where friend and chat messages were incorrectly trimming the last character.
|
||||
* Steam2 ServerClient now exposes a IsConnected property.
|
||||
* Steam2 ContentServerClient can now optionally not perform a server handshake when opening a storage session.
|
||||
* Added various enums: EClanPermission, EMarketingMessageFlags, ENewsUpdateType, ESystemIMType, EChatFlags,
|
||||
ERemoteStoragePlatform, EDRMBlobDownloadType, EDRMBlobDownloadErrorDetail, EClientStat, EClientStatAggregateMethod,
|
||||
ELeaderboardDataRequest, ELeaderboardSortMethod, ELeaderboardUploadScoreMethod, and EChatPermission.
|
||||
* Fixed case where SteamKit was throwing an unhandled exception during Steam3 tcp connection teardown.
|
||||
* Added PICS support to the SteamApps handler: PICSGetAccessTokens, PICSGetChangesSince, and PICSGetProductInfo.
|
||||
* Added anonymous download support to CDNClient.
|
||||
* Updated the following enums: EMsg, EUniverse, EChatEntryType, EPersonaState, EFriendRelationship, EFriendFlags,
|
||||
EClientPersonaStateFlag, ELicenseFlags, ELicenseType, EPaymentMethod, EIntroducerRouting, EClanRank, EClanRelationship,
|
||||
EAppInfoSection, EContentDownloadSourceType, EOSType, EServerType, ECurrencyCode, EDepotFileFlag, EEconTradeResponse,
|
||||
ESystemIMType, ERemoteStoragePlatform, and EResult.
|
||||
* Exposed the following properties in SteamUser.LoggedOnCallback: CellIDPingThreshold, UsePICS, WebAPIUserNonce, and
|
||||
IPCountryCode.
|
||||
* Fixed case where SteamKit was incorrectly handling certain logoff messages during Steam server unavailability.
|
||||
* Fixed potential crash in Steam2 ContentServerClient when opening a storage session.
|
||||
* Updated to latest protobuf-net.
|
||||
|
||||
BREAKING CHANGES
|
||||
* DepotManifest.ChunkData.CRC is now named DepotManifest.ChunkData.Checksum.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.2.2 Nov 11, 2012
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Fixed critical issue that occured while serializing protobuf messages.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.2.1 Nov 11, 2012
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Added EPersonaState.LookingToTrade and EPersonaState.LookingToPlay.
|
||||
* Added SteamFriends.UnbanChatMember.
|
||||
* Removed GeneralDSClient.GetAuthServerList as Steam2 auth servers no longer exist.
|
||||
* Removed dependency on Classless.Hasher.
|
||||
* Updated to latest protobuf-net.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.2.0 Nov 04, 2012
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Fixed issue where LoginKeyCallback was being passed incorrect data.
|
||||
* Fixed ClientGCMsg PacketMessage constructor.
|
||||
* WebAPI list and array parameters are now accepted and flattened to x[n]=y format.
|
||||
* Fixed KeyValue issue when multiple duplicate children exist.
|
||||
* Updated protobuf definitions for internal message classes to their latest definitions.
|
||||
* Updated EMsgs.
|
||||
* Fixed critical MsgMulti handling.
|
||||
* Added EEconTradeResponse.
|
||||
* Added SteamTrading client message handler.
|
||||
* Modified Steam3 TCP socket shutdown to play well with Mono.
|
||||
* Modified CMClient.Connect method to be properly async.
|
||||
* Implemented friend blocking/unblocking with SteamFriends.IgnoreFriend and SteamFriends.IgnoreFriendCallback.
|
||||
* Fixed gameserver logon.
|
||||
* Local user is now given the persona name [unassigned] before SteamUser.AccountInfoCallback comes in.
|
||||
* Updated SteamKit2's bootstrap CM list, this should reduce how often SK2 will connect to an offline/dead server.
|
||||
* Steam2 ServerClient's now expose a ConnectionTimeout member.
|
||||
|
||||
BREAKING CHANGES
|
||||
* Dota GC EMsgs are now longer located in SteamKit2.GC.Dota.EGCMsg, they are now in SteamKit2.Gc.Dota.Internal.EDOTAGCMsg.
|
||||
* Base GC EMsgs are now longer located in SyteamKit2.GC.EGCMsgBase, they are now in multiple enums in the SteamKit2.GC.Internal namespace:
|
||||
EGCBaseMsg, EGCSystemMsg, EGCSharedMsg, ESOMsg, EGCItemMsg
|
||||
* SteamApps.AppInfoCallback now exposes the immediate child KeyValue for every Section, instead of an empty root parent.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.1.0 May 14, 2012
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Added SteamWorkshop for enumerating and requesting details of published workshop files.
|
||||
* Large overhaul of SteamGameCoordinator to support the sending and receiving of GC messages.
|
||||
* Added SteamFriends ChatInviteCallback.
|
||||
* Added SteamFriends KickChatMember and BanChatMember.
|
||||
* Fixed invalid handling of PackageInfoCallback response.
|
||||
* Updated protobuf definitions for internal message classes to their latest definitions.
|
||||
|
||||
BREAKING CHANGES
|
||||
* Consumers of SteamClient.JobCallback<T> will have to change their handler functions to take a "JobID" parameter instead of a "ulong".
|
||||
These are functionally equivalent, and JobIDs can be implicitly casted to and from ulongs.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
v 1.0.0 Feb 26, 2012
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
* Initial release.
|
BIN
packages/protobuf-net.2.0.0.668/lib/net20-cf/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/net20-cf/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2529
packages/protobuf-net.2.0.0.668/lib/net20-cf/protobuf-net.xml
vendored
Normal file
2529
packages/protobuf-net.2.0.0.668/lib/net20-cf/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/lib/net20/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/net20/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2758
packages/protobuf-net.2.0.0.668/lib/net20/protobuf-net.xml
vendored
Normal file
2758
packages/protobuf-net.2.0.0.668/lib/net20/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/lib/net30/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/net30/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2879
packages/protobuf-net.2.0.0.668/lib/net30/protobuf-net.xml
vendored
Normal file
2879
packages/protobuf-net.2.0.0.668/lib/net30/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/lib/net35-cf/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/net35-cf/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2529
packages/protobuf-net.2.0.0.668/lib/net35-cf/protobuf-net.xml
vendored
Normal file
2529
packages/protobuf-net.2.0.0.668/lib/net35-cf/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/lib/net35/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/net35/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2879
packages/protobuf-net.2.0.0.668/lib/net35/protobuf-net.xml
vendored
Normal file
2879
packages/protobuf-net.2.0.0.668/lib/net35/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/lib/net40-cf/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/net40-cf/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2529
packages/protobuf-net.2.0.0.668/lib/net40-cf/protobuf-net.xml
vendored
Normal file
2529
packages/protobuf-net.2.0.0.668/lib/net40-cf/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/lib/net40/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/net40/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2879
packages/protobuf-net.2.0.0.668/lib/net40/protobuf-net.xml
vendored
Normal file
2879
packages/protobuf-net.2.0.0.668/lib/net40/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
2539
packages/protobuf-net.2.0.0.668/lib/netcore45/protobuf-net.XML
vendored
Normal file
2539
packages/protobuf-net.2.0.0.668/lib/netcore45/protobuf-net.XML
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/lib/netcore45/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/netcore45/protobuf-net.dll
vendored
Normal file
Binary file not shown.
BIN
packages/protobuf-net.2.0.0.668/lib/netcore45/protobuf-net.pri
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/netcore45/protobuf-net.pri
vendored
Normal file
Binary file not shown.
BIN
packages/protobuf-net.2.0.0.668/lib/portable-sl4+net40+wp7+windows8/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/portable-sl4+net40+wp7+windows8/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2529
packages/protobuf-net.2.0.0.668/lib/portable-sl4+net40+wp7+windows8/protobuf-net.xml
vendored
Normal file
2529
packages/protobuf-net.2.0.0.668/lib/portable-sl4+net40+wp7+windows8/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/lib/sl3-wp/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/sl3-wp/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2539
packages/protobuf-net.2.0.0.668/lib/sl3-wp/protobuf-net.xml
vendored
Normal file
2539
packages/protobuf-net.2.0.0.668/lib/sl3-wp/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/lib/sl4-windowsphone71/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/sl4-windowsphone71/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2539
packages/protobuf-net.2.0.0.668/lib/sl4-windowsphone71/protobuf-net.xml
vendored
Normal file
2539
packages/protobuf-net.2.0.0.668/lib/sl4-windowsphone71/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/lib/sl4/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/sl4/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2585
packages/protobuf-net.2.0.0.668/lib/sl4/protobuf-net.xml
vendored
Normal file
2585
packages/protobuf-net.2.0.0.668/lib/sl4/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/lib/windowsphone8/protobuf-net.dll
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/lib/windowsphone8/protobuf-net.dll
vendored
Normal file
Binary file not shown.
2641
packages/protobuf-net.2.0.0.668/lib/windowsphone8/protobuf-net.xml
vendored
Normal file
2641
packages/protobuf-net.2.0.0.668/lib/windowsphone8/protobuf-net.xml
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
packages/protobuf-net.2.0.0.668/protobuf-net.2.0.0.668.nupkg
vendored
Normal file
BIN
packages/protobuf-net.2.0.0.668/protobuf-net.2.0.0.668.nupkg
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue