mirror of
https://github.com/tildeverse/lobsters
synced 2024-06-14 04:56:39 +00:00
first stab at planet rss aggregation
could probably use a prettier layout and auto-posting a weblog url to the main site (carrying tags)
This commit is contained in:
parent
8d17638085
commit
85cb7c2057
4
Gemfile
4
Gemfile
|
@ -32,6 +32,10 @@ gem "oauth"
|
|||
# for parsing incoming mail
|
||||
gem "mail"
|
||||
|
||||
# for planet rss aggregation
|
||||
gem "feed-normalizer"
|
||||
gem "loofah"
|
||||
|
||||
group :test, :development do
|
||||
gem "rspec-rails", "~> 2.6"
|
||||
gem "machinist"
|
||||
|
|
|
@ -39,7 +39,11 @@ GEM
|
|||
execjs (2.2.1)
|
||||
faker (1.4.2)
|
||||
i18n (~> 0.5)
|
||||
feed-normalizer (1.5.2)
|
||||
hpricot (>= 0.6)
|
||||
simple-rss (>= 1.1)
|
||||
hike (1.2.3)
|
||||
hpricot (0.8.6)
|
||||
htmlentities (4.3.2)
|
||||
i18n (0.6.11)
|
||||
innertube (1.1.0)
|
||||
|
@ -48,6 +52,8 @@ GEM
|
|||
thor (>= 0.14, < 2.0)
|
||||
json (1.8.1)
|
||||
kgio (2.9.2)
|
||||
loofah (2.0.0)
|
||||
nokogiri (>= 1.5.9)
|
||||
machinist (2.0)
|
||||
mail (2.5.4)
|
||||
mime-types (~> 1.16)
|
||||
|
@ -97,6 +103,7 @@ GEM
|
|||
rspec-core (~> 2.99.0)
|
||||
rspec-expectations (~> 2.99.0)
|
||||
rspec-mocks (~> 2.99.0)
|
||||
simple-rss (1.3.1)
|
||||
sprockets (2.12.1)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
|
@ -136,8 +143,10 @@ DEPENDENCIES
|
|||
dynamic_form
|
||||
exception_notification
|
||||
faker
|
||||
feed-normalizer
|
||||
htmlentities
|
||||
jquery-rails
|
||||
loofah
|
||||
machinist
|
||||
mail
|
||||
mysql2 (>= 0.3.14)
|
||||
|
|
|
@ -494,6 +494,10 @@ li .domain {
|
|||
font-size: 8.5pt;
|
||||
vertical-align: middle;
|
||||
}
|
||||
li .domain a {
|
||||
color: #888;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.merge {
|
||||
background: url(data:image/png;base64,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) no-repeat;
|
||||
|
@ -1121,3 +1125,10 @@ div.fieldWithErrors {
|
|||
font-style: italic;
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
div.weblog_content {
|
||||
padding: 0 2em;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ private
|
|||
:email_replies, :email_messages, :email_mentions,
|
||||
:pushover_replies, :pushover_messages, :pushover_mentions,
|
||||
:pushover_user_key, :pushover_device, :pushover_sound,
|
||||
:mailing_list_mode,
|
||||
:mailing_list_mode, :weblog_feed_url
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
24
app/controllers/weblogs_controller.rb
Normal file
24
app/controllers/weblogs_controller.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
class WeblogsController < ApplicationController
|
||||
before_filter { @page = page }
|
||||
|
||||
WEBLOGS_PER_PAGE = 10
|
||||
|
||||
def index
|
||||
@pages = (Weblog.count / WEBLOGS_PER_PAGE.to_f).ceil
|
||||
if @page > @pages
|
||||
@page = @pages
|
||||
end
|
||||
@show_more = @page < @pages
|
||||
|
||||
@weblogs = Weblog.order("created_at DESC").
|
||||
offset((@page - 1) * WEBLOGS_PER_PAGE).
|
||||
limit(WEBLOGS_PER_PAGE)
|
||||
|
||||
render :action => "index"
|
||||
end
|
||||
|
||||
private
|
||||
def page
|
||||
params[:page].to_i > 0 ? params[:page].to_i : 1
|
||||
end
|
||||
end
|
|
@ -16,4 +16,8 @@ module ApplicationHelper
|
|||
label_tag(nil, time_ago_in_words(*args),
|
||||
:title => args.first.strftime("%F %T %z"))
|
||||
end
|
||||
|
||||
def main_root_url
|
||||
Rails.application.routes.url_helpers.root_url
|
||||
end
|
||||
end
|
||||
|
|
|
@ -19,6 +19,7 @@ class User < ActiveRecord::Base
|
|||
belongs_to :banned_by_user,
|
||||
:class_name => "User"
|
||||
has_many :invitations
|
||||
has_many :weblogs
|
||||
|
||||
has_secure_password
|
||||
|
||||
|
@ -31,6 +32,10 @@ class User < ActiveRecord::Base
|
|||
:format => { :with => /\A[A-Za-z0-9][A-Za-z0-9_-]{0,24}\Z/ },
|
||||
:uniqueness => { :case_sensitive => false }
|
||||
|
||||
validates :weblog_feed_url,
|
||||
:format => { :with => /\Ahttps?:\/\/([^\.]+\.)+[a-z]+(\/|\z)/ },
|
||||
:allow_blank => true
|
||||
|
||||
validates_each :username do |record,attr,value|
|
||||
if BANNED_USERNAMES.include?(value.to_s.downcase)
|
||||
record.errors.add(attr, "is not permitted")
|
||||
|
|
9
app/models/weblog.rb
Normal file
9
app/models/weblog.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
class Weblog < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
|
||||
serialize :tags, Array
|
||||
|
||||
def sanitized_content
|
||||
Loofah.fragment(self.content).scrub!(:strip).scrub!(:nofollow).to_s.html_safe
|
||||
end
|
||||
end
|
|
@ -65,7 +65,7 @@
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<div id="headerright" class="<%= @user ? "loggedin" : "" %>">
|
||||
<div id="headerright">
|
||||
<span class="headerlinks">
|
||||
<a href="/filters" <%= @cur_url == "/filters" ?
|
||||
raw("class=\"cur_url\"") : "" %>>Filters</a>
|
||||
|
|
63
app/views/layouts/weblogs.html.erb
Normal file
63
app/views/layouts/weblogs.html.erb
Normal file
|
@ -0,0 +1,63 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon.png" />
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon.png" />
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-144.png" />
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="robots" content="noarchive,noodp,noydir" />
|
||||
<meta name="referrer" content="always" />
|
||||
<% if @short_url %>
|
||||
<link rev="canonical" rel="self alternate shorter shorturl shortlink"
|
||||
href="<%= @short_url %>" />
|
||||
<% end %>
|
||||
<title><%= @title.present? ? "#{@title} | " : "" %>Planet <%=
|
||||
Rails.application.name %></title>
|
||||
<%= stylesheet_link_tag "application", :media => "all" %>
|
||||
<% if @user %>
|
||||
<%= javascript_include_tag "application" %>
|
||||
<script>
|
||||
Lobsters.curUser = '<%= @user.id %>';
|
||||
</script>
|
||||
<% end %>
|
||||
<%= csrf_meta_tags %>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrapper">
|
||||
<div id="header">
|
||||
<div id="headerleft">
|
||||
<a id="l_holder" style="background-color: #<%= sprintf("%02x%02x%02x",
|
||||
[ 255, (@traffic * 7).floor + 50.0 ].min, 0, 0) %>;" href="/"
|
||||
title="<%= Rails.application.name %> (<%= @traffic.to_i %>)"></a>
|
||||
<span id="headertitle">
|
||||
<a href="/">Planet <%= Rails.application.name %></a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div id="headerright">
|
||||
<span class="headerlinks">
|
||||
<a href="<%= main_root_url %>"><%= Rails.application.name %></a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div id="inside">
|
||||
<% if flash[:error] %>
|
||||
<div class="flash-error"><%= flash[:error] %></div>
|
||||
<% elsif flash[:success] %>
|
||||
<div class="flash-success"><%= flash[:success] %></div>
|
||||
<% end %>
|
||||
|
||||
<%= yield %>
|
||||
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -38,11 +38,16 @@
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="boxline">
|
||||
<%= f.label :pushover_user_key,
|
||||
raw("<a href=\"https://pushover.net/\">Pushover</a> User Key:"),
|
||||
:class => "required" %>
|
||||
<%= f.text_field :pushover_user_key, :size => 40 %>
|
||||
<span class="hint">
|
||||
For optional comment and message notifications below
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="boxline">
|
||||
|
@ -58,6 +63,20 @@
|
|||
<%= f.select :pushover_sound, Pushover.sounds.map{|k,v| [ v, k ] } %>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="boxline">
|
||||
<%= f.label :weblog_feed_url, "Weblog Feed URL:",
|
||||
:class => "required" %>
|
||||
<%= f.text_field :weblog_feed_url, :placeholder => "optional",
|
||||
:size => 40 %>
|
||||
<span class="hint">
|
||||
For RSS/Atom feed aggregation; restrict to a technical feed if possible
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div class="boxline">
|
||||
<%= f.label :about, "About:", :class => "required" %>
|
||||
<%= f.text_area :about, :size => "100x5", :style => "width: 600px;" %>
|
||||
|
|
44
app/views/weblogs/index.html.erb
Normal file
44
app/views/weblogs/index.html.erb
Normal file
|
@ -0,0 +1,44 @@
|
|||
<ol class="stories list">
|
||||
<% @weblogs.each do |weblog| %>
|
||||
<li class="story">
|
||||
<div class="story_liner">
|
||||
<div class="details">
|
||||
<span class="link">
|
||||
<a href="<%= weblog.url %>"><%= weblog.title %></a>
|
||||
</span>
|
||||
<span class="tags">
|
||||
<% weblog.tags.map{|t| t.downcase }.sort.each do |tag| %>
|
||||
<a href="<%= main_root_url %>t/<%= tag %>" class="tag"><%= tag %></a>
|
||||
<% end %>
|
||||
</span>
|
||||
<span class="domain">
|
||||
<a href="<%= weblog.site_url %>"><%= weblog.site_title %></a>
|
||||
</span>
|
||||
<div class="byline">
|
||||
by <a href="<%= main_root_url %>u/<%= weblog.user.username %>"><%=
|
||||
weblog.user.username %></a>
|
||||
<%= raw(time_ago_in_words_label(weblog.created_at).
|
||||
gsub(/^about /, "")) %> ago
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="story_content weblog_content shorten_first_p">
|
||||
<%= weblog.sanitized_content %>
|
||||
</div>
|
||||
</li>
|
||||
<% end %>
|
||||
</ol>
|
||||
|
||||
<div class="morelink">
|
||||
<% if @page && @page > 1 %>
|
||||
<a href="/<%= @page == 2 ? "" : "page/#{@page - 1}" %>"><< Page
|
||||
<%= @page - 1 %></a>
|
||||
<% end %>
|
||||
|
||||
<% if @show_more %>
|
||||
<% if @page && @page > 1 %>
|
||||
|
|
||||
<% end %>
|
||||
<a href="/page/<%= @page + 1 %>">Page <%= @page + 1 %> >></a>
|
||||
<% end %>
|
||||
</div>
|
192
config/routes.rb
192
config/routes.rb
|
@ -1,111 +1,125 @@
|
|||
Lobsters::Application.routes.draw do
|
||||
scope :format => "html" do
|
||||
root :to => "home#index",
|
||||
constraints(:subdomain => "planet") do
|
||||
root :to => "weblogs#index",
|
||||
:subdomain => "planet",
|
||||
:as => "weblogs_root",
|
||||
:protocol => (Rails.env == "production" ? "https://" : "http://")
|
||||
|
||||
get "/rss" => "home#index", :format => "rss"
|
||||
get "/hottest" => "home#index", :format => "json"
|
||||
get "/page/:page" => "weblogs#index"
|
||||
end
|
||||
|
||||
get "/page/:page" => "home#index"
|
||||
constraints do
|
||||
scope :format => "html" do
|
||||
root :to => "home#index",
|
||||
:protocol => (Rails.env == "production" ? "https://" : "http://"),
|
||||
:as => "root"
|
||||
|
||||
get "/newest" => "home#newest", :format => /html|json|rss/
|
||||
get "/newest/page/:page" => "home#newest"
|
||||
get "/newest/:user" => "home#newest_by_user"
|
||||
get "/newest/:user/page/:page" => "home#newest_by_user"
|
||||
get "/recent" => "home#recent"
|
||||
get "/recent/page/:page" => "home#recent"
|
||||
get "/hidden" => "home#hidden"
|
||||
get "/hidden/page/:page" => "home#hidden"
|
||||
get "/rss" => "home#index", :format => "rss"
|
||||
get "/hottest" => "home#index", :format => "json"
|
||||
|
||||
get "/top" => "home#top"
|
||||
get "/top/page/:page" => "home#top"
|
||||
get "/top/:length" => "home#top"
|
||||
get "/top/:length/page/:page" => "home#top"
|
||||
get "/page/:page" => "home#index"
|
||||
|
||||
get "/threads" => "comments#threads"
|
||||
get "/threads/:user" => "comments#threads"
|
||||
get "/newest" => "home#newest", :format => /html|json|rss/
|
||||
get "/newest/page/:page" => "home#newest"
|
||||
get "/newest/:user" => "home#newest_by_user"
|
||||
get "/newest/:user/page/:page" => "home#newest_by_user"
|
||||
get "/recent" => "home#recent"
|
||||
get "/recent/page/:page" => "home#recent"
|
||||
get "/hidden" => "home#hidden"
|
||||
get "/hidden/page/:page" => "home#hidden"
|
||||
|
||||
get "/login" => "login#index"
|
||||
post "/login" => "login#login"
|
||||
post "/logout" => "login#logout"
|
||||
get "/top" => "home#top"
|
||||
get "/top/page/:page" => "home#top"
|
||||
get "/top/:length" => "home#top"
|
||||
get "/top/:length/page/:page" => "home#top"
|
||||
|
||||
get "/signup" => "signup#index"
|
||||
post "/signup" => "signup#signup"
|
||||
get "/signup/invite" => "signup#invite"
|
||||
get "/threads" => "comments#threads"
|
||||
get "/threads/:user" => "comments#threads"
|
||||
|
||||
get "/login/forgot_password" => "login#forgot_password",
|
||||
:as => "forgot_password"
|
||||
post "/login/reset_password" => "login#reset_password",
|
||||
:as => "reset_password"
|
||||
match "/login/set_new_password" => "login#set_new_password",
|
||||
:as => "set_new_password", :via => [:get, :post]
|
||||
get "/login" => "login#index"
|
||||
post "/login" => "login#login"
|
||||
post "/logout" => "login#logout"
|
||||
|
||||
get "/t/:tag" => "home#tagged", :as => "tag", :format => /html|rss/
|
||||
get "/t/:tag/page/:page" => "home#tagged"
|
||||
get "/signup" => "signup#index"
|
||||
post "/signup" => "signup#signup"
|
||||
get "/signup/invite" => "signup#invite"
|
||||
|
||||
get "/search" => "search#index"
|
||||
get "/login/forgot_password" => "login#forgot_password",
|
||||
:as => "forgot_password"
|
||||
post "/login/reset_password" => "login#reset_password",
|
||||
:as => "reset_password"
|
||||
match "/login/set_new_password" => "login#set_new_password",
|
||||
:as => "set_new_password", :via => [:get, :post]
|
||||
|
||||
resources :stories do
|
||||
post "upvote"
|
||||
post "downvote"
|
||||
post "unvote"
|
||||
post "undelete"
|
||||
post "hide"
|
||||
post "unhide"
|
||||
end
|
||||
post "/stories/fetch_url_title", :format => "json"
|
||||
post "/stories/preview" => "stories#preview"
|
||||
get "/t/:tag" => "home#tagged", :as => "tag", :format => /html|rss/
|
||||
get "/t/:tag/page/:page" => "home#tagged"
|
||||
|
||||
resources :comments do
|
||||
member do
|
||||
get "reply"
|
||||
get "/search" => "search#index"
|
||||
|
||||
resources :stories do
|
||||
post "upvote"
|
||||
post "downvote"
|
||||
post "unvote"
|
||||
|
||||
post "delete"
|
||||
post "undelete"
|
||||
post "hide"
|
||||
post "unhide"
|
||||
end
|
||||
post "/stories/fetch_url_title", :format => "json"
|
||||
post "/stories/preview" => "stories#preview"
|
||||
|
||||
resources :comments do
|
||||
member do
|
||||
get "reply"
|
||||
post "upvote"
|
||||
post "downvote"
|
||||
post "unvote"
|
||||
|
||||
post "delete"
|
||||
post "undelete"
|
||||
end
|
||||
end
|
||||
get "/comments/page/:page" => "comments#index"
|
||||
|
||||
get "/messages/sent" => "messages#sent"
|
||||
post "/messages/batch_delete" => "messages#batch_delete",
|
||||
:as => "batch_delete_messages"
|
||||
resources :messages do
|
||||
post "keep_as_new"
|
||||
end
|
||||
|
||||
get "/s/:id/:title/comments/:comment_short_id" => "stories#show"
|
||||
get "/s/:id/(:title)" => "stories#show", :format => /html|json/
|
||||
|
||||
get "/u" => "users#tree"
|
||||
get "/u/:username" => "users#show", :as => "user"
|
||||
|
||||
get "/settings" => "settings#index"
|
||||
post "/settings" => "settings#update"
|
||||
post "/settings/delete_account" => "settings#delete_account",
|
||||
:as => "delete_account"
|
||||
|
||||
get "/filters" => "filters#index"
|
||||
post "/filters" => "filters#update"
|
||||
|
||||
post "/invitations" => "invitations#create"
|
||||
get "/invitations" => "invitations#index"
|
||||
get "/invitations/request" => "invitations#build"
|
||||
post "/invitations/create_by_request" => "invitations#create_by_request",
|
||||
:as => "create_invitation_by_request"
|
||||
get "/invitations/confirm/:code" => "invitations#confirm_email"
|
||||
post "/invitations/send_for_request" => "invitations#send_for_request",
|
||||
:as => "send_invitation_for_request"
|
||||
get "/invitations/:invitation_code" => "signup#invited"
|
||||
post "/invitations/delete_request" => "invitations#delete_request",
|
||||
:as => "delete_invitation_request"
|
||||
|
||||
get "/moderations" => "moderations#index"
|
||||
get "/moderations/page/:page" => "moderations#index"
|
||||
|
||||
get "/privacy" => "home#privacy"
|
||||
get "/about" => "home#about"
|
||||
|
||||
get "/resettraffic" => "home#resettraffic"
|
||||
end
|
||||
get "/comments/page/:page" => "comments#index"
|
||||
|
||||
get "/messages/sent" => "messages#sent"
|
||||
post "/messages/batch_delete" => "messages#batch_delete",
|
||||
:as => "batch_delete_messages"
|
||||
resources :messages do
|
||||
post "keep_as_new"
|
||||
end
|
||||
|
||||
get "/s/:id/:title/comments/:comment_short_id" => "stories#show"
|
||||
get "/s/:id/(:title)" => "stories#show", :format => /html|json/
|
||||
|
||||
get "/u" => "users#tree"
|
||||
get "/u/:username" => "users#show", :as => "user"
|
||||
|
||||
get "/settings" => "settings#index"
|
||||
post "/settings" => "settings#update"
|
||||
post "/settings/delete_account" => "settings#delete_account",
|
||||
:as => "delete_account"
|
||||
|
||||
get "/filters" => "filters#index"
|
||||
post "/filters" => "filters#update"
|
||||
|
||||
post "/invitations" => "invitations#create"
|
||||
get "/invitations" => "invitations#index"
|
||||
get "/invitations/request" => "invitations#build"
|
||||
post "/invitations/create_by_request" => "invitations#create_by_request",
|
||||
:as => "create_invitation_by_request"
|
||||
get "/invitations/confirm/:code" => "invitations#confirm_email"
|
||||
post "/invitations/send_for_request" => "invitations#send_for_request",
|
||||
:as => "send_invitation_for_request"
|
||||
get "/invitations/:invitation_code" => "signup#invited"
|
||||
post "/invitations/delete_request" => "invitations#delete_request",
|
||||
:as => "delete_invitation_request"
|
||||
|
||||
get "/moderations" => "moderations#index"
|
||||
get "/moderations/page/:page" => "moderations#index"
|
||||
|
||||
get "/privacy" => "home#privacy"
|
||||
get "/about" => "home#about"
|
||||
end
|
||||
end
|
||||
|
|
5
db/migrate/20140701153554_add_user_weblog_url.rb
Normal file
5
db/migrate/20140701153554_add_user_weblog_url.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddUserWeblogUrl < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :users, :weblog_feed_url, :string, :length => 500
|
||||
end
|
||||
end
|
21
db/migrate/20140804005415_add_weblogs.rb
Normal file
21
db/migrate/20140804005415_add_weblogs.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
class AddWeblogs < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :weblogs do |t|
|
||||
t.timestamps
|
||||
t.integer :user_id
|
||||
t.string :title, :limit => 512
|
||||
t.string :url, :limit => 512
|
||||
t.string :site_title, :limit => 512
|
||||
t.string :site_url, :limit => 512
|
||||
t.text :content, :limit => 16777215 # mediumtext
|
||||
t.text :tags
|
||||
t.string :uuid
|
||||
end
|
||||
|
||||
# why can't the charset be specified in the create_table?
|
||||
execute("ALTER TABLE weblogs MODIFY `uuid` varchar(200) CHARACTER SET utf8")
|
||||
|
||||
add_index "weblogs", ["user_id", "uuid"], :name => "user_and_uuid",
|
||||
:unique => true
|
||||
end
|
||||
end
|
18
db/schema.rb
18
db/schema.rb
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20140408160306) do
|
||||
ActiveRecord::Schema.define(version: 20140804005415) do
|
||||
|
||||
create_table "comments", force: true do |t|
|
||||
t.datetime "created_at", null: false
|
||||
|
@ -167,6 +167,7 @@ ActiveRecord::Schema.define(version: 20140408160306) do
|
|||
t.string "banned_reason", limit: 200
|
||||
t.datetime "deleted_at"
|
||||
t.string "pushover_sound"
|
||||
t.string "weblog_feed_url"
|
||||
end
|
||||
|
||||
add_index "users", ["mailing_list_mode"], name: "mailing_list_enabled", using: :btree
|
||||
|
@ -187,4 +188,19 @@ ActiveRecord::Schema.define(version: 20140408160306) do
|
|||
add_index "votes", ["user_id", "comment_id"], name: "user_id_comment_id", using: :btree
|
||||
add_index "votes", ["user_id", "story_id"], name: "user_id_story_id", using: :btree
|
||||
|
||||
create_table "weblogs", force: true do |t|
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "user_id"
|
||||
t.string "title", limit: 512
|
||||
t.string "url", limit: 512
|
||||
t.string "site_title", limit: 512
|
||||
t.string "site_url", limit: 512
|
||||
t.text "content", limit: 16777215
|
||||
t.text "tags"
|
||||
t.string "uuid", limit: 200
|
||||
end
|
||||
|
||||
add_index "weblogs", ["user_id", "uuid"], name: "user_and_uuid", unique: true, using: :btree
|
||||
|
||||
end
|
||||
|
|
58
script/update_weblogs
Executable file
58
script/update_weblogs
Executable file
|
@ -0,0 +1,58 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
ENV["RAILS_ENV"] ||= "production"
|
||||
|
||||
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
||||
require File.expand_path('../../config/boot', __FILE__)
|
||||
require APP_PATH
|
||||
Rails.application.require_environment!
|
||||
|
||||
require "feed-normalizer"
|
||||
|
||||
User.where("weblog_feed_url <> ''").each do |u|
|
||||
begin
|
||||
s = Sponge.new
|
||||
data = s.fetch(u.weblog_feed_url, :get, nil, nil, {
|
||||
"User-Agent" => "Mozilla/5.0 (compatible; Planet Lobsters; " <<
|
||||
"https://#{Rails.application.domain}/)" })
|
||||
if !data
|
||||
raise "no data returned"
|
||||
end
|
||||
|
||||
feed = FeedNormalizer::FeedNormalizer.parse(data)
|
||||
if !feed
|
||||
raise "could not parse feed"
|
||||
end
|
||||
rescue => e
|
||||
puts "error updating user #{u.id} from #{u.weblog_feed_url}: #{e}"
|
||||
# TODO: send the user a private message on failure, probably limit to every
|
||||
# x tries/days
|
||||
next
|
||||
end
|
||||
|
||||
feed.entries.each do |e|
|
||||
w = u.weblogs.where(:uuid => e.id).first
|
||||
if !w
|
||||
w = u.weblogs.build(:uuid => e.id)
|
||||
end
|
||||
|
||||
# prevent entries with bogus or future times from dominating the front page
|
||||
if e.last_updated > Time.now
|
||||
puts "skipping future entry #{e.id} with time #{e.last_updated}"
|
||||
next
|
||||
end
|
||||
|
||||
# TODO: compare these manually, AR seems to always mark them dirty even if
|
||||
# the content is the same
|
||||
w.created_at = e.last_updated
|
||||
w.url = e.url
|
||||
w.title = e.title
|
||||
w.content = e.content
|
||||
w.tags = e.categories
|
||||
|
||||
w.site_url = feed.url
|
||||
w.site_title = feed.title
|
||||
|
||||
w.save
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user