forked from premiere/premiere-libtorrent
parent
8848d467da
commit
f0d95f5e3e
|
@ -66,7 +66,6 @@ set(sources
|
|||
request_blocks
|
||||
resolve_links
|
||||
resolver
|
||||
rss
|
||||
session
|
||||
session_call
|
||||
session_handle
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
* removed RSS support
|
||||
* removed feature to resolve country for peers
|
||||
* added support for BEP 32, "IPv6 extension for DHT"
|
||||
* overhauled listen socket and UDP socket handling, improving multi-home
|
||||
|
|
1
Jamfile
1
Jamfile
|
@ -614,7 +614,6 @@ SOURCES =
|
|||
read_resume_data
|
||||
receive_buffer
|
||||
resolve_links
|
||||
rss
|
||||
session
|
||||
session_handle
|
||||
session_impl
|
||||
|
|
|
@ -3,7 +3,6 @@ EXTRA_DIST = \
|
|||
Jamfile \
|
||||
setup.py \
|
||||
client.py \
|
||||
rss_reader.py \
|
||||
simple_client.py \
|
||||
make_torrent.py \
|
||||
src/alert.cpp \
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import libtorrent as lt
|
||||
import time
|
||||
|
||||
if len(sys.argv) != 2:
|
||||
print('usage: rss_reader.py rss-feed-url')
|
||||
sys.exit(1)
|
||||
|
||||
ses = lt.session()
|
||||
|
||||
h = ses.add_feed({'url': sys.argv[1], 'auto_download': False})
|
||||
f = h.get_feed_status()
|
||||
spinner = ['|', '/', '-', '\\']
|
||||
i = 0
|
||||
while f['updating']:
|
||||
time.sleep(0.1)
|
||||
i = (i + 1) % 4
|
||||
print('\b%s' % spinner[i]),
|
||||
sys.stdout.flush()
|
||||
f = h.get_feed_status()
|
||||
|
||||
print('\n\nFEED: %s' % f['url'])
|
||||
if len(f['error']) > 0:
|
||||
print('ERROR: %s' % f['error'])
|
||||
|
||||
print(' %s\n %s\n' % (f['title'], f['description']))
|
||||
print(' ttl: %d minutes' % f['ttl'])
|
||||
|
||||
for item in f['items']:
|
||||
print('\n%s\n------------------------------------------------------' % item['title'])
|
||||
print(' url: %s\n size: %d\n uuid: %s\n description: %s' % (item['url'], item['size'], item['uuid'], item['description']))
|
||||
print(' comment: %s\n category: %s' % (item['comment'], item['category']))
|
||||
|
|
@ -71,7 +71,6 @@ dict get_params(add_torrent_alert const& alert)
|
|||
ret["trackerid"] = p.trackerid;
|
||||
ret["url"] = p.url;
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
ret["source_feed_url"] = p.source_feed_url;
|
||||
ret["uuid"] = p.uuid;
|
||||
#endif
|
||||
return ret;
|
||||
|
|
|
@ -65,7 +65,6 @@ namespace {
|
|||
ret["url"] = p.url;
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
ret["uuid"] = p.uuid;
|
||||
ret["source_feed_url"] = p.source_feed_url;
|
||||
#endif
|
||||
ret["flags"] = p.flags;
|
||||
return ret;
|
||||
|
|
|
@ -257,8 +257,6 @@ namespace
|
|||
if (params.has_key("url"))
|
||||
p.url = extract<std::string>(params["url"]);
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
if (params.has_key("source_feed_url"))
|
||||
p.source_feed_url = extract<std::string>(params["source_feed_url"]);
|
||||
if (params.has_key("uuid"))
|
||||
p.uuid = extract<std::string>(params["uuid"]);
|
||||
#endif
|
||||
|
@ -302,87 +300,6 @@ namespace
|
|||
}
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
void dict_to_feed_settings(dict params, feed_settings& feed)
|
||||
{
|
||||
if (params.has_key("auto_download"))
|
||||
feed.auto_download = extract<bool>(params["auto_download"]);
|
||||
if (params.has_key("default_ttl"))
|
||||
feed.default_ttl = extract<int>(params["default_ttl"]);
|
||||
if (params.has_key("url"))
|
||||
feed.url = extract<std::string>(params["url"]);
|
||||
if (params.has_key("add_args"))
|
||||
dict_to_add_torrent_params(dict(params["add_args"]), feed.add_args);
|
||||
}
|
||||
|
||||
feed_handle add_feed(lt::session& s, dict params)
|
||||
{
|
||||
feed_settings feed;
|
||||
// this static here is a bit of a hack. It will
|
||||
// probably work for the most part
|
||||
dict_to_feed_settings(params, feed);
|
||||
|
||||
allow_threading_guard guard;
|
||||
return s.add_feed(feed);
|
||||
}
|
||||
|
||||
dict get_feed_status(feed_handle const& h)
|
||||
{
|
||||
feed_status s;
|
||||
{
|
||||
allow_threading_guard guard;
|
||||
s = h.get_feed_status();
|
||||
}
|
||||
dict ret;
|
||||
ret["url"] = s.url;
|
||||
ret["title"] = s.title;
|
||||
ret["description"] = s.description;
|
||||
ret["last_update"] = s.last_update;
|
||||
ret["next_update"] = s.next_update;
|
||||
ret["updating"] = s.updating;
|
||||
ret["error"] = s.error ? s.error.message() : "";
|
||||
ret["ttl"] = s.ttl;
|
||||
|
||||
list items;
|
||||
for (std::vector<feed_item>::iterator i = s.items.begin()
|
||||
, end(s.items.end()); i != end; ++i)
|
||||
{
|
||||
dict item;
|
||||
item["url"] = i->url;
|
||||
item["uuid"] = i->uuid;
|
||||
item["title"] = i->title;
|
||||
item["description"] = i->description;
|
||||
item["comment"] = i->comment;
|
||||
item["category"] = i->category;
|
||||
item["size"] = i->size;
|
||||
item["handle"] = i->handle;
|
||||
item["info_hash"] = i->info_hash.to_string();
|
||||
items.append(item);
|
||||
}
|
||||
ret["items"] = items;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void set_feed_settings(feed_handle& h, dict sett)
|
||||
{
|
||||
feed_settings feed;
|
||||
dict_to_feed_settings(sett, feed);
|
||||
h.set_settings(feed);
|
||||
}
|
||||
|
||||
dict get_feed_settings(feed_handle& h)
|
||||
{
|
||||
feed_settings s;
|
||||
{
|
||||
allow_threading_guard guard;
|
||||
s = h.settings();
|
||||
}
|
||||
dict ret;
|
||||
ret["url"] = s.url;
|
||||
ret["auto_download"] = s.auto_download;
|
||||
ret["default_ttl"] = s.default_ttl;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void start_natpmp(lt::session& s)
|
||||
{
|
||||
allow_threading_guard guard;
|
||||
|
@ -727,7 +644,6 @@ void bind_session()
|
|||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
.def_readwrite("uuid", &add_torrent_params::uuid)
|
||||
.def_readwrite("source_feed_url", &add_torrent_params::source_feed_url)
|
||||
.def_readwrite("resume_data", &add_torrent_params::resume_data)
|
||||
#endif
|
||||
;
|
||||
|
@ -860,7 +776,6 @@ void bind_session()
|
|||
#endif // BOOST_NO_EXCEPTIONS
|
||||
.def("remove_torrent", allow_threads(<::session::remove_torrent), arg("option") = 0)
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
.def("add_feed", &add_feed)
|
||||
.def("status", allow_threads(<::session::status))
|
||||
.def("settings", <::session::settings)
|
||||
.def("set_settings", &session_set_settings)
|
||||
|
@ -978,13 +893,6 @@ void bind_session()
|
|||
.value("listen_reuse_address", lt::session::listen_reuse_address)
|
||||
.value("listen_no_system_port", lt::session::listen_no_system_port)
|
||||
;
|
||||
|
||||
class_<feed_handle>("feed_handle")
|
||||
.def("update_feed", &feed_handle::update_feed)
|
||||
.def("get_feed_status", &get_feed_status)
|
||||
.def("set_settings", &set_feed_settings)
|
||||
.def("settings", &get_feed_settings)
|
||||
;
|
||||
#endif
|
||||
|
||||
typedef void (*mem_preset2)(settings_pack& s);
|
||||
|
|
|
@ -107,7 +107,6 @@ nobase_include_HEADERS = \
|
|||
resolver.hpp \
|
||||
resolver_interface.hpp \
|
||||
request_blocks.hpp \
|
||||
rss.hpp \
|
||||
session.hpp \
|
||||
session_handle.hpp \
|
||||
session_settings.hpp \
|
||||
|
|
|
@ -483,10 +483,6 @@ namespace libtorrent
|
|||
// items which has UUIDs specified.
|
||||
std::string uuid;
|
||||
|
||||
// should point to the URL of the RSS feed this torrent comes from, if it
|
||||
// comes from an RSS feed.
|
||||
std::string source_feed_url;
|
||||
|
||||
// The optional parameter, ``resume_data`` can be given if up to date
|
||||
// fast-resume data is available. The fast-resume data can be acquired
|
||||
// from a running torrent by calling save_resume_data() on
|
||||
|
|
|
@ -46,10 +46,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/entry.hpp"
|
||||
#include "libtorrent/peer_request.hpp"
|
||||
#include "libtorrent/performance_counters.hpp"
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
#include "libtorrent/rss.hpp" // for feed_handle
|
||||
#endif
|
||||
#include "libtorrent/operations.hpp" // for operation_t enum
|
||||
#include "libtorrent/close_reason.hpp"
|
||||
#include "libtorrent/aux_/escape_string.hpp" // for convert_from_native
|
||||
|
@ -1702,54 +1698,6 @@ namespace libtorrent
|
|||
virtual std::string message() const TORRENT_OVERRIDE;
|
||||
};
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
// This alert is posted on RSS feed events such as start of RSS feed updates,
|
||||
// successful completed updates and errors during updates.
|
||||
//
|
||||
// This alert is only posted if the ``rss_notifications`` category is enabled
|
||||
// in the alert_mask.
|
||||
struct TORRENT_DEPRECATED TORRENT_EXPORT rss_alert TORRENT_FINAL : alert
|
||||
{
|
||||
// internal
|
||||
rss_alert(aux::stack_allocator& alloc, feed_handle h
|
||||
, std::string const& u, int s, error_code const& ec);
|
||||
|
||||
TORRENT_DEFINE_ALERT(rss_alert, 63)
|
||||
|
||||
static const int static_category = alert::rss_notification;
|
||||
virtual std::string message() const TORRENT_OVERRIDE;
|
||||
|
||||
enum state_t
|
||||
{
|
||||
// An update of this feed was just initiated, it will either succeed
|
||||
// or fail soon.
|
||||
state_updating,
|
||||
|
||||
// The feed just completed a successful update, there may be new items
|
||||
// in it. If you're adding torrents manually, you may want to request
|
||||
// the feed status of the feed and look through the ``items`` vector.
|
||||
state_updated,
|
||||
|
||||
// An error just occurred. See the ``error`` field for information on
|
||||
// what went wrong.
|
||||
state_error
|
||||
};
|
||||
|
||||
// the handle to the feed which generated this alert.
|
||||
feed_handle handle;
|
||||
|
||||
// a short cut to access the url of the feed, without
|
||||
// having to call feed_handle::get_settings().
|
||||
std::string url;
|
||||
|
||||
// one of the values from rss_alert::state_t.
|
||||
int state;
|
||||
|
||||
// an error code used for when an error occurs on the feed.
|
||||
error_code error;
|
||||
};
|
||||
#endif // TORRENT_NO_DEPRECATE
|
||||
|
||||
// This is posted whenever a torrent is transitioned into the error state.
|
||||
struct TORRENT_EXPORT torrent_error_alert TORRENT_FINAL : torrent_alert
|
||||
{
|
||||
|
@ -1938,26 +1886,6 @@ namespace libtorrent
|
|||
sha1_hash old_ih;
|
||||
sha1_hash new_ih;
|
||||
};
|
||||
|
||||
// This alert is posted every time a new RSS item (i.e. torrent) is received
|
||||
// from an RSS feed.
|
||||
//
|
||||
// It is only posted if the ``rss_notifications`` category is enabled in the
|
||||
// alert_mask.
|
||||
struct TORRENT_EXPORT rss_item_alert TORRENT_FINAL : alert
|
||||
{
|
||||
// internal
|
||||
rss_item_alert(aux::stack_allocator& alloc, feed_handle h
|
||||
, feed_item const& item);
|
||||
|
||||
TORRENT_DEFINE_ALERT(rss_item_alert, 72)
|
||||
|
||||
static const int static_category = alert::rss_notification;
|
||||
virtual std::string message() const TORRENT_OVERRIDE;
|
||||
|
||||
feed_handle handle;
|
||||
feed_item item;
|
||||
};
|
||||
#endif
|
||||
|
||||
// posted when something fails in the DHT. This is not necessarily a fatal
|
||||
|
|
|
@ -86,7 +86,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/address.hpp"
|
||||
#include "libtorrent/utp_socket_manager.hpp"
|
||||
#include "libtorrent/bloom_filter.hpp"
|
||||
#include "libtorrent/rss.hpp"
|
||||
#include "libtorrent/peer_class.hpp"
|
||||
#include "libtorrent/disk_io_job.hpp" // block_cache_reference
|
||||
#include "libtorrent/network_thread_pool.hpp"
|
||||
|
@ -268,12 +267,6 @@ namespace libtorrent
|
|||
|
||||
void incoming_connection(boost::shared_ptr<socket_type> const& s);
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
feed_handle add_feed(feed_settings const& feed);
|
||||
void remove_feed(feed_handle h);
|
||||
void get_feeds(std::vector<feed_handle>* f) const;
|
||||
#endif
|
||||
|
||||
boost::weak_ptr<torrent> find_torrent(sha1_hash const& info_hash) const TORRENT_OVERRIDE;
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
//deprecated in 1.2
|
||||
|
@ -656,13 +649,6 @@ namespace libtorrent
|
|||
void inc_boost_connections() TORRENT_OVERRIDE { ++m_boost_connections; }
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
// the time when the next rss feed needs updating
|
||||
time_point m_next_rss_update;
|
||||
|
||||
// update any rss feeds that need updating and
|
||||
// recalculate m_next_rss_update
|
||||
void update_rss_feeds();
|
||||
|
||||
void update_ssl_listen();
|
||||
void update_dht_upload_rate_limit();
|
||||
void update_local_download_rate();
|
||||
|
@ -1238,10 +1224,6 @@ namespace libtorrent
|
|||
// is true if the session is paused
|
||||
bool m_paused;
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
std::vector<boost::shared_ptr<feed> > m_feeds;
|
||||
#endif
|
||||
|
||||
// this is a list of peer connections who have been
|
||||
// corked (i.e. their network socket) and needs to be
|
||||
// uncorked at the end of the burst of events. This is
|
||||
|
|
|
@ -1,290 +0,0 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2010-2016, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_RSS_HPP_INCLUDED
|
||||
#define TORRENT_RSS_HPP_INCLUDED
|
||||
|
||||
#include "libtorrent/torrent_handle.hpp"
|
||||
#include "libtorrent/add_torrent_params.hpp"
|
||||
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <string>
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
namespace libtorrent
|
||||
{
|
||||
namespace aux
|
||||
{ struct session_impl; }
|
||||
|
||||
class session;
|
||||
struct bdecode_node;
|
||||
|
||||
// represents one item from an RSS feed. Specifically
|
||||
// a feed of torrents.
|
||||
//
|
||||
struct TORRENT_EXPORT feed_item
|
||||
{
|
||||
feed_item();
|
||||
#if __cplusplus >= 201103L
|
||||
feed_item(feed_item const&) = default;
|
||||
feed_item & operator=(feed_item const&) = default;
|
||||
#endif
|
||||
~feed_item();
|
||||
|
||||
// these are self explanatory and may be empty if the feed does not specify
|
||||
// those fields.
|
||||
std::string url;
|
||||
std::string uuid;
|
||||
std::string title;
|
||||
std::string description;
|
||||
std::string comment;
|
||||
std::string category;
|
||||
|
||||
// the total size of the content the torrent refers to, or -1
|
||||
// if no size was specified by the feed.
|
||||
boost::int64_t size;
|
||||
|
||||
// the handle to the torrent, if the session is already downloading
|
||||
// this torrent.
|
||||
torrent_handle handle;
|
||||
|
||||
// the info-hash of the torrent, or cleared (i.e. all zeroes) if
|
||||
// the feed does not specify the info-hash.
|
||||
sha1_hash info_hash;
|
||||
};
|
||||
|
||||
// given a feed_item ``f``, add the torrent it refers to to session ``s``.
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
torrent_handle TORRENT_EXPORT add_feed_item(session& s, feed_item const& fi
|
||||
, add_torrent_params const& p);
|
||||
#endif
|
||||
torrent_handle TORRENT_EXPORT add_feed_item(session& s, feed_item const& fi
|
||||
, add_torrent_params const& p, error_code& ec);
|
||||
|
||||
// the feed_settings object is all the information
|
||||
// and configuration for a specific feed. All of
|
||||
// these settings can be changed by the user
|
||||
// after adding the feed
|
||||
struct TORRENT_EXPORT feed_settings
|
||||
{
|
||||
feed_settings()
|
||||
: auto_download(true)
|
||||
, auto_map_handles(true)
|
||||
, default_ttl(30)
|
||||
{}
|
||||
|
||||
std::string url;
|
||||
|
||||
// By default ``auto_download`` is true, which means all torrents in
|
||||
// the feed will be downloaded. Set this to false in order to manually
|
||||
// add torrents to the session. You may react to the rss_alert when
|
||||
// a feed has been updated to poll it for the new items in the feed
|
||||
// when adding torrents manually. When torrents are added automatically,
|
||||
// an add_torrent_alert is posted which includes the torrent handle
|
||||
// as well as the error code if it failed to be added. You may also call
|
||||
// ``session::get_torrents()`` to get the handles to the new torrents.
|
||||
bool auto_download;
|
||||
|
||||
// ``auto_map_handles`` defaults to true and determines whether or
|
||||
// not to set the ``handle`` field in the feed_item, returned
|
||||
// as the feed status. If auto-download is enabled, this setting
|
||||
// is ignored. If auto-download is not set, setting this to false
|
||||
// will save one pass through all the feed items trying to find
|
||||
// corresponding torrents in the session.
|
||||
bool auto_map_handles;
|
||||
|
||||
// The ``default_ttl`` is the default interval for refreshing a feed.
|
||||
// This may be overridden by the feed itself (by specifying the ``<ttl>``
|
||||
// tag) and defaults to 30 minutes. The field specifies the number of
|
||||
// minutes between refreshes.
|
||||
int default_ttl;
|
||||
|
||||
// If torrents are added automatically, you may want to set the
|
||||
// ``add_args`` to appropriate values for download directory etc.
|
||||
// This object is used as a template for adding torrents from feeds,
|
||||
// but some torrent specific fields will be overridden by the
|
||||
// individual torrent being added. For more information on the
|
||||
// add_torrent_params, see async_add_torrent() and add_torrent().
|
||||
add_torrent_params add_args;
|
||||
};
|
||||
|
||||
// holds information about the status of an RSS feed. Retrieved by
|
||||
// calling get_feed_status() on feed_handle.
|
||||
struct TORRENT_EXPORT feed_status
|
||||
{
|
||||
feed_status(): last_update(0), next_update(0)
|
||||
, updating(false), ttl(0) {}
|
||||
|
||||
// the URL of the feed.
|
||||
std::string url;
|
||||
|
||||
// the name of the feed (as specified by the feed itself). This
|
||||
// may be empty if we have not recevied a response from the RSS server yet,
|
||||
// or if the feed does not specify a title.
|
||||
std::string title;
|
||||
|
||||
// the feed description (as specified by the feed itself).
|
||||
// This may be empty if we have not received a response from the RSS server
|
||||
// yet, or if the feed does not specify a description.
|
||||
std::string description;
|
||||
|
||||
// the posix time of the last successful response from the feed.
|
||||
time_t last_update;
|
||||
|
||||
// the number of seconds, from now, when the feed will be
|
||||
// updated again.
|
||||
int next_update;
|
||||
|
||||
// true if the feed is currently being updated (i.e. waiting for
|
||||
// DNS resolution, connecting to the server or waiting for the response to the
|
||||
// HTTP request, or receiving the response).
|
||||
bool updating;
|
||||
|
||||
// a vector of all items that we have received from the feed. See
|
||||
// feed_item for more information.
|
||||
std::vector<feed_item> items;
|
||||
|
||||
// set to the appropriate error code if the feed encountered an
|
||||
// error. See error_code for more info.
|
||||
error_code error;
|
||||
|
||||
// the current refresh time (in minutes). It's either the configured
|
||||
// default ttl, or the ttl specified by the feed.
|
||||
int ttl;
|
||||
};
|
||||
|
||||
struct feed;
|
||||
|
||||
// The ``feed_handle`` refers to a specific RSS feed that is watched by the session.
|
||||
struct TORRENT_EXPORT feed_handle
|
||||
{
|
||||
feed_handle() {}
|
||||
|
||||
// Forces an update/refresh of the feed. Regular updates of the feed is managed
|
||||
// by libtorrent, be careful to not call this too frequently since it may
|
||||
// overload the RSS server.
|
||||
void update_feed();
|
||||
|
||||
// Queries the RSS feed for information, including all the items in the feed.
|
||||
// see feed_status.
|
||||
feed_status get_feed_status() const;
|
||||
|
||||
// Sets and gets settings for this feed. For more information on the
|
||||
// available settings, see add_feed().
|
||||
void set_settings(feed_settings const& s);
|
||||
feed_settings settings() const;
|
||||
private:
|
||||
friend struct aux::session_impl;
|
||||
friend struct feed;
|
||||
feed_handle(boost::weak_ptr<feed> const& p);
|
||||
boost::weak_ptr<feed> m_feed_ptr;
|
||||
};
|
||||
|
||||
struct feed_state;
|
||||
class http_parser;
|
||||
|
||||
boost::shared_ptr<feed> TORRENT_EXPORT new_feed(aux::session_impl& ses, feed_settings const& sett);
|
||||
|
||||
// this is the internal object holding all state about an
|
||||
// RSS feed. All user interaction with this object
|
||||
// goes through the feed_handle, which makes sure all calls
|
||||
// are posted to the network thread
|
||||
struct TORRENT_EXTRA_EXPORT feed : boost::enable_shared_from_this<feed>
|
||||
{
|
||||
friend void parse_feed(feed_state& f, int token, char const* name, int len
|
||||
, char const* val, int val_len);
|
||||
|
||||
feed(aux::session_impl& ses, feed_settings const& feed);
|
||||
|
||||
void on_feed(error_code const& ec, http_parser const& parser
|
||||
, char const* data, int size);
|
||||
|
||||
int update_feed();
|
||||
|
||||
aux::session_impl& session() const { return m_ses; }
|
||||
|
||||
void set_settings(feed_settings const& s);
|
||||
void get_settings(feed_settings* s) const;
|
||||
void get_feed_status(feed_status* ret) const;
|
||||
|
||||
int next_update(time_t now) const;
|
||||
|
||||
void load_state(bdecode_node const& rd);
|
||||
void save_state(entry& rd) const;
|
||||
|
||||
private:
|
||||
friend struct aux::session_impl;
|
||||
|
||||
// explicitly disallow assignment, to silence msvc warning
|
||||
feed& operator=(feed const&);
|
||||
|
||||
void add_item(feed_item const& item);
|
||||
|
||||
feed_handle my_handle();
|
||||
|
||||
error_code m_error;
|
||||
std::vector<feed_item> m_items;
|
||||
|
||||
// these are all the URLs we've seen in the items list.
|
||||
// it's used to avoid adding duplicate entries to the actual
|
||||
// item vector
|
||||
std::set<std::string> m_urls;
|
||||
|
||||
// these are URLs that have been added to the session
|
||||
// once. If we see them again, and they're not in the
|
||||
// session, don't add them again, since it means they
|
||||
// were removed from the session. It maps URLs to the
|
||||
// posix time when they were added. The timestamp is
|
||||
// used to prune this list by removing the oldest ones
|
||||
// when the size gets too big
|
||||
std::map<std::string, time_t> m_added;
|
||||
|
||||
std::string m_title;
|
||||
std::string m_description;
|
||||
time_t m_last_attempt;
|
||||
time_t m_last_update;
|
||||
// refresh rate of this feed in minutes
|
||||
int m_ttl;
|
||||
// the number of update failures in a row
|
||||
int m_failures;
|
||||
// true while waiting for the server to respond
|
||||
bool m_updating;
|
||||
feed_settings m_settings;
|
||||
|
||||
aux::session_impl& m_ses;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // TORRENT_NO_DEPRECATE
|
||||
|
||||
#endif
|
||||
|
|
@ -54,7 +54,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/thread.hpp"
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
#include "libtorrent/rss.hpp"
|
||||
#include "libtorrent/fingerprint.hpp"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -45,10 +45,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "libtorrent/kademlia/dht_storage.hpp"
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
#include "libtorrent/rss.hpp"
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
struct plugin;
|
||||
|
@ -97,8 +93,6 @@ namespace libtorrent
|
|||
#ifndef TORRENT_NO_DEPRECATE
|
||||
,
|
||||
save_as_map = 0x040,
|
||||
// saves RSS feeds
|
||||
save_feeds = 0x080,
|
||||
save_proxy = 0x008,
|
||||
save_i2p_proxy = 0x010,
|
||||
save_dht_proxy = save_proxy,
|
||||
|
@ -305,28 +299,6 @@ namespace libtorrent
|
|||
void get_cache_info(cache_status* ret, torrent_handle h = torrent_handle(), int flags = 0) const;
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
// This adds an RSS feed to the session. The feed will be refreshed
|
||||
// regularly and optionally add all torrents from the feed, as they
|
||||
// appear.
|
||||
//
|
||||
// Before adding the feed, you must set the ``url`` field to the feed's
|
||||
// url. It may point to an RSS or an atom feed. The returned feed_handle
|
||||
// is a handle which is used to interact with the feed, things like
|
||||
// forcing a refresh or querying for information about the items in the
|
||||
// feed. For more information, see feed_handle.
|
||||
TORRENT_DEPRECATED
|
||||
feed_handle add_feed(feed_settings const& feed);
|
||||
|
||||
// Removes a feed from being watched by the session. When this
|
||||
// call returns, the feed handle is invalid and won't refer
|
||||
// to any feed.
|
||||
TORRENT_DEPRECATED
|
||||
void remove_feed(feed_handle h);
|
||||
|
||||
// Returns a list of all RSS feeds that are being watched by the session.
|
||||
TORRENT_DEPRECATED
|
||||
void get_feeds(std::vector<feed_handle>& f) const;
|
||||
|
||||
// ``start_dht`` starts the dht node and makes the trackerless service
|
||||
// available to torrents.
|
||||
//
|
||||
|
|
|
@ -108,7 +108,6 @@ libtorrent_rasterbar_la_SOURCES = \
|
|||
request_blocks.cpp \
|
||||
resolve_links.cpp \
|
||||
resolver.cpp \
|
||||
rss.cpp \
|
||||
session.cpp \
|
||||
session_call.cpp \
|
||||
session_handle.cpp \
|
||||
|
|
|
@ -1201,22 +1201,6 @@ namespace libtorrent {
|
|||
return "DHT bootstrap complete";
|
||||
}
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
rss_alert::rss_alert(aux::stack_allocator&, feed_handle h
|
||||
, std::string const& u, int s, error_code const& ec)
|
||||
: handle(h), url(u), state(s), error(ec)
|
||||
{}
|
||||
|
||||
std::string rss_alert::message() const
|
||||
{
|
||||
char msg[600];
|
||||
char const* state_msg[] = {"updating", "updated", "error"};
|
||||
snprintf(msg, sizeof(msg), "RSS feed %s: %s (%s)"
|
||||
, url.c_str(), state_msg[state], convert_from_native(error.message()).c_str());
|
||||
return msg;
|
||||
}
|
||||
#endif
|
||||
|
||||
torrent_error_alert::torrent_error_alert(
|
||||
aux::stack_allocator& alloc
|
||||
, torrent_handle const& h
|
||||
|
@ -1423,21 +1407,6 @@ namespace libtorrent {
|
|||
, to_hex(new_ih.to_string()).c_str());
|
||||
return torrent_alert::message() + msg;
|
||||
}
|
||||
|
||||
rss_item_alert::rss_item_alert(aux::stack_allocator&, feed_handle h
|
||||
, feed_item const& i)
|
||||
: handle(h)
|
||||
, item(i)
|
||||
{}
|
||||
|
||||
std::string rss_item_alert::message() const
|
||||
{
|
||||
char msg[500];
|
||||
snprintf(msg, sizeof(msg), "feed [%s] has new RSS item %s"
|
||||
, handle.get_feed_status().title.c_str()
|
||||
, item.title.empty() ? item.url.c_str() : item.title.c_str());
|
||||
return msg;
|
||||
}
|
||||
#endif
|
||||
|
||||
peer_disconnected_alert::peer_disconnected_alert(aux::stack_allocator& alloc
|
||||
|
|
|
@ -150,7 +150,6 @@ namespace libtorrent
|
|||
#ifndef TORRENT_NO_DEPRECATE
|
||||
// deprecated in 1.2
|
||||
ret.uuid = rd.dict_find_string_value("uuid");
|
||||
ret.source_feed_url = rd.dict_find_string_value("feed");
|
||||
#endif
|
||||
|
||||
bdecode_node mapped_files = rd.dict_find_list("mapped_files");
|
||||
|
|
706
src/rss.cpp
706
src/rss.cpp
|
@ -1,706 +0,0 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2010-2016, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "libtorrent/rss.hpp"
|
||||
#include "libtorrent/xml_parse.hpp"
|
||||
#include "libtorrent/http_parser.hpp"
|
||||
#include "libtorrent/http_connection.hpp"
|
||||
#include "libtorrent/aux_/session_impl.hpp"
|
||||
#include "libtorrent/aux_/session_call.hpp"
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/alert_types.hpp" // for rss_alert
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
feed_item::feed_item(): size(-1) {}
|
||||
feed_item::~feed_item() {}
|
||||
|
||||
struct feed_state
|
||||
{
|
||||
feed_state(feed& r)
|
||||
: in_item(false)
|
||||
, num_items(0)
|
||||
, type(none)
|
||||
, ret(r)
|
||||
{}
|
||||
|
||||
bool in_item;
|
||||
int num_items;
|
||||
std::string current_tag;
|
||||
enum feed_type
|
||||
{
|
||||
none, atom, rss2
|
||||
} type;
|
||||
feed_item current_item;
|
||||
feed& ret;
|
||||
|
||||
bool is_item(char const* tag) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case atom: return string_equal_no_case(tag, "entry");
|
||||
case rss2: return string_equal_no_case(tag, "item");
|
||||
case none: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_title(char const* tag) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case atom:
|
||||
case rss2: return string_equal_no_case(tag, "title");
|
||||
case none: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_url(char const* tag) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case atom:
|
||||
case rss2: return string_equal_no_case(tag, "link");
|
||||
case none: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_desc(char const* tag) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case atom: return string_equal_no_case(tag, "summary");
|
||||
case rss2: return string_equal_no_case(tag, "description")
|
||||
|| string_equal_no_case(tag, "media:text");
|
||||
case none: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_uuid(char const* tag) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case atom: return string_equal_no_case(tag, "id");
|
||||
case rss2: return string_equal_no_case(tag, "guid");
|
||||
case none: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_comment(char const* tag) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case atom: return false;
|
||||
case rss2: return string_equal_no_case(tag, "comments");
|
||||
case none: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_category(char const* tag) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case atom: return false;
|
||||
case rss2: return string_equal_no_case(tag, "category");
|
||||
case none: return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool is_size(char const* tag) const
|
||||
{
|
||||
return string_equal_no_case(tag, "size")
|
||||
|| string_equal_no_case(tag, "contentlength");
|
||||
}
|
||||
|
||||
bool is_hash(char const* tag) const
|
||||
{
|
||||
return string_equal_no_case(tag, "hash")
|
||||
|| string_equal_no_case(tag, "media:hash");
|
||||
}
|
||||
|
||||
bool is_ttl(char const* tag) const
|
||||
{
|
||||
return string_equal_no_case(tag, "ttl");
|
||||
}
|
||||
};
|
||||
|
||||
void parse_feed(feed_state& f, int token, char const* name, int name_len
|
||||
, char const* val, int val_len)
|
||||
{
|
||||
switch (token)
|
||||
{
|
||||
case xml_parse_error:
|
||||
f.ret.m_error = errors::parse_failed;
|
||||
return;
|
||||
case xml_start_tag:
|
||||
case xml_empty_tag:
|
||||
{
|
||||
f.current_tag.assign(name, name_len);
|
||||
if (f.type == feed_state::none)
|
||||
{
|
||||
if (string_equal_no_case(f.current_tag.c_str(), "feed"))
|
||||
f.type = feed_state::atom;
|
||||
else if (string_equal_no_case(f.current_tag.c_str(), "rss"))
|
||||
f.type = feed_state::rss2;
|
||||
}
|
||||
if (f.is_item(f.current_tag.c_str())) f.in_item = true;
|
||||
return;
|
||||
}
|
||||
case xml_attribute:
|
||||
{
|
||||
if (!f.in_item) return;
|
||||
std::string str(name, name_len);
|
||||
if (f.is_url(f.current_tag.c_str())
|
||||
&& f.type == feed_state::atom)
|
||||
{
|
||||
// atom feeds have items like this:
|
||||
// <link href="http://..." length="12345"/>
|
||||
if (string_equal_no_case(str.c_str(), "href"))
|
||||
f.current_item.url.assign(val, val_len);
|
||||
else if (string_equal_no_case(str.c_str(), "length"))
|
||||
f.current_item.size = strtoll(val, 0, 10);
|
||||
}
|
||||
else if (f.type == feed_state::rss2
|
||||
&& string_equal_no_case(f.current_tag.c_str(), "enclosure"))
|
||||
{
|
||||
// rss feeds have items like this:
|
||||
// <enclosure url="http://..." length="12345"/>
|
||||
if (string_equal_no_case(str.c_str(), "url"))
|
||||
f.current_item.url.assign(val, val_len);
|
||||
else if (string_equal_no_case(str.c_str(), "length"))
|
||||
f.current_item.size = strtoll(val, 0, 10);
|
||||
}
|
||||
else if (f.type == feed_state::rss2
|
||||
&& string_equal_no_case(f.current_tag.c_str(), "media:content"))
|
||||
{
|
||||
// rss feeds sometimes have items like this:
|
||||
// <media:content url="http://..." filesize="12345"/>
|
||||
if (string_equal_no_case(str.c_str(), "url"))
|
||||
f.current_item.url.assign(val, val_len);
|
||||
else if (string_equal_no_case(str.c_str(), "filesize"))
|
||||
f.current_item.size = strtoll(val, 0, 10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
case xml_end_tag:
|
||||
{
|
||||
if (f.in_item && f.is_item(std::string(name, name_len).c_str()))
|
||||
{
|
||||
f.in_item = false;
|
||||
if (!f.current_item.title.empty()
|
||||
&& !f.current_item.url.empty())
|
||||
{
|
||||
f.ret.add_item(f.current_item);
|
||||
++f.num_items;
|
||||
}
|
||||
f.current_item = feed_item();
|
||||
}
|
||||
f.current_tag = "";
|
||||
return;
|
||||
}
|
||||
case xml_string:
|
||||
{
|
||||
if (!f.in_item)
|
||||
{
|
||||
if (f.is_title(f.current_tag.c_str()))
|
||||
f.ret.m_title.assign(name, name_len);
|
||||
else if (f.is_desc(f.current_tag.c_str()))
|
||||
f.ret.m_description.assign(name, name_len);
|
||||
else if (f.is_ttl(f.current_tag.c_str()))
|
||||
{
|
||||
int tmp = atoi(name);
|
||||
if (tmp > 0) f.ret.m_ttl = tmp;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (f.is_title(f.current_tag.c_str()))
|
||||
f.current_item.title.assign(name, name_len);
|
||||
else if (f.is_desc(f.current_tag.c_str()))
|
||||
f.current_item.description.assign(name, name_len);
|
||||
else if (f.is_uuid(f.current_tag.c_str()))
|
||||
f.current_item.uuid.assign(name, name_len);
|
||||
else if (f.is_url(f.current_tag.c_str()) && f.type != feed_state::atom)
|
||||
f.current_item.url.assign(name, name_len);
|
||||
else if (f.is_comment(f.current_tag.c_str()))
|
||||
f.current_item.comment.assign(name, name_len);
|
||||
else if (f.is_category(f.current_tag.c_str()))
|
||||
f.current_item.category.assign(name, name_len);
|
||||
else if (f.is_size(f.current_tag.c_str()))
|
||||
f.current_item.size = strtoll(name, 0, 10);
|
||||
else if (f.is_hash(f.current_tag.c_str()) && name_len == 40)
|
||||
{
|
||||
if (!from_hex(name, 40, f.current_item.info_hash.data()))
|
||||
{
|
||||
// hex parsing failed
|
||||
f.current_item.info_hash.clear();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case xml_declaration_tag: return;
|
||||
case xml_comment: return;
|
||||
}
|
||||
}
|
||||
|
||||
torrent_handle add_feed_item(session& s, feed_item const& fi
|
||||
, add_torrent_params const& tp, error_code& ec)
|
||||
{
|
||||
add_torrent_params p = tp;
|
||||
p.url = fi.url;
|
||||
p.uuid = fi.uuid;
|
||||
// #error figure out how to get the feed url in here
|
||||
// p.source_feed_url = ???;
|
||||
p.ti.reset();
|
||||
p.info_hash.clear();
|
||||
p.name = fi.title.c_str();
|
||||
return s.add_torrent(p, ec);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_EXCEPTIONS
|
||||
torrent_handle add_feed_item(session& s, feed_item const& fi
|
||||
, add_torrent_params const& tp)
|
||||
{
|
||||
error_code ec;
|
||||
torrent_handle ret = add_feed_item(s, fi, tp, ec);
|
||||
if (ec) throw libtorrent_exception(ec);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<feed> new_feed(aux::session_impl& ses, feed_settings const& sett)
|
||||
{
|
||||
return boost::shared_ptr<feed>(new feed(ses, sett));
|
||||
}
|
||||
|
||||
feed::feed(aux::session_impl& ses, feed_settings const& sett)
|
||||
: m_last_attempt(0)
|
||||
, m_last_update(0)
|
||||
, m_ttl(-1)
|
||||
, m_failures(0)
|
||||
, m_updating(false)
|
||||
, m_settings(sett)
|
||||
, m_ses(ses)
|
||||
{
|
||||
}
|
||||
|
||||
void feed::set_settings(feed_settings const& s)
|
||||
{
|
||||
m_settings = s;
|
||||
}
|
||||
|
||||
void feed::get_settings(feed_settings* s) const
|
||||
{
|
||||
*s = m_settings;
|
||||
}
|
||||
|
||||
feed_handle feed::my_handle()
|
||||
{
|
||||
return feed_handle(boost::weak_ptr<feed>(shared_from_this()));
|
||||
}
|
||||
|
||||
void feed::on_feed(error_code const& ec
|
||||
, http_parser const& parser, char const* data, int size)
|
||||
{
|
||||
// enabling this assert makes the unit test a lot more difficult
|
||||
// TORRENT_ASSERT(m_updating);
|
||||
m_updating = false;
|
||||
|
||||
// rss_alert is deprecated, and so is all of this code.
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
if (ec && ec != boost::asio::error::eof)
|
||||
{
|
||||
++m_failures;
|
||||
m_error = ec;
|
||||
if (m_ses.alerts().should_post<rss_alert>())
|
||||
{
|
||||
m_ses.alerts().emplace_alert<rss_alert>(my_handle(), m_settings.url
|
||||
, rss_alert::state_error, m_error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (parser.status_code() != 200)
|
||||
{
|
||||
++m_failures;
|
||||
m_error = error_code(parser.status_code(), get_http_category());
|
||||
if (m_ses.alerts().should_post<rss_alert>())
|
||||
{
|
||||
m_ses.alerts().emplace_alert<rss_alert>(my_handle(), m_settings.url
|
||||
, rss_alert::state_error, m_error);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
m_failures = 0;
|
||||
|
||||
feed_state s(*this);
|
||||
xml_parse(data, data + size, boost::bind(&parse_feed, boost::ref(s)
|
||||
, _1, _2, _3, _4, _5));
|
||||
|
||||
time_t now = time(NULL);
|
||||
|
||||
// keep history of the typical feed size times 5
|
||||
int max_history = (std::max)(s.num_items * 5, 100);
|
||||
|
||||
// this is not very efficient, but that's probably OK for now
|
||||
while (int(m_added.size()) > max_history)
|
||||
{
|
||||
// loop over all elements and find the one with the lowest timestamp
|
||||
// i.e. it was added the longest ago, then remove it
|
||||
std::map<std::string, time_t>::iterator i = std::min_element(
|
||||
m_added.begin(), m_added.end()
|
||||
, boost::bind(&std::pair<const std::string, time_t>::second, _1)
|
||||
< boost::bind(&std::pair<const std::string, time_t>::second, _2));
|
||||
m_added.erase(i);
|
||||
}
|
||||
|
||||
m_last_update = now;
|
||||
|
||||
// rss_alert is deprecated, and so is all of this code.
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
// report that we successfully updated the feed
|
||||
if (m_ses.alerts().should_post<rss_alert>())
|
||||
{
|
||||
m_ses.alerts().emplace_alert<rss_alert>(my_handle(), m_settings.url
|
||||
, rss_alert::state_updated, error_code());
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
// update m_ses.m_next_rss_update timestamps
|
||||
// now that we have updated our timestamp
|
||||
m_ses.update_rss_feeds();
|
||||
}
|
||||
|
||||
void feed::load_state(bdecode_node const& rd)
|
||||
{
|
||||
m_title = rd.dict_find_string_value("m_title");
|
||||
m_description = rd.dict_find_string_value("m_description");
|
||||
m_last_attempt = rd.dict_find_int_value("m_last_attempt");
|
||||
m_last_update = rd.dict_find_int_value("m_last_update");
|
||||
|
||||
bdecode_node e = rd.dict_find_list("items");
|
||||
if (e)
|
||||
{
|
||||
m_items.reserve(e.list_size());
|
||||
for (int i = 0; i < e.list_size(); ++i)
|
||||
{
|
||||
bdecode_node entry = e.list_at(i);
|
||||
if (entry.type() != bdecode_node::dict_t) continue;
|
||||
|
||||
m_items.push_back(feed_item());
|
||||
feed_item& item = m_items.back();
|
||||
item.url = entry.dict_find_string_value("url");
|
||||
item.uuid = entry.dict_find_string_value("uuid");
|
||||
item.title = entry.dict_find_string_value("title");
|
||||
item.description = entry.dict_find_string_value("description");
|
||||
item.comment = entry.dict_find_string_value("comment");
|
||||
item.category = entry.dict_find_string_value("category");
|
||||
item.size = entry.dict_find_int_value("size");
|
||||
|
||||
// don't load duplicates
|
||||
if (m_urls.find(item.url) != m_urls.end())
|
||||
{
|
||||
m_items.pop_back();
|
||||
continue;
|
||||
}
|
||||
m_urls.insert(item.url);
|
||||
}
|
||||
}
|
||||
|
||||
m_settings.url = rd.dict_find_string_value("url");
|
||||
m_settings.auto_download = rd.dict_find_int_value("auto_download") != 0;
|
||||
m_settings.auto_map_handles = rd.dict_find_int_value("auto_map_handles") != 0;
|
||||
m_settings.default_ttl = rd.dict_find_int_value("default_ttl");
|
||||
|
||||
e = rd.dict_find_dict("add_params");
|
||||
if (e)
|
||||
{
|
||||
m_settings.add_args.save_path = e.dict_find_string_value("save_path");
|
||||
m_settings.add_args.flags = e.dict_find_int_value("flags");
|
||||
}
|
||||
|
||||
e = rd.dict_find_list("history");
|
||||
if (e)
|
||||
{
|
||||
for (int i = 0; i < e.list_size(); ++i)
|
||||
{
|
||||
if (e.list_at(i).type() != bdecode_node::list_t) continue;
|
||||
|
||||
bdecode_node item = e.list_at(i);
|
||||
|
||||
if (item.list_size() != 2
|
||||
|| item.list_at(0).type() != bdecode_node::string_t
|
||||
|| item.list_at(1).type() != bdecode_node::int_t)
|
||||
continue;
|
||||
|
||||
m_added.insert(std::pair<std::string, time_t>(
|
||||
item.list_at(0).string_value()
|
||||
, item.list_at(1).int_value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void feed::save_state(entry& rd) const
|
||||
{
|
||||
// feed properties
|
||||
rd["m_title"] = m_title;
|
||||
rd["m_description"] = m_description;
|
||||
rd["m_last_attempt"] = m_last_attempt;
|
||||
rd["m_last_update"] = m_last_update;
|
||||
|
||||
// items
|
||||
entry::list_type& items = rd["items"].list();
|
||||
for (std::vector<feed_item>::const_iterator i = m_items.begin()
|
||||
, end(m_items.end()); i != end; ++i)
|
||||
{
|
||||
items.push_back(entry());
|
||||
entry& item = items.back();
|
||||
item["url"] = i->url;
|
||||
item["uuid"] = i->uuid;
|
||||
item["title"] = i->title;
|
||||
item["description"] = i->description;
|
||||
item["comment"] = i->comment;
|
||||
item["category"] = i->category;
|
||||
item["size"] = i->size;
|
||||
}
|
||||
|
||||
// settings
|
||||
feed_settings sett_def;
|
||||
#define TORRENT_WRITE_SETTING(name) \
|
||||
if (m_settings.name != sett_def.name) rd[#name] = m_settings.name
|
||||
|
||||
TORRENT_WRITE_SETTING(url);
|
||||
TORRENT_WRITE_SETTING(auto_download);
|
||||
TORRENT_WRITE_SETTING(auto_map_handles);
|
||||
TORRENT_WRITE_SETTING(default_ttl);
|
||||
|
||||
#undef TORRENT_WRITE_SETTING
|
||||
|
||||
entry& add = rd["add_params"];
|
||||
add_torrent_params add_def;
|
||||
#define TORRENT_WRITE_SETTING(name) \
|
||||
if (m_settings.add_args.name != add_def.name) add[#name] = m_settings.add_args.name;
|
||||
|
||||
TORRENT_WRITE_SETTING(save_path);
|
||||
TORRENT_WRITE_SETTING(flags);
|
||||
|
||||
#undef TORRENT_WRITE_SETTING
|
||||
|
||||
entry::list_type& history = rd["history"].list();
|
||||
for (std::map<std::string, time_t>::const_iterator i = m_added.begin()
|
||||
, end(m_added.end()); i != end; ++i)
|
||||
{
|
||||
history.push_back(entry());
|
||||
entry::list_type& item = history.back().list();
|
||||
item.push_back(entry(i->first));
|
||||
item.push_back(entry(i->second));
|
||||
}
|
||||
}
|
||||
|
||||
void feed::add_item(feed_item const& item)
|
||||
{
|
||||
// don't add duplicates
|
||||
if (m_urls.find(item.url) != m_urls.end())
|
||||
return;
|
||||
|
||||
m_urls.insert(item.url);
|
||||
m_items.push_back(item);
|
||||
|
||||
feed_item& i = m_items.back();
|
||||
|
||||
if (m_settings.auto_map_handles)
|
||||
i.handle = torrent_handle(m_ses.find_torrent(i.uuid.empty() ? i.url : i.uuid));
|
||||
|
||||
if (m_ses.alerts().should_post<rss_item_alert>())
|
||||
m_ses.alerts().emplace_alert<rss_item_alert>(my_handle(), i);
|
||||
|
||||
if (m_settings.auto_download)
|
||||
{
|
||||
if (!m_settings.auto_map_handles)
|
||||
i.handle = torrent_handle(m_ses.find_torrent(i.uuid.empty() ? i.url : i.uuid));
|
||||
|
||||
// if we're already downloading this torrent
|
||||
// move along to the next one
|
||||
if (i.handle.is_valid()) return;
|
||||
|
||||
// has this already been added?
|
||||
if (m_added.find(i.url) != m_added.end()) return;
|
||||
|
||||
// this means we should add this torrent to the session
|
||||
add_torrent_params p = m_settings.add_args;
|
||||
p.url = i.url;
|
||||
p.uuid = i.uuid;
|
||||
p.source_feed_url = m_settings.url;
|
||||
p.ti.reset();
|
||||
p.info_hash.clear();
|
||||
p.name = i.title.c_str();
|
||||
|
||||
error_code e;
|
||||
m_ses.add_torrent(p, e);
|
||||
time_t now = time(NULL);
|
||||
m_added.insert(make_pair(i.url, now));
|
||||
}
|
||||
}
|
||||
|
||||
// returns the number of seconds until trying again
|
||||
int feed::update_feed()
|
||||
{
|
||||
if (m_updating) return 60;
|
||||
|
||||
m_last_attempt = time(0);
|
||||
m_last_update = 0;
|
||||
|
||||
// rss_alert is deprecated, and so is all of this code.
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
if (m_ses.alerts().should_post<rss_alert>())
|
||||
{
|
||||
m_ses.alerts().emplace_alert<rss_alert>(my_handle(), m_settings.url
|
||||
, rss_alert::state_updating, error_code());
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<http_connection> feed(
|
||||
new http_connection(m_ses.get_io_service()
|
||||
, m_ses.get_resolver()
|
||||
, boost::bind(&feed::on_feed, shared_from_this()
|
||||
, _1, _2, _3, _4)));
|
||||
|
||||
m_updating = true;
|
||||
feed->get(m_settings.url, seconds(30), 0, 0, 5
|
||||
, m_ses.settings().get_str(settings_pack::user_agent));
|
||||
|
||||
return 60 + m_failures * m_failures * 60;
|
||||
}
|
||||
|
||||
void feed::get_feed_status(feed_status* ret) const
|
||||
{
|
||||
ret->items = m_items;
|
||||
ret->last_update = m_last_update;
|
||||
ret->updating = m_updating;
|
||||
ret->url = m_settings.url;
|
||||
ret->title = m_title;
|
||||
ret->description = m_description;
|
||||
ret->error = m_error;
|
||||
ret->ttl = m_ttl == -1 ? m_settings.default_ttl : m_ttl;
|
||||
ret->next_update = next_update(time(0));
|
||||
}
|
||||
|
||||
int feed::next_update(time_t now) const
|
||||
{
|
||||
if (m_last_update == 0) return int(m_last_attempt + 60 * 5 - now);
|
||||
int ttl = m_ttl == -1 ? m_settings.default_ttl : m_ttl;
|
||||
TORRENT_ASSERT((m_last_update + ttl * 60) - now < INT_MAX);
|
||||
return int((m_last_update + ttl * 60) - now);
|
||||
}
|
||||
|
||||
#define TORRENT_ASYNC_CALL(x) \
|
||||
boost::shared_ptr<feed> f = m_feed_ptr.lock(); \
|
||||
if (!f) return; \
|
||||
aux::session_impl& ses = f->session(); \
|
||||
ses.get_io_service().post(boost::bind(&feed:: x, f))
|
||||
|
||||
#define TORRENT_ASYNC_CALL1(x, a1) \
|
||||
boost::shared_ptr<feed> f = m_feed_ptr.lock(); \
|
||||
if (!f) return; \
|
||||
aux::session_impl& ses = f->session(); \
|
||||
ses.get_io_service().post(boost::bind(&feed:: x, f, a1))
|
||||
|
||||
#define TORRENT_SYNC_CALL1(x, a1) \
|
||||
boost::shared_ptr<feed> f = m_feed_ptr.lock(); \
|
||||
if (f) aux::sync_call_handle(f, boost::bind(&feed:: x, f, a1));
|
||||
|
||||
feed_handle::feed_handle(boost::weak_ptr<feed> const& p)
|
||||
: m_feed_ptr(p) {}
|
||||
|
||||
void feed_handle::update_feed()
|
||||
{
|
||||
TORRENT_ASYNC_CALL(update_feed);
|
||||
}
|
||||
|
||||
feed_status feed_handle::get_feed_status() const
|
||||
{
|
||||
feed_status ret;
|
||||
TORRENT_SYNC_CALL1(get_feed_status, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void feed_handle::set_settings(feed_settings const& s)
|
||||
{
|
||||
TORRENT_ASYNC_CALL1(set_settings, s);
|
||||
}
|
||||
|
||||
feed_settings feed_handle::settings() const
|
||||
{
|
||||
feed_settings ret;
|
||||
TORRENT_SYNC_CALL1(get_settings, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // TORRENT_NO_DEPRECATE
|
||||
|
|
@ -232,7 +232,6 @@ namespace libtorrent
|
|||
atp.last_seen_complete = resume_data.last_seen_complete;
|
||||
atp.url = resume_data.url;
|
||||
atp.uuid = resume_data.uuid;
|
||||
atp.source_feed_url = resume_data.source_feed_url;
|
||||
|
||||
atp.added_time = resume_data.added_time;
|
||||
atp.completed_time = resume_data.completed_time;
|
||||
|
@ -439,24 +438,6 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
feed_handle session_handle::add_feed(feed_settings const& feed)
|
||||
{
|
||||
// if you have auto-download enabled, you must specify a download directory!
|
||||
TORRENT_ASSERT_PRECOND(!feed.auto_download || !feed.add_args.save_path.empty());
|
||||
return TORRENT_SYNC_CALL_RET1(feed_handle, add_feed, feed);
|
||||
}
|
||||
|
||||
void session_handle::remove_feed(feed_handle h)
|
||||
{
|
||||
TORRENT_ASYNC_CALL1(remove_feed, h);
|
||||
}
|
||||
|
||||
void session_handle::get_feeds(std::vector<feed_handle>& f) const
|
||||
{
|
||||
f.clear();
|
||||
TORRENT_SYNC_CALL1(get_feeds, &f);
|
||||
}
|
||||
|
||||
void session_handle::start_dht()
|
||||
{
|
||||
settings_pack p;
|
||||
|
|
|
@ -351,10 +351,6 @@ namespace aux {
|
|||
|
||||
session_impl::session_impl(io_service& ios)
|
||||
:
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
m_next_rss_update(min_time())
|
||||
,
|
||||
#endif
|
||||
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
|
||||
m_send_buffers(send_buffer_size())
|
||||
,
|
||||
|
@ -667,19 +663,6 @@ namespace aux {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
if (flags & session::save_feeds)
|
||||
{
|
||||
entry::list_type& feeds = e["feeds"].list();
|
||||
for (std::vector<boost::shared_ptr<feed> >::const_iterator i =
|
||||
m_feeds.begin(), end(m_feeds.end()); i != end; ++i)
|
||||
{
|
||||
feeds.push_back(entry());
|
||||
(*i)->save_state(feeds.back());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (ses_extension_list_t::const_iterator i = m_ses_extensions.begin()
|
||||
, end(m_ses_extensions.end()); i != end; ++i)
|
||||
|
@ -802,24 +785,6 @@ namespace aux {
|
|||
val = settings.dict_find_int("allowed_enc_level");
|
||||
if (val) m_settings.set_int(settings_pack::allowed_enc_level, val.int_value());
|
||||
}
|
||||
|
||||
if (flags & session::save_feeds)
|
||||
{
|
||||
settings = e->dict_find_list("feeds");
|
||||
if (settings)
|
||||
{
|
||||
m_feeds.reserve(settings.list_size());
|
||||
for (int i = 0; i < settings.list_size(); ++i)
|
||||
{
|
||||
if (settings.list_at(i).type() != bdecode_node::dict_t) continue;
|
||||
boost::shared_ptr<feed> f(new_feed(*this, feed_settings()));
|
||||
f->load_state(settings.list_at(i));
|
||||
f->update_feed();
|
||||
m_feeds.push_back(f);
|
||||
}
|
||||
update_rss_feeds();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (flags & session::save_settings)
|
||||
|
@ -911,53 +876,6 @@ namespace aux {
|
|||
|
||||
#endif // TORRENT_DISABLE_EXTENSIONS
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
feed_handle session_impl::add_feed(feed_settings const& sett)
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
||||
// look for duplicates. If we already have a feed with this
|
||||
// URL, return a handle to the existing one
|
||||
for (std::vector<boost::shared_ptr<feed> >::const_iterator i
|
||||
= m_feeds.begin(), end(m_feeds.end()); i != end; ++i)
|
||||
{
|
||||
if (sett.url != (*i)->m_settings.url) continue;
|
||||
return feed_handle(*i);
|
||||
}
|
||||
|
||||
boost::shared_ptr<feed> f(new_feed(*this, sett));
|
||||
m_feeds.push_back(f);
|
||||
update_rss_feeds();
|
||||
return feed_handle(f);
|
||||
}
|
||||
|
||||
void session_impl::remove_feed(feed_handle h)
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
||||
boost::shared_ptr<feed> f = h.m_feed_ptr.lock();
|
||||
if (!f) return;
|
||||
|
||||
std::vector<boost::shared_ptr<feed> >::iterator i
|
||||
= std::find(m_feeds.begin(), m_feeds.end(), f);
|
||||
|
||||
if (i == m_feeds.end()) return;
|
||||
|
||||
m_feeds.erase(i);
|
||||
}
|
||||
|
||||
void session_impl::get_feeds(std::vector<feed_handle>* ret) const
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
||||
ret->clear();
|
||||
ret->reserve(m_feeds.size());
|
||||
for (std::vector<boost::shared_ptr<feed> >::const_iterator i = m_feeds.begin()
|
||||
, end(m_feeds.end()); i != end; ++i)
|
||||
ret->push_back(feed_handle(*i));
|
||||
}
|
||||
#endif
|
||||
|
||||
void session_impl::pause()
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
@ -3235,14 +3153,6 @@ namespace aux {
|
|||
// don't do any of the following while we're shutting down
|
||||
if (m_abort) return;
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
// --------------------------------------------------------------
|
||||
// RSS feeds
|
||||
// --------------------------------------------------------------
|
||||
if (now > m_next_rss_update)
|
||||
update_rss_feeds();
|
||||
#endif
|
||||
|
||||
switch (m_settings.get_int(settings_pack::mixed_mode_algorithm))
|
||||
{
|
||||
case settings_pack::prefer_tcp:
|
||||
|
@ -3555,27 +3465,6 @@ namespace aux {
|
|||
m_stats_counters.inc_stats_counter(counters::socket_send_size3 + index);
|
||||
}
|
||||
|
||||
#ifndef TORRENT_NO_DEPRECATE
|
||||
void session_impl::update_rss_feeds()
|
||||
{
|
||||
time_t now_posix = time(0);
|
||||
time_point min_update = max_time();
|
||||
time_point now = aux::time_now();
|
||||
for (std::vector<boost::shared_ptr<feed> >::iterator i
|
||||
= m_feeds.begin(), end(m_feeds.end()); i != end; ++i)
|
||||
{
|
||||
feed& f = **i;
|
||||
int delta = f.next_update(now_posix);
|
||||
if (delta <= 0)
|
||||
delta = f.update_feed();
|
||||
TORRENT_ASSERT(delta >= 0);
|
||||
time_point next_update = now + seconds(delta);
|
||||
if (next_update < min_update) min_update = next_update;
|
||||
}
|
||||
m_next_rss_update = min_update;
|
||||
}
|
||||
#endif
|
||||
|
||||
void session_impl::prioritize_connections(boost::weak_ptr<torrent> t)
|
||||
{
|
||||
m_prio_torrents.push_back(std::make_pair(t, 10));
|
||||
|
@ -4877,8 +4766,6 @@ namespace aux {
|
|||
torrent_ptr->set_uuid(params.uuid);
|
||||
if (!params.url.empty() && torrent_ptr->url().empty())
|
||||
torrent_ptr->set_url(params.url);
|
||||
if (!params.source_feed_url.empty() && torrent_ptr->source_feed_url().empty())
|
||||
torrent_ptr->set_source_feed_url(params.source_feed_url);
|
||||
#endif
|
||||
return torrent_handle(torrent_ptr);
|
||||
}
|
||||
|
|
|
@ -200,7 +200,6 @@ namespace libtorrent
|
|||
// deprecated in 1.2
|
||||
, m_url(p.url)
|
||||
, m_uuid(p.uuid)
|
||||
, m_source_feed_url(p.source_feed_url)
|
||||
#endif
|
||||
, m_stats_counters(ses.stats_counters())
|
||||
, m_storage_constructor(p.storage)
|
||||
|
@ -494,8 +493,6 @@ namespace libtorrent
|
|||
t->set_uuid(m_uuid);
|
||||
if (!m_url.empty() && t->url().empty())
|
||||
t->set_url(m_url);
|
||||
if (!m_source_feed_url.empty() && t->source_feed_url().empty())
|
||||
t->set_source_feed_url(m_source_feed_url);
|
||||
|
||||
// insert this torrent in the uuid index
|
||||
if (!m_uuid.empty() || !m_url.empty())
|
||||
|
@ -6490,7 +6487,6 @@ namespace libtorrent
|
|||
// deprecated in 1.2
|
||||
if (!m_url.empty()) ret["url"] = m_url;
|
||||
if (!m_uuid.empty()) ret["uuid"] = m_uuid;
|
||||
if (!m_source_feed_url.empty()) ret["feed"] = m_source_feed_url;
|
||||
#endif
|
||||
|
||||
const sha1_hash& info_hash = torrent_file().info_hash();
|
||||
|
|
Loading…
Reference in New Issue