aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Powers <mark@marks.kitchen>2022-12-30 13:58:20 -0600
committerMark Powers <mark@marks.kitchen>2022-12-30 13:58:20 -0600
commit3bdc11a9b2c78f2be8c11d28befce7328b6e5424 (patch)
tree98a88b435bf14f71a28537a0e5c8e052ab58a78c
parentb5c10718ddeaa8fcac368515ca150705b1a2c5ab (diff)
Improve RSS preview
-rw-r--r--content_scripts/bridges/instagram.js2
-rw-r--r--content_scripts/bridges/twitter.js10
-rw-r--r--content_scripts/bridges/youtube.js9
-rw-r--r--content_scripts/cs.js75
-rw-r--r--content_scripts/rss_bridge.js20
-rw-r--r--content_scripts/scraper.js35
-rw-r--r--manifest.json6
-rw-r--r--popup/index.js191
-rw-r--r--popup/main.html7
9 files changed, 200 insertions, 155 deletions
diff --git a/content_scripts/bridges/instagram.js b/content_scripts/bridges/instagram.js
index 0ced06a..18988b9 100644
--- a/content_scripts/bridges/instagram.js
+++ b/content_scripts/bridges/instagram.js
@@ -7,4 +7,4 @@ async function get_insta() {
let feed_url = `${base_url}/?action=display&bridge=Instagram&context=Username&u=${uid}&media_type=all&format=`;
return get_all_types(feed_url)
}
-
+register(["instagram"], get_insta)
diff --git a/content_scripts/bridges/twitter.js b/content_scripts/bridges/twitter.js
index e9855cb..1ffa131 100644
--- a/content_scripts/bridges/twitter.js
+++ b/content_scripts/bridges/twitter.js
@@ -4,9 +4,15 @@ function get_twitter() {
let match = url.match(pattern);
if (match) {
let twitter_handle = match[1]
+
let feed_url = `${base_url}/?action=display&bridge=Twitter&context=By+username&u=${twitter_handle}&format=`
- return get_all_types(feed_url)
+ let feeds = get_all_types(feed_url)
+
+ let feed_url_norep = `${base_url}/?action=display&bridge=Twitter&context=By+username&u=${twitter_handle}&norep=on&format=`
+ let feeds_norep = get_all_types(feed_url, "no replies")
+
+ return feeds.concat(feeds_norep)
}
return []
}
-
+register(["twitter"], get_twitter)
diff --git a/content_scripts/bridges/youtube.js b/content_scripts/bridges/youtube.js
index 202873b..e6b584c 100644
--- a/content_scripts/bridges/youtube.js
+++ b/content_scripts/bridges/youtube.js
@@ -31,7 +31,7 @@ async function get_youtube() {
let patternListInVideo = /youtube.com\/watch\?v=\w+\&list=(\w+)/
let matchListInVideo = url.match(patternListInVideo)
- if(matchListInVideo){
+ if(matchListInVideo && matchListInVideo[1]){
let playlistId = matchListInVideo[1]
let playlist_feed_url = `${base_url}/?action=display&bridge=Youtube&context=By+playlist+Id&p=${playlistId}&duration_min=&duration_max=&format=`
let native_url = get_native_playlist_feed(playlistId)
@@ -41,17 +41,17 @@ async function get_youtube() {
return feeds
}
- if (matchUser) {
+ if (matchUser && matchUser[1]) {
let user = matchUser[1];
let feed_url = `${base_url}/?action=display&bridge=Youtube&context=By+username&u=${user}&duration_min=&duration_max=&format=`
return get_all_types(feed_url)
}
- if (matchChannel) {
+ if (matchChannel && matchChannel[1]) {
let channelId = matchChannel[1]
let feed_url = `${base_url}/?action=display&bridge=Youtube&context=By+channel+id&c=${channelId}&duration_min=&duration_max=&format=`
return get_all_types(feed_url)
}
- if (matchPlaylist) {
+ if (matchPlaylist && matchPlaylist[1]) {
let playlistId = matchPlaylist[1]
let native_url = get_native_playlist_feed(playlistId)
let feed_url = `${base_url}/?action=display&bridge=Youtube&context=By+playlist+Id&p=${playlistId}&duration_min=&duration_max=&format=`
@@ -61,3 +61,4 @@ async function get_youtube() {
return []
}
+register(["youtube"], get_youtube)
diff --git a/content_scripts/cs.js b/content_scripts/cs.js
index e57176b..6b66d92 100644
--- a/content_scripts/cs.js
+++ b/content_scripts/cs.js
@@ -1,86 +1,29 @@
var base_url = undefined
-let formats = ["Atom", "Mrss", "Html"]
-let types = {
- 'application/rss+xml': "rss",
- 'application/atom+xml': "atom",
- 'application/rdf+xml': "rdf",
- 'application/rss': "rss",
- 'application/atom': "atom",
- 'application/rdf': "rdf",
- 'text/rss+xml': "rss",
- 'text/atom+xml': "atom",
- 'text/rdf+xml': "rdf",
- 'text/rss': "rss",
- 'text/atom': "atom",
- 'text/rdf': "rdf"
-}
-
-
-function find_links_in_page() {
- let links = document.querySelectorAll('link[type]');
- let feeds = [];
- for (let i = 0; i < links.length; i++) {
- if (links[i].hasAttribute('type') && links[i].getAttribute('type') in types) {
- let title = links[i].getAttribute('title')
- let href = links[i].getAttribute('href')
- let feed_url = new URL(href, window.location.href).href
- let type = types[links[i].getAttribute('type')]
- let feed = {
- type: `native: ${title || type}`,
- url: feed_url,
- };
- feeds.push(feed);
- }
- }
- return feeds
-}
-
-function get_all_types(feed_url, note) {
- let feeds = [];
- formats.forEach(el => {
- if(note){
- feeds.push({
- type: `rss-bridge (${note}): ${el}`,
- url: feed_url + el
- });
- } else {
- feeds.push({
- type: `rss-bridge: ${el}`,
- url: feed_url + el
- });
- }
- })
- return feeds;
-}
-
-let objs = []
+// Get the list of all feeds, combining bridged and native feeds
async function get_feed_urls() {
let settings = await browser.storage.sync.get("rb");
base_url = settings.rb;
let all_feed_urls = []
- let host = window.location.host;
- for (const obj of objs) {
- for (const obj_host of obj.hosts) {
- if (host.includes(obj_host)) {
- result = await obj.callback()
+ for (const bridge of bridges) {
+ for (const host of bridge.hosts) {
+ if (window.location.host.includes(host)) {
+ result = await bridge.callback()
all_feed_urls = all_feed_urls.concat(result)
break
}
}
}
- all_feed_urls = all_feed_urls.concat(find_links_in_page())
+ all_feed_urls = all_feed_urls.concat(find_feeds_in_page())
return all_feed_urls
}
+// Function to register a new bridge
+let bridges = []
function register(hosts, callback) {
- objs.push({hosts, callback})
+ bridges.push({hosts, callback})
}
-register(["instagram"], get_insta)
-register(["twitter"], get_twitter)
-register(["youtube"], get_youtube)
-
browser.runtime.onMessage.addListener(function (msg, sender) {
return Promise.resolve(get_feed_urls());
})
diff --git a/content_scripts/rss_bridge.js b/content_scripts/rss_bridge.js
new file mode 100644
index 0000000..ac591bd
--- /dev/null
+++ b/content_scripts/rss_bridge.js
@@ -0,0 +1,20 @@
+let formats = ["Atom", "Mrss"]
+function get_all_types(feed_url, note) {
+ let feeds = [];
+ formats.forEach(el => {
+ if(note){
+ feeds.push({
+ type: el,
+ name: `rss-bridge (${note}): ${el}`,
+ url: feed_url + el
+ });
+ } else {
+ feeds.push({
+ type: el,
+ name: `rss-bridge: ${el}`,
+ url: feed_url + el
+ });
+ }
+ })
+ return feeds;
+}
diff --git a/content_scripts/scraper.js b/content_scripts/scraper.js
new file mode 100644
index 0000000..51043c3
--- /dev/null
+++ b/content_scripts/scraper.js
@@ -0,0 +1,35 @@
+let types = {
+ 'application/rss+xml': "rss",
+ 'application/atom+xml': "atom",
+ 'application/rdf+xml': "rdf",
+ 'application/rss': "rss",
+ 'application/atom': "atom",
+ 'application/rdf': "rdf",
+ 'text/rss+xml': "rss",
+ 'text/atom+xml': "atom",
+ 'text/rdf+xml': "rdf",
+ 'text/rss': "rss",
+ 'text/atom': "atom",
+ 'text/rdf': "rdf"
+}
+
+// Scrape feed links from DOM
+function find_feeds_in_page() {
+ let links = document.querySelectorAll('link[type]');
+ let feeds = [];
+ for (let i = 0; i < links.length; i++) {
+ if (links[i].hasAttribute('type') && links[i].getAttribute('type') in types) {
+ let title = links[i].getAttribute('title')
+ let href = links[i].getAttribute('href')
+ let feed_url = new URL(href, window.location.href).href
+ let type = types[links[i].getAttribute('type')]
+ let feed = {
+ name: `native: ${title || type}`,
+ type: type,
+ url: feed_url,
+ };
+ feeds.push(feed);
+ }
+ }
+ return feeds
+}
diff --git a/manifest.json b/manifest.json
index a98c9d8..0e84d52 100644
--- a/manifest.json
+++ b/manifest.json
@@ -10,10 +10,12 @@
"https://*/*"
],
"js": [
+ "content_scripts/cs.js",
+ "content_scripts/rss_bridge.js",
+ "content_scripts/scraper.js",
"content_scripts/bridges/youtube.js",
"content_scripts/bridges/twitter.js",
- "content_scripts/bridges/instagram.js",
- "content_scripts/cs.js"
+ "content_scripts/bridges/instagram.js"
]
}
],
diff --git a/popup/index.js b/popup/index.js
index c674f39..4944e9f 100644
--- a/popup/index.js
+++ b/popup/index.js
@@ -8,114 +8,149 @@ function subscribe_link(reader, feed_url){
}
}
+function insertElementsIntoRow(rowElement, elements){
+ let tdElement = document.createElement("td")
+ elements.forEach( el => tdElement.append(el))
+ rowElement.append(tdElement)
+}
+
+function insertElementIntoRow(rowElement, element){
+ let tdElement = document.createElement("td")
+ tdElement.append(element)
+ rowElement.append(tdElement)
+}
+
+function wrapInDiv(element){
+ let wrapperDiv = document.createElement("div")
+ wrapperDiv.append(element)
+ return wrapperDiv
+}
+
+let itemMap = {
+ "updated": "pubDate",
+ "summary": "description",
+}
+function parseCollection(collection, entries){
+ for(const child of collection){
+ feedEntry = {"link": "", "title": "", "pubDate": "", "description": ""}
+ for(const c of child.children){
+ if(c.tagName == "link" && c.getAttribute("href")){
+ feedEntry["link"] = c.getAttribute("href")
+ } else {
+ feedEntry[c.tagName] = c.innerHTML
+ }
+ }
+ // Copy keys to normalized version
+ for(const key in itemMap){
+ if(feedEntry[key]){
+ feedEntry[itemMap[key]] = feedEntry[key]
+ }
+ }
+ entries.push(feedEntry)
+ }
+}
+
+function previewOnclick(item){
+ return function(){
+ fetch(item.url)
+ .then( r => r.text() )
+ .then(r => new window.DOMParser().parseFromString(r, "text/xml"))
+ .then(p => {
+ let entries = []
+ parseCollection(p.getElementsByTagName("entry"), entries)
+ parseCollection(p.getElementsByTagName("item"), entries)
+
+ let tableEl = document.createElement("table")
+ tableEl.classList.add("preview")
+ entries.forEach(entry => {
+ let trEl = document.createElement("tr")
+ tableEl.append(trEl)
+
+ let titleEl = document.createElement("a")
+ titleEl.href = entry["link"]
+ titleEl.innerHTML = entry["title"]
+
+ let wrapperDiv2 = document.createElement("div")
+ wrapperDiv2.innerText = entry["pubDate"]
+
+ insertElementsIntoRow(trEl, [
+ wrapInDiv(titleEl), wrapperDiv2
+ ])
+
+ let td3El = document.createElement("td")
+ td3El.innerHTML = entry["description"]
+ trEl.append(td3El)
+ })
+ feeds.append(tableEl)
+ })
+ }
+}
+
window.onload = async function () {
let settings = await browser.storage.sync.get(["rb", "reader", "instance"]);
base_reader = settings.instance;
let base_rb = settings.rb;
- let feeds = document.getElementById('feeds');
- feeds.innerText = "Loading..."
+ let feedsElement = document.getElementById('feeds');
+ feedsElement.innerText = "Loading..."
browser.tabs.query({ active: true, currentWindow: true }, function (tabs) {
browser.tabs.sendMessage(tabs[0].id, {}).then(
- function (feed_urls) {
- feeds.innerText = ""
+ function (feeds) {
+ feedsElement.innerText = ""
if(!base_rb) {
let newSettingsLink = document.createElement("a")
newSettingsLink["href"] = "/options.html"
newSettingsLink.innerText = "RSS-bridge instance not set! Click here to open options.";
let newDiv = document.createElement('div');
newDiv.append(newSettingsLink);
- feeds.appendChild(newDiv);
+ feedsElement.appendChild(newDiv);
let newP = document.createElement('p')
- newP.innerText = `Found ${feed_urls.length} feeds`
- feeds.append(newP)
+ newP.innerText = `Found ${feeds.length} feeds`
+ feedsElement.append(newP)
return;
}
- feed_urls.forEach(item => {
- let newLink = document.createElement('a');
- newLink["href"] = item.url
- newLink.innerText = item.type;
-
+ let table = document.createElement("table")
+ table.classList.add("feeds")
+ feedsElement.append(table)
+ feeds.forEach(feed => {
+ let newRow = document.createElement("tr")
+ table.append(newRow)
- let newDiv = document.createElement('div');
- newDiv.append(newLink)
+ let newLink = document.createElement('a');
+ newLink["href"] = feed.url
+ newLink.innerText = feed.name;
+ insertElementIntoRow(newRow, newLink)
let previewLink = document.createElement('a');
- previewLink["onclick"] = function(){
- fetch(item.url)
- .then( r => r.text() )
- .then(r => new window.DOMParser().parseFromString(r, "text/xml"))
- .then(p => {
- let channelTitle = "Items"
- let description = undefined
- let items = []
- let lastBuild = undefined
- console.log(p.firstChild.children)
- for(const channel of p.firstChild.children) {
- //p.firstChild.children.forEach(channel => {
- for(const child of channel.children) {
- //channel.children.forEach(child => {
- if(child.tagName == "title"){
- channelTitle = child.textContent
- } else if (child.tagName == "lastBuildDate") {
- lastBuild = child.textContent
- } else if (child.tagName == "description") {
- description = child.textContent
- } else if (child.tagName == "item") {
- item = {}
- for(const c of child.children){
- //child.children.forEach(c => {
- item[c.tagName] = c.innerHTML
- }
- items.push(item)
- }
- }
- }
- console.log(items)
- let tableEl = document.createElement("table")
- items.forEach(item => {
- let trEl = document.createElement("tr")
- tableEl.append(trEl)
-
- let tdEl = document.createElement("td")
-
- let titleEl = document.createElement("a")
- titleEl.href = item["link"]
- titleEl.innerText = item["title"]
- let wrapperDiv = document.createElement("div")
- wrapperDiv.append(titleEl)
- let wrapperDiv2 = document.createElement("div")
- wrapperDiv2.innerText = item["pubDate"]
- tdEl.append(wrapperDiv)
- tdEl.append(wrapperDiv2)
- trEl.append(tdEl)
-
- let td3El = document.createElement("td")
- td3El.innerHTML = item["description"]
- trEl.append(td3El)
-
- })
- feeds.append(tableEl)
- })
- }
+ previewLink["onclick"] = previewOnclick(feed)
previewLink["href"] = "#"
previewLink.innerText = "preview";
- newDiv.append(previewLink)
+
+ let newPreviewData = document.createElement("td")
+ // Preview only works for XML feeds
+ if(
+ feed.type.toLowerCase().includes("rss") ||
+ feed.type.toLowerCase().includes("xml") ||
+ feed.type.toLowerCase().includes("atom")
+ ){
+ newPreviewData.append(previewLink)
+ }
+ newRow.append(newPreviewData)
if(base_reader){
let subLink = document.createElement('a');
- subLink["href"] = subscribe_link(settings.reader, item.url)
+ subLink["href"] = subscribe_link(settings.reader, feed.url)
subLink.innerText = "subscribe";
- newDiv.append(subLink)
+ let newSubData = document.createElement("td")
+ newSubData.append(subLink)
+ newRow.append(newSubData)
}
-
- feeds.append(newDiv)
})
- if(feed_urls.length == 0) {
+ if(feeds.length == 0) {
let newP = document.createElement('p')
newP.innerText = "No feeds found"
- feeds.append(newP)
+ feedsElement.append(newP)
}
});
});
diff --git a/popup/main.html b/popup/main.html
index 81f8f06..6c57d10 100644
--- a/popup/main.html
+++ b/popup/main.html
@@ -6,12 +6,15 @@
div a {
margin: 1em;
}
- table td a {
+ table.preview td a {
margin: 0em;
}
- td {
+ table.preview td {
border: 1px solid black;
}
+ table.feeds tr td {
+ //border-bottom: 1px solid black;
+ }
</style>
</head>
<body>