<commit_before>using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Configuration;
using McMaster.NETCore.Plugins;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;

namespace BTCPayServer.Plugins
{
    public static class PluginManager
    {
        public const string BTCPayPluginSuffix = ".btcpay";
        private static readonly List<Assembly> _pluginAssemblies = new List<Assembly>();
        private static readonly List<PluginLoader> _plugins = new List<PluginLoader>();
        private static ILogger _logger;

        public static bool IsExceptionByPlugin(Exception exception)
        {
            return _pluginAssemblies.Any(assembly => assembly?.FullName?.Contains(exception.Source!, StringComparison.OrdinalIgnoreCase) is true);
        }
        public static IMvcBuilder AddPlugins(this IMvcBuilder mvcBuilder, IServiceCollection serviceCollection,
            IConfiguration config, ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger(typeof(PluginManager));
            var pluginsFolder = new DataDirectories().Configure(config).PluginDir;
            var plugins = new List<IBTCPayServerPlugin>();

            serviceCollection.Configure<KestrelServerOptions>(options =>
            {
                options.Limits.MaxRequestBodySize = int.MaxValue; // if don't set default value is: 30 MB
            });
            _logger.LogInformation($"Loading plugins from {pluginsFolder}");
            Directory.CreateDirectory(pluginsFolder);
            ExecuteCommands(pluginsFolder);
            List<(PluginLoader, Assembly, IFileProvider)> loadedPlugins =
                new List<(PluginLoader, Assembly, IFileProvider)>();
            var systemExtensions = GetDefaultLoadedPluginAssemblies();
            plugins.AddRange(systemExtensions.SelectMany(assembly =>
                GetAllPluginTypesFromAssembly(assembly).Select(GetPluginInstanceFromType)));
            foreach (IBTCPayServerPlugin btcPayServerExtension in plugins)
            {
                btcPayServerExtension.SystemPlugin = true;
            }

            var orderFilePath = Path.Combine(pluginsFolder, "order");
            
            var availableDirs = Directory.GetDirectories(pluginsFolder);
            var orderedDirs = new List<string>();
            if (File.Exists(orderFilePath))
            {
                var order = File.ReadLines(orderFilePath);
                foreach (var s in order)
                {
                    if (availableDirs.Contains(s))
                    {
                        orderedDirs.Add(s);
                    }
                }

                orderedDirs.AddRange(availableDirs.Where(s => !orderedDirs.Contains(s)));
            }
            else
            {
                orderedDirs = availableDirs.ToList();
            }

            var disabledPlugins = GetDisabledPlugins(pluginsFolder);
           
            

            foreach (var dir in orderedDirs)
            {
                var pluginName = Path.GetFileName(dir);
                var pluginFilePath = Path.Combine(dir, pluginName + ".dll");
                if (disabledPlugins.Contains(pluginName))
                {
                    continue;
                }
                if (!File.Exists(pluginFilePath))
                {
                    _logger.LogError(
                        $"Error when loading plugin {pluginName} - {pluginFilePath} does not exist");
                    continue;
                }

                var plugin = PluginLoader.CreateFromAssemblyFile(
                    pluginFilePath, // create a plugin from for the .dll file
                    config =>
                    {
                        
                        // this ensures that the version of MVC is shared between this app and the plugin
                        config.PreferSharedTypes = true;
                        config.IsUnloadable = true;
                    });

                mvcBuilder.AddPluginLoader(plugin);
                var pluginAssembly = plugin.LoadDefaultAssembly();
                _pluginAssemblies.Add(pluginAssembly);
                _plugins.Add(plugin);
                var fileProvider = CreateEmbeddedFileProviderForAssembly(pluginAssembly);
                loadedPlugins.Add((plugin, pluginAssembly, fileProvider));
                plugins.AddRange(GetAllPluginTypesFromAssembly(pluginAssembly)
                    .Select(GetPluginInstanceFromType));
            }

            foreach (var plugin in plugins)
            {
                try
                {
                    _logger.LogInformation(<commit_msg>Wrap more plugin loading logic in try catch to not crash fatally<commit_after>using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using BTCPayServer.Abstractions.Contracts;
using BTCPayServer.Configuration;
using McMaster.NETCore.Plugins;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;

namespace BTCPayServer.Plugins
{
    public static class PluginManager
    {
        public const string BTCPayPluginSuffix = ".btcpay";
        private static readonly List<Assembly> _pluginAssemblies = new List<Assembly>();
        private static readonly List<PluginLoader> _plugins = new List<PluginLoader>();
        private static ILogger _logger;

        public static bool IsExceptionByPlugin(Exception exception)
        {
            return _pluginAssemblies.Any(assembly => assembly?.FullName?.Contains(exception.Source!, StringComparison.OrdinalIgnoreCase) is true);
        }
        public static IMvcBuilder AddPlugins(this IMvcBuilder mvcBuilder, IServiceCollection serviceCollection,
            IConfiguration config, ILoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger(typeof(PluginManager));
            var pluginsFolder = new DataDirectories().Configure(config).PluginDir;
            var plugins = new List<IBTCPayServerPlugin>();

            serviceCollection.Configure<KestrelServerOptions>(options =>
            {
                options.Limits.MaxRequestBodySize = int.MaxValue; // if don't set default value is: 30 MB
            });
            _logger.LogInformation($"Loading plugins from {pluginsFolder}");
            Directory.CreateDirectory(pluginsFolder);
            ExecuteCommands(pluginsFolder);
            List<(PluginLoader, Assembly, IFileProvider)> loadedPlugins =
                new List<(PluginLoader, Assembly, IFileProvider)>();
            var systemExtensions = GetDefaultLoadedPluginAssemblies();
            plugins.AddRange(systemExtensions.SelectMany(assembly =>
                GetAllPluginTypesFromAssembly(assembly).Select(GetPluginInstanceFromType)));
            foreach (IBTCPayServerPlugin btcPayServerExtension in plugins)
            {
                btcPayServerExtension.SystemPlugin = true;
            }

            var orderFilePath = Path.Combine(pluginsFolder, "order");
            
            var availableDirs = Directory.GetDirectories(pluginsFolder);
            var orderedDirs = new List<string>();
            if (File.Exists(orderFilePath))
            {
                var order = File.ReadLines(orderFilePath);
                foreach (var s in order)
                {
                    if (availableDirs.Contains(s))
                    {
                        orderedDirs.Add(s);
                    }
                }

                orderedDirs.AddRange(availableDirs.Where(s => !orderedDirs.Contains(s)));
            }
            else
            {
                orderedDirs = availableDirs.ToList();
            }

            var disabledPlugins = GetDisabledPlugins(pluginsFolder);



            foreach (var dir in orderedDirs)
            {
                var pluginName = Path.GetFileName(dir);
                var pluginFilePath = Path.Combine(dir, pluginName + ".dll");
                if (disabledPlugins.Contains(pluginName))
                {
                    continue;
                }
                if (!File.Exists(pluginFilePath))
                {
                    _logger.LogError(
                        $"Error when loading plugin {pluginName} - {pluginFilePath} does not exist");
                    continue;
                }

                try
                {

                    var plugin = PluginLoader.CreateFromAssemblyFile(
                        pluginFilePath, // create a plugin from for the .dll file
                        config =>
                        {

                            // this ensures that the version of MVC is shared between this app and the plugin
                            config.PreferSharedTypes = true;
                            config.IsUnloadable = true;
                        });

                    mvcBuilder.AddPluginLoader(plugin);
                    var pluginAssembly = plugin.LoadDefaultAssembly();
                    _pluginAssemblies.Add(pluginAssembly);
                    _plugins.Add(plugin);
                    var fileProvider = CreateEmbeddedFileProviderForAssembly(pluginAssembly);
                    loadedPlugins.Add((plugin, pluginAssembly, fileProvider));
                    plugins.AddRange(GetAllPluginTypesFromAssembly(pluginAssembly)
                        .Select(GetPluginInstanceFromType));

                }
                catch (Exception e)
                {
                    _logger.LogError(e,
                        $"Error when loading plugin {pluginName}");
                }
            }

            foreach (var plugin in plugins)
            {
                try
                {
                    _logger.LogInformation(
{'fraction_non_alphanumeric': 0.07461538461538461, 'fraction_numerical': 0.0003846153846153846, 'mean_word_length': 1.8449124726477024, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 31, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '113048', 'n_tokens_mistral': 2420, 'n_tokens_neox': 2293, 'n_words': 514}