Skip to content
This repository has been archived by the owner on Oct 26, 2024. It is now read-only.

Commit

Permalink
chore: Merge branch dev to main (#665)
Browse files Browse the repository at this point in the history
  • Loading branch information
oSumAtrIX authored Aug 6, 2024
2 parents 34a224e + 36cb36f commit e5736fc
Show file tree
Hide file tree
Showing 21 changed files with 446 additions and 138 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
fingerprint: ${{ env.GPG_FINGERPRINT }}
fingerprint: ${{ vars.GPG_FINGERPRINT }}

- name: Release
env:
Expand Down
8 changes: 7 additions & 1 deletion .releaserc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
}
],
"plugins": [
"@semantic-release/commit-analyzer",
[
"@semantic-release/commit-analyzer", {
"releaseRules": [
{ "type": "build", "scope": "Needs bump", "release": "patch" }
]
}
],
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"gradle-semantic-release-plugin",
Expand Down
96 changes: 96 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,99 @@
# [1.12.0-dev.10](https://github.com/ReVanced/revanced-integrations/compare/v1.12.0-dev.9...v1.12.0-dev.10) (2024-08-05)


### Bug Fixes

* **YouTube - Return YouTube Dislike:** Fix dislikes not appearing due to new component name ([#674](https://github.com/ReVanced/revanced-integrations/issues/674)) ([509e151](https://github.com/ReVanced/revanced-integrations/commit/509e1516f817bd736c3b2cc75bb5b48ab7de404a))

# [1.12.0-dev.9](https://github.com/ReVanced/revanced-integrations/compare/v1.12.0-dev.8...v1.12.0-dev.9) (2024-08-04)


### Bug Fixes

* **YouTube - Spoof client:** Restore livestream audio only playback with iOS spoofing ([#673](https://github.com/ReVanced/revanced-integrations/issues/673)) ([5bf5fbd](https://github.com/ReVanced/revanced-integrations/commit/5bf5fbd1a79389895991f6b672d87373e96b698c))

# [1.12.0-dev.8](https://github.com/ReVanced/revanced-integrations/compare/v1.12.0-dev.7...v1.12.0-dev.8) (2024-08-02)


### Bug Fixes

* **YouTube - SponsorBlock:** Improve create segment manual seek accuracy ([#671](https://github.com/ReVanced/revanced-integrations/issues/671)) ([34c02ae](https://github.com/ReVanced/revanced-integrations/commit/34c02aeb2a75bd95492e55958a446c9f99efdbb3))

# [1.12.0-dev.7](https://github.com/ReVanced/revanced-integrations/compare/v1.12.0-dev.6...v1.12.0-dev.7) (2024-08-01)


### Features

* **YouTube - Description components:** Add `Hide 'Key concepts' section` option ([#670](https://github.com/ReVanced/revanced-integrations/issues/670)) ([86b25ea](https://github.com/ReVanced/revanced-integrations/commit/86b25ea468a132bd01e3fb1e2972cc903dd46d0c))

# [1.12.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v1.12.0-dev.5...v1.12.0-dev.6) (2024-07-28)


### Bug Fixes

* **YouTube - Keyword filter:** Filter videos from new subscription layout ([2f2eeea](https://github.com/ReVanced/revanced-integrations/commit/2f2eeea5a722b6b7053eb2825d16fa37938b4e9e))

# [1.12.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v1.12.0-dev.4...v1.12.0-dev.5) (2024-07-28)


### Bug Fixes

* **YouTube - Client Spoof:** Restore missing high qualities by spoofing the iOS client user agent ([#668](https://github.com/ReVanced/revanced-integrations/issues/668)) ([fbf629f](https://github.com/ReVanced/revanced-integrations/commit/fbf629fd6278440e70b0f1fb07e4cb7c412f0949))

# [1.12.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v1.12.0-dev.3...v1.12.0-dev.4) (2024-07-28)


### Bug Fixes

* **YouTube - Spoof client:** Fix tracking history on brand accounts ([#669](https://github.com/ReVanced/revanced-integrations/issues/669)) ([4ac698f](https://github.com/ReVanced/revanced-integrations/commit/4ac698fd4bd493d3830009853454a8f6566362b5))

# [1.12.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.12.0-dev.2...v1.12.0-dev.3) (2024-07-26)


### Bug Fixes

* **YouTube - SponsorBlock:** Correctly show minute timestamp when creating a new segment ([e71955d](https://github.com/ReVanced/revanced-integrations/commit/e71955d5bbe58c1c634e82262d0e67dc65eca078))

# [1.12.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.12.0-dev.1...v1.12.0-dev.2) (2024-07-15)


### Bug Fixes

* **YouTube - Disable auto captions:** Do not break Shorts captions menu ([0345a00](https://github.com/ReVanced/revanced-integrations/commit/0345a00d6095797e275bb31f92ccda2e861f44c4))

# [1.12.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.11.2-dev.3...v1.12.0-dev.1) (2024-07-14)


### Features

* **YouTube:** Add `Bypass image region restrictions` patch ([#667](https://github.com/ReVanced/revanced-integrations/issues/667)) ([396ba77](https://github.com/ReVanced/revanced-integrations/commit/396ba77c207b438651ba6b83fb4b31e623544c00))

## [1.11.2-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v1.11.2-dev.2...v1.11.2-dev.3) (2024-07-14)

## [1.11.2-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.11.2-dev.1...v1.11.2-dev.2) (2024-07-14)


### Bug Fixes

* **YouTube - Alternative thumbnails:** Always use primary thumbnail domain for still captures ([#666](https://github.com/ReVanced/revanced-integrations/issues/666)) ([7cdaf8d](https://github.com/ReVanced/revanced-integrations/commit/7cdaf8df146fdc0da8254a27d9c125f1e3d34765))
* **YouTube - Hide layout components:** Hide new type of horizontal shelf ([1fa59a6](https://github.com/ReVanced/revanced-integrations/commit/1fa59a62a17c63916808647331fa682d3de6aafb))

## [1.11.2-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v1.11.2-dev.1...v1.11.2-dev.2) (2024-07-13)


### Bug Fixes

* **YouTube - Alternative thumbnails:** Always use primary thumbnail domain for still captures ([#666](https://github.com/ReVanced/revanced-integrations/issues/666)) ([7cdaf8d](https://github.com/ReVanced/revanced-integrations/commit/7cdaf8df146fdc0da8254a27d9c125f1e3d34765))

## [1.11.2-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v1.11.1...v1.11.2-dev.1) (2024-07-12)


### Bug Fixes

* adjust blacklist ([d8d2a85](https://github.com/ReVanced/revanced-integrations/commit/d8d2a852d3879060bd95cc43d66c7cf195e82b43))
* **YouTube - Hide keyword content:** Do not hide flyout menu ([cda1f31](https://github.com/ReVanced/revanced-integrations/commit/cda1f3160c12d239df1183799ead39526cbac20f))
* **YouTube - Hide keyword content:** Do not hide flyout menu ([#664](https://github.com/ReVanced/revanced-integrations/issues/664)) ([120188d](https://github.com/ReVanced/revanced-integrations/commit/120188d6431b5500d6fde9cec136c752f8ee0ea4))

## [1.11.1](https://github.com/ReVanced/revanced-integrations/compare/v1.11.0...v1.11.1) (2024-07-11)


Expand Down
28 changes: 14 additions & 14 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin)
publishing
signing
}

android {
Expand Down Expand Up @@ -53,28 +54,27 @@ dependencies {
compileOnly(project(":stub"))
}


tasks {
// Because the signing plugin doesn't support signing APKs, do it manually.
register("sign") {
group = "signing"
val assembleReleaseSignApk by registering {
dependsOn("assembleRelease")

dependsOn(build)
val apk = layout.buildDirectory.file("outputs/apk/release/${rootProject.name}-$version.apk")

doLast {
val outputDirectory = layout.buildDirectory.dir("outputs/apk/release").get().asFile
val integrationsApk = outputDirectory.resolve("${rootProject.name}-$version.apk")
inputs.file(apk).withPropertyName("input")
outputs.file(apk.map { it.asFile.resolveSibling("${it.asFile.name}.asc") })

org.gradle.security.internal.gnupg.GnupgSignatoryFactory().createSignatory(project).sign(
integrationsApk.inputStream(),
outputDirectory.resolve("${integrationsApk.name}.asc").outputStream(),
)
doLast {
signing {
useGpgCmd()
sign(*inputs.files.files.toTypedArray())
}
}
}

// Needed by gradle-semantic-release-plugin.
// Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
// Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435.
publish {
dependsOn(build)
dependsOn("sign")
dependsOn(assembleReleaseSignApk)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,6 @@ public static <T extends View> T getChildView(@NonNull ViewGroup viewGroup, bool
@NonNull MatchFilter<View> filter) {
for (int i = 0, childCount = viewGroup.getChildCount(); i < childCount; i++) {
View childAt = viewGroup.getChildAt(i);
Logger.printDebug(() -> "View id: " + childAt.getId() + " tag: " + childAt.getTag());

if (filter.matches(childAt)) {
//noinspection unchecked
Expand All @@ -285,6 +284,7 @@ public static <T extends View> T getChildView(@NonNull ViewGroup viewGroup, bool
if (match != null) return match;
}
}

return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,16 +190,17 @@ private static ThumbnailOption optionSettingForCurrentNavigation() {
* Build the alternative thumbnail url using YouTube provided still video captures.
*
* @param decodedUrl Decoded original thumbnail request url.
* @return The alternative thumbnail url, or the original url. Both without tracking parameters.
* @return The alternative thumbnail url, or if not available NULL.
*/
@NonNull
private static String buildYoutubeVideoStillURL(@NonNull DecodedThumbnailUrl decodedUrl,
@Nullable
private static String buildYouTubeVideoStillURL(@NonNull DecodedThumbnailUrl decodedUrl,
@NonNull ThumbnailQuality qualityToUse) {
String sanitizedReplacement = decodedUrl.createStillsUrl(qualityToUse, false);
if (VerifiedQualities.verifyAltThumbnailExist(decodedUrl.videoId, qualityToUse, sanitizedReplacement)) {
return sanitizedReplacement;
}
return decodedUrl.sanitizedUrl;

return null;
}

/**
Expand Down Expand Up @@ -284,14 +285,21 @@ public static String overrideImageURL(String originalUrl) {
final boolean includeTracking;
if (option.useDeArrow && canUseDeArrowAPI()) {
includeTracking = false; // Do not include view tracking parameters with API call.
final String fallbackUrl = option.useStillImages
? buildYoutubeVideoStillURL(decodedUrl, qualityToUse)
: decodedUrl.sanitizedUrl;
String fallbackUrl = null;
if (option.useStillImages) {
fallbackUrl = buildYouTubeVideoStillURL(decodedUrl, qualityToUse);
}
if (fallbackUrl == null) {
fallbackUrl = decodedUrl.sanitizedUrl;
}

sanitizedReplacementUrl = buildDeArrowThumbnailURL(decodedUrl.videoId, fallbackUrl);
} else if (option.useStillImages) {
includeTracking = true; // Include view tracking parameters if present.
sanitizedReplacementUrl = buildYoutubeVideoStillURL(decodedUrl, qualityToUse);
sanitizedReplacementUrl = buildYouTubeVideoStillURL(decodedUrl, qualityToUse);
if (sanitizedReplacementUrl == null) {
return originalUrl; // Still capture is not available. Return the untouched original url.
}
} else {
return originalUrl; // Recently experienced DeArrow failure and video stills are not enabled.
}
Expand Down Expand Up @@ -345,7 +353,7 @@ public static void handleCronetSuccess(UrlRequest request, @NonNull UrlResponseI
return; // Not a thumbnail.
}

Logger.printDebug(() -> "handleCronetSuccess, image not available: " + url);
Logger.printDebug(() -> "handleCronetSuccess, image not available: " + decodedUrl.sanitizedUrl);

ThumbnailQuality quality = ThumbnailQuality.altImageNameToQuality(decodedUrl.imageQuality);
if (quality == null) {
Expand Down Expand Up @@ -627,14 +635,17 @@ synchronized boolean verifyYouTubeThumbnailExists(@NonNull String videoId, @NonN
* YouTube video thumbnail url, decoded into it's relevant parts.
*/
private static class DecodedThumbnailUrl {
/**
* YouTube thumbnail URL prefix. Can be '/vi/' or '/vi_webp/'
*/
private static final String YOUTUBE_THUMBNAIL_PREFIX = "https://i.ytimg.com/vi";
private static final String YOUTUBE_THUMBNAIL_DOMAIN = "https://i.ytimg.com/";

@Nullable
static DecodedThumbnailUrl decodeImageUrl(String url) {
final int videoIdStartIndex = url.indexOf('/', YOUTUBE_THUMBNAIL_PREFIX.length()) + 1;
final int urlPathStartIndex = url.indexOf('/', "https://".length()) + 1;
if (urlPathStartIndex <= 0) return null;

final int urlPathEndIndex = url.indexOf('/', urlPathStartIndex);
if (urlPathEndIndex < 0) return null;

final int videoIdStartIndex = url.indexOf('/', urlPathEndIndex) + 1;
if (videoIdStartIndex <= 0) return null;

final int videoIdEndIndex = url.indexOf('/', videoIdStartIndex);
Expand All @@ -647,15 +658,15 @@ static DecodedThumbnailUrl decodeImageUrl(String url) {
int imageExtensionEndIndex = url.indexOf('?', imageSizeEndIndex);
if (imageExtensionEndIndex < 0) imageExtensionEndIndex = url.length();

return new DecodedThumbnailUrl(url, videoIdStartIndex, videoIdEndIndex,
return new DecodedThumbnailUrl(url, urlPathStartIndex, urlPathEndIndex, videoIdStartIndex, videoIdEndIndex,
imageSizeStartIndex, imageSizeEndIndex, imageExtensionEndIndex);
}

final String originalFullUrl;
/** Full usable url, but stripped of any tracking information. */
final String sanitizedUrl;
/** Url up to the video ID. */
final String urlPrefix;
/** Url path, such as 'vi' or 'vi_webp' */
final String urlPath;
final String videoId;
/** Quality, such as hq720 or sddefault. */
final String imageQuality;
Expand All @@ -664,11 +675,11 @@ static DecodedThumbnailUrl decodeImageUrl(String url) {
/** User view tracking parameters, only present on some images. */
final String viewTrackingParameters;

DecodedThumbnailUrl(String fullUrl, int videoIdStartIndex, int videoIdEndIndex,
DecodedThumbnailUrl(String fullUrl, int urlPathStartIndex, int urlPathEndIndex, int videoIdStartIndex, int videoIdEndIndex,
int imageSizeStartIndex, int imageSizeEndIndex, int imageExtensionEndIndex) {
originalFullUrl = fullUrl;
sanitizedUrl = fullUrl.substring(0, imageExtensionEndIndex);
urlPrefix = fullUrl.substring(0, videoIdStartIndex);
urlPath = fullUrl.substring(urlPathStartIndex, urlPathEndIndex);
videoId = fullUrl.substring(videoIdStartIndex, videoIdEndIndex);
imageQuality = fullUrl.substring(imageSizeStartIndex, imageSizeEndIndex);
imageExtension = fullUrl.substring(imageSizeEndIndex + 1, imageExtensionEndIndex);
Expand All @@ -681,9 +692,12 @@ String createStillsUrl(@NonNull ThumbnailQuality qualityToUse, boolean includeVi
// Images could be upgraded to webp if they are not already, but this fails quite often,
// especially for new videos uploaded in the last hour.
// And even if alt webp images do exist, sometimes they can load much slower than the original jpg alt images.
// (as much as 4x slower has been observed, despite the alt webp image being a smaller file).
// (as much as 4x slower network response has been observed, despite the alt webp image being a smaller file).
StringBuilder builder = new StringBuilder(originalFullUrl.length() + 2);
builder.append(urlPrefix);
// Many different "i.ytimage.com" domains exist such as "i9.ytimg.com",
// but still captures are frequently not available on the other domains (especially newly uploaded videos).
// So always use the primary domain for a higher success rate.
builder.append(YOUTUBE_THUMBNAIL_DOMAIN).append(urlPath).append('/');
builder.append(videoId).append('/');
builder.append(qualityToUse.getAltImageNameToUse());
builder.append('.').append(imageExtension);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package app.revanced.integrations.youtube.patches;

import static app.revanced.integrations.youtube.settings.Settings.BYPASS_IMAGE_REGION_RESTRICTIONS;

import java.util.regex.Pattern;

import app.revanced.integrations.shared.Logger;
import app.revanced.integrations.youtube.settings.Settings;

@SuppressWarnings("unused")
public final class BypassImageRegionRestrictionsPatch {

private static final boolean BYPASS_IMAGE_REGION_RESTRICTIONS_ENABLED = BYPASS_IMAGE_REGION_RESTRICTIONS.get();

private static final String REPLACEMENT_IMAGE_DOMAIN = "https://yt4.ggpht.com";

/**
* YouTube static images domain. Includes user and channel avatar images and community post images.
*/
private static final Pattern YOUTUBE_STATIC_IMAGE_DOMAIN_PATTERN
= Pattern.compile("^https://(yt3|lh[3-6]|play-lh)\\.(ggpht|googleusercontent)\\.com");

/**
* Injection point. Called off the main thread and by multiple threads at the same time.
*
* @param originalUrl Image url for all image urls loaded.
*/
public static String overrideImageURL(String originalUrl) {
try {
if (BYPASS_IMAGE_REGION_RESTRICTIONS_ENABLED) {
String replacement = YOUTUBE_STATIC_IMAGE_DOMAIN_PATTERN
.matcher(originalUrl).replaceFirst(REPLACEMENT_IMAGE_DOMAIN);

if (Settings.DEBUG.get() && !replacement.equals(originalUrl)) {
Logger.printDebug(() -> "Replaced: '" + originalUrl + "' with: '" + replacement + "'");
}

return replacement;
}
} catch (Exception ex) {
Logger.printException(() -> "overrideImageURL failure", ex);
}

return originalUrl;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package app.revanced.integrations.youtube.patches;

import app.revanced.integrations.youtube.settings.Settings;
import app.revanced.integrations.youtube.shared.PlayerType;

@SuppressWarnings("unused")
public class DisableAutoCaptionsPatch {
Expand All @@ -11,7 +12,9 @@ public class DisableAutoCaptionsPatch {
public static boolean captionsButtonDisabled;

public static boolean autoCaptionsEnabled() {
return Settings.AUTO_CAPTIONS.get();
return Settings.AUTO_CAPTIONS.get()
// Do not use auto captions for Shorts.
&& !PlayerType.getCurrent().isNoneHiddenOrSlidingMinimized();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,12 @@ private static CharSequence onLithoTextLoaded(@NonNull Object conversionContext,

String conversionContextString = conversionContext.toString();

if (isRollingNumber && !conversionContextString.contains("video_action_bar.eml|")) {
if (isRollingNumber && !conversionContextString.contains("video_action_bar.eml")) {
return original;
}

final CharSequence replacement;
if (conversionContextString.contains("|segmented_like_dislike_button.eml|")) {
if (conversionContextString.contains("segmented_like_dislike_button.eml")) {
// Regular video.
ReturnYouTubeDislike videoData = currentVideoData;
if (videoData == null) {
Expand Down
Loading

0 comments on commit e5736fc

Please sign in to comment.