package de.srsoftware.widerhall.data; import de.srsoftware.widerhall.Util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.internet.InternetAddress; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import static de.srsoftware.widerhall.Constants.*; import static de.srsoftware.widerhall.Constants.VARCHAR; public class Post { public static final Logger LOG = LoggerFactory.getLogger(Post.class); public static final String TABLE_NAME = "Posts"; private static final String FROM_ADDR = "from_addr"; private static final String FROM_NAME = "from_name"; private static final String PARENT = "parent"; private static final String LONG = "LONG"; private static final String DATE = "date"; private static final String FILE = "file"; private static HashMap cache = new HashMap<>(); private String id, fromAddr, fromName, subject, filename; private MailingList list; private Post parent; private Long timestamp; public Post(String id, MailingList list, String fromAddr, String fromName, String subject, Long timestamp){ this.id = id; this.list = list; this.fromAddr = fromAddr; this.fromName = fromName; this.subject = subject; this.timestamp = timestamp; this.filename = generateFilename(); } public static Post create(MailingList list, Message message){ try { var id = message.getHeader("Message-ID")[0].replace("<", "").replace(">", ""); var addr = ((InternetAddress) message.getFrom()[0]); var fromEmail = addr.getAddress(); var fromName = addr.getPersonal(); if (fromName == null || fromName.isBlank()) fromName = fromEmail.split("@")[0] + "@xxxxxx"; var subject = message.getSubject(); var text = Util.getText(message); var time = message.getSentDate().getTime(); Post post = new Post(id,list,fromEmail,fromName,subject,time); Files.writeString(post.file().toPath(),text, StandardCharsets.UTF_8); return post.save(); } catch (MessagingException | IOException | SQLException e) { LOG.warn("Failed to create post from {}",message); } return null; } /** * create posts table * @throws SQLException */ public static void createTable() throws SQLException { var sql = new StringBuilder() .append("CREATE TABLE ").append(TABLE_NAME) .append(" (") .append(ID).append(" ").append(VARCHAR).append(" NOT NULL PRIMARY KEY, ") .append(LIST).append(" ").append(VARCHAR).append(", ") .append(FROM_ADDR).append(" ").append(VARCHAR).append(", ") .append(FROM_NAME).append(" ").append(VARCHAR).append(", ") .append(PARENT).append(" ").append(VARCHAR).append(", ") .append(SUBJECT).append(" ").append(VARCHAR).append(", ") .append(DATE).append(" ").append(LONG).append(", ") .append(FILE).append(" ").append(VARCHAR) .append(");"); Database.open().query(sql).compile().run(); } public File file(){ return new File(filename); } public static HashSet find(MailingList list) throws SQLException { var rs = Database.open().select(TABLE_NAME).where(LIST,list.email()).compile().exec(); try { var result = new HashSet(); while (rs.next()) result.add(Post.from(rs)); return result; } finally { rs.close(); } } private static Post from(ResultSet rs) { try { var id = rs.getString(ID); var post = cache.get(id); if (post == null) { var list = MailingList.load(rs.getString(LIST)); post = new Post(id, list, rs.getString(FROM_ADDR), rs.getString(FROM_NAME), rs.getString(SUBJECT), rs.getLong(DATE)); cache.put(id,post); } return post; } catch (SQLException e){ LOG.debug("Failed to load Post from database!",e); } return null; } private String generateFilename() { return "/tmp/"+id+".json"; } public String id() { return id; } public static Post load(String id) throws SQLException { var rs = Database.open().select(TABLE_NAME).where(ID,id).compile().exec(); try { if (rs.next()) return Post.from(rs); } finally { rs.close(); } return null; } public Map map() { return Map.of(ID,id, LIST,list.email(), FROM_ADDR,fromAddr, FROM_NAME,fromName, SUBJECT,subject, DATE,timestamp, FILE,filename); } public Map safeMap() { return Map.of(ID,id, LIST,list.name(), FROM_NAME,fromName, SUBJECT,Util.dropEmail(subject), DATE,timestamp); } private Post save() throws SQLException { Database.open().insertInto(TABLE_NAME).values(map()).compile().run(); return this; } public long timestamp(){ return timestamp; } }