All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.smoofyuniverse.ore.update.UpdateChecker Maven / Gradle / Ivy

/*
 * Copyright (c) 2021-2024 Hugo Dupanloup (Yeregorix)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package net.smoofyuniverse.ore.update;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.JoinConfiguration;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.smoofyuniverse.ore.OreAPI;
import net.smoofyuniverse.ore.project.OreProject;
import net.smoofyuniverse.ore.project.OreVersion;
import org.apache.logging.log4j.Logger;
import org.spongepowered.api.Server;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.entity.living.player.server.ServerPlayer;
import org.spongepowered.api.event.Listener;
import org.spongepowered.api.event.Order;
import org.spongepowered.api.event.lifecycle.RefreshGameEvent;
import org.spongepowered.api.event.lifecycle.StartedEngineEvent;
import org.spongepowered.api.event.network.ServerSideConnectionEvent;
import org.spongepowered.api.scheduler.ScheduledTask;
import org.spongepowered.api.scheduler.Task;
import org.spongepowered.configurate.ConfigurationNode;
import org.spongepowered.configurate.loader.ConfigurationLoader;
import org.spongepowered.plugin.PluginContainer;

import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;

public class UpdateChecker {
	private final Logger logger;
	private final PluginContainer plugin;
	private final ConfigurationLoader loader;
	private final OreProject project;
	private final Predicate predicate;
	private final String permission;

	private final OreAPI api = new OreAPI();
	private ScheduledTask checkTask;
	private UpdateCheckConfig config;
	private Component[] messages = new Component[0];

	public UpdateChecker(Logger logger, PluginContainer plugin, ConfigurationLoader loader,
						 String owner, String name) {
		this(logger, plugin, loader, owner, name, "spongeapi");
	}

	public UpdateChecker(Logger logger, PluginContainer plugin, ConfigurationLoader loader,
						 String owner, String name, String spongeDependency) {
		this(logger, plugin, loader,
				new OreProject(plugin.metadata().id()),
				v -> v.dependencies.get(spongeDependency).startsWith("12."),
				plugin.metadata().id() + ".update.notify");
		if (owner == null || owner.isEmpty())
			throw new IllegalArgumentException("owner");
		if (name == null || name.isEmpty())
			throw new IllegalArgumentException("name");

		this.project.owner = owner;
		this.project.name = name;
	}

	public UpdateChecker(Logger logger, PluginContainer plugin, ConfigurationLoader loader,
						 OreProject project, Predicate predicate, String permission) {
		if (logger == null)
			throw new IllegalArgumentException("logger");
		if (plugin == null)
			throw new IllegalArgumentException("plugin");
		if (loader == null)
			throw new IllegalArgumentException("loader");
		if (project == null)
			throw new IllegalArgumentException("project");
		if (predicate == null)
			throw new IllegalArgumentException("predicate");
		if (permission == null || permission.isEmpty())
			throw new IllegalArgumentException("permission");

		this.logger = logger;
		this.loader = loader;
		this.plugin = plugin;
		this.project = project;
		this.predicate = predicate;
		this.permission = permission;
	}

	@Listener(order = Order.LATE)
	public void onServerStarted(StartedEngineEvent e) {
		load();
	}

	private void load() {
		if (this.checkTask != null) {
			this.checkTask.cancel();
			this.checkTask = null;
		}

		this.logger.debug("Loading update check configuration ...");

		try {
			ConfigurationNode root = this.loader.load();
			this.config = root.get(UpdateCheckConfig.class);

			if (this.config == null)
				this.config = new UpdateCheckConfig();
			else
				this.config.normalize();

			root.set(this.config);
			this.loader.save(root);
		} catch (Exception ex) {
			this.logger.error("Failed to load update check configuration", ex);
			return;
		}

		if (this.config.enabled) {
			this.checkTask = Sponge.asyncScheduler().submit(
					Task.builder().interval(this.config.repetitionInterval, TimeUnit.HOURS).execute(this::check).plugin(this.plugin).build());
		}
	}

	private void check() {
		this.logger.debug("Checking for update ...");

		OreVersion latestVersion = null;
		try {
			latestVersion = OreVersion.getLatest(this.project.getVersions(this.api), this.predicate).orElse(null);
		} catch (Exception e) {
			this.logger.info("Failed to check for update", e);
		}

		String version = this.plugin.metadata().version().toString();
		if (latestVersion != null && !latestVersion.name.equals(version)) {
			Component msg1 = Component.join(JoinConfiguration.noSeparators(),
					Component.text("A new version of " + this.project.name + " is available: "),
					Component.text(latestVersion.name, NamedTextColor.AQUA),
					Component.text(". You're currently using version: "),
					Component.text(version, NamedTextColor.AQUA),
					Component.text("."));

			if (this.config.consoleDelay != -1) {
				Sponge.server().scheduler().submit(Task.builder().delay(this.config.consoleDelay, TimeUnit.MILLISECONDS)
						.execute(() -> Sponge.game().systemSubject().sendMessage(msg1)).plugin(this.plugin).build());
			}

			if (this.config.playerDelay != -1) {
				String page = latestVersion.getPage().orElse(null);
				if (page == null) {
					this.messages = new Component[]{msg1};
				} else {
					this.messages = new Component[]{msg1,
							Component.text().content("Click here to open the download page.")
									.color(NamedTextColor.GOLD).clickEvent(ClickEvent.openUrl(page)).build()
					};
				}
			}
		}
	}

	@Listener(order = Order.LATE)
	public void onRefreshGame(RefreshGameEvent e) {
		load();
	}

	@Listener(order = Order.LATE)
	public void onPlayerJoin(ServerSideConnectionEvent.Join e) {
		if (this.messages.length != 0) {
			ServerPlayer p = e.player();
			if (p.hasPermission(this.permission)) {
				Sponge.server().scheduler().submit(Task.builder().delay(this.config.playerDelay, TimeUnit.MILLISECONDS)
						.execute(() -> {
							for (Component msg : this.messages)
								p.sendMessage(msg);
						}).plugin(this.plugin).build());
			}
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy