Skip to content

Commit 4189e2f

Browse files
committed
add support for renewing uploaded JSON/log files
1 parent 98dbc68 commit 4189e2f

7 files changed

Lines changed: 48 additions & 29 deletions

File tree

docs/release-notes.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
* Migrated to Harmony 2.0 (see [_migrate to Harmony 2.0_](https://stardewvalleywiki.com/Modding:Migrate_to_Harmony_2.0) for more info).
88
-->
99

10+
## Upcoming release
11+
* For the web UI:
12+
* You can now renew the expiry for an uploaded JSON/log file if you need it longer.
13+
1014
## 3.7.2
1115
Released 08 September 2020 for Stardew Valley 1.4.1 or later.
1216

src/SMAPI.Web/Controllers/JsonValidatorController.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public JsonValidatorController(IStorageProvider storage)
5858
/// <summary>Render the schema validator UI.</summary>
5959
/// <param name="schemaName">The schema name with which to validate the JSON, or 'edit' to return to the edit screen.</param>
6060
/// <param name="id">The stored file ID.</param>
61-
/// <param name="operation">The operation to perform for the selected log ID. This can be 'edit', or any other value to view.</param>
61+
/// <param name="operation">The operation to perform for the selected log ID. This can be 'edit', 'renew', or any other value to view.</param>
6262
[HttpGet]
6363
[Route("json")]
6464
[Route("json/{schemaName}")]
@@ -68,16 +68,18 @@ public async Task<ViewResult> Index(string schemaName = null, string id = null,
6868
{
6969
// parse arguments
7070
schemaName = this.NormalizeSchemaName(schemaName);
71+
operation = operation?.Trim().ToLower();
7172
bool hasId = !string.IsNullOrWhiteSpace(id);
72-
bool isEditView = !hasId || operation?.Trim().ToLower() == "edit";
73+
bool isEditView = !hasId || operation == "edit";
74+
bool renew = operation == "renew";
7375

7476
// build result model
7577
var result = this.GetModel(id, schemaName, isEditView);
7678
if (!hasId)
7779
return this.View("Index", result);
7880

7981
// fetch raw JSON
80-
StoredFileInfo file = await this.Storage.GetAsync(id);
82+
StoredFileInfo file = await this.Storage.GetAsync(id, renew);
8183
if (string.IsNullOrWhiteSpace(file.Content))
8284
return this.View("Index", result.SetUploadError("The JSON file seems to be empty."));
8385
result.SetContent(file.Content, expiry: file.Expiry, uploadWarning: file.Warning);

src/SMAPI.Web/Controllers/LogParserController.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,18 @@ public LogParserController(IStorageProvider storage)
4040
/// <summary>Render the log parser UI.</summary>
4141
/// <param name="id">The stored file ID.</param>
4242
/// <param name="raw">Whether to display the raw unparsed log.</param>
43+
/// <param name="renew">Whether to reset the log expiry.</param>
4344
[HttpGet]
4445
[Route("log")]
4546
[Route("log/{id}")]
46-
public async Task<ViewResult> Index(string id = null, bool raw = false)
47+
public async Task<ViewResult> Index(string id = null, bool raw = false, bool renew = false)
4748
{
4849
// fresh page
4950
if (string.IsNullOrWhiteSpace(id))
5051
return this.View("Index", this.GetModel(id));
5152

5253
// log page
53-
StoredFileInfo file = await this.Storage.GetAsync(id);
54+
StoredFileInfo file = await this.Storage.GetAsync(id, renew);
5455
ParsedLog log = file.Success
5556
? new LogParser().Parse(file.Content)
5657
: new ParsedLog { IsValid = false, Error = file.Error };

src/SMAPI.Web/Framework/Storage/IStorageProvider.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ internal interface IStorageProvider
1313

1414
/// <summary>Fetch raw text from storage.</summary>
1515
/// <param name="id">The storage ID returned by <see cref="SaveAsync"/>.</param>
16-
Task<StoredFileInfo> GetAsync(string id);
16+
/// <param name="renew">Whether to reset the file expiry.</param>
17+
Task<StoredFileInfo> GetAsync(string id, bool renew);
1718
}
1819
}

src/SMAPI.Web/Framework/Storage/StorageProvider.cs

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.IO;
34
using System.Text;
45
using System.Threading.Tasks;
@@ -48,10 +49,7 @@ public StorageProvider(IOptions<ApiClientsConfig> clientsConfig, IPastebinClient
4849
this.GzipHelper = gzipHelper;
4950
}
5051

51-
/// <summary>Save a text file to storage.</summary>
52-
/// <param name="content">The content to upload.</param>
53-
/// <param name="compress">Whether to gzip the text.</param>
54-
/// <returns>Returns metadata about the save attempt.</returns>
52+
/// <inheritdoc />
5553
public async Task<UploadResult> SaveAsync(string content, bool compress = true)
5654
{
5755
string id = Guid.NewGuid().ToString("N");
@@ -84,9 +82,8 @@ public async Task<UploadResult> SaveAsync(string content, bool compress = true)
8482
}
8583
}
8684

87-
/// <summary>Fetch raw text from storage.</summary>
88-
/// <param name="id">The storage ID returned by <see cref="SaveAsync"/>.</param>
89-
public async Task<StoredFileInfo> GetAsync(string id)
85+
/// <inheritdoc />
86+
public async Task<StoredFileInfo> GetAsync(string id, bool renew)
9087
{
9188
// fetch from blob storage
9289
if (Guid.TryParseExact(id, "N", out Guid _))
@@ -96,14 +93,21 @@ public async Task<StoredFileInfo> GetAsync(string id)
9693
{
9794
try
9895
{
96+
// get client
9997
BlobClient blob = this.GetAzureBlobClient(id);
98+
99+
// extend expiry
100+
if (renew)
101+
await blob.SetMetadataAsync(new Dictionary<string, string> { ["expiryRenewed"] = DateTime.UtcNow.ToString("O") }); // change the blob's last-modified date (the specific property set doesn't matter)
102+
103+
// fetch file
100104
Response<BlobDownloadInfo> response = await blob.DownloadAsync();
101105
using BlobDownloadInfo result = response.Value;
102-
103106
using StreamReader reader = new StreamReader(result.Content);
104107
DateTimeOffset expiry = result.Details.LastModified + TimeSpan.FromDays(this.ExpiryDays);
105108
string content = this.GzipHelper.DecompressString(reader.ReadToEnd());
106109

110+
// build model
107111
return new StoredFileInfo
108112
{
109113
Success = true,
@@ -125,25 +129,32 @@ public async Task<StoredFileInfo> GetAsync(string id)
125129
// local filesystem for testing
126130
else
127131
{
132+
// get file
128133
FileInfo file = new FileInfo(this.GetDevFilePath(id));
129-
if (file.Exists)
134+
if (file.Exists && file.LastWriteTimeUtc.AddDays(this.ExpiryDays) < DateTime.UtcNow) // expired
135+
file.Delete();
136+
if (!file.Exists)
130137
{
131-
if (file.LastWriteTimeUtc.AddDays(this.ExpiryDays) < DateTime.UtcNow)
132-
file.Delete();
133-
else
138+
return new StoredFileInfo
134139
{
135-
return new StoredFileInfo
136-
{
137-
Success = true,
138-
Content = File.ReadAllText(file.FullName),
139-
Expiry = DateTime.UtcNow.AddDays(this.ExpiryDays),
140-
Warning = "This file was saved temporarily to the local computer. This should only happen in a local development environment."
141-
};
142-
}
140+
Error = "There's no file with that ID."
141+
};
143142
}
143+
144+
// renew
145+
if (renew)
146+
{
147+
File.SetLastWriteTimeUtc(file.FullName, DateTime.UtcNow);
148+
file.Refresh();
149+
}
150+
151+
// build model
144152
return new StoredFileInfo
145153
{
146-
Error = "There's no file with that ID."
154+
Success = true,
155+
Content = File.ReadAllText(file.FullName),
156+
Expiry = DateTime.UtcNow.AddDays(this.ExpiryDays),
157+
Warning = "This file was saved temporarily to the local computer. This should only happen in a local development environment."
147158
};
148159
}
149160
}

src/SMAPI.Web/Views/JsonValidator/Index.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ else if (!Model.IsEditView && Model.PasteID != null)
7676
<div class="save-metadata" v-pre>
7777
@if (Model.Expiry != null)
7878
{
79-
<text>This JSON file will expire in @((DateTime.UtcNow - Model.Expiry.Value).Humanize()). </text>
79+
<text>This JSON file will expire in @((DateTime.UtcNow - Model.Expiry.Value).Humanize()) (<a href="@(this.Url.PlainAction("Index", "JsonValidator", new { schemaName = this.Model.SchemaName, id = this.Model.PasteID, operation = "renew" }))">renew</a>).</text>
8080
}
8181
<!--@Model.UploadWarning-->
8282
</div>

src/SMAPI.Web/Views/LogParser/Index.cshtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ else if (Model.ParsedLog?.IsValid == true)
7878
<div class="save-metadata" v-pre>
7979
@if (Model.Expiry != null)
8080
{
81-
<text>This log will expire in @((DateTime.UtcNow - Model.Expiry.Value).Humanize()).</text>
81+
<text>This log will expire in @((DateTime.UtcNow - Model.Expiry.Value).Humanize()) (<a href="proxy.php?url=https%3A%2F%2Fgithub.com%2F%40%28this.Url.PlainAction%28"Index", "LogParser", new { id = this.Model.PasteID, renew = true }))">renew</a>).</text>
8282
}
8383
</div>
8484
}

0 commit comments

Comments
 (0)