NET 8
This commit is contained in:
parent
ec256ac090
commit
238b58d555
1017
ARControl/.editorconfig
Normal file
1017
ARControl/.editorconfig
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0-windows</TargetFramework>
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
<Version>3.3</Version>
|
<Version>4.0</Version>
|
||||||
<LangVersion>11.0</LangVersion>
|
<LangVersion>12</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||||
|
@ -44,6 +44,9 @@ public sealed partial class AutoRetainerControlPlugin : IDalamudPlugin
|
|||||||
IClientState clientState, IChatGui chatGui, ICommandManager commandManager, ITextureProvider textureProvider,
|
IClientState clientState, IChatGui chatGui, ICommandManager commandManager, ITextureProvider textureProvider,
|
||||||
IPluginLog pluginLog)
|
IPluginLog pluginLog)
|
||||||
{
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(pluginInterface);
|
||||||
|
ArgumentNullException.ThrowIfNull(dataManager);
|
||||||
|
|
||||||
_pluginInterface = pluginInterface;
|
_pluginInterface = pluginInterface;
|
||||||
_clientState = clientState;
|
_clientState = clientState;
|
||||||
_chatGui = chatGui;
|
_chatGui = chatGui;
|
||||||
@ -226,28 +229,7 @@ public sealed partial class AutoRetainerControlPlugin : IDalamudPlugin
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_chatGui.Print(
|
PrintNextVentureMessage(retainerName, venture, reward, list);
|
||||||
new SeString(new UIForegroundPayload(579))
|
|
||||||
.Append(SeIconChar.Collectible.ToIconString())
|
|
||||||
.Append(new UIForegroundPayload(0))
|
|
||||||
.Append($" Sending retainer ")
|
|
||||||
.Append(new UIForegroundPayload(1))
|
|
||||||
.Append(retainerName)
|
|
||||||
.Append(new UIForegroundPayload(0))
|
|
||||||
.Append(" to collect ")
|
|
||||||
.Append(new UIForegroundPayload(1))
|
|
||||||
.Append($"{reward.Quantity}x ")
|
|
||||||
.Append(new ItemPayload(venture.ItemId))
|
|
||||||
.Append(venture.Name)
|
|
||||||
.Append(RawPayload.LinkTerminator)
|
|
||||||
.Append(new UIForegroundPayload(0))
|
|
||||||
.Append(" for ")
|
|
||||||
.Append(new UIForegroundPayload(1))
|
|
||||||
.Append($"{list.Name} {list.GetIcon()}")
|
|
||||||
.Append(new UIForegroundPayload(0))
|
|
||||||
.Append("."));
|
|
||||||
_pluginLog.Information(
|
|
||||||
$"Setting AR to use venture {venture.RowId}, which should retrieve {reward.Quantity}x {venture.Name}");
|
|
||||||
|
|
||||||
if (!dryRun)
|
if (!dryRun)
|
||||||
{
|
{
|
||||||
@ -272,21 +254,7 @@ public sealed partial class AutoRetainerControlPlugin : IDalamudPlugin
|
|||||||
// fallback: managed but no venture found/
|
// fallback: managed but no venture found/
|
||||||
if (retainer.LastVenture != QuickVentureId)
|
if (retainer.LastVenture != QuickVentureId)
|
||||||
{
|
{
|
||||||
_chatGui.Print(
|
PrintEndOfListMessage(retainerName, retainer);
|
||||||
new SeString(new UIForegroundPayload(579))
|
|
||||||
.Append(SeIconChar.Collectible.ToIconString())
|
|
||||||
.Append(new UIForegroundPayload(0))
|
|
||||||
.Append($" No tasks left for retainer ")
|
|
||||||
.Append(new UIForegroundPayload(1))
|
|
||||||
.Append(retainerName)
|
|
||||||
.Append(new UIForegroundPayload(0))
|
|
||||||
.Append(", sending to ")
|
|
||||||
.Append(new UIForegroundPayload(1))
|
|
||||||
.Append("Quick Venture")
|
|
||||||
.Append(new UIForegroundPayload(0))
|
|
||||||
.Append("."));
|
|
||||||
_pluginLog.Information($"No tasks left (previous venture = {retainer.LastVenture}), using QV");
|
|
||||||
|
|
||||||
if (!dryRun)
|
if (!dryRun)
|
||||||
{
|
{
|
||||||
retainer.HasVenture = true;
|
retainer.HasVenture = true;
|
||||||
@ -310,6 +278,50 @@ public sealed partial class AutoRetainerControlPlugin : IDalamudPlugin
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void PrintNextVentureMessage(string retainerName, Venture venture, VentureReward reward, Configuration.ItemList list)
|
||||||
|
{
|
||||||
|
_chatGui.Print(
|
||||||
|
new SeString(new UIForegroundPayload(579))
|
||||||
|
.Append(SeIconChar.Collectible.ToIconString())
|
||||||
|
.Append(new UIForegroundPayload(0))
|
||||||
|
.Append($" Sending retainer ")
|
||||||
|
.Append(new UIForegroundPayload(1))
|
||||||
|
.Append(retainerName)
|
||||||
|
.Append(new UIForegroundPayload(0))
|
||||||
|
.Append(" to collect ")
|
||||||
|
.Append(new UIForegroundPayload(1))
|
||||||
|
.Append($"{reward.Quantity}x ")
|
||||||
|
.Append(new ItemPayload(venture.ItemId))
|
||||||
|
.Append(venture.Name)
|
||||||
|
.Append(RawPayload.LinkTerminator)
|
||||||
|
.Append(new UIForegroundPayload(0))
|
||||||
|
.Append(" for ")
|
||||||
|
.Append(new UIForegroundPayload(1))
|
||||||
|
.Append($"{list.Name} {list.GetIcon()}")
|
||||||
|
.Append(new UIForegroundPayload(0))
|
||||||
|
.Append("."));
|
||||||
|
_pluginLog.Information(
|
||||||
|
$"Setting AR to use venture {venture.RowId}, which should retrieve {reward.Quantity}x {venture.Name}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PrintEndOfListMessage(string retainerName, Configuration.RetainerConfiguration retainer)
|
||||||
|
{
|
||||||
|
_chatGui.Print(
|
||||||
|
new SeString(new UIForegroundPayload(579))
|
||||||
|
.Append(SeIconChar.Collectible.ToIconString())
|
||||||
|
.Append(new UIForegroundPayload(0))
|
||||||
|
.Append($" No tasks left for retainer ")
|
||||||
|
.Append(new UIForegroundPayload(1))
|
||||||
|
.Append(retainerName)
|
||||||
|
.Append(new UIForegroundPayload(0))
|
||||||
|
.Append(", sending to ")
|
||||||
|
.Append(new UIForegroundPayload(1))
|
||||||
|
.Append("Quick Venture")
|
||||||
|
.Append(new UIForegroundPayload(0))
|
||||||
|
.Append("."));
|
||||||
|
_pluginLog.Information($"No tasks left (previous venture = {retainer.LastVenture}), using QV");
|
||||||
|
}
|
||||||
|
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This treats the retainer who is currently doing the venture as 'in-progress', since I believe the
|
/// This treats the retainer who is currently doing the venture as 'in-progress', since I believe the
|
||||||
/// relevant event is fired BEFORE the venture rewards are collected.
|
/// relevant event is fired BEFORE the venture rewards are collected.
|
||||||
@ -378,7 +390,7 @@ public sealed partial class AutoRetainerControlPlugin : IDalamudPlugin
|
|||||||
{
|
{
|
||||||
if (arguments == "sync")
|
if (arguments == "sync")
|
||||||
Sync();
|
Sync();
|
||||||
else if (arguments.StartsWith("dnv"))
|
else if (arguments.StartsWith("dnv", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
var ch = _configuration.Characters.SingleOrDefault(x => x.LocalContentId == _clientState.LocalContentId);
|
var ch = _configuration.Characters.SingleOrDefault(x => x.LocalContentId == _clientState.LocalContentId);
|
||||||
if (ch == null || ch.Type == Configuration.CharacterType.NotManaged || ch.Retainers.Count == 0)
|
if (ch == null || ch.Type == Configuration.CharacterType.NotManaged || ch.Retainers.Count == 0)
|
||||||
|
4
ARControl/External/AllaganToolsIpc.cs
vendored
4
ARControl/External/AllaganToolsIpc.cs
vendored
@ -7,7 +7,7 @@ using FFXIVClientStructs.FFXIV.Client.Game;
|
|||||||
|
|
||||||
namespace ARControl.External;
|
namespace ARControl.External;
|
||||||
|
|
||||||
public class AllaganToolsIpc
|
internal sealed class AllaganToolsIpc
|
||||||
{
|
{
|
||||||
private readonly IPluginLog _pluginLog;
|
private readonly IPluginLog _pluginLog;
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ public class AllaganToolsIpc
|
|||||||
_pluginLog.Verbose($"Found {itemCount} items in retainer inventories for itemId {itemId}");
|
_pluginLog.Verbose($"Found {itemCount} items in retainer inventories for itemId {itemId}");
|
||||||
return itemCount;
|
return itemCount;
|
||||||
}
|
}
|
||||||
catch (IpcError e)
|
catch (IpcError)
|
||||||
{
|
{
|
||||||
_pluginLog.Warning("Could not query allagantools for retainer inventory counts");
|
_pluginLog.Warning("Could not query allagantools for retainer inventory counts");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@ -19,10 +19,11 @@ using ECommons;
|
|||||||
using ECommons.ImGuiMethods;
|
using ECommons.ImGuiMethods;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using LLib;
|
using LLib;
|
||||||
|
using LLib.ImGui;
|
||||||
|
|
||||||
namespace ARControl.Windows;
|
namespace ARControl.Windows;
|
||||||
|
|
||||||
internal sealed class ConfigWindow : LImGui.LWindow
|
internal sealed class ConfigWindow : LWindow
|
||||||
{
|
{
|
||||||
// TODO This should also allow retainers under max level
|
// TODO This should also allow retainers under max level
|
||||||
private const byte MinLevel = 10;
|
private const byte MinLevel = 10;
|
||||||
@ -316,17 +317,17 @@ internal sealed class ConfigWindow : LImGui.LWindow
|
|||||||
var regexMatch = CountAndName.Match(_searchString);
|
var regexMatch = CountAndName.Match(_searchString);
|
||||||
if (regexMatch.Success)
|
if (regexMatch.Success)
|
||||||
{
|
{
|
||||||
quantity = int.Parse(regexMatch.Groups[1].Value);
|
quantity = int.Parse(regexMatch.Groups[1].Value, CultureInfo.InvariantCulture);
|
||||||
itemName = regexMatch.Groups[2].Value.ToLower();
|
itemName = regexMatch.Groups[2].Value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
quantity = 0;
|
quantity = 0;
|
||||||
itemName = _searchString.ToLower();
|
itemName = _searchString;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var filtered in _gameCache.Ventures
|
foreach (var filtered in _gameCache.Ventures
|
||||||
.Where(x => x.Name.ToLower().Contains(itemName))
|
.Where(x => x.Name.Contains(itemName, StringComparison.OrdinalIgnoreCase))
|
||||||
.OrderBy(x => x.Level)
|
.OrderBy(x => x.Level)
|
||||||
.ThenBy(x => x.Name)
|
.ThenBy(x => x.Name)
|
||||||
.ThenBy(x => x.ItemId)
|
.ThenBy(x => x.ItemId)
|
||||||
@ -466,36 +467,15 @@ internal sealed class ConfigWindow : LImGui.LWindow
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui.Spacing();
|
ImGui.Spacing();
|
||||||
List<Configuration.QueuedItem> clipboardItems = new();
|
List<Configuration.QueuedItem> clipboardItems = ParseClipboardItems();
|
||||||
try
|
ImportFromClipboardButton(list, clipboardItems);
|
||||||
{
|
RemoveFinishedItemsButton(list);
|
||||||
string? clipboardText = GetClipboardText();
|
|
||||||
if (!string.IsNullOrWhiteSpace(clipboardText))
|
|
||||||
{
|
|
||||||
foreach (var clipboardLine in clipboardText.ReplaceLineEndings().Split(Environment.NewLine))
|
|
||||||
{
|
|
||||||
var match = CountAndName.Match(clipboardLine);
|
|
||||||
if (!match.Success)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
var venture = _gameCache.Ventures.FirstOrDefault(x =>
|
ImGui.Spacing();
|
||||||
x.Name.Equals(match.Groups[2].Value, StringComparison.CurrentCultureIgnoreCase));
|
|
||||||
if (venture != null && int.TryParse(match.Groups[1].Value, out int quantity))
|
|
||||||
{
|
|
||||||
clipboardItems.Add(new Configuration.QueuedItem
|
|
||||||
{
|
|
||||||
ItemId = venture.ItemId,
|
|
||||||
RemainingQuantity = quantity,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
_pluginLog.Warning(e, "Unable to extract clipboard text");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ImportFromClipboardButton(Configuration.ItemList list, List<Configuration.QueuedItem> clipboardItems)
|
||||||
|
{
|
||||||
ImGui.BeginDisabled(clipboardItems.Count == 0);
|
ImGui.BeginDisabled(clipboardItems.Count == 0);
|
||||||
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Download, "Import from Clipboard"))
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Download, "Import from Clipboard"))
|
||||||
{
|
{
|
||||||
@ -540,7 +520,10 @@ internal sealed class ConfigWindow : LImGui.LWindow
|
|||||||
|
|
||||||
ImGui.EndTooltip();
|
ImGui.EndTooltip();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveFinishedItemsButton(Configuration.ItemList list)
|
||||||
|
{
|
||||||
if (list.Items.Count > 0 && list.Type == Configuration.ListType.CollectOneTime)
|
if (list.Items.Count > 0 && list.Type == Configuration.ListType.CollectOneTime)
|
||||||
{
|
{
|
||||||
ImGui.SameLine();
|
ImGui.SameLine();
|
||||||
@ -553,8 +536,41 @@ internal sealed class ConfigWindow : LImGui.LWindow
|
|||||||
|
|
||||||
ImGui.EndDisabled();
|
ImGui.EndDisabled();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui.Spacing();
|
private List<Configuration.QueuedItem> ParseClipboardItems()
|
||||||
|
{
|
||||||
|
List<Configuration.QueuedItem> clipboardItems = new List<Configuration.QueuedItem>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string? clipboardText = GetClipboardText();
|
||||||
|
if (!string.IsNullOrWhiteSpace(clipboardText))
|
||||||
|
{
|
||||||
|
foreach (var clipboardLine in clipboardText.ReplaceLineEndings().Split(Environment.NewLine))
|
||||||
|
{
|
||||||
|
var match = CountAndName.Match(clipboardLine);
|
||||||
|
if (!match.Success)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var venture = _gameCache.Ventures.FirstOrDefault(x =>
|
||||||
|
x.Name.Equals(match.Groups[2].Value, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (venture != null && int.TryParse(match.Groups[1].Value, out int quantity))
|
||||||
|
{
|
||||||
|
clipboardItems.Add(new Configuration.QueuedItem
|
||||||
|
{
|
||||||
|
ItemId = venture.ItemId,
|
||||||
|
RemainingQuantity = quantity,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_pluginLog.Warning(e, "Unable to extract clipboard text");
|
||||||
|
}
|
||||||
|
|
||||||
|
return clipboardItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawCharacters()
|
private void DrawCharacters()
|
||||||
@ -644,7 +660,8 @@ internal sealed class ConfigWindow : LImGui.LWindow
|
|||||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||||
if (character.ItemListIds == null)
|
if (character.ItemListIds == null)
|
||||||
character.ItemListIds = new();
|
character.ItemListIds = new();
|
||||||
DrawVentureListSelection(character.LocalContentId.ToString(),
|
DrawVentureListSelection(
|
||||||
|
character.LocalContentId.ToString(CultureInfo.InvariantCulture),
|
||||||
character.ItemListIds);
|
character.ItemListIds);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -890,14 +907,14 @@ internal sealed class ConfigWindow : LImGui.LWindow
|
|||||||
private bool IsValidGroupName(string name, Configuration.CharacterGroup? existingGroup)
|
private bool IsValidGroupName(string name, Configuration.CharacterGroup? existingGroup)
|
||||||
{
|
{
|
||||||
return name.Length >= 2 &&
|
return name.Length >= 2 &&
|
||||||
!name.Contains('%') &&
|
!name.Contains('%', StringComparison.Ordinal) &&
|
||||||
!_configuration.CharacterGroups.Any(x => x != existingGroup && name.EqualsIgnoreCase(x.Name));
|
!_configuration.CharacterGroups.Any(x => x != existingGroup && name.EqualsIgnoreCase(x.Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsValidListName(string name, Configuration.ItemList? existingList)
|
private bool IsValidListName(string name, Configuration.ItemList? existingList)
|
||||||
{
|
{
|
||||||
return name.Length >= 2 &&
|
return name.Length >= 2 &&
|
||||||
!name.Contains('%') &&
|
!name.Contains('%', StringComparison.Ordinal) &&
|
||||||
!_configuration.ItemLists.Any(x => x != existingList && name.EqualsIgnoreCase(x.Name));
|
!_configuration.ItemLists.Any(x => x != existingList && name.EqualsIgnoreCase(x.Name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -949,7 +966,7 @@ internal sealed class ConfigWindow : LImGui.LWindow
|
|||||||
|
|
||||||
if (checkPerCharacter)
|
if (checkPerCharacter)
|
||||||
{
|
{
|
||||||
foreach (var ch in charactersToCheck.Where(x => x.ToCheck(onlyShowMissing).Any()))
|
foreach (var ch in charactersToCheck.Where(x => x.ToCheck(onlyShowMissing).Count != 0))
|
||||||
{
|
{
|
||||||
bool currentCharacter = _clientState.LocalContentId == ch.Character.LocalContentId;
|
bool currentCharacter = _clientState.LocalContentId == ch.Character.LocalContentId;
|
||||||
ImGui.BeginDisabled(currentCharacter);
|
ImGui.BeginDisabled(currentCharacter);
|
||||||
@ -1027,7 +1044,10 @@ internal sealed class ConfigWindow : LImGui.LWindow
|
|||||||
{
|
{
|
||||||
ImGui.PushFont(UiBuilder.IconFont);
|
ImGui.PushFont(UiBuilder.IconFont);
|
||||||
var pos = ImGui.GetCursorPos();
|
var pos = ImGui.GetCursorPos();
|
||||||
ImGui.SetCursorPos(pos with { X = pos.X - ImGui.CalcTextSize(CurrentCharPrefix).X - 5 });
|
ImGui.SetCursorPos(pos with
|
||||||
|
{
|
||||||
|
X = pos.X - ImGui.CalcTextSize(CurrentCharPrefix).X - 5
|
||||||
|
});
|
||||||
ImGui.TextUnformatted(CurrentCharPrefix);
|
ImGui.TextUnformatted(CurrentCharPrefix);
|
||||||
ImGui.SetCursorPos(pos);
|
ImGui.SetCursorPos(pos);
|
||||||
ImGui.PopFont();
|
ImGui.PopFont();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"net7.0-windows7.0": {
|
"net8.0-windows7.0": {
|
||||||
"DalamudPackager": {
|
"DalamudPackager": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[2.1.12, )",
|
"requested": "[2.1.12, )",
|
||||||
@ -11,7 +11,7 @@
|
|||||||
"autoretainerapi": {
|
"autoretainerapi": {
|
||||||
"type": "Project",
|
"type": "Project",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ECommons": "[2.1.0.1, )"
|
"ECommons": "[2.1.0.7, )"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ecommons": {
|
"ecommons": {
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 7ff15133ac0d48e9aa57f69524bd9daf36c609bc
|
Subproject commit 6f0aaa55bce6ec79fd4d72f84f21597b39e5445d
|
2
ECommons
2
ECommons
@ -1 +1 @@
|
|||||||
Subproject commit f1c688a0599b41d70230021328a575da7351cf91
|
Subproject commit 6c6e6db85dcb28a6bdc3a69fd69f4eef6a8598cf
|
2
LLib
2
LLib
@ -1 +1 @@
|
|||||||
Subproject commit 865a6080319f8ccbcd5fd5b0004404822b6e60d4
|
Subproject commit 3792244261a9f5426a7916f5a6dd1966238ba84a
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"sdk": {
|
"sdk": {
|
||||||
"version": "7.0.0",
|
"version": "8.0.0",
|
||||||
"rollForward": "latestMinor",
|
"rollForward": "latestMinor",
|
||||||
"allowPrerelease": false
|
"allowPrerelease": false
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user