Skip to content

Instantly share code, notes, and snippets.

@schoeffm
Last active October 25, 2020 08:45
Show Gist options
  • Save schoeffm/fe6a7bdf9af159f6877917c5a51b11aa to your computer and use it in GitHub Desktop.
Save schoeffm/fe6a7bdf9af159f6877917c5a51b11aa to your computer and use it in GitHub Desktop.
Scriptable approach to have a HuffDuffIt-ShareSheet entry
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: orange; icon-glyph: headphones;
// share-sheet-inputs: url;
// this script is supposed to be used as an action-extension
if (! config.runsInActionExtension && ! config.runsInApp) {
await warn('No Arguments given',
'This script can only be used as an Action-Extension where a URL is passed down to it');
Script.complete();
}
// take the url which were passed to the script
let url = (args.urls.length > 0) ? args.urls[0] : 'https://changelog.com'
// load the page and find all sound-file references in there
const info = await extractStreamInfosFrom(url);
let selection;
if (info.episodes.length > 1) {
// in case there are more than one file referenced in the page ... show a selection dialo
let listWidget = await createSelectionTable(info);
await listWidget.present(false);
// once the user selected one entry ... huffduff that entry
await huffduffit(selection.title, selection.episode);
} else if (info.episodes.length === 1) {
// we there was only one episode-reference contained in the page ... directly huffduff it
await huffduffit(info.title, info.episodes[0]);
} else {
// if there was no sound-file at all ... tell the user
await warn('No Audio File Found',
`Apparently there\'s no suitable audio file contained in the given web-page ${url}`);
}
Script.complete();
/**
* Takes the given url (as a string) and fetches the content of the respective page.
* After that, it'll look for all kinds of sound files (mp3, m4a, ogg, oga, opus) and
* extracts the URL-references to that files. Along with that sound-file-references
* the method is looking for some kind of title (basically a h1-tag) and tries at least
* to extract that as well (in order to make a title-suggestion).
*/
async function extractStreamInfosFrom(url) {
let req = new Request(url);
let content = await req.loadString();
let titleExp = new RegExp(/<h1.*>\s*(.*)\s*<.*h1>/g);
let titleMatches = titleExp.exec(content);
let title = (titleMatches) ? titleMatches[1].trim() : '';
let streams = content.match(/https?:\/\/.*?\.(mp3|opus|oga|ogg|m4a)/g)
if(streams) {
streams = streams
.filter((a, b) => streams.indexOf(a) === b);
return { title, episodes: streams }
} else {
return { title, episodes: [] }
}
}
/**
* A quick and simple table-view where the user can pick one of the given items.
* Notice: I had some strange behavior with the `onSelect`-handler. I wasn't able to
* directly trigger the `huffduffit`-WebView from that callback. Hence, I
* now set a global variable which is used after the UITable-View was
* dismissed. That works
*/
async function createSelectionTable(item) {
let table = new UITable();
for (episode of item.episodes) {
let row = new UITableRow();
let episodeCell = row.addText((episode.indexOf('/') > 0)
? episode.substring(episode.lastIndexOf('/') + 1)
: episode);
row.height = 60
row.cellSpacing = 10
row.dismissOnSelect = true;
row.onSelect = (idx) => selection = { title: item.title, episode };
table.addRow(row);
}
return table;
}
/**
* The actual call to huffduff a file ... it actually only calls the add-huffduff
* popup in order to reuse auth-info stored in the browser
*/
async function huffduffit(title, url) {
let webView = new WebView();
await webView.loadURL(`https://huffduffer.com/add?popup=true&bookmark[url]=${url}&bookmark[title]=${encodeURI(title)}`);
return webView.present(false);
}
/**
* Small helper to show a warning-notification
*/
async function warn(title, message) {
let nothingFoundAlert = new Alert();
nothingFoundAlert.title = title;
nothingFoundAlert.message = message;
return nothingFoundAlert.presentAlert();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment