fix: instantiate deobfuscator in mapresponse fn

Reason: quickjs context is not Send
This commit is contained in:
ThetaDev 2023-02-08 12:28:30 +01:00
parent d9e07b37e6
commit ee5e82f6bb
17 changed files with 74 additions and 84 deletions

View file

@ -162,7 +162,7 @@ impl MapResponse<Channel<Paginator<VideoItem>>> for response::Channel {
self,
id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Channel<Paginator<VideoItem>>>, ExtractionError> {
let content = map_channel_content(self.contents, self.alerts)?;
@ -202,7 +202,7 @@ impl MapResponse<Channel<Paginator<PlaylistItem>>> for response::Channel {
self,
id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Channel<Paginator<PlaylistItem>>>, ExtractionError> {
let content = map_channel_content(self.contents, self.alerts)?;
@ -236,7 +236,7 @@ impl MapResponse<Channel<ChannelInfo>> for response::Channel {
self,
id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Channel<ChannelInfo>>, ExtractionError> {
let content = map_channel_content(self.contents, self.alerts)?;
let channel_data = map_channel(

View file

@ -35,7 +35,7 @@ use tokio::sync::RwLock;
use crate::{
cache::{CacheStorage, FileStorage},
deobfuscate::{DeobfData, Deobfuscator},
deobfuscate::DeobfData,
error::{Error, ExtractionError},
param::{Country, Language},
report::{FileReporter, Level, Report, Reporter},
@ -706,20 +706,19 @@ impl RustyPipe {
}
/// Instantiate a new deobfuscator from either cached or extracted YouTube JavaScript code.
async fn get_deobf(&self) -> Result<Deobfuscator, Error> {
async fn get_deobf_data(&self) -> Result<DeobfData, Error> {
// Write lock here to prevent concurrent tasks from fetching the same data
let mut deobf_data = self.inner.cache.deobf.write().await;
match deobf_data.get() {
Some(deobf_data) => Ok(Deobfuscator::new(deobf_data.clone())?),
Some(deobf_data) => Ok(deobf_data.clone()),
None => {
log::debug!("getting deobfuscator");
let data = DeobfData::download(self.inner.http.clone()).await?;
let new_deobf = Deobfuscator::new(data.clone())?;
*deobf_data = CacheEntry::from(data);
let new_data = DeobfData::download(self.inner.http.clone()).await?;
*deobf_data = CacheEntry::from(new_data.clone());
drop(deobf_data);
self.store_cache().await;
Ok(new_deobf)
Ok(new_data)
}
}
}
@ -1027,7 +1026,7 @@ impl RustyPipeQuery {
id: &str,
endpoint: &str,
body: &B,
deobf: Option<&Deobfuscator>,
deobf: Option<&DeobfData>,
) -> Result<M, Error> {
log::debug!("getting {}({})", operation, id);
@ -1056,7 +1055,7 @@ impl RustyPipeQuery {
operation: format!("{operation}({id})"),
error,
msgs,
deobf_data: deobf.map(Deobfuscator::get_data),
deobf_data: deobf.cloned(),
http_request: crate::report::HTTPRequest {
url: request_url,
method: "POST".to_string(),
@ -1197,7 +1196,7 @@ trait MapResponse<T> {
self,
id: &str,
lang: Language,
deobf: Option<&Deobfuscator>,
deobf: Option<&DeobfData>,
) -> Result<MapResult<T>, ExtractionError>;
}

View file

@ -145,7 +145,7 @@ impl MapResponse<MusicArtist> for response::MusicArtist {
self,
id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<MusicArtist>, ExtractionError> {
let mapped = map_artist_page(self, id, lang, false)?;
Ok(MapResult {
@ -160,7 +160,7 @@ impl MapResponse<(MusicArtist, Vec<String>)> for response::MusicArtist {
self,
id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<(MusicArtist, Vec<String>)>, ExtractionError> {
map_artist_page(self, id, lang, true)
}
@ -328,7 +328,7 @@ impl MapResponse<Vec<AlbumItem>> for response::MusicArtistAlbums {
self,
id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Vec<AlbumItem>>, ExtractionError> {
// dbg!(&self);

View file

@ -59,7 +59,7 @@ impl MapResponse<MusicCharts> for response::MusicCharts {
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<crate::serializer::MapResult<MusicCharts>, crate::error::ExtractionError> {
let countries = self
.framework_updates

View file

@ -156,7 +156,7 @@ impl MapResponse<TrackDetails> for response::MusicDetails {
self,
id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<TrackDetails>, ExtractionError> {
let tabs = self
.contents
@ -232,7 +232,7 @@ impl MapResponse<Paginator<TrackItem>> for response::MusicDetails {
self,
_id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Paginator<TrackItem>>, ExtractionError> {
let tabs = self
.contents
@ -287,7 +287,7 @@ impl MapResponse<Lyrics> for response::MusicLyrics {
self,
_id: &str,
_lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Lyrics>, ExtractionError> {
let lyrics = self
.contents
@ -317,7 +317,7 @@ impl MapResponse<MusicRelated> for response::MusicRelated {
self,
_id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<MusicRelated>, ExtractionError> {
// Find artist
let artist_id = self

View file

@ -66,7 +66,7 @@ impl MapResponse<Vec<MusicGenreItem>> for response::MusicGenres {
self,
_id: &str,
_lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<crate::serializer::MapResult<Vec<MusicGenreItem>>, ExtractionError> {
let content = self
.contents
@ -119,7 +119,7 @@ impl MapResponse<MusicGenre> for response::MusicGenre {
self,
id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<crate::serializer::MapResult<MusicGenre>, ExtractionError> {
// dbg!(&self);

View file

@ -51,7 +51,7 @@ impl<T: FromYtItem> MapResponse<Vec<T>> for response::MusicNew {
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<crate::serializer::MapResult<Vec<T>>, ExtractionError> {
let items = self
.contents

View file

@ -104,7 +104,7 @@ impl MapResponse<MusicPlaylist> for response::MusicPlaylist {
self,
id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<MusicPlaylist>, ExtractionError> {
// dbg!(&self);
@ -242,7 +242,7 @@ impl MapResponse<MusicAlbum> for response::MusicPlaylist {
self,
id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<MusicAlbum>, ExtractionError> {
// dbg!(&self);

View file

@ -230,7 +230,7 @@ impl MapResponse<MusicSearchResult> for response::MusicSearch {
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<MusicSearchResult>, crate::error::ExtractionError> {
// dbg!(&self);
@ -284,7 +284,7 @@ impl<T: FromYtItem> MapResponse<MusicSearchFiltered<T>> for response::MusicSearc
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<MusicSearchFiltered<T>>, ExtractionError> {
// dbg!(&self);
@ -339,7 +339,7 @@ impl MapResponse<MusicSearchSuggestion> for response::MusicSearchSuggestion {
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<MusicSearchSuggestion>, ExtractionError> {
let mut mapper = MusicListMapper::new(lang);
let mut terms = Vec::new();

View file

@ -98,7 +98,7 @@ impl MapResponse<Paginator<YouTubeItem>> for response::Continuation {
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Paginator<YouTubeItem>>, ExtractionError> {
let items = self
.on_response_received_actions
@ -130,7 +130,7 @@ impl MapResponse<Paginator<MusicItem>> for response::MusicContinuation {
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Paginator<MusicItem>>, ExtractionError> {
let mut mapper = MusicListMapper::new(lang);
let mut continuations = Vec::new();

View file

@ -30,7 +30,7 @@ struct QPlayer<'a> {
context: YTContext<'a>,
/// Website playback context
#[serde(skip_serializing_if = "Option::is_none")]
playback_context: Option<QPlaybackContext>,
playback_context: Option<QPlaybackContext<'a>>,
/// Content playback nonce (mobile only, 16 random chars)
#[serde(skip_serializing_if = "Option::is_none")]
cpn: Option<String>,
@ -44,15 +44,15 @@ struct QPlayer<'a> {
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct QPlaybackContext {
content_playback_context: QContentPlaybackContext,
struct QPlaybackContext<'a> {
content_playback_context: QContentPlaybackContext<'a>,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct QContentPlaybackContext {
struct QContentPlaybackContext<'a> {
/// Signature timestamp extracted from player.js
signature_timestamp: String,
signature_timestamp: &'a str,
/// Referer URL from website
referer: String,
}
@ -95,7 +95,7 @@ impl RustyPipeQuery {
let video_id = video_id.as_ref();
let (context, deobf) = tokio::join!(
self.get_context(client_type, false, None),
self.client.get_deobf()
self.client.get_deobf_data()
);
let deobf = deobf?;
@ -104,7 +104,7 @@ impl RustyPipeQuery {
context,
playback_context: Some(QPlaybackContext {
content_playback_context: QContentPlaybackContext {
signature_timestamp: deobf.get_sts(),
signature_timestamp: &deobf.sts,
referer: format!("https://www.youtube.com/watch?v={video_id}"),
},
}),
@ -141,9 +141,10 @@ impl MapResponse<VideoPlayer> for response::Player {
self,
id: &str,
_lang: Language,
deobf: Option<&Deobfuscator>,
deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<super::MapResult<VideoPlayer>, ExtractionError> {
let deobf = deobf.unwrap();
let deobf = Deobfuscator::new(deobf.unwrap())
.map_err(|e| ExtractionError::InvalidData(e.to_string().into()))?;
let mut warnings = vec![];
// Check playability status
@ -253,21 +254,21 @@ impl MapResponse<VideoPlayer> for response::Player {
match (f.is_video(), f.is_audio()) {
(true, true) => {
let mut map_res = map_video_stream(f, deobf, &mut last_nsig);
let mut map_res = map_video_stream(f, &deobf, &mut last_nsig);
warnings.append(&mut map_res.warnings);
if let Some(c) = map_res.c {
video_streams.push(c);
};
}
(true, false) => {
let mut map_res = map_video_stream(f, deobf, &mut last_nsig);
let mut map_res = map_video_stream(f, &deobf, &mut last_nsig);
warnings.append(&mut map_res.warnings);
if let Some(c) = map_res.c {
video_only_streams.push(c);
};
}
(false, true) => {
let mut map_res = map_audio_stream(f, deobf, &mut last_nsig);
let mut map_res = map_audio_stream(f, &deobf, &mut last_nsig);
warnings.append(&mut map_res.warnings);
if let Some(c) = map_res.c {
audio_streams.push(c);
@ -612,20 +613,19 @@ mod tests {
use std::{fs::File, io::BufReader};
use path_macro::path;
use rstest::{fixture, rstest};
use rstest::rstest;
use super::*;
use crate::deobfuscate::DeobfData;
#[fixture]
fn deobf() -> Deobfuscator {
Deobfuscator::new(DeobfData {
js_url: "https://www.youtube.com/s/player/c8b8a173/player_ias.vflset/en_US/base.js".to_owned(),
sig_fn: "var oB={B4:function(a){a.reverse()},xm:function(a,b){a.splice(0,b)},dC:function(a,b){var c=a[0];a[0]=a[b%a.length];a[b%a.length]=c}};var Vva=function(a){a=a.split(\"\");oB.dC(a,42);oB.xm(a,3);oB.dC(a,48);oB.B4(a,68);return a.join(\"\")};var deobf_sig=Vva;".to_owned(),
nsig_fn: "Ska=function(a){var b=a.split(\"\"),c=[-1505243983,function(d,e){e=(e%d.length+d.length)%d.length;d.splice(-e).reverse().forEach(function(f){d.unshift(f)})},\n-1692381986,function(d,e){e=(e%d.length+d.length)%d.length;var f=d[0];d[0]=d[e];d[e]=f},\n-262444939,\"unshift\",function(d){for(var e=d.length;e;)d.push(d.splice(--e,1)[0])},\n1201502951,-546377604,-504264123,-1978377336,1042456724,function(d,e){for(e=(e%d.length+d.length)%d.length;e--;)d.unshift(d.pop())},\n711986897,406699922,-1842537993,-1678108293,1803491779,1671716087,12778705,-718839990,null,null,-1617525823,342523552,-1338406651,-399705108,-696713950,b,function(d,e){e=(e%d.length+d.length)%d.length;d.splice(0,1,d.splice(e,1,d[0])[0])},\nfunction(d,e){e=(e%d.length+d.length)%d.length;d.splice(e,1)},\n-980602034,356396192,null,-1617525823,function(d,e,f){var h=f.length;d.forEach(function(l,m,n){this.push(n[m]=f[(f.indexOf(l)-f.indexOf(this[m])+m+h--)%f.length])},e.split(\"\"))},\n-1029864222,-641353250,-1681901809,-1391247867,1707415199,-1957855835,b,function(){for(var d=64,e=[];++d-e.length-32;)switch(d){case 58:d=96;continue;case 91:d=44;break;case 65:d=47;continue;case 46:d=153;case 123:d-=58;default:e.push(String.fromCharCode(d))}return e},\n-1936558978,-1505243983,function(d){d.reverse()},\n1296889058,-1813915420,-943019300,function(d,e,f){var h=f.length;d.forEach(function(l,m,n){this.push(n[m]=f[(f.indexOf(l)-f.indexOf(this[m])+m+h--)%f.length])},e.split(\"\"))},\n\"join\",b,-2061642263];c[21]=c;c[22]=c;c[33]=c;try{c[3](c[33],c[9]),c[29](c[22],c[25]),c[29](c[22],c[19]),c[29](c[33],c[17]),c[29](c[21],c[2]),c[29](c[42],c[10]),c[1](c[52],c[40]),c[12](c[28],c[8]),c[29](c[21],c[45]),c[1](c[21],c[48]),c[44](c[26]),c[39](c[5],c[2]),c[31](c[53],c[16]),c[30](c[29],c[8]),c[51](c[29],c[6],c[44]()),c[4](c[43],c[1]),c[2](c[23],c[42]),c[2](c[0],c[46]),c[38](c[14],c[52]),c[32](c[5]),c[26](c[29],c[46]),c[26](c[5],c[13]),c[28](c[1],c[37]),c[26](c[31],c[13]),c[26](c[1],c[34]),\nc[46](c[1],c[32],c[40]()),c[26](c[50],c[44]),c[17](c[50],c[51]),c[0](c[3],c[24]),c[32](c[13]),c[43](c[3],c[51]),c[0](c[34],c[17]),c[16](c[45],c[53]),c[29](c[44],c[13]),c[42](c[1],c[50]),c[47](c[22],c[53]),c[37](c[22]),c[13](c[52],c[21]),c[6](c[43],c[34]),c[6](c[31],c[46])}catch(d){return\"enhanced_except_gZYB_un-_w8_\"+a}return b.join(\"\")};var deobf_nsig=Ska;".to_owned(),
sts: "19201".to_owned(),
}).unwrap()
static DEOBF_DATA: Lazy<DeobfData> = Lazy::new(|| {
DeobfData {
js_url: "https://www.youtube.com/s/player/c8b8a173/player_ias.vflset/en_US/base.js".to_owned(),
sig_fn: "var oB={B4:function(a){a.reverse()},xm:function(a,b){a.splice(0,b)},dC:function(a,b){var c=a[0];a[0]=a[b%a.length];a[b%a.length]=c}};var Vva=function(a){a=a.split(\"\");oB.dC(a,42);oB.xm(a,3);oB.dC(a,48);oB.B4(a,68);return a.join(\"\")};var deobf_sig=Vva;".to_owned(),
nsig_fn: "Ska=function(a){var b=a.split(\"\"),c=[-1505243983,function(d,e){e=(e%d.length+d.length)%d.length;d.splice(-e).reverse().forEach(function(f){d.unshift(f)})},\n-1692381986,function(d,e){e=(e%d.length+d.length)%d.length;var f=d[0];d[0]=d[e];d[e]=f},\n-262444939,\"unshift\",function(d){for(var e=d.length;e;)d.push(d.splice(--e,1)[0])},\n1201502951,-546377604,-504264123,-1978377336,1042456724,function(d,e){for(e=(e%d.length+d.length)%d.length;e--;)d.unshift(d.pop())},\n711986897,406699922,-1842537993,-1678108293,1803491779,1671716087,12778705,-718839990,null,null,-1617525823,342523552,-1338406651,-399705108,-696713950,b,function(d,e){e=(e%d.length+d.length)%d.length;d.splice(0,1,d.splice(e,1,d[0])[0])},\nfunction(d,e){e=(e%d.length+d.length)%d.length;d.splice(e,1)},\n-980602034,356396192,null,-1617525823,function(d,e,f){var h=f.length;d.forEach(function(l,m,n){this.push(n[m]=f[(f.indexOf(l)-f.indexOf(this[m])+m+h--)%f.length])},e.split(\"\"))},\n-1029864222,-641353250,-1681901809,-1391247867,1707415199,-1957855835,b,function(){for(var d=64,e=[];++d-e.length-32;)switch(d){case 58:d=96;continue;case 91:d=44;break;case 65:d=47;continue;case 46:d=153;case 123:d-=58;default:e.push(String.fromCharCode(d))}return e},\n-1936558978,-1505243983,function(d){d.reverse()},\n1296889058,-1813915420,-943019300,function(d,e,f){var h=f.length;d.forEach(function(l,m,n){this.push(n[m]=f[(f.indexOf(l)-f.indexOf(this[m])+m+h--)%f.length])},e.split(\"\"))},\n\"join\",b,-2061642263];c[21]=c;c[22]=c;c[33]=c;try{c[3](c[33],c[9]),c[29](c[22],c[25]),c[29](c[22],c[19]),c[29](c[33],c[17]),c[29](c[21],c[2]),c[29](c[42],c[10]),c[1](c[52],c[40]),c[12](c[28],c[8]),c[29](c[21],c[45]),c[1](c[21],c[48]),c[44](c[26]),c[39](c[5],c[2]),c[31](c[53],c[16]),c[30](c[29],c[8]),c[51](c[29],c[6],c[44]()),c[4](c[43],c[1]),c[2](c[23],c[42]),c[2](c[0],c[46]),c[38](c[14],c[52]),c[32](c[5]),c[26](c[29],c[46]),c[26](c[5],c[13]),c[28](c[1],c[37]),c[26](c[31],c[13]),c[26](c[1],c[34]),\nc[46](c[1],c[32],c[40]()),c[26](c[50],c[44]),c[17](c[50],c[51]),c[0](c[3],c[24]),c[32](c[13]),c[43](c[3],c[51]),c[0](c[34],c[17]),c[16](c[45],c[53]),c[29](c[44],c[13]),c[42](c[1],c[50]),c[47](c[22],c[53]),c[37](c[22]),c[13](c[52],c[21]),c[6](c[43],c[34]),c[6](c[31],c[46])}catch(d){return\"enhanced_except_gZYB_un-_w8_\"+a}return b.join(\"\")};var deobf_nsig=Ska;".to_owned(),
sts: "19201".to_owned(),
}
});
#[rstest]
#[case::desktop("desktop")]
@ -633,13 +633,13 @@ mod tests {
#[case::tv_html5_embed("tvhtml5embed")]
#[case::android("android")]
#[case::ios("ios")]
fn map_player_data(#[case] name: &str, deobf: Deobfuscator) {
fn map_player_data(#[case] name: &str) {
let json_path = path!("testfiles" / "player" / format!("{name}_video.json"));
let json_file = File::open(json_path).unwrap();
let resp: response::Player = serde_json::from_reader(BufReader::new(json_file)).unwrap();
let map_res = resp
.map_response("pPvd8UxmSbQ", Language::En, Some(&deobf))
.map_response("pPvd8UxmSbQ", Language::En, Some(&DEOBF_DATA))
.unwrap();
assert!(
@ -661,10 +661,11 @@ mod tests {
});
}
#[rstest]
fn cipher_to_url(deobf: Deobfuscator) {
#[test]
fn cipher_to_url() {
let signature_cipher = "s=w%3DAe%3DA6aDNQLkViKS7LOm9QtxZJHKwb53riq9qEFw-ecBWJCAiA%3DcEg0tn3dty9jEHszfzh4Ud__bg9CEHVx4ix-7dKsIPAhIQRw8JQ0qOA&sp=sig&url=https://rr5---sn-h0jelnez.googlevideo.com/videoplayback%3Fexpire%3D1659376413%26ei%3Dvb7nYvH5BMK8gAfBj7ToBQ%26ip%3D2003%253Ade%253Aaf06%253A6300%253Ac750%253A1b77%253Ac74a%253A80e3%26id%3Do-AB_BABwrXZJN428ZwDxq5ScPn2AbcGODnRlTVhCQ3mj2%26itag%3D251%26source%3Dyoutube%26requiressl%3Dyes%26mh%3DhH%26mm%3D31%252C26%26mn%3Dsn-h0jelnez%252Csn-4g5ednsl%26ms%3Dau%252Conr%26mv%3Dm%26mvi%3D5%26pl%3D37%26initcwndbps%3D1588750%26spc%3DlT-Khi831z8dTejFIRCvCEwx_6romtM%26vprv%3D1%26mime%3Daudio%252Fwebm%26ns%3Db_Mq_qlTFcSGlG9RpwpM9xQH%26gir%3Dyes%26clen%3D3781277%26dur%3D229.301%26lmt%3D1655510291473933%26mt%3D1659354538%26fvip%3D5%26keepalive%3Dyes%26fexp%3D24001373%252C24007246%26c%3DWEB%26rbqsm%3Dfr%26txp%3D4532434%26n%3Dd2g6G2hVqWIXxedQ%26sparams%3Dexpire%252Cei%252Cip%252Cid%252Citag%252Csource%252Crequiressl%252Cspc%252Cvprv%252Cmime%252Cns%252Cgir%252Cclen%252Cdur%252Clmt%26lsparams%3Dmh%252Cmm%252Cmn%252Cms%252Cmv%252Cmvi%252Cpl%252Cinitcwndbps%26lsig%3DAG3C_xAwRQIgCKCGJ1iu4wlaGXy3jcJyU3inh9dr1FIfqYOZEG_MdmACIQCbungkQYFk7EhD6K2YvLaHFMjKOFWjw001_tLb0lPDtg%253D%253D";
let mut last_nsig: [String; 2] = ["".to_owned(), "".to_owned()];
let deobf = Deobfuscator::new(&DEOBF_DATA).unwrap();
let map_res = map_url(
&None,
&Some(signature_cipher.to_owned()),

View file

@ -3,10 +3,8 @@ use std::{borrow::Cow, convert::TryFrom};
use time::OffsetDateTime;
use crate::{
deobfuscate::Deobfuscator,
error::{Error, ExtractionError},
model::{paginator::Paginator, ChannelId, Playlist, PlaylistVideo},
param::Language,
timeago,
util::{self, TryRemove},
};
@ -60,8 +58,8 @@ impl MapResponse<Playlist> for response::Playlist {
fn map_response(
self,
id: &str,
lang: Language,
_deobf: Option<&Deobfuscator>,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Playlist>, ExtractionError> {
let (contents, header) = match (self.contents, self.header) {
(Some(contents), Some(header)) => (contents, header),
@ -183,8 +181,8 @@ impl MapResponse<Paginator<PlaylistVideo>> for response::PlaylistCont {
fn map_response(
self,
_id: &str,
_lang: Language,
_deobf: Option<&Deobfuscator>,
_lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Paginator<PlaylistVideo>>, ExtractionError> {
let mut actions = self.on_response_received_actions;
let action = actions
@ -235,6 +233,8 @@ mod tests {
use path_macro::path;
use rstest::rstest;
use crate::param::Language;
use super::*;
#[rstest]

View file

@ -3,10 +3,9 @@ use std::borrow::Cow;
use serde::{de::IgnoredAny, Serialize};
use crate::{
deobfuscate::Deobfuscator,
error::{Error, ExtractionError},
model::{paginator::Paginator, SearchResult, YouTubeItem},
param::{search_filter::SearchFilter, Language},
param::search_filter::SearchFilter,
};
use super::{response, ClientType, MapResponse, MapResult, RustyPipeQuery, YTContext};
@ -97,8 +96,8 @@ impl MapResponse<SearchResult> for response::Search {
fn map_response(
self,
_id: &str,
lang: Language,
_deobf: Option<&Deobfuscator>,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<SearchResult>, ExtractionError> {
let items = self
.contents

View file

@ -53,7 +53,7 @@ impl MapResponse<Paginator<VideoItem>> for response::Startpage {
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Paginator<VideoItem>>, ExtractionError> {
let mut contents = self.contents.two_column_browse_results_renderer.tabs;
let grid = contents
@ -77,7 +77,7 @@ impl MapResponse<Vec<VideoItem>> for response::Trending {
self,
_id: &str,
lang: crate::param::Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Vec<VideoItem>>, ExtractionError> {
let mut contents = self.contents.two_column_browse_results_renderer.tabs;
let items = contents

View file

@ -301,7 +301,7 @@ impl MapResponse<UrlTarget> for response::ResolvedUrl {
self,
_id: &str,
_lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<UrlTarget>, ExtractionError> {
let browse_endpoint = self
.endpoint

View file

@ -82,7 +82,7 @@ impl MapResponse<VideoDetails> for response::VideoDetails {
self,
id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<VideoDetails>, ExtractionError> {
let mut warnings = Vec::new();
@ -367,7 +367,7 @@ impl MapResponse<Paginator<Comment>> for response::VideoComments {
self,
_id: &str,
lang: Language,
_deobf: Option<&crate::deobfuscate::Deobfuscator>,
_deobf: Option<&crate::deobfuscate::DeobfData>,
) -> Result<MapResult<Paginator<Comment>>, ExtractionError> {
let received_endpoints = self.on_response_received_endpoints;
let mut warnings = received_endpoints.warnings;

View file

@ -9,7 +9,6 @@ use crate::{error::DeobfError, util};
type Result<T> = core::result::Result<T, DeobfError>;
pub struct Deobfuscator {
data: DeobfData,
ctx: quick_js::Context,
}
@ -42,13 +41,13 @@ impl DeobfData {
}
impl Deobfuscator {
pub fn new(data: DeobfData) -> Result<Self> {
pub fn new(data: &DeobfData) -> Result<Self> {
let ctx =
quick_js::Context::new().or(Err(DeobfError::Other("could not create QuickJS rt")))?;
ctx.eval(&data.sig_fn)?;
ctx.eval(&data.nsig_fn)?;
Ok(Self { data, ctx })
Ok(Self { ctx })
}
pub fn deobfuscate_sig(&self, sig: &str) -> Result<String> {
@ -74,14 +73,6 @@ impl Deobfuscator {
},
)
}
pub fn get_sts(&self) -> String {
self.data.sts.to_owned()
}
pub fn get_data(&self) -> DeobfData {
self.data.to_owned()
}
}
const DEOBF_SIG_FUNC_NAME: &str = "deobf_sig";
@ -322,7 +313,7 @@ c[36](c[8],c[32]),c[20](c[25],c[10]),c[2](c[22],c[8]),c[32](c[20],c[16]),c[32](c
#[fixture]
fn deobf() -> Deobfuscator {
Deobfuscator::new(DeobfData {
Deobfuscator::new(&DeobfData {
js_url: String::default(),
sig_fn: SIG_DEOBF_FUNC.to_owned(),
nsig_fn: NSIG_DEOBF_FUNC.to_owned(),
@ -406,7 +397,7 @@ c[36](c[8],c[32]),c[20](c[25],c[10]),c[2](c[22],c[8]),c[32](c[20],c[16]),c[32](c
fn t_update() {
let client = Client::new();
let deobf_data = tokio_test::block_on(DeobfData::download(client)).unwrap();
let deobf = Deobfuscator::new(deobf_data).unwrap();
let deobf = Deobfuscator::new(&deobf_data).unwrap();
let deobf_sig = deobf.deobfuscate_sig("GOqGOqGOq0QJ8wRAIgaryQHfplJ9xJSKFywyaSMHuuwZYsoMTAvRvfm51qIGECIA5061zWeyfMPX9hEl_U6f9J0tr7GTJMKyPf5XNrJb5fb5i").unwrap();
println!("{deobf_sig}");