diff options
-rw-r--r-- | backend.php | 183 | ||||
-rw-r--r-- | tt-rss.css | 52 | ||||
-rw-r--r-- | tt-rss.js | 34 | ||||
-rw-r--r-- | tt-rss.php | 5 | ||||
-rw-r--r-- | ttrss_schema.sql | 14 |
5 files changed, 233 insertions, 55 deletions
diff --git a/backend.php b/backend.php index d850f0233..5eb64d102 100644 --- a/backend.php +++ b/backend.php @@ -3,13 +3,22 @@ include "config.php"; - $link = pg_connect(DB_CONN); - + require_once('magpierss/rss_fetch.inc'); + + $link = pg_connect(DB_CONN); + + pg_query("set client_encoding = 'utf-8'"); + $op = $_GET["op"]; if ($op == "feeds") { - $result = pg_query("SELECT * FROM ttrss_feeds ORDER BY title"); + $result = pg_query("SELECT *, + (SELECT count(id) FROM ttrss_entries + WHERE feed_id = ttrss_feeds.id) AS total, + (SELECT count(id) FROM ttrss_entries + WHERE feed_id = ttrss_feeds.id AND unread = true) as unread + FROM ttrss_feeds ORDER BY title"); print "<ul>"; @@ -20,11 +29,14 @@ $feed = $line["title"]; $feed_id = $line["id"]; + $total = $line["total"]; + $unread = $line["unread"]; + $class = ($lnum % 2) ? "even" : "odd"; // if ($lnum == 2 || $lnum == 0) $feed = "<b>$feed</b>"; - $feed = "<a href=\"javascript:viewfeed($feed_id);\">$feed</a>"; + $feed = "<a href=\"javascript:viewfeed($feed_id, 0);\">$feed ($unread/$total)</a>"; print "<li class=\"$class\">$feed</li>"; ++$lnum; @@ -36,46 +48,163 @@ if ($op == "view") { - $post = $_GET["post"]; - $feed = $_GET["feed"]; + $id = $_GET["id"]; + + $result = pg_query("SELECT title,link,content FROM ttrss_entries + WHERE id = '$id'"); - print "<h1>$post</h1>"; - print "<h2>$feed</h2>"; + if ($result) { - print "<p>Blah blah blah blah blah</p>"; + $line = pg_fetch_assoc($result); + print "<table class=\"feedOverview\">"; + print "<tr><td><b>Title:</b></td><td>".$line["title"]."</td></tr>"; + print "<tr><td><b>Link:</b></td><td><a href=\"".$line["link"]."\">".$line["link"]."</a></td></tr>"; + + print "</table>"; + + print $line["content"]; + + + } } if ($op == "viewfeed") { $feed = $_GET["feed"]; +// $feed = 0; // for speed - $headlines = array("Linus Torvalds flies to the Moon", - "SCO bankrupt at last", - "OMG WTF ANOTHER HEADLINE", - "Another clever headline from $feed", - "I'm really not feeling creative today", - "No, seriously"); + $skip = $_GET["skip"]; - $headlines = array_merge($headlines, $headlines); + $result = pg_query("SELECT * FROM ttrss_feeds WHERE id = '$feed'"); - print "<ul>"; + if ($result) { - $lnum = 0; + $line = pg_fetch_assoc($result); - foreach ($headlines as $hl) { - $class = ($lnum % 2) ? "even" : "odd"; + $rss = fetch_rss($line["feed_url"]); -// if ($lnum == 2 || $lnum == 0) $feed = "<b>$feed</b>"; - - $hl = "<a href=\"javascript:view('$feed','$hl')\">$hl</a>"; + if ($rss) { + + foreach ($rss->items as $item) { + + $entry_guid = $item["id"]; + + if (!$entry_guid) $entry_guid = $item["guid"]; + if (!$entry_guid) $entry_guid = $item["link"]; + + $entry_timestamp = $item["pubdate"]; + if (!$entry_timestamp) $entry_timestamp = $item["modified"]; + if (!$entry_timestamp) $entry_timestamp = $item["updated"]; + + $entry_timestamp = strtotime($entry_timestamp); + + $entry_title = $item["title"]; + $entry_link = $item["link"]; + + $entry_content = $item["description"]; + if (!$entry_content) $entry_content = $item["content"]; + + $entry_content = pg_escape_string($entry_content); + $entry_title = pg_escape_string($entry_title); + + $content_md5 = md5($entry_content); + + $result = pg_query(" + SELECT + id,unread,md5_hash + FROM + ttrss_entries + WHERE + guid = '$entry_guid' OR md5_hash = '$content_md5'"); + + if (pg_num_rows($result) == 0) { + + $entry_timestamp = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp); + + $query = "INSERT INTO ttrss_entries + (title, guid, link, updated, content, feed_id, md5_hash) + VALUES + ('$entry_title', '$entry_guid', '$entry_link', + '$entry_timestamp', '$entry_content', '$feed', + '$content_md5')"; + + pg_query($query); + + } else { + + $entry_id = pg_fetch_result($result, 0, "id"); + $entry_timestamp = strftime("%Y/%m/%d %H:%M:%S", $entry_timestamp); + + $unread = pg_fetch_result($result, 0, "unread"); + $md5_hash = pg_fetch_result($result, 0, "md5_hash"); + + if ($md5_hash != $content_md5) + $unread = "false"; + + $query = "UPDATE ttrss_entries + SET + title ='$entry_title', + link = '$entry_link', + updated = '$entry_timestamp', + content = '$entry_content', + md5_hash = '$content_md5', + unread = '$unread' + WHERE + id = '$entry_id'"; + + $result = pg_query($query); + +// print "$entry_guid - $entry_timestamp - $entry_title - +// $entry_link - $entry_id<br>"; + + } + + } - print "<li class=\"$class\">$hl</li>"; - ++$lnum; - } + print "<table class=\"headlines\" width=\"100%\">"; + print "<tr><td colspan=\"2\" class=\"title\">" . $rss->channel["title"] . "</td></tr>"; - print "</ul>"; + $result = pg_query("SELECT id,title,updated,unread FROM ttrss_entries WHERE + feed_id = '$feed' ORDER BY updated LIMIT 10 OFFSET $skip"); + $lnum = 0; + + while ($line = pg_fetch_assoc($result)) { + + $class = ($lnum % 2) ? "even" : "odd"; + + if ($line["unread"] == "t") + $class .= "Unread"; + + $content_link = "<a href=\"javascript:view(".$line["id"].");\">".$line["title"]."</a>"; + + print "<tr class='$class' id='RROW-".$line["id"]."'>"; + print "<td class='headlineUpdated'>".$line["updated"]."</td>"; + print "<td class='headlineTitle'>$content_link</td>"; + + print "</tr>"; + + ++$lnum; + } + + print "<tr><td colspan=\"2\" class=\"headlineToolbar\">"; + + $next_skip = $skip + 10; + $prev_skip = $skip - 10; + + print "<a class=\"button\" + href=\"javascript:viewfeed($feed, $prev_skip);\">Previous Page</a>"; + print " "; + print "<a class=\"button\" + href=\"javascript:viewfeed($feed, $next_skip);\">Next Page</a>"; + + print "</td></tr>"; + print "</table>"; + + } + + } } diff --git a/tt-rss.css b/tt-rss.css index 77e36b073..5903e77c3 100644 --- a/tt-rss.css +++ b/tt-rss.css @@ -18,7 +18,7 @@ a.button { border : 1px solid #d0d0d0; background : white; color : black; - padding : 5px 10px 5px 10px; + padding : 2px 10px 2px 10px; } a.button:hover { @@ -26,14 +26,41 @@ a.button:hover { text-decoration : none; } -td.toolbar { +table.feedOverview { + margin : 5px; + border : 1px solid #c0c0c0; + background : #f0f0f0; + -moz-border-radius : 5px; + padding : 5px; + font-size : small; +} + +td.headlineToolbar { + padding-top : 10px; +} + +table.headlines td.title { + font-weight : bold; + font-size : large; + border-width : 0px 0px 1px 0px; + border-color : #d0d0d0; + border-style : solid; + text-align : right; +} + +table.headlines td.headlineUpdated { + width : 200px; + +} + +table.main td.toolbar { height : 40px; text-align : right; background : #f0f0f0; padding-right : 5px; } -td.header { +table.main td.header { font-size : 18pt; background : #f0f0f0; height : 50px; @@ -42,15 +69,15 @@ td.header { font-weight : bold; } -td.feeds { - width : 180px; +table.main td.feeds { + width : 250px; border-width : 1px 1px 0px 0px; border-color : #c0c0c0; border-style : solid; padding : 10px; } -td.headlines { +table.main td.headlines { height : 25%; padding : 10px; border-width : 1px 0px 0px 0px; @@ -59,7 +86,7 @@ td.headlines { overflow : scroll; } -td.content { +table.main td.content { padding : 10px; border-width : 1px 0px 0px 0px; border-color : #c0c0c0; @@ -67,7 +94,7 @@ td.content { overflow : scroll; } -td.notify { +table.main td.notify { height : 40px; border-width : 1px 0px 0px 0px; border-color : #c0c0c0; @@ -81,11 +108,14 @@ td.notify { background-color : #f0f0f0; } -.odd { - - +.evenUnread { + background-color : #f0f0f0; + font-weight : bold; } +.oddUnread { + font-weight : bold; +} li { list-style-type : none; @@ -47,20 +47,26 @@ function notify(msg) { } function feedlist_callback() { + var container = document.getElementById('feeds'); if (xmlhttp.readyState == 4) { - document.getElementById('feeds').innerHTML=xmlhttp.responseText; + container.innerHTML=xmlhttp.responseText; + } else { } } function viewfeed_callback() { + var container = document.getElementById('headlines'); if (xmlhttp.readyState == 4) { - document.getElementById('headlines').innerHTML=xmlhttp.responseText; + container.innerHTML = xmlhttp.responseText; + } else { } } function view_callback() { + var container = document.getElementById('content'); if (xmlhttp.readyState == 4) { - document.getElementById('content').innerHTML=xmlhttp.responseText; + container.innerHTML=xmlhttp.responseText; + } else { } } @@ -73,22 +79,32 @@ function update_feed_list() { } -function viewfeed(feed) { +function viewfeed(feed, skip) { notify("view-feed: " + feed); - xmlhttp.open("GET", "backend.php?op=viewfeed&feed=" + param_escape(feed) , true); + document.getElementById('headlines').innerHTML='Loading headlines, please wait...'; + + xmlhttp.open("GET", "backend.php?op=viewfeed&feed=" + param_escape(feed) + + "&skip=" + skip, true); xmlhttp.onreadystatechange=viewfeed_callback; xmlhttp.send(null); } -function view(feed, post) { +function view(id) { + + var crow = document.getElementById("RROW-" + id); + + if (crow) { + crow.className = crow.className.replace("Unread", ""); + } + + notify(crow.className); - notify("view: " + feed + ", " + post); + document.getElementById('content').innerHTML='Loading, please wait...'; - xmlhttp.open("GET", "backend.php?op=view&feed=" + param_escape(feed) + - "&post=" + post, true); + xmlhttp.open("GET", "backend.php?op=view&id=" + param_escape(id), true); xmlhttp.onreadystatechange=view_callback; xmlhttp.send(null); diff --git a/tt-rss.php b/tt-rss.php index cc854ea6b..cba57923d 100644 --- a/tt-rss.php +++ b/tt-rss.php @@ -3,11 +3,12 @@ <title>Tiny Tiny RSS</title> <link rel="stylesheet" href="tt-rss.css" type="text/css"> <script type="text/javascript" src="tt-rss.js"></script> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body onload="init()"> -<table width="100%" height="100%" cellspacing=0 cellpadding=0> +<table width="100%" height="100%" cellspacing=0 cellpadding=0 class="main"> <tr> <td class="header" valign="middle" colspan="2"> Tiny Tiny RSS @@ -16,7 +17,7 @@ <tr> <td class="toolbar" valign="middle" colspan="2"> <a class="button">Preferences</a> - <a class="button">Refresh</a> + <a class="button" href="javascript:reload()">Refresh</a> </td> </tr> <tr> diff --git a/ttrss_schema.sql b/ttrss_schema.sql index e627442e2..62446a8b3 100644 --- a/ttrss_schema.sql +++ b/ttrss_schema.sql @@ -6,20 +6,22 @@ create table ttrss_feeds (id serial not null primary key, feed_url varchar(250) unique not null, last_updated timestamp default null); -insert into ttrss_feeds (id,title,feed_url) values (0, 'Art.Gnome.Org Releases', 'http://art.gnome.org/backend.php'); +insert into ttrss_feeds (id,title,feed_url) values (0, 'Daily Strips', 'http://naboo.lan/~fox/strips/backend.php?op=rss'); insert into ttrss_feeds (id,title,feed_url) values (1, 'Footnotes', 'http://gnomedesktop.org/node/feed'); insert into ttrss_feeds (id,title,feed_url) values (2, 'Freedesktop.org', 'http://planet.freedesktop.org/rss20.xml'); insert into ttrss_feeds (id,title,feed_url) values (3, 'Planet Debian', 'http://planet.debian.org/rss20.xml'); insert into ttrss_feeds (id,title,feed_url) values (4, 'Planet Ubuntu', 'http://planet.ubuntulinux.org/rss20.xml'); insert into ttrss_feeds (id,title,feed_url) values (5, 'Planet GNOME', 'http://planet.gnome.org/rss20.xml'); insert into ttrss_feeds (id,title,feed_url) values (6, 'Monologue', 'http://www.go-mono.com/monologue/index.rss'); +insert into ttrss_feeds (id,title,feed_url) values (7, 'Art.Gnome.Org Releases', 'http://art.gnome.org/backend.php'); create table ttrss_entries (id serial not null primary key, - feed_id int references ttrss_feeds(id), - entry_time timestamp not null, - headline varchar(250) not null, + feed_id int references ttrss_feeds(id) not null, + updated timestamp not null, + title varchar(250) not null, guid varchar(300) not null unique, - link varchar(300) not null, - content text not null + link varchar(300) not null unique, + md5_hash varchar(200) not null unique, + content text not null, unread boolean default true); |