Skip to content

Commit b8f9e4b

Browse files
committed
Add: UpdatePlugin task
1 parent 635f56e commit b8f9e4b

File tree

2 files changed

+198
-3
lines changed

2 files changed

+198
-3
lines changed

MediaInfoKeeper.csproj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
<Description>MediaInfoKeeper Emby plugin</Description>
55
<PackageTags>emby;plugin;pms;media;server;</PackageTags>
66
<BaseOutputPath>Build\bin\</BaseOutputPath>
7-
<AssemblyVersion>1.4.0.0</AssemblyVersion>
8-
<FileVersion>1.4.0.0</FileVersion>
9-
<Version>1.4.0</Version>
7+
<AssemblyVersion>1.4.1.0</AssemblyVersion>
8+
<FileVersion>1.4.1.0</FileVersion>
9+
<Version>1.4.1</Version>
1010
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
1111
</PropertyGroup>
1212
<ItemGroup>

ScheduledTask/UpdatePluginTask.cs

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
using MediaBrowser.Common;
2+
using MediaBrowser.Common.Configuration;
3+
using MediaBrowser.Common.Net;
4+
using MediaBrowser.Controller;
5+
using MediaBrowser.Model.Activity;
6+
using MediaBrowser.Model.Logging;
7+
using MediaBrowser.Model.Serialization;
8+
using MediaBrowser.Model.Tasks;
9+
using System;
10+
using System.Collections.Generic;
11+
using System.IO;
12+
using System.Linq;
13+
using System.Reflection;
14+
using System.Threading;
15+
using System.Threading.Tasks;
16+
17+
namespace MediaInfoKeeper.ScheduledTask
18+
{
19+
public class UpdatePluginTask : IScheduledTask
20+
{
21+
private readonly ILogger logger;
22+
private readonly IApplicationHost applicationHost;
23+
private readonly IApplicationPaths applicationPaths;
24+
private readonly IHttpClient httpClient;
25+
private readonly IJsonSerializer jsonSerializer;
26+
private readonly IActivityManager activityManager;
27+
private readonly IServerApplicationHost serverApplicationHost;
28+
29+
public UpdatePluginTask(
30+
IApplicationHost applicationHost,
31+
IApplicationPaths applicationPaths,
32+
IHttpClient httpClient,
33+
IJsonSerializer jsonSerializer,
34+
IActivityManager activityManager,
35+
IServerApplicationHost serverApplicationHost)
36+
{
37+
this.logger = Plugin.Instance.Logger;
38+
this.applicationHost = applicationHost;
39+
this.applicationPaths = applicationPaths;
40+
this.httpClient = httpClient;
41+
this.jsonSerializer = jsonSerializer;
42+
this.activityManager = activityManager;
43+
this.serverApplicationHost = serverApplicationHost;
44+
}
45+
46+
private static string PluginAssemblyFilename => Assembly.GetExecutingAssembly().GetName().Name + ".dll";
47+
private static string RepoReleaseUrl => "https://api.github.com/repos/honue/MediaInfoKeeper/releases/latest";
48+
49+
public string Key => "UpdatePluginTask";
50+
51+
public string Name => "更新插件";
52+
53+
public string Description => "更新插件至最新版本";
54+
55+
public string Category => Plugin.PluginName;
56+
57+
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
58+
{
59+
yield return new TaskTriggerInfo
60+
{
61+
Type = TaskTriggerInfo.TriggerWeekly,
62+
DayOfWeek = (DayOfWeek)new Random().Next(7),
63+
TimeOfDayTicks = TimeSpan.FromMinutes(new Random().Next(24 * 4) * 15).Ticks
64+
};
65+
}
66+
67+
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
68+
{
69+
await Task.Yield();
70+
progress.Report(0);
71+
72+
try
73+
{
74+
using var response = await httpClient.SendAsync(new HttpRequestOptions
75+
{
76+
Url = RepoReleaseUrl,
77+
CancellationToken = cancellationToken,
78+
AcceptHeader = "application/json",
79+
UserAgent = "MediaInfoKeeper",
80+
EnableDefaultUserAgent = false
81+
}, "GET").ConfigureAwait(false);
82+
83+
await using var contentStream = response.Content;
84+
var apiResult = jsonSerializer.DeserializeFromStream<ApiResponseInfo>(contentStream);
85+
86+
var currentVersion = ParseVersion(GetCurrentVersion());
87+
var remoteVersion = ParseVersion(apiResult?.tag_name);
88+
89+
if (currentVersion.CompareTo(remoteVersion) < 0)
90+
{
91+
logger.Info("Found new plugin version: {0}", remoteVersion);
92+
93+
var url = (apiResult?.assets ?? new List<ApiAssetInfo>())
94+
.FirstOrDefault(asset => asset.name == PluginAssemblyFilename)
95+
?.browser_download_url;
96+
if (!Uri.IsWellFormedUriString(url, UriKind.Absolute))
97+
{
98+
throw new Exception("Invalid download url");
99+
}
100+
101+
await using (var responseStream = await httpClient.Get(new HttpRequestOptions
102+
{
103+
Url = url,
104+
CancellationToken = cancellationToken,
105+
UserAgent = "MediaInfoKeeper",
106+
EnableDefaultUserAgent = false,
107+
Progress = progress
108+
})
109+
.ConfigureAwait(false))
110+
{
111+
using (var memoryStream = new MemoryStream())
112+
{
113+
await responseStream.CopyToAsync(memoryStream, 81920, cancellationToken)
114+
.ConfigureAwait(false);
115+
116+
memoryStream.Seek(0, SeekOrigin.Begin);
117+
var dllFilePath = Path.Combine(applicationPaths.PluginsPath, PluginAssemblyFilename);
118+
119+
await using (var fileStream =
120+
new FileStream(dllFilePath, FileMode.Create, FileAccess.Write))
121+
{
122+
await memoryStream.CopyToAsync(fileStream, 81920, cancellationToken)
123+
.ConfigureAwait(false);
124+
}
125+
}
126+
}
127+
128+
logger.Info("Plugin update complete");
129+
130+
activityManager.Create(new ActivityLogEntry
131+
{
132+
Name = Plugin.Instance.Name + " Updated to " + remoteVersion + " on " +
133+
serverApplicationHost.FriendlyName,
134+
Type = "PluginUpdateInstalled",
135+
Severity = LogSeverity.Info
136+
});
137+
138+
applicationHost.NotifyPendingRestart();
139+
}
140+
else
141+
{
142+
logger.Info("No need to update");
143+
}
144+
}
145+
catch (Exception ex)
146+
{
147+
activityManager.Create(new ActivityLogEntry
148+
{
149+
Name = Plugin.Instance.Name + " update failed on " + serverApplicationHost.FriendlyName,
150+
Type = "PluginUpdateFailed",
151+
Overview = ex.Message,
152+
Severity = LogSeverity.Error
153+
});
154+
155+
logger.Error("Update error: {0}", ex.Message);
156+
logger.Debug(ex.StackTrace);
157+
}
158+
159+
progress.Report(100);
160+
}
161+
162+
private static Version ParseVersion(string value)
163+
{
164+
if (string.IsNullOrWhiteSpace(value))
165+
{
166+
return new Version(0, 0, 0);
167+
}
168+
169+
var normalized = value.StartsWith("v", StringComparison.OrdinalIgnoreCase)
170+
? value.Substring(1)
171+
: value;
172+
return new Version(normalized);
173+
}
174+
175+
private static string GetCurrentVersion()
176+
{
177+
var version = Assembly.GetExecutingAssembly().GetName().Version;
178+
return version == null ? "0.0.0" : version.ToString(3);
179+
}
180+
181+
internal class ApiResponseInfo
182+
{
183+
public string tag_name { get; set; }
184+
185+
public List<ApiAssetInfo> assets { get; set; }
186+
}
187+
188+
internal class ApiAssetInfo
189+
{
190+
public string name { get; set; }
191+
192+
public string browser_download_url { get; set; }
193+
}
194+
}
195+
}

0 commit comments

Comments
 (0)