- # Hooks should return a list of FrontPageUpdate objects, making this
- # return value a list of lists
- updates_lol = run_hooks('frontpage_updates', limit=10)
- updates = sum(updates_lol, [])
-
- updates.sort(key=lambda obj: obj.time)
- updates.reverse()
- c.updates = updates[0:10]
+ # XXX no reason to do this on the fly; cache it on server startup
+ update_config = defaultdict(dict) # source_name => config
+ key_rx = re.compile(
+ '(?x) ^ spline-frontpage [.] sources [.] (\w+) (?: [.] (\w+) )? $')
+ for key, val in config.iteritems():
+ match = key_rx.match(key)
+ if not match:
+ continue
+
+ source_name, subkey = match.groups()
+ if not subkey:
+ # This is the type declaration; use a special key
+ subkey = '__type__'
+
+ if subkey in ('limit', 'max_age'):
+ val = int(val)
+ update_config[source_name][subkey] = val
+
+ global_limit = int(config.get('spline-frontpage.limit', 10))
+ now = datetime.datetime.now()
+ try:
+ global_max_age = now - datetime.timedelta(
+ seconds=int(config['spline-frontpage.max_age']))
+ except KeyError:
+ global_max_age = None
+
+ # Ask plugins to deal with this stuff for us!
+ updates = []
+ for source, source_config in update_config.iteritems():
+ hook_name = 'frontpage_updates_' + source_config['__type__']
+
+ # Merge with the global config
+ merged_config = source_config.copy()
+ del merged_config['__type__']
+
+ merged_config['limit'] = min(
+ merged_config.get('limit', global_limit),
+ global_limit,
+ )
+
+ try:
+ local_max_age = now - datetime.timedelta(
+ seconds=merged_config['max_age'])
+ except KeyError:
+ local_max_age = None
+
+ if global_max_age and local_max_age:
+ merged_config['max_age'] = max(global_max_age, local_max_age)
+ else:
+ merged_config['max_age'] = global_max_age or local_max_age
+
+ # XXX bleh
+ updates_lol = run_hooks(hook_name, **merged_config)
+ source_obj = updates_lol[0]
+ updates += source_obj.poll(merged_config['limit'], merged_config['max_age'])
+
+ # Little optimization: maximum age effectively becomes the age of
+ # the oldest thing that would still appear on the page, as anything
+ # older would drop off the end no matter what.
+ # So sort by descending time and crop each iteration...
+ updates.sort(key=lambda obj: obj.time, reverse=True)
+ updates = updates[:global_limit]
+
+ if updates and len(updates) == global_limit:
+ global_max_age = updates[-1].time
+
+ c.updates = updates