Skip to content

Commit

Permalink
Merge pull request #3 from asdfzxcvbn/main
Browse files Browse the repository at this point in the history
v1.1
  • Loading branch information
whoeevee authored Apr 21, 2024
2 parents 1208b32 + a51c500 commit 0c1278e
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 20 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ include $(THEOS)/makefiles/common.mk
TWEAK_NAME = EeveeSpotify

$(TWEAK_NAME)_FILES = $(shell find src -name '*.m' -o -name '*.x')
$(TWEAK_NAME)_CFLAGS = -fobjc-arc -Wno-unused-variable
$(TWEAK_NAME)_CFLAGS = -fobjc-arc
$(TWEAK_NAME)_FRAMEWORKS = UIKit
$(TWEAK_NAME)_LOGOS_DEFAULT_GENERATOR = internal

include $(THEOS_MAKE_PATH)/tweak.mk
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ This branch contains the same tweak but rewritten in Objective-C by [asdfzxcvbn]

After looking into it, I discovered that Orion is not the problem. Instead [pyzule](https://github.com/asdfzxcvbn/pyzule) wasn't injecting CydiaSubstrate for unknown reasons, resulting in ipa crashes.

However, the Objective-C version isn't stable. You might need to restart the app a lot to get Premium. Therefore, it's better to use the Swift version.

~~However, the Objective-C version isn't stable. You might need to restart the app a lot to get Premium. Therefore, it's better to use the Swift version.~~

After updating the Objective-C version, it should be just as stable as the Swift version. However, your results may vary, so you should try both if one isn't working for you.
4 changes: 2 additions & 2 deletions control
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
Package: com.eevee.spotify
Name: EeveeSpotify
Version: 1.0
Version: 1.1
Architecture: iphoneos-arm
Description: A tweak to get Spotify Premium for free, just like Spotilife
Maintainer: Eevee
Author: Eevee
Section: Tweaks
Depends: ${ORION}, firmware (>= 14.0)
Depends: firmware (>= 15.0)
7 changes: 5 additions & 2 deletions src/EVEBundleHelper.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#import <Foundation/Foundation.h>
#import <libroot.h>
#import <UIKit/UIKit.h>

@interface EVEBundleHelper : NSObject
@property (nonatomic, strong, readonly) NSBundle *bundle;
+ (instancetype)sharedHelper;
- (NSData *)premiumBlankData;
- (void)showPopupWithTitle:(NSString *)title message:(NSString *)msg buttonText:(NSString *)bText;
@end

@interface UITabBarButtonLabel : UILabel
@end
18 changes: 18 additions & 0 deletions src/EVEBundleHelper.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#import "EVEBundleHelper.h"
#import <libroot.h>

@implementation EVEBundleHelper
@synthesize bundle = _bundle;
Expand Down Expand Up @@ -30,4 +31,21 @@ - (instancetype)init {
- (NSData *)premiumBlankData {
return [NSData dataWithContentsOfURL:[self.bundle URLForResource:@"premiumblank" withExtension:@"bnk"]];
}

- (void)showPopupWithTitle:(NSString *)title message:(NSString *)msg buttonText:(NSString *)bText {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title
message:msg
preferredStyle:UIAlertControllerStyleAlert];

[alert addAction:[UIAlertAction actionWithTitle:bText
style:UIAlertActionStyleDefault
handler:nil]];

[UIApplication.sharedApplication.delegate.window.rootViewController
presentViewController:alert animated:YES completion:nil];
});
});
}
@end
20 changes: 20 additions & 0 deletions src/SpotifyHidePremium.x
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#import "EVEBundleHelper.h"

%hook UITabBar
- (NSArray *)items {
return [%orig subarrayWithRange:NSMakeRange(0, 3)]; // there is only one UITabBar, so no problem
}
%end

// this method is called quite a lot, but only when you switch tabs, so it's fine i guess
%hook UITabBarButtonLabel
- (NSString *)text {
NSString *t = %orig;

// comment while open sourcing: i originally thought i fucked up because "Premium" wouldn't match other languages.
// however somehow this actually does work? for all languages?? weird, but whatever, no complaints lmao
if ([t isEqualToString:@"Premium"]) [self.superview removeFromSuperview];

return t;
}
%end
50 changes: 36 additions & 14 deletions src/Tweak.x
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,53 @@
%end

%hook AppDelegate
- (BOOL)application:(id)app didFinishLaunchingWithOptions:(id)opts {
- (BOOL)application:(id)app willFinishLaunchingWithOptions:(id)opts {
%orig(app, opts);

@try {
NSArray<NSURL *> *fileURLs = [[NSFileManager defaultManager]
URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask];
NSURL *filePath = [fileURLs.firstObject URLByAppendingPathComponent:@"PersistentCache/offline.bnk"];

if ([[NSFileManager defaultManager] fileExistsAtPath:filePath.path]) {
NSData *fileData = [NSData dataWithContentsOfURL:filePath];
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath.path]) {
NSLog(@"[EeveeSpotify] Not activating due to nonexistent file: %@", filePath.path);

NSUInteger usernameLength = (NSUInteger)(((const char *)[fileData bytes])[8]);
NSData *usernameData = [fileData subdataWithRange:NSMakeRange(9, usernameLength)];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[[EVEBundleHelper sharedHelper] showPopupWithTitle:@"EeveeSpotify"
message:@"An offline.bnk file was not found. Please log in and restart the app when you're done!"
buttonText:@"Okay!"];
});

NSMutableData *blankData = [[[EVEBundleHelper sharedHelper] premiumBlankData] mutableCopy];
return YES;
};

// range(whatever, 0) is for INSERTING data (Data.insert swift equivalent) (also needs length: i think?)
[blankData replaceBytesInRange:NSMakeRange(8, 0) withBytes:(const void *)&usernameLength length:1];
[blankData replaceBytesInRange:NSMakeRange(9, 0) withBytes:[usernameData bytes] length:[usernameData length]];
NSData *fileData = [NSData dataWithContentsOfURL:filePath];
NSUInteger usernameLength = (NSUInteger)(((const char *)[fileData bytes])[8]);
NSData *usernameData = [fileData subdataWithRange:NSMakeRange(9, usernameLength)];
NSMutableData *blankData = [[[EVEBundleHelper sharedHelper] premiumBlankData] mutableCopy];

[blankData writeToURL:filePath atomically:NO];
NSLog(@"[EeveeSpotify] Successfully applied");
} else {
NSLog(@"[EeveeSpotify] Not activating due to nonexistent file: %@", filePath.path);
}
// range(whatever, 0) is for INSERTING data (Data.insert swift equivalent) (also needs length: i think?)
[blankData replaceBytesInRange:NSMakeRange(8, 0) withBytes:(const void *)&usernameLength length:1];
[blankData replaceBytesInRange:NSMakeRange(9, 0) withBytes:[usernameData bytes] length:[usernameData length]];

[blankData writeToURL:filePath atomically:NO];
NSLog(@"[EeveeSpotify] Successfully applied");

// runs in background, reapplies every 20 seconds, maybe this could be useful?
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
for (;;) {
// waits 20 seconds without blocking thread
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20.0 * NSEC_PER_SEC));
dispatch_after(delay, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

[blankData writeToURL:filePath atomically:NO];
NSLog(@"[EeveeSpotify] Successfully reapplied");
};
});
} @catch (NSException *error) {
NSLog(@"[EeveeSpotify] Unable to apply tweak: %@", error);
}
Expand Down

0 comments on commit 0c1278e

Please sign in to comment.