More fixes, should work now

This commit is contained in:
Johannes Frohnmeyer 2022-10-22 23:55:55 +02:00
parent 694ddece28
commit 95ec7be10b
Signed by: Johannes
GPG Key ID: E76429612C2929F4
7 changed files with 39 additions and 28 deletions

View File

@ -25,6 +25,7 @@ dependencies {
implementation("com.kohlschutter.junixsocket:junixsocket-core:2.6.0") implementation("com.kohlschutter.junixsocket:junixsocket-core:2.6.0")
implementation("org.jsoup:jsoup:1.15.3") implementation("org.jsoup:jsoup:1.15.3")
implementation("net.freeutils:jlhttp:2.6") implementation("net.freeutils:jlhttp:2.6")
implementation("org.commonmark:commonmark:0.20.0")
compileOnly("org.jetbrains:annotations:23.0.0") compileOnly("org.jetbrains:annotations:23.0.0")
} }

View File

@ -8,11 +8,15 @@ import io.gitlab.jfronny.gitea.helpdesk.gitea.*;
import io.gitlab.jfronny.gitea.helpdesk.mail.*; import io.gitlab.jfronny.gitea.helpdesk.mail.*;
import io.gitlab.jfronny.gitea.helpdesk.web.WebInterface; import io.gitlab.jfronny.gitea.helpdesk.web.WebInterface;
import jakarta.mail.MessagingException; import jakarta.mail.MessagingException;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
public record UpdateTask(DBInterface db, MailInterface mail, GiteaInterface gitea, WebInterface web) implements Runnable { public record UpdateTask(DBInterface db, MailInterface mail, GiteaInterface gitea, WebInterface web) implements Runnable {
private static final Parser MARKDOWN_PARSER = Parser.builder().build();
private static final HtmlRenderer MARKDOWN_RENDER = HtmlRenderer.builder().build();
private static final String TEMPLATE = Main.getResource("/mail/template.html"); private static final String TEMPLATE = Main.getResource("/mail/template.html");
private static final String MAIL_ERROR = Main.getResource("/mail/error.html"); private static final String MAIL_ERROR = Main.getResource("/mail/error.html");
private static final String MAIL_UNEXPECTED = Main.getResource("/mail/unexpected.html"); private static final String MAIL_UNEXPECTED = Main.getResource("/mail/unexpected.html");
@ -42,7 +46,6 @@ public record UpdateTask(DBInterface db, MailInterface mail, GiteaInterface gite
ThrowingBiConsumer<String, String, Exception> reply = (content, subject) -> { ThrowingBiConsumer<String, String, Exception> reply = (content, subject) -> {
String[] previousMessages = subscription.referenceChain().split(" "); String[] previousMessages = subscription.referenceChain().split(" ");
String previousMessageId = previousMessages[previousMessages.length - 1]; String previousMessageId = previousMessages[previousMessages.length - 1];
//TODO test
mail.reply(addressParts[0] + "+reply+" + subscription.id(), subscription.email(), content, subject, previousMessageId, subscription.referenceChain(), null); mail.reply(addressParts[0] + "+reply+" + subscription.id(), subscription.email(), content, subject, previousMessageId, subscription.referenceChain(), null);
}; };
GiteaIssue issue; GiteaIssue issue;
@ -53,13 +56,13 @@ public record UpdateTask(DBInterface db, MailInterface mail, GiteaInterface gite
db.removeSubscription(subscription.id()); db.removeSubscription(subscription.id());
return; return;
} }
if (issue.state.equals("closed")) { //TODO test if (issue.state.equals("closed")) {
reply.accept(template(MAIL_ISSUE_CLOSED), "Issue closed"); reply.accept(template(MAIL_ISSUE_CLOSED), "Issue closed");
db.removeSubscription(subscription.id()); db.removeSubscription(subscription.id());
} }
for (GiteaIssueComment comment : gitea.getComments(subscription.repoOwner(), subscription.repo(), subscription.issue())) { for (GiteaIssueComment comment : gitea.getComments(subscription.repoOwner(), subscription.repo(), subscription.issue())) {
if (comment.id > subscription.issueComment()) { if (comment.id > subscription.issueComment()) {
reply.accept(comment.body, issue.title); reply.accept(MARKDOWN_RENDER.render(MARKDOWN_PARSER.parse(comment.body)), issue.title);
db.updateSubscriptionIssueComment(subscription.id(), comment.id); db.updateSubscriptionIssueComment(subscription.id(), comment.id);
} }
} }
@ -79,19 +82,20 @@ public record UpdateTask(DBInterface db, MailInterface mail, GiteaInterface gite
String repo = args[2]; String repo = args[2];
checkArgs(owner, repo); checkArgs(owner, repo);
GiteaIssue issue = gitea.createIssue(owner, repo, message.getSubject(), formatBody(message)); GiteaIssue issue = gitea.createIssue(owner, repo, message.getSubject(), formatBody(message));
String id = db.addSubscription(message.getSender(), owner, repo, issue.id, 0, message.getSender(), true); String id = db.addSubscription(message.getSender(), owner, repo, issue.id, 0, message.getMessageID(), true);
String unsubscribeUrl = web.getAddress() + "/unsubscribe?id=" + id; //TODO test String unsubscribeUrl = web.getAddress() + "/unsubscribe?id=" + id;
message.reply(addressParts[0] + "+reply+" + owner + "+" + repo + "+" + issue.id + '@' + addressParts[1], template(MAIL_CREATE.formatted(issue.url, unsubscribeUrl))); String closeUrl = web.getAddress() + "/close?id=" + id;
message.reply(addressParts[0] + "+reply+" + id + '@' + addressParts[1], template(MAIL_CREATE.formatted(issue.url, unsubscribeUrl, closeUrl)));
} }
case "reply" -> { case "reply" -> {
if (args.length != 2) throw new UnexpectedMailException("Reply classifier only allows one parameter"); if (args.length != 2) throw new UnexpectedMailException("Reply classifier only allows one parameter");
Subscription sub = db.getSubscription(args[1]).orElseThrow(() -> new UnexpectedMailException("Reply classifier does not represent an active issue")); Subscription sub = db.getSubscription(args[1]).orElseThrow(() -> new UnexpectedMailException("Reply classifier does not represent an active issue"));
GiteaIssueComment commentId = gitea.addComment(sub.repoOwner(), sub.repo(), sub.issue(), formatBody(message)); GiteaIssueComment commentId = gitea.addComment(sub.repoOwner(), sub.repo(), sub.issue(), formatBody(message));
db.updateSubscriptionIssueComment(sub.id(), commentId.id); db.updateSubscriptionIssueComment(sub.id(), commentId.id);
db.updateSubscriptionReferenceChain(sub.id(), sub.referenceChain() + " " + message.getSender()); db.updateSubscriptionReferenceChain(sub.id(), sub.referenceChain() + " " + message.getMessageID());
} }
case "comment" -> { case "comment" -> {
if (args.length == 4) throw new UnexpectedMailException("Comment classifier requires four parameters"); if (args.length != 4) throw new UnexpectedMailException("Comment classifier requires four parameters");
String owner = args[1]; String owner = args[1];
String repo = args[2]; String repo = args[2];
long issueId = Long.parseLong(args[3]); long issueId = Long.parseLong(args[3]);
@ -102,13 +106,13 @@ public record UpdateTask(DBInterface db, MailInterface mail, GiteaInterface gite
} catch (FileNotFoundException fe) { } catch (FileNotFoundException fe) {
throw new UnexpectedMailException("This issue does not exist"); throw new UnexpectedMailException("This issue does not exist");
} }
gitea.addComment(owner, repo, issueId, formatBody(message)); long issueComment = gitea.addComment(owner, repo, issueId, formatBody(message)).id;
if (issue.state.equals("closed")) { if (issue.state.equals("closed")) {
message.reply(addressParts[0] + "+reply+" + owner + "+" + repo + "+" + issue.id + '@' + addressParts[1], template(MAIL_COMMENT_CLOSED.formatted(issue.url))); message.reply(mail.getAddress(), template(MAIL_COMMENT_CLOSED.formatted(issue.url)));
} else { } else {
String id = db.addSubscription(message.getSender(), owner, repo, issue.id, 0, message.getSender(), false); String id = db.addSubscription(message.getSender(), owner, repo, issue.id, issueComment, message.getMessageID(), false);
String unsubscribeUrl = web.getAddress() + "/unsubscribe?id=" + id; //TODO test String unsubscribeUrl = web.getAddress() + "/unsubscribe?id=" + id;
message.reply(addressParts[0] + "+reply+" + owner + "+" + repo + "+" + issue.id + '@' + addressParts[1], template(MAIL_COMMENT.formatted(issue.url, unsubscribeUrl))); message.reply(addressParts[0] + "+reply+" + id + '@' + addressParts[1], template(MAIL_COMMENT.formatted(issue.url, unsubscribeUrl)));
} }
} }
default -> throw new UnexpectedMailException("Did not expect classifier " + args[0]); default -> throw new UnexpectedMailException("Did not expect classifier " + args[0]);

View File

@ -21,22 +21,22 @@ public class DBInterface implements AutoCloseable {
try (Connection cx = ds.getConnection()) { try (Connection cx = ds.getConnection()) {
try (Statement st = cx.createStatement()) { try (Statement st = cx.createStatement()) {
st.executeUpdate(""" st.executeUpdate("""
CREATE EXTENSION pgcrypto; create extension if not exists pgcrypto;
CREATE OR REPLACE FUNCTION helpdesk_generate_uid(size INT) RETURNS TEXT AS $$ create or replace function helpdesk_generate_uid(size int) returns text as $$
DECLARE declare
characters TEXT := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; characters text := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
bytes BYTEA := gen_random_bytes(size); bytes bytea := gen_random_bytes(size);
l INT := length(characters); l int := length(characters);
i INT := 0; i int := 0;
output TEXT := ''; output text := '';
BEGIN BEGIN
WHILE i < size LOOP while i < size loop
output := output || substr(characters, get_byte(bytes, i) % l + 1, 1); output := output || substr(characters, get_byte(bytes, i) % l + 1, 1);
i := i + 1; i := i + 1;
END LOOP; end loop;
RETURN output; return output;
END; END;
$$ LANGUAGE plpgsql VOLATILE; $$ language plpgsql volatile;
create table if not exists helpdesk_subscriptions( create table if not exists helpdesk_subscriptions(
id text primary key default helpdesk_generate_uid(20), id text primary key default helpdesk_generate_uid(20),
email text, email text,

View File

@ -66,7 +66,7 @@ public class MailInterface implements AutoCloseable {
MimeMessage reply = new MimeMessage(smtp); MimeMessage reply = new MimeMessage(smtp);
reply.setFrom(from); reply.setFrom(from);
reply.addRecipients(Message.RecipientType.TO, to); reply.addRecipients(Message.RecipientType.TO, to);
reply.setSubject(subject.startsWith("Re: ") ? subject : "Re: " + subject); reply.setSubject(subject == null ? "Reply" : subject.startsWith("Re: ") ? subject : "Re: " + subject);
final MimeBodyPart textPart = new MimeBodyPart(); final MimeBodyPart textPart = new MimeBodyPart();
textPart.setContent(Jsoup.parse(content).text(), "text/plain"); textPart.setContent(Jsoup.parse(content).text(), "text/plain");

View File

@ -91,6 +91,10 @@ public class WrappedMessage {
return "Sender Suppressed"; return "Sender Suppressed";
} }
public String getMessageID() throws MessagingException {
return message.getMessageID();
}
public void reply(String from, String content) throws MessagingException { public void reply(String from, String content) throws MessagingException {
mail.reply( mail.reply(
from, from,

View File

@ -1,4 +1,5 @@
<h1>Successfully added issue</h1> <h1>Successfully added issue</h1>
<p>You can find your new issue <a href="%s">here</a></p> <p>You can find your new issue <a href="%s">here</a></p>
<p>If you wish to unsubscribe from new comments, you may do so <a href="%s">here</a></p> <p>If you wish to unsubscribe from new comments, you may do so <a href="%s">here</a></p>
<p>Please be aware that you will not be sent these a second time!</p> <p>Please be aware that you will not be sent these a second time!</p>
<p>If this was a mistake or you resolved the issue yourself, you can close it <a href="%s">here</a></p>

View File

@ -1,2 +1,3 @@
<h1>This issue was moved or deleted</h1> <h1>This issue was moved or deleted</h1>
<p>This issue was moved or deleted and is no longer accessible</p> <p>This issue was moved or deleted and is no longer accessible</p>
<p>Your subscription has therefore been removed</p>