// Path: src/main/java/jp/jyn/jecon/config/MessageConfig.java
// public class MessageConfig {
//     private final static String PREFIX = "[Jecon] ";
//     public final static String HEADER = "========== Jecon ==========";
//     public final static String PLAYER_ONLY = PREFIX + ChatColor.RED + "This command can only be run by players.";
// 
//     public final TemplateParser doNotHavePermission;
//     public final TemplateParser missingArgument;
//     /**
//      * value
//      */
//     public final TemplateParser invalidArgument;
//     /**
//      * name
//      */
//     public final TemplateParser playerNotFound;
// 
//     /**
//      * name
//      */
//     public final TemplateParser accountNotFound;
//     public final TemplateParser notEnough;
// 
//     /**
//      * name,balance
//      */
//     public final TemplateParser show;
//     /**
//      * amount,name
//      */
//     public final TemplateParser paySuccess;
//     /**
//      * amount,name
//      */
//     public final TemplateParser payReceive;
//     /**
//      * name,balance
//      */
//     public final TemplateParser set;
//     /**
//      * amount,name
//      */
//     public final TemplateParser give;
//     /**
//      * amount,name
//      */
//     public final TemplateParser take;
//     /**
//      * name,balance
//      */
//     public final TemplateParser create;
//     /**
//      * name
//      */
//     public final TemplateParser createAlready;
//     /**
//      * name,balance
//      */
//     public final TemplateParser remove;
//     public final TemplateParser reloaded;
// 
//     /**
//      * page
//      */
//     public final TemplateParser topFirst;
//     /**
//      * rank,name,balance
//      */
//     public final TemplateParser topEntry;
// 
//     /**
//      * old,new,url
//      */
//     public final List<TemplateParser> newVersion;
// 
//     public final HelpMessage help;
// 
//     @PackagePrivate
//     MessageConfig(ConfigurationSection config) {
//         doNotHavePermission = parse(config, "doNotHavePermission");
//         missingArgument = parse(config, "missingArgument");
//         invalidArgument = parse(config, "invalidArgument");
//         playerNotFound = parse(config, "playerNotFound");
// 
//         accountNotFound = parse(config, "accountNotFound");
//         notEnough = parse(config, "notEnough");
// 
//         show = parse(config, "show");
//         paySuccess = parse(config, "paySuccess");
//         payReceive = parse(config, "payReceive");
//         set = parse(config, "set");
//         give = parse(config, "give");
//         take = parse(config, "take");
//         create = parse(config, "create");
//         createAlready = parse(config, "createAlready");
//         remove = parse(config, "remove");
//         reloaded = parse(config, "reloaded");
// 
//         topFirst = parse(config.getString("topFirst"));
//         topEntry = parse(config.getString("topEntry"));
// 
//         newVersion = config.getStringList("newVersion")
//             .stream()
//             .map(MessageConfig::parse)
//             .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
// 
//         help = new HelpMessage(config.getConfigurationSection("help"));
//     }
// 
//     public final static class HelpMessage {
//         public final TemplateParser show;
//         public final TemplateParser pay;
//         public final TemplateParser set;
//         public final TemplateParser give;
//         public final TemplateParser take;
//         public final TemplateParser create;
//         public final TemplateParser remove;
//         public final TemplateParser top;
//         public final TemplateParser reload;
//         public final TemplateParser version;
//         public final TemplateParser help;
//         public final TemplateParser example;
// 
//         private HelpMessage(ConfigurationSection config) {
//             show = parse(config.getString("show"));
//             pay = parse(config.getString("pay"));
//             set = parse(config.getString("set"));
//             give = parse(config.getString("give"));
//             take = parse(config.getString("take"));
//             create = parse(config.getString("create"));
//             remove = parse(config.getString("remove"));
//             top = parse(config.getString("top"));
//             reload = parse(config.getString("reload"));
//             version = parse(config.getString("version"));
//             help = parse(config.getString("help"));
//             example = parse(config.getString("example"));
//         }
//     }
// 
//     private static TemplateParser parse(ConfigurationSection config, String key) {
//         return parse(PREFIX + config.getString(key));
//     }
// 
//     private static TemplateParser parse(String value) {
//         return StringParser.parse(value);
//     }
// }


import jp.jyn.jbukkitlib.config.parser.template.variable.StringVariable;
import jp.jyn.jbukkitlib.config.parser.template.variable.TemplateVariable;
import jp.jyn.jbukkitlib.util.updater.GitHubReleaseChecker;
import jp.jyn.jbukkitlib.util.updater.UpdateChecker;
import jp.jyn.jecon.config.MessageConfig;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.Plugin;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
        this.message = message;
    }

    public void check(CommandSender sender) {
        if (!enable) {
            return;
        }

        if (nextCheck > System.currentTimeMillis()) {
            if (result != null) {
                sender.sendMessage(result);
            }
            return;
        }

        Plugin plugin = Jecon.getInstance();
        Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
            nextCheck = CHECK_PERIOD + System.currentTimeMillis();
            UpdateChecker.LatestVersion latest = checker.callEx();

            String currentVersion = plugin.getDescription().getVersion();
            if (currentVersion.equals(latest.version)) {
                return;
            }

            TemplateVariable variable = StringVariable.init()
                .put("old", currentVersion)
                .put("new", latest.version)
                .put("url", latest.url);
            result = Stream.concat(
// Path: src/main/java/jp/jyn/jecon/config/MessageConfig.java
// public class MessageConfig {
//     private final static String PREFIX = "[Jecon] ";
//     public final static String HEADER = "========== Jecon ==========";
//     public final static String PLAYER_ONLY = PREFIX + ChatColor.RED + "This command can only be run by players.";
// 
//     public final TemplateParser doNotHavePermission;
//     public final TemplateParser missingArgument;
//     /**
//      * value
//      */
//     public final TemplateParser invalidArgument;
//     /**
//      * name
//      */
//     public final TemplateParser playerNotFound;
// 
//     /**
//      * name
//      */
//     public final TemplateParser accountNotFound;
//     public final TemplateParser notEnough;
// 
//     /**
//      * name,balance
//      */
//     public final TemplateParser show;
//     /**
//      * amount,name
//      */
//     public final TemplateParser paySuccess;
//     /**
//      * amount,name
//      */
//     public final TemplateParser payReceive;
//     /**
//      * name,balance
//      */
//     public final TemplateParser set;
//     /**
//      * amount,name
//      */
//     public final TemplateParser give;
//     /**
//      * amount,name
//      */
//     public final TemplateParser take;
//     /**
//      * name,balance
//      */
//     public final TemplateParser create;
//     /**
//      * name
//      */
//     public final TemplateParser createAlready;
//     /**
//      * name,balance
//      */
//     public final TemplateParser remove;
//     public final TemplateParser reloaded;
// 
//     /**
//      * page
//      */
//     public final TemplateParser topFirst;
//     /**
//      * rank,name,balance
//      */
//     public final TemplateParser topEntry;
// 
//     /**
//      * old,new,url
//      */
//     public final List<TemplateParser> newVersion;
// 
//     public final HelpMessage help;
// 
//     @PackagePrivate
//     MessageConfig(ConfigurationSection config) {
//         doNotHavePermission = parse(config, "doNotHavePermission");
//         missingArgument = parse(config, "missingArgument");
//         invalidArgument = parse(config, "invalidArgument");
//         playerNotFound = parse(config, "playerNotFound");
// 
//         accountNotFound = parse(config, "accountNotFound");
//         notEnough = parse(config, "notEnough");
// 
//         show = parse(config, "show");
//         paySuccess = parse(config, "paySuccess");
//         payReceive = parse(config, "payReceive");
//         set = parse(config, "set");
//         give = parse(config, "give");
//         take = parse(config, "take");
//         create = parse(config, "create");
//         createAlready = parse(config, "createAlready");
//         remove = parse(config, "remove");
//         reloaded = parse(config, "reloaded");
// 
//         topFirst = parse(config.getString("topFirst"));
//         topEntry = parse(config.getString("topEntry"));
// 
//         newVersion = config.getStringList("newVersion")
//             .stream()
//             .map(MessageConfig::parse)
//             .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
// 
//         help = new HelpMessage(config.getConfigurationSection("help"));
//     }
// 
//     public final static class HelpMessage {
//         public final TemplateParser show;
//         public final TemplateParser pay;
//         public final TemplateParser set;
//         public final TemplateParser give;
//         public final TemplateParser take;
//         public final TemplateParser create;
//         public final TemplateParser remove;
//         public final TemplateParser top;
//         public final TemplateParser reload;
//         public final TemplateParser version;
//         public final TemplateParser help;
//         public final TemplateParser example;
// 
//         private HelpMessage(ConfigurationSection config) {
//             show = parse(config.getString("show"));
//             pay = parse(config.getString("pay"));
//             set = parse(config.getString("set"));
//             give = parse(config.getString("give"));
//             take = parse(config.getString("take"));
//             create = parse(config.getString("create"));
//             remove = parse(config.getString("remove"));
//             top = parse(config.getString("top"));
//             reload = parse(config.getString("reload"));
//             version = parse(config.getString("version"));
//             help = parse(config.getString("help"));
//             example = parse(config.getString("example"));
//         }
//     }
// 
//     private static TemplateParser parse(ConfigurationSection config, String key) {
//         return parse(PREFIX + config.getString(key));
//     }
// 
//     private static TemplateParser parse(String value) {
//         return StringParser.parse(value);
//     }
// }


// Path: src/main/java/jp/jyn/jecon/VersionChecker.java
import jp.jyn.jbukkitlib.config.parser.template.variable.StringVariable;
import jp.jyn.jbukkitlib.config.parser.template.variable.TemplateVariable;
import jp.jyn.jbukkitlib.util.updater.GitHubReleaseChecker;
import jp.jyn.jbukkitlib.util.updater.UpdateChecker;
import jp.jyn.jecon.config.MessageConfig;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.Plugin;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

        this.message = message;
    }

    public void check(CommandSender sender) {
        if (!enable) {
            return;
        }

        if (nextCheck > System.currentTimeMillis()) {
            if (result != null) {
                sender.sendMessage(result);
            }
            return;
        }

        Plugin plugin = Jecon.getInstance();
        Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
            nextCheck = CHECK_PERIOD + System.currentTimeMillis();
            UpdateChecker.LatestVersion latest = checker.callEx();

            String currentVersion = plugin.getDescription().getVersion();
            if (currentVersion.equals(latest.version)) {
                return;
            }

            TemplateVariable variable = StringVariable.init()
                .put("old", currentVersion)
                .put("new", latest.version)
                .put("url", latest.url);
            result = Stream.concat(
                Stream.of(MessageConfig.HEADER),