aboutsummaryrefslogtreecommitdiff
path: root/src/odysee.js
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2022-06-28 18:17:14 +0200
committerWojtek Kosior <koszko@koszko.org>2022-06-30 12:33:03 +0200
commitecc6c218af8ef864fe8d03badfed0e6e7c730fd0 (patch)
treed30ef4b7d74802204130e8a2af27938d0412ab04 /src/odysee.js
parentc6505d419b6c6a6207c6418ede107d00e6792015 (diff)
downloadhydrilla-fixes-bundle-ecc6c218af8ef864fe8d03badfed0e6e7c730fd0.tar.gz
hydrilla-fixes-bundle-ecc6c218af8ef864fe8d03badfed0e6e7c730fd0.zip
put each fix in a separate directory with its own index.json
This commit also updates the repository to use version 2 of package source schema.
Diffstat (limited to 'src/odysee.js')
-rw-r--r--src/odysee.js425
1 files changed, 0 insertions, 425 deletions
diff --git a/src/odysee.js b/src/odysee.js
deleted file mode 100644
index e0c6609..0000000
--- a/src/odysee.js
+++ /dev/null
@@ -1,425 +0,0 @@
-/**
- * SPDX-License-Identifier: LicenseRef-GPL-3.0-or-later-WITH-js-exceptions
- *
- * Make video playback and search on odysee.com functional without nonfree js
- *
- * Copyright (C) 2021 Wojtek Kosior <koszko@koszko.org>
- *
- * This program 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 3 of the License, or
- * (at your option) any later version.
- *
- * This program 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.
- *
- * As additional permission under GNU GPL version 3 section 7, you
- * may distribute forms of that code without the copy of the GNU
- * GPL normally required by section 4, provided you include this
- * license notice and, in case of non-source distribution, a URL
- * through which recipients can access the Corresponding Source.
- * If you modify file(s) with this exception, you may extend this
- * exception to your version of the file(s), but you are not
- * obligated to do so. If you do not wish to do so, delete this
- * exception statement from your version.
- *
- * As a special exception to the GPL, any HTML file which merely
- * makes function calls to this code, and for that purpose
- * includes it by reference shall be deemed a separate work for
- * copyright law purposes. If you modify this code, you may extend
- * this exception to your version of the code, but you are not
- * obligated to do so. If you do not wish to do so, delete this
- * exception statement from your version.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *
- * I, Wojtek Kosior, thereby promise not to sue for violation of this file's
- * license. Although I request that you do not make use of this code in a
- * proprietary program, I am not going to enforce this in court.
- */
-
-/* use with https://odysee.com/*** */
-
-/* Helper functions for ajax. */
-
-function ajax_callback(xhttp, cb)
-{
- cb(xhttp.response);
-}
-
-function perform_ajax(method, url, callback, err_callback, data)
-{
- const xhttp = new XMLHttpRequest();
- xhttp.onload = () => ajax_callback(xhttp, callback);
- xhttp.onerror = err_callback;
- xhttp.onabort = err_callback;
- xhttp.open(method, url, true);
- try {
- xhttp.send(data);
- } catch(e) {
- err_callback();
- }
-}
-
-/* Helper functions for strings with HTML entities (e.g. `&quot;'). */
-function HTML_decode(text)
-{
- const tmp_span = document.createElement("span");
- tmp_span.innerHTML = text;
- return tmp_span.textContent;
-}
-
-/* Odysee API servers. */
-
-const odysee_resolve_url = "https://api.na-backend.odysee.com/api/v1/proxy?m=resolve";
-const lighthouse_search_url = "https://lighthouse.odysee.com/search";
-
-/*
- * If we're on a video page, show the video. Use JSON data embedded in <head>
- * if possible. If not - fetch video data using Odysee API.
- */
-
-let data = null;
-
-function process_json_script(json_script)
-{
- try {
- data = JSON.parse(json_script.textContent);
- } catch (e) {
- console.log("Error parsing content data", e);
- }
-}
-
-for (const json_script of document.querySelectorAll("head script")) {
- if (["blocked-type", "type"].map(a => json_script.getAttribute(a))
- .includes("application/ld+json"))
- process_json_script(json_script);
-}
-
-const body = document.createElement("body");
-const video_container = document.createElement("div");
-
-body.appendChild(video_container);
-
-function show_video(content_url, title, upload_date, description)
-{
- if (content_url) {
- const video = document.createElement("video");
- const source = document.createElement("source");
-
- source.src = content_url;
-
- video.setAttribute("width", "100%");
- video.setAttribute("height", "auto");
- video.setAttribute("controls", "");
-
- video.appendChild(source);
-
- video_container.appendChild(video);
- }
-
- if (title) {
- const h1 = document.createElement("h1");
-
- h1.textContent = HTML_decode(title);
- h1.setAttribute("style", "color: #555;");
-
- video_container.appendChild(h1);
- }
-
- if (upload_date) {
- try {
- const date = new Date(upload_date).toString();
- const date_div = document.createElement("div");
-
- date_div.textContent = `Uploaded: ${date}`;
- date_div.setAttribute("style", "font-size: 14px; font-weight: bold; margin-bottom: 5px;");
-
- video_container.appendChild(date_div);
- } catch(e) {
- console.log("Error parsing content upload date", e);
- }
- }
-
- if (description) {
- const description_div = document.createElement("div");
-
- description_div.textContent = HTML_decode(description);
- description_div.setAttribute("style", "white-space: pre;");
-
- video_container.appendChild(description_div);
- }
-}
-
-function show_video_from_query(response)
-{
- try {
- var result = Object.values(JSON.parse(response).result)[0];
-
- if (result.value_type !== "stream")
- return;
-
- var date = result.timestamp * 1000;
- var description = result.value.description;
- var title = result.value.title;
- const name = encodeURIComponent(result.name);
- var url = `https://odysee.com/$/stream/${name}/${result.claim_id}`;
- } catch (e) {
- return;
- }
-
- show_video(url, title, date, description);
-}
-
-function fetch_show_video(name, claim_id)
-{
- const payload = {
- jsonrpc: "2.0",
- method: "resolve",
- params: {
- urls: [`lbry://${decodeURIComponent(name)}#${claim_id}`],
- include_purchase_receipt: true
- },
- id: Math.round(Math.random() * 10**14)
- };
-
- perform_ajax("POST", odysee_resolve_url, show_video_from_query,
- () => null, JSON.stringify(payload));
-}
-
-if (data && typeof data === "object" && data["@type"] === "VideoObject") {
- show_video(data.contentUrl, data.name, data.uploadDate, data.description);
-} else {
- const match = /\/([^/]+):([0-9a-f]+)$/.exec(document.URL);
- if (match)
- fetch_show_video(match[1], match[2]);
-}
-
-/* Show search. */
-
-const search_input = document.createElement("input");
-const search_submit = document.createElement("button");
-const search_form = document.createElement("form");
-const error_div = document.createElement("div");
-
-search_submit.textContent = "Search Odysee";
-
-search_form.setAttribute("style", "margin: 15px 0 0 0;");
-
-search_form.appendChild(search_input);
-search_form.appendChild(search_submit);
-
-error_div.textContent = "Failed to perform search :c";
-error_div.setAttribute("style", "display: none;");
-
-body.appendChild(search_form);
-body.appendChild(error_div);
-
-/* Replace the UI. */
-
-document.documentElement.replaceChild(body, document.body);
-
-/* Add the logic of performing search and showing results. */
-
-function show_error()
-{
- error_div.setAttribute("style", "color: #b44;");
-}
-
-function clear_error()
-{
- error_div.setAttribute("style", "display: none;");
-}
-
-let results_div = null;
-const load_more_but = document.createElement("button");
-
-load_more_but.textContent = "Load more";
-
-function show_search_entries(new_results_div, response)
-{
- try {
- var results = Object.values(JSON.parse(response).result);
- } catch (e) {
- console.log("Failed to parse search response :c",
- "Bad response format from api.na-backend.odysee.com.");
- show_error();
- return;
- }
-
- for (const result of results) {
- try {
- if (result.value_type !== "stream")
- continue;
-
- let channel_specifier = "";
- let channel_name = null;
- try {
- channel_name = result.signing_channel.name;
- const channel_name_enc = encodeURIComponent(channel_name);
- const channel_digit = result.signing_channel.claim_id[0];
- channel_specifier = `${channel_name_enc}:${channel_digit}`;
- } catch (e) {
- }
- const video_name = encodeURIComponent(result.name);
- const video_id = result.claim_id[0];
-
- const result_a = document.createElement("a");
- const thumbnail = document.createElement("img");
- const title_span = document.createElement("span");
- const uploader_div = document.createElement("div");
- const description_div = document.createElement("div");
-
- thumbnail.setAttribute("style", "width: 100px; height: auto;");
- thumbnail.setAttribute("alt", result.value.thumbnail.url);
- thumbnail.src = result.value.thumbnail.url;
-
- title_span.setAttribute("style", "font-weight: bold;");
- title_span.textContent = result.value.title;
-
- uploader_div.setAttribute("style", "margin-left: 5px; font-size: 21px; color: #555;");
- uploader_div.textContent = channel_name;
-
- description_div.setAttribute("style", "white-space: pre;");
- description_div.textContent = result.value.description;
-
- result_a.setAttribute("style", "display: block; width: 100%; text-decoration: none; color: #333; margin: 8px; border-style: solid; border-width: 3px 0 0 0; border-color: #7aa;");
- result_a.href = `https://odysee.com/${channel_specifier}/${video_name}:${video_id}`;
-
- if (result.value.thumbnail.url)
- result_a.appendChild(thumbnail);
- result_a.appendChild(title_span);
- if (channel_name)
- result_a.appendChild(uploader_div);
- result_a.appendChild(description_div);
-
- new_results_div.appendChild(result_a);
- }
- catch(e) {
- console.log(e);
- }
- }
-
- clear_error();
-
- if (results_div)
- results_div.remove();
-
- results_div = new_results_div;
-
- body.appendChild(results_div);
- body.appendChild(load_more_but);
-
- enable_search_form();
-}
-
-function search_ajax_error(url)
-{
- console.log(`Failed to query ${url} :c`);
- show_error();
- enable_search_form();
-}
-
-function get_detailed_search_entries(new_results_div, response)
-{
- /* TODO: Simplify JSON handling using JSON schemas. */
- try {
- var response_data = JSON.parse(response);
- if (!Array.isArray(response_data))
- throw "Bad response format from lighthouse.odysee.com.";
- } catch (e) {
- show_error();
- console.log("Failed to parse search response :c", e);
- enable_search_form();
- return;
- }
-
- const callback = r => show_search_entries(new_results_div, r);
- const lbry_urls = [];
-
- for (const search_result of response_data) {
- if (!search_result.claimId || !search_result.name)
- continue;
- lbry_urls.push(`lbry://${search_result.name}#${search_result.claimId}`);
- }
-
- const payload = {
- jsonrpc: "2.0",
- method: "resolve",
- params: {
- urls: lbry_urls,
- include_purchase_receipt: true
- },
- id: Math.round(Math.random() * 10**14)
- };
-
- const url = odysee_resolve_url;
-
- perform_ajax("POST", url, callback, () => search_ajax_error(url),
- JSON.stringify(payload));
-}
-
-function get_search_entries(new_results_div, query, from)
-{
- const callback = r => get_detailed_search_entries(new_results_div, r);
- const url = `${lighthouse_search_url}?s=${encodeURIComponent(query)}&size=20&from=${from}&claimType=file,channel&nsfw=false&free_only=true`;
-
- new_results_div.setAttribute("data-fetched", parseInt(from) + 20);
-
- perform_ajax("GET", url, callback, () => search_ajax_error(url));
-}
-
-function search(event)
-{
- if (event)
- event.preventDefault();
-
- if (!/[^\s]/.test(search_input.value))
- return;
-
- disable_search_form();
-
- const new_results_div = document.createElement("div");
-
- new_results_div.setAttribute("data-query", search_input.value);
-
- get_search_entries(new_results_div, search_input.value, 0);
-}
-
-function search_more()
-{
- disable_search_form();
-
- get_search_entries(results_div, results_div.getAttribute("data-query"),
- results_div.getAttribute("data-fetched"));
-}
-
-load_more_but.addEventListener("click", search_more);
-
-function enable_search_form()
-{
- search_form.addEventListener("submit", search);
- search_submit.removeAttribute("disabled");
- if (results_div)
- load_more_but.removeAttribute("disabled");
-}
-
-function disable_search_form()
-{
- search_form.removeEventListener("submit", search);
- search_submit.setAttribute("disabled", "");
- load_more_but.setAttribute("disabled", "");
-}
-
-
-enable_search_form();
-
-
-const match = /^[^?]*search\?q=([^&]+)/.exec(document.URL)
-if (match) {
- search_input.value = decodeURIComponent(match[1]);
- search();
-}