def main(): parser = argparse.ArgumentParser(description='Site RSS feed generator') parser.add_argument('-b', metavar='blogs_dir', help='Directory containing blogs', required=True, dest='blogs_dir') parser.add_argument('-o', metavar='rss_file', help='Output file (defaults to ./feed.rss)', default='feed.rss', dest='output') parser.add_argument('-a', metavar='atom_file', help='Atom Feed Output file', dest='atom_output') parser.add_argument('-v', action='store_true', help='verbose mode, show info/warnings') args = parser.parse_args() if args.v: logging.basicConfig(level=logging.INFO) blogs = Path(args.blogs_dir).glob('*.md') blogs = list(blogs) feed = FeedGenerator() make_feed(feed, blogs) feed.rss_file(args.output, pretty=True) if args.atom_output: feed.atom_file(args.atom_output, pretty=True)
def make_rss_feed(): fg = FeedGenerator() fg.id('https://github.com/YunoHost/Apps/') fg.title('App Lists news') fg.author({'name': 'YunoHost'}) fg.language('en') for diff in diffs(): fe = fg.add_entry() fe.id('https://github.com/YunoHost/Apps/#' + diff["end"].strftime("%y-%m-%d")) fe.title( 'Changes between %s and %s' % (diff["begin"].strftime("%b %d"), diff["end"].strftime("%b %d"))) fe.link( href= 'https://github.com/YunoHost/apps/commits/master/community.json') fe.content(jinja2.Template( open("rss_template.html").read()).render(data=diff), type="html") fe._FeedEntry__atom_updated = diff["end"] print('Changes between %s and %s' % (diff["begin"].strftime("%b %d"), diff["end"].strftime("%b %d"))) open("tmp.html", "w").write( jinja2.Template(open("rss_template.html").read()).render(data=diff)) fg.atom_file('atom.xml')
def generate_rss_feed(repo, filename, me): generator = FeedGenerator() generator.id(repo.html_url) generator.title(f"RSS feed of {repo.owner.login}'s {repo.name}") generator.author( {"name": os.getenv("GITHUB_NAME"), "email": os.getenv("GITHUB_EMAIL")} ) generator.link(href=repo.html_url) generator.link( href=f"https://raw.githubusercontent.com/{repo.full_name}/master/{filename}", rel="self", ) for issue in repo.get_issues(): if not issue.body or not is_me(issue, me) or issue.pull_request: continue item = generator.add_entry(order="append") item.id(issue.html_url) item.link(href=issue.html_url) item.title(issue.title) item.published(issue.created_at.strftime("%Y-%m-%dT%H:%M:%SZ")) for label in issue.labels: item.category({"term": label.name}) body = "".join(c for c in issue.body if _valid_xml_char_ordinal(c)) item.content(CDATA(marko.convert(body)), type="html") generator.atom_file(filename)
def write_feed(posts): fg = FeedGenerator() fg.id(f"{BASE_URL}/updates/") fg.title("St Columbas's - Updates") fg.author(name="St Columba's Free Church", email="*****@*****.**") fg.link(href=f"{BASE_URL}/updates") fg.logo(f"{BASE_URL}/static/images/stcolumbas-logo-small.png") fg.language("en") fg.description("St Columba's Free Church Updates") for p in posts: fe = fg.add_entry() fe.id(f'{BASE_URL}/{p["path"]}') fe.title(p["title"]) fe.link(href=f'{BASE_URL}/{p["path"]}') fe.author(name=p["author"]) fe.summary(p["intro"]) fe.content(markdown(p["body"])) rss_path = os.path.join(DIST_DIR, "updates", "rss.xml") atom_path = os.path.join(DIST_DIR, "updates", "atom.xml") print(rss_path) fg.rss_file(rss_path) print(atom_path) fg.atom_file(atom_path)
def generate_feeds(config_data, output_path, drafts=False): fg = FeedGenerator() fg.id("1234") fg.title(config_data["RSS_title"]) fg.author({ "name": config_data["RSS_author_name"], "email": config_data["RSS_author_email"], }) fg.link(href=config_data["RSS_link"], rel="alternate") fg.logo(config_data["RSS_logo"]) fg.description(config_data["RSS_subtitle"]) fg.link(href=config_data["RSS_link"] + "/test.atom", rel="self") fg.language(config_data["RSS_language"]) for post in config_data["blog_posts"]: fe = fg.add_entry() fe.id(config_data["RSS_link"] + post["url"] + "/") fe.title(post["post_title"]) fe.summary(post["abstract"]) fe.published( datetime.strptime(post["date"], "%Y-%m-%d").isoformat() + "+00:00") fe.link(href=config_data["RSS_link"] + post["url"] + "/") fg.atom_file(os.path.join(output_path, "atom.xml")) fg.rss_file(os.path.join(output_path, "rss.xml"))
def _build_rss(self, messages, rss_file, atom_file): f = FeedGenerator() f.id(self.config["site_url"]) f.generator("tg-archive {}".format( pkg_resources.get_distribution("tg-archive").version)) f.link(href=self.config["site_url"], rel="alternate") f.title(self.config["site_name"].format(group=self.config["group"])) f.subtitle(self.config["site_description"]) for m in messages: url = "{}/{}#{}".format(self.config["site_url"], self.page_ids[m.id], m.id) e = f.add_entry() e.id(url) e.title("@{} on {} (#{})".format(m.user.username, m.date, m.id)) e.description(self._make_abstract(m)) if m.media and m.media.url: murl = "{}/{}/{}".format( self.config["site_url"], os.path.basename(self.config["media_dir"]), m.media.url) e.enclosure(murl, 0, "application/octet-stream") f.rss_file(os.path.join(self.config["publish_dir"], "index.xml")) f.atom_file(os.path.join(self.config["publish_dir"], "index.atom"))
def build_feed(directory, time_func, base_url, output="atom.xml", n=10, title="", subtitle="", author="", email="", verbose=False): """ Build an Atom feed for all world readable Gemini files in the current directory, and write it to atom.xml. """ # If a title hasn't been provided, try to get one from an index page if not title: title = get_feed_title(directory) # Let user know feed title and URL feed_url = urljoin(base_url, output) if verbose: print('Generating feed "{}", which should be served from {}'.format( title, feed_url)) # Setup feed feed = FeedGenerator() feed.id(base_url) feed.title(title) if subtitle: feed.subtitle(subtitle) author_details = {} if author: author_details["name"] = author if email: author_details["email"] = email if author_details: feed.author(author_details) feed.link(href=feed_url, rel='self') feed.link(href=base_url, rel='alternate') # Add one entry per .gmi file files = find_files(directory, time_func, n) if not files: if verbose: print("No world-readable Gemini content found! :(") return for n, filename in enumerate(files): entry = feed.add_entry() populate_entry_from_file(filename, base_url, entry, time_func) if n == 0: feed.updated(entry.updated()) if verbose: print("Adding {} with title '{}'...".format( os.path.basename(filename), entry.title())) # Write file output = os.path.join(directory, output) feed.atom_file(output, pretty=True) if verbose: print("Wrote Atom feed to {}.".format(output))
def render_feed(root_path: str, link_page_rows: List[LinkRow]): logger.info("Rendering feed outputs.") feed = FeedGenerator() feed.id(ENV["SITE_URL"]) feed.title(ENV["SITE_TITLE"]) feed.link(href=ENV["SITE_URL"], rel="alternate") feed.subtitle(ENV["SITE_DESC"]) feed.link(href=urljoin(ENV["SITE_URL"], "feed.rss"), rel="self") feed.language("tr") links = get_links_by_date(link_page_rows) for link in links: entry = feed.add_entry() entry.id(link.file_path) entry.title(link.title) entry.description(link.desc) entry.link( title=link.title, rel="alternate", type="text/html", href=urljoin(ENV["SITE_URL"], link.file_path), ) entry.updated(link.create_time) feed.rss_file(join(root_path, "rss.xml"), pretty=True) feed.atom_file(join(root_path, "atom.xml"), pretty=True)
def writeRSS(papers, output): fg = FeedGenerator() fg.id(RSS_URL) fg.title(RSS_TITLE) fg.subtitle(RSS_SUBTITLE) fg.author(RSS_AUTHOR) fg.link(href='http://www.vldb.org/pvldb/', rel='alternate') fg.language('en') for p in papers: summary = "%(title)s\nAuthors: %(authors)s\nPVLDB Volume %(volume)d, Number %(number)d" % p fe = fg.add_entry() fe.author(name=p["authors"]) fe.title(p["title"]) fe.link(href=p["link"]) fe.id(p["link"]) fe.published(published=p["published"]) fe.description(description=summary, isSummary=True) ## FOR atomfeed = fg.atom_str(pretty=True) # Get the ATOM feed as string atom_file = os.path.join(output, 'pvldb-atom.xml') fg.atom_file(atom_file) # Write the ATOM feed to a file LOG.info("Created ATOM '%s'" % atom_file) rssfeed = fg.rss_str(pretty=True) # Get the RSS feed as string rss_file = os.path.join(output, RSS_FILE) fg.rss_file(rss_file) # Write the RSS feed to a file LOG.info("Created RSS '%s'" % rss_file)
def write_feeds(posts): g = FeedGenerator() g.id('http://peterdowns.com/blog') g.link(href='http://peterdowns.com/blog') g.description('incredibly on-brand') g.title(u'Peter Downs — Posts') first_post = posts[0] updated = first_post['updated'] or first_post['date'] g.updated(_utcstrp(updated, _time_fmt)) for post in posts: e = g.add_entry() post_url = os.path.join(_blog_root, post['html_path']) e.id(post_url) e.link(href=post_url, rel='alternate') e.title(post['title']) e.author(name=post['author'][0]) e.published(_utcstrp(post['date'], _time_fmt)) if post['updated'] is None: e.updated(e.published()) else: e.updated(_utcstrp(post['updated'], _time_fmt)) g.atom_file('{}/atom.xml'.format(_feeds_dir)) g.rss_file('{}/rss.xml'.format(_feeds_dir))
def build_xml_feed(allchapters, verbose=True): if verbose: print print "Generating feeds..." if len(allchapters) == 0: raise CRMangaFeedException("Empty chapter list") crtz = pytz.timezone('America/New_York') fg = FeedGenerator() fg.id('http://utils.senpai.moe/') fg.title('Crunchyroll Manga - Latest Chapters (Unofficial)') fg.author({'name': 'Nosgoroth', 'email': '*****@*****.**'}) fg.link(href='http://utils.senpai.moe/') fg.subtitle( 'Latest manga chapters, updated daily, using undocumented API.') fg.language('en') fg.ttl(15) allchapters = sorted(allchapters, key=itemgetter('updated_t'), reverse=True) first = allchapters[0]["updated_t"].replace(tzinfo=crtz) fg.updated(first) fg.lastBuildDate(first) for chapter in allchapters[0:100]: fe = fg.add_entry() fe.id(chapter["url"]) fe.link({ "href": chapter["url"], "rel": "alternate", "title": "Read online" }) fe.title("%s - %s" % (chapter["series"], chapter["name"])) fe.summary("<p>%s has been added to %s in Crunchyroll Manga.</p>" % (chapter["name"], chapter["series"])) fe.published(chapter["updated_t"].replace(tzinfo=crtz)) chapter_serial = chapter.copy() chapter_serial.pop("updated_t", None) chapter_serial.pop("url", None) chapter_serial.pop("thumb", None) chapter_serial["chapter_id"] = chapter_serial["guid"] chapter_serial.pop("guid", None) content = "<p>%s has been added to %s in Crunchyroll Manga.</p><p>Updated: %s</p><img src=\"%s\" />" % ( chapter["name"], chapter["series"], chapter["updated"], chapter["thumb"]) content += "<!--JSON:[[%s]]-->" % json.dumps(chapter_serial) fe.content(content) fg.rss_file(os.path.join(DESTINATION_FOLDER, 'updates_rss.xml'), pretty=DEBUG) # Write the RSS feed to a file fg.atom_file(os.path.join(DESTINATION_FOLDER, 'updates_atom.xml'), pretty=DEBUG) # Write the ATOM feed to a file
def update_ics(self, data, rss=None): c = Calendar(events=self.get_exist_events()) for e in self.new_events(data): # remove by hash if e in c.events: c.events.remove(e) # add the newer one c.events.add(e) # print(c.events) if rss: assert rss in ["atom", "rss"] fg = FeedGenerator() fg.id(self.name) fg.title(f"Events of {self.cal_name}") for i, e in enumerate(c.events): # type: Event fe = fg.add_entry() fe.id(e.uid) fe.title(e.name) fe.link(href=e.url) fe.updated(e.begin.datetime) market = e.name.split("|")[0].strip() # only latest symbols if market == "US": # and len(c.events) - i <= 5: # disable for timeout in now server info_html = get_ipo_info_html(e.uid, enable=False) link = f'<p><a href="https://www.nasdaq.com/symbol/{e.uid}">Goto NASDAQ detail page</a></p>' fe.description( f"<p>{e.description}</p> {link} {info_html}") else: fe.description(e.description) rss_output = self.get_output_path(rss) if rss == "atom": fg.atom_file(rss_output) print(f"wrote {rss_output}") elif rss == "rss": fg.rss_file(rss_output) print(f"wrote {rss_output}") else: ics_output = self.get_output_path() with open(ics_output, "w") as f: wrote = False for l in c: f.write(l) if not wrote and l.startswith("VERSION"): f.write(f"X-WR-CALNAME:{self.cal_name}\n") wrote = True print(f"wrote {ics_output}")
def generate_feed(json): print("Generating feed...") fg = FeedGenerator() fg.id(STUDIP_SYNC_CONFIG.base_url) fg.title('STUD.IP Activities') for entry in json: fe = fg.add_entry() fe.id(entry['id']) fe.title(entry['title']) fe.content(BeautifulSoup(entry['content']).get_text()) fe.link({'href': STUDIP_SYNC_CONFIG.base_url + list(entry['object_url'].keys())[0]}) fe.published(datetime.fromtimestamp(int(entry['mkdate']), timezone.utc)) fg.atom_file("/dev/stdout", pretty=True)
def generate_feed(entries_file=None): language = entries_file and entries_file.split('.')[1] or 'en' fg = FeedGenerator() fg.load_extension('i2p') fg.language(language) load_feed_metadata(fg) load_entries(fg, entries_file and entries_file or ENTRIES_FILE) load_releases(fg) load_revocations(fg) load_blocklist(fg) if not os.path.exists(BUILD_DIR): os.mkdir(BUILD_DIR) fg.atom_file(entries_file and TRANSLATED_NEWS_FILE % language or NEWS_FILE, pretty=True)
def main(): client = moduleSocial.connectTumblr() posts = client.posts('fernand0') fg = FeedGenerator() fg.id(posts['blog']['url']) fg.title(posts['blog']['title']) fg.author( {'name':posts['blog']['name'],'email':'*****@*****.**'} ) fg.link( href=posts['blog']['url'], rel='alternate' ) fg.subtitle('Alternate feed due to Tumblr GDPR restrictions') fg.language('en') print(len(posts['posts'])) for i in range(len(posts['posts'])): fe = fg.add_entry() print(posts['posts'][i]['post_url']) if 'title' in posts['posts'][i]: title = posts['posts'][i]['title'] print('T', posts['posts'][i]['title']) else: title = posts['posts'][i]['summary'].split('\n')[0] print('S', posts['posts'][i]['summary'].split('\n')[0]) fe.title(title) fe.link(href=posts['posts'][i]['post_url']) fe.id(posts['posts'][i]['post_url']) print(fg.atom_file('/var/www/html/elmundoesimperfecto/tumblr.xml')) sys.exit()
def _build_feed(self): router = Router(self._config) fp = filterPlaceholders fg = FeedGenerator() fg.id(self._config.site_prefix) fg.title(self._config.site_name) fg.author({ 'name': fp(self._config.author), 'email': fp(self._config.email) }) fg.link(href=self._config.domain_name + self._config.site_prefix, rel='alternate') fg.logo(fp(self._config.site_logo)) fg.subtitle(fp(self._config.description)) fg.description(fp(self._config.description) or ' ') fg.language(fp(self._config.language)) fg.lastBuildDate(moment.now().locale(self._config.locale).date) fg.pubDate(moment.now().locale(self._config.locale).date) for post in self._posts[:10]: meta = post.meta fe = fg.add_entry() fe.title(meta['title']) fe.link(href=self._config.domain_name + router.gen_permalink_by_meta(meta)) fe.guid(router.gen_permalink_by_meta(meta), True) fe.pubDate(meta['date'].date) fe.author({ 'name': meta['author'], 'uri': fp(self._config.author_homepage), 'email': fp(self._config.email) }) fe.content(post.parsed) if not os.path.exists( unify_joinpath(self._config.build_dir, 'feed/atom')): os.makedirs(unify_joinpath(self._config.build_dir, 'feed/atom')) fg.rss_file(unify_joinpath(self._config.build_dir, 'feed/index.xml')) fg.rss_file(unify_joinpath(self._config.build_dir, 'feed/index.html')) fg.atom_file( unify_joinpath(self._config.build_dir, 'feed/atom/index.xml')) fg.atom_file( unify_joinpath(self._config.build_dir, 'feed/atom/index.html'))
def generateFeed(): fg = FeedGenerator() fg.id(URL) fg.title('Package Tracking') fg.link(href=URL) fg.description('Delivers Package Tracking Updates') for entry in database.all(): fe = fg.add_entry() fe.link(href=entry.get('link')) fe.id(URL + '/' + str(entry.doc_id)) fe.title(entry.get('edd')) fe.description(entry.get('discr')) fe.updated( datetime.datetime.fromtimestamp(entry.get('epoch'), datetime.timezone.utc)) atomfeed = fg.atom_str(pretty=True) # Get the ATOM feed as string fg.atom_file('/srv/atom.xml') # Write the ATOM feed to a file
def create_feed_file( fg: FeedGenerator, feed_file_name: str, feed_type: FeedType ) -> str: path_within_strealit_static = "feeds" # Create a directory within the streamlit static asset directory STREAMLIT_STATIC_PATH = pathlib.Path(st.__path__[0]) / "static" FEEDS_PATH = STREAMLIT_STATIC_PATH / path_within_strealit_static if not FEEDS_PATH.is_dir(): FEEDS_PATH.mkdir() final_file_name = feed_file_name.replace(os.path.sep, "_") if feed_type == FeedType.ATOM: fg.atom_file(str(FEEDS_PATH / f"{final_file_name}_atom.xml")) return f"{path_within_strealit_static}{os.sep}{final_file_name}_atom.xml" else: fg.rss_file(str(FEEDS_PATH / f"{final_file_name}_rss.xml")) return f"{path_within_strealit_static}{os.sep}{final_file_name}_rss.xml"
def saveFeed(listings, title, path): url = githubRepoURL + title + ".xml" # Create a feed generator fg = FeedGenerator() # Create the feed's title fg.id(url) fg.title(title) fg.author({'name': 'Ben Snell'}) fg.description("NYC 2BR Apartment Listings in " + title) fg.link(href=url, rel='alternate') fg.language('en') time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + "-05:00" fg.pubDate(time) fg.updated(time) for apt in listings: e = fg.add_entry() e.id(apt[0]) e.title("$" + apt[1] + " // " + apt[4]) e.link(href=apt[0]) text = "" if apt[5] != "": imgs = apt[5].split(" ") for i in range(len(imgs)): text += "<img src=\"" + imgs[i] + "\" /> " if i == 0: text += "<p>" + apt[8] + "</p>" else: text += "<p>" + apt[8] + "</p>" e.content(type="html", content=text) # This doesn't seem to work: e.pubDate(datetime2RSSString(clDate(apt[2]))) e.updated(datetime2RSSString(clDate(apt[2]))) fg.atom_str(pretty=True) fg.atom_file(path)
def render_rss(self, post_list): router = Router(self._config) fg = FeedGenerator() fg.id(self._config.site_prefix) fg.title(self._config.site_name) fg.author({'name': self._config.author, 'email': self._config.email}) fg.link(href=self._config.site_prefix, rel='alternate') fg.logo(self._config.site_logo) fg.subtitle(self._config.description) fg.language('zh-CN') fg.lastBuildDate(moment.now().locale('Asia/Shanghai').date) fg.pubDate(moment.now().locale('Asia/Shanghai').date) for post in post_list[:10]: meta = post.meta fe = fg.add_entry() fe.title(meta['title']) fe.link(href=router.gen_permalink_by_meta(meta)) fe.guid(router.gen_permalink_by_meta(meta), True) fe.pubDate(meta['date'].date) fe.author({ 'name': meta['author'], 'uri': self._config.author_homepage, 'email': self._config.email }) fe.content(post.parsed) if not os.path.exists( Utils.unify_joinpath(self._config.build_dir, 'feed/atom')): os.makedirs( Utils.unify_joinpath(self._config.build_dir, 'feed/atom')) fg.rss_file( Utils.unify_joinpath(self._config.build_dir, 'feed/index.xml')) fg.rss_file( Utils.unify_joinpath(self._config.build_dir, 'feed/index.html')) fg.atom_file( Utils.unify_joinpath(self._config.build_dir, 'feed/atom/index.xml')) fg.atom_file( Utils.unify_joinpath(self._config.build_dir, 'feed/atom/index.html'))
def saveFeed(listings, title, path): url = githubRepoURL + title + ".xml" # Create a feed generator fg = FeedGenerator() # Create the feed's title fg.id(url) fg.title(title) fg.author({'name': 'Ben Snell'}) fg.description("Art Show Open Call Opportunities") fg.link(href=url, rel='alternate') fg.language('en') time = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + "-05:00" fg.pubDate(time) fg.updated(time) for item in listings: e = fg.add_entry() e.id(item["ID"]) # Get a clearer title thisTitle = getShortDate(item["Application Deadline"]) + item["Title"] e.title(thisTitle) # for key, value in item.items(): # print(key, value); # print(item["url"]) # if "url" in item: e.link(href=item["url"]) text = getHtmlFormattedListing(item) e.content(type="html", content=text) # This doesn't seem to work: # e.pubDate( datetime2RSSString(clDate(apt[2])) ) # e.updated( datetime2RSSString(clDate(apt[2])) ) fg.atom_str(pretty=True) fg.atom_file(path)
def create_feed(episodes, output_filepath=None): woe_feed = FeedGenerator() woe_feed.load_extension('podcast', atom=True) woe_feed.title(u"Willkommen Österreich") woe_feed.id(EPISODES_SCRAPING_URL) woe_feed.link(href=BASE_URL, rel='self') woe_feed.description(u"Inoffizieller RSS-Feed für 'Willkommen Österreich'-Episoden") woe_feed.language('de') for episode in episodes: episode_entry = woe_feed.add_entry() episode_entry.id(episode.page) episode_entry.link(href=episode.page, rel='alternate') episode_entry.title(u"Folge {0} - {1}: {2}".format(episode.num, episode.date, episode.description)) for video in episode.videos: episode_entry.enclosure(url=video, length=0, type='mp4') if output_filepath: woe_feed.atom_file(output_filepath) else: print(woe_feed.atom_str(pretty=True))
def make_feed(entries, yargs): """Take a list of (datetime, feedgen.entry)s and the program arguments and create a feed file.""" from feedgen.feed import FeedGenerator fg = FeedGenerator() # metadata fg.id(yargs.feed_link) fg.title(yargs.feed_title) fg.description( yargs.feed_description if yargs.feed_description else yargs.feed_title) fg.link(href=yargs.feed_link) # entries for ts, e in entries: fg.add_entry(e) # output if yargs.feed_type == "RSS": fg.rss_file(yargs.feed_path) elif yargs.feed_type == "Atom": fg.atom_file(yargs.feed_path)
def generate_feed(articles): articles_count = settings.FEED.get('articles_count', 10) author = settings.FEED.get('author', '') language = settings.FEED.get('language', 'en') fg = FeedGenerator() fg.title(settings.BLOG_TITLE) fg.author(name=author) fg.id(id=settings.HOST) fg.link(href=settings.HOST, rel='alternate') fg.language(language) for i, article in enumerate(articles): if i == articles_count: break fe = fg.add_entry() fe.id(article_link(article.meta['Url'])) fe.link(href=article_link(article.meta['Url']), rel='alternate') fe.title(article.meta['Title']) fg.atom_file(pjoin(settings.OUTPUT_DIR.full_path, 'feed.xml'))
def generate_feed(): tz = pytz.timezone(config.timezone) # Get latest X entries from database entries = dbhelper.get_latest_entries() fg = FeedGenerator() # Feed id fg.id(config.bot_link) # Creator info (for Atom) fg.author(name=config.author_name, email=config.author_email, replace=True) # Self link to the feed fg.link(href=config.feed_link, rel='self') # Set description of your feed fg.description(config.feed_description) # Last time feed updated (use system time with timezone) fg.lastBuildDate( formatdate(datetime.timestamp(datetime.now(tz)), localtime=True)) fg.title(config.feed_title) # Set time-to-live (I really don't know why set this) fg.ttl(5) # Does this parameter mean anything? fg.language(config.feed_language) for entry in entries: item = fg.add_entry() # Use message id to form valid URL (new feature in Telegram since Feb 2016) item.id("{!s}".format(entry["pid"])) item.link(href="{!s}/{!s}".format(config.bot_link, entry["pid"]), rel="alternate") # Set title and content from message text item.title(entry["ptext"]) item.content(entry["ptext"]) # Set publish/update datetime item.pubdate(entry["pdate"]) item.updated(entry["pdate"]) # Write RSS/Atom feed to file # It's preferred to have only one type at a time (or just create two functions) fg.atom_file('static/atom.xml')
def getDataFeed(): # have a useragent so we do not look like a robot useragent = "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0" sesh = requests.Session() # type: requests.Session sesh.headers.update({"User-Agent": useragent}) r = sesh.get(fmeasure) # ok to make the gotten feed slimmer I will be building a new one # containing only the title of the blog, the feed it # and the entries so I am using feedgen library to do so fg = FeedGenerator() feed = feedparser.parse(r.text) fg.title(feed.feed.title) fg.id(feed.feed.id) entries = [] # concatenate every entry from the current pagination entries.extend(feed.entries) # as usual check next and while good get next set of entries # and extract the entries good, nl = check_next(r.text) while good: r = sesh.get(nl) feed = feedparser.parse(r.text) entries.extend(feed.entries) good, nl = check_next(r.text) r.close() # for each of the entries for e in entries: # create a new entry fe = fg.add_entry() # add the entry id, title and content fe.id(e.id) fe.title(e.title) c = e.content[0] fe.content(content=c.value, type=c.type) # write the new feed file out fg.atom_file("datafiles/f-measure.xml", pretty=True) sesh.close() # now to get the genres get_genres()
def generate_feed(events): fg = FeedGenerator() fg.id('https://feeds.awsome.click/menoinfo/') fg.title( 'Artem Kajalainen\'s menoinfo filter feed for pirkanmaa.menoinfo.fi') fg.author({'name': 'Artem Kajalainen', 'email': '*****@*****.**'}) fg.link(href='http://feeds.awsome.click/menoinfo/atom.xml', rel='self') fg.language('fi') today_string = date.today().strftime("%d.%m.%Y") for event in events: entry = fg.add_entry() if event['duration_days'] > 1: # next time the long lasting same event appears in stream - id will change with current date, so # client will show it again event_id = f'{event["url"]}-{today_string}' else: event_id = event["url"] entry.id(event_id) entry.title(f'{event["title"]} @ {event["date"]}') entry.summary(event["summary"]) entry.category(term=event["category"], label=event["category"]) entry.link(href=event["url"]) fg.atom_file('/tmp/atom.xml')
def add(td): fg = FeedGenerator() fg.id("10") fg.title('Kollektive Geographie Heidelberg') fg.author({ 'name': 'Kollektive Geographie Heidelberg', 'email': '*****@*****.**' }) fg.link(href='http://kollektive-geographie-heidelberg.de', rel='alternate') fg.logo('http://kollektive-geographie-heidelberg.de/favicon-earth.svg') fg.subtitle('Definitionen') fg.language('de') fe = fg.add_entry() fe.id("10") fe.title(td[0]) fe.link(href="http://kollektive-geographie-heidelberg.de/test.html") fe.description(td[1]) atomfeed = fg.atom_str(pretty=True) # Get the ATOM feed as string rssfeed = fg.rss_str(pretty=True) # Get the RSS feed as string fg.atom_file('atom.xml') # Write the ATOM feed to a file fg.rss_file('rss.xml') # Write the RSS feed to a file
def generate_feed(posts): fg = FeedGenerator() fg.id('%s/' % SITE_URL) fg.title("jml's notebook") fg.author({'name': 'Jonathan M. Lange', 'email': '*****@*****.**'}) fg.link(href=SITE_URL, rel='alternate') fg.link(href='%s/feed.xml' % (SITE_URL, ), rel='self') fg.language('en') dates = [] for post in reversed(posts): fe = fg.add_entry() fe.id(SITE_URL + post.url) fe.link(href=SITE_URL + post.url) fe.title(post.title or post.name) fe.content(post.body) updated = subprocess.check_output([ "git", "log", "-1", '--date=iso8601', '--format="%ad"', "--", post.original_file, ]).decode('ascii').strip().strip('"') if updated: updated = dateutil.parser.parse(updated) else: updated = datetime.strptime(post.name.replace( '.html', ''), POST_DATE_FORMAT).replace(tzinfo=tz.gettz()) dates.append(updated) fe.updated(updated) fg.updated(max(dates)) fg.atom_file(os.path.join(HTML_ROOT, 'feed.xml'), pretty=True)
def generate_feed(): tz = pytz.timezone(config.timezone) # Get latest X entries from database entries = dbhelper.get_latest_entries() fg = FeedGenerator() # Feed id fg.id(config.bot_link) # Creator info (for Atom) fg.author(name=config.author_name, email=config.author_email, replace=True ) # Self link to the feed fg.link(href=config.feed_link, rel='self') # Set description of your feed fg.description(config.feed_description) # Last time feed updated (use system time with timezone) fg.lastBuildDate(formatdate(datetime.timestamp(datetime.now(tz)), localtime=True)) fg.title(config.feed_title) # Set time-to-live (I really don't know why set this) fg.ttl(5) # Does this parameter mean anything? fg.language(config.feed_language) for entry in entries: item = fg.add_entry() # Use message id to form valid URL (new feature in Telegram since Feb 2016) item.id("{!s}".format(entry["pid"])) item.link(href="{!s}/{!s}".format(config.bot_link, entry["pid"]), rel="alternate") # Set title and content from message text item.title(entry["ptext"]) item.content(entry["ptext"]) # Set publish/update datetime item.pubdate(entry["pdate"]) item.updated(entry["pdate"]) # Write RSS/Atom feed to file # It's preferred to have only one type at a time (or just create two functions) fg.atom_file('static/atom.xml')
def create_feeds(entries): print("Updating feeds.") fg = FeedGenerator() fg.title('FOIA The Dead') fg.author(name='FOIA The Dead', email='*****@*****.**') fg.link(href=home, rel='alternate') fg.id(home) fg.description("FOIA The Dead is a long-term transparency project using the Freedom of Information Act. It releases FBI records on recently deceased public figures.") for entry in reversed(entries): fe = fg.add_entry() fe.title(entry['name']) fe.link(href=urllib.parse.urljoin(home, "posts/" + entry['slug'] + "/")) fe.id(urllib.parse.urljoin(home, "posts/" + entry['slug'] + "/")) if entry['long_desc']: fe.content(entry['long_desc']) elif entry['short_desc']: fe.content(entry['short_desc']) else: fe.content("FOIA The Dead has obtained the FBI file for {}.".format(entry['name'])) fg.atom_file('site/atom.xml', pretty=True) fg.rss_file('site/rss.xml', pretty=True)
class SteamCommentsRss: def __init__(self, app_id): self.app_id = app_id self.steam_comments = CommentsFeed(app_id) self.feed = FeedGenerator() self.feed.id( "https://steamcommunity.com/games/{app_id}/allnews/".format( app_id=self.app_id)) self.feed.title("PULSAR: Lost Colony Developer Comments on Steam") self.feed.link(href="https://pulsar.wiki/leafytracker/") self.feed.description( "Comments by leafygamesdev on PULSAR news articles.") self.feed.language("en") self.feed.generator("https://pulsar.wiki/leafytracker/" ) # TODO: Automate project name and version def append_comments(self, news_ids, user_ids): news_ids = set(int(x) for x in news_ids) user_ids = set(int(x) for x in user_ids) for nid in news_ids: for comment in self.steam_comments.get(nid, user_ids): entry = self.feed.add_entry() entry.id(str(comment.cid)) entry.link({"href": comment.url}) entry.title("{} commented on {}".format( comment.author.name, comment.title)) entry.author({"name": comment.author.name}) entry.published(comment.datetime) entry.content(comment.body) def to_atom(self, output_path, pretty=True): return self.feed.atom_file(output_path, pretty=pretty) def to_rss(self, output_path, pretty=True): return self.feed.rss_file(output_path, pretty=pretty)
from feedgen.feed import FeedGenerator fg = FeedGenerator() fg.id('http://lernfunk.de/media/654321') fg.title('Some Testfeed') fg.author({'name': 'John Doe', 'email': '*****@*****.**'}) fg.link(href='http://example.com', rel='alternate') fg.logo('http://ex.com/logo.jpg') fg.subtitle('This is a cool feed!') fg.link(href='http://larskiesow.de/test.atom', rel='self') fg.language('en') atomfeed = fg.atom_str(pretty=True) # Get the ATOM feed as string rssfeed = fg.rss_str(pretty=True) # Get the RSS feed as string fg.atom_file('atom.xml') # Write the ATOM feed to a file fg.rss_file('rss.xml') # Write the RSS feed to a file
# entries in the feed, too. Thus also for our “fe”. fg.load_extension('podcast') fg.podcast.itunes_author('Lars Kiesow') fg.podcast.itunes_category('Technology', 'Podcasting') fg.podcast.itunes_explicit('no') fg.podcast.itunes_complete('no') fg.podcast.itunes_new_feed_url('http://example.com/new-feed.rss') fg.podcast.itunes_owner('John Doe', '*****@*****.**') fg.podcast.itunes_summary('Lorem ipsum dolor sit amet, ' + \ 'consectetur adipiscing elit. ' + \ 'Verba tu fingas et ea dicas, quae non sentias?') fe.podcast.itunes_author('Lars Kiesow') print_enc (fg.rss_str(pretty=True)) elif arg == 'dc.atom': fg.load_extension('dc') fg.dc.dc_contributor('Lars Kiesow') fe.dc.dc_contributor('Lars Kiesow') print_enc (fg.atom_str(pretty=True)) elif arg == 'dc.rss': fg.load_extension('dc') fg.dc.dc_contributor('Lars Kiesow') print_enc (fg.rss_str(pretty=True)) elif arg.endswith('atom'): fg.atom_file(arg) elif arg.endswith('rss'): fg.rss_file(arg)
def main (args): """ main functions """ logger = logging.getLogger(sys._getframe().f_code.co_name) with open(args.config) as f: config = json.load(f) logger.debug(pformat(config, indent=4)) # override any loaded config with items specified on command line for arg, argv in vars(args).iteritems(): if argv is not None: config[arg] = argv if 'maximum' not in config.keys(): config['maximum'] = DEFAULTMAXIMUM logger.debug(pformat(config, indent=4)) # get metadata about the collection context = '{0}/collections/{1}'.format(config['zotero_account'], config['zotero_collection']) url = '/'.join((ZOT_BASE, context, '?format=json')) response = zot_get(url) alt_html = json.loads(response['content'])['links']['alternate']['href'] # get list of items in collection context = '{0}/collections/{1}/items/top'.format(config['zotero_account'], config['zotero_collection']) url = '/'.join((ZOT_BASE, context, '?format=keys&sort=dateModified&direction=desc&limit={0}'.format(config['maximum']))) logger.debug('fetching: {0}'.format(url)) response = zot_get(url) if int(response['length']) > 0: keys = response['content'].split('\n') else: print "boom" if len(keys) > config['maximum']+1: logger.error("gigantic: {0}".format(len(keys))) raise Exception fg = FeedGenerator() feed_id = u'tag:{domain},{date}:{slug}'.format( domain=config['tag_domain'], date=config['tag_date'], slug=config['tag_slug']) fg.id(feed_id) fg.title(config['title']) fg.author( {'name':config['author_name'],'email':config['author_email']} ) fg.link( href=config['self'], rel='self' ) fg.link( href=alt_html, rel='alternate' ) fg.logo('https://www.zotero.org/support/_media/logo/zotero_256x256x32.png') fg.language('en') fg.updated(datetime.now(pytz.utc)) context = '{0}/items'.format(config['zotero_account']) entries = {} for key in [k for k in keys if len(k.strip()) > 0]: logger.info(u'zotero key: "{0}"'.format(key)) url = '/'.join((ZOT_BASE, context, key)) response = zot_get(url) data = json.loads(response['content']) zot_link_html = data['links']['alternate']['href'] zot_link_json = data['links']['self']['href'] data = data['data'] logger.info(u'zotero itemType: "{0}"'.format(data['itemType'])) if data['itemType'] == 'note': logger.warning('ignored note (key="{0}")'.format(key)) elif data['itemType'] == 'attachment': if data['linkMode'] == u'linked_url': fe = entries[data['parentItem']] fe.link(href=data['url'], title=data['title'], rel='alternate') else: raise NotImplemented('Zotero attachment (key="{0}") with unhandled linkMode="{1}"'.format(key, data['linkMode'])) else: fe = fg.add_entry() entries[key] = fe entry_id = u'tag:{domain},{date}:{slug}'.format( domain='zotero.org', date=data['dateAdded'].split('T')[0], slug='/'.join((context, key))) fe.id(entry_id) try: fe.title(data['title']) except KeyError: logger.warning("unexpected lack of title in zotero record") logger.debug(pformat(data, indent=2)) raise try: creators = data['creators'] except KeyError: pass else: authors = [c for c in data['creators'] if c['creatorType'] == u'author'] for a in authors: if 'name' in a.keys(): fe.author({'name':a['name']}) else: fe.author({'name':u'{0} {1}'.format(a['firstName'], a['lastName']), }) try: fe.link(href=data['url'], rel='alternate', title='link to resource') except KeyError: pass fe.link(href=zot_link_html, rel='alternate', title='link to zotero record (html)') #fe.link(href=zot_link_json, rel='alternate', title='link to zotero record (json)') try: fe.description(data['abstractNote'], isSummary=True) except KeyError: pass url = '/'.join((ZOT_BASE, context, key, '?format=bib')) bib = zot_get(url) logger.debug(pformat(bib, indent=4)) bib = bib['content'].split('\n')[2].strip() logger.debug("bib: '{0}'".format(bib)) fe.content(content=bib, type='xhtml') fe.published(data['dateAdded']) fe.updated(data['dateModified']) #fe.updated(datetime.now(pytz.utc)) with open(config['out_path'], 'w') as f: fg.atom_file(f)
class Feed: def __init__(self, url: str, name: str, email: str, title: str = None, generator: str = None, generator_version: str = None, logo: str = None, icon: str = None, description: str = None, language: str = None) -> None: self.name = name self.email = email self.fg = FeedGenerator() self.fg.id(url + "feed.atom") self.fg.link(href=url + "feed.xml", rel="self") self.fg.link(href=url, rel="alternate") self.fg.author(name=name, email=email) self.fg.contributor(name=name, email=email) self.fg.managingEditor(email) self.fg.webMaster(email) self.fg.title(title) self.fg.generator(generator=generator, version=generator_version) self.fg.logo(logo) self.fg.icon(icon) self.fg.description(description) self.fg.language(language) def add(self, article: Article) -> None: feed_entry = self.fg.add_entry() feed_entry.id(article.url) feed_entry.title(article.title) feed_entry.link(href=article.url) feed_entry.guid(guid=article.url, permalink=True) feed_entry.author(name=self.name, email=self.email) feed_entry.summary(article.description or article.snippet) feed_entry.content(content=article.content, type="CDATA") feed_entry.published(article.date) if article.date: feed_entry.published(article.date) feed_entry.updated(article.date) else: epoch = datetime.datetime(1970, 1, 1, tzinfo=datetime.timezone.utc) feed_entry.published(epoch) feed_entry.updated(epoch) def add_from_blog(self, url: str) -> None: blog = Blog(url) if not self.fg.title(): self.fg.title(blog.title) for article in blog.articles: self.add(article) def atom(self) -> bytes: return self.fg.atom_str(pretty=True) def rss(self) -> bytes: return self.fg.rss_str(pretty=True) def atom_file(self, filename: str = "feed.atom") -> None: self.fg.atom_file(filename, pretty=True) def rss_file(self, filename: str = "feed.xml") -> None: self.fg.rss_file(filename, pretty=True)
def main(): if len(sys.argv) != 2 or not ( sys.argv[1].endswith('rss') or sys.argv[1].endswith('atom') or sys.argv[1] == 'torrent' or sys.argv[1] == 'podcast'): print(USAGE) exit() arg = sys.argv[1] fg = FeedGenerator() fg.id('http://lernfunk.de/_MEDIAID_123') fg.title('Testfeed') fg.author({'name': 'Lars Kiesow', 'email': '*****@*****.**'}) fg.link(href='http://example.com', rel='alternate') fg.category(term='test') fg.contributor(name='Lars Kiesow', email='*****@*****.**') fg.contributor(name='John Doe', email='*****@*****.**') fg.icon('http://ex.com/icon.jpg') fg.logo('http://ex.com/logo.jpg') fg.rights('cc-by') fg.subtitle('This is a cool feed!') fg.link(href='http://larskiesow.de/test.atom', rel='self') fg.language('de') fe = fg.add_entry() fe.id('http://lernfunk.de/_MEDIAID_123#1') fe.title('First Element') fe.content('''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Tamen aberramus a proposito, et, ne longius, prorsus, inquam, Piso, si ista mala sunt, placet. Aut etiam, ut vestitum, sic sententiam habeas aliam domesticam, aliam forensem, ut in fronte ostentatio sit, intus veritas occultetur? Cum id fugiunt, re eadem defendunt, quae Peripatetici, verba.''') fe.summary(u'Lorem ipsum dolor sit amet, consectetur adipiscing elit…') fe.link(href='http://example.com', rel='alternate') fe.author(name='Lars Kiesow', email='*****@*****.**') if arg == 'atom': print_enc(fg.atom_str(pretty=True)) elif arg == 'rss': print_enc(fg.rss_str(pretty=True)) elif arg == 'podcast': # Load the podcast extension. It will automatically be loaded for all # entries in the feed, too. Thus also for our “fe”. fg.load_extension('podcast') fg.podcast.itunes_author('Lars Kiesow') fg.podcast.itunes_category('Technology', 'Podcasting') fg.podcast.itunes_explicit('no') fg.podcast.itunes_complete('no') fg.podcast.itunes_new_feed_url('http://example.com/new-feed.rss') fg.podcast.itunes_owner('John Doe', '*****@*****.**') fg.podcast.itunes_summary('Lorem ipsum dolor sit amet, consectetur ' + 'adipiscing elit. Verba tu fingas et ea ' + 'dicas, quae non sentias?') fe.podcast.itunes_author('Lars Kiesow') print_enc(fg.rss_str(pretty=True)) elif arg == 'torrent': fg.load_extension('torrent') fe.link(href='http://example.com/torrent/debian-8-netint.iso.torrent', rel='alternate', type='application/x-bittorrent, length=1000') fe.torrent.filename('debian-8.4.0-i386-netint.iso.torrent') fe.torrent.infohash('7661229811ef32014879ceedcdf4a48f256c88ba') fe.torrent.contentlength('331350016') fe.torrent.seeds('789') fe.torrent.peers('456') fe.torrent.verified('123') print_enc(fg.rss_str(pretty=True)) elif arg.startswith('dc.'): fg.load_extension('dc') fg.dc.dc_contributor('Lars Kiesow') if arg.endswith('.atom'): print_enc(fg.atom_str(pretty=True)) else: print_enc(fg.rss_str(pretty=True)) elif arg.startswith('syndication'): fg.load_extension('syndication') fg.syndication.update_period('daily') fg.syndication.update_frequency(2) fg.syndication.update_base('2000-01-01T12:00+00:00') if arg.endswith('.rss'): print_enc(fg.rss_str(pretty=True)) else: print_enc(fg.atom_str(pretty=True)) elif arg.endswith('atom'): fg.atom_file(arg) elif arg.endswith('rss'): fg.rss_file(arg)
def execute(): feed_items = {} added_entry_urls = set() sections = { 'jap': "日本の昔話 (Japanese Legends)", 'minwa': "日本の民話 (Japanese Folktales)", 'world': "世界の昔話 (World Folktales)", 'aesop': "イソップ童話 (Aesop's Fables)", 'kobanashi': "江戸小話 (Edo Short Stories)", 'kaidan': "百物語 (Japanese Ghost Stories)", } for section in sections: feed_items[section] = [] for batch in [_month_urls(section) for section in sections]: for section, month, month_url in batch: root = _fetch_root(month_url) for link in root.cssselect('a'): url = urljoin(month_url, link.get('href')) if url in added_entry_urls: continue if re.match( r'^http://hukumusume.com/douwa/pc/(jap|minwa|world|aesop|kobanashi|kaidan)/{:02}/\w+\.html?$'.format(month), url, ): title = link.text if not title: continue table = link.xpath('./ancestor::table[1]')[0] texts = table.itertext() description = '' for text1, text2 in zip(texts, texts[1:]): if '内容 :' in text1: description = (text1 + text2)[len('内容 :'):] try: image_relative_url = table.cssselect('img')[0].get('src') # Avoid weird case with "001", "002" links in Aesop feed (and maybe elsewhere). if 'corner' in image_relative_url: continue image_url = urljoin(month_url, image_relative_url) except IndexError: # Every one has an image. continue feed_items[section].append({ 'url': url, 'title': link.text, 'description': description, 'image_url': image_url, }) added_entry_urls.add(url) for section, title in sections.items(): fg = FeedGenerator() fg.id('http://hukumusume.com/douwa/pc/{}/index.html'.format(section)) fg.title(title) fg.language('ja') for item in feed_items[section]: entry = fg.add_entry() entry.id(item['url']) entry.title(item['title']) entry.link(href=item['url'], rel='alternate') entry.summary(item['description']) entry.content('<img src="{}" />'.format(item['image_url']), type='CDATA') fg.atom_file('manabi/static/reader/feeds/hukumusume-{}.rss'.format(section))