From cbd2fe866c8aa7ed630d748648850d0e5e5d069b Mon Sep 17 00:00:00 2001 From: James Shiffer <2191476+scoliono@users.noreply.github.com> Date: Wed, 21 Dec 2022 02:14:45 -0800 Subject: [PATCH] Cute and funny game --- cunnyfinder.xcodeproj/project.pbxproj | 55 ++++++++- cunnyfinder/AppDelegate.h | 4 +- cunnyfinder/AppDelegate.m | 48 ++++++-- cunnyfinder/cunnyfinder-Info.plist | 2 +- cunnyfinder/en.lproj/Credits.rtf | 16 +-- cunnyfinder/en.lproj/MainMenu.xib | 14 +-- cunnyfinder/libbooru/BooruClient.h | 29 +++++ cunnyfinder/libbooru/BooruClient.m | 81 +++++++++++++ cunnyfinder/libbooru/BooruImage.h | 27 +++++ cunnyfinder/libbooru/BooruImage.m | 109 ++++++++++++++++++ cunnyfinder/libbooru/BooruXMLParserDelegate.h | 30 +++++ cunnyfinder/libbooru/BooruXMLParserDelegate.m | 46 ++++++++ cunnyfinder/ui/ClickableImageView.h | 21 ++++ cunnyfinder/ui/ClickableImageView.m | 68 +++++++++++ 14 files changed, 522 insertions(+), 28 deletions(-) create mode 100644 cunnyfinder/libbooru/BooruClient.h create mode 100644 cunnyfinder/libbooru/BooruClient.m create mode 100644 cunnyfinder/libbooru/BooruImage.h create mode 100644 cunnyfinder/libbooru/BooruImage.m create mode 100644 cunnyfinder/libbooru/BooruXMLParserDelegate.h create mode 100644 cunnyfinder/libbooru/BooruXMLParserDelegate.m create mode 100644 cunnyfinder/ui/ClickableImageView.h create mode 100644 cunnyfinder/ui/ClickableImageView.m diff --git a/cunnyfinder.xcodeproj/project.pbxproj b/cunnyfinder.xcodeproj/project.pbxproj index 2250d26..3a0b5f2 100644 --- a/cunnyfinder.xcodeproj/project.pbxproj +++ b/cunnyfinder.xcodeproj/project.pbxproj @@ -7,6 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 802B076229515EE20019C2B1 /* BooruClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 802B076129515EE20019C2B1 /* BooruClient.m */; }; + 802B07682952C38C0019C2B1 /* BooruXMLParserDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 802B07672952C38C0019C2B1 /* BooruXMLParserDelegate.m */; }; + 802B076C2952CDBB0019C2B1 /* BooruImage.m in Sources */ = {isa = PBXBuildFile; fileRef = 802B076B2952CDBB0019C2B1 /* BooruImage.m */; }; + 802B076F2952D07D0019C2B1 /* ClickableImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 802B076E2952D07D0019C2B1 /* ClickableImageView.m */; }; BC6610FD294C62B900277180 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC6610FC294C62B900277180 /* Cocoa.framework */; }; BC661107294C62B900277180 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BC661105294C62B900277180 /* InfoPlist.strings */; }; BC661109294C62B900277180 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BC661108294C62B900277180 /* main.m */; }; @@ -30,7 +34,15 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - BC6610F9294C62B900277180 /* Cunny Corrector.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Cunny Corrector.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 802B076029515EE20019C2B1 /* BooruClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BooruClient.h; sourceTree = ""; }; + 802B076129515EE20019C2B1 /* BooruClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BooruClient.m; sourceTree = ""; }; + 802B07662952C38C0019C2B1 /* BooruXMLParserDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BooruXMLParserDelegate.h; sourceTree = ""; }; + 802B07672952C38C0019C2B1 /* BooruXMLParserDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BooruXMLParserDelegate.m; sourceTree = ""; }; + 802B076A2952CDBB0019C2B1 /* BooruImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BooruImage.h; sourceTree = ""; }; + 802B076B2952CDBB0019C2B1 /* BooruImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BooruImage.m; sourceTree = ""; }; + 802B076D2952D07D0019C2B1 /* ClickableImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ClickableImageView.h; sourceTree = ""; }; + 802B076E2952D07D0019C2B1 /* ClickableImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ClickableImageView.m; sourceTree = ""; }; + BC6610F9294C62B900277180 /* Cunny Collector.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Cunny Collector.app"; sourceTree = BUILT_PRODUCTS_DIR; }; BC6610FC294C62B900277180 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; BC6610FF294C62B900277180 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; BC661100294C62B900277180 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; @@ -72,6 +84,28 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 802B07692952CD640019C2B1 /* libbooru */ = { + isa = PBXGroup; + children = ( + 802B076029515EE20019C2B1 /* BooruClient.h */, + 802B076129515EE20019C2B1 /* BooruClient.m */, + 802B07662952C38C0019C2B1 /* BooruXMLParserDelegate.h */, + 802B07672952C38C0019C2B1 /* BooruXMLParserDelegate.m */, + 802B076A2952CDBB0019C2B1 /* BooruImage.h */, + 802B076B2952CDBB0019C2B1 /* BooruImage.m */, + ); + path = libbooru; + sourceTree = ""; + }; + 802B07732952F4D40019C2B1 /* ui */ = { + isa = PBXGroup; + children = ( + 802B076D2952D07D0019C2B1 /* ClickableImageView.h */, + 802B076E2952D07D0019C2B1 /* ClickableImageView.m */, + ); + path = ui; + sourceTree = ""; + }; BC6610F0294C62B900277180 = { isa = PBXGroup; children = ( @@ -85,7 +119,7 @@ BC6610FA294C62B900277180 /* Products */ = { isa = PBXGroup; children = ( - BC6610F9294C62B900277180 /* Cunny Corrector.app */, + BC6610F9294C62B900277180 /* Cunny Collector.app */, BC661119294C62BA00277180 /* cunnyfinderTests.octest */, ); name = Products; @@ -114,6 +148,8 @@ BC661102294C62B900277180 /* cunnyfinder */ = { isa = PBXGroup; children = ( + 802B07732952F4D40019C2B1 /* ui */, + 802B07692952CD640019C2B1 /* libbooru */, BC66110E294C62B900277180 /* AppDelegate.h */, BC66110F294C62B900277180 /* AppDelegate.m */, BC661111294C62BA00277180 /* MainMenu.xib */, @@ -170,7 +206,7 @@ ); name = cunnyfinder; productName = cunnyfinder; - productReference = BC6610F9294C62B900277180 /* Cunny Corrector.app */; + productReference = BC6610F9294C62B900277180 /* Cunny Collector.app */; productType = "com.apple.product-type.application"; }; BC661118294C62BA00277180 /* cunnyfinderTests */ = { @@ -206,6 +242,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ); mainGroup = BC6610F0294C62B900277180; @@ -263,6 +300,10 @@ files = ( BC661109294C62B900277180 /* main.m in Sources */, BC661110294C62B900277180 /* AppDelegate.m in Sources */, + 802B076C2952CDBB0019C2B1 /* BooruImage.m in Sources */, + 802B076F2952D07D0019C2B1 /* ClickableImageView.m in Sources */, + 802B076229515EE20019C2B1 /* BooruClient.m in Sources */, + 802B07682952C38C0019C2B1 /* BooruXMLParserDelegate.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -386,7 +427,8 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "cunnyfinder/cunnyfinder-Prefix.pch"; INFOPLIST_FILE = "cunnyfinder/cunnyfinder-Info.plist"; - PRODUCT_NAME = "Cunny Corrector"; + PRODUCT_BUNDLE_IDENTIFIER = jp.femboyfinancial.CunnyCollector; + PRODUCT_NAME = "Cunny Collector"; WRAPPER_EXTENSION = app; }; name = Debug; @@ -398,7 +440,8 @@ GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "cunnyfinder/cunnyfinder-Prefix.pch"; INFOPLIST_FILE = "cunnyfinder/cunnyfinder-Info.plist"; - PRODUCT_NAME = "Cunny Corrector"; + PRODUCT_BUNDLE_IDENTIFIER = jp.femboyfinancial.CunnyCollector; + PRODUCT_NAME = "Cunny Collector"; WRAPPER_EXTENSION = app; }; name = Release; @@ -452,6 +495,7 @@ BC66112C294C62BA00277180 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; BC66112D294C62BA00277180 /* Build configuration list for PBXNativeTarget "cunnyfinderTests" */ = { isa = XCConfigurationList; @@ -460,6 +504,7 @@ BC66112F294C62BA00277180 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; diff --git a/cunnyfinder/AppDelegate.h b/cunnyfinder/AppDelegate.h index 946dba8..4542362 100644 --- a/cunnyfinder/AppDelegate.h +++ b/cunnyfinder/AppDelegate.h @@ -8,10 +8,12 @@ #import -@interface AppDelegate : NSObject +@interface AppDelegate : NSObject @property (assign) IBOutlet NSWindow *window; -(IBAction)actionUohhh:(id)sender; +-(NSRect)randomPositionWithWidth:(int)width height:(int)height; +-(void)addWaifu:(id)btn; @end diff --git a/cunnyfinder/AppDelegate.m b/cunnyfinder/AppDelegate.m index 8fd893b..a4c3f9b 100644 --- a/cunnyfinder/AppDelegate.m +++ b/cunnyfinder/AppDelegate.m @@ -7,12 +7,48 @@ // #import "AppDelegate.h" +#import "libbooru/BooruClient.h" +#import "ui/ClickableImageView.h" @implementation AppDelegate -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification +BooruClient* booru; + +-(void)applicationDidFinishLaunching:(NSNotification *)aNotification { - // Insert code here to initialize your application + booru = [[BooruClient alloc] init:@[@"hatsune_miku", @"kuroki_tomoko", @"monika_(doki_doki_literature_club)", @"megumin"]]; +} + +-(NSRect)randomPositionWithWidth:(int)width height:(int)height +{ + float x = arc4random_uniform(self.window.frame.size.width - width); + float y = arc4random_uniform(self.window.frame.size.height - height); + NSRect rect = NSMakeRect(x, y, width, height); + return rect; +} + +-(void)addWaifu:(id)btn +{ + // find the image + BooruImage* img = [booru search]; + + // download and show image + NSRect frame = [self randomPositionWithWidth:[img previewWidth] height:[img previewHeight]]; + ClickableImageView* imgView = [[ClickableImageView alloc] initWithFrame:frame imageUrl:[img fileUrl]]; + NSURL* displayUrl; + if ([img hasSample]) + { + displayUrl = [img sampleUrl]; + } + else + { + displayUrl = [img fileUrl]; + } + [booru downloadAndDisplayImage:displayUrl inView:imgView]; + [self.window.contentView addSubview:imgView positioned:NSWindowBelow relativeTo:btn]; + + // cleanup + [booru reset]; } -(IBAction)actionUohhh:(id)sender @@ -24,13 +60,10 @@ [alert setInformativeText:@"Damn bratty girl, seducing an adult... correction is needed!"]; [alert setAlertStyle:NSInformationalAlertStyle]; [alert runModal]; - */ - float x = arc4random_uniform(self.window.frame.size.width - 48); - float y = arc4random_uniform(self.window.frame.size.height - 48); + */ bool brat = arc4random_uniform(20) == 0; - NSRect rect = NSMakeRect(x, y, 48, 48); - NSTextField *label = [[NSTextField alloc] initWithFrame:rect]; + NSTextField *label = [[NSTextField alloc] initWithFrame:[self randomPositionWithWidth:48 height:48]]; [label setEditable:false]; [label setBezeled:false]; [label setFont:[NSFont fontWithName:@"Apple Color Emoji" size:32]]; @@ -38,6 +71,7 @@ [label setAlignment:NSCenterTextAlignment]; if (brat) { [label setStringValue:@"💢"]; + [self addWaifu:sender]; } else { [label setStringValue:@"😭"]; } diff --git a/cunnyfinder/cunnyfinder-Info.plist b/cunnyfinder/cunnyfinder-Info.plist index ce79a78..ecf5402 100644 --- a/cunnyfinder/cunnyfinder-Info.plist +++ b/cunnyfinder/cunnyfinder-Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - jp.femboyfinancial.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/cunnyfinder/en.lproj/Credits.rtf b/cunnyfinder/en.lproj/Credits.rtf index 5518137..b80266b 100644 --- a/cunnyfinder/en.lproj/Credits.rtf +++ b/cunnyfinder/en.lproj/Credits.rtf @@ -1,15 +1,17 @@ -{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf510 -{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\rtf1\ansi\ansicpg1252\cocoartf2580 +\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica-Bold;\f1\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} +{\*\expandedcolortbl;;} \vieww9600\viewh8400\viewkind0 -\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\partightenfactor0 \f0\b\fs24 \cf0 Programming: -\b0 \ +\f1\b0 \ James Shiffer\ \ -\b Special Thanks: -\b0 \ +\f0\b Special Thanks: +\f1\b0 \ abmayo\ - dorontabi} \ No newline at end of file + dorontabi\ + Gelbooru.com} \ No newline at end of file diff --git a/cunnyfinder/en.lproj/MainMenu.xib b/cunnyfinder/en.lproj/MainMenu.xib index 5ae2c09..7bd5063 100644 --- a/cunnyfinder/en.lproj/MainMenu.xib +++ b/cunnyfinder/en.lproj/MainMenu.xib @@ -42,7 +42,7 @@ - Cunny Corrector + Cunny Collector 1048576 2147483647 @@ -56,11 +56,11 @@ submenuAction: - Cunny Corrector + Cunny Collector - About Cunny Corrector + About Cunny Collector 2147483647 @@ -125,7 +125,7 @@ - Hide Cunny + Hide Cunny Collector h 1048576 2147483647 @@ -163,7 +163,7 @@ - Quit Cunny Corrector + Quit Cunny Collector q 1048576 2147483647 @@ -366,7 +366,7 @@ - cunnyfinder Help + Cunny Collector Help ? 1048576 2147483647 @@ -385,7 +385,7 @@ 2 {{335, 390}, {480, 360}} 1954021376 - Cunny Corrector + Cunny Collector NSWindow diff --git a/cunnyfinder/libbooru/BooruClient.h b/cunnyfinder/libbooru/BooruClient.h new file mode 100644 index 0000000..311994b --- /dev/null +++ b/cunnyfinder/libbooru/BooruClient.h @@ -0,0 +1,29 @@ +// +// BooruClient.h +// cunnyfinder +// +// Created by James Shiffer on 12/19/22. +// Copyright © 2022 FemboyFinancial. All rights reserved. +// + +#import +#import "BooruImage.h" +#import "BooruXMLParserDelegate.h" + +@interface BooruClient : NSObject + +@property NSString* urlFormat; +@property NSString* tags; +@property NSMutableArray* waifus; +@property NSDictionary* metadata; +@property NSImageView* imageView; + +-(id)init:(NSArray *)waifus; +-(void)reset; +-(BooruImage *)search; +-(void)downloadAndDisplayImage:(NSURL *)url inView:(NSImageView *)imageView; +-(void)downloadImage:(NSURL *)url; +-(void)displayImage:(NSImage *)image; ++(NSString *)urlEncode:(NSString *)str; + +@end diff --git a/cunnyfinder/libbooru/BooruClient.m b/cunnyfinder/libbooru/BooruClient.m new file mode 100644 index 0000000..4f0e711 --- /dev/null +++ b/cunnyfinder/libbooru/BooruClient.m @@ -0,0 +1,81 @@ +// +// BooruClient.m +// cunnyfinder +// +// Created by James Shiffer on 12/19/22. +// Copyright © 2022 FemboyFinancial. All rights reserved. +// + +#import "BooruClient.h" + +@implementation BooruClient + +-(id)init:(NSArray *)waifus +{ + self.urlFormat = @"https://gelbooru.com/index.php?page=dapi&s=post&q=index&limit=1&tags=%@%%20%@"; + self.tags = @"score%3A%3E%3D10%20sort%3Arandom%201girl%20solo"; + self.waifus = [[NSMutableArray alloc] initWithArray:waifus]; + self.metadata = nil; + return self; +} + ++(NSString *)urlEncode:(NSString*)str +{ + CFStringRef urlString = CFURLCreateStringByAddingPercentEscapes( + NULL, + (CFStringRef)str, + NULL, + (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ", + kCFStringEncodingUTF8 + ); + return (NSString *)CFBridgingRelease(urlString); +} + + +-(BooruImage *)search +{ + NSString* randomWaifu = self.waifus[arc4random_uniform(self.waifus.count)]; + NSLog(@"searching for pics of %@", randomWaifu); + NSString* urlStr = [[NSString alloc] initWithFormat:self.urlFormat, self.tags, [BooruClient urlEncode:randomWaifu]]; + NSURL* url = [NSURL URLWithString:urlStr]; + NSXMLParser* xml = [[NSXMLParser alloc] initWithContentsOfURL:url]; + BooruXMLParserDelegate* parser = [[BooruXMLParserDelegate alloc] init]; + [xml setDelegate:parser]; + [xml setShouldProcessNamespaces:NO]; + [xml setShouldReportNamespacePrefixes:NO]; + [xml setShouldResolveExternalEntities:NO]; + [xml parse]; + if ([xml parserError]) + { + NSLog(@"parsing error: %@", [xml parserError]); + } + NSLog(@"found image id: %@", parser.data[@"id"]); + return [[BooruImage alloc] init:parser.data]; +} + +-(void)downloadAndDisplayImage:(NSURL *)url inView:(NSImageView *)imageView +{ + self.imageView = imageView; + NSOperationQueue* queue = [NSOperationQueue new]; + NSInvocationOperation* operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadImage:) object:url]; + [queue addOperation:operation]; +} + +-(void)downloadImage:(NSURL *)url +{ + NSData* imageData = [[NSData alloc] initWithContentsOfURL:url]; + NSImage* image = [[NSImage alloc] initWithData:imageData]; + [self performSelectorOnMainThread:@selector(displayImage:) withObject:image waitUntilDone:YES]; +} + +-(void)displayImage:(NSImage *)image +{ + self.imageView.image = image; +} + +-(void)reset +{ + self.metadata = nil; +} + +@end diff --git a/cunnyfinder/libbooru/BooruImage.h b/cunnyfinder/libbooru/BooruImage.h new file mode 100644 index 0000000..f52a305 --- /dev/null +++ b/cunnyfinder/libbooru/BooruImage.h @@ -0,0 +1,27 @@ +// +// BooruImage.h +// cunnyfinder +// +// Created by James Shiffer on 12/20/22. +// Copyright © 2022 FemboyFinancial. All rights reserved. +// + +#import + +@interface BooruImage : NSObject + +@property NSDictionary* metadata; + +-(id)init:(NSDictionary *)metadata; +-(int)width; +-(int)height; +-(int)previewWidth; +-(int)previewHeight; +-(int)sampleWidth; +-(int)sampleHeight; +-(bool)hasSample; +-(NSURL *)fileUrl; +-(NSURL *)previewUrl; +-(NSURL *)sampleUrl; + +@end diff --git a/cunnyfinder/libbooru/BooruImage.m b/cunnyfinder/libbooru/BooruImage.m new file mode 100644 index 0000000..00dcabb --- /dev/null +++ b/cunnyfinder/libbooru/BooruImage.m @@ -0,0 +1,109 @@ +// +// BooruImage.m +// cunnyfinder +// +// Created by James Shiffer on 12/20/22. +// Copyright © 2022 FemboyFinancial. All rights reserved. +// + +#import "BooruImage.h" + +@implementation BooruImage + +-(id)init:(NSDictionary *)metadata +{ + self.metadata = [[NSDictionary alloc] initWithDictionary:metadata]; + return self; +} + +-(int)width +{ + if (!self.metadata) + { + return -1; + } + return [self.metadata[@"width"] integerValue]; +} + +-(int)height +{ + if (!self.metadata) + { + return -1; + } + return [self.metadata[@"height"] integerValue]; +} + +-(int)previewWidth +{ + if (!self.metadata) + { + return -1; + } + return [self.metadata[@"preview_width"] integerValue]; +} + +-(int)previewHeight +{ + if (!self.metadata) + { + return -1; + } + return [self.metadata[@"preview_height"] integerValue]; +} + +-(int)sampleWidth +{ + if (!self.metadata || ![self hasSample]) + { + return -1; + } + return [self.metadata[@"sample_width"] integerValue]; +} + +-(int)sampleHeight +{ + if (!self.metadata || ![self hasSample]) + { + return -1; + } + return [self.metadata[@"sample_height"] integerValue]; +} + +-(NSURL *)fileUrl +{ + if (!self.metadata) + { + return nil; + } + return [NSURL URLWithString:self.metadata[@"file_url"]]; +} + +-(NSURL *)previewUrl +{ + if (!self.metadata) + { + return nil; + } + return [NSURL URLWithString:self.metadata[@"preview_url"]]; +} + +-(NSURL *)sampleUrl +{ + if (!self.metadata || ![self hasSample]) + { + return nil; + } + return [NSURL URLWithString:self.metadata[@"sample_url"]]; +} + +-(bool)hasSample +{ + if (!self.metadata) + { + return nil; + } + return [self.metadata[@"sample"] boolValue]; +} + +@end diff --git a/cunnyfinder/libbooru/BooruXMLParserDelegate.h b/cunnyfinder/libbooru/BooruXMLParserDelegate.h new file mode 100644 index 0000000..4b331d2 --- /dev/null +++ b/cunnyfinder/libbooru/BooruXMLParserDelegate.h @@ -0,0 +1,30 @@ +// +// BooruXMLParserDelegate.h +// cunnyfinder +// +// Created by James Shiffer on 12/20/22. +// Copyright © 2022 FemboyFinancial. All rights reserved. +// + +#import + +@interface BooruXMLParserDelegate : NSObject + +@property NSMutableDictionary* data; + +-(id)init; +-(void)parser:(NSXMLParser *)parser + didStartElement:(NSString *)elementName + namespaceURI:(NSString *)namespaceURI + qualifiedName:(NSString *)qName + attributes:(NSDictionary *)attributeDict; + +-(void)parser:(NSXMLParser *)parser + foundCharacters:(NSString *)string; + +-(void)parser:(NSXMLParser *)parser + didEndElement:(NSString *)elementName + namespaceURI:(NSString *)namespaceURI + qualifiedName:(NSString *)qName; + +@end diff --git a/cunnyfinder/libbooru/BooruXMLParserDelegate.m b/cunnyfinder/libbooru/BooruXMLParserDelegate.m new file mode 100644 index 0000000..694f2f4 --- /dev/null +++ b/cunnyfinder/libbooru/BooruXMLParserDelegate.m @@ -0,0 +1,46 @@ +// +// BooruXMLParserDelegate.m +// cunnyfinder +// +// Created by James Shiffer on 12/20/22. +// Copyright © 2022 FemboyFinancial. All rights reserved. +// + +#import "BooruXMLParserDelegate.h" + +@implementation BooruXMLParserDelegate + +NSMutableString* value; + +-(id)init +{ + self.data = [[NSMutableDictionary alloc] init]; + return self; +} + +-(void)parser:(NSXMLParser *)parser + didStartElement:(NSString *)elementName + namespaceURI:(NSString *)namespaceURI + qualifiedName:(NSString *)qName + attributes:(NSDictionary *)attributeDict +{ + value = [NSMutableString string]; +} + +-(void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string +{ + [value appendString:string]; +} + +-(void)parser:(NSXMLParser *)parser + didEndElement:(NSString *)elementName + namespaceURI:(NSString *)namespaceURI + qualifiedName:(NSString *)qName +{ + if (value) + { + [self.data setObject:value forKey:elementName]; + } +} + +@end diff --git a/cunnyfinder/ui/ClickableImageView.h b/cunnyfinder/ui/ClickableImageView.h new file mode 100644 index 0000000..b05717c --- /dev/null +++ b/cunnyfinder/ui/ClickableImageView.h @@ -0,0 +1,21 @@ +// +// ClickableImageView.h +// cunnyfinder +// +// Created by James Shiffer on 12/20/22. +// Copyright © 2022 FemboyFinancial. All rights reserved. +// + +#import + +@interface ClickableImageView : NSImageView + +@property NSURL* fileUrl; + +-(id)initWithFrame:(NSRect)frame imageUrl:(NSURL *)fileUrl; +-(void)mouseDown:(NSEvent *)event; +-(void)downloadImage:(NSString *)filePath; +-(void)downloadAndSaveImage:(NSString *)filePath; +-(void)showWarning:(id)sender; + +@end diff --git a/cunnyfinder/ui/ClickableImageView.m b/cunnyfinder/ui/ClickableImageView.m new file mode 100644 index 0000000..64b276a --- /dev/null +++ b/cunnyfinder/ui/ClickableImageView.m @@ -0,0 +1,68 @@ +// +// ClickableImageView.m +// cunnyfinder +// +// Created by James Shiffer on 12/20/22. +// Copyright © 2022 FemboyFinancial. All rights reserved. +// + +#import "ClickableImageView.h" + +@implementation ClickableImageView + +-(id)initWithFrame:(NSRect)frame imageUrl:(NSURL *)fileUrl +{ + self = [super initWithFrame:frame]; + self.fileUrl = fileUrl; + return self; +} + +-(void)drawRect:(NSRect)dirtyRect +{ + [super drawRect:dirtyRect]; + // Drawing code here. +} + +-(void)downloadImage:(NSString *)filePath +{ + NSOperationQueue* queue = [NSOperationQueue new]; + NSInvocationOperation* operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(downloadAndSaveImage:) object:filePath]; + [queue addOperation:operation]; +} + +-(void)downloadAndSaveImage:(NSString *)filePath +{ + NSData* imageData = [[NSData alloc] initWithContentsOfURL:self.fileUrl]; + NSFileManager* fs = [[NSFileManager alloc] init]; + BOOL success = [fs createFileAtPath:filePath contents:imageData attributes:nil]; + if (!success) + { + [self performSelectorOnMainThread:@selector(showWarning:) withObject:nil waitUntilDone:YES]; + } +} + +-(void)showWarning:(id)sender +{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert addButtonWithTitle:@"OK"]; + [alert setMessageText:@"Uohhh!"]; + [alert setIcon:[NSImage imageNamed:NSImageNameCaution]]; + [alert setInformativeText:@"Damn bratty file failed to save... correction is needed!"]; + [alert setAlertStyle:NSWarningAlertStyle]; + [alert beginSheetModalForWindow:self.window completionHandler:nil]; +} + +-(void)mouseDown:(NSEvent *)event +{ + NSSavePanel* panel = [NSSavePanel savePanel]; + panel.allowedFileTypes = @[[self.fileUrl pathExtension]]; + panel.nameFieldStringValue = [self.fileUrl lastPathComponent]; + [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result) { + if (result == NSFileHandlingPanelOKButton) + { + [self downloadImage:[panel filename]]; + } + }]; +} + +@end