Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 5 commits
  • 13 files changed
  • 0 commit comments
  • 1 contributor
View
6 README
@@ -5,8 +5,10 @@ PritTorrent
TODO
----
-* 1shot pages
-* Front page?
+* Feed summaries: X items, Y torrents
+* Recent Torrents excluding Popular Torrents
+* render_item styles
+* Flattr button on img hover
* URL longener?
View
28 apps/model/include/model.hrl
@@ -1,4 +1,7 @@
-record(download, {
+ %% User key:
+ user :: binary(),
+ slug :: binary(),
%% Enclosure key:
feed :: binary(),
item :: binary(),
@@ -20,14 +23,17 @@
downspeed :: integer()
}).
--record(feed_item, {feed :: binary(),
- id :: binary(),
- title :: (binary() | null),
- published :: calendar:datetime(),
- homepage :: binary(),
- payment :: binary(),
- image :: binary(),
- xml :: binary(),
- enclosures :: [binary()],
- downloads :: [#download{}]
- }).
+-record(feed_item, {
+ user :: binary(),
+ slug :: binary(),
+ feed :: binary(),
+ id :: binary(),
+ title :: (binary() | null),
+ published :: calendar:datetime(),
+ homepage :: binary(),
+ payment :: binary(),
+ image :: binary(),
+ xml :: binary(),
+ enclosures :: [binary()],
+ downloads :: [#download{}]
+ }).
View
75 apps/model/src/model_enclosures.erl
@@ -1,6 +1,7 @@
-module(model_enclosures).
-export([to_hash/0, set_torrent/3, item_torrents/2,
+ recent_downloads/0, popular_downloads/0,
user_downloads/1, feed_downloads/1]).
-include("../include/model.hrl").
@@ -35,46 +36,64 @@ item_torrents(Feed, Item) ->
?Q("SELECT \"url\", \"info_hash\" FROM item_torrents WHERE \"feed\"=$1 AND \"item\"=$2 ORDER BY \"url\"", [Feed, Item]),
Torrents.
+recent_downloads() ->
+ query_downloads("TRUE", [],
+ "\"published\" DESC", 42).
+
+popular_downloads() ->
+ query_downloads("(\"seeders\" + \"leechers\") > 1", [],
+ "(\"seeders\" + \"leechers\") DESC", 23).
+
user_downloads(UserName) ->
- query_downloads("\"feed\" IN (SELECT \"feed\" FROM user_feeds WHERE \"user\"=$1)", [UserName], 23).
+ query_downloads("\"feed\" IN (SELECT \"feed\" FROM user_feeds WHERE \"user\"=$1)", [UserName],
+ "\"published\" DESC", 23).
feed_downloads(Feed) ->
- query_downloads("\"feed\"=$1", [Feed], 100).
+ query_downloads("\"feed\"=$1", [Feed],
+ "\"published\" DESC", 50).
-query_downloads(Cond, Params, Limit) ->
- case ?Q("SELECT \"feed\", \"item\", \"enclosure\", \"info_hash\", \"name\", \"size\", \"title\", \"published\", \"homepage\", \"payment\", \"image\", \"seeders\", \"leechers\", \"upspeed\", \"downspeed\" FROM downloads_scraped WHERE " ++ Cond ++ " ORDER BY \"published\" DESC LIMIT " ++ integer_to_list(Limit), Params) of
+query_downloads(Cond, Params, Order, Limit) ->
+ case ?Q("SELECT \"user\", \"slug\", \"feed\", \"item\", \"enclosure\", \"info_hash\", \"name\", \"size\", \"title\", \"published\", \"homepage\", \"payment\", \"image\", \"seeders\", \"leechers\", \"upspeed\", \"downspeed\" FROM downloads_scraped WHERE " ++ Cond ++ " ORDER BY " ++ Order ++ " LIMIT " ++ integer_to_list(Limit), Params) of
{ok, _, Rows} ->
Downloads =
- [#download{feed = Feed,
- item = Item,
- enclosure = Enclosure,
- info_hash = InfoHash,
- name = Name,
- size = Size,
- title = Title,
- published = Published,
- homepage = Homepage,
- payment = Payment,
- image = Image,
- seeders = Seeders,
- leechers = Leechers,
- upspeed = Upspeed,
- downspeed = Downspeed}
- || {Feed, Item, Enclosure,
- InfoHash, Name, Size,
- Title, Published, Homepage, Payment, Image,
- Seeders, Leechers, Upspeed, Downspeed
- } <- Rows],
- {ok, group_downloads(Downloads)};
+ rows_to_downloads(Rows),
+ FeedItems = group_downloads(Downloads),
+ {ok, FeedItems};
{error, Reason} ->
{error, Reason}
end.
+rows_to_downloads(Rows) ->
+ [#download{user = User,
+ slug = Slug,
+ feed = Feed,
+ item = Item,
+ enclosure = Enclosure,
+ info_hash = InfoHash,
+ name = Name,
+ size = Size,
+ title = Title,
+ published = Published,
+ homepage = Homepage,
+ payment = Payment,
+ image = Image,
+ seeders = Seeders,
+ leechers = Leechers,
+ upspeed = Upspeed,
+ downspeed = Downspeed}
+ || {User, Slug, Feed, Item, Enclosure,
+ InfoHash, Name, Size,
+ Title, Published, Homepage, Payment, Image,
+ Seeders, Leechers, Upspeed, Downspeed
+ } <- Rows].
+
%% By homepage
group_downloads([]) ->
[];
group_downloads([Download | Downloads]) ->
- #download{feed = Feed,
+ #download{user = User,
+ slug = Slug,
+ feed = Feed,
item = Item,
title = Title,
published = Published,
@@ -87,7 +106,9 @@ group_downloads([Download | Downloads]) ->
Homepage == Homepage1
end, Downloads),
FeedItem =
- #feed_item{feed = Feed,
+ #feed_item{user = User,
+ slug = Slug,
+ feed = Feed,
id = Item,
title = Title,
published = Published,
View
20 apps/ui/priv/static/l.svg
@@ -11,7 +11,7 @@
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="11"
- height="11"
+ height="12"
id="svg3770"
version="1.1"
inkscape:version="0.48.1 r9760"
@@ -30,7 +30,7 @@
<linearGradient
id="linearGradient3762">
<stop
- style="stop-color:#0000ff;stop-opacity:1;"
+ style="stop-color:#008000;stop-opacity:1;"
offset="0"
id="stop3764" />
<stop
@@ -47,7 +47,7 @@
x1="5.3333335"
y1="0"
x2="5.3333335"
- y2="43.75" />
+ y2="75" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3762-9"
@@ -88,14 +88,14 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="16"
- inkscape:cx="10.063858"
- inkscape:cy="10.98577"
+ inkscape:cx="7.032608"
+ inkscape:cy="13.26358"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
- inkscape:window-width="956"
- inkscape:window-height="1057"
- inkscape:window-x="960"
+ inkscape:window-width="601"
+ inkscape:window-height="877"
+ inkscape:window-x="835"
inkscape:window-y="19"
inkscape:window-maximized="0">
<inkscape:grid
@@ -122,10 +122,10 @@
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
- transform="translate(0,-1041.3622)">
+ transform="translate(0,-1040.3622)">
<path
style="fill:url(#linearGradient4329);fill-opacity:1;fill-rule:evenodd;stroke:none"
- d="m 5.5,1052.3622 4.5,-5 -3,0 -0.5,-3 1.5,0 -2.5,-3 -2.5,3 1.5,0 -0.5,3 -3,0 z"
+ d="m 5.5,1052.3622 4.5,-5 -3,0 0,-3 2,0 -3.5,-4 -3.5,4 2,0 0,3 -3,0 z"
id="rect2991"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccccc" />
View
260 apps/ui/priv/static/logo.svg
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="41"
+ height="35"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.1 r9760"
+ sodipodi:docname="logo.svg"
+ inkscape:export-filename="/home/stephan/programming/erlang/prittorrent/apps/ui/priv/static/logo.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="11.313708"
+ inkscape:cx="11.511368"
+ inkscape:cy="16.368244"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1436"
+ inkscape:window-height="877"
+ inkscape:window-x="0"
+ inkscape:window-y="19"
+ inkscape:window-maximized="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid2985"
+ empspacing="5"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-452.36218)">
+ <rect
+ style="fill:#3fff3f;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987"
+ width="5.0000029"
+ height="5.0000029"
+ x="5.9999804"
+ y="452.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7"
+ width="5.0000029"
+ height="5.0000029"
+ x="11.999984"
+ y="452.36218" />
+ <rect
+ style="fill:#3fff3f;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-78"
+ width="5.0000029"
+ height="5.0000029"
+ x="-2.2656639e-05"
+ y="458.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7-8"
+ width="5.0000029"
+ height="5.0000029"
+ x="5.9999804"
+ y="458.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-1"
+ width="5.0000029"
+ height="5.0000029"
+ x="11.999984"
+ y="458.36218" />
+ <rect
+ style="fill:#3fff3f;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7-0"
+ width="5.0000029"
+ height="5.0000029"
+ x="17.999987"
+ y="458.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-6"
+ width="5.0000029"
+ height="5.0000029"
+ x="23.99999"
+ y="458.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7-4"
+ width="5.0000029"
+ height="5.0000029"
+ x="29.999994"
+ y="458.36218" />
+ <rect
+ style="fill:#3fff3f;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-5"
+ width="5.0000029"
+ height="5.0000029"
+ x="23.99999"
+ y="452.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7-9"
+ width="5.0000029"
+ height="5.0000029"
+ x="29.999994"
+ y="452.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-54"
+ width="5.0000029"
+ height="5.0000029"
+ x="29.999994"
+ y="464.36218" />
+ <rect
+ style="fill:#009f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7-6"
+ width="5.0000029"
+ height="5.0000029"
+ x="35.999996"
+ y="464.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7-6-5"
+ width="5.0000029"
+ height="5.0000029"
+ x="35.999996"
+ y="458.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-78-4"
+ width="5.0000029"
+ height="5.0000029"
+ x="-2.2656639e-05"
+ y="464.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7-8-1"
+ width="5.0000029"
+ height="5.0000029"
+ x="5.9999804"
+ y="464.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-1-0"
+ width="5.0000029"
+ height="5.0000029"
+ x="11.999984"
+ y="464.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7-0-1"
+ width="5.0000029"
+ height="5.0000029"
+ x="17.999987"
+ y="464.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-6-5"
+ width="5.0000029"
+ height="5.0000029"
+ x="23.99999"
+ y="464.36218" />
+ <rect
+ style="fill:#009f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-54-0"
+ width="5.0000029"
+ height="5.0000029"
+ x="29.999994"
+ y="470.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7-8-1-5"
+ width="5.0000029"
+ height="5.0000029"
+ x="5.9999804"
+ y="470.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-1-0-9"
+ width="5.0000029"
+ height="5.0000029"
+ x="11.999984"
+ y="470.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7-0-1-4"
+ width="5.0000029"
+ height="5.0000029"
+ x="17.999987"
+ y="470.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-6-5-8"
+ width="5.0000029"
+ height="5.0000029"
+ x="23.99999"
+ y="470.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-1-0-9-3"
+ width="5.0000029"
+ height="5.0000029"
+ x="11.999984"
+ y="476.36218" />
+ <rect
+ style="fill:#00c000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-7-0-1-4-7"
+ width="5.0000029"
+ height="5.0000029"
+ x="17.999987"
+ y="476.36218" />
+ <rect
+ style="fill:#009f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-6-5-8-8"
+ width="5.0000029"
+ height="5.0000029"
+ x="23.99999"
+ y="476.36218" />
+ <rect
+ style="fill:#009f00;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect2987-54-0-8"
+ width="5.0000029"
+ height="5.0000029"
+ x="17.999987"
+ y="482.36221" />
+ </g>
+</svg>
View
12 apps/ui/priv/static/s.svg
@@ -35,8 +35,8 @@
id="linearGradient3768"
x1="8"
y1="1"
- x2="7.7400341"
- y2="39.016735"
+ x2="8.3393936"
+ y2="29.09091"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.64453125,0,0,0.55,0.625,1041.3622)" />
</defs>
@@ -47,15 +47,15 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="45.254834"
+ inkscape:zoom="16"
inkscape:cx="6.2323852"
inkscape:cy="4.6093924"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
- inkscape:window-width="956"
- inkscape:window-height="1057"
- inkscape:window-x="0"
+ inkscape:window-width="710"
+ inkscape:window-height="453"
+ inkscape:window-x="835"
inkscape:window-y="19"
inkscape:window-maximized="0">
<inkscape:grid
View
36 apps/ui/priv/static/style.css
@@ -10,17 +10,15 @@ body > * {
text-align: left;
}
a {
- color: #555;
+ color: #073;
text-decoration: none;
font-weight: bold;
}
a:hover {
- color: #333;
text-decoration: underline;
}
header.site {
- color: #333;
margin: 0 auto 1em;
text-align: center;
border-bottom: 1px dotted #ccc;
@@ -35,7 +33,10 @@ header.site h1 {
line-height: 1em;
}
header.site h1 a {
- color: #444;
+ background: url('logo.svg') no-repeat center left;
+ min-height: 35px;
+ padding-left: 42px;
+ display: inline-block;
}
header.site h1 a:hover {
color: #444;
@@ -58,10 +59,14 @@ header.site .slogan {
max-width: 40em;
}
.col1, .col2 {
- max-width: 50%;
+ max-width: 49%;
+ min-width: 32em;
}
.col1 {
- margin-right: 1em;
+ margin-right: 0.5em;
+}
+.col2 {
+ margin-left: 0.5em;
}
h2 {
@@ -97,7 +102,7 @@ h2 .feedicon {
vertical-align: top;
padding-top: 16px;
padding-left: 16px;
- background: url('rss.png') no-repeat top center;
+ background: url('rss.png') no-repeat center top;
}
h2 .publisher {
font-size: 50%;
@@ -124,6 +129,7 @@ img.logo {
.flattr {
float: right;
text-align: right;
+ padding: 0 0.2em;
}
.flattr a {
font-size: 70%;
@@ -138,7 +144,7 @@ article {
border-top: 1px solid #eee;
margin: 0;
min-height: 72px;
- padding: 0.2em 0;
+ padding: 0.5em 0;
}
.col2 article {
margin-right: 0;
@@ -152,6 +158,11 @@ h3 {
color: #999;
font-weight: bold;
line-height: 1em;
+ font-style: italic;
+ font-family: 'Georgia', serif;
+}
+.col1 h3, .col2 h3 {
+ min-width: 42em;
}
.homepage {
margin: 0;
@@ -164,16 +175,19 @@ h3 {
.download {
list-style-type: none;
- margin: 0.5em 0 0.8em;
+ margin: 0.5em 0 0;
padding: 0;
/* meta & flattr floats above */
clear: both;
}
.download .torrent {
float: left;
- width: 18em;
+}
+.col1 .download .torrent, .col2 .download .torrent {
+ max-width: 18em;
}
.torrent a {
+ color: #090;
background: url('favicon.png') no-repeat top left;
padding-left: 19px;
font-size: 90%;
@@ -211,7 +225,7 @@ h3 {
}
.stats .bw {
background: url('swarm.svg') no-repeat 8% 50%;
- padding-left: 16px;
+ padding-left: 18px;
min-width: 4em;
}
View
16 apps/ui/priv/static/swarm.svg
@@ -96,15 +96,15 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="44.8"
- inkscape:cx="4.5607817"
+ inkscape:zoom="22.4"
+ inkscape:cx="0.79962099"
inkscape:cy="5.2587901"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
- inkscape:window-width="956"
- inkscape:window-height="1057"
- inkscape:window-x="960"
+ inkscape:window-width="831"
+ inkscape:window-height="877"
+ inkscape:window-x="0"
inkscape:window-y="19"
inkscape:window-maximized="0">
<inkscape:grid
@@ -123,7 +123,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -133,13 +133,13 @@
id="layer1"
transform="translate(0,-1040.3622)">
<path
- style="fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ style="fill:#008000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="M 6.4863933,1040.3622 6,1045.0973 l -1.424496,-1.574 -3.1477862,2.8491 -1.42451653,-1.5738 3.14668993,-2.827 -1.4234608,-1.596 z"
id="rect2991"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
- style="fill:#800000;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ style="fill:#008000;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 0,1047.6859 4.8328635,-1.3237 -1.0030115,1.9969 3.9941034,2.0062 -1.0030113,1.9969 -3.9719243,-2.0133 -1.0250443,2.0045 z"
id="rect2991-1"
inkscape:connector-curvature="0"
View
71 apps/ui/src/ui_template.erl
@@ -165,10 +165,10 @@ render_item(ItemLink, Title, Image, Homepage, Payment) ->
render_enclosure(#download{name = Name,
info_hash = InfoHash,
- size = Size}) ->
- Seeders = 0, %% TODO
- Leechers = 0, %% TODO
- Downspeed = 0, %% TODO
+ size = Size,
+ seeders = Seeders,
+ leechers = Leechers,
+ downspeed = Downspeed}) ->
{ok, MySeeders} = application:get_env(ui, seeders),
render_torrent(Name, InfoHash, Size, Seeders + length(MySeeders), Leechers, Downspeed).
@@ -190,6 +190,23 @@ render_torrent(Title, InfoHash, Size, Seeders, Leechers, Bandwidth) ->
]}
]}.
+render_downloads(Downloads) ->
+ lists:map(
+ fun(#feed_item{user = User,
+ slug = Slug,
+ id = ItemId,
+ title = ItemTitle,
+ image = ItemImage,
+ homepage = ItemHomepage,
+ payment = ItemPayment,
+ downloads = ItemDownloads}) ->
+ ItemLink = ui_link:link_item(User, Slug, ItemId),
+ {article, [{class, "item"}],
+ [render_item(ItemLink, ItemTitle, ItemImage, ItemHomepage, ItemPayment) |
+ lists:map(fun render_enclosure/1, ItemDownloads)
+ ]}
+ end, Downloads).
+
page_1column(FeedLink, Col) ->
HeadEls =
if
@@ -220,15 +237,20 @@ page_2column(Prologue, Col1, Col2) ->
%% TODO
render_index() ->
+ {ok, RecentDownloads} =
+ model_enclosures:recent_downloads(),
+ {ok, PopularDownloads} =
+ model_enclosures:popular_downloads(),
+
page_2column(
[{'div',
[{h2, "Recent Torrents"}
]} |
- []],
+ render_downloads(RecentDownloads)],
[{'div',
- [{h2, "Popular Feeds"}
+ [{h2, "Popular Torrents"}
]} |
- []]
+ render_downloads(PopularDownloads)]
).
%% Feeds, Recent Episodes
@@ -251,7 +273,7 @@ render_user(UserName) ->
},
[{h2, "Feeds"} |
lists:map(fun({Slug, _Feed, Title, Homepage, Image}) ->
- {article,
+ {article, [{class, "feed"}],
[{'div',
[if
@@ -278,23 +300,8 @@ render_user(UserName) ->
]}
end, UserFeeds)
],
- [{h2, "Recent Episodes"} |
- lists:map(fun(#feed_item{feed = FeedURL,
- id = ItemId,
- title = ItemTitle,
- image = ItemImage,
- homepage = ItemHomepage,
- payment = ItemPayment,
- downloads = ItemDownloads}) ->
- {value, Feed} =
- lists:keysearch(FeedURL, 2, UserFeeds),
- Slug = element(1, Feed),
- ItemLink = ui_link:link_item(UserName, Slug, ItemId),
- {article, [{class, "item"}],
- [render_item(ItemLink, ItemTitle, ItemImage, ItemHomepage, ItemPayment) |
- lists:map(fun render_enclosure/1, ItemDownloads)
- ]}
- end, UserDownloads)
+ [{h2, "Recent Torrents"} |
+ render_downloads(UserDownloads)
]
).
@@ -334,19 +341,7 @@ render_user_feed(UserName, Slug) ->
]}
], FeedImage, FeedHomepage)
} |
- lists:map(fun(#feed_item{id = ItemId,
- title = ItemTitle,
- image = ItemImage,
- homepage = ItemHomepage,
- payment = ItemPayment,
- downloads = ItemDownloads}) ->
- ItemLink = ui_link:link_item(UserName, Slug, ItemId),
- {article, [{class, "item"},
- {id, ItemId}],
- [render_item(ItemLink, ItemTitle, ItemImage, ItemHomepage, ItemPayment) |
- lists:map(fun render_enclosure/1, ItemDownloads)
- ]}
- end, FeedDownloads)
+ render_downloads(FeedDownloads)
]).
export_feed(UserName, Slug) ->
View
50 pg_downloads.sql
@@ -3,11 +3,17 @@
--
CREATE TABLE downloads_cache(
+ -- User key:
+ "user" TEXT,
+ "slug" TEXT,
-- Enclosure key:
"feed" TEXT,
"item" TEXT,
"enclosure" TEXT,
- PRIMARY KEY ("feed", "item", "enclosure"),
+ PRIMARY KEY ("user", "slug", "feed", "item", "enclosure"),
+ FOREIGN KEY ("user", "slug", "feed")
+ REFERENCES "user_feeds" ("user", "slug", "feed")
+ ON DELETE CASCADE,
FOREIGN KEY ("feed", "item", "enclosure")
REFERENCES "enclosures" ("feed", "item", "url")
ON DELETE CASCADE,
@@ -28,6 +34,8 @@ CREATE INDEX downloads_cache_feed_published ON downloads_cache ("feed", "publish
CREATE OR REPLACE FUNCTION update_downloads_cache(
+ t_user TEXT,
+ t_slug TEXT,
t_feed TEXT,
t_item TEXT,
t_enclosure TEXT,
@@ -39,9 +47,11 @@ CREATE OR REPLACE FUNCTION update_downloads_cache(
t_size BIGINT;
BEGIN
DELETE FROM downloads_cache
- WHERE feed=t_feed
- AND item=t_item
- AND enclosure=t_enclosure;
+ WHERE "user"=t_user
+ AND "slug"=t_slug
+ AND "feed"=t_feed
+ AND "item"=t_item
+ AND "enclosure"=t_enclosure;
SELECT * INTO item_rec
FROM feed_items
@@ -51,15 +61,35 @@ CREATE OR REPLACE FUNCTION update_downloads_cache(
WHERE info_hash=t_info_hash;
INSERT INTO downloads_cache
- (feed, item, enclosure,
+ ("user", slug, feed, item, enclosure,
info_hash, "name", "size",
title, published, homepage, payment, image)
- VALUES (t_feed, t_item, t_enclosure,
+ VALUES (t_user, t_slug, t_feed, t_item, t_enclosure,
t_info_hash, t_name, t_size,
item_rec.title, item_rec.published, item_rec.homepage, item_rec.payment, item_rec.image);
END;
$$ LANGUAGE plpgsql;
+CREATE OR REPLACE FUNCTION update_downloads_cache(
+ t_feed TEXT,
+ t_item TEXT,
+ t_enclosure TEXT,
+ t_info_hash BYTEA
+) RETURNS void AS $$
+ DECLARE
+ user_feed RECORD;
+ BEGIN
+ FOR user_feed IN SELECT *
+ FROM user_feeds
+ WHERE feed=t_feed
+ LOOP
+ PERFORM update_downloads_cache(user_feed."user", user_feed."slug",
+ user_feed."feed",
+ t_item, t_enclosure, t_info_hash);
+ END LOOP;
+ END;
+$$ LANGUAGE plpgsql;
+
CREATE OR REPLACE FUNCTION update_downloads_cache_on_enclosure_torrents(
) RETURNS trigger AS $$
DECLARE
@@ -131,9 +161,11 @@ CREATE TRIGGER enclosures_update_downloads_cache AFTER INSERT OR UPDATE ON enclo
EXECUTE PROCEDURE update_downloads_cache_on_enclosures();
-CREATE VIEW downloads_scraped AS
- SELECT downloads_cache."feed", downloads_cache."item", downloads_cache."enclosure",
+CREATE OR REPLACE VIEW downloads_scraped AS
+ SELECT downloads_cache."user", downloads_cache."slug",
+ downloads_cache."feed", downloads_cache."item", downloads_cache."enclosure",
downloads_cache."info_hash", downloads_cache."name", downloads_cache."size",
downloads_cache."title", downloads_cache."published", downloads_cache."homepage", downloads_cache."payment", downloads_cache."image",
- scraped.seeders, scraped.leechers, scraped.upspeed, scraped.downspeed
+ COALESCE(scraped.seeders, 0) AS "seeders", COALESCE(scraped.leechers, 0) AS "leechers",
+ COALESCE(scraped.upspeed, 0) AS "upspeed", COALESCE(scraped.downspeed, 0) AS "downspeed"
FROM downloads_cache LEFT JOIN scraped ON (downloads_cache.info_hash=scraped.info_hash);
View
6 pg_install.sql
@@ -0,0 +1,6 @@
+SET default_tablespace = safe;
+\i pg_meta.sql
+SET default_tablespace = fast;
+\i pg_var.sql
+\i pg_tracker.sql
+\i pg_downloads.sql
View
70 pg_meta.sql
@@ -0,0 +1,70 @@
+CREATE TABLE users ("name" TEXT NOT NULL,
+ "email" TEXT NOT NULL,
+ "password" TEXT NOT NULL,
+ "activated" BOOLEAN DEFAULT FALSE,
+ "title" TEXT,
+ "image" TEXT,
+ "homepage" TEXT,
+ PRIMARY KEY ("name"));
+CREATE VIEW activated_users AS
+ SELECT "name", "email", "password"
+ FROM users
+ WHERE "activated";
+
+CREATE TABLE feeds ("url" TEXT NOT NULL,
+ "last_update" TIMESTAMP,
+ "etag" TEXT,
+ "last_modified" TEXT,
+ "error" TEXT,
+ "title" TEXT,
+ "homepage" TEXT,
+ "image" TEXT,
+ "xml" TEXT,
+ PRIMARY KEY ("url"));
+
+CREATE TABLE user_feeds ("user" TEXT NOT NULL REFERENCES "users" ("name"),
+ "slug" TEXT NOT NULL,
+ "feed" TEXT NOT NULL REFERENCES "feeds" ("url"),
+ PRIMARY KEY ("user", "slug", "feed"));
+
+CREATE OR REPLACE FUNCTION feed_to_update(
+ update_interval INTERVAL,
+ OUT next_url TEXT, OUT wait INTERVAL
+ ) RETURNS RECORD AS $$
+ DECLARE
+ next_feed RECORD;
+ BEGIN
+ LOCK "feeds" IN SHARE ROW EXCLUSIVE MODE;
+ SELECT "url", "last_update"
+ INTO next_feed
+ FROM "feeds"
+ ORDER BY "last_update" ASC NULLS FIRST
+ LIMIT 1;
+
+ next_url := next_feed.url;
+ IF next_feed.last_update IS NULL THEN
+ next_feed.last_update = '1970-01-01 00:00:00';
+ END IF;
+ wait := next_feed.last_update + update_interval - CURRENT_TIMESTAMP;
+
+ IF wait <= '0'::INTERVAL THEN
+ UPDATE "feeds"
+ SET "last_update"=CURRENT_TIMESTAMP
+ WHERE "url"=next_url;
+ END IF;
+ END;
+$$ LANGUAGE plpgsql;
+
+
+-- Check this with: select * from enclosure_torrents where info_hash not in (select info_hash from torrents);
+-- Or add a constraint on info_hash with either NULL or FOREIGN KEY torrents (info_hash)
+CREATE TABLE enclosure_torrents ("url" TEXT NOT NULL PRIMARY KEY,
+ last_update TIMESTAMP,
+ error TEXT,
+ info_hash BYTEA);
+
+CREATE TABLE torrents ("info_hash" BYTEA PRIMARY KEY,
+ "name" TEXT,
+ "size" BIGINT,
+ "torrent" BYTEA);
+
View
73 pg_users.sql → pg_var.sql
@@ -1,60 +1,3 @@
-CREATE TABLE users ("name" TEXT NOT NULL,
- "email" TEXT NOT NULL,
- "password" TEXT NOT NULL,
- "activated" BOOLEAN DEFAULT FALSE,
- "title" TEXT,
- "image" TEXT,
- "homepage" TEXT,
- PRIMARY KEY ("name"));
-CREATE VIEW activated_users AS
- SELECT "name", "email", "password"
- FROM users
- WHERE "activated";
-
-CREATE TABLE feeds ("url" TEXT NOT NULL,
- "last_update" TIMESTAMP,
- "etag" TEXT,
- "last_modified" TEXT,
- "error" TEXT,
- "title" TEXT,
- "homepage" TEXT,
- "image" TEXT,
- "xml" TEXT,
- PRIMARY KEY ("url"));
-
-CREATE TABLE user_feeds ("user" TEXT NOT NULL REFERENCES "users" ("name"),
- "slug" TEXT NOT NULL,
- "feed" TEXT NOT NULL REFERENCES "feeds" ("url"),
- PRIMARY KEY ("user", "slug", "feed"));
-
-CREATE OR REPLACE FUNCTION feed_to_update(
- update_interval INTERVAL,
- OUT next_url TEXT, OUT wait INTERVAL
- ) RETURNS RECORD AS $$
- DECLARE
- next_feed RECORD;
- BEGIN
- LOCK "feeds" IN SHARE ROW EXCLUSIVE MODE;
- SELECT "url", "last_update"
- INTO next_feed
- FROM "feeds"
- ORDER BY "last_update" ASC NULLS FIRST
- LIMIT 1;
-
- next_url := next_feed.url;
- IF next_feed.last_update IS NULL THEN
- next_feed.last_update = '1970-01-01 00:00:00';
- END IF;
- wait := next_feed.last_update + update_interval - CURRENT_TIMESTAMP;
-
- IF wait <= '0'::INTERVAL THEN
- UPDATE "feeds"
- SET "last_update"=CURRENT_TIMESTAMP
- WHERE "url"=next_url;
- END IF;
- END;
-$$ LANGUAGE plpgsql;
-
CREATE TABLE feed_items ("feed" TEXT NOT NULL REFERENCES "feeds" ("url") ON DELETE CASCADE,
"id" TEXT NOT NULL,
@@ -90,12 +33,8 @@ CREATE TABLE enclosures ("feed" TEXT NOT NULL,
ON DELETE CASCADE);
CREATE INDEX enclosures_url ON enclosures ("url");
--- Check this with: select * from enclosure_torrents where info_hash not in (select info_hash from torrents);
--- Or add a constraint on info_hash with either NULL or FOREIGN KEY torrents (info_hash)
-CREATE TABLE enclosure_torrents ("url" TEXT NOT NULL PRIMARY KEY,
- last_update TIMESTAMP,
- error TEXT,
- info_hash BYTEA);
+
+
CREATE INDEX enclosure_torrents_info_hash
ON enclosure_torrents (info_hash)
WHERE LENGTH(info_hash) = 20;
@@ -145,10 +84,9 @@ CREATE VIEW torrentified AS
ON (enclosures.url=enclosure_torrents.url)
WHERE LENGTH(enclosure_torrents.info_hash)=20 ORDER BY last_update;
-CREATE TABLE torrents ("info_hash" BYTEA PRIMARY KEY,
- "name" TEXT,
- "size" BIGINT,
- "torrent" BYTEA);
+
+
+
CREATE VIEW item_torrents AS
SELECT enclosures.feed, enclosures.item, enclosures.url,
@@ -169,4 +107,3 @@ CREATE OR REPLACE VIEW torrentified_items AS
WHERE "url"=enclosures.url
)
) ORDER BY "published" DESC;
-

No commit comments for this range

Something went wrong with that request. Please try again.