@using BTCPayServer.Configuration @using BTCPayServer.Plugins @model BTCPayServer.Controllers.UIServerController.ListPluginsViewModel @inject BTCPayServerOptions BTCPayServerOptions @inject PluginService PluginService @{ Layout = "_Layout"; ViewData.SetActivePage(ServerNavPages.Plugins); var installed = Model.Installed.ToDictionary(plugin => plugin.Identifier, plugin => plugin.Version); var installedWithoutSystemPlugins = Model.Installed.Where(i => !i.SystemPlugin).ToList(); var availableAndNotInstalled = new List(); var availableAndNotInstalledx = Model.Available .Where(plugin => !installed.ContainsKey(plugin.Identifier)) .GroupBy(plugin => plugin.Identifier) .ToList(); foreach (var availableAndNotInstalledItem in availableAndNotInstalledx) { var ordered = availableAndNotInstalledItem.OrderByDescending(plugin => plugin.Version).ToArray(); availableAndNotInstalled.Add(ordered.FirstOrDefault(availablePlugin => PluginManager.DependenciesMet(availablePlugin.Dependencies, installed)) ?? ordered.FirstOrDefault()); } bool DependentOn(string plugin) { foreach (var installedPlugin in Model.Installed) { if (installedPlugin.Dependencies.Any(dep => dep.Identifier.Equals(plugin, StringComparison.InvariantCultureIgnoreCase))) { return true; } } var pendingInstalls = Model.Commands.Where(tuple => tuple.command != "uninstall").Select(tuple => tuple.plugin).Distinct(); foreach (var pendingInstall in pendingInstalls) { if (Model.Available.Any(availablePlugin => availablePlugin.Identifier.Equals(pendingInstall, StringComparison.InvariantCultureIgnoreCase) && availablePlugin.Dependencies.Any(dep => dep.Identifier.Equals(plugin, StringComparison.InvariantCultureIgnoreCase)))) { return true; } } return false; } } @if (Model.Commands.Any()) {
You need to restart BTCPay Server in order to update your active plugins. @if (Model.CanShowRestart) {
}
} @if (Model.Disabled.Any()) {
Some plugins were disabled due to fatal errors. They may be incompatible with this version of BTCPay Server.

Disabled Plugins

    @foreach (var (plugin, version) in Model.Disabled) {
  • @plugin @if (version != null) { (@version) } @{ var uninstalled = Model.Commands.Any(c => c.plugin == plugin && c.command == "delete"); }
    @if (uninstalled) { } else { }
  • }
} @if (Model.Installed.Any()) {

Installed Plugins

@foreach (var plugin in Model.Installed.Where(i => !i.SystemPlugin)) { Model.DownloadedPluginsByIdentifier.TryGetValue(plugin.Identifier, out var downloadInfo); var matchedAvailable = Model.Available.Where(availablePlugin => availablePlugin.Identifier == plugin.Identifier && availablePlugin.Version > plugin.Version).OrderByDescending(availablePlugin => availablePlugin.Version).ToArray(); var x = matchedAvailable.FirstOrDefault(availablePlugin => PluginManager.DependenciesMet(availablePlugin.Dependencies, installed)) ?? matchedAvailable.FirstOrDefault(); var updateAvailable = matchedAvailable.Any(); var tabId = plugin.Identifier.ToLowerInvariant().Replace(".", "_");

@plugin.Name

@if (!string.IsNullOrEmpty(downloadInfo?.Author)) { by @downloadInfo.Author }
@plugin.Version @if (updateAvailable && x != null) {
@x.Version available
}
@if (updateAvailable) { Show current info Show update info }

@plugin.Description

@if (plugin.Dependencies.Any()) {
Dependencies
    @foreach (var dependency in plugin.Dependencies) {
  • @dependency @if (!PluginManager.DependencyMet(dependency, installed)) { }
  • }
}
@if (updateAvailable && x != null) {

@x.Description

@if (x.Dependencies.Any()) {
Dependencies
    @foreach (var dependency in x.Dependencies) {
  • @dependency @if (!PluginManager.DependencyMet(dependency, installed)) { }
  • }
}
} @if (plugin != null) {
Resources
    @if (downloadInfo?.Source is not null) {
  • Sources
  • } @if (!string.IsNullOrEmpty(downloadInfo?.Documentation)) {
  • Documentation
  • } else {
  • No documentation
  • }
}
@{ var pendingAction = Model.Commands.LastOrDefault(tuple => tuple.plugin.Equals(plugin.Identifier, StringComparison.InvariantCultureIgnoreCase)).command; var exclusivePendingAction = true; var versionOfPendingInstall = PluginService.GetVersionOfPendingInstall(plugin.Identifier); }
}
}
@if (!availableAndNotInstalled.Any()) {
No plugins found
} else {

Available Plugins

@foreach (var plugin in availableAndNotInstalled) { var recommended = BTCPayServerOptions.RecommendedPlugins.Any(id => string.Equals(id, plugin.Identifier, StringComparison.InvariantCultureIgnoreCase)); Model.Disabled.TryGetValue(plugin.Identifier, out var disabled);

@plugin.Name

@if (!string.IsNullOrEmpty(plugin.Author)) { by @plugin.Author }
@plugin.Version @if (disabled is { } && disabled != plugin.Version) {
Disabled (@disabled)
} else if (disabled is { } && disabled == plugin.Version) {
Disabled
} else if (recommended) {
Recommended
}

@plugin.Description

@if (plugin.Dependencies?.Any() is true) {
Dependencies
    @foreach (var dependency in plugin.Dependencies) {
  • @dependency @if (!PluginManager.DependencyMet(dependency, installed)) { }
  • }
if(!PluginManager.DependenciesMet(plugin.Dependencies, installed)) {
Dependencies not met.
} } @if (plugin != null) {
Resources
    @if (plugin.Source is not null) {
  • Sources
  • } @if (!string.IsNullOrEmpty(plugin.Documentation)) {
  • Documentation
  • } else {
  • No documentation
  • }
}
}
}

Upload Plugin

Add plugin manually

This is an extremely dangerous operation!
Only upload plugins from trusted sources.
@if (Model.Commands.Any()) {

Pending Action

Pending actions

    @foreach (var extComm in Model.Commands.GroupBy(tuple => tuple.plugin)) {
  • @extComm.Key
  • }
}