package org.manalith.ircbot.plugin.feedreader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;
import java.util.List;
import org.manalith.ircbot.ManalithBot;
import org.manalith.ircbot.plugin.SimplePlugin;
import org.manalith.ircbot.resources.MessageEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;
@Component
public class FeedReaderPlugin extends SimplePlugin {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private FeedDao feedDao;
@Override
public String getName() {
return "피드리더";
}
@Override
public String getCommands() {
return "!feed, !feedreg, !feedrm";
}
@Override
public String getHelp() {
return "설 명: RSS 피드를 읽어옵니다, 사용법: !feed|!feedreg|!feedrm [피드주소]";
}
@Override
public void onMessage(MessageEvent event) {
String[] segments = event.getMessageSegments();
if (segments.length >= 1 && segments[0].startsWith("!feed")) {
if (segments.length == 2 && segments[0].equals("!feed")) {
try {
String url = segments[1];
SyndEntry entry = getNewestEntry(url);
if (entry != null) {
event.respond(entry.getTitle() + " - " + entry.getUri());
} else {
event.respond(url + " 에 컨텐츠가 없습니다.");
}
} catch (MalformedURLException e) {
logger.warn(e.getMessage(), e);
event.respond(segments[1] + "은 지원하지 않는 URL입니다.");
} catch (IllegalArgumentException | FeedException | IOException e) {
logger.warn(e.getMessage(), e);
event.respond("오류가 발생했습니다 : " + e.getMessage());
}
} else if (segments.length == 2 && segments[0].equals("!feedreg")) {
String url = segments[1];
try {
Feed feed = feedDao.findByUrl(url);
if (feed != null) {
event.respond("이미 등록된 피드입니다 : " + url);
return;
}
SyndEntry entry = getNewestEntry(url);
feed = new Feed();
feed.setUrl(url);
feed.setDate(new Date());
feed.setUser(event.getUser().getNick());
feed.setChannel(event.getChannel().getName());
feed.setLatestContents(entry.getTitle());
feedDao.save(feed);
event.respond(entry.getTitle() + " - " + entry.getLink());
event.respond("이제 주기적으로 다음 피드를 확인합니다 : " + url);
} catch (Exception e) {
logger.warn(e.getMessage(), e);
event.respond("피드를 등록하던 중 오류가 발생했습니다 : " + e.getMessage());
}
} else if (segments.length == 2 && segments[0].equals("!feedrm")) {
String url = segments[1];
Feed feed = feedDao
.findByUrl(url, event.getChannel().getName());
if (feed != null) {
feedDao.delete(feed);
event.respond("피드가 삭제되었습니다 : " + url);
} else {
event.respond("등록된 피드가 없습니다 : " + url);
}
} else {
event.respond(getHelp());
}
}
}
@Scheduled(fixedDelay = 1000 * 60 * 5)
public void feedUpdateCheck() {
List<Feed> feeds = feedDao.findAll();
for (Feed f : feeds) {
logger.trace("피드 검사 : " + f.getUrl());
try {
// FIXME 비동기로 동작하도록 수정
SyndEntry entry = getNewestEntry(f.getUrl());
if (!entry.getTitle().equals(f.getLatestContents())) {
// TODO 단축 주소로 변환
ManalithBot.getInstance().sendMessage(
f.getChannel(),
"[Feed]" + entry.getTitle() + " - "
+ entry.getLink());
f.setLatestContents(entry.getTitle());
feedDao.update(f);
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}
private SyndEntry getNewestEntry(String url) throws MalformedURLException,
IllegalArgumentException, FeedException, IOException {
URL feedUrl = new URL(url);
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(new XmlReader(feedUrl));
@SuppressWarnings("unchecked")
List<SyndEntry> feedEntries = feed.getEntries();
if (feedEntries.size() == 0) {
return null;
} else {
return feedEntries.get(0);
}
}
}