fix: instantiate deobfuscator in mapresponse fn
Reason: quickjs context is not Send
This commit is contained in:
parent
d9e07b37e6
commit
ee5e82f6bb
17 changed files with 74 additions and 84 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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>;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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()),
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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}");
|
||||
|
|
|
|||
Reference in a new issue