Openbox:Pipemenus:feeder-python
From Openbox
Originally appeared on nakamura-gebeit.de/scripts/ repository.
Retrieved from the depths of the Wayback Machine.
Depends on python-feedparser and python-elementtree modules as per comments.
#!/usr/bin/env python # -*- coding: utf-8 -*- """ #------------------------------------------------------------------------------- feeder.py - version 5 by Vlad George #------------------------------------------------------------------------------- Description: This script pipes rss and podcast feeds into the openbox menu Usage: First you need the python-feedparser and python-elementtree modules (archlinux (AUR)/ ubuntu). Place this script under ~/.config/openbox/scripts, edit the variables under "User set variables" according to your likings (your list of rss_urls, browser and media-player to open links, number of displayed rss-entries, enable/disable caching of feeds, maximum age of feeds), make it executable, then add following to your ~/.config/openbox/menu.xml: "<menu id="feeder-menu" label="rss-feeds" execute="~/.config/openbox/scripts/feeder.py" />... <menu id="root-menu" label="Openbox3">...<menu id="feeder-menu" />...</menu>" and reconfigure openbox. Changelog: 01.07.2007: 1st version 03.07.2007: works now (changed "~").... 05.07.2007: added cache 07.10.2007: added name of rss and sorted output 03.2008: added podcast support #------------------------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. http://www.fsf.org/ """ #------------------------------------------------------------------------------- # User set variables #------------------------------------------------------------------------------- ## your rss feeds: rss_urls = [ #('name to be shown', 'url of rss'), ('Arch Packages', 'http://www.archlinux.org/feeds/packages/'), #('', ''), #('', ''), #('', ''), ] ## browser and audio/video-player to use: # open_with = "gnome-open" open_with = "firefox" play_with = "xmms" ## how many entries should be shown: rss_feeds_count = 60 ## use cache (1 enabled, 0 disabled) cache = 0 ### if cache enabled: ## how old should cache files get - in minutes; set to 0 for manual refresh: ## you can also use >> feeder.py --update << to only update the cache file (useful as cronjob) age = 120 ## temporary directory for cache file (default=/tmp/); leave it as it is. cache_dir = "/tmp" #------------------------------------------------------------------------------- # Script #------------------------------------------------------------------------------- # {{{ ## fold marker start def gettingTitles(url_list): # get feeds for each url: rss_dict = {} for i in xrange(len(url_list)): rss = feedparser.parse(url_list[i][1]) rss_entry = [] try: append = rss_entry.append if rss.entries[i].has_key('link') == False: [append((rss.entries[num].title, None, rss.entries[num].enclosures[0].href)) for num in xrange(rss_feeds_count)] elif rss.entries[i].has_key('enclosures') == False: [append((rss.entries[num].title, rss.entries[num].link, None)) for num in xrange(rss_feeds_count)] else: [append((rss.entries[num].title, rss.entries[num].link, rss.entries[num].enclosures[0].href)) for num in xrange(rss_feeds_count)] except IndexError: pass try: if url_list[i][0] == '': rss_dict[(rss.feed.title, url_list[i][1])] = rss_entry[0:int(rss_feeds_count)] else: rss_dict[(url_list[i][0], url_list[i][1])] = rss_entry[0:int(rss_feeds_count)] except: pass # rss_dict-items: { ..., ([i][0]:> rss-url, [i][1]:> rss-name):[..., ([i][j][0]:> entry-title, [i][j][1]:> entry-link, [i][j][2]:> entry-podcast_link), ...], ... } return rss_dict def generateXml(dict_url_entry, outfile): # sort dict items according display name sorted_list = dict_url_entry.items() sorted_list.sort() # [ ..., (([i][0][0] -> rss-name, [i][0][1] -> rss-url), [..., ([i][1][j][0] -> entry-title, [i][1][j][1] -> entry-link, [i][1][j][2]:> entry-podcast_link), ...]), ... ] root = ET.Element("openbox_pipe_menu") for i in xrange(len(sorted_list)): menu = ET.SubElement(root,"menu", attrib = {"id" : sorted_list[i][0][1], "label" : unicode(sorted_list[i][0][0])}) for j in xrange(len(sorted_list[i][1])): try: if sorted_list[i][1][j][2] == None: item = ET.SubElement(menu, "item", attrib = {"label" : unicode(sorted_list[i][1][j][0])}) action = ET.SubElement(item, "action", attrib = {"name" : "Execute"}) command = ET.SubElement(action, "command") tmp = str(sorted_list[i][1][j][1]).replace('~','%7E') command.text = "%s %s" % (open_with, tmp) elif sorted_list[i][1][j][1] == None: podcast_menu = ET.SubElement(menu, "menu", attrib = {"id" : str(int(random.random()*10000000)) + "-menu", "label" : unicode(sorted_list[i][1][j][0])}) podcast_play = ET.SubElement(podcast_menu, "item", attrib = {"label" : " play podcast"}) podcast_play_action = ET.SubElement(podcast_play, "action", attrib = {"name": "Execute"}) podcast_play_execute = ET.SubElement(podcast_play_action, "command") tmp = str(sorted_list[i][1][j][2]).replace('~','%7E') podcast_play_execute.text = "%s %s" % (play_with, tmp) else: podcast_menu = ET.SubElement(menu, "menu", attrib = {"id" : str(int(random.random()*10000000)) + "-menu", "label" : unicode(sorted_list[i][1][j][0])}) podcast_open = ET.SubElement(podcast_menu, "item", attrib = {"label" : " open "}) podcast_open_action = ET.SubElement(podcast_open, "action", attrib = {"name": "Execute"}) podcast_open_execute = ET.SubElement(podcast_open_action, "command") tmp1 = str(sorted_list[i][1][j][1]).replace('~','%7E') podcast_open_execute.text = "%s %s" % (open_with, tmp1) podcast_play = ET.SubElement(podcast_menu, "item", attrib = {"label" : " play podcast"}) podcast_play_action = ET.SubElement(podcast_play, "action", attrib = {"name": "Execute"}) podcast_play_execute = ET.SubElement(podcast_play_action, "command") tmp2 = str(sorted_list[i][1][j][2]).replace('~','%7E') podcast_play_execute.text = "%s %s" % (play_with, tmp2) except IndexError: pass if cache == 1: separator = ET.SubElement(root,"separator") refresh = ET.SubElement(root,"item", attrib = {"label":"Reload Cache"}) action2 = ET.SubElement(refresh,"action",attrib = {"name":"Execute"}) command2 = ET.SubElement(action2,"command") command2.text = "%s %s" % (sys.argv[0], "--update") tree = ET.ElementTree(root) tree.write(outfile) def ageCheck(age_in_min, file_to_check): age_in_sec = int(age_in_min)*60 file_age = int(time())-int(os.path.getmtime(file_to_check)) if age_in_min == 0: return 1 elif os.path.isfile(file_to_check) and file_age < age_in_sec: return 1 else: return 0 def printXml(xml_entry): temp_file = file(xml_entry,'r') a = temp_file.read() temp_file.close() print a #------------------------------------------------------------------------------- # Main #------------------------------------------------------------------------------- import os.path, sys, feedparser import elementtree.ElementTree as ET import random from time import time #-------------------------# if __name__ == "__main__" : #-------------------------# if cache == 1: cache_file = cache_dir + "/." + str(os.path.split(sys.argv[0])[1]) + "-" + str(os.getuid()) + ".cache" if ('--update' in sys.argv[1:]): generateXml(gettingTitles(rss_urls), cache_file) elif os.path.isfile(cache_file) and ageCheck(age, cache_file): print '<?xml version="1.0" encoding="UTF-8"?>' printXml(cache_file) else: generateXml(gettingTitles(rss_urls), cache_file) print '<?xml version="1.0" encoding="UTF-8"?>' printXml(cache_file) else: print '<?xml version="1.0" encoding="UTF-8"?>' generateXml(gettingTitles(rss_urls), sys.stdout) # }}} ## fold marker end # vim: set ft=python ts=4 sw=4 foldmethod=marker :