public void testParse() throws Exception {
    final SyndFeedInput input = new SyndFeedInput();

    final SyndFeed feed = input.build(new File(super.getTestFile("xml/custom-tags-example.xml")));
    final List<SyndEntry> entries = feed.getEntries();
    final SyndEntry entry = entries.get(0);
    final CustomTags customTags = (CustomTags) entry.getModule(CustomTags.URI);
    final Iterator<CustomTag> it = customTags.getValues().iterator();
    while (it.hasNext()) {
      final CustomTag tag = it.next();
      LOG.debug("{}", tag);
      if (tag.getName().equals("language_skills")) {
        Assert.assertEquals("Fluent in English and German", tag.getValue());
      }
      if (tag.getName().equals("prior_experience_years")) {
        Assert.assertEquals(new Integer(5), tag.getValue());
      } else if (tag.getName().equals("start_date")) {
        final Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(0);
        cal.set(2005, 10, 15, 0, 0, 0);
        Assert.assertEquals(cal.getTime(), tag.getValue());
      } else if (tag.getName().equals("test_url")) {
        Assert.assertEquals(new URL("http://www.screaming-penguin.com"), tag.getValue());
      } else if (tag.getName().equals("test_boolean")) {
        Assert.assertEquals(new Boolean(true), tag.getValue());
      } else if (tag.getName().equals("test_intUnit")) {
        Assert.assertEquals(new IntUnit(25, "horses"), tag.getValue());
      } else if (tag.getName().equals("test_floatUnit")) {
        Assert.assertEquals(new FloatUnit((float) 2.5, "cows"), tag.getValue());
      } else if (tag.getName().equals("test_location")) {
        Assert.assertEquals(
            new CustomTagImpl.Location("125 Main St, Sometown, GA"), tag.getValue());
      } else if (tag.getName().equals("test_dateRange")) {
        final Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(0);
        cal.set(2005, 06, 04, 20, 0, 0);
        final Date start = cal.getTime();
        cal.set(2005, 06, 04, 23, 0, 0);
        final DateTimeRange dtr = new DateTimeRange(start, cal.getTime());
        Assert.assertEquals(dtr, tag.getValue());
      }
    }
  }
Exemple #2
0
 public void notifySubscribers(SyndEntry[] entries) {
   for (SyndEntry entry : entries) {
     for (String destination : subscribers) {
       Main.getBot()
           .sendMessage(
               destination,
               String.format(
                   "["
                       + Colors.BOLD
                       + "RSS - %s"
                       + Colors.NORMAL
                       + "]"
                       + " ["
                       + Colors.BOLD
                       + "%s"
                       + Colors.NORMAL
                       + "]"
                       + Colors.BLUE
                       + Colors.BOLD
                       + " %s"
                       + Colors.NORMAL
                       + ": "
                       + Colors.DARK_GREEN
                       + "%s"
                       + Colors.NORMAL
                       + " ("
                       + Colors.OLIVE
                       + Colors.BOLD
                       + "%s"
                       + Colors.NORMAL
                       + ")",
                   title,
                   entry.getPublishedDate().toString(),
                   entry.getAuthor(),
                   entry.getTitle(),
                   entry.getLink()));
     }
   }
 }
  /** 全文输出 */
  @At
  @Ok("raw:xml")
  public String rss() throws IOException, FeedException {
    SyndFeed feed = new SyndFeedImpl();
    feed.setFeedType("rss_2.0");
    String urlbase = conf.get("website.urlbase", "https://nutz.cn");
    feed.setLink(urlbase);
    feed.setTitle(conf.get("website.title", "Nutz社区"));
    feed.setDescription(conf.get("website.description", "一个有爱的社区"));

    feed.setAuthor(conf.get("website.author", "wendal"));
    feed.setEncoding("UTF-8");
    feed.setLanguage("zh-cn");

    List<SyndEntry> entries = new ArrayList<SyndEntry>();
    SyndEntry entry;
    SyndContent description;
    List<Topic> list =
        dao.query(Topic.class, Cnd.orderBy().desc("createTime"), dao.createPager(1, 10));
    for (Topic topic : list) {
      dao.fetchLinks(topic, "author");
      entry = new SyndEntryImpl();
      entry.setTitle(topic.getTitle());
      entry.setLink(urlbase + "/yvr/t/" + topic.getId());
      entry.setPublishedDate(topic.getCreateTime());
      description = new SyndContentImpl();
      description.setType("text/html");
      description.setValue(Markdowns.toHtml(topic.getContent(), urlbase));
      entry.setDescription(description);
      entry.setAuthor(topic.getAuthor().getLoginname());
      entries.add(entry);
    }

    feed.setEntries(entries);
    if (list.size() > 0) {
      feed.setPublishedDate(list.get(0).getCreateTime());
    }

    SyndFeedOutput output = new SyndFeedOutput();
    return output.outputString(feed, true);
  }
  @SuppressWarnings("unchecked")
  public void setPodcastFeedAttributes(Podcast podcast, boolean feedPropertyHasBeenSet)
      throws IllegalArgumentException, FeedException, IOException {

    SyndFeed syndFeed = null;
    if (!feedPropertyHasBeenSet) {
      syndFeed = syndFeedService.getSyndFeedForUrl(podcast.getUrl());
      podcast.setPodcastFeed(syndFeed);
    }

    if (syndFeed != null) {
      // set DESCRIPTION for podcast - used in search
      if (syndFeed.getDescription() != null && !syndFeed.getDescription().equals("")) {
        String description = syndFeed.getDescription();
        // out of description remove tags if any exist and store also
        // short description
        String descWithoutTabs = description.replaceAll("\\<[^>]*>", "");
        if (descWithoutTabs.length() > MAX_LENGTH_DESCRIPTION) {
          podcast.setDescription(descWithoutTabs.substring(0, MAX_LENGTH_DESCRIPTION));
        } else {
          podcast.setDescription(descWithoutTabs);
        }
      }

      // set TITLE - used in search
      String podcastTitle = syndFeed.getTitle();
      podcast.setTitle(podcastTitle);

      // build the title that will appear in the URL when accessing a
      // podcast from the main application
      String titleInUrl = podcastTitle.trim().replaceAll("[^a-zA-Z0-9\\-\\s\\.]", "");
      titleInUrl = titleInUrl.replaceAll("[\\-| |\\.]+", "-");
      if (titleInUrl.length() > TITLE_IN_URL_MAX_LENGTH) {
        podcast.setTitleInUrl(titleInUrl.substring(0, TITLE_IN_URL_MAX_LENGTH));
      } else {
        podcast.setTitleInUrl(titleInUrl);
      }

      // set author
      podcast.setAuthor(syndFeed.getAuthor());

      // set COPYRIGHT
      podcast.setCopyright(syndFeed.getCopyright());

      // set LINK
      podcast.setLink(syndFeed.getLink());

      // set url link of the podcast's image when selecting the podcast in
      // the main application - mostly used through <a
      // href="urlOfImageToDisplay"....
      SyndImage podcastImage = syndFeed.getImage();
      if (null != podcastImage) {
        if (podcastImage.getUrl() != null) {
          podcast.setUrlOfImageToDisplay(podcastImage.getUrl());
        } else if (podcastImage.getLink() != null) {
          podcast.setUrlOfImageToDisplay(podcastImage.getLink());
        } else {
          podcast.setUrlOfImageToDisplay(configBean.get("NO_IMAGE_LOCAL_URL"));
        }
      } else {
        podcast.setUrlOfImageToDisplay(configBean.get("NO_IMAGE_LOCAL_URL"));
      }

      podcast.setPublicationDate(null); // default value is null, if cannot
      // be set

      // set url media link of the last episode - this is used when
      // generating the ATOM and RSS feeds from the Start page for example
      for (SyndEntry entry : (List<SyndEntry>) syndFeed.getEntries()) {
        // get the list of enclosures
        List<SyndEnclosure> enclosures = (List<SyndEnclosure>) entry.getEnclosures();

        if (null != enclosures) {
          // if in the enclosure list is a media type (either audio or
          // video), this will set as the link of the episode
          for (SyndEnclosure enclosure : enclosures) {
            if (null != enclosure) {
              podcast.setLastEpisodeMediaUrl(enclosure.getUrl());
              break;
            }
          }
        }

        if (entry.getPublishedDate() == null) {
          LOG.warn(
              "PodURL["
                  + podcast.getUrl()
                  + "] - "
                  + "COULD NOT SET publication date for podcast, default date 08.01.1983 will be used ");
        } else {
          podcast.setPublicationDate(entry.getPublishedDate());
        }
        // first episode in the list is last episode - normally (are
        // there any exceptions?? TODO -investigate)
        break;
      }
    }
  }
  public void setEpisodeAttributes(Episode episode, Podcast podcast, SyndEntry entry) {
    // set DESCRIPTION for episode - used in search
    if (null != entry.getDescription()) {

      String episodeDesc = entry.getDescription().getValue();
      // tags are removed from description
      String descWithoutTabs = episodeDesc.replaceAll("\\<[^>]*>", "");
      // carriage returns are removed from description - for player
      String descWithoutEndOfLine = descWithoutTabs.replaceAll("\\n", "");
      if (descWithoutEndOfLine.length() > MAX_LENGTH_DESCRIPTION) {
        episode.setDescription(descWithoutEndOfLine.substring(0, MAX_LENGTH_DESCRIPTION));
      } else {
        episode.setDescription(descWithoutEndOfLine);
      }
    }

    // set author
    episode.setAuthor(entry.getAuthor());

    // set title for episode - used in search
    String episodeTitle = entry.getTitle();
    if (episodeTitle != null) {
      // removes quotes to display properly in player
      episodeTitle = episodeTitle.replaceAll("\"", "");
      if (episodeTitle.length() > MAX_PERMITTED_TITLE_LENGTH) {
        episodeTitle = episodeTitle.substring(0, MAX_PERMITTED_TITLE_LENGTH);
      }
      episode.setTitle(episodeTitle);
      String titleInUrl = episodeTitle.trim().replaceAll("[^a-zA-Z0-9\\-\\s\\.]", "");
      titleInUrl = titleInUrl.replaceAll("[\\-| |\\.]+", "-");
      if (titleInUrl.length() > TITLE_IN_URL_MAX_LENGTH) {
        episode.setTitleInUrl(titleInUrl.substring(0, TITLE_IN_URL_MAX_LENGTH));
      } else {
        episode.setTitleInUrl(titleInUrl);
      }
    }

    episode.setLink(entry.getLink());

    // in the beginning inherit the media type from the podcast
    episode.setMediaType(podcast.getMediaType());

    // get the list of enclosures
    @SuppressWarnings("unchecked")
    List<SyndEnclosure> enclosures = (List<SyndEnclosure>) entry.getEnclosures();

    List<String> audioMimeTypesList = Arrays.asList(audioMimeTypesArray);
    List<String> videoMimeTypesList = Arrays.asList(videoMimeTypesArray);

    // set media url for the episode - this will be played in the player
    if (null != enclosures) {
      // if in the enclosure list is a media type (either audio or video),
      // this will set as the link of the episode
      for (SyndEnclosure enclosure : enclosures) {
        if (null != enclosure) {
          episode.setMediaUrl(enclosure.getUrl());
          if (enclosure.getLength() >= 0) episode.setLength(enclosure.getLength());
          // when adding a new podcast media type is selected for the
          // podcast based on an initial view, but it can be that is a
          // mixed podcast so both audio
          // and video should be considered and in that case PRIORITY
          // has the type of the episode if any...
          if (null != enclosure.getType()) {
            episode.setEnclosureType(enclosure.getType().trim());
            if (audioMimeTypesList.contains(enclosure.getType().trim())) {
              episode.setMediaType(MediaType.Audio);
              break;
            }
            if (videoMimeTypesList.contains(enclosure.getType().trim())) {
              episode.setMediaType(MediaType.Video);
              break;
            }
          }
        }
      }
    } else {
      episode.setMediaUrl("noMediaUrl");
    }

    if (episode.getMediaUrl() == null) {
      episode.setMediaUrl("noMediaUrl");
    }

    if (episode.getMediaUrl() == null || episode.getMediaUrl().equals("noMediaUrl")) {
      LOG.warn(
          "PodcastId["
              + podcast.getPodcastId()
              + "] - "
              + "COULD NOT SET MEDIA URL - "
              + "epTitle["
              + entry.getTitle()
              + "]"
              + "feed["
              + podcast.getUrl()
              + "]");
    }

    // set link attribute
    episode.setLink(entry.getLink());

    episode.setPublicationDate(entry.getPublishedDate());
    updatePodcastPublicationDateAndLastMediaUrl(episode, podcast);

    if (episode.getPublicationDate() == null) {
      LOG.warn(
          "PodcastId["
              + podcast.getPodcastId()
              + "] - "
              + "COULD NOT SET publication date "
              + "epTitle["
              + entry.getTitle()
              + "]"
              + "feed["
              + podcast.getUrl()
              + "]");
    }
  }
  private List<Outlink> parseFeed(String url, byte[] content, Metadata parentMetadata)
      throws MalformedURLException {
    List<Outlink> links = new ArrayList<>();

    SyndFeed feed = null;
    try (ByteArrayInputStream is = new ByteArrayInputStream(content)) {
      SyndFeedInput input = new SyndFeedInput();
      feed = input.build(new InputSource(is));
    } catch (Exception e) {
      LOG.error("Exception parsing feed from DOM {}", url);
      return links;
    }

    URL sURL = new URL(url);

    List<SyndEntry> entries = feed.getEntries();
    for (SyndEntry entry : entries) {
      String targetURL = entry.getLink();

      // build an absolute URL
      try {
        targetURL = URLUtil.resolveURL(sURL, targetURL).toExternalForm();
      } catch (MalformedURLException e) {
        LOG.debug("MalformedURLException on {}", targetURL);
        continue;
      }

      targetURL = urlFilters.filter(sURL, parentMetadata, targetURL);

      if (StringUtils.isBlank(targetURL)) continue;

      Outlink newLink = new Outlink(targetURL);

      Metadata targetMD = metadataTransfer.getMetaForOutlink(targetURL, url, parentMetadata);
      newLink.setMetadata(targetMD);

      String title = entry.getTitle();
      if (StringUtils.isNotBlank(title)) {
        targetMD.setValue("feed.title", title.trim());
      }

      Date publishedDate = entry.getPublishedDate();
      if (publishedDate != null) {
        // filter based on the published date
        if (filterHoursSincePub != -1) {
          Calendar rightNow = Calendar.getInstance();
          rightNow.add(Calendar.HOUR, -filterHoursSincePub);
          if (publishedDate.before(rightNow.getTime())) {
            LOG.info(
                "{} has a published date {} which is more than {} hours old",
                targetURL,
                publishedDate.toString(),
                filterHoursSincePub);
            continue;
          }
        }
        targetMD.setValue("feed.publishedDate", publishedDate.toString());
      }

      SyndContent description = entry.getDescription();
      if (description != null && StringUtils.isNotBlank(description.getValue())) {
        targetMD.setValue("feed.description", description.getValue());
      }

      links.add(newLink);
    }

    return links;
  }