You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
6.9 KiB
200 lines
6.9 KiB
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.*; |
|
|
|
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 DATE = "date"; |
|
private static final String FILE = "file"; |
|
private static final String FROM_ADDR = "from_addr"; |
|
private static final String FROM_NAME = "from_name"; |
|
private static final String LONG = "LONG"; |
|
private static final String PARENT = "parent"; |
|
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, List<String> allowedSenders) throws SQLException { |
|
var query = Database.open() |
|
.select(TABLE_NAME,"*","strftime('%Y-%m',date/1000,'unixepoch') as month") |
|
.where(LIST,list.email()) |
|
.where(MONTH,month); |
|
if (allowedSenders != null) query = query.where(FROM_ADDR,allowedSenders); |
|
var rs = query.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 MailingList list() { |
|
return list; |
|
} |
|
|
|
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 void remove() throws SQLException { |
|
Database.open().deleteFrom(TABLE_NAME).where(ID,id).compile().run(); |
|
file().delete(); |
|
} |
|
|
|
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,List<String> limitedUsers) throws SQLException { |
|
var sql = new StringBuilder("SELECT count(*) as count,strftime('%Y-%m',date/1000,'unixepoch') as month FROM Posts"); |
|
var query = Database.open().query(sql).where(LIST,list.email()).groupBy(MONTH).sort(MONTH); |
|
if (limitedUsers != null) query.where(FROM_ADDR,limitedUsers); |
|
var rs = query.compile().exec(); |
|
|
|
var map = new TreeMap<String,Object>(); |
|
while (rs.next()) map.put(rs.getString("month"),rs.getInt("count")); |
|
rs.close(); |
|
return map; |
|
} |
|
|
|
public long timestamp(){ |
|
return timestamp; |
|
} |
|
}
|
|
|