The end is near... #48

This commit is contained in:
JustArchi
2016-03-09 03:10:33 +01:00
parent 5c1da24def
commit 3d9fe36245
5 changed files with 237 additions and 28 deletions

View File

@@ -12,6 +12,7 @@
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<IsWebBootstrapper>false</IsWebBootstrapper>
<TargetFrameworkProfile />
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
@@ -26,7 +27,6 @@
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -108,6 +108,7 @@
<Compile Include="CMsgClientClanInviteAction.cs" />
<Compile Include="Debugging.cs" />
<Compile Include="GlobalConfig.cs" />
<Compile Include="JSON\GitHub.cs" />
<Compile Include="Logging.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />

View File

@@ -0,0 +1,46 @@
/*
_ _ _ ____ _ _____
/ \ _ __ ___ | |__ (_)/ ___| | |_ ___ __ _ _ __ ___ | ___|__ _ _ __ _ __ ___
/ _ \ | '__|/ __|| '_ \ | |\___ \ | __|/ _ \ / _` || '_ ` _ \ | |_ / _` || '__|| '_ ` _ \
/ ___ \ | | | (__ | | | || | ___) || |_| __/| (_| || | | | | || _|| (_| || | | | | | | |
/_/ \_\|_| \___||_| |_||_||____/ \__|\___| \__,_||_| |_| |_||_| \__,_||_| |_| |_| |_|
Copyright 2015-2016 Łukasz "JustArchi" Domeradzki
Contact: JustArchi@JustArchi.net
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
using Newtonsoft.Json;
using System.Collections.Generic;
namespace ArchiSteamFarm {
internal static class GitHub {
internal sealed class Asset {
[JsonProperty(PropertyName = "name", Required = Required.Always)]
internal string Name { get; private set; }
[JsonProperty(PropertyName = "browser_download_url", Required = Required.Always)]
internal string DownloadURL { get; private set; }
}
internal sealed class ReleaseResponse {
[JsonProperty(PropertyName = "tag_name", Required = Required.Always)]
internal string Tag { get; private set; }
[JsonProperty(PropertyName = "assets", Required = Required.Always)]
internal List<Asset> Assets { get; private set; }
}
}
}

View File

@@ -22,8 +22,10 @@
*/
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading;
@@ -48,7 +50,7 @@ namespace ArchiSteamFarm {
Server // Normal + WCF server
}
private const string LatestGithubReleaseURL = "https://api.github.com/repos/JustArchi/ArchiSteamFarm/releases/latest";
private const string GithubReleaseURL = "https://api.github.com/repos/JustArchi/ArchiSteamFarm/releases";
internal const string ASF = "ASF";
internal const string ConfigDirectory = "config";
@@ -62,6 +64,7 @@ namespace ArchiSteamFarm {
private static readonly ManualResetEvent ShutdownResetEvent = new ManualResetEvent(false);
private static readonly Assembly Assembly = Assembly.GetExecutingAssembly();
private static readonly string ExecutableFile = Assembly.Location;
private static readonly string ExecutableName = Path.GetFileName(ExecutableFile);
private static readonly string ExecutableDirectory = Path.GetDirectoryName(ExecutableFile);
private static readonly WCF WCF = new WCF();
@@ -74,29 +77,161 @@ namespace ArchiSteamFarm {
private static EMode Mode = EMode.Normal;
private static async Task CheckForUpdate() {
JObject response = await WebBrowser.UrlGetToJObject(LatestGithubReleaseURL).ConfigureAwait(false);
if (response == null) {
string oldExeFile = ExecutableFile + ".old";
// We booted successfully so we can now remove old exe file
if (File.Exists(oldExeFile)) {
try {
File.Delete(oldExeFile);
} catch (Exception e) {
Logging.LogGenericException(e);
return;
}
}
if (GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Unknown) {
return;
}
string remoteVersion = response["tag_name"].ToString();
if (string.IsNullOrEmpty(remoteVersion)) {
string releaseURL = GithubReleaseURL;
if (GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Stable) {
releaseURL += "/latest";
}
string response = null;
Logging.LogGenericInfo("Checking new version...");
for (byte i = 0; i < WebBrowser.MaxRetries && string.IsNullOrEmpty(response); i++) {
response = await WebBrowser.UrlGetToContent(releaseURL).ConfigureAwait(false);
}
if (string.IsNullOrEmpty(response)) {
Logging.LogGenericWarning("Could not check latest version!");
return;
}
string localVersion = Version;
GitHub.ReleaseResponse releaseResponse = null;
if (GlobalConfig.UpdateChannel == GlobalConfig.EUpdateChannel.Stable) {
try {
releaseResponse = JsonConvert.DeserializeObject<GitHub.ReleaseResponse>(response);
} catch (JsonException e) {
Logging.LogGenericException(e);
return;
}
} else {
List<GitHub.ReleaseResponse> releases;
try {
releases = JsonConvert.DeserializeObject<List<GitHub.ReleaseResponse>>(response);
} catch (JsonException e) {
Logging.LogGenericException(e);
return;
}
Logging.LogGenericInfo("Local version: " + localVersion);
Logging.LogGenericInfo("Remote version: " + remoteVersion);
if (releases == null || releases.Count == 0) {
Logging.LogGenericWarning("Could not check latest version!");
return;
}
int comparisonResult = localVersion.CompareTo(remoteVersion);
if (comparisonResult < 0) {
releaseResponse = releases[0];
}
if (string.IsNullOrEmpty(releaseResponse.Tag)) {
Logging.LogGenericWarning("Could not check latest version!");
return;
}
Logging.LogGenericInfo("Local version: " + Version);
Logging.LogGenericInfo("Remote version: " + releaseResponse.Tag);
int comparisonResult = Version.CompareTo(releaseResponse.Tag);
if (comparisonResult >= 0) {
return;
}
if (!GlobalConfig.AutoUpdates) {
Logging.LogGenericInfo("New version is available!");
Logging.LogGenericInfo("Consider updating yourself!");
await Utilities.SleepAsync(5000).ConfigureAwait(false);
} else if (comparisonResult > 0) {
Logging.LogGenericInfo("You're currently using pre-release version!");
Logging.LogGenericInfo("Be careful!");
return;
}
// Auto update logic starts here
if (releaseResponse.Assets == null) {
Logging.LogGenericWarning("Could not proceed with update because that version doesn't include assets!");
return;
}
GitHub.Asset binaryAsset = null;
foreach (var asset in releaseResponse.Assets) {
if (string.IsNullOrEmpty(asset.Name) || !asset.Name.Equals(ExecutableName)) {
continue;
}
binaryAsset = asset;
break;
}
if (binaryAsset == null) {
Logging.LogGenericWarning("Could not proceed with update because there is no asset that relates to currently running binary!");
return;
}
if (string.IsNullOrEmpty(binaryAsset.DownloadURL)) {
Logging.LogGenericWarning("Could not proceed with update because download URL is empty!");
return;
}
Logging.LogGenericInfo("Downloading new version...");
Stream newExe = await WebBrowser.UrlGetToStream(binaryAsset.DownloadURL).ConfigureAwait(false);
if (newExe == null) {
Logging.LogGenericWarning("Could not download new version!");
return;
}
// We start deep update logic here
string newExeFile = ExecutableFile + ".new";
// Firstly we create new exec
try {
using (FileStream fileStream = File.Open(newExeFile, FileMode.Create)) {
await newExe.CopyToAsync(fileStream).ConfigureAwait(false);
}
} catch (Exception e) {
Logging.LogGenericException(e);
return;
}
// Now we move current -> old
try {
File.Move(ExecutableFile, oldExeFile);
} catch (Exception e) {
Logging.LogGenericException(e);
try {
// Cleanup
File.Delete(newExeFile);
} catch { }
return;
}
// Now we move new -> current
try {
File.Move(newExeFile, ExecutableFile);
} catch (Exception e) {
Logging.LogGenericException(e);
try {
// Cleanup
File.Move(oldExeFile, ExecutableFile);
File.Delete(newExeFile);
} catch { }
return;
}
Logging.LogGenericInfo("Update process is finished! ASF will now restart itself...");
await Utilities.SleepAsync(5000);
if (!Restart()) {
// Shit happens
Logging.LogGenericWarning("ASF could not restart itself, you may need to restart it manually!");
await Utilities.SleepAsync(5000);
}
}
@@ -104,9 +239,19 @@ namespace ArchiSteamFarm {
Environment.Exit(exitCode);
}
internal static void Restart() {
System.Diagnostics.Process.Start(ExecutableFile, string.Join(" ", Environment.GetCommandLineArgs()));
Exit();
internal static bool Restart() {
try {
// TODO: This probably won't work on Mono, I wonder if I can make it work at some point
if (Process.Start(ExecutableFile, string.Join(" ", Environment.GetCommandLineArgs())) != null) {
Exit();
return true;
} else {
return false;
}
} catch (Exception e) {
Logging.LogGenericException(e);
return false;
}
}
internal static async Task LimitSteamRequestsAsync() {
@@ -283,7 +428,7 @@ namespace ArchiSteamFarm {
Exit(1);
}
Task.Run(async () => await CheckForUpdate().ConfigureAwait(false)).Wait();
CheckForUpdate().Wait();
// Before attempting to connect, initialize our list of CMs
Bot.RefreshCMs(GlobalDatabase.CellID).Wait();

View File

@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ArchiSteamFarm")]
[assembly: AssemblyCopyright("Copyright © Łukasz Domeradzki 2015")]
[assembly: AssemblyCopyright("Copyright © Łukasz Domeradzki 2015-2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 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("2.0.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyVersion("2.0.0.1")]
[assembly: AssemblyFileVersion("2.0.0.1")]

View File

@@ -26,6 +26,7 @@ using HtmlAgilityPack;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
@@ -81,7 +82,7 @@ namespace ArchiSteamFarm {
return await UrlRequest(request, HttpMethod.Post, data, cookies, referer).ConfigureAwait(false);
}
internal static async Task<string> UrlGetToContent(string request, Dictionary<string, string> cookies, string referer = null) {
internal static async Task<string> UrlGetToContent(string request, Dictionary<string, string> cookies = null, string referer = null) {
if (string.IsNullOrEmpty(request)) {
return null;
}
@@ -91,12 +92,28 @@ namespace ArchiSteamFarm {
return null;
}
HttpContent httpContent = httpResponse.Content;
if (httpContent == null) {
if (httpResponse.Content == null) {
return null;
}
return await httpContent.ReadAsStringAsync().ConfigureAwait(false);
return await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false);
}
internal static async Task<Stream> UrlGetToStream(string request, Dictionary<string, string> cookies = null, string referer = null) {
if (string.IsNullOrEmpty(request)) {
return null;
}
HttpResponseMessage httpResponse = await UrlGet(request, cookies, referer).ConfigureAwait(false);
if (httpResponse == null) {
return null;
}
if (httpResponse.Content == null) {
return null;
}
return await httpResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
}
internal static async Task<HtmlDocument> UrlGetToHtmlDocument(string request, Dictionary<string, string> cookies = null, string referer = null) {
@@ -145,7 +162,7 @@ namespace ArchiSteamFarm {
HttpResponseMessage responseMessage;
using (HttpRequestMessage requestMessage = new HttpRequestMessage(httpMethod, request)) {
if (data != null) {
if (data != null && data.Count > 0) {
try {
requestMessage.Content = new FormUrlEncodedContent(data);
} catch (UriFormatException e) {
@@ -162,7 +179,7 @@ namespace ArchiSteamFarm {
requestMessage.Headers.Add("Cookie", cookieHeader.ToString());
}
if (referer != null) {
if (!string.IsNullOrEmpty(referer)) {
requestMessage.Headers.Referrer = new Uri(referer);
}