Created
April 20, 2009 16:06
-
-
Save satyr/98601 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* appjet:version 0.1 */ | |
const | |
ItemMax = 16, | |
H = (function(m){ | |
function f($){ return m[$] } | |
return function H(s){ return s.replace(/[&<>\"\']/g, f) }; | |
}({'&':'&','<':'<','>':'>','"':'"',"'":'''})), | |
$ = function(s, a){ | |
return s.replace(/\$[\d$]/g, function($x){ | |
var x = $x[1]; | |
return x === '$' ? x : a[x] || $x; | |
}); | |
}, | |
re_desc = | |
/<meta[^<]+name=([\'\"]?)description\1[^<]+content=([\"\']?)([^]+?)\2/i, | |
re_lang = /<html[^<]+lang=([\"\']?)(\w+?)\1/i; | |
for each(let m in ( | |
'url,re,title,desc,author,link,ftitle,fdesc,fauthor,flink,'+ | |
'max,lang,rev').split(',')) this[m] = request.params[m]; | |
if(!url || !re || !title) printForm(); | |
max = +max || ItemMax; | |
try { re = RegExp(re, 'mg') } catch(e){ die('Failed to compile "re".') } | |
({data:data, headers:headers}) = wget(url, {}, {complete: true}); | |
data || die('wget() returned nothing.'); | |
var channel = { | |
titl: ftitle || (/<title>([^<]+)<\/title/i(data) || '')[1] || url, | |
link: flink || url, | |
desc: fdesc || (re_desc(data) || 0)[3] || '', | |
auth: fauthor || '', | |
lang: lang || (re_lang(data) || 0)[2] || 'en', | |
date: (headers['Last-Modified'] || headers.Date || '')[0], | |
self: ['http://', appjet.appName, '.', appjet.mainDomain, request.path, | |
request.query ? '?'+ request.query : ''].join(''), | |
}; | |
for(let [k, s] in channel) if(s) channel[k] = H(s); | |
var items = [], i = 0, m | |
while((m = re(data))){ | |
let guid = md5(m[0]); | |
items.push({ | |
titl: H($(title, m)), | |
link: H(link ? $(link, m) : channel.link + '#' + guid), | |
guid: guid, | |
desc: desc ? $(desc, m).replace(/\]\]>/g, ']]]]><![CDATA[>') : '', | |
auth: author ? H($(author, m)) : '', | |
}); | |
if(++i >= max) break; | |
} | |
W = response.write; | |
page.setMode('plain'); | |
response.setContentType('application/xml;charset=utf-8'); | |
W("<?xml version='1.0' encoding='utf-8'?>"); W(supplant(channel, """ | |
<rss version='2.0' xml:lang='{lang}' | |
xmlns:dc='http://purl.org/dc/elements/1.1/' | |
xmlns:atom='http://www.w3.org/2005/Atom'> | |
<channel> | |
<language>{lang}</language> | |
<title>{titl}</title> | |
<link>{link}</link> | |
<description>{desc}</description> | |
<dc:creator>{auth}</dc:creator> | |
<pubDate>{date}</pubDate> | |
<lastBuildDate>{date}</lastBuildDate> | |
<atom:link href='{self}' rel='self' type='application/rss+xml'/>""")); | |
for each(let item in rev ? items.reverse() : items) W(supplant(item, """ | |
<item> | |
<title>{titl}</title> | |
<link>{link}</link> | |
<guid isPermaLink='false'>{guid}</guid> | |
<description><![CDATA[{desc}]]></description> | |
<dc:creator>{auth}</dc:creator> | |
</item>""")); W(""" | |
</channel> | |
</rss>"""); | |
function die(msg, err){ | |
print(H3('Error:'), P(msg)); | |
err && print(PRE(err.stack())); | |
response.stop(); | |
} | |
function pli(name, desc, size){ | |
return P(LABEL( | |
{'for': name}, | |
name + (~desc.indexOf('$') ? ' [ '+ desc +' ] ' : ' ('+ desc +')'), BR(), | |
INPUT({name: name, id: name, size: size}))); | |
} | |
function printForm(){ print( | |
H1('feed9en'), | |
P('See ', A({href: 'http://feedgen.appjet.net/'}, 'original'),' for usage.'), | |
FORM( | |
{action: '/', target: '_blank'}, | |
FIELDSET( | |
LEGEND('Required'), | |
pli('url', 'URL', 80), | |
P('re (Regular expression for items)', BR(), | |
TEXTAREA({name: 're', rows: 3, cols: 60})), | |
pli('title', "Item title. Use $n to include captures ($$ for `$').", 80), | |
INPUT({type: 'submit'})), | |
FIELDSET( | |
LEGEND('Optional'), | |
pli('desc', 'Item description. Can use $n.', 80), | |
pli('author', 'Item author. Can use $n.', 80), | |
pli('link', 'Item link. Can use $n.', 80), | |
pli('ftitle', 'Feed title', 80), | |
pli('fdesc', 'Feed description', 80), | |
pli('fauthor', 'Feed author', 80), | |
pli('flink', 'Feed link', 80), | |
pli('lang', 'Language', 20), | |
pli('max', 'Max number of items. Defaults to '+ ItemMax, 10), | |
P(LABEL( | |
{'for': 'rev'}, | |
'rev (Reverse order)', BR(), | |
INPUT({name: 'rev', id: 'rev', type: 'checkbox'})))))); | |
response.stop(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment