package fr.ippon.tatami.web.syndic;
import com.sun.syndication.feed.rss.Channel;
import com.sun.syndication.feed.rss.Content;
import com.sun.syndication.feed.rss.Item;
import fr.ippon.tatami.service.dto.StatusDTO;
import org.pegdown.PegDownProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.view.feed.AbstractRssFeedView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* View used to generate the RSS stream corresponding to the timeline
*
* @author Pierre Rust
*/
public class SyndicView extends AbstractRssFeedView {
private final Logger log = LoggerFactory.getLogger(SyndicView.class);
@Override
protected void buildFeedMetadata(Map<String, Object> model, Channel feed, HttpServletRequest request) {
// this is mandatory: a feed with no title is invalid and is not rendered
// by the actual view implementation
String title = (String) model.get("feedTitle");
if (title == null) {
title = "This RSS feed does not exist.";
}
String description = (String) model.get("feedDescription");
if (description == null) {
description = "Either you typed a wrong URL, or the feed was removed by the user to which it belongs.";
}
String link = (String) model.get("feedLink");
if (link == null) {
link = "";
}
feed.setTitle(title);
feed.setDescription(description);
feed.setLink(link);
feed.setEncoding("UTF-8");
super.buildFeedMetadata(model, feed, request);
}
@Override
@SuppressWarnings("unchecked")
protected List<Item> buildFeedItems(Map<String, Object> model, HttpServletRequest hsr, HttpServletResponse hsr1) throws Exception {
List<Item> items = new ArrayList<Item>();
Collection<StatusDTO> listContent = (Collection<StatusDTO>) model.get("feedContent");
if (listContent == null) {
return items;
}
String statusBaseLink = (String) model.get("statusBaseLink");
for (StatusDTO tempContent : listContent) {
Item item = new Item();
String statusText = tempContent.getContent();
PegDownProcessor processor = new PegDownProcessor();
String htmlText = processor.markdownToHtml(statusText);
log.debug("feed html content {}", htmlText);
// url handling for mention & tags
htmlText = convertLinks(htmlText);
Content content = new Content();
content.setType(Content.HTML);
content.setValue(htmlText);
item.setContent(content);
// build link for the status
StringBuilder linkBuilder = new StringBuilder(statusBaseLink);
linkBuilder
.append("status/")
.append(tempContent.getStatusId());
item.setTitle(statusText.substring(0, Math.min(30, statusText.length())));
item.setLink(linkBuilder.toString());
item.setPubDate(tempContent.getStatusDate());
items.add(item);
}
return items;
}
/**
* convert #tag and @mention to html links
*
* @param htmlText the original text
* @return html with converted links
*/
private String convertLinks(String htmlText) {
// inside status : users (mention) & tags
// the regexp are converted from tatami customized marked.js
Pattern p = Pattern.compile("@([A-Za-z0-9!#$%'*+\\/=?\\^_`{|}~\\-]+(?:\\.[A-Za-z0-9!#$%'*+\\/=?\\^_`{|}~\\-]+)*)");
Matcher m = p.matcher(htmlText);
StringBuffer mentionSb = new StringBuffer();
while (m.find()) {
m.appendReplacement(mentionSb, "<a href='/tatami/home/users/$1' >$0</a>");
}
m.appendTail(mentionSb);
p = Pattern.compile("#([^\\s!\"$%'()*+,./:;<=>?@\\\\\\[\\]^_`{|}~-]+(?:\\.[^\\s !\"$%'()*+,./:;<=>?@\\\\\\[\\]^_`{|}~-]+)*)");
m = p.matcher(mentionSb.toString());
StringBuffer tagSb = new StringBuffer();
while (m.find()) {
m.appendReplacement(tagSb, "<a href='/tatami/home/tags/$1' >$0</a>");
}
m.appendTail(tagSb);
return tagSb.toString();
}
}