191 lines
6.5 KiB
Java
191 lines
6.5 KiB
Java
package de.srsoftware.widerhall.data;
|
|
|
|
import de.srsoftware.widerhall.Configuration;
|
|
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.sql.Timestamp;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.TreeMap;
|
|
|
|
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<String, Post> 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);
|
|
var file = post.file();
|
|
file.getParentFile().mkdirs();
|
|
Files.writeString(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 ArrayList<Post> find(MailingList list, String month) throws SQLException {
|
|
var rs = Database.open()
|
|
.select(TABLE_NAME,"*","strftime('%Y-%m',date/1000,'unixepoch') as month")
|
|
.where(LIST,list.email())
|
|
.where(MONTH,month)
|
|
.sort(DATE)
|
|
.compile()
|
|
.exec();
|
|
try {
|
|
var result = new ArrayList<Post>();
|
|
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));
|
|
post.filename = rs.getString(FILE);
|
|
cache.put(id,post);
|
|
}
|
|
return post;
|
|
} catch (SQLException e){
|
|
LOG.debug("Failed to load Post from database!",e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
|
|
private String generateFilename() {
|
|
return Configuration.instance().archiveDir()+File.separator+id+".txt";
|
|
}
|
|
|
|
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<String,Object> map() {
|
|
return Map.of(ID,id,
|
|
LIST,list.email(),
|
|
FROM_ADDR,fromAddr,
|
|
FROM_NAME,fromName,
|
|
SUBJECT,subject,
|
|
DATE,timestamp,
|
|
FILE,filename);
|
|
}
|
|
|
|
public Map<String,Object> safeMap() {
|
|
return Map.of(ID,id,
|
|
LIST,list.name(),
|
|
FROM_NAME,fromName,
|
|
SUBJECT,Util.dropEmail(subject),
|
|
DATE, new Timestamp(timestamp).toString());
|
|
}
|
|
|
|
private Post save() throws SQLException {
|
|
Database.open().insertInto(TABLE_NAME).values(map()).compile().run();
|
|
return this;
|
|
}
|
|
|
|
public static Map<String, Object> summarize(MailingList list) throws SQLException {
|
|
var sql = new StringBuilder("SELECT count(*) as count,strftime('%Y-%m',date/1000,'unixepoch') as month FROM Posts WHERE list = ? GROUP BY month ORDER BY month;");
|
|
var map = new TreeMap<String,Object>();
|
|
var rs = Database.open().query(sql).compile(list.email()).exec();
|
|
while (rs.next()) map.put(rs.getString("month"),rs.getInt("count"));
|
|
rs.close();
|
|
return map;
|
|
}
|
|
|
|
public long timestamp(){
|
|
return timestamp;
|
|
}
|
|
|
|
}
|