{"result":{"depiction_url":null,"edges":{"observes":{"objects":[{"created":"2026-10-13T15:15:42Z","object_id":{"id":1466,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_admin_menu","title":"observe_admin_menu\/3","uri":"https:\/\/zotonic.com\/id\/1466"},"seq":1},{"created":"2026-10-13T15:15:42Z","object_id":{"id":2293,"is_a":["text","documentation","reference","notification"],"name":"doc_notification_rsc_import_fetch","title":"observe_rsc_import_fetch\/2","uri":"https:\/\/zotonic.com\/id\/2293"},"seq":2}],"predicate":{"id":2550,"is_a":["meta","predicate"],"name":"observes","title":{"_type":"trans","tr":{"en":"Observes"}},"uri":"https:\/\/zotonic.com\/id\/observes"}},"subject":{"objects":[{"created":"2026-10-13T15:15:42Z","object_id":{"id":2555,"is_a":["categorization","keyword","keyword_information_type"],"name":"zotonic_topic_reference","title":"Reference","uri":"https:\/\/zotonic.com\/id\/2555"},"seq":1},{"created":"2026-10-13T15:15:43Z","object_id":{"id":2565,"is_a":["categorization","keyword","keyword_audience"],"name":"zotonic_topic_integrator","title":"Integrator","uri":"https:\/\/zotonic.com\/id\/2565"},"seq":2},{"created":"2026-10-13T15:15:43Z","object_id":{"id":2600,"is_a":["categorization","keyword","keyword_domain"],"name":"zotonic_topic_import_and_migration","title":"Import and migration","uri":"https:\/\/zotonic.com\/id\/2600"},"seq":3},{"created":"2026-10-13T15:15:43Z","object_id":{"id":2635,"is_a":["categorization","keyword","keyword_architecture"],"name":"zotonic_topic_module","title":"Module","uri":"https:\/\/zotonic.com\/id\/2635"},"seq":4},{"created":"2026-10-13T15:15:43Z","object_id":{"id":2650,"is_a":["categorization","keyword","keyword_task"],"name":"zotonic_topic_import","title":"Import","uri":"https:\/\/zotonic.com\/id\/2650"},"seq":5},{"created":"2026-10-13T15:15:43Z","object_id":{"id":2656,"is_a":["categorization","keyword","keyword_task"],"name":"zotonic_topic_schedule","title":"Schedule","uri":"https:\/\/zotonic.com\/id\/2656"},"seq":6},{"created":"2026-10-13T15:15:43Z","object_id":{"id":2667,"is_a":["categorization","keyword","keyword_data_type"],"name":"zotonic_topic_url","title":"URL","uri":"https:\/\/zotonic.com\/id\/2667"},"seq":7}],"predicate":{"id":308,"is_a":["meta","predicate"],"name":"subject","title":{"_type":"trans","tr":{"en":"Keyword"}},"uri":"http:\/\/purl.org\/dc\/elements\/1.1\/subject"}}},"id":3085,"is_a":["text","documentation","reference","module"],"links":[{"rel":"self","target":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/3085"},{"rel":"hub","target":"https:\/\/zotonic.com\/.zotonic\/websub"}],"medium":null,"medium_url":null,"name":"doc_module_mod_import_feed","page_url":{"en":"https:\/\/zotonic.com\/docs\/3085\/mod_import_feed","x-default":"https:\/\/zotonic.com\/docs\/3085\/mod_import_feed"},"preview_url":null,"resource":{"version":22,"pivot_location_lat":null,"title":"mod_import_feed","is_authoritative":true,"body":"<p>Discover RSS 2.0, RSS 1.0\/RDF and Atom feeds and automatically import articles and media.<\/p>\n<p>Administrator accounts cannot run imports. Select an enabled non-administrator account\nwith only the required import permissions. This is checked when saving settings and\nbefore polling, including for existing feeds whose account is later promoted to admin.<\/p>\n<h2>Setup and administration<\/h2>\n<p>Enable <strong>Import feeds<\/strong> in Modules and open <strong>Content &gt; Import feeds<\/strong>. The module\nrequires <code>mod_admin<\/code> and <code>mod_cron<\/code>. Enter a website or feed URL, select one of the\ndiscovered feeds, and review three example entries beside the import settings.\nDiscovery uses HTML alternate links and HTTP Link headers.<\/p>\n<p>Managing feeds requires <code>use<\/code> permission for <code>mod_import_feed<\/code>. New feeds default to the current editor. Administrators and users with <code>use<\/code> permission\nfor <code>mod_admin_identity<\/code> can select another enabled account with <strong>Select user<\/strong>.\nSaving records that account and its user groups for background imports; ordinary\nsettings edits preserve the selected account and saved groups. The worker checks that the\neditor is still enabled and uses the editor&#39;s current, bounded permissions. Resource,\nmedia and edge operations enforce their normal ACLs; imported HTML is sanitized.<\/p>\n<h2>Per-feed settings<\/h2>\n<p>Settings are stored in the feed table. There are no <code>m_config<\/code> options.<\/p>\n<table class=\"table\"><thead><tr><th>Setting<\/th><th>Behavior<\/th><\/tr><\/thead><tbody><tr><td>Import user<\/td><td>Defaults to the creator. Only administrators or users with full account access can select or change it.<\/td><\/tr><tr><td>Default category<\/td><td>An existing non-meta category; initially Article.<\/td><\/tr><tr><td>Content group<\/td><td>Available when <code>mod_content_groups<\/code> is enabled. Empty uses the site default.<\/td><\/tr><tr><td>Guess category<\/td><td>Match tags against existing category names or translated titles, case-insensitively; otherwise use the default category.<\/td><\/tr><tr><td>Default connections<\/td><td>Use Add connection to select a predicate and page. Remove entries from the list as needed, then save. Existing article connections are preserved.<\/td><\/tr><tr><td>Media<\/td><td>Dependent resources with depiction edges, the most important medium attached directly, or no media import.<\/td><\/tr><tr><td>Fetch using<\/td><td>Anonymous by default, or registered OAuth2 credentials for the import user and destination host.<\/td><\/tr><tr><td>Polling interval<\/td><td>5 to 10080 minutes; initially 60 minutes.<\/td><\/tr><tr><td>Authority<\/td><td>Non-authoritative by default; authoritative copies also retain source identities.<\/td><\/tr><tr><td>WordPress enrichment<\/td><td>Enabled initially in the admin form; use the anonymous public REST API for content, author, dates and featured media. Failures fall back to feed data.<\/td><\/tr><tr><td>Pause<\/td><td>Suspend automatic imports. New feeds are active unless saved paused.<\/td><\/tr><\/tbody><\/table>\n<p>Imports create published resources. Dependent media are created through <code>m_media<\/code>,\nwhich detects the MIME type and selects the appropriate media category.\nFor each inline image, the importer selects one\nvariant, preferring the largest declared <code>srcset<\/code> width or density, with <code>src<\/code> as\nfallback. Imported variants share one local medium and inline references are rewritten\nto its URL. WordPress featured-image variants reuse the original image. In attached\nmode, other inline images retain their source URLs.<\/p>\n<h2>Fetch authentication and development<\/h2>\n<p>Discovery can use the current user&#39;s registered OAuth2 consumer credentials.\nSaved feeds use their selected import user&#39;s credentials for previews and polling.\nTokens are resolved per destination host and port, only over HTTPS, and are never\nstored in feed settings. Missing credentials leave a request anonymous. Native\nimports save their fetch preference for core reimports and medium downloads.<\/p>\n<p>Development sites allow local destinations and self-signed TLS certificates.\nTransport, redirects and certificate checks use the shared <code>z_fetch<\/code> routines;\nbrowser input cannot change the server&#39;s environment. OAuth2 credentials are never\nsent over HTTP. Anonymous fetching remains anonymous across redirects.<\/p>\n<h2>Polling and identity<\/h2>\n<p>The minute tick starts a bounded background job for due feeds. Database leases prevent\nconcurrent claims. The overview shows article counts, cumulative import\/update\/skip\/error\nstatistics and poll times. Each feed has settings, pause\/resume, test\/preview, poll-now,\nreimport and paginated history for articles and dependent media.<\/p>\n<p>Stable source URIs and checksums allow repeated polls without duplicates. Reimport\nprocesses only entries currently present in the feed, preserving resource IDs. Deleted\nresources remain deleted. Media already imported from the same URL is reused. Feeds\nwith more than 100 entries are rejected, rather than silently importing a partial feed.\nWebSub hub links are recognized in feed data; feed fetching uses polling.<\/p>\n<h2>Zotonic resource feeds<\/h2>\n<p>Atom entries from <code>mod_export<\/code> advertise a JSON resource link with relation\n<code>https:\/\/zotonic.com\/rel\/resource<\/code>. These use <code>m_rsc_import<\/code>, preserving native\nproperties, categories, media embeds and connections. Connection import depth\ndefaults to 1 and accepts 0–10. Content-group\/copyright defaults and cleanup\npatterns apply; category guessing and media-layout choices do not reshape native\nresources. Choosing no media disables native medium downloads.<\/p>\n<p>With <code>mod_websub<\/code> enabled, optional subscriptions cover imported articles and,\nwhen selected, their connections within the import depth. Both options default\nto false and require non-authoritative imports and a supporting source. Existing\nsubscriptions are managed separately through WebSub administration. Native\nresources use the core Fetch new version flow and saved import options, without\nrequiring the entry to remain in the feed. These refreshes use the core import\nnotification with native resource source metadata.<\/p>\n<h2>Fetch new version<\/h2>\n<p>For ordinary feed entries, the <code>rsc_import_fetch<\/code> observer refreshes known imported articles from their current\nfeed, using the saved settings and import account. The caller needs feed-management\nand article-edit permission. Paused feeds can be refreshed manually without resuming\npolling. This bypasses unchanged checksums and still runs the import notification.\nAn article no longer present in the feed returns <code>feed_entry_not_found<\/code>; unknown\nURIs fall through to the standard resource importer.<\/p>\n<h2>Import notification<\/h2>\n<p>Before writing an entry or its media, the importer dispatches the core\n<code>#import_resource{item, related, source, options, raw}<\/code> notification. The source\nis <code>#{importer =&gt; mod_import_feed, feed =&gt; Settings}<\/code>. Include\n<code>zotonic_core\/include\/zotonic.hrl<\/code>, declare <code>zotonic_observer<\/code>, and implement\n<code>observe_import_resource\/2<\/code> or its optional PID-aware variant. See the core\nobserver documentation for the payload, permissions and result contract.<\/p>\n<p>Unchanged and deleted entries are skipped before notifying. Native feed entries\nnotify once; their delegation to <code>m_rsc_import<\/code> preserves this scope, while\nrecursively imported resources may generate separate notifications.<\/p>","slug":"mod_import_feed","doc_module_config":[],"is_protected":false,"visible_for":0,"tz":"UTC","language":["en"],"doc_source_hash":"63949bdb402fb4881e35f2d02367d8ed02d99b009a08a56e8aaa37f974cbb268","is_featured":false,"content_group_id":{"id":2551,"is_a":["meta","content_group"],"name":"content_group_imported_docs","title":"Imported documentation","uri":"https:\/\/zotonic.com\/id\/content_group_imported_docs"},"category_id":{"id":320,"is_a":["meta","category"],"name":"module","title":"Modules","uri":"https:\/\/test.zotonic.com\/id\/320"},"doc_source_path":"apps\/zotonic_mod_import_feed\/src\/mod_import_feed.erl","publication_start":"2026-10-13T15:15:42Z","github_url":"https:\/\/github.com\/zotonic\/zotonic\/blob\/master\/apps\/zotonic_mod_import_feed\/src\/mod_import_feed.erl","pivot_location_lng":null,"doc_source_kind":"module","name":"doc_module_mod_import_feed","is_unfindable":false,"is_published":true,"pivot_geocode":null,"created":"2026-10-13T15:15:42Z","uri":null,"doc_status":"current","is_dependent":false,"erlang_app":"zotonic_mod_import_feed","publication_end":"9999-06-01T00:00:00Z","modifier_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"privacy":0,"doc_source_commit":"92d27433689eef55504265c6dd5486c65dd73483\n","creator_id":{"id":1,"is_a":["person"],"name":"administrator","title":"Site Administrator","uri":"https:\/\/zotonic.com\/id\/1"},"modified":"2026-10-13T15:40:16Z","title_slug":"mod_import_feed"},"uri":"https:\/\/zotonic.com\/id\/3085","uri_template":"https:\/\/zotonic.com\/id\/:id","websub":{"hub":"https:\/\/zotonic.com\/.zotonic\/websub","topic":"https:\/\/zotonic.com\/.zotonic\/websub\/topic\/3085"}},"status":"ok"}