Skip to content

Commit

Permalink
first ShortLook-Telegram commit
Browse files Browse the repository at this point in the history
  • Loading branch information
RedenticDev committed Jan 31, 2021
0 parents commit a15b836
Show file tree
Hide file tree
Showing 10 changed files with 280 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# gitignore for Theos

*.deb
_/
theos/
theos
.theos
packages/
./packages/
obj/
./obj/
obj
.DS_Store
6 changes: 6 additions & 0 deletions FolderFinder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#import <Foundation/Foundation.h>

@interface FolderFinder : NSObject
+(NSString *)findSharedFolder:(NSString *)appName;
+(NSString *)findFolder:(NSString *)appName folder:(NSString *)dir;
@end
41 changes: 41 additions & 0 deletions FolderFinder.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Credit: u/Mordred666
// Source: https://reddit.com/r/jailbreakdevelopers/comments/5wb3tv/application_appgroup_path/

#import "FolderFinder.h"

@implementation FolderFinder

+ (NSString *)findSharedFolder:(NSString *)appName {
NSString *dir = @"/var/mobile/Containers/Shared/AppGroup/";
NSString *result = [self findFolder:appName folder:dir];
return result;
}

+ (NSString *)findFolder:(NSString *)appName folder:(NSString *)dir {
NSFileManager *manager = [NSFileManager defaultManager];

NSError *error = nil;
NSArray *folders = [manager contentsOfDirectoryAtPath:dir error:&error];

if (!error) {
for (NSString *folder in folders) {
NSString *folderPath = [dir stringByAppendingString:folder];
NSArray *items = [manager contentsOfDirectoryAtPath:folderPath error:&error];

for (NSString *itemPath in items) {
if ([itemPath rangeOfString:@".com.apple.mobile_container_manager.metadata.plist"].location != NSNotFound) {
NSString *fullpath = [NSString stringWithFormat:@"%@/%@", folderPath, itemPath];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:fullpath];

NSString *mcmmetadata = dict[@"MCMMetadataIdentifier"];
if (mcmmetadata && [mcmmetadata.lowercaseString isEqualToString:appName.lowercaseString]) {
return folderPath;
}
}
}
}
}
return nil;
}

@end
15 changes: 15 additions & 0 deletions Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDisplayName</key>
<string>Telegram</string>
<key>DDNotificationExternalProviderClasses</key>
<dict>
<key>TelegramContactPhotoProvider</key>
<string>ph.telegra.Telegraph</string>
</dict>
<key>DDNotificationExternalProviderAPIVersion</key>
<integer>1</integer>
</dict>
</plist>
20 changes: 20 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
ARCHS = armv7 arm64 arm64e

include $(THEOS)/makefiles/common.mk

BUNDLE_NAME = ShortLook-Telegram
$(BUNDLE_NAME)_CFLAGS = -fobjc-arc
$(BUNDLE_NAME)_FILES = $(wildcard *.m)
$(BUNDLE_NAME)_FRAMEWORKS = UIKit
$(BUNDLE_NAME)_INSTALL_PATH = /Library/Dynastic/ShortLook/Plugins/ContactPhotoProviders

include $(THEOS_MAKE_PATH)/bundle.mk

BUNDLE_PATH = $($(BUNDLE_NAME)_INSTALL_PATH)/$(BUNDLE_NAME).bundle

internal-stage::
$(ECHO_NOTHING)mkdir -p $(THEOS_STAGING_DIR)$(BUNDLE_PATH)$(ECHO_END)
$(ECHO_NOTHING)cp Info.plist $(THEOS_STAGING_DIR)$(BUNDLE_PATH)/Info.plist$(ECHO_END)

after-install::
install.exec "killall -9 SpringBoard"
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Telegram Contact Photos Provider for ShortLook

Show Telegram Contact Photos in ShortLook when you receive a Telegram notification!

(This is not ShortLook itself, but a plugin for it)
107 changes: 107 additions & 0 deletions ShortLook-API.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//
// WARNING:
// This file contains the required headers to compile a tweak that
// interacts with ShortLook's contact photo API. Do not modify the
// headers within, or it could lead to unexpected behaviour.
//
// ---
//
// ShortLook-API.h
//
// Created by AppleBetas on 2018-05-18.
// Copyright © 2018 Dynastic Development. All rights reserved.
//

#import <UIKit/UIKit.h>
@class NCNotificationRequest, UNNotificationContent;

/// A ShortLook-displayable notification representing a real user notification sent by an application to the system.
@interface DDUserNotification : NSObject
/// A custom notification title, separate from the application's title.
@property (nonatomic, retain, readonly) NSString *notificationTitle;

/// A dictionary of any extra information included by ShortLook.
@property (nonatomic, retain) NSDictionary *userInfo;

/// The system notification request that created this notification.
@property (nonatomic, readonly, retain) NCNotificationRequest *request;

/// The user notification's content, sent by the application.
- (UNNotificationContent *)content;

/// A dictionary of any extra information provided by the application sending the notification.
- (NSDictionary *)applicationUserInfo;

/// The bundle identifier of the application this notification represents.
- (NSString *)senderIdentifier;
@end

/// An object representing settings for the photo to be provided by a promise.
@interface DDNotificationContactPhotoSettings: NSObject
/// The background colour to show for the contact photo view if the provided image contains any transparency.
@property (nonatomic, retain) UIColor *backgroundColor;

/// Whether or not ShortLook should automatically cache the returned image from your provider and use it for all future notifications with the same photo identifier and application.
@property (nonatomic, assign) BOOL usesCaching;
@end

/// A promise representing a commitment to providing a contact icon for a notification.
@interface DDNotificationContactPhotoPromise: NSObject
/// An object holding the settings pertaining to the photo to be displayed.
@property (nonatomic, retain) DDNotificationContactPhotoSettings *settings;

/// Whether or not this promise has already been resolved or rejected.
@property (nonatomic, readonly, assign) BOOL isComplete;

// MARK: - Provider methods

/// Resolve this promise with the provided image, notifying ShortLook that you have received your image.
/// - NOTE: This method should only be ran from within `addResolver:`.
- (void)resolveWithImage:(UIImage *)image;

/// Reject this promise, notifying ShortLook that you failed to receive an image.
/// - NOTE: This method should only be ran from within `addResolver:`.
- (void)reject;
@end

/// An offer to fulfill a promise representing a commitment to providing a contact icon for a notification.
@interface DDNotificationContactPhotoPromiseOffer: NSObject
/// A unique identifier for the photo that will be provided by this promise.
@property (nonatomic, readonly, retain) NSString *photoIdentifier;

/// A string to replace the notification's title with, if it is required for your provider's context. Set to "" to remove the provided notification's title.
@property (nonatomic, retain) NSString *titleOverride;

/// A string to replace the notification's subtitle with, if it is required for your provider's context. Set to "" to remove the provided notification's subtitle.
@property (nonatomic, retain) NSString *subtitleOverride;

/// A string to replace the notification's body with, if it is required for your provider's context. Set to "" to remove the provided notification's body.
@property (nonatomic, retain) NSString *bodyOverride;

/// Initialize a promise with the provided photo identifier.
- (instancetype)initWithPhotoIdentifier:(NSString *)photoIdentifier;

/// Create a promise offer that will return the image at the provided URL, if needed.
+ (instancetype)offerDownloadingPromiseWithPhotoIdentifier:(NSString *)photoIdentifier fromURL:(NSURL *)url;

/// Create a promise offer that will return the image at the provided URL, if needed, with custom settings.
+ (instancetype)offerDownloadingPromiseWithPhotoIdentifier:(NSString *)photoIdentifier fromURL:(NSURL *)url withSettings:(DDNotificationContactPhotoSettings *)settings;

/// Create a promise offer that will instantly return the provided image.
+ (instancetype)offerInstantlyResolvingPromiseWithPhotoIdentifier:(NSString *)photoIdentifier image:(UIImage *)image;

/// Create a promise offer that will instantly return the provided image with custom settings.
+ (instancetype)offerInstantlyResolvingPromiseWithPhotoIdentifier:(NSString *)photoIdentifier image:(UIImage *)image withSettings:(DDNotificationContactPhotoSettings *)settings;

/// Add the block that will run if your image is needed (as it will not be in some cases, such as if your image is already cached by ShortLook).
/// If your provider does any long-running or asynchronous operations, they should be done using this method.
/// Any code run inside the provider block will be performed on a background thread.
- (void)fulfillWithBlock:(void (^)(DDNotificationContactPhotoPromise *promise))block;
@end

/// An object that can provide contact photos for ShortLook notifications.
@protocol DDNotificationContactPhotoProviding <NSObject>
@required
/// Returns an offer to fulfill a promise to provide a contact photo for a notification.
- (DDNotificationContactPhotoPromiseOffer *)contactPhotoPromiseOfferForNotification:(DDUserNotification *)notification;
@end
5 changes: 5 additions & 0 deletions TelegramContactPhotoProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#import "ShortLook-API.h"

@interface TelegramContactPhotoProvider : NSObject <DDNotificationContactPhotoProviding>
- (DDNotificationContactPhotoPromiseOffer *)contactPhotoPromiseOfferForNotification:(DDUserNotification *)notification;
@end
59 changes: 59 additions & 0 deletions TelegramContactPhotoProvider.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#import "FolderFinder.h"
#import "TelegramContactPhotoProvider.h"

@interface NCNotificationRequest
-(NSString *)threadIdentifier;
@end

@implementation TelegramContactPhotoProvider

- (DDNotificationContactPhotoPromiseOffer *)contactPhotoPromiseOfferForNotification:(DDUserNotification *)notification {
NCNotificationRequest *request = [notification request];
NSString *threadIdentifier = [request threadIdentifier];
NSString *sharedFolder = [FolderFinder findSharedFolder:@"group.ph.telegra.Telegraph"];
NSLog(@"[TLGM] Starting Telegram Contact Photo search");

if ([[threadIdentifier lowercaseString] isEqualToString:@"locked"]) { // Telegram is locked!
NSLog(@"[TLGM] Error: Telegram app is locked, no info provided");
} else if ([threadIdentifier hasPrefix:@"-"]) { // group/bot -> unsupported
/*
Current state for group/bot profile pictures:
- Local pictures: I know where they are stored, but I cannot find how to get their path from a threadID
as the "p:" folder technique used below for high-res is only available for standard conversations.
- Online download: It would probably be only available for public bots. Also, as far as I can see, the public
API is not available without the private key of the channel (why??) so I can't fetch bot picture online,
plus I miss at least one element for each technique I can think of.
- Database: I found nothing interesting in all local databases existing in Telegram folders.
*/
NSLog(@"[TLGM] Error: negative threadId (threadId = %@), group or bot -> unsupported", threadIdentifier);
} else { // casual convo
NSString *convoFolder = [NSString stringWithFormat:@"%@/telegram-data/accounts-metadata/spotlight/p:%@", sharedFolder, threadIdentifier];
NSLog(@"[TLGM] Good path found! Path: %@", convoFolder);
if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@/data.json", convoFolder]]) {
NSLog(@"[TLGM] Looking for High-res profile picture...");
NSData *jsonData = [NSData dataWithContentsOfFile:[NSString stringWithFormat:@"%@/data.json", convoFolder]];
NSError *error = nil;
NSDictionary *parsedData = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
if (!error) {
NSString *imagePath = [NSString stringWithFormat:@"%@/%@", sharedFolder, parsedData[@"avatarSourcePath"]];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
NSLog(@"[TLGM] High-res (%.fx%.f) profile picture found! Path: %@", image.size.width * image.scale, image.size.height * image.scale, imagePath);

return [NSClassFromString(@"DDNotificationContactPhotoPromiseOffer") offerInstantlyResolvingPromiseWithPhotoIdentifier:imagePath image:image];
}
NSLog(@"[TLGM] An error occurred while fetching High-res profile picture (error: %@)", error);
}
if ([[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithFormat:@"%@/avatar.png", convoFolder]]) {
NSString *imagePath = [NSString stringWithFormat:@"%@/avatar.png", convoFolder];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
NSLog(@"[TLGM] Low-res (%.fx%.f) avatar only found? (This is a rare bad case). Path: %@", image.size.width * image.scale, image.size.height * image.scale, imagePath);

return [NSClassFromString(@"DDNotificationContactPhotoPromiseOffer") offerInstantlyResolvingPromiseWithPhotoIdentifier:imagePath image:image];
}
NSLog(@"[TLGM] No avatar for this conversation");
}

return nil;
}

@end
9 changes: 9 additions & 0 deletions control
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Package: com.redenticdev.shortlook.plugin.contact-photo.telegram
Name: Telegram Contact Photos for ShortLook
Depends: mobilesubstrate, co.dynastic.ios.tweak.shortlook
Version: 1.0.0
Architecture: iphoneos-arm
Description: Show Telegram Contact Photos in ShortLook when you receive a Telegram notification!
Maintainer: RedenticDev
Author: RedenticDev
Section: Tweaks (ShortLook)

0 comments on commit a15b836

Please sign in to comment.