diff options
Diffstat (limited to 'src/miners/rss')
-rw-r--r-- | src/miners/rss/.gitignore | 2 | ||||
-rw-r--r-- | src/miners/rss/Makefile.am | 73 | ||||
-rw-r--r-- | src/miners/rss/meson.build | 43 | ||||
-rw-r--r-- | src/miners/rss/org.freedesktop.Tracker1.Miner.RSS.service.in.in | 10 | ||||
-rw-r--r-- | src/miners/rss/tracker-main.c | 237 | ||||
-rw-r--r-- | src/miners/rss/tracker-miner-rss.c | 1483 | ||||
-rw-r--r-- | src/miners/rss/tracker-miner-rss.desktop.in.in | 18 | ||||
-rw-r--r-- | src/miners/rss/tracker-miner-rss.h | 53 | ||||
-rw-r--r-- | src/miners/rss/tracker-miner-rss.service.in | 10 |
9 files changed, 0 insertions, 1929 deletions
diff --git a/src/miners/rss/.gitignore b/src/miners/rss/.gitignore deleted file mode 100644 index 62c2dec7e..000000000 --- a/src/miners/rss/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tracker-miner-rss -*.service diff --git a/src/miners/rss/Makefile.am b/src/miners/rss/Makefile.am deleted file mode 100644 index 5b059e34c..000000000 --- a/src/miners/rss/Makefile.am +++ /dev/null @@ -1,73 +0,0 @@ -AM_CPPFLAGS = \ - $(BUILD_CFLAGS) \ - -DSHAREDIR=\""$(datadir)"\" \ - -DLOCALEDIR=\""$(localedir)"\" \ - -DLIBEXEC_PATH=\""$(libexecdir)"\" \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - $(TRACKER_MINER_RSS_CFLAGS) - -libexec_PROGRAMS = tracker-miner-rss - -tracker_miner_rss_SOURCES = \ - tracker-main.c \ - tracker-miner-rss.h \ - tracker-miner-rss.c - -tracker_miner_rss_LDADD = \ - $(top_builddir)/src/libtracker-sparql-backend/libtracker-sparql-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-miner/libtracker-miner-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_MINER_RSS_LIBS) - -# DBus interfaces (XML files) and services -%.service.in: %.service.in.in - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -servicedir = $(DBUS_SERVICES_DIR) -service_DATA = org.freedesktop.Tracker1.Miner.RSS.service - -INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -d -u' -@INTLTOOL_SERVICE_RULE@ - -tracker-miner-rss.service: tracker-miner-rss.service.in Makefile - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -systemd_userdir = $(prefix)/lib/systemd/user -systemd_user_DATA = tracker-miner-rss.service - -install-data-hook: - $(MKDIR_P) "$(DESTDIR)$(datadir)/tracker/miners" && \ - $(LN_S) -f "$(servicedir)/$(service_DATA)" \ - "$(DESTDIR)$(datadir)/tracker/miners/$(service_DATA)" - -uninstall-local: - $(RM) "$(DESTDIR)$(datadir)/tracker/miners/$(service_DATA)" && \ - $(RM) "$(servicedir)/$(service_DATA)" - -# Desktop files: First we fix the VERSION and libexecdir -%.desktop.in: %.desktop.in.in - @sed -e "s|@libexecdir[@]|${libexecdir}|" \ - -e "s|@VERSION[@]|${VERSION}|" $< > $@ - -autostartdir = $(sysconfdir)/xdg/autostart -autostart_DATA = tracker-miner-rss.desktop - -@INTLTOOL_DESKTOP_RULE@ - -# Dist / Clean rules for all data -CLEANFILES = \ - $(autostart_DATA) \ - $(autostart_DATA:.desktop=.desktop.in) \ - $(service_DATA) \ - $(service_DATA:.service=.service.in) \ - $(systemd_user_DATA) \ - $(NULL) - -EXTRA_DIST = \ - $(autostart_DATA:.desktop=.desktop.in.in) \ - $(service_DATA:.service=.service.in.in) \ - $(systemd_user_DATA:.service=.service.in) \ - meson.build \ - $(NULL) diff --git a/src/miners/rss/meson.build b/src/miners/rss/meson.build deleted file mode 100644 index 1e1172fc3..000000000 --- a/src/miners/rss/meson.build +++ /dev/null @@ -1,43 +0,0 @@ -sources = [ - 'tracker-main.c', - 'tracker-miner-rss.c', -] - -executable('tracker-miner-rss', sources, - dependencies: [libgrss, tracker_common_dep, tracker_miner_dep, tracker_extract_dep], - c_args: tracker_c_args, - install_rpath: tracker_internal_libs_dir, -) - -dbus_service_file_untranslated = configure_file( - input: 'org.freedesktop.Tracker1.Miner.RSS.service.in.in', - output: 'org.freedesktop.Tracker1.Miner.RSS.service.in', - configuration: conf) - -dbus_service_file = custom_target('tracker-miner-rss-dbus-service-file', - input: dbus_service_file_untranslated, - output: 'org.freedesktop.Tracker1.Miner.RSS.service', - command: ['intltool-merge', '--quiet', '--desktop-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: dbus_services_dir) - -desktop_file_untranslated = configure_file( - input: 'tracker-miner-rss.desktop.in.in', - output: 'tracker-miner-rss.desktop.in', - configuration: conf) - -desktop_file = custom_target('tracker-miner-rss-desktop-file', - input: desktop_file_untranslated, - output: 'tracker-miner-rss.desktop', - command: ['intltool-merge', '--quiet', '--desktop-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: join_paths(get_option('sysconfdir'), 'xdg/autostart')) - -if install_systemd_user_services - configure_file( - input: 'tracker-miner-rss.service.in', - output: 'tracker-miner-rss.service', - configuration: conf, - install: true, - install_dir: systemd_user_services_dir) -endif diff --git a/src/miners/rss/org.freedesktop.Tracker1.Miner.RSS.service.in.in b/src/miners/rss/org.freedesktop.Tracker1.Miner.RSS.service.in.in deleted file mode 100644 index 372c21965..000000000 --- a/src/miners/rss/org.freedesktop.Tracker1.Miner.RSS.service.in.in +++ /dev/null @@ -1,10 +0,0 @@ -[D-BUS Service] -Name=org.freedesktop.Tracker1.Miner.RSS -Exec=@libexecdir@/tracker-miner-rss -SystemdService=tracker-miner-rss.service - -# Miner details needed for tracker-control -Path=/org/freedesktop/Tracker1/Miner/RSS -NameSuffix=Miner.RSS -_DisplayName=RSS/ATOM Feeds -_Comment=Fetch RSS/ATOM Feeds diff --git a/src/miners/rss/tracker-main.c b/src/miners/rss/tracker-main.c deleted file mode 100644 index 850ed03c9..000000000 --- a/src/miners/rss/tracker-main.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (C) 2009/2010, Roberto Guido <madbob@users.barberaware.org> - * Michele Tameni <michele@amdplanet.it> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdlib.h> - -#include <locale.h> -#include <glib/gi18n.h> - -#include <libtracker-common/tracker-common.h> - -#include "tracker-miner-rss.h" - -#define DBUS_NAME_SUFFIX "Miner.RSS" -#define DBUS_PATH "/org/freedesktop/Tracker1/Miner/RSS" - -static gint verbosity = -1; -static gchar *add_feed; -static gchar *title; -static gchar *domain_ontology_name = NULL; - -static GOptionEntry entries[] = { - { "verbosity", 'v', 0, - G_OPTION_ARG_INT, &verbosity, - N_("Logging, 0 = errors only, " - "1 = minimal, 2 = detailed and 3 = debug (default=0)"), - NULL }, - { "add-feed", 'a', 0, - G_OPTION_ARG_STRING, &add_feed, - /* Translators: this is a "feed" as in RSS */ - N_("Add feed"), - N_("URL") }, - { "title", 't', 0, - G_OPTION_ARG_STRING, &title, - N_("Title to use (must be used with --add-feed)"), - NULL }, - { "domain-ontology", 'd', 0, - G_OPTION_ARG_STRING, &domain_ontology_name, - N_("Runs for an specific domain ontology"), - NULL }, - { NULL } -}; - -static void -on_domain_vanished (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - GMainLoop *loop = user_data; - g_main_loop_quit (loop); -} - -int -main (int argc, char **argv) -{ - gchar *log_filename; - GMainLoop *loop; - GOptionContext *context; - TrackerMinerRSS *miner; - GError *error = NULL; - GDBusConnection *connection; - TrackerMinerProxy *proxy; - TrackerDomainOntology *domain_ontology; - gchar *dbus_name; - - setlocale (LC_ALL, ""); - - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - tzset (); - - /* Translators: this messagge will apper immediately after the - * usage string - Usage: COMMAND <THIS_MESSAGE> - */ - context = g_option_context_new (_("— start the feeds indexer")); - g_option_context_add_main_entries (context, entries, NULL); - g_option_context_parse (context, &argc, &argv, NULL); - - if (title && !add_feed) { - gchar *help; - - help = g_option_context_get_help (context, TRUE, NULL); - g_option_context_free (context); - g_printerr ("%s", help); - g_free (help); - - return EXIT_FAILURE; - } - - g_option_context_free (context); - - tracker_sparql_connection_set_domain (domain_ontology_name); - - /* Command line stuff doesn't use logging, so we're using g_print*() */ - if (add_feed) { - TrackerSparqlConnection *connection; - GString *query; - - g_print ("Adding feed:\n" - " title:'%s'\n" - " url:'%s'\n", - title, - add_feed); - - connection = tracker_sparql_connection_get (NULL, &error); - - if (!connection) { - g_printerr ("%s: %s\n", - _("Could not establish a connection to Tracker"), - error ? error->message : _("No error given")); - g_clear_error (&error); - return EXIT_FAILURE; - } - - /* FIXME: Make interval configurable */ - query = g_string_new ("INSERT {" - " _:FeedSettings a mfo:FeedSettings ;" - " mfo:updateInterval 20 ." - " _:Feed a nie:DataObject, mfo:FeedChannel ;" - " mfo:feedSettings _:FeedSettings ;"); - - if (title) { - g_string_append_printf (query, "nie:title \"%s\";", title); - } - - g_string_append_printf (query, " nie:url \"%s\" }", add_feed); - - tracker_sparql_connection_update (connection, - query->str, - G_PRIORITY_DEFAULT, - NULL, - &error); - g_string_free (query, TRUE); - - if (error) { - g_printerr ("%s, %s\n", - _("Could not add feed"), - error->message); - g_error_free (error); - g_object_unref (connection); - - return EXIT_FAILURE; - } - - g_print ("Done\n"); - - return EXIT_SUCCESS; - } - - tracker_log_init (verbosity, &log_filename); - if (log_filename != NULL) { - g_message ("Using log file:'%s'", log_filename); - g_free (log_filename); - } - - domain_ontology = tracker_domain_ontology_new (domain_ontology_name, NULL, &error); - if (error) { - g_critical ("Could not load domain ontology '%s': %s", - domain_ontology_name, error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &error); - if (error) { - g_critical ("Could not create DBus connection: %s\n", - error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - miner = tracker_miner_rss_new (&error); - if (!miner) { - g_critical ("Could not create new RSS miner: '%s', exiting...\n", - error ? error->message : "unknown error"); - return EXIT_FAILURE; - } - - tracker_miner_start (TRACKER_MINER (miner)); - proxy = tracker_miner_proxy_new (TRACKER_MINER (miner), connection, DBUS_PATH, NULL, &error); - if (error) { - g_critical ("Could not create miner DBus proxy: %s\n", error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - dbus_name = tracker_domain_ontology_get_domain (domain_ontology, DBUS_NAME_SUFFIX); - - if (!tracker_dbus_request_name (connection, dbus_name, &error)) { - g_critical ("Could not request DBus name '%s': %s", - dbus_name, error->message); - g_error_free (error); - g_free (dbus_name); - return EXIT_FAILURE; - } - - g_free (dbus_name); - - loop = g_main_loop_new (NULL, FALSE); - - if (domain_ontology && domain_ontology_name) { - g_bus_watch_name_on_connection (connection, domain_ontology_name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - NULL, on_domain_vanished, - loop, NULL); - } - - g_main_loop_run (loop); - - tracker_log_shutdown (); - g_main_loop_unref (loop); - g_object_unref (miner); - g_object_unref (connection); - g_object_unref (proxy); - g_object_unref (domain_ontology); - - return EXIT_SUCCESS; -} diff --git a/src/miners/rss/tracker-miner-rss.c b/src/miners/rss/tracker-miner-rss.c deleted file mode 100644 index 3d87052cd..000000000 --- a/src/miners/rss/tracker-miner-rss.c +++ /dev/null @@ -1,1483 +0,0 @@ -/* - * Copyright (C) 2009/2010, Roberto Guido <madbob@users.barberaware.org> - * Michele Tameni <michele@amdplanet.it> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdio.h> - -#include <libgrss.h> - -#include <libtracker-common/tracker-dbus.h> -#include <libtracker-sparql/tracker-ontologies.h> -#include <libtracker-common/tracker-common.h> - -#include <glib/gi18n.h> - -#include "tracker-miner-rss.h" - -#define TRACKER_MINER_RSS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_MINER_RSS, TrackerMinerRSSPrivate)) - -typedef struct _TrackerMinerRSSPrivate TrackerMinerRSSPrivate; - -struct _TrackerMinerRSSPrivate { - gboolean paused; - gboolean stopped; - gchar *last_status; - - GrssFeedsPool *pool; - gint now_fetching; - GDBusConnection *connection; - guint graph_updated_id; - - GHashTable *channel_updates; - GHashTable *channels; - - gint rdf_type_id; - gint mfo_feed_channel_id; -}; - -typedef struct { - TrackerMinerRSS *miner; - GrssFeedChannel *channel; - gint timeout_id; - GCancellable *cancellable; -} FeedChannelUpdateData; - -typedef struct { - TrackerMinerRSS *miner; - GrssFeedItem *item; - GCancellable *cancellable; -} FeedItemInsertData; - -typedef struct { - TrackerMinerRSS *miner; - GrssFeedChannel *channel; - GHashTable *items; -} FeedItemListInsertData; - -static void graph_updated_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data); -static void miner_started (TrackerMiner *miner); -static void miner_stopped (TrackerMiner *miner); -static void miner_paused (TrackerMiner *miner); -static void miner_resumed (TrackerMiner *miner); -static void retrieve_and_schedule_feeds (TrackerMinerRSS *miner, - GArray *channel_ids); -static gboolean feed_channel_changed_timeout_cb (gpointer user_data); -static void feed_channel_update_data_free (FeedChannelUpdateData *fcud); -static void feed_fetching_cb (GrssFeedsPool *pool, - GrssFeedChannel *feed, - gpointer user_data); -static void feed_ready_cb (GrssFeedsPool *pool, - GrssFeedChannel *feed, - GList *items, - gpointer user_data); -static const gchar *get_message_url (GrssFeedItem *item); - -G_DEFINE_TYPE (TrackerMinerRSS, tracker_miner_rss, TRACKER_TYPE_MINER_ONLINE) - -static void -parser_characters (void *data, - const xmlChar *ch, - int len) -{ - GString *string = data; - const gchar *str, *end; - - str = (gchar *)ch; - g_utf8_validate (str, len, &end); - - if (end > str) { - g_string_append_len (string, str, end - str); - } - - if (string->str[string->len - 1] != ' ') - g_string_append_c (string, ' '); -} - -static gchar * -parse_html_text (const gchar *html) -{ - GString *string; - htmlDocPtr doc; - xmlSAXHandler handler = { - NULL, /* internalSubset */ - NULL, /* isStandalone */ - NULL, /* hasInternalSubset */ - NULL, /* hasExternalSubset */ - NULL, /* resolveEntity */ - NULL, /* getEntity */ - NULL, /* entityDecl */ - NULL, /* notationDecl */ - NULL, /* attributeDecl */ - NULL, /* elementDecl */ - NULL, /* unparsedEntityDecl */ - NULL, /* setDocumentLocator */ - NULL, /* startDocument */ - NULL, /* endDocument */ - NULL, /* startElement */ - NULL, /* endElement */ - NULL, /* reference */ - parser_characters, /* characters */ - NULL, /* ignorableWhitespace */ - NULL, /* processingInstruction */ - NULL, /* comment */ - NULL, /* xmlParserWarning */ - NULL, /* xmlParserError */ - NULL, /* xmlParserError */ - NULL, /* getParameterEntity */ - NULL, /* cdataBlock */ - NULL, /* externalSubset */ - 1, /* initialized */ - NULL, /* private */ - NULL, /* startElementNsSAX2Func */ - NULL, /* endElementNsSAX2Func */ - NULL /* xmlStructuredErrorFunc */ - }; - - string = g_string_new (NULL); - doc = htmlSAXParseDoc ((xmlChar *) html, "UTF-8", &handler, string); - - if (doc) { - xmlFreeDoc (doc); - } - - return g_string_free (string, FALSE); -} - -static void -tracker_miner_rss_finalize (GObject *object) -{ - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (object); - - priv->stopped = TRUE; - g_free (priv->last_status); - g_object_unref (priv->pool); - - g_dbus_connection_signal_unsubscribe (priv->connection, priv->graph_updated_id); - g_object_unref (priv->connection); - - g_hash_table_unref (priv->channel_updates); - g_hash_table_unref (priv->channels); - - G_OBJECT_CLASS (tracker_miner_rss_parent_class)->finalize (object); -} - -static gint -get_class_id (TrackerSparqlConnection *conn, - const gchar *class) -{ - TrackerSparqlCursor *cursor; - GError *error = NULL; - gchar *query; - gint id = -1; - - query = g_strdup_printf ("select tracker:id (%s) {}", class); - cursor = tracker_sparql_connection_query (conn, query, NULL, &error); - g_free (query); - - if (error) { - g_critical ("Could not get class ID for '%s': %s\n", - class, error->message); - g_error_free (error); - return -1; - } - - if (tracker_sparql_cursor_next (cursor, NULL, NULL)) - id = tracker_sparql_cursor_get_integer (cursor, 0); - else - g_critical ("'%s' didn't resolve to a known class ID", class); - - g_object_unref (cursor); - - return id; -} - -static gboolean -miner_connected (TrackerMinerOnline *miner, - TrackerNetworkType network) -{ - return (network == TRACKER_NETWORK_TYPE_LAN); -} - -static void -tracker_miner_rss_class_init (TrackerMinerRSSClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - TrackerMinerClass *miner_class = TRACKER_MINER_CLASS (klass); - TrackerMinerOnlineClass *miner_online_class = TRACKER_MINER_ONLINE_CLASS (klass); - - object_class->finalize = tracker_miner_rss_finalize; - - miner_class->started = miner_started; - miner_class->stopped = miner_stopped; - miner_class->paused = miner_paused; - miner_class->resumed = miner_resumed; - - miner_online_class->connected = miner_connected; - - g_type_class_add_private (object_class, sizeof (TrackerMinerRSSPrivate)); -} - -static void -tracker_miner_rss_init (TrackerMinerRSS *object) -{ - GError *error = NULL; - TrackerMinerRSSPrivate *priv; - TrackerDomainOntology *domain_ontology; - gchar *dbus_name; - - g_message ("Initializing..."); - - priv = TRACKER_MINER_RSS_GET_PRIVATE (object); - - priv->connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &error); - - if (!priv->connection) { - g_critical ("Could not connect to the D-Bus session bus, %s", - error ? error->message : "no error given."); - g_error_free (error); - return; - } - - /* Key object reference is cleaned up in value destroy func */ - priv->channel_updates = g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify) feed_channel_update_data_free); - priv->channels = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) g_object_unref); - - priv->pool = grss_feeds_pool_new (); - g_signal_connect (priv->pool, "feed-fetching", G_CALLBACK (feed_fetching_cb), object); - g_signal_connect (priv->pool, "feed-ready", G_CALLBACK (feed_ready_cb), object); - priv->now_fetching = 0; - - g_message ("Listening for GraphUpdated changes on D-Bus interface..."); - g_message (" arg0:'%s'", TRACKER_PREFIX_MFO "FeedChannel"); - - domain_ontology = tracker_domain_ontology_new (tracker_sparql_connection_get_domain (), - NULL, NULL); - dbus_name = tracker_domain_ontology_get_domain (domain_ontology, NULL); - - priv->graph_updated_id = - g_dbus_connection_signal_subscribe (priv->connection, - dbus_name, - "org.freedesktop.Tracker1.Resources", - "GraphUpdated", - "/org/freedesktop/Tracker1/Resources", - TRACKER_PREFIX_MFO "FeedChannel", - G_DBUS_SIGNAL_FLAGS_NONE, - graph_updated_cb, - object, - NULL); - g_free (dbus_name); - g_object_unref (domain_ontology); -} - -static void -delete_unbound_messages (TrackerMinerRSS *miner) -{ - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - "DELETE { ?msg a rdfs:Resource." - " ?encl a rdfs:Resource. }" - "WHERE { ?msg a mfo:FeedMessage ;" - " mfo:enclosureList ?encl ." - " FILTER(!BOUND(nmo:communicationChannel(?msg)))" - "}", - G_PRIORITY_DEFAULT, - NULL, NULL, NULL); -} - -static void -delete_message_channels_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - TrackerMinerRSS *miner = user_data; - TrackerSparqlConnection *connection; - GError *error = NULL; - - connection = TRACKER_SPARQL_CONNECTION (source_object); - tracker_sparql_connection_update_finish (connection, res, &error); - - if (error != NULL) { - g_message ("Could not delete message channels: %s", error->message); - g_error_free (error); - return; - } - - delete_unbound_messages (miner); -} - -static void -delete_message_channels (TrackerMinerRSS *miner, - GArray *channel_ids) -{ - TrackerMinerRSSPrivate *priv; - GString *query, *ids_str; - GrssFeedChannel *channel; - gint i, id; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - ids_str = g_string_new (NULL); - query = g_string_new (NULL); - - for (i = 0; i < channel_ids->len; i++) { - id = g_array_index (channel_ids, gint, i); - if (i != 0) - g_string_append (ids_str, ","); - g_string_append_printf (ids_str, "%d", id); - - channel = g_hash_table_lookup (priv->channels, - GINT_TO_POINTER (id)); - - if (channel) { - g_hash_table_remove (priv->channel_updates, channel); - g_hash_table_remove (priv->channels, GINT_TO_POINTER (id)); - } - } - - g_string_append_printf (query, - "DELETE { ?msg nmo:communicationChannel ?chan }" - "WHERE { ?msg a mfo:FeedMessage;" - " nmo:communicationChannel ?chan ." - " FILTER (tracker:id(?chan) IN (%s))" - "}", ids_str->str); - - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - query->str, G_PRIORITY_DEFAULT, - NULL, - delete_message_channels_cb, - miner); - g_string_free (ids_str, TRUE); - g_string_free (query, TRUE); -} - -static void -handle_deletes (TrackerMinerRSS *miner, - GVariantIter *iter) -{ - GArray *deleted = g_array_new (FALSE, FALSE, sizeof (gint)); - gint graph, subject, pred, object; - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - - while (g_variant_iter_next (iter, "(iiii)", - &graph, &subject, &pred, &object)) { - if (pred == priv->rdf_type_id && - object == priv->mfo_feed_channel_id) { - g_array_append_val (deleted, subject); - } - } - - if (deleted->len > 0) - delete_message_channels (miner, deleted); - - g_array_free (deleted, TRUE); -} - -static void -handle_updates (TrackerMinerRSS *miner, - GVariantIter *iter) -{ - GArray *updated = g_array_new (FALSE, FALSE, sizeof (gint)); - gint graph, subject, pred, object; - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - - while (g_variant_iter_next (iter, "(iiii)", - &graph, &subject, &pred, &object)) { - if (pred == priv->rdf_type_id && - object == priv->mfo_feed_channel_id) { - g_array_append_val (updated, subject); - } - } - - if (updated->len > 0) - retrieve_and_schedule_feeds (miner, updated); - - g_array_free (updated, TRUE); -} - -static void -graph_updated_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - TrackerMinerRSS *miner = TRACKER_MINER_RSS (user_data); - GVariantIter *deletes, *updates; - - g_variant_get (parameters, "(&sa(iiii)a(iiii))", NULL, &deletes, &updates); - handle_deletes (miner, deletes); - handle_updates (miner, updates); - g_variant_iter_free (deletes); - g_variant_iter_free (updates); -} - -static FeedChannelUpdateData * -feed_channel_update_data_new (TrackerMinerRSS *miner, - GrssFeedChannel *channel) -{ - FeedChannelUpdateData *fcud; - - fcud = g_slice_new0 (FeedChannelUpdateData); - fcud->miner = g_object_ref (miner); - fcud->channel = g_object_ref (channel); - fcud->timeout_id = g_timeout_add_seconds (2, feed_channel_changed_timeout_cb, fcud); - fcud->cancellable = g_cancellable_new (); - - return fcud; -} - -static void -feed_channel_update_data_free (FeedChannelUpdateData *fcud) -{ - if (!fcud) { - return; - } - - if (fcud->cancellable) { - g_cancellable_cancel (fcud->cancellable); - g_object_unref (fcud->cancellable); - } - - if (fcud->timeout_id) { - g_source_remove (fcud->timeout_id); - } - - if (fcud->channel) { - g_object_unref (fcud->channel); - } - - if (fcud->miner) { - g_object_unref (fcud->miner); - } - - g_slice_free (FeedChannelUpdateData, fcud); -} - -static FeedItemListInsertData * -feed_item_list_insert_data_new (TrackerMinerRSS *miner, - GrssFeedChannel *channel, - GList *items) -{ - FeedItemListInsertData *data; - GrssFeedItem *prev; - const gchar *url; - GList *l; - - data = g_slice_new0 (FeedItemListInsertData); - data->channel = channel; - data->miner = miner; - data->items = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); - - /* Make items unique, keep most recent */ - for (l = items; l; l = l->next) { - url = get_message_url (l->data); - prev = g_hash_table_lookup (data->items, url); - - if (prev) { - /* Compare publish times */ - if (grss_feed_item_get_publish_time (l->data) <= - grss_feed_item_get_publish_time (prev)) - continue; - } - - g_hash_table_insert (data->items, g_strdup (url), - g_object_ref (l->data)); - } - - return data; -} - -static void -feed_item_list_insert_data_free (FeedItemListInsertData *data) -{ - g_hash_table_destroy (data->items); - g_slice_free (FeedItemListInsertData, data); -} - -static void -feed_channel_change_updated_time_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - TrackerMinerRSSPrivate *priv; - FeedChannelUpdateData *fcud; - GError *error = NULL; - - fcud = user_data; - priv = TRACKER_MINER_RSS_GET_PRIVATE (fcud->miner); - - tracker_sparql_connection_update_finish (TRACKER_SPARQL_CONNECTION (source), result, &error); - if (error != NULL) { - g_critical ("Could not change feed channel updated time, %s", error->message); - g_error_free (error); - } - - /* This will clean up the fcud data too */ - g_hash_table_remove (priv->channel_updates, fcud->channel); -} - -static gboolean -feed_channel_changed_timeout_cb (gpointer user_data) -{ - TrackerSparqlBuilder *sparql; - FeedChannelUpdateData *fcud; - gchar *uri; - time_t now; - - fcud = user_data; - fcud->timeout_id = 0; - - now = time (NULL); - uri = g_object_get_data (G_OBJECT (fcud->channel), "subject"); - - g_message ("Updating mfo:updatedTime for channel '%s'", grss_feed_channel_get_title (fcud->channel)); - - /* I hope there will be soon a SPARQL command to just update a - * value instead to delete and re-insert it - */ - - sparql = tracker_sparql_builder_new_update (); - tracker_sparql_builder_delete_open (sparql, NULL); - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "mfo:updatedTime"); - tracker_sparql_builder_object_variable (sparql, "unknown"); - tracker_sparql_builder_delete_close (sparql); - tracker_sparql_builder_where_open (sparql); - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "mfo:updatedTime"); - tracker_sparql_builder_object_variable (sparql, "unknown"); - tracker_sparql_builder_where_close (sparql); - - tracker_sparql_builder_insert_open (sparql, NULL); - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "mfo:updatedTime"); - tracker_sparql_builder_object_date (sparql, &now); - tracker_sparql_builder_insert_close (sparql); - - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (fcud->miner)), - tracker_sparql_builder_get_result (sparql), - G_PRIORITY_DEFAULT, - fcud->cancellable, - feed_channel_change_updated_time_cb, - fcud); - g_object_unref (sparql); - - return FALSE; -} - -static void -feed_channel_change_updated_time (TrackerMinerRSS *miner, - GrssFeedChannel *channel) -{ - TrackerMinerRSSPrivate *priv; - FeedChannelUpdateData *fcud; - - if (!channel) - return; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - - fcud = g_hash_table_lookup (priv->channel_updates, channel); - if (fcud) { - /* We already had an update for this channel in - * progress, so we just reset the timeout. - */ - g_source_remove (fcud->timeout_id); - fcud->timeout_id = g_timeout_add_seconds (2, - feed_channel_changed_timeout_cb, - fcud); - } else { - /* This is a new update for this channel */ - fcud = feed_channel_update_data_new (miner, channel); - g_hash_table_insert (priv->channel_updates, - fcud->channel, - fcud); - } -} - -static void -feed_fetching_cb (GrssFeedsPool *pool, - GrssFeedChannel *channel, - gpointer user_data) -{ - gint avail; - gdouble prog; - TrackerMinerRSS *miner; - TrackerMinerRSSPrivate *priv; - - miner = TRACKER_MINER_RSS (user_data); - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - avail = grss_feeds_pool_get_listened_num (priv->pool); - - priv->now_fetching++; - - if (priv->now_fetching > avail) - priv->now_fetching = avail; - - g_message ("Fetching channel details, source:'%s' (in progress: %d/%d)", - grss_feed_channel_get_source (channel), - priv->now_fetching, - avail); - - prog = ((gdouble) priv->now_fetching) / ((gdouble) avail); - g_object_set (miner, "progress", prog, "status", "Fetching…", NULL); -} - -static gchar * -sparql_add_website (TrackerSparqlBuilder *sparql, - const gchar *uri) -{ - gchar *website_urn; - - website_urn = tracker_sparql_escape_uri_printf ("urn:website:%s", uri); - - tracker_sparql_builder_insert_silent_open (sparql, NULL); - tracker_sparql_builder_subject_iri (sparql, website_urn); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nie:DataObject"); - tracker_sparql_builder_object (sparql, "nfo:Website"); - - tracker_sparql_builder_predicate (sparql, "nie:url"); - tracker_sparql_builder_object_unvalidated (sparql, uri); - - tracker_sparql_builder_insert_close (sparql); - - return website_urn; -} - -static void -sparql_add_contact (TrackerSparqlBuilder *sparql, - const gchar *alias, - GrssPerson *contact, - const gchar *website_urn, - gboolean is_iri) -{ - const gchar *name = grss_person_get_name (contact); - const gchar *email = grss_person_get_email (contact); - - tracker_sparql_builder_subject (sparql, alias); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nco:Contact"); - - tracker_sparql_builder_predicate (sparql, "nco:fullname"); - tracker_sparql_builder_object_unvalidated (sparql, name); - - if (email != NULL) { - tracker_sparql_builder_predicate (sparql, "nco:hasEmailAddress"); - - tracker_sparql_builder_object_blank_open (sparql); - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nco:EmailAddress"); - - tracker_sparql_builder_predicate (sparql, "nco:emailAddress"); - tracker_sparql_builder_object_unvalidated (sparql, email); - tracker_sparql_builder_object_blank_close (sparql); - } - - if (website_urn) { - tracker_sparql_builder_predicate (sparql, "nco:websiteUrl"); - - if (is_iri) { - tracker_sparql_builder_object_iri (sparql, website_urn); - } else { - tracker_sparql_builder_object (sparql, website_urn); - } - } -} - -static void -sparql_add_enclosure (TrackerSparqlBuilder *sparql, - const gchar *subject, - GrssFeedEnclosure *enclosure) -{ - gchar *url; - gint length; - gchar * format; - - url = grss_feed_enclosure_get_url (enclosure); - length = grss_feed_enclosure_get_length (enclosure); - format = grss_feed_enclosure_get_format (enclosure); - - tracker_sparql_builder_subject (sparql, subject); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "mfo:Enclosure"); - tracker_sparql_builder_object (sparql, "nfo:RemoteDataObject"); - - tracker_sparql_builder_predicate (sparql, "mfo:remoteLink"); - tracker_sparql_builder_object_unvalidated (sparql, url); - - tracker_sparql_builder_predicate (sparql, "nfo:fileSize"); - tracker_sparql_builder_object_int64 (sparql, length); - - if (format != NULL) { - tracker_sparql_builder_predicate (sparql, "nie:mimeType"); - tracker_sparql_builder_object_unvalidated (sparql, format); - } - -} - -static gchar * -feed_message_create_update_channel_query (const gchar *item_urn, - GrssFeedItem *item) -{ - GrssFeedChannel *channel; - const gchar *channel_urn; - - channel = grss_feed_item_get_parent (item); - channel_urn = g_object_get_data (G_OBJECT (channel), "subject"); - - return g_strdup_printf ("INSERT SILENT { <%s> nmo:communicationChannel <%s> }", - item_urn, channel_urn); -} - -static gchar * -feed_message_create_delete_properties_query (const gchar *item_urn) -{ - return g_strdup_printf ("DELETE { <%s> ?p ?o }" - "WHERE { <%s> a mfo:FeedMessage ;" - " ?p ?o ." - " FILTER (?p != rdf:type &&" - " ?p != nmo:communicationChannel)" - "}", item_urn, item_urn); -} - -static TrackerSparqlBuilder * -feed_message_create_insert_builder (TrackerMinerRSS *miner, - GrssFeedItem *item, - const gchar *item_urn) -{ - time_t t; - gchar *uri; - const gchar *url; - GrssPerson *author; - gdouble latitude; - gdouble longitude; - const gchar *tmp_string; - TrackerSparqlBuilder *sparql; - GrssFeedChannel *channel; - gboolean has_geolocation; - const GList *contributors; - const GList *enclosures; - const GList *list, *l; - GList *contrib_aliases = NULL; - GList *enclosure_aliases = NULL; - GHashTable *websites; - GHashTable *enclosure_urls; - gboolean is_iri = FALSE; - gint i = 0; - - if (!item_urn) { - item_urn = "_:message"; - } else { - is_iri = TRUE; - } - - url = get_message_url (item); - g_message ("Inserting feed item for '%s'", url); - - websites = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); - g_hash_table_insert (websites, g_strdup (url), g_strdup (item_urn)); - - sparql = tracker_sparql_builder_new_update (); - author = grss_feed_item_get_author (item); - contributors = grss_feed_item_get_contributors (item); - channel = grss_feed_item_get_parent (item); - enclosures = grss_feed_item_get_enclosures (item); - - for (l = contributors; l; l = l->next) { - const gchar *person_url; - - person_url = grss_person_get_uri (l->data); - - if (!person_url) - continue; - - if (g_hash_table_lookup (websites, person_url)) - continue; - - g_hash_table_insert (websites, g_strdup (person_url), - sparql_add_website (sparql, person_url)); - } - - if (author && grss_person_get_uri (author)) { - const gchar *person_url; - - person_url = grss_person_get_uri (author); - - if (!g_hash_table_lookup (websites, person_url)) { - g_hash_table_insert (websites, g_strdup (person_url), - sparql_add_website (sparql, person_url)); - } - } - - has_geolocation = grss_feed_item_get_geo_point (item, &latitude, &longitude); - tracker_sparql_builder_insert_open (sparql, NULL); - - if (has_geolocation) { - g_message (" Geolocation, using longitude:%f, latitude:%f", - longitude, latitude); - - tracker_sparql_builder_subject (sparql, "_:location"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "slo:GeoLocation"); - - tracker_sparql_builder_predicate (sparql, "slo:latitude"); - tracker_sparql_builder_object_double (sparql, latitude); - tracker_sparql_builder_predicate (sparql, "slo:longitude"); - tracker_sparql_builder_object_double (sparql, longitude); - } - - if (author != NULL) { - g_message (" Author:'%s'", grss_person_get_name (author)); - - if (grss_person_get_uri (author)) - tmp_string = g_hash_table_lookup (websites, grss_person_get_uri (author)); - else - tmp_string = NULL; - - sparql_add_contact (sparql, "_:author", author, tmp_string, - (tmp_string && tmp_string[0] != '_')); - } - - i = 0; - for (l = contributors; l; l = l->next) { - gchar *subject; - - g_debug (" Contributor:'%s'", grss_person_get_name (l->data)); - - subject = g_strdup_printf ("_:contrib%d", i++); - contrib_aliases = g_list_prepend (contrib_aliases, subject); - - if (grss_person_get_uri (l->data)) - tmp_string = g_hash_table_lookup (websites, grss_person_get_uri (l->data)); - else - tmp_string = NULL; - - sparql_add_contact (sparql, subject, l->data, tmp_string, - (tmp_string && tmp_string[0] != '_')); - - /* subject is not freed right now as it will be freed at the end of the - * method in a foreach loop over the contrib_aliases list */ - } - - enclosure_urls = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); - i = 0; - for (l = enclosures; l; l = l->next) { - gchar *subject; - gchar *url; - - url = grss_feed_enclosure_get_url (l->data); - - if (!g_hash_table_contains (enclosure_urls, url)) { - g_debug (" Enclosure:'%s'", url); - subject = g_strdup_printf ("_:enclosure%d", i++); - enclosure_aliases = g_list_prepend (enclosure_aliases, subject); - g_hash_table_insert (enclosure_urls, g_strdup (url), NULL); - - sparql_add_enclosure (sparql, subject, l->data); - - } - - /* subject is not freed right now as it will be freed at the end of the - * method in a foreach loop over the enclosure_aliases list */ - } - - if (is_iri) { - tracker_sparql_builder_subject_iri (sparql, item_urn); - } else { - tracker_sparql_builder_subject (sparql, item_urn); - } - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "mfo:FeedMessage"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:RemoteDataObject"); - - if (has_geolocation == TRUE) { - tracker_sparql_builder_predicate (sparql, "slo:location"); - tracker_sparql_builder_object (sparql, "_:location"); - } - - tmp_string = grss_feed_item_get_title (item); - if (tmp_string != NULL) { - g_message (" Title:'%s'", tmp_string); - - tracker_sparql_builder_predicate (sparql, "nie:title"); - tracker_sparql_builder_object_unvalidated (sparql, tmp_string); - } - - if (author != NULL) { - tracker_sparql_builder_predicate (sparql, "nco:creator"); - tracker_sparql_builder_object (sparql, "_:author"); - } - - for (l = contrib_aliases; l; l = l->next) { - tracker_sparql_builder_predicate (sparql, "nco:contributor"); - tracker_sparql_builder_object (sparql, l->data); - } - - for (l = enclosure_aliases; l; l = l->next) { - tracker_sparql_builder_predicate (sparql, "mfo:enclosureList"); - tracker_sparql_builder_object (sparql, l->data); - } - - tmp_string = grss_feed_item_get_description (item); - if (tmp_string != NULL) { - gchar *plain_text; - - plain_text = parse_html_text (tmp_string); - tracker_sparql_builder_predicate (sparql, "nie:plainTextContent"); - tracker_sparql_builder_object_unvalidated (sparql, plain_text); - g_free (plain_text); - - tracker_sparql_builder_predicate (sparql, "nmo:htmlMessageContent"); - tracker_sparql_builder_object_unvalidated (sparql, tmp_string); - } - - if (url != NULL) { - tracker_sparql_builder_predicate (sparql, "nie:url"); - tracker_sparql_builder_object_unvalidated (sparql, url); - } - - /* TODO nmo:receivedDate and mfo:downloadedTime are the same? - * Ask for the MFO maintainer */ - - t = time (NULL); - - tracker_sparql_builder_predicate (sparql, "nmo:receivedDate"); - tracker_sparql_builder_object_date (sparql, &t); - - tracker_sparql_builder_predicate (sparql, "mfo:downloadedTime"); - tracker_sparql_builder_object_date (sparql, &t); - - t = grss_feed_item_get_publish_time (item); - tracker_sparql_builder_predicate (sparql, "nie:contentCreated"); - tracker_sparql_builder_object_date (sparql, &t); - - tracker_sparql_builder_predicate (sparql, "nmo:isRead"); - tracker_sparql_builder_object_boolean (sparql, FALSE); - - uri = g_object_get_data (G_OBJECT (channel), "subject"); - tracker_sparql_builder_predicate (sparql, "nmo:communicationChannel"); - tracker_sparql_builder_object_iri (sparql, uri); - - tmp_string = grss_feed_item_get_copyright (item); - if (tmp_string) { - tracker_sparql_builder_predicate (sparql, "nie:copyright"); - tracker_sparql_builder_object_unvalidated (sparql, tmp_string); - } - - list = grss_feed_item_get_categories (item); - for (l = list; l; l = l->next) { - tracker_sparql_builder_predicate (sparql, "nie:keyword"); - tracker_sparql_builder_object_unvalidated (sparql, l->data); - } - - tracker_sparql_builder_insert_close (sparql); - - g_list_free_full (contrib_aliases, g_free); - g_list_free_full (enclosure_aliases, g_free); - g_hash_table_destroy (websites); - g_hash_table_destroy (enclosure_urls); - - return sparql; -} - -static void -feed_channel_content_update_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - TrackerSparqlConnection *connection; - GPtrArray *errors, *array = user_data; - GError *error = NULL; - guint i; - - connection = TRACKER_SPARQL_CONNECTION (source); - errors = tracker_sparql_connection_update_array_finish (connection, - result, &error); - - if (error) { - g_warning ("Could not update feed items: %s", - error->message); - g_error_free (error); - } else { - for (i = 0; i < errors->len; i++) { - GError *error = g_ptr_array_index (errors, i); - - if (!error) - continue; - - g_warning ("Error in item %d of update: %s\nQuery: %s", i, - error->message, (gchar *) g_ptr_array_index (array, i)); - } - - g_ptr_array_unref (errors); - } - - g_ptr_array_unref (array); -} - -static void -check_feed_items_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - TrackerSparqlConnection *connection; - TrackerSparqlBuilder *sparql; - FeedItemListInsertData *data; - TrackerSparqlCursor *cursor; - GrssFeedItem *item; - GError *error = NULL; - GHashTableIter iter; - GPtrArray *array; - const gchar *str; - - data = user_data; - connection = TRACKER_SPARQL_CONNECTION (source_object); - cursor = tracker_sparql_connection_query_finish (connection, res, &error); - array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); - - while (!error && tracker_sparql_cursor_next (cursor, NULL, &error)) { - const gchar *urn, *url, *date; - time_t time; - - urn = tracker_sparql_cursor_get_string (cursor, 0, NULL); - url = tracker_sparql_cursor_get_string (cursor, 1, NULL); - date = tracker_sparql_cursor_get_string (cursor, 2, NULL); - time = (time_t) tracker_string_to_date (date, NULL, NULL); - - item = g_hash_table_lookup (data->items, url); - - if (!item) - continue; - - if (time <= grss_feed_item_get_publish_time (item)) { - g_debug ("Item '%s' already up to date", url); - g_ptr_array_add (array, feed_message_create_update_channel_query (urn, item)); - } else { - g_debug ("Updating item '%s'", url); - - g_ptr_array_add (array, feed_message_create_delete_properties_query (urn)); - - sparql = feed_message_create_insert_builder (data->miner, - item, urn); - str = tracker_sparql_builder_get_result (sparql); - g_ptr_array_add (array, g_strdup (str)); - g_object_unref (sparql); - } - - g_hash_table_remove (data->items, url); - } - - if (cursor) { - g_object_unref (cursor); - } - - if (error) { - g_message ("Could check feed items, %s", error->message); - g_error_free (error); - feed_item_list_insert_data_free (data); - g_ptr_array_unref (array); - return; - } - - g_hash_table_iter_init (&iter, data->items); - - /* Insert all remaining items as new */ - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &item)) { - sparql = feed_message_create_insert_builder (data->miner, - item, NULL); - str = tracker_sparql_builder_get_result (sparql); - g_ptr_array_add (array, g_strdup (str)); - g_object_unref (sparql); - } - - if (array->len == 0) { - feed_item_list_insert_data_free (data); - g_ptr_array_unref (array); - return; - } - - tracker_sparql_connection_update_array_async (tracker_miner_get_connection (TRACKER_MINER (data->miner)), - (gchar **) array->pdata, - array->len, - G_PRIORITY_DEFAULT, NULL, - feed_channel_content_update_cb, - array); - feed_channel_change_updated_time (data->miner, data->channel); - feed_item_list_insert_data_free (data); -} - -static void -check_feed_items (TrackerMinerRSS *miner, - GrssFeedChannel *channel, - GList *items) -{ - FeedItemListInsertData *data; - GHashTableIter iter; - GrssFeedItem *item; - gboolean first = TRUE; - const gchar *url; - GString *query; - - data = feed_item_list_insert_data_new (miner, channel, items); - g_hash_table_iter_init (&iter, data->items); - - query = g_string_new ("SELECT ?msg nie:url(?msg)" - " nie:contentCreated(?msg) {" - " ?msg a rdfs:Resource ." - " FILTER (nie:url(?msg) IN ("); - - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &item)) { - if (!first) - g_string_append_c (query, ','); - - url = get_message_url (item); - g_string_append_printf (query, "\"%s\"", url); - first = FALSE; - } - - g_string_append (query, "))}"); - - tracker_sparql_connection_query_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - query->str, NULL, - check_feed_items_cb, - data); - g_string_free (query, TRUE); -} - -static void -update_feed_channel_info (TrackerMinerRSS *miner, - GrssFeedChannel *channel) -{ - const gchar *subject, *str; - GString *update; - gchar *escaped; - time_t time; - - g_debug ("Updating mfo:FeedChannel for '%s'", - grss_feed_channel_get_title (channel)); - - subject = g_object_get_data (G_OBJECT (channel), "subject"); - update = g_string_new ("INSERT OR REPLACE { "); - - str = grss_feed_channel_get_title (channel); - if (str) { - escaped = tracker_sparql_escape_string (str); - g_string_append_printf (update, "<%s> nie:title \"%s\".", subject, escaped); - g_free (escaped); - } - - str = grss_feed_channel_get_format (channel); - if (str) { - escaped = tracker_sparql_escape_string (str); - g_string_append_printf (update, - "<%s> mfo:type [ a mfo:FeedType ;" - " mfo:name \"%s\"].", - subject, escaped); - g_free (escaped); - } - - str = grss_feed_channel_get_description (channel); - if (str) { - escaped = tracker_sparql_escape_string (str); - g_string_append_printf (update, "<%s> nie:description \"%s\".", subject, escaped); - g_free (escaped); - } - - str = grss_feed_channel_get_image (channel); - if (str) { - g_string_append_printf (update, "<%s> mfo:image \"%s\".", subject, str); - } - - str = grss_feed_channel_get_copyright (channel); - if (str) { - escaped = tracker_sparql_escape_string (str); - g_string_append_printf (update, "<%s> nie:copyright \"%s\".", subject, escaped); - g_free (escaped); - } - - time = grss_feed_channel_get_publish_time (channel); - - if (time != 0) { - escaped = tracker_date_to_string (time); - g_string_append_printf (update, "<%s> nmo:lastMessageDate \"%s\".", subject, escaped); - g_free (escaped); - } - - g_string_append (update, "}"); - - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - update->str, G_PRIORITY_DEFAULT, - NULL, NULL, NULL); - g_string_free (update, TRUE); -} - -static void -feed_ready_cb (GrssFeedsPool *pool, - GrssFeedChannel *channel, - GList *items, - gpointer user_data) -{ - TrackerMinerRSS *miner; - TrackerMinerRSSPrivate *priv; - - miner = TRACKER_MINER_RSS (user_data); - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - - priv->now_fetching--; - - g_debug ("Feed fetched, %d remaining", priv->now_fetching); - - if (priv->now_fetching <= 0) { - priv->now_fetching = 0; - g_object_set (miner, "progress", 1.0, "status", "Idle", NULL); - } - - if (items == NULL) { - return; - } - - update_feed_channel_info (miner, channel); - - g_message ("Verifying channel:'%s' is up to date", - grss_feed_channel_get_title (channel)); - - check_feed_items (miner, channel, items); -} - -static void -feeds_retrieve_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - GList *channels; - TrackerSparqlCursor *cursor; - GError *error = NULL; - TrackerMinerRSSPrivate *priv; - GrssFeedChannel *chan; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (user_data); - cursor = tracker_sparql_connection_query_finish (TRACKER_SPARQL_CONNECTION (source_object), - res, - &error); - - if (error != NULL) { - g_message ("Could not retrieve feeds, %s", error->message); - g_error_free (error); - if (cursor) { - g_object_unref (cursor); - } - return; - } - - while (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - const gchar *source; - const gchar *title; - const gchar *interval; - const gchar *subject; - gint mins, id; - - source = tracker_sparql_cursor_get_string (cursor, 0, NULL); - title = tracker_sparql_cursor_get_string (cursor, 1, NULL); - interval = tracker_sparql_cursor_get_string (cursor, 2, NULL); - subject = tracker_sparql_cursor_get_string (cursor, 3, NULL); - id = tracker_sparql_cursor_get_integer (cursor, 4); - - g_debug ("Indexing channel '%s'", source); - - if (g_hash_table_lookup (priv->channels, GINT_TO_POINTER (id))) - continue; - - chan = grss_feed_channel_new (); - g_object_set_data_full (G_OBJECT (chan), - "subject", - g_strdup (subject), - g_free); - grss_feed_channel_set_source (chan, g_strdup (source)); - - /* TODO How to manage feeds with an update mfo:updateInterval == 0 ? - * Here the interval is forced to be at least 1 minute, but perhaps those - * elements are to be considered "disabled" - */ - mins = strtoull (interval, NULL, 10); - if (mins <= 0) - mins = 1; - grss_feed_channel_set_update_interval (chan, mins); - - g_message (" '%s' (%s) - update interval of %s minutes", - title, - source, - interval); - - g_hash_table_insert (priv->channels, GINT_TO_POINTER (id), chan); - } - - if (g_hash_table_size (priv->channels) == 0) { - g_message ("No feeds set up, nothing more to do"); - } - - channels = g_hash_table_get_values (priv->channels); - grss_feeds_pool_listen (priv->pool, channels); - g_list_free (channels); - - g_object_unref (cursor); - - if (g_hash_table_size (priv->channels) == 0) { - g_object_set (user_data, "progress", 1.0, "status", "Idle", NULL); - } -} - -static void -retrieve_and_schedule_feeds (TrackerMinerRSS *miner, - GArray *channel_ids) -{ - GString *sparql; - gint i, id; - - g_message ("Retrieving and scheduling feeds..."); - - sparql = g_string_new ("SELECT ?url nie:title(?urn) ?interval ?urn tracker:id(?urn)" - "WHERE {" - " ?urn a mfo:FeedChannel ; " - " mfo:feedSettings ?settings ; " - " nie:url ?url . " - " ?settings mfo:updateInterval ?interval "); - - if (channel_ids && channel_ids->len > 0) { - g_string_append (sparql, ". FILTER (tracker:id(?urn) IN ("); - - for (i = 0; i < channel_ids->len; i++) { - id = g_array_index (channel_ids, gint, i); - if (i != 0) - g_string_append (sparql, ","); - g_string_append_printf (sparql, "%d", id); - } - - g_string_append (sparql, "))"); - } - - g_string_append_printf (sparql, "}"); - - tracker_sparql_connection_query_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - sparql->str, - NULL, - feeds_retrieve_cb, - miner); - g_string_free (sparql, TRUE); -} - -static const gchar * -get_message_url (GrssFeedItem *item) -{ - const gchar *url; - - grss_feed_item_get_real_source (item, &url, NULL); - if (url == NULL) - url = grss_feed_item_get_source (item); - return url; -} - -static void -miner_started (TrackerMiner *miner) -{ - TrackerMinerRSSPrivate *priv; - TrackerSparqlConnection *conn; - - g_object_set (miner, "progress", 0.0, "status", "Initializing", NULL); - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - conn = tracker_miner_get_connection (miner); - priv->rdf_type_id = get_class_id (conn, "rdf:type"); - priv->mfo_feed_channel_id = get_class_id (conn, "mfo:FeedChannel"); - retrieve_and_schedule_feeds (TRACKER_MINER_RSS (miner), NULL); - grss_feeds_pool_switch (priv->pool, TRUE); -} - -static void -miner_stopped (TrackerMiner *miner) -{ - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - grss_feeds_pool_switch (priv->pool, FALSE); - g_object_set (miner, "progress", 1.0, "status", "Idle", NULL); -} - -static void -miner_paused (TrackerMiner *miner) -{ - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - grss_feeds_pool_switch (priv->pool, FALSE); - - /* Save last status */ - g_free (priv->last_status); - g_object_get (miner, "status", &priv->last_status, NULL); - - /* Set paused */ - g_object_set (miner, "status", "Paused", NULL); -} - -static void -miner_resumed (TrackerMiner *miner) -{ - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - grss_feeds_pool_switch (priv->pool, TRUE); - - /* Resume */ - g_object_set (miner, "status", priv->last_status ? priv->last_status : "Idle", NULL); -} - -TrackerMinerRSS * -tracker_miner_rss_new (GError **error) -{ - return g_initable_new (TRACKER_TYPE_MINER_RSS, - NULL, - error, - NULL); -} diff --git a/src/miners/rss/tracker-miner-rss.desktop.in.in b/src/miners/rss/tracker-miner-rss.desktop.in.in deleted file mode 100644 index 49be40191..000000000 --- a/src/miners/rss/tracker-miner-rss.desktop.in.in +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -_Name=Tracker RSS/ATOM Feeds Miner -_Comment=Fetch RSS/ATOM feeds -Icon= -Exec=@libexecdir@/tracker-miner-rss -Terminal=false -Type=Application -Categories=Utility; -X-GNOME-Autostart-enabled=false -X-KDE-autostart-after=panel -X-KDE-StartupNotify=false -X-KDE-UniqueApplet=true -NoDisplay=true -OnlyShowIn=GNOME;KDE;XFCE;Unity; -X-GNOME-Bugzilla-Bugzilla=GNOME -X-GNOME-Bugzilla-Product=tracker -X-GNOME-Bugzilla-Component=Miners -X-GNOME-Bugzilla-Version=@VERSION@ diff --git a/src/miners/rss/tracker-miner-rss.h b/src/miners/rss/tracker-miner-rss.h deleted file mode 100644 index 2271ec9da..000000000 --- a/src/miners/rss/tracker-miner-rss.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2009/2010, Roberto Guido <madbob@users.barberaware.org> - * Michele Tameni <michele@amdplanet.it> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_MINER_RSS_H__ -#define __TRACKER_MINER_RSS_H__ - -#include <libtracker-miner/tracker-miner.h> - -#include <libtracker-sparql/tracker-sparql.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_MINER_RSS (tracker_miner_rss_get_type()) -#define TRACKER_MINER_RSS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_MINER_RSS, TrackerMinerRSS)) -#define TRACKER_MINER_RSS_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_MINER_RSS, TrackerMinerRSSClass)) -#define TRACKER_IS_MINER_RSS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_MINER_RSS)) -#define TRACKER_IS_MINER_RSS_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_MINER_RSS)) -#define TRACKER_MINER_RSS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_MINER_RSS, TrackerMinerRSSClass)) - -typedef struct _TrackerMinerRSS TrackerMinerRSS; -typedef struct _TrackerMinerRSSClass TrackerMinerRSSClass; - -struct _TrackerMinerRSS { - TrackerMinerOnline parent; -}; - -struct _TrackerMinerRSSClass { - TrackerMinerOnlineClass parent; -}; - -GType tracker_miner_rss_get_type (void) G_GNUC_CONST; -TrackerMinerRSS *tracker_miner_rss_new (GError **error); - -G_END_DECLS - -#endif /* __TRACKER_MINER_RSS_H__ */ diff --git a/src/miners/rss/tracker-miner-rss.service.in b/src/miners/rss/tracker-miner-rss.service.in deleted file mode 100644 index 2bebf4cf5..000000000 --- a/src/miners/rss/tracker-miner-rss.service.in +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Tracker RSS/ATOM feed data miner - -[Service] -Type=dbus -BusName=org.freedesktop.Tracker1.Miner.RSS -ExecStart=@libexecdir@/tracker-miner-rss -Restart=on-failure -# Don't restart after tracker daemon -k (aka tracker-control -k) -RestartPreventExitStatus=SIGKILL |