Skip to content

Commit

Permalink
Merge remote-tracking branch 'NewPipe/dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
polymorphicshade committed Feb 5, 2025
2 parents 2f7eef7 + c6e1721 commit 7b58b69
Show file tree
Hide file tree
Showing 273 changed files with 3,592 additions and 604 deletions.
9 changes: 6 additions & 3 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ android {
if (System.properties.containsKey('versionCodeOverride')) {
versionCode System.getProperty('versionCodeOverride') as Integer
} else {
versionCode 1002
versionCode 1003
}
versionName "0.27.5"
versionName "0.27.6"
if (System.properties.containsKey('versionNameSuffix')) {
versionNameSuffix System.getProperty('versionNameSuffix')
}
Expand Down Expand Up @@ -213,7 +213,9 @@ dependencies {
// name and the commit hash with the commit hash of the (pushed) commit you want to test
// This works thanks to JitPack: https://jitpack.io/
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
implementation 'com.github.polymorphicshade:TubularExtractor:4f2f7737895679c409e49ac4423f0ffa7f288570'
// WORKAROUND: if you get errors with the NewPipeExtractor dependency, replace `v0.24.3` with
// the corresponding commit hash, since JitPack is sometimes buggy
implementation 'com.github.polymorphicshade:TubularExtractor:c973caab73ed8647afd76ad01fe0726de62b9e81'
implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0'

/** Checkstyle **/
Expand Down Expand Up @@ -246,6 +248,7 @@ dependencies {
implementation "androidx.work:work-runtime-ktx:${androidxWorkVersion}"
implementation "androidx.work:work-rxjava3:${androidxWorkVersion}"
implementation 'com.google.android.material:material:1.11.0'
implementation "androidx.webkit:webkit:1.9.0"

/** Third-party libraries **/
// Instance state boilerplate elimination
Expand Down
127 changes: 127 additions & 0 deletions app/src/main/assets/po_token.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<!DOCTYPE html>
<html lang="en"><head><title></title><script>
/**
* Factory method to create and load a BotGuardClient instance.
* @param options - Configuration options for the BotGuardClient.
* @returns A promise that resolves to a loaded BotGuardClient instance.
*/
function loadBotGuard(challengeData) {
this.vm = this[challengeData.globalName];
this.program = challengeData.program;
this.vmFunctions = {};
this.syncSnapshotFunction = null;

if (!this.vm)
throw new Error('[BotGuardClient]: VM not found in the global object');

if (!this.vm.a)
throw new Error('[BotGuardClient]: Could not load program');

const vmFunctionsCallback = function (
asyncSnapshotFunction,
shutdownFunction,
passEventFunction,
checkCameraFunction
) {
this.vmFunctions = {
asyncSnapshotFunction: asyncSnapshotFunction,
shutdownFunction: shutdownFunction,
passEventFunction: passEventFunction,
checkCameraFunction: checkCameraFunction
};
};

this.syncSnapshotFunction = this.vm.a(this.program, vmFunctionsCallback, true, this.userInteractionElement, function () {/** no-op */ }, [ [], [] ])[0]

// an asynchronous function runs in the background and it will eventually call
// `vmFunctionsCallback`, however we need to manually tell JavaScript to pass
// control to the things running in the background by interrupting this async
// function in any way, e.g. with a delay of 1ms. The loop is most probably not
// needed but is there just because.
return new Promise(function (resolve, reject) {
i = 0
refreshIntervalId = setInterval(function () {
if (!!this.vmFunctions.asyncSnapshotFunction) {
resolve(this)
clearInterval(refreshIntervalId);
}
if (i >= 10000) {
reject("asyncSnapshotFunction is null even after 10 seconds")
clearInterval(refreshIntervalId);
}
i += 1;
}, 1);
})
}

/**
* Takes a snapshot asynchronously.
* @returns The snapshot result.
* @example
* ```ts
* const result = await botguard.snapshot({
* contentBinding: {
* c: "a=6&a2=10&b=SZWDwKVIuixOp7Y4euGTgwckbJA&c=1729143849&d=1&t=7200&c1a=1&c6a=1&c6b=1&hh=HrMb5mRWTyxGJphDr0nW2Oxonh0_wl2BDqWuLHyeKLo",
* e: "ENGAGEMENT_TYPE_VIDEO_LIKE",
* encryptedVideoId: "P-vC09ZJcnM"
* }
* });
*
* console.log(result);
* ```
*/
function snapshot(args) {
return new Promise(function (resolve, reject) {
if (!this.vmFunctions.asyncSnapshotFunction)
return reject(new Error('[BotGuardClient]: Async snapshot function not found'));

this.vmFunctions.asyncSnapshotFunction(function (response) { resolve(response) }, [
args.contentBinding,
args.signedTimestamp,
args.webPoSignalOutput,
args.skipPrivacyBuffer
]);
});
}

function runBotGuard(challengeData) {
const interpreterJavascript = challengeData.interpreterJavascript.privateDoNotAccessOrElseSafeScriptWrappedValue;

if (interpreterJavascript) {
new Function(interpreterJavascript)();
} else throw new Error('Could not load VM');

const webPoSignalOutput = [];
return loadBotGuard({
globalName: challengeData.globalName,
globalObj: this,
program: challengeData.program
}).then(function (botguard) {
return botguard.snapshot({ webPoSignalOutput: webPoSignalOutput })
}).then(function (botguardResponse) {
return { webPoSignalOutput: webPoSignalOutput, botguardResponse: botguardResponse }
})
}

function obtainPoToken(webPoSignalOutput, integrityToken, identifier) {
const getMinter = webPoSignalOutput[0];

if (!getMinter)
throw new Error('PMD:Undefined');

const mintCallback = getMinter(integrityToken);

if (!(mintCallback instanceof Function))
throw new Error('APF:Failed');

const result = mintCallback(identifier);

if (!result)
throw new Error('YNJ:Undefined');

if (!(result instanceof Uint8Array))
throw new Error('ODM:Invalid');

return result;
}
</script></head><body></body></html>
4 changes: 4 additions & 0 deletions app/src/main/java/org/schabi/newpipe/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.schabi.newpipe.error.ReCaptchaActivity;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.downloader.Downloader;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.ktx.ExceptionUtils;
import org.schabi.newpipe.settings.NewPipeSettings;
import org.schabi.newpipe.util.BridgeStateSaverInitializer;
Expand All @@ -26,6 +27,7 @@
import org.schabi.newpipe.util.image.ImageStrategy;
import org.schabi.newpipe.util.image.PicassoHelper;
import org.schabi.newpipe.util.image.PreferredImageQuality;
import org.schabi.newpipe.util.potoken.PoTokenProviderImpl;

import java.io.IOException;
import java.io.InterruptedIOException;
Expand Down Expand Up @@ -118,6 +120,8 @@ public void onCreate() {
&& prefs.getBoolean(getString(R.string.show_image_indicators_key), false));

configureRxJavaErrorHandler();

YoutubeStreamExtractor.setPoTokenProvider(PoTokenProviderImpl.INSTANCE);
}

@Override
Expand Down
54 changes: 25 additions & 29 deletions app/src/main/java/org/schabi/newpipe/DownloaderImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,46 +137,42 @@ public Response execute(@NonNull final Request request)
}

final okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder()
.method(httpMethod, requestBody).url(url)
.method(httpMethod, requestBody)
.url(url)
.addHeader("User-Agent", USER_AGENT);

final String cookies = getCookies(url);
if (!cookies.isEmpty()) {
requestBuilder.addHeader("Cookie", cookies);
}

for (final Map.Entry<String, List<String>> pair : headers.entrySet()) {
final String headerName = pair.getKey();
final List<String> headerValueList = pair.getValue();
headers.forEach((headerName, headerValueList) -> {
requestBuilder.removeHeader(headerName);
headerValueList.forEach(headerValue ->
requestBuilder.addHeader(headerName, headerValue));
});

try (
okhttp3.Response response = client.newCall(requestBuilder.build()).execute()
) {
if (response.code() == 429) {
throw new ReCaptchaException("reCaptcha Challenge requested", url);
}

if (headerValueList.size() > 1) {
requestBuilder.removeHeader(headerName);
for (final String headerValue : headerValueList) {
requestBuilder.addHeader(headerName, headerValue);
String responseBodyToReturn = null;
try (ResponseBody body = response.body()) {
if (body != null) {
responseBodyToReturn = body.string();
}
} else if (headerValueList.size() == 1) {
requestBuilder.header(headerName, headerValueList.get(0));
}

final String latestUrl = response.request().url().toString();
return new Response(
response.code(),
response.message(),
response.headers().toMultimap(),
responseBodyToReturn,
latestUrl);
}

final okhttp3.Response response = client.newCall(requestBuilder.build()).execute();

if (response.code() == 429) {
response.close();

throw new ReCaptchaException("reCaptcha Challenge requested", url);
}

final ResponseBody body = response.body();
String responseBodyToReturn = null;

if (body != null) {
responseBodyToReturn = body.string();
}

final String latestUrl = response.request().url().toString();
return new Response(response.code(), response.message(), response.headers().toMultimap(),
responseBodyToReturn, latestUrl);
}
}
12 changes: 11 additions & 1 deletion app/src/main/java/org/schabi/newpipe/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.StateSaver;
import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.views.FocusOverlayView;

import java.util.ArrayList;
Expand Down Expand Up @@ -120,7 +121,8 @@ public class MainActivity extends AppCompatActivity {
private static final int ITEM_ID_DOWNLOADS = -4;
private static final int ITEM_ID_HISTORY = -5;
private static final int ITEM_ID_SETTINGS = 0;
private static final int ITEM_ID_ABOUT = 1;
private static final int ITEM_ID_DONATION = 1;
private static final int ITEM_ID_ABOUT = 2;

private static final int ORDER = 0;

Expand Down Expand Up @@ -262,6 +264,10 @@ private void addDrawerMenuForCurrentService() throws ExtractionException {
drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_options_about_group, ITEM_ID_SETTINGS, ORDER, R.string.settings)
.setIcon(R.drawable.ic_settings);
drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_options_about_group, ITEM_ID_DONATION, ORDER,
R.string.donation_title)
.setIcon(R.drawable.volunteer_activism_ic);
drawerLayoutBinding.navigation.getMenu()
.add(R.id.menu_options_about_group, ITEM_ID_ABOUT, ORDER, R.string.tab_about)
.setIcon(R.drawable.ic_info_outline);
Expand Down Expand Up @@ -337,6 +343,9 @@ private void optionsAboutSelected(final MenuItem item) {
case ITEM_ID_SETTINGS:
NavigationHelper.openSettings(this);
break;
case ITEM_ID_DONATION:
ShareUtils.openUrlInBrowser(this, getString(R.string.donation_url));
break;
case ITEM_ID_ABOUT:
NavigationHelper.openAbout(this);
break;
Expand Down Expand Up @@ -924,4 +933,5 @@ private boolean bottomSheetHiddenOrCollapsed() {
return sheetState == BottomSheetBehavior.STATE_HIDDEN
|| sheetState == BottomSheetBehavior.STATE_COLLAPSED;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -308,11 +308,11 @@ public void onServiceDisconnected() {
/*////////////////////////////////////////////////////////////////////////*/

public static VideoDetailFragment getInstance(final int serviceId,
@Nullable final String videoUrl,
@Nullable final String url,
@NonNull final String name,
@Nullable final PlayQueue queue) {
final VideoDetailFragment instance = new VideoDetailFragment();
instance.setInitialData(serviceId, videoUrl, name, queue);
instance.setInitialData(serviceId, url, name, queue);
return instance;
}

Expand Down Expand Up @@ -1855,7 +1855,7 @@ public void onQueueUpdate(final PlayQueue queue) {
playQueue = queue;
if (DEBUG) {
Log.d(TAG, "onQueueUpdate() called with: serviceId = ["
+ serviceId + "], videoUrl = [" + url + "], name = ["
+ serviceId + "], url = [" + url + "], name = ["
+ title + "], playQueue = [" + playQueue + "]");
}

Expand Down
Loading

0 comments on commit 7b58b69

Please sign in to comment.