diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java index 9a811737a..0f97bd12a 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeParsingHelper.java @@ -48,6 +48,7 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.stream.AudioTrackType; import org.schabi.newpipe.extractor.utils.JsonUtils; import org.schabi.newpipe.extractor.utils.Parser; +import org.schabi.newpipe.extractor.utils.ProtoBuilder; import org.schabi.newpipe.extractor.utils.RandomStringFromAlphabetGenerator; import org.schabi.newpipe.extractor.utils.Utils; @@ -212,7 +213,7 @@ public final class YoutubeParsingHelper { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; /** - * The device machine id for the iPhone 15, used to get 60fps with the {@code iOS} client. + * The device machine id for the iPhone 16, used to get 60fps with the {@code iOS} client. * *

* See this GitHub Gist for more @@ -222,15 +223,15 @@ public final class YoutubeParsingHelper { private static final String IOS_DEVICE_MODEL = "iPhone16,2"; /** - * Spoofing an iPhone 15 Pro Max running iOS 17.5.1 with the hardcoded version of the iOS app. + * Spoofing an iPhone 16 Pro Max running iOS 18.1.0 with the hardcoded version of the iOS app. * To be used for the {@code "osVersion"} field in JSON POST requests. *

* The value of this field seems to use the following structure: * "iOS major version.minor version.patch version.build version", where * "patch version" is equal to 0 if it isn't set * The build version corresponding to the iOS version used can be found on - * - * https://theapplewiki.com/wiki/Firmware/iPhone/17.x#iPhone_15_Pro_Max + * + * https://theapplewiki.com/wiki/Firmware/iPhone/18.x#iPhone_16_Pro_Max *

* * @see #IOS_USER_AGENT_VERSION @@ -238,7 +239,7 @@ public final class YoutubeParsingHelper { private static final String IOS_OS_VERSION = "18.1.0.22B83"; /** - * Spoofing an iPhone 15 running iOS 17.5.1 with the hardcoded version of the iOS app. To be + * Spoofing an iPhone 16 Pro Max running iOS 18.1.0 with the hardcoded version of the iOS app. To be * used in the user agent for requests. * * @see #IOS_OS_VERSION @@ -306,7 +307,7 @@ public final class YoutubeParsingHelper { public static String randomVisitorData(final ContentCountry country) { final ProtoBuilder pbE2 = new ProtoBuilder(); pbE2.string(2, ""); - pbE2.varint(4, numberGenerator.nextInt(1, 256)); + pbE2.varint(4, numberGenerator.nextInt(255) + 1); final ProtoBuilder pbE = new ProtoBuilder(); pbE.string(1, country.getCountryCode()); @@ -1181,10 +1182,11 @@ public final class YoutubeParsingHelper { public static JsonBuilder prepareDesktopJsonBuilder( @Nonnull final Localization localization, @Nonnull final ContentCountry contentCountry, - @Nullable String visitorData) + @Nullable final String visitorData) throws IOException, ExtractionException { - if (visitorData == null) { - visitorData = randomVisitorData(contentCountry); + String vData = visitorData; + if (vData == null) { + vData = randomVisitorData(contentCountry); } // @formatter:off @@ -1198,7 +1200,7 @@ public final class YoutubeParsingHelper { .value("originalUrl", "https://www.youtube.com") .value("platform", "DESKTOP") .value("utcOffsetMinutes", 0) - .value("visitorData", visitorData) + .value("visitorData", vData) .end() .object("request") .array("internalExperimentFlags") @@ -1410,7 +1412,7 @@ public final class YoutubeParsingHelper { */ @Nonnull public static String getIosUserAgent(@Nullable final Localization localization) { - // Spoofing an iPhone 15 running iOS 17.5.1 with the hardcoded version of the iOS app + // Spoofing an iPhone 16 Pro Max running iOS 17.5.1 with the hardcoded version of the iOS app return "com.google.ios.youtube/" + IOS_YOUTUBE_CLIENT_VERSION + "(" + IOS_DEVICE_MODEL + "; U; CPU iOS " + IOS_USER_AGENT_VERSION + " like Mac OS X; " diff --git a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/ProtoBuilder.java b/extractor/src/main/java/org/schabi/newpipe/extractor/utils/ProtoBuilder.java similarity index 82% rename from extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/ProtoBuilder.java rename to extractor/src/main/java/org/schabi/newpipe/extractor/utils/ProtoBuilder.java index 01368ca78..f0e223a9c 100644 --- a/extractor/src/main/java/org/schabi/newpipe/extractor/services/youtube/ProtoBuilder.java +++ b/extractor/src/main/java/org/schabi/newpipe/extractor/utils/ProtoBuilder.java @@ -1,4 +1,4 @@ -package org.schabi.newpipe.extractor.services.youtube; +package org.schabi.newpipe.extractor.utils; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -22,22 +22,23 @@ public class ProtoBuilder { return URLEncoder.encode(b64, StandardCharsets.UTF_8); } - private void writeVarint(long val) { + private void writeVarint(final long val) { try { if (val == 0) { byteBuffer.write(new byte[]{(byte) 0}); } else { - while (val != 0) { - byte b = (byte) (val & 0x7f); - val >>= 7; + long v = val; + while (v != 0) { + byte b = (byte) (v & 0x7f); + v >>= 7; - if (val != 0) { + if (v != 0) { b |= (byte) 0x80; } byteBuffer.write(new byte[]{b}); } } - } catch (IOException e) { + } catch (final IOException e) { throw new RuntimeException(e); } } @@ -64,7 +65,7 @@ public class ProtoBuilder { writeVarint(bytes.length); try { byteBuffer.write(bytes); - } catch (IOException e) { + } catch (final IOException e) { throw new RuntimeException(e); } } diff --git a/extractor/src/test/java/org/schabi/newpipe/extractor/utils/ProtoBuilderTest.java b/extractor/src/test/java/org/schabi/newpipe/extractor/utils/ProtoBuilderTest.java new file mode 100644 index 000000000..b39879451 --- /dev/null +++ b/extractor/src/test/java/org/schabi/newpipe/extractor/utils/ProtoBuilderTest.java @@ -0,0 +1,18 @@ +package org.schabi.newpipe.extractor.utils; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ProtoBuilderTest { + @Test + public void testProtoBuilder() { + final ProtoBuilder pb = new ProtoBuilder(); + pb.varint(1, 128); + pb.varint(2, 1234567890); + pb.varint(3, 1234567890123456789L); + pb.string(4, "Hello"); + pb.bytes(5, new byte[]{1, 2, 3}); + assertEquals("CIABENKF2MwEGJWCpu_HnoSRESIFSGVsbG8qAwECAw%3D%3D", pb.toUrlencodedBase64()); + } +}