diff --git a/.gitignore b/.gitignore
new file mode 100755
index 0000000..310b10c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,13 @@
+# gitignore for Theos
+
+*.deb
+_/
+theos/
+theos
+.theos
+packages/
+./packages/
+obj/
+./obj/
+obj
+.DS_Store
diff --git a/FolderFinder.h b/FolderFinder.h
new file mode 100644
index 0000000..f191627
--- /dev/null
+++ b/FolderFinder.h
@@ -0,0 +1,4 @@
+@interface FolderFinder : NSObject
+ +(NSString*) findSharedFolder:(NSString*) appName;
+ +(NSString*) findFolder:(NSString*) appName folder:(NSString*) dir;
+@end
diff --git a/FolderFinder.m b/FolderFinder.m
new file mode 100644
index 0000000..f697c3a
--- /dev/null
+++ b/FolderFinder.m
@@ -0,0 +1,40 @@
+// Credit: u/Mordred666
+// Source: https://reddit.com/r/jailbreakdevelopers/comments/5wb3tv/application_appgroup_path/
+
+#import "FolderFinder.h"
+
+@implementation FolderFinder : NSObject
+ +(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
diff --git a/Info.plist b/Info.plist
new file mode 100755
index 0000000..cfac928
--- /dev/null
+++ b/Info.plist
@@ -0,0 +1,15 @@
+
+
+
+
+ CFBundleDisplayName
+ Viber
+ DDNotificationExternalProviderClasses
+
+ ViberContactPhotoProvider
+ com.viber
+
+ DDNotificationExternalProviderAPIVersion
+ 1
+
+
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..add6066
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+ARCHS = armv7 arm64
+
+include $(THEOS)/makefiles/common.mk
+
+BUNDLE_NAME = ShortLook-Viber
+$(BUNDLE_NAME)_CFLAGS = -fobjc-arc
+$(BUNDLE_NAME)_FILES = $(wildcard *.m)
+$(BUNDLE_NAME)_FRAMEWORKS = UIKit
+$(BUNDLE_NAME)_INSTALL_PATH = /Library/Dynastic/ShortLook/Plugins/ContactPhotoProviders
+$(BUNDLE_NAME)_LDFLAGS = -lsqlite3
+
+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"
diff --git a/README.md b/README.md
new file mode 100755
index 0000000..f016939
--- /dev/null
+++ b/README.md
@@ -0,0 +1,5 @@
+# Viber Contact Photo Provider for ShortLook
+
+Show Viber users' profile pictures in ShortLook when you receive a Viber notification!
+
+(This is not ShortLook itself, but a plugin for it)
diff --git a/ShortLook-API.h b/ShortLook-API.h
new file mode 100755
index 0000000..2c5cc07
--- /dev/null
+++ b/ShortLook-API.h
@@ -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
+@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
+@required
+/// Returns an offer to fulfill a promise to provide a contact photo for a notification.
+- (DDNotificationContactPhotoPromiseOffer *)contactPhotoPromiseOfferForNotification:(DDUserNotification *)notification;
+@end
diff --git a/ViberContactPhotoProvider.h b/ViberContactPhotoProvider.h
new file mode 100755
index 0000000..b729732
--- /dev/null
+++ b/ViberContactPhotoProvider.h
@@ -0,0 +1,5 @@
+#import "ShortLook-API.h"
+
+@interface ViberContactPhotoProvider : NSObject
+- (DDNotificationContactPhotoPromiseOffer *)contactPhotoPromiseOfferForNotification:(DDUserNotification *)notification;
+@end
diff --git a/ViberContactPhotoProvider.m b/ViberContactPhotoProvider.m
new file mode 100755
index 0000000..70543ce
--- /dev/null
+++ b/ViberContactPhotoProvider.m
@@ -0,0 +1,36 @@
+#import
+#import "FolderFinder.h"
+#import "ViberContactPhotoProvider.h"
+
+@implementation ViberContactPhotoProvider
+ - (DDNotificationContactPhotoPromiseOffer *)contactPhotoPromiseOfferForNotification:(DDUserNotification *)notification {
+ NSString *containerPath = [FolderFinder findSharedFolder:@"group.viber.share.container"];
+ NSString *databasePath = [NSString stringWithFormat:@"%@/com.viber/database/Contacts.data", containerPath];
+ NSString *iconsPath = [NSString stringWithFormat:@"%@/com.viber/ViberIcons", containerPath];
+
+ NSString *senderMemberId = [notification.applicationUserInfo valueForKey:@"senderMemberId"];
+
+ const char *dbpath = [databasePath UTF8String];
+ sqlite3 *_viberdb;
+
+ if (sqlite3_open(dbpath, &_viberdb) == SQLITE_OK) {
+ const char *stmt = [[NSString stringWithFormat:@"SELECT ZICONID FROM ZMEMBER WHERE ZMEMBERID = '%@' AND ZICONSTATE = 'iconExist';", senderMemberId] UTF8String];
+ sqlite3_stmt *statement;
+
+ if (sqlite3_prepare_v2(_viberdb, stmt, -1, &statement, NULL) == SQLITE_OK) {
+ if (sqlite3_step(statement) == SQLITE_ROW) {
+ const unsigned char *result = sqlite3_column_text(statement, 0);
+ NSString *imageName = [NSString stringWithUTF8String:(char *)result];
+ NSString *imageURL = [NSString stringWithFormat:@"%@/%@.jpg", iconsPath, imageName];
+ UIImage *image = [UIImage imageWithContentsOfFile:imageURL];
+
+ return [NSClassFromString(@"DDNotificationContactPhotoPromiseOffer") offerInstantlyResolvingPromiseWithPhotoIdentifier:imageURL image:image];
+ }
+ sqlite3_finalize(statement);
+ }
+ sqlite3_close(_viberdb);
+ }
+
+ return nil;
+ }
+@end
diff --git a/control b/control
new file mode 100755
index 0000000..ba74d70
--- /dev/null
+++ b/control
@@ -0,0 +1,9 @@
+Package: ch.marcoroth.shortlook.plugin.contact-photo.viber
+Name: Viber Profile Pictures for ShortLook
+Depends: mobilesubstrate, co.dynastic.ios.tweak.shortlook
+Version: 1.0.0
+Architecture: iphoneos-arm
+Description: Show Viber users' profile pictures in ShortLook when you receive a Viber notification!
+Maintainer: Marco Roth
+Author: Marco Roth
+Section: Tweaks (ShortLook)