Cute and funny game

This commit is contained in:
James Shiffer 2022-12-21 02:14:45 -08:00
parent e23deb75e3
commit cbd2fe866c
No known key found for this signature in database
GPG Key ID: C0DB8774A1B3BA45
14 changed files with 522 additions and 28 deletions

View File

@ -7,6 +7,10 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* 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 */; }; BC6610FD294C62B900277180 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC6610FC294C62B900277180 /* Cocoa.framework */; };
BC661107294C62B900277180 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BC661105294C62B900277180 /* InfoPlist.strings */; }; BC661107294C62B900277180 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = BC661105294C62B900277180 /* InfoPlist.strings */; };
BC661109294C62B900277180 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BC661108294C62B900277180 /* main.m */; }; BC661109294C62B900277180 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = BC661108294C62B900277180 /* main.m */; };
@ -30,7 +34,15 @@
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXFileReference 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 = "<group>"; };
802B076129515EE20019C2B1 /* BooruClient.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BooruClient.m; sourceTree = "<group>"; };
802B07662952C38C0019C2B1 /* BooruXMLParserDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BooruXMLParserDelegate.h; sourceTree = "<group>"; };
802B07672952C38C0019C2B1 /* BooruXMLParserDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BooruXMLParserDelegate.m; sourceTree = "<group>"; };
802B076A2952CDBB0019C2B1 /* BooruImage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BooruImage.h; sourceTree = "<group>"; };
802B076B2952CDBB0019C2B1 /* BooruImage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BooruImage.m; sourceTree = "<group>"; };
802B076D2952D07D0019C2B1 /* ClickableImageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ClickableImageView.h; sourceTree = "<group>"; };
802B076E2952D07D0019C2B1 /* ClickableImageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ClickableImageView.m; sourceTree = "<group>"; };
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; }; 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; }; 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; }; 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 */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup 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 = "<group>";
};
802B07732952F4D40019C2B1 /* ui */ = {
isa = PBXGroup;
children = (
802B076D2952D07D0019C2B1 /* ClickableImageView.h */,
802B076E2952D07D0019C2B1 /* ClickableImageView.m */,
);
path = ui;
sourceTree = "<group>";
};
BC6610F0294C62B900277180 = { BC6610F0294C62B900277180 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -85,7 +119,7 @@
BC6610FA294C62B900277180 /* Products */ = { BC6610FA294C62B900277180 /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
BC6610F9294C62B900277180 /* Cunny Corrector.app */, BC6610F9294C62B900277180 /* Cunny Collector.app */,
BC661119294C62BA00277180 /* cunnyfinderTests.octest */, BC661119294C62BA00277180 /* cunnyfinderTests.octest */,
); );
name = Products; name = Products;
@ -114,6 +148,8 @@
BC661102294C62B900277180 /* cunnyfinder */ = { BC661102294C62B900277180 /* cunnyfinder */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
802B07732952F4D40019C2B1 /* ui */,
802B07692952CD640019C2B1 /* libbooru */,
BC66110E294C62B900277180 /* AppDelegate.h */, BC66110E294C62B900277180 /* AppDelegate.h */,
BC66110F294C62B900277180 /* AppDelegate.m */, BC66110F294C62B900277180 /* AppDelegate.m */,
BC661111294C62BA00277180 /* MainMenu.xib */, BC661111294C62BA00277180 /* MainMenu.xib */,
@ -170,7 +206,7 @@
); );
name = cunnyfinder; name = cunnyfinder;
productName = cunnyfinder; productName = cunnyfinder;
productReference = BC6610F9294C62B900277180 /* Cunny Corrector.app */; productReference = BC6610F9294C62B900277180 /* Cunny Collector.app */;
productType = "com.apple.product-type.application"; productType = "com.apple.product-type.application";
}; };
BC661118294C62BA00277180 /* cunnyfinderTests */ = { BC661118294C62BA00277180 /* cunnyfinderTests */ = {
@ -206,6 +242,7 @@
developmentRegion = English; developmentRegion = English;
hasScannedForEncodings = 0; hasScannedForEncodings = 0;
knownRegions = ( knownRegions = (
English,
en, en,
); );
mainGroup = BC6610F0294C62B900277180; mainGroup = BC6610F0294C62B900277180;
@ -263,6 +300,10 @@
files = ( files = (
BC661109294C62B900277180 /* main.m in Sources */, BC661109294C62B900277180 /* main.m in Sources */,
BC661110294C62B900277180 /* AppDelegate.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; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -386,7 +427,8 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "cunnyfinder/cunnyfinder-Prefix.pch"; GCC_PREFIX_HEADER = "cunnyfinder/cunnyfinder-Prefix.pch";
INFOPLIST_FILE = "cunnyfinder/cunnyfinder-Info.plist"; INFOPLIST_FILE = "cunnyfinder/cunnyfinder-Info.plist";
PRODUCT_NAME = "Cunny Corrector"; PRODUCT_BUNDLE_IDENTIFIER = jp.femboyfinancial.CunnyCollector;
PRODUCT_NAME = "Cunny Collector";
WRAPPER_EXTENSION = app; WRAPPER_EXTENSION = app;
}; };
name = Debug; name = Debug;
@ -398,7 +440,8 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "cunnyfinder/cunnyfinder-Prefix.pch"; GCC_PREFIX_HEADER = "cunnyfinder/cunnyfinder-Prefix.pch";
INFOPLIST_FILE = "cunnyfinder/cunnyfinder-Info.plist"; INFOPLIST_FILE = "cunnyfinder/cunnyfinder-Info.plist";
PRODUCT_NAME = "Cunny Corrector"; PRODUCT_BUNDLE_IDENTIFIER = jp.femboyfinancial.CunnyCollector;
PRODUCT_NAME = "Cunny Collector";
WRAPPER_EXTENSION = app; WRAPPER_EXTENSION = app;
}; };
name = Release; name = Release;
@ -452,6 +495,7 @@
BC66112C294C62BA00277180 /* Release */, BC66112C294C62BA00277180 /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
}; };
BC66112D294C62BA00277180 /* Build configuration list for PBXNativeTarget "cunnyfinderTests" */ = { BC66112D294C62BA00277180 /* Build configuration list for PBXNativeTarget "cunnyfinderTests" */ = {
isa = XCConfigurationList; isa = XCConfigurationList;
@ -460,6 +504,7 @@
BC66112F294C62BA00277180 /* Release */, BC66112F294C62BA00277180 /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
}; };
/* End XCConfigurationList section */ /* End XCConfigurationList section */
}; };

View File

@ -8,10 +8,12 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate> @interface AppDelegate : NSObject<NSApplicationDelegate>
@property (assign) IBOutlet NSWindow *window; @property (assign) IBOutlet NSWindow *window;
-(IBAction)actionUohhh:(id)sender; -(IBAction)actionUohhh:(id)sender;
-(NSRect)randomPositionWithWidth:(int)width height:(int)height;
-(void)addWaifu:(id)btn;
@end @end

View File

@ -7,12 +7,48 @@
// //
#import "AppDelegate.h" #import "AppDelegate.h"
#import "libbooru/BooruClient.h"
#import "ui/ClickableImageView.h"
@implementation AppDelegate @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 -(IBAction)actionUohhh:(id)sender
@ -24,13 +60,10 @@
[alert setInformativeText:@"Damn bratty girl, seducing an adult... correction is needed!"]; [alert setInformativeText:@"Damn bratty girl, seducing an adult... correction is needed!"];
[alert setAlertStyle:NSInformationalAlertStyle]; [alert setAlertStyle:NSInformationalAlertStyle];
[alert runModal]; [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; bool brat = arc4random_uniform(20) == 0;
NSRect rect = NSMakeRect(x, y, 48, 48); NSTextField *label = [[NSTextField alloc] initWithFrame:[self randomPositionWithWidth:48 height:48]];
NSTextField *label = [[NSTextField alloc] initWithFrame:rect];
[label setEditable:false]; [label setEditable:false];
[label setBezeled:false]; [label setBezeled:false];
[label setFont:[NSFont fontWithName:@"Apple Color Emoji" size:32]]; [label setFont:[NSFont fontWithName:@"Apple Color Emoji" size:32]];
@ -38,6 +71,7 @@
[label setAlignment:NSCenterTextAlignment]; [label setAlignment:NSCenterTextAlignment];
if (brat) { if (brat) {
[label setStringValue:@"💢"]; [label setStringValue:@"💢"];
[self addWaifu:sender];
} else { } else {
[label setStringValue:@"😭"]; [label setStringValue:@"😭"];
} }

View File

@ -9,7 +9,7 @@
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string></string> <string></string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>jp.femboyfinancial.${PRODUCT_NAME:rfc1034identifier}</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>

View File

@ -1,15 +1,17 @@
{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf510 {\rtf1\ansi\ansicpg1252\cocoartf2580
{\fonttbl\f0\fswiss\fcharset0 Helvetica;} \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica-Bold;\f1\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;} {\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;}
\vieww9600\viewh8400\viewkind0 \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: \f0\b\fs24 \cf0 Programming:
\b0 \ \f1\b0 \
James Shiffer\ James Shiffer\
\ \
\b Special Thanks: \f0\b Special Thanks:
\b0 \ \f1\b0 \
abmayo\ abmayo\
dorontabi} dorontabi\
Gelbooru.com}

View File

@ -42,7 +42,7 @@
<array class="NSMutableArray" key="NSMenuItems"> <array class="NSMutableArray" key="NSMenuItems">
<object class="NSMenuItem" id="694149608"> <object class="NSMenuItem" id="694149608">
<reference key="NSMenu" ref="649796088"/> <reference key="NSMenu" ref="649796088"/>
<string key="NSTitle">Cunny Corrector</string> <string key="NSTitle">Cunny Collector</string>
<string key="NSKeyEquiv"/> <string key="NSKeyEquiv"/>
<int key="NSKeyEquivModMask">1048576</int> <int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int> <int key="NSMnemonicLoc">2147483647</int>
@ -56,11 +56,11 @@
</object> </object>
<string key="NSAction">submenuAction:</string> <string key="NSAction">submenuAction:</string>
<object class="NSMenu" key="NSSubmenu" id="110575045"> <object class="NSMenu" key="NSSubmenu" id="110575045">
<string key="NSTitle">Cunny Corrector</string> <string key="NSTitle">Cunny Collector</string>
<array class="NSMutableArray" key="NSMenuItems"> <array class="NSMutableArray" key="NSMenuItems">
<object class="NSMenuItem" id="238522557"> <object class="NSMenuItem" id="238522557">
<reference key="NSMenu" ref="110575045"/> <reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">About Cunny Corrector</string> <string key="NSTitle">About Cunny Collector</string>
<string key="NSKeyEquiv"/> <string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int> <int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/> <reference key="NSOnImage" ref="35465992"/>
@ -125,7 +125,7 @@
</object> </object>
<object class="NSMenuItem" id="755159360"> <object class="NSMenuItem" id="755159360">
<reference key="NSMenu" ref="110575045"/> <reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">Hide Cunny</string> <string key="NSTitle">Hide Cunny Collector</string>
<string key="NSKeyEquiv">h</string> <string key="NSKeyEquiv">h</string>
<int key="NSKeyEquivModMask">1048576</int> <int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int> <int key="NSMnemonicLoc">2147483647</int>
@ -163,7 +163,7 @@
</object> </object>
<object class="NSMenuItem" id="632727374"> <object class="NSMenuItem" id="632727374">
<reference key="NSMenu" ref="110575045"/> <reference key="NSMenu" ref="110575045"/>
<string key="NSTitle">Quit Cunny Corrector</string> <string key="NSTitle">Quit Cunny Collector</string>
<string key="NSKeyEquiv">q</string> <string key="NSKeyEquiv">q</string>
<int key="NSKeyEquivModMask">1048576</int> <int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int> <int key="NSMnemonicLoc">2147483647</int>
@ -366,7 +366,7 @@
<array class="NSMutableArray" key="NSMenuItems"> <array class="NSMutableArray" key="NSMenuItems">
<object class="NSMenuItem" id="105068016"> <object class="NSMenuItem" id="105068016">
<reference key="NSMenu" ref="992780483"/> <reference key="NSMenu" ref="992780483"/>
<string key="NSTitle">cunnyfinder Help</string> <string key="NSTitle">Cunny Collector Help</string>
<string key="NSKeyEquiv">?</string> <string key="NSKeyEquiv">?</string>
<int key="NSKeyEquivModMask">1048576</int> <int key="NSKeyEquivModMask">1048576</int>
<int key="NSMnemonicLoc">2147483647</int> <int key="NSMnemonicLoc">2147483647</int>
@ -385,7 +385,7 @@
<int key="NSWindowBacking">2</int> <int key="NSWindowBacking">2</int>
<string key="NSWindowRect">{{335, 390}, {480, 360}}</string> <string key="NSWindowRect">{{335, 390}, {480, 360}}</string>
<int key="NSWTFlags">1954021376</int> <int key="NSWTFlags">1954021376</int>
<string key="NSWindowTitle">Cunny Corrector</string> <string key="NSWindowTitle">Cunny Collector</string>
<string key="NSWindowClass">NSWindow</string> <string key="NSWindowClass">NSWindow</string>
<nil key="NSViewClass"/> <nil key="NSViewClass"/>
<nil key="NSUserInterfaceItemIdentifier"/> <nil key="NSUserInterfaceItemIdentifier"/>

View File

@ -0,0 +1,29 @@
//
// BooruClient.h
// cunnyfinder
//
// Created by James Shiffer on 12/19/22.
// Copyright © 2022 FemboyFinancial. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "BooruImage.h"
#import "BooruXMLParserDelegate.h"
@interface BooruClient : NSObject
@property NSString* urlFormat;
@property NSString* tags;
@property NSMutableArray* waifus;
@property NSDictionary<NSString*, NSString*>* 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

View File

@ -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

View File

@ -0,0 +1,27 @@
//
// BooruImage.h
// cunnyfinder
//
// Created by James Shiffer on 12/20/22.
// Copyright © 2022 FemboyFinancial. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface BooruImage : NSObject
@property NSDictionary<NSString*, NSString*>* metadata;
-(id)init:(NSDictionary<NSString*, NSString*> *)metadata;
-(int)width;
-(int)height;
-(int)previewWidth;
-(int)previewHeight;
-(int)sampleWidth;
-(int)sampleHeight;
-(bool)hasSample;
-(NSURL *)fileUrl;
-(NSURL *)previewUrl;
-(NSURL *)sampleUrl;
@end

View File

@ -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<NSString*, NSString*> *)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

View File

@ -0,0 +1,30 @@
//
// BooruXMLParserDelegate.h
// cunnyfinder
//
// Created by James Shiffer on 12/20/22.
// Copyright © 2022 FemboyFinancial. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface BooruXMLParserDelegate : NSObject<NSXMLParserDelegate>
@property NSMutableDictionary<NSString *, NSString *>* data;
-(id)init;
-(void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary<NSString *, NSString *> *)attributeDict;
-(void)parser:(NSXMLParser *)parser
foundCharacters:(NSString *)string;
-(void)parser:(NSXMLParser *)parser
didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName;
@end

View File

@ -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<NSString *,NSString *> *)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

View File

@ -0,0 +1,21 @@
//
// ClickableImageView.h
// cunnyfinder
//
// Created by James Shiffer on 12/20/22.
// Copyright © 2022 FemboyFinancial. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@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

View File

@ -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