feeds/app/models/site_feed.rb

189 lines
6.9 KiB
Ruby

class SiteFeed
include Mongoid::Document
include Mongoid::Timestamps
ModuleAppSyncFields = ["feeds_model", "feeds_uid_field", "feeds_update_callback", "feeds_time_field", "feeds_finish_callback", "feeds_update_statuses_callback"]
field :remote_site_url
field :merge_with_category
field :channel_name
field :channel_title, :localize => true
field :channel_key
field :feed_name, localize: true
field :disabled, type: Boolean, default: false
field :feed_url
field :feed_uid
field :feeds_model
field :feeds_uid_field
field :feeds_update_callback
field :feeds_time_field, type: String, default: "postdate"
field :feeds_finish_callback
field :feeds_update_statuses_callback
field :enable_notify, type: Boolean, default: false
require 'feed_model/cache'
require 'fileutils'
include FeedModel::Cache
Category.send(:include,FeedModel::Cache)
after_create do
self.add_notify
crontab_list = `crontab -l`.split("\n") rescue []
site_root = Rails.root.to_s
if crontab_list.select{|s| s.include?(site_root) && s.include?("feeds_module:make_cache")} == []
`(crontab -l ; echo "*/5 * * * * /bin/bash -l -c 'cd #{site_root} && bundle exec rake feeds_module:make_cache > /dev/null'") | crontab`
end
end
before_destroy do
self.remove_notify
tmp = SiteFeedAnnc.where(feed_id: self.id)
main_directory = File.join("#{Rails.root}","public","site_feeds")
feed_directory = File.join(main_directory.to_s, self.id.to_s)
FileUtils.rm_rf(feed_directory.to_s)
if tmp.count!=0
tmp.destroy
end
end
after_save do
if @skip_callback
unless @skip_fix_data
update_url = self.remote_site_url_changed?
if self.channel_title_changed?
self.update_channel_title(update_url)
elsif update_url
self.update_remote_site_url
end
end
else
self.sync_data_to_annc
end
@site_feed_annc = nil
end
scope :enabled, ->{where(:disabled => false)}
def site_feed_annc
@site_feed_annc ||= SiteFeedAnnc.where(:feed_id=>self.id).first
end
def update_channel_title(update_url=false) #update_url=true will also fix remote_site_url in data
site_feed_annc.update_channel_title(update_url) if site_feed_annc
end
def update_remote_site_url
site_feed_annc.update_remote_site_url if site_feed_annc
end
def sync_data_to_annc(site_feed_annc=nil)
category_title = self.category[:title] rescue {}
tmp_channel_title = self.channel_title_for_cache
clone_fields =["channel_key", "merge_with_category", "remote_site_url", "feeds_model", "feeds_uid_field", "feeds_update_callback", "feeds_time_field", "feeds_update_statuses_callback"]
(site_feed_annc ? [site_feed_annc] : SiteFeedAnnc.where(:feed_id=>self.id)).each do |tmp|
clone_fields.each do |f|
tmp.send("#{f}=", self.send(f))
end
tmp[:feed_name] = self[:feed_name]
tmp.category_title = category_title
tmp.channel_title = tmp_channel_title
tmp.save
end
end
def get_annc(force_refresh=false)
main_directory = File.join("#{Rails.root}","public","site_feeds")
feed_directory = File.join(main_directory.to_s, self.id.to_s)
if !force_refresh && File.exists?(feed_directory)
anns = JSON.parse(File.read(File.join(feed_directory.to_s, self.feed_uid + ".json")))[self.channel_key.pluralize] rescue []
else
uri = URI(self.feed_url)
res = get_response_body(uri) rescue ''
FileUtils.mkdir_p(feed_directory) if !File.exists?(feed_directory)
File.open(File.join(feed_directory.to_s,self.feed_uid + ".json"),"w") do |file|
res.force_encoding("utf-8")
file.write(res)
end
anns = JSON.parse(res)[self.channel_key.pluralize] rescue []
end
anns
end
def get_response_body(uri)
res = Net::HTTP.start(uri.host, uri.port,
:use_ssl => uri.scheme == 'https',
open_timeout: 60,read_timeout: 60,
verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http|
req = Net::HTTP::Get.new(uri)
http.request(req)
end
if res.code == "302" || res.code == "301"
location = res['Location']
cookie = res['Set-Cookie']
if location[0] == "/"
uri = URI.parse("#{uri.scheme}://#{uri.host}#{location}")
else
uri = URI.parse(location)
end
res = Net::HTTP.start(uri.host, uri.port,
:use_ssl => uri.scheme == 'https',
open_timeout: 60,read_timeout: 60,
verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http|
req = Net::HTTP::Get.new(uri)
req['Cookie'] = cookie
http.request(req)
end
return res.body
else
return res.body
end
end
def category
Category.find(self.merge_with_category) rescue nil
end
def channel_title_for_cache
!self[:channel_title].to_s.empty? ? self[:channel_title] : I18n.t("feed.source")
end
def http_request(http, request)
response = http.request(request)
if response.code.to_i == 301 || response.code.to_i == 302
location = response["location"]
new_uri = URI(location)
http = Net::HTTP.new(new_uri.host, new_uri.port)
if location.include?('https')
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
request.instance_variable_set(:@path, new_uri.path)
response = http_request(http, request)
end
response
end
def add_notify
unless self.enable_notify
root_url = Site.first.root_url rescue ""
if root_url.present?
uri = URI(self.remote_site_url)
http_req = Net::HTTP.new(uri.host, uri.port)
if self.remote_site_url.include?('https')
http_req.use_ssl = true
http_req.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
http_req.open_timeout = 10
request = Net::HTTP::Post.new("/xhr/#{self.channel_key.pluralize}/feed_add_remote/#{self.feed_uid}", 'Content-Type' => 'application/json')
request.body = {"url"=>root_url}.to_json
response = http_request( http_req , request )
if response.code.to_i == 200
self.update(:enable_notify=>true)
end
end
end
end
def remove_notify
if self.enable_notify
root_url = Site.first.root_url rescue ""
if root_url.present?
uri = URI(self.remote_site_url)
http_req = Net::HTTP.new(uri.host, uri.port)
if self.remote_site_url.include?('https')
http_req.use_ssl = true
http_req.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
http_req.open_timeout = 10
request = Net::HTTP::Post.new("/xhr/#{self.channel_key.pluralize}/feed_remove_remote/#{self.feed_uid}", 'Content-Type' => 'application/json')
request.body = {"url"=>root_url}.to_json
response = http_request( http_req , request )
if response.code.to_i == 200
self.update(:enable_notify=>false)
end
end
end
end
end