Skip to content

Commit

Permalink
Merge pull request #2 from Forested-Studios/master
Browse files Browse the repository at this point in the history
Update code to the latest JDA versions
  • Loading branch information
Ryzeon authored Apr 13, 2024
2 parents d874838 + eaba4ab commit 8d96a5f
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 74 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"java.configuration.updateBuildConfiguration": "automatic"
}
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,14 @@ DiscordHtmlTranscripts transcript = DiscordHtmlTranscripts.getInstance();
transcript.generateFromMessages(messages); // return to InputStream
```

### You can also put the transcript into a variable
```java
DiscordHtmlTranscripts transcripts = new DiscordHtmlTranscripts();
try {
testChannel.sendFiles(transcripts.getTranscript(testChannel, "test.html")).queue();
} catch (IOException e) {
throw new RuntimeException(e);
}
```


44 changes: 37 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,52 @@

<groupId>me.ryzeon.html</groupId>
<artifactId>discord-html-transcripts</artifactId>
<version>1.0-SNAPSHOT</version>
<version>2.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
<source>17</source>
<target>17</target>
<compilerArgs>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
<arg>--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>me.ryzeon.html.DiscordHtmlTranscripts</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<properties>
<java.version>1.8</java.version>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

Expand All @@ -38,21 +68,21 @@
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>4.3.0_322</version>
<version>5.0.0-Beta.20</version>
</dependency>

<dependency>
<!-- jsoup HTML parser library @ https://jsoup.org/ -->
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.14.3</version>
<version>1.15.3</version>
</dependency>

</dependencies>
Expand Down
157 changes: 90 additions & 67 deletions src/main/java/me/ryzeon/transcripts/DiscordHtmlTranscripts.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
package me.ryzeon.transcripts;

import lombok.var;
import net.dv8tion.jda.api.entities.*;
import lombok.Getter;
import net.dv8tion.jda.api.entities.ISnowflake;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.utils.FileUpload;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import java.awt.*;
import java.io.*;
import java.net.URL;;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
* Created by Ryzeon
* Edited by Incbom
* Project: discord-html-transcripts
* Date: 2/12/21 @ 00:32
* Twitter: @Ryzeon_ 😎
Expand All @@ -29,39 +37,61 @@ public class DiscordHtmlTranscripts {
audioFormats = Arrays.asList("mp3", "wav", "ogg", "flac");


@Getter
private static final DiscordHtmlTranscripts instance = new DiscordHtmlTranscripts();

public static DiscordHtmlTranscripts getInstance() {
return instance;
/**
* This method sends the transcript in the channel it is logging. To get the FileUpload object, use {@link #getTranscript(TextChannel, String)}. To get the InputStream object, use {@link #generateFromMessages(Collection)}.
* @param channel Channel to generate transcript from
*/
public void createTranscript(TextChannel channel) throws IOException {
createTranscript(channel, "transcript.html");
}

public void createTranscript(TextChannel channel) throws IOException {
createTranscript(channel, null);
/**
* This method sends the transcript in the channel it is logging. To get the InputStream object, use {@link #generateFromMessages(Collection)}.
* @param channel Channel to generate transcript from
* @param fileName Name of the file
* @return Returns a usable FileUpload object to send to a channel
*/
public FileUpload getTranscript(TextChannel channel, String fileName) throws IOException {
return FileUpload.fromData((generateFromMessages(channel.getIterableHistory().stream().collect(Collectors.toList()))), fileName);
}

public void createTranscript(TextChannel channel, String fileName) throws IOException {
channel.sendFile(generateFromMessages(channel.getIterableHistory().stream().collect(Collectors.toList())), fileName != null ? fileName : "transcript.html").queue();
private void createTranscript(TextChannel channel, String fileName) throws IOException {
FileUpload transcript = FileUpload.fromData((generateFromMessages(channel.getIterableHistory().stream().collect(Collectors.toList()))), fileName != null ? fileName : "transcript.html");
channel.sendFiles(transcript).queue();;
}

public InputStream generateFromMessages(Collection<Message> messages) throws IOException {
File htmlTemplate = findFile("template.html");
private InputStream generateFromMessages(Collection<Message> messages) throws IOException {
InputStream htmlTemplate = findFile();
if (messages.isEmpty()) {
throw new IllegalArgumentException("No messages to generate a transcript from");
}
TextChannel channel = messages.iterator().next().getTextChannel();
Document document = Jsoup.parse(htmlTemplate, "UTF-8");
TextChannel channel = messages.iterator().next().getJDA().getTextChannelById(messages.iterator().next().getChannel().getId());
Document document = Jsoup.parse(htmlTemplate, "UTF-8", "");
document.outputSettings().indentAmount(0).prettyPrint(true);
document.getElementsByClass("preamble__guild-icon")
.first().attr("src", channel.getGuild().getIconUrl()); // set guild icon

document.getElementById("transcriptTitle").text(channel.getName()); // set title
document.getElementById("guildname").text(channel.getGuild().getName()); // set guild name
document.getElementById("ticketname").text(channel.getName()); // set channel name
assert channel != null;
Element preambleGuildIcon = document.getElementsByClass("preamble__guild-icon").first();
String guildIconUrl = channel.getGuild().getIconUrl();

if (preambleGuildIcon != null && guildIconUrl != null) {
preambleGuildIcon.attr("src", guildIconUrl);
} else {
preambleGuildIcon.attr("src", "https://guild-studio.com/wp-content/uploads/2021/05/s9biyhs4lix61.jpg");
}
Objects.requireNonNull(document.getElementById("transcriptTitle")).text(channel.getName()); // set title
Objects.requireNonNull(document.getElementById("guildname")).text(channel.getGuild().getName()); // set guild name
Objects.requireNonNull(document.getElementById("ticketname")).text(channel.getName()); // set channel name

Element chatLog = document.getElementById("chatlog"); // chat log
for (Message message : messages.stream()
.sorted(Comparator.comparing(ISnowflake::getTimeCreated))
.collect(Collectors.toList())) {
.toList()) {

if (message.getAuthor().isBot()) {
continue;
}
// create message group
Element messageGroup = document.createElement("div");
messageGroup.addClass("chatlog__message-group");
Expand All @@ -79,27 +109,17 @@ public InputStream generateFromMessages(Collection<Message> messages) throws IOE

var referenceMessage = message.getReferencedMessage();
User author = referenceMessage.getAuthor();
Member member = channel.getGuild().getMember(author);
var color = Formatter.toHex(Objects.requireNonNull(member.getColor()));

// System.out.println("REFERENCE MSG " + referenceMessage.getContentDisplay());
reference.html("<img class=\"chatlog__reference-avatar\" src=\""
+ author.getAvatarUrl() + "\" alt=\"Avatar\" loading=\"lazy\">" +
"<span class=\"chatlog__reference-name\" title=\"" + author.getName()
+ "\" style=\"color: " + color + "\">" + author.getName() + "\"</span>" +
"<div class=\"chatlog__reference-content\">" +
" <span class=\"chatlog__reference-link\" onclick=\"scrollToMessage(event, '"
+ referenceMessage.getId() + "')\">" +
"<em>" +
referenceMessage.getContentDisplay() != null
? referenceMessage.getContentDisplay().length() > 42
author.getAvatarUrl();
author.getName();
author.getName();
referenceMessage.getId();
referenceMessage.getContentDisplay();
reference.html(referenceMessage.getContentDisplay().length() > 42
? referenceMessage.getContentDisplay().substring(0, 42)
+ "..."
: referenceMessage.getContentDisplay()
: "Click to see attachment" +
"</em>" +
"</span>" +
"</div>");
: referenceMessage.getContentDisplay());

messageGroup.appendChild(referenceSymbol);
messageGroup.appendChild(reference);
Expand All @@ -112,26 +132,35 @@ public InputStream generateFromMessages(Collection<Message> messages) throws IOE

Element authorAvatar = document.createElement("img");
authorAvatar.addClass("chatlog__author-avatar");
authorAvatar.attr("src", author.getAvatarUrl());
authorAvatar.attr("alt", "Avatar");
authorAvatar.attr("loading", "lazy");

Element authorName = document.createElement("span");
authorName.addClass("chatlog__author-name");

if (author != null) {
authorName.attr("title", Objects.requireNonNull(author.getGlobalName()));
authorName.text(author.getName());
authorName.attr("data-user-id", author.getId());
authorAvatar.attr("src", Objects.requireNonNull(author.getAvatarUrl()));
} else {
// Handle the case when author is null (e.g., when the message is from a bot)
authorName.attr("title", "Bot");
authorName.text("Bot");
authorName.attr("data-user-id", "Bot");
authorAvatar.attr("src", "default_bot_avatar_url"); // replace with your default bot avatar URL
}

authorElement.appendChild(authorAvatar);
messageGroup.appendChild(authorElement);

// message content
Element content = document.createElement("div");
content.addClass("chatlog__messages");
// message author name
Element authorName = document.createElement("span");
authorName.addClass("chatlog__author-name");
// authorName.attr("title", author.getName()); // author.name
authorName.attr("title", author.getAsTag());
authorName.text(author.getName());
authorName.attr("data-user-id", author.getId());

content.appendChild(authorName);

if (author.isBot()) {
if (author != null && author.isBot()) {
Element botTag = document.createElement("span");
botTag.addClass("chatlog__bot-tag").text("BOT");
content.appendChild(botTag);
Expand All @@ -152,7 +181,7 @@ public InputStream generateFromMessages(Collection<Message> messages) throws IOE
messageContent.attr("title", "Message sent: "
+ message.getTimeCreated().format(DateTimeFormatter.ofPattern("HH:mm:ss")));

if (message.getContentDisplay().length() > 0) {
if (!message.getContentDisplay().isEmpty()) {
Element messageContentContent = document.createElement("div");
messageContentContent.addClass("chatlog__content");

Expand All @@ -161,13 +190,6 @@ public InputStream generateFromMessages(Collection<Message> messages) throws IOE

Element messageContentContentMarkdownSpan = document.createElement("span");
messageContentContentMarkdownSpan.addClass("preserve-whitespace");
// System.out.println(message.getContentDisplay());
// System.out.println(message.getContentDisplay().length());
// System.out.println(message.getContentStripped());
// System.out.println(message.getContentRaw());
// System.out.println(message.getContentDisplay().contains("\n"));
// System.out.println(message.getContentDisplay().contains("\r"));
// System.out.println(message.getContentDisplay().contains("\r\n"));
messageContentContentMarkdownSpan
.html(Formatter.format(message.getContentDisplay()));

Expand Down Expand Up @@ -365,13 +387,13 @@ public InputStream generateFromMessages(Collection<Message> messages) throws IOE
embedField.addClass(field.isInline() ? "chatlog__embed-field-inline"
: "chatlog__embed-field");

// Field nmae
// Field name
Element embedFieldName = document.createElement("div");
embedFieldName.addClass("chatlog__embed-field-name");

Element embedFieldNameMarkdown = document.createElement("div");
embedFieldNameMarkdown.addClass("markdown preserve-whitespace");
embedFieldNameMarkdown.html(field.getName());
embedFieldNameMarkdown.html(Objects.requireNonNull(field.getName()));

embedFieldName.appendChild(embedFieldNameMarkdown);
embedField.appendChild(embedFieldName);
Expand Down Expand Up @@ -404,7 +426,7 @@ public InputStream generateFromMessages(Collection<Message> messages) throws IOE

Element embedThumbnailLink = document.createElement("a");
embedThumbnailLink.addClass("chatlog__embed-thumbnail-link");
embedThumbnailLink.attr("href", embed.getThumbnail().getUrl());
embedThumbnailLink.attr("href", Objects.requireNonNull(embed.getThumbnail().getUrl()));

Element embedThumbnailImage = document.createElement("img");
embedThumbnailImage.addClass("chatlog__embed-thumbnail");
Expand Down Expand Up @@ -461,7 +483,7 @@ public InputStream generateFromMessages(Collection<Message> messages) throws IOE
embedFooterText.text(embed.getTimestamp() != null
? embed.getFooter().getText() + " • " + embed.getTimestamp()
.format(DateTimeFormatter.ofPattern("HH:mm:ss"))
: embed.getFooter().getText());
: Objects.requireNonNull(embed.getFooter().getText()));

embedFooter.appendChild(embedFooterText);

Expand All @@ -474,16 +496,17 @@ public InputStream generateFromMessages(Collection<Message> messages) throws IOE
}

messageGroup.appendChild(content);
assert chatLog != null;
chatLog.appendChild(messageGroup);
}
return new ByteArrayInputStream(document.outerHtml().getBytes());
}

private File findFile(String fileName) {
URL url = getClass().getClassLoader().getResource(fileName);
if (url == null) {
throw new IllegalArgumentException("file is not found: " + fileName);
private InputStream findFile() {
InputStream is = getClass().getClassLoader().getResourceAsStream("template.html");
if (is == null) {
throw new IllegalArgumentException("file is not found: " + "template.html");
}
return new File(url.getFile());
return is;
}
}
}

0 comments on commit 8d96a5f

Please sign in to comment.