Skip to content

Commit

Permalink
Fix adding new vimeo embeds
Browse files Browse the repository at this point in the history
  • Loading branch information
nygrenh committed Oct 3, 2024
1 parent 4a893f0 commit 0d0803b
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 9 deletions.
3 changes: 1 addition & 2 deletions services/cms/src/styles/Gutenberg/editor-styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@
// This height is same as the headless-lms oembed proxy maxheight=440.
iframe[title="Embedded content from youtube.com"],
//For youtube shortlink
iframe[title="Embedded content from youtu"],
iframe[title="Embedded content from vimeo"] {
iframe[title="Embedded content from youtu"] {
height: 440px;
}

Expand Down
17 changes: 15 additions & 2 deletions services/headless-lms/server/src/controllers/cms/gutenberg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::time::Duration;

use headless_lms_utils::url_to_oembed_endpoint::{
mentimeter_oembed_response_builder, thinglink_oembed_response_builder, url_to_oembed_endpoint,
OEmbedRequest, OEmbedResponse,
vimeo_oembed_response_builder, OEmbedRequest, OEmbedResponse,
};
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -175,6 +175,18 @@ async fn get_thinglink_oembed_data(
token.authorized_ok(web::Json(response))
}

#[instrument(skip(app_conf))]
async fn get_vimeo_oembed_data(
query_params: web::Query<OEmbedRequest>,
app_conf: web::Data<ApplicationConfiguration>,
pool: web::Data<PgPool>,
) -> ControllerResult<web::Json<OEmbedResponse>> {
let token = skip_authorize();
let url = query_params.url.to_string();
let response = vimeo_oembed_response_builder(url, app_conf.base_url.to_string())?;
token.authorized_ok(web::Json(response))
}

/**
Add a route for each controller in this module.
Expand All @@ -195,5 +207,6 @@ pub fn _add_routes(cfg: &mut ServiceConfig) {
.route(
"/oembed/thinglink",
web::get().to(get_thinglink_oembed_data),
);
)
.route("/oembed/vimeo", web::get().to(get_vimeo_oembed_data));
}
101 changes: 96 additions & 5 deletions services/headless-lms/utils/src/url_to_oembed_endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,11 @@ pub fn url_to_oembed_endpoint(url: String, base_url: Option<String>) -> UtilResu
}
if host.ends_with("vimeo.com") {
return oembed_url_builder(
"https://vimeo.com/api/oembed.json",
&format!("url={}&maxwidth=780&maxheight=440", url),
&format!("{}/api/v0/cms/gutenberg/oembed/vimeo", base_url.unwrap()),
&format!(
"url={}",
utf8_percent_encode(url.as_str(), NON_ALPHANUMERIC)
),
);
}
if host.ends_with("menti.com") || host.ends_with("mentimeter.com") {
Expand Down Expand Up @@ -140,7 +143,13 @@ pub fn mentimeter_oembed_response_builder(
url: String,
base_url: String,
) -> UtilResult<OEmbedResponse> {
let mut parsed_url = Url::parse(url.as_str()).unwrap();
let mut parsed_url = Url::parse(url.as_str()).map_err(|e| {
UtilError::new(
UtilErrorType::UrlParse,
"Failed to parse url".to_string(),
Some(e.into()),
)
})?;
// Get the height and title params
let params: HashMap<_, _> = parsed_url.query_pairs().into_owned().collect();
// We want to remove the query params so that the iframe src url doesn't have them
Expand Down Expand Up @@ -178,7 +187,13 @@ pub fn thinglink_oembed_response_builder(
url: String,
base_url: String,
) -> UtilResult<OEmbedResponse> {
let mut parsed_url = Url::parse(url.as_str()).unwrap();
let mut parsed_url = Url::parse(url.as_str()).map_err(|e| {
UtilError::new(
UtilErrorType::UrlParse,
"Failed to parse url".to_string(),
Some(e.into()),
)
})?;
// Get the height and title params
let params: HashMap<_, _> = parsed_url.query_pairs().into_owned().collect();
// We want to remove the query params so that the iframe src url doesn't have them
Expand All @@ -196,7 +211,7 @@ pub fn thinglink_oembed_response_builder(
author_name: "Mooc.fi".to_string(),
author_url: base_url,
html: format!(
"<iframe sandbox=\"allow-scripts allow-same-origin\" src={} style='width: 99%;' height={:?} title={:?}></iframe>",
"<iframe sandbox=\"allow-scripts allow-same-origin\" src=\"{}\" style=\"width: 99%;\" height={:?} title=\"{:?}\"></iframe>",
parsed_url,
params.get("height").unwrap_or(&"500".to_string()),
decoded_title
Expand All @@ -212,12 +227,76 @@ pub fn thinglink_oembed_response_builder(
Ok(response)
}

pub fn vimeo_oembed_response_builder(url: String, base_url: String) -> UtilResult<OEmbedResponse> {
let mut parsed_url = Url::parse(url.as_str()).map_err(|e| {
UtilError::new(
UtilErrorType::UrlParse,
"Failed to parse url".to_string(),
Some(e.into()),
)
})?;
// Get the height and title params
let params: HashMap<_, _> = parsed_url.query_pairs().into_owned().collect();
// We want to remove the query params so that the iframe src url doesn't have them
parsed_url.set_query(None);
let decoded_title =
percent_decode_str(params.get("title").unwrap_or(&"Vimeo%20embed".to_string()))
.decode_utf8()
.expect("Decoding title or default value for vimeo embed failed")
.to_string();

let path = parsed_url.path();
let video_id = extract_numerical_id(path).ok_or_else(|| {
UtilError::new(
UtilErrorType::Other,
"Could not find video id from url".to_string(),
None,
)
})?;

let mut iframe_url = Url::parse("https://player.vimeo.com").map_err(|e| {
UtilError::new(
UtilErrorType::UrlParse,
"Failed to parse url".to_string(),
Some(e.into()),
)
})?;
iframe_url.set_path(&format!("/video/{}", video_id));
iframe_url.set_query(Some("app_id=122963"));

let response = OEmbedResponse {
author_name: "Mooc.fi".to_string(),
author_url: base_url,
html: format!(
"<iframe sandbox=\"allow-scripts allow-same-origin\" frameborder=\"0\" src=\"{}\" style=\"width: 99%;\" height={:?} title=\"{:?}\"></iframe>",
iframe_url,
params.get("height").unwrap_or(&"500".to_string()),
decoded_title
),
provider_name: "vimeo".to_string(),
provider_url: parsed_url
.host_str()
.unwrap_or("https://www.vimeo.com/")
.to_string(),
title: decoded_title,
version: "1.0".to_string(),
};
Ok(response)
}

fn oembed_url_builder(url: &str, query_params: &str) -> UtilResult<Url> {
let mut endpoint_url = Url::parse(url)?;
endpoint_url.set_query(Some(query_params));
Ok(endpoint_url)
}

fn extract_numerical_id(path: &str) -> Option<String> {
path.split('/')
.map(|o| o.trim())
.find(|segment| !segment.is_empty() && segment.chars().all(|c| c.is_ascii_digit()))
.map(|s| s.to_string())
}

#[cfg(test)]
mod tests {
use url::Url;
Expand Down Expand Up @@ -280,4 +359,16 @@ mod tests {
"http://project-331.local/api/v0/cms/gutenberg/oembed/thinglink?url=https%3A%2F%2Fwww%2Ethinglink%2Ecom%2Fcard%2F1205257932048957445"
)
}

#[test]
fn works_with_vimeo() {
assert_eq!(
url_to_oembed_endpoint(
"https://vimeo.com/275255674".to_string(),
Some("http://project-331.local".to_string())
)
.unwrap().to_string(),
"http://project-331.local/api/v0/cms/gutenberg/oembed/vimeo?url=https%3A%2F%2Fvimeo%2Ecom%2F275255674"
)
}
}

0 comments on commit 0d0803b

Please sign in to comment.