Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of a Command printing the release time of a build #47

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public Dispatcher()
{
this.registerCommand(new BuildGradleCommand());
this.registerCommand(new ChangelogCommand());
this.registerCommand(new DateVersionCommand());
this.registerCommand(new DocsCommand(this.reactListReg));
this.registerCommand(new EvalCommand());
this.registerCommand(new GradleCommand());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.almightyalpaca.discord.jdabutler.commands.commands;

import com.almightyalpaca.discord.jdabutler.Bot;
import com.almightyalpaca.discord.jdabutler.commands.Command;
import com.almightyalpaca.discord.jdabutler.util.DateUtils;
import com.almightyalpaca.discord.jdabutler.util.EmbedUtil;
import com.kantenkugel.discordbot.jenkinsutil.JenkinsApi;
import com.kantenkugel.discordbot.jenkinsutil.JenkinsBuild;
import com.kantenkugel.discordbot.versioncheck.VersionCheckerRegistry;
import com.kantenkugel.discordbot.versioncheck.changelog.ChangelogProvider;
import com.kantenkugel.discordbot.versioncheck.changelog.JenkinsChangelogProvider;
import com.kantenkugel.discordbot.versioncheck.items.VersionedItem;
import net.dv8tion.jda.api.AccountType;
import net.dv8tion.jda.api.EmbedBuilder;
Expand All @@ -13,12 +18,17 @@
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;

import java.io.IOException;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

public class ChangelogCommand extends Command
{

private static final String[] ALIASES = { "changes" };
private static final JenkinsApi JENKINS = DateUtils.JENKINS;
private static final DateTimeFormatter FORMATTER = DateUtils.getDateTimeFormatter();

@Override
public void dispatch(final User sender, final TextChannel channel, final Message message, final String content, final GuildMessageReceivedEvent event)
Expand Down Expand Up @@ -67,11 +77,33 @@ public void dispatch(final User sender, final TextChannel channel, final Message
reply(event, "The specified version does not exist");
return;
}

// Get time of build
String publishedTime;
try
{
final JenkinsBuild build = args == null
? JENKINS.getLastSuccessfulBuild()
: JENKINS.getBuild(Integer.parseInt(args[0]));
Copy link
Author

@DManstrator DManstrator Jul 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe I made a tiny mistake here. Shouldn't args[0] not be the item name according to line 45?

I mean VersionedItem#getChangelogProvider always returns null at the moment so it will always stop executing with "No Changelogs set up for " + item.getName() (line 57) but if this is gonna be changed, this will "crash" (the NumberFormatException will be catched) when providing another Item since args[0] isn't a build number / an integer in that case.

I would fix that by replacing args[0] with args[args.length - 1].

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kantenkugel I talked already with Alpaca in the JDA Server about this today, he has problems with the general code base right now so it would be great if you can also look over it (and maybe you can give me some response on that one too). However, it "sounds plausible" for Alpaca and it's ready to be merged (after I updated the code based on my last review).


final OffsetDateTime buildTime = build.buildTime;
publishedTime = FORMATTER.format(buildTime);
}
catch (NumberFormatException | IOException ex)
{
Bot.LOG.error("Exception in ChangelogCommand occured!", ex);
publishedTime = "Unable to get Release Time";
}

String title;
if(changelog.getChangelogUrl() == null)
eb.appendDescription("**").appendDescription(changelog.getTitle()).appendDescription("**:\n");
title = String.format("**%s**", changelog.getTitle());
else
eb.appendDescription("[").appendDescription(changelog.getTitle()).appendDescription("](")
.appendDescription(changelog.getChangelogUrl()).appendDescription("):\n");
title = String.format("[%s](%s)", changelog.getTitle(), changelog.getChangelogUrl());

final String versionTitle = String.format("%s *(%s)*:\n", title, publishedTime);
eb.appendDescription(versionTitle);

if(changelog.getChangeset().isEmpty())
eb.appendDescription("No changes available for this version");
else
Expand All @@ -80,13 +112,19 @@ public void dispatch(final User sender, final TextChannel channel, final Message
//more than 1 version given
else
{
List<ChangelogProvider.Changelog> changelogs = clProvider.getChangelogs(args[versionStart], args[versionStart + 1]);
final String startVersion = args[versionStart];
final String endVersion = args[versionStart + 1];

// get and increment build number instead of fetching it from every changelog to be more reliable
final int start = JenkinsChangelogProvider.extractBuild(startVersion);
List<ChangelogProvider.Changelog> changelogs = clProvider.getChangelogs(startVersion, endVersion);
if(changelogs.size() == 0)
{
reply(event, "No Changelogs found in given range");
return;
}
int fields = 0;
int buildNr = start;
for(ChangelogProvider.Changelog changelog : changelogs) {
String body = String.join("\n", changelog.getChangeset());
if(body.length() > MessageEmbed.VALUE_MAX_LENGTH)
Expand All @@ -97,13 +135,27 @@ public void dispatch(final User sender, final TextChannel channel, final Message
body = "[Link]("+changelog.getChangelogUrl()+") Too large to show.";
}

eb.addField(changelog.getTitle(), body, false);
// Get time of build
String publishedTime;
try
{
final JenkinsBuild build = JENKINS.getBuild(buildNr);
final OffsetDateTime buildTime = build.buildTime;
publishedTime = FORMATTER.format(buildTime);
}
catch (IOException ex)
{
Bot.LOG.error("Exception in ChangelogCommand occured!", ex);
publishedTime = "Unable to get Release Time";
}
eb.addField(String.format("%s (%s)", changelog.getTitle(), publishedTime), body, false);

if(++fields == 19 && changelogs.size() > 20)
{
eb.addField("...", "Embed limit reached. See [Online changelog]("
+ clProvider.getChangelogUrl() + ')', false);
}
buildNr++;
}
}

Expand Down Expand Up @@ -135,4 +187,5 @@ public String getName()
{
return "changelog";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package com.almightyalpaca.discord.jdabutler.commands.commands;

import com.almightyalpaca.discord.jdabutler.Bot;
import com.almightyalpaca.discord.jdabutler.commands.Command;
import com.almightyalpaca.discord.jdabutler.util.DateUtils;
import com.almightyalpaca.discord.jdabutler.util.DurationUtils;
import com.almightyalpaca.discord.jdabutler.util.EmbedUtil;
import com.kantenkugel.discordbot.jenkinsutil.JenkinsApi;
import com.kantenkugel.discordbot.jenkinsutil.JenkinsBuild;

import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;

import java.awt.Color;
import java.io.IOException;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class DateVersionCommand extends Command
{
private static final String[] ALIASES = { "published" };
private static final JenkinsApi JENKINS = DateUtils.JENKINS;
private static final DateTimeFormatter FORMATTER = DateUtils.getDateTimeFormatter();

@Override
public void dispatch(final User sender, final TextChannel channel, final Message message, final String content, final GuildMessageReceivedEvent event)
{
JenkinsBuild build;
try
{
if (content.trim().isEmpty())
build = JENKINS.getLastSuccessfulBuild();
else
{
String buildNrStr = content;

final int underscoreIndex = content.indexOf('_'); // in case somebody provided a full version (e. g. 3.8.3_463)
if (underscoreIndex != -1)
buildNrStr = content.substring(underscoreIndex + 1);

final int buildNr = Integer.parseInt(buildNrStr.trim());
build = JENKINS.getBuild(buildNr);
}
}
catch (IOException | NumberFormatException ex)
{
Bot.LOG.error("Exception in DateVersionCommand occured!", ex);

String title;
if (ex instanceof IOException)
title = "Connection to the Jenkins Server timed out!";
else if (ex instanceof NumberFormatException)
title = "Given input was not a valid build number!";
else
title = "Unknown Error occured!";
DManstrator marked this conversation as resolved.
Show resolved Hide resolved

final MessageEmbed failureEmbed = new EmbedBuilder().setAuthor("Error occured!", null, EmbedUtil.getJDAIconUrl())
.setTitle(title, null)
.setColor(Color.RED)
.build();
reply(event, failureEmbed);
return;
}

// Get time of build
final OffsetDateTime buildTime = build.buildTime;
final String publishedTime = FORMATTER.format(buildTime);

final Duration dur = DurationUtils.toDuration(System.currentTimeMillis() - buildTime.toInstant().toEpochMilli());
final String difference = DurationUtils.formatDuration(dur, true);

final int lastSpace = difference.lastIndexOf(' ');
final String differenceWithoutMs = lastSpace < 0 ? difference : difference.substring(0, lastSpace);

// Get correct version (copied from JenkinsChangelogProvider#getChangelogs(String, String))
final String buildVersion = build.status == JenkinsBuild.Status.SUCCESS
? build.artifacts.values().iterator().next().fileNameParts.get(1)
: build.buildNum + " (failed)";

// Return Info to User
final EmbedBuilder eb = new EmbedBuilder();
EmbedUtil.setColor(eb);

final MessageEmbed successEmbed = eb.setAuthor("Release Time of Version " + buildVersion, build.getUrl(), EmbedUtil.getJDAIconUrl())
.setTitle(publishedTime).setDescription(String.format("That was approximately %s ago.", differenceWithoutMs))
.build();

reply(event, successEmbed);
}

@Override
public String[] getAliases()
{
return DateVersionCommand.ALIASES;
}

@Override
public String getHelp()
{
return "Prints the datetime when the given build number or the latest build was published";
}

@Override
public String getName()
{
return "date";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.almightyalpaca.discord.jdabutler.util;

import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

import com.almightyalpaca.discord.jdabutler.Bot;
import com.kantenkugel.discordbot.jenkinsutil.JenkinsApi;

public final class DateUtils
{
private static final String DATE_FORMAT = "dd/MM/yyyy 'at' HH:mm:ss";
public static final JenkinsApi JENKINS = JenkinsApi.JDA_JENKINS;
public static final DateTimeFormatter FORMATTER = getDateTimeFormatter();

public static DateTimeFormatter getDateTimeFormatter() {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The { should be in the next line to match the general code style.

DateTimeFormatter formatter;
try
{
formatter = DateTimeFormatter.ofPattern(DATE_FORMAT + " (z)");
}
catch (NullPointerException | IllegalArgumentException ex)
{
final String defaultFormat = "dd.MM.yyyy 'at' HH:mm:ss (z)";
Bot.LOG.warn("Given format for DateVersionCommand was not valid, using: " + defaultFormat);
formatter = DateTimeFormatter.ofPattern(defaultFormat);
}

return formatter.withZone(ZoneId.of("UTC"));
}

// prevent instantiation
private DateUtils() {}

}
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ private List<String> getChangelog(List<JenkinsChange> changeSet)
return fields;
}

private static int extractBuild(String version)
// public since also accessed in the ChangelogCommand class
public static int extractBuild(String version)
{
int i = version.lastIndexOf('_');
try
Expand Down