) toBuilder;
79 |
80 | /**
81 | * Returns a string description of the message.
82 | */
83 | - (NSString*) description;
84 |
85 | @end
86 |
--------------------------------------------------------------------------------
/Pod/Dependencies/protobuf/ExtendableMessageBuilder.h:
--------------------------------------------------------------------------------
1 | // Protocol Buffers for Objective C
2 | //
3 | // Copyright 2010 Booyah Inc.
4 | // Copyright 2008 Cyrus Najmabadi
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | #import "GeneratedMessageBuilder.h"
19 |
20 | #import "ExtensionField.h"
21 |
22 | @class PBExtendableMessage;
23 |
24 | /**
25 | * Generated message builders for message types that contain extension ranges
26 | * subclass this.
27 | *
28 | * This class implements type-safe accessors for extensions. They
29 | * implement all the same operations that you can do with normal fields --
30 | * e.g. "get", "set", and "add" -- but for extensions. The extensions are
31 | * identified using instances of the class {@link GeneratedExtension}; the
32 | * protocol compiler generates a static instance of this class for every
33 | * extension in its input. Through the magic of generics, all is made
34 | * type-safe.
35 | *
36 | *
For example, imagine you have the {@code .proto} file:
37 | *
38 | *
39 | * option java_class = "MyProto";
40 | *
41 | * message Foo {
42 | * extensions 1000 to max;
43 | * }
44 | *
45 | * extend Foo {
46 | * optional int32 bar;
47 | * }
48 | *
49 | *
50 | * Then you might write code like:
51 | *
52 | *
53 | * MyProto.Foo foo =
54 | * MyProto.Foo.newBuilder()
55 | * .setExtension(MyProto.bar, 123)
56 | * .build();
57 | *
58 | *
59 | * See also {@link ExtendableMessage}.
60 | */
61 | @interface PBExtendableMessageBuilder : PBGeneratedMessageBuilder {
62 | }
63 |
64 | - (id) getExtension:(id) extension;
65 | - (BOOL) hasExtension:(id) extension;
66 | - (PBExtendableMessageBuilder*) setExtension:(id) extension
67 | value:(id) value;
68 | - (PBExtendableMessageBuilder*) addExtension:(id) extension
69 | value:(id) value;
70 | - (PBExtendableMessageBuilder*) setExtension:(id) extension
71 | index:(SInt32) index
72 | value:(id) value;
73 | - (PBExtendableMessageBuilder*) clearExtension:(id) extension;
74 |
75 | /* @protected */
76 | - (void) mergeExtensionFields:(PBExtendableMessage*) other;
77 |
78 | @end
79 |
--------------------------------------------------------------------------------
/Pod/Classes/Model/SKMessage.h:
--------------------------------------------------------------------------------
1 | //
2 | // SKMessage.h
3 | // SnapchatKit
4 | //
5 | // Created by Tanner Bennett on 5/19/15.
6 | // Copyright (c) 2015 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | #import "SKThing.h"
10 |
11 | typedef NS_ENUM(NSUInteger, SKMessageKind)
12 | {
13 | SKMessageKindText = 1,
14 | SKMessageKindMedia,
15 | SKMessageKindDiscoverShared,
16 | SKMessageKindStoryReply
17 | };
18 |
19 | extern SKMessageKind SKMessageKindFromString(NSString *messageKindString);
20 |
21 | @interface SKMessage : SKThing
22 |
23 | // SKPagination
24 | @property (nonatomic, readonly) NSString *pagination;
25 | @property (nonatomic, readonly) NSString *conversationIdentifier;
26 | @property (nonatomic, readonly) NSDate *created;
27 |
28 | /** Use this property to mark a message as read. */
29 | @property (nonatomic, readonly) NSString *identifier;
30 | @property (nonatomic, readonly) NSString *messageIdentifier;
31 | @property (nonatomic, readonly) SKMessageKind messageKind;
32 |
33 | /** \c nil if \c messageKind is \c SKMessageKindMedia. */
34 | @property (nonatomic, readonly) NSString *text;
35 |
36 | /** \c nil if \c messageKind is \c SKMessageKindText. */
37 | @property (nonatomic, readonly) NSString *mediaIdentifier;
38 |
39 | #ifndef UIKIT_EXTERN
40 | /** \c 0 if \c messageKind is \c SKMessageKindText. */
41 | @property (nonatomic, readonly) NSInteger mediaWidth;
42 | /** \c 0 if \c messageKind is \c SKMessageKindText. */
43 | @property (nonatomic, readonly) NSInteger mediaHeight;
44 | #else
45 | /** \c {0,0} if \c messageKind is \c SKMessageKindText. */
46 | @property (nonatomic, readonly) CGSize mediaSize;
47 | #endif
48 |
49 | /** \c nil if \c messageKind is \c SKMessageKindText. */
50 | @property (nonatomic, readonly) NSString *mediaIV;
51 | /** \c nil if \c messageKind is \c SKMessageKindText. */
52 | @property (nonatomic, readonly) NSString *mediaKey;
53 | /** i.e. "VIDEO" or "IMAGE" */
54 | @property (nonatomic, readonly) NSString *mediaType;
55 | /** The identifier of the replied-to story. \c nil unless \c messageKind is \c SKMessageKindStoryReply. */
56 | @property (nonatomic, readonly) NSString *storyIdentifier;
57 | /** Whether the replied-to story is zipped. */
58 | @property (nonatomic, readonly) BOOL zipped;
59 |
60 | /** Array of usernames. */
61 | @property (nonatomic, readonly) NSArray *recipients;
62 | @property (nonatomic, readonly) NSString *sender;
63 |
64 | /** The position of this message in the conversation. i.e. 1 if it is the first message. */
65 | @property (nonatomic, readonly) NSUInteger index;
66 |
67 | /** Keys for each participant mapped to dictionaries with keys "saved" and "version". */
68 | @property (nonatomic, readonly) NSDictionary *savedState;
69 |
70 | /** So far, it's just "chat_message". Odd. */
71 | @property (nonatomic, readonly) NSString *type;
72 |
73 |
74 | @end
75 |
--------------------------------------------------------------------------------
/Pod/Classes/Model/SKSnap.m:
--------------------------------------------------------------------------------
1 | //
2 | // SKSnap.m
3 | // SnapchatKit
4 | //
5 | // Created by Tanner Bennett on 5/19/15.
6 | // Copyright (c) 2015 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | #import "SKSnap.h"
10 | #import "SKBlob.h"
11 | #import "SKClient+Snaps.h"
12 |
13 | @implementation SKSnap
14 |
15 | - (id)initWithDictionary:(NSDictionary *)json error:(NSError *__autoreleasing *)error {
16 | if (!json.allKeys.count) return nil;
17 |
18 | self = [super initWithDictionary:json error:error];
19 | if (self) {
20 | _isOutgoing = [_identifier hasSuffix:@"s"];
21 | }
22 |
23 | return self;
24 | }
25 |
26 | - (NSString *)description {
27 | return [NSString stringWithFormat:@"<%@ to/from=%@, kind=%lu, duration=%f, screenshots=%lu>",
28 | NSStringFromClass(self.class), self.sender?:self.recipient, (long)self.mediaKind, self.mediaTimer, (unsigned long)self.screenshots];
29 | }
30 |
31 | #pragma mark - Mantle
32 |
33 | + (NSDictionary *)JSONKeyPathsByPropertyKey {
34 | return @{@"sender": @"sn",
35 | @"recipient": @"rp",
36 | @"identifier": @"id",
37 | @"conversationIdentifier": @"c_id",
38 | @"mediaKind": @"m",
39 | @"status": @"st",
40 | @"screenshots": @"c",
41 | @"timer": @"t",
42 | @"mediaTimer": @"timer",
43 | @"sentDate": @"sts",
44 | @"timestamp": @"ts",
45 | @"zipped": @"zipped",
46 | @"esIdentifier": @"es_id",
47 | @"mo": @"mo"};
48 | }
49 |
50 | MTLTransformPropertyDate(sentDate)
51 | MTLTransformPropertyDate(timestamp)
52 |
53 | #pragma mark - Equality
54 |
55 | - (BOOL)isEqual:(id)object {
56 | if ([object isKindOfClass:[SKSnap class]])
57 | return [self isEqualToSnap:object];
58 |
59 | return [super isEqual:object];
60 | }
61 |
62 | - (BOOL)isEqualToSnap:(SKSnap *)snap {
63 | return [self.identifier isEqualToString:snap.identifier];
64 | }
65 |
66 | - (NSUInteger)hash {
67 | return self.identifier.hash;
68 | }
69 |
70 | @end
71 |
72 |
73 | @implementation SKSnap (SKClient)
74 |
75 | - (void)load:(ErrorBlock)completion {
76 | NSParameterAssert(completion);
77 | [[SKClient sharedClient] loadSnap:self completion:^(SKBlob *blob, NSError *error) {
78 | if (!error) {
79 | _blob = blob;
80 | completion(nil);
81 | } else {
82 | completion(error);
83 | }
84 | }];
85 | }
86 |
87 | - (NSString *)suggestedFilename {
88 | if (!self.blob)
89 | return nil;
90 | return [NSString stringWithFormat:@"%@~%@", self.sender, self.identifier];
91 | // if (self.blob.isImage)
92 | // return [NSString stringWithFormat:@"%@.jpg", self.identifier];
93 | // else if (self.blob.overlay)
94 | // return self.identifier;
95 | // else
96 | // return [NSString stringWithFormat:@"%@.mp4", self.identifier];
97 | }
98 |
99 | @end
--------------------------------------------------------------------------------
/Pod/Dependencies/protobuf/GeneratedMessageBuilder.m:
--------------------------------------------------------------------------------
1 | // Protocol Buffers for Objective C
2 | //
3 | // Copyright 2010 Booyah Inc.
4 | // Copyright 2008 Cyrus Najmabadi
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | #import "GeneratedMessageBuilder.h"
19 |
20 | #import "GeneratedMessage.h"
21 | #import "Message.h"
22 | #import "MessageBuilder.h"
23 | #import "UnknownFieldSet.h"
24 | #import "UnknownFieldSetBuilder.h"
25 |
26 |
27 | @interface PBGeneratedMessage ()
28 | @property (strong) PBUnknownFieldSet* unknownFields;
29 | @end
30 |
31 |
32 | @implementation PBGeneratedMessageBuilder
33 |
34 | /**
35 | * Get the message being built. We don't just pass this to the
36 | * constructor because it becomes null when build() is called.
37 | */
38 | - (PBGeneratedMessage*) internalGetResult {
39 | @throw [NSException exceptionWithName:@"ImproperSubclassing" reason:@"" userInfo:nil];
40 | }
41 |
42 |
43 | - (void) checkInitialized {
44 | PBGeneratedMessage* result = self.internalGetResult;
45 | if (result != nil && !result.isInitialized) {
46 | @throw [NSException exceptionWithName:@"UninitializedMessage" reason:@"" userInfo:nil];
47 | }
48 | }
49 |
50 |
51 | - (PBUnknownFieldSet*) unknownFields {
52 | return self.internalGetResult.unknownFields;
53 | }
54 |
55 |
56 | - (id) setUnknownFields:(PBUnknownFieldSet*) unknownFields {
57 | self.internalGetResult.unknownFields = unknownFields;
58 | return self;
59 | }
60 |
61 |
62 | - (id) mergeUnknownFields:(PBUnknownFieldSet*) unknownFields {
63 | PBGeneratedMessage* result = self.internalGetResult;
64 | result.unknownFields =
65 | [[[PBUnknownFieldSet builderWithUnknownFields:result.unknownFields]
66 | mergeUnknownFields:unknownFields] build];
67 | return self;
68 | }
69 |
70 |
71 | - (BOOL) isInitialized {
72 | return self.internalGetResult.isInitialized;
73 | }
74 |
75 |
76 | /**
77 | * Called by subclasses to parse an unknown field.
78 | * @return {@code YES} unless the tag is an end-group tag.
79 | */
80 | - (BOOL) parseUnknownField:(PBCodedInputStream*) input
81 | unknownFields:(PBUnknownFieldSetBuilder*) unknownFields
82 | extensionRegistry:(PBExtensionRegistry*) extensionRegistry
83 | tag:(SInt32) tag {
84 | return [unknownFields mergeFieldFrom:tag input:input];
85 | }
86 |
87 |
88 | - (void) checkInitializedParsed {
89 | PBGeneratedMessage* result = self.internalGetResult;
90 | if (result != nil && !result.isInitialized) {
91 | @throw [NSException exceptionWithName:@"InvalidProtocolBuffer" reason:@"" userInfo:nil];
92 | }
93 | }
94 |
95 | @end
96 |
--------------------------------------------------------------------------------
/Pod/Classes/Networking/SKClient+Snaps.h:
--------------------------------------------------------------------------------
1 | //
2 | // SKClient+Snaps.h
3 | // SnapchatKit
4 | //
5 | // Created by Tanner Bennett on 5/26/15.
6 | // Copyright (c) 2015 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SKClient.h"
11 | #import "SKSnap.h"
12 |
13 | @class SKSnapOptions, CLLocation;
14 |
15 |
16 | @interface SKClient (Snaps)
17 |
18 | /** Sends a snap with the given options.
19 | @param blob The \c SKBlob object containing the image or video data to send. Can be created with any \c NSData object.
20 | @param options The options for the snap to be sent.
21 | @param completion Takes an error, if any, and an \c SKSnapResponse object. */
22 | - (void)sendSnap:(SKBlob *)blob options:(SKSnapOptions *)options completion:(ResponseBlock)completion;
23 | /** Sends a snap to everyone in \c recipients with text \c text for \c duration seconds.
24 | @param blob The \c SKBlob object containing the image or video data to send. Can be created with any \c NSData object.
25 | @param recipients An array of username strings.
26 | @param text The text to label the snap with. This text is not superimposed upon the image; you must do that yourself.
27 | @param duration The legnth of the snap. It must be greater than \c 0 or an exception will be raised.
28 | @param completion Takes an error, if any, and an \c SKSnapResponse object. */
29 | - (void)sendSnap:(SKBlob *)blob to:(NSArray *)recipients text:(NSString *)text timer:(NSTimeInterval)duration completion:(ResponseBlock)completion;
30 |
31 | /** Marks a snap as opened for \c secondsViewed seconds at the current time.
32 | @param secondsViewed The number of seconds the snap was viewed for.
33 | @param replayed Whether the snap was also replayed.
34 | @param completion Takes an error, if any. */
35 | - (void)markSnapViewed:(SKSnap *)snap for:(CGFloat)secondsViewed replay:(BOOL)replayed completion:(ErrorBlock)completion;
36 | /** Marks a set of snaps as opened for the specified length at the given times.
37 | @param snaps An array of \c SKSnap objects.
38 | @param times An array of \c NSDate objects.
39 | @param replayed An array of NSNumber booleans indicating whether the corresponding snap was replayed.
40 | @param secondsViewed An array of \c NSNumber objects. Try to use floating point nubmers. */
41 | - (void)markSnapsViewed:(NSArray *)snaps atTimes:(NSArray *)times for:(NSArray *)secondsViewed replayed:(NSArray *)replayed completion:(ErrorBlock)completion;
42 | /** Marks a snap as screenshotted and viewed for \c secondsViewed seconds.
43 | @param secondsViewed The number of seconds the corresponding snap was viewed for.
44 | @param replayed An array of NSNumber booleans indicating whether the corresponding snap was replayed.
45 | @param completion Takes an error, if any. */
46 | - (void)markSnapScreenshot:(SKSnap *)snap for:(NSUInteger)secondsViewed completion:(ErrorBlock)completion;
47 |
48 | /** Loads a snap.
49 | @param completion Takes an error, if any, and an \c SKBlob object. */
50 | - (void)loadSnap:(SKSnap *)snap completion:(ResponseBlock)completion;
51 |
52 | /** Loads filters for a location.
53 | @param completion Takes an error, if any, and an \c SKLocation object. */
54 | - (void)loadFiltersForLocation:(CLLocation *)location completion:(ResponseBlock)completion;
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/Pod/Classes/Networking/SKClient+Device.m:
--------------------------------------------------------------------------------
1 | //
2 | // SKClient+Device.m
3 | // SnapchatKit
4 | //
5 | // Created by Tanner Bennett on 6/14/15.
6 | // Copyright (c) 2015 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | #import "SKClient+Device.h"
10 | #import "SKUser.h"
11 | #import "SKRequest.h"
12 |
13 | #import "NSString+SnapchatKit.h"
14 | #import "NSArray+SnapchatKit.h"
15 | #import "NSDictionary+SnapchatKit.h"
16 |
17 | #define kUnimplemented @"Unimplemented"
18 |
19 | @implementation SKClient (Device)
20 |
21 | - (void)sendDidOpenAppEvent:(ErrorBlock)completion {
22 | [self updateSession:^(NSError *error) {
23 | if (!error) {
24 | NSString *uuid = SKUniqueIdentifier();
25 | NSInteger friendCount = -1;
26 |
27 | for (SKUser *friend in self.currentSession.friends)
28 | if (friend.friendStatus == SKFriendStatusMutual)
29 | friendCount++;
30 |
31 | NSString *timestamp = [NSString timestamp];
32 | NSString *batchID = [NSString stringWithFormat:@"%@-%@%@", uuid, [SKConsts.userAgent stringByReplacingMatchesForRegex:@"[\\W]+" withString:@""], timestamp];
33 | NSDictionary *eventDict = @{@"common_params": @{@"user_id":self.username.MD5Hash,
34 | @"city": kUnimplemented,
35 | @"sc_user_agent": SKConsts.userAgent,
36 | @"session_id":@"00000000-0000-0000-0000-000000000000",
37 | @"region": kUnimplemented,
38 | @"latlon": kUnimplemented,
39 | @"friend_count": @(friendCount),
40 | @"country": kUnimplemented}.JSONString,
41 | @"events": @[@{@"event_name": @"APP_OPEN",
42 | @"event_timestamp": timestamp,
43 | @"event_params": @{@"open_state": @"NORMAL", @"intent_action": @"NULL"}.JSONString}.JSONString].JSONString,
44 | @"batch_id": batchID};
45 |
46 | [SKRequest sendEvents:eventDict callback:^(NSData *data, NSURLResponse *response, NSError *error) {
47 | if (completion) {
48 | if ([(NSHTTPURLResponse *)response statusCode] == 200) {
49 | completion(nil);
50 | } else {
51 | [self handleError:error data:data response:response completion:^(id object, NSError *error) {
52 | completion(error);
53 | }];
54 | }
55 | }
56 | }];
57 |
58 | } else {
59 | completion(error);
60 | }
61 | }];
62 | }
63 |
64 | - (void)sendDidCloseAppEvent:(ErrorBlock)completion {
65 | NSArray *events = @[@{@"eventName": @"CLOSE",
66 | @"params": @{},
67 | @"ts": [NSString timestamp]}];
68 | [self sendEvents:events data:nil completion:completion];
69 | }
70 |
71 | @end
72 |
--------------------------------------------------------------------------------
/Pod/Dependencies/protobuf/AbstractMessage.m:
--------------------------------------------------------------------------------
1 | // Protocol Buffers for Objective C
2 | //
3 | // Copyright 2010 Booyah Inc.
4 | // Copyright 2008 Cyrus Najmabadi
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | #import "AbstractMessage.h"
19 |
20 | #import "CodedOutputStream.h"
21 |
22 | @implementation PBAbstractMessage
23 |
24 | - (instancetype) init {
25 | if ((self = [super init])) {
26 | }
27 |
28 | return self;
29 | }
30 |
31 |
32 | - (NSData*) data {
33 | NSMutableData* data = [NSMutableData dataWithLength:self.serializedSize];
34 | PBCodedOutputStream* stream = [PBCodedOutputStream streamWithData:data];
35 | [self writeToCodedOutputStream:stream];
36 | return data;
37 | }
38 |
39 |
40 | - (BOOL) isInitialized {
41 | @throw [NSException exceptionWithName:@"ImproperSubclassing" reason:@"" userInfo:nil];
42 | }
43 |
44 |
45 | - (SInt32) serializedSize {
46 | @throw [NSException exceptionWithName:@"ImproperSubclassing" reason:@"" userInfo:nil];
47 | }
48 |
49 |
50 | - (void) writeToCodedOutputStream:(PBCodedOutputStream*) output {
51 | @throw [NSException exceptionWithName:@"ImproperSubclassing" reason:@"" userInfo:nil];
52 | }
53 |
54 |
55 | - (void) writeToOutputStream:(NSOutputStream*) output {
56 | PBCodedOutputStream* codedOutput = [PBCodedOutputStream streamWithOutputStream:output];
57 | [self writeToCodedOutputStream:codedOutput];
58 | [codedOutput flush];
59 | }
60 |
61 |
62 | - (instancetype) defaultInstance {
63 | @throw [NSException exceptionWithName:@"ImproperSubclassing" reason:@"" userInfo:nil];
64 | }
65 |
66 |
67 | - (PBUnknownFieldSet*) unknownFields {
68 | @throw [NSException exceptionWithName:@"ImproperSubclassing" reason:@"" userInfo:nil];
69 | }
70 |
71 |
72 | - (id) builder {
73 | @throw [NSException exceptionWithName:@"ImproperSubclassing" reason:@"" userInfo:nil];
74 | }
75 |
76 |
77 | - (id) toBuilder {
78 | @throw [NSException exceptionWithName:@"ImproperSubclassing" reason:@"" userInfo:nil];
79 | }
80 |
81 |
82 | - (void) writeDescriptionTo:(NSMutableString*) output
83 | withIndent:(NSString*) indent {
84 | @throw [NSException exceptionWithName:@"ImproperSubclassing" reason:@"" userInfo:nil];
85 | }
86 |
87 |
88 | - (NSString*) description {
89 | NSMutableString* output = [NSMutableString string];
90 | [self writeDescriptionTo:output withIndent:@""];
91 | return output;
92 | }
93 |
94 | - (void) storeInDictionary: (NSMutableDictionary *) dic {
95 | @throw [NSException exceptionWithName:@"ImproperSubclassing" reason:@"" userInfo:nil];
96 | }
97 |
98 | - (NSDictionary *) dictionaryRepresentation {
99 | @throw [NSException exceptionWithName:@"ImproperSubclassing" reason:@"" userInfo:nil];
100 | }
101 |
102 |
103 | @end
104 |
--------------------------------------------------------------------------------
/Pod/Classes/Categories/NSDictionary+SnapchatKit.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSDictionary+SnapchatKit.m
3 | // SnapchatKit
4 | //
5 | // Created by Tanner Bennett on 5/22/15.
6 | // Copyright (c) 2015 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | #import "NSDictionary+SnapchatKit.h"
10 | #import "NSString+SnapchatKit.h"
11 | #import "NSData+SnapchatKit.h"
12 | #import
13 | #import
14 |
15 |
16 | @implementation NSDictionary (JSON)
17 |
18 | - (NSString *)JSONString {
19 | NSData *data = [NSJSONSerialization dataWithJSONObject:self options:0 error:nil];
20 | return data ? [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] : @"{}";
21 | }
22 |
23 | - (NSString *)JWTStringWithSecret:(NSString *)key {
24 | NSString *header = @"{\"typ\":\"JWT\",\"alg\":\"HS256\"}";
25 | NSString *payload = [self.JSONString stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"];
26 |
27 | NSString *data = [@"." join:@[header.base64URLEncoded, payload.base64URLEncoded]];
28 |
29 | unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
30 | CCHmac(kCCHmacAlgSHA256, key.UTF8String, strlen(key.UTF8String), data.UTF8String, strlen(data.UTF8String), cHMAC);
31 | NSData *signature = [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
32 |
33 | return [@"." join:@[data, signature.base64URLEncodedString]];
34 | }
35 |
36 | @end
37 |
38 |
39 | @implementation NSDictionary (Util)
40 |
41 | - (NSArray *)split:(NSUInteger)entryLimit {
42 | NSParameterAssert(entryLimit > 0);
43 | if (self.allKeys.count <= entryLimit)
44 | return @[self];
45 |
46 | NSMutableArray *dicts = [NSMutableArray array];
47 | __block NSMutableDictionary *tmp = [NSMutableDictionary dictionary];
48 | [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
49 | tmp[key] = obj;
50 | if (tmp.allKeys.count % entryLimit == 0) {
51 | [dicts addObject:tmp];
52 | tmp = [NSMutableDictionary dictionary];
53 | }
54 | }];
55 |
56 | return dicts;
57 | }
58 |
59 | - (NSDictionary *)dictionaryByReplacingValuesForKeys:(NSDictionary *)dictionary {
60 | if (!dictionary || !dictionary.allKeys.count || !self) return self;
61 |
62 | NSMutableDictionary *m = self.mutableCopy;
63 | [m setValuesForKeysWithDictionary:dictionary];
64 | return m.copy;
65 | }
66 |
67 | - (NSDictionary *)dictionaryByReplacingKeysWithNewKeys:(NSDictionary *)oldKeysToNewKeys {
68 | if (!oldKeysToNewKeys || !oldKeysToNewKeys.allKeys.count || !self) return self;
69 |
70 | NSMutableDictionary *m = self.mutableCopy;
71 | [oldKeysToNewKeys enumerateKeysAndObjectsUsingBlock:^(NSString *oldKey, NSString *newKey, BOOL *stop) {
72 | id val = m[oldKey];
73 | m[oldKey] = nil;
74 | m[newKey] = val;
75 | }];
76 |
77 | return m;
78 | }
79 |
80 | - (NSArray *)allKeyPaths {
81 | NSMutableArray *keyPaths = [NSMutableArray array];
82 |
83 | [self enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
84 | [keyPaths addObject:key];
85 |
86 | if ([obj isKindOfClass:[NSDictionary class]]) {
87 | for (NSString *kp in [obj allKeyPaths])
88 | [keyPaths addObject:[NSString stringWithFormat:@"%@.%@", key, kp]];
89 | }
90 | }];
91 |
92 | return keyPaths.copy;
93 | }
94 |
95 | @end
--------------------------------------------------------------------------------
/Pod/Dependencies/protobuf/ExtensionRegistry.h:
--------------------------------------------------------------------------------
1 | // Protocol Buffers for Objective C
2 | //
3 | // Copyright 2010 Booyah Inc.
4 | // Copyright 2008 Cyrus Najmabadi
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | /**
19 | * A table of known extensions, searchable by name or field number. When
20 | * parsing a protocol message that might have extensions, you must provide
21 | * an {@code ExtensionRegistry} in which you have registered any extensions
22 | * that you want to be able to parse. Otherwise, those extensions will just
23 | * be treated like unknown fields.
24 | *
25 | * For example, if you had the {@code .proto} file:
26 | *
27 | *
28 | * option java_class = "MyProto";
29 | *
30 | * message Foo {
31 | * extensions 1000 to max;
32 | * }
33 | *
34 | * extend Foo {
35 | * optional int32 bar;
36 | * }
37 | *
38 | *
39 | * Then you might write code like:
40 | *
41 | *
42 | * ExtensionRegistry registry = ExtensionRegistry.newInstance();
43 | * registry.add(MyProto.bar);
44 | * MyProto.Foo message = MyProto.Foo.parseFrom(input, registry);
45 | *
46 | *
47 | * Background:
48 | *
49 | *
You might wonder why this is necessary. Two alternatives might come to
50 | * mind. First, you might imagine a system where generated extensions are
51 | * automatically registered when their containing classes are loaded. This
52 | * is a popular technique, but is bad design; among other things, it creates a
53 | * situation where behavior can change depending on what classes happen to be
54 | * loaded. It also introduces a security vulnerability, because an
55 | * unprivileged class could cause its code to be called unexpectedly from a
56 | * privileged class by registering itself as an extension of the right type.
57 | *
58 | *
Another option you might consider is lazy parsing: do not parse an
59 | * extension until it is first requested, at which point the caller must
60 | * provide a type to use. This introduces a different set of problems. First,
61 | * it would require a mutex lock any time an extension was accessed, which
62 | * would be slow. Second, corrupt data would not be detected until first
63 | * access, at which point it would be much harder to deal with it. Third, it
64 | * could violate the expectation that message objects are immutable, since the
65 | * type provided could be any arbitrary message class. An unpriviledged user
66 | * could take advantage of this to inject a mutable object into a message
67 | * belonging to priviledged code and create mischief.
68 | *
69 | * @author Cyrus Najmabadi
70 | */
71 |
72 | #import "ExtensionField.h"
73 |
74 | @interface PBExtensionRegistry : NSObject {
75 | @protected
76 | NSDictionary* classMap;
77 | }
78 |
79 | + (PBExtensionRegistry*) emptyRegistry;
80 | - (id) getExtension:(Class) clazz fieldNumber:(SInt32) fieldNumber;
81 |
82 | /* @protected */
83 | - (instancetype) initWithClassMap:(NSDictionary*) classMap;
84 | - (id) keyForClass:(Class) clazz;
85 |
86 | @end
87 |
--------------------------------------------------------------------------------
/Pod/Classes/Model/SKStory.h:
--------------------------------------------------------------------------------
1 | //
2 | // SKStory.h
3 | // SnapchatKit
4 | //
5 | // Created by Tanner Bennett on 5/18/15.
6 | // Copyright (c) 2015 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SKThing.h"
11 | #import "SKBlob.h"
12 |
13 | @interface SKStory : SKThing
14 |
15 | /** The username of whoever posted this story. */
16 | @property (nonatomic, readonly) NSString *author;
17 |
18 | /** The length of the snap in seconds. */
19 | @property (nonatomic, readonly) NSUInteger duration;
20 |
21 | /** Whether the story has been viewed. */
22 | @property (nonatomic, readonly) BOOL viewed;
23 | /** Whether the story is a "live" or "shared" story. */
24 | @property (nonatomic, readonly) BOOL shared;
25 | /** Whether the story is zipped (video stories with an overlay will be zipped). */
26 | @property (nonatomic, readonly) BOOL zipped;
27 | /** Whether the story contains explicit content. */
28 | @property (nonatomic, readonly) BOOL matureContent;
29 | /** Not sure. */
30 | @property (nonatomic, readonly) BOOL needsAuth;
31 |
32 | /** The story's ID. Fun fact: this value is just username + timestamp string. */
33 | @property (nonatomic, readonly) NSString *identifier;
34 | /** The text of the story. */
35 | @property (nonatomic, readonly) NSString *text;
36 | /** Unknown */
37 | @property (nonatomic, readonly) NSArray *unlockables;
38 | /** Unknown */
39 | @property (nonatomic, readonly) NSString *clientIdentifier;
40 | /** Unknown */
41 | @property (nonatomic, readonly) NSString *submissionIdentifier;
42 |
43 | /** Unknown */
44 | @property (nonatomic, readonly) NSString *storyFilterIdentifier;
45 | /** Unknown */
46 | @property (nonatomic, readonly) BOOL adCanFollow;
47 |
48 | /** The story's media ID. */
49 | @property (nonatomic, readonly) NSString *mediaIdentifier;
50 | /** The IV used to decrypt the media. */
51 | @property (nonatomic, readonly) NSString *mediaIV;
52 | /** The key used to decrypt the media. */
53 | @property (nonatomic, readonly) NSString *mediaKey;
54 | @property (nonatomic, readonly) SKMediaKind mediaKind;
55 | /** The URL of the media. */
56 | @property (nonatomic, readonly) NSURL *mediaURL;
57 |
58 | /** The IV used to decrypt the thumbnail. */
59 | @property (nonatomic, readonly) NSString *thumbIV;
60 | /** The URL of the thumbnail. */
61 | @property (nonatomic, readonly) NSURL *thumbURL;
62 |
63 | /** The number of seconds left before the story expires. */
64 | @property (nonatomic, readonly) NSUInteger timeLeft;
65 | /** The date the story was created. */
66 | @property (nonatomic, readonly) NSDate *created;
67 |
68 | /** \c nil until you call \c load: */
69 | @property (nonatomic, readonly) SKBlob *blob;
70 | /** \c nil until you call \c loadThumbnail: */
71 | @property (nonatomic, readonly) SKBlob *thumbnailBlob;
72 |
73 | @end
74 |
75 | @interface SKStory (SKClient)
76 | /** Loads the blob for the story. If successful, the \c blob property of the original \c SKStory object will contain the story's blob data.
77 | @param completion Takes an error, if any. */
78 | - (void)load:(ErrorBlock)completion;
79 | /** Loads the blob for the story thumbnail. If successful, the \c thumbnailBlob property of the original \c SKStory object will contain the story's thumbnail blob data.
80 | @param completion Takes an error, if any. */
81 | - (void)loadThumbnail:(ErrorBlock)completion;
82 | /** @return If \c blob is \c nil, returns nil. For images: \c {identifier}.jpg, for videos: \c {identifier}.mp4, and for videos with an overlay just {identifier} */
83 | @property (nonatomic, readonly) NSString *suggestedFilename;
84 |
85 | @end
--------------------------------------------------------------------------------
/Pod/Dependencies/protobuf/ExtendableMessage.h:
--------------------------------------------------------------------------------
1 | // Protocol Buffers for Objective C
2 | //
3 | // Copyright 2010 Booyah Inc.
4 | // Copyright 2008 Cyrus Najmabadi
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | #import "GeneratedMessage.h"
19 |
20 | #import "ExtensionField.h"
21 |
22 | /**
23 | * Generated message classes for message types that contain extension ranges
24 | * subclass this.
25 | *
26 | * This class implements type-safe accessors for extensions. They
27 | * implement all the same operations that you can do with normal fields --
28 | * e.g. "has", "get", and "getCount" -- but for extensions. The extensions
29 | * are identified using instances of the class {@link GeneratedExtension};
30 | * the protocol compiler generates a static instance of this class for every
31 | * extension in its input. Through the magic of generics, all is made
32 | * type-safe.
33 | *
34 | *
For example, imagine you have the {@code .proto} file:
35 | *
36 | *
37 | * option java_class = "MyProto";
38 | *
39 | * message Foo {
40 | * extensions 1000 to max;
41 | * }
42 | *
43 | * extend Foo {
44 | * optional int32 bar;
45 | * }
46 | *
47 | *
48 | * Then you might write code like:
49 | *
50 | *
51 | * MyProto.Foo foo = getFoo();
52 | * int i = foo.getExtension(MyProto.bar);
53 | *
54 | *
55 | * See also {@link ExtendableBuilder}.
56 | */
57 | @interface PBExtendableMessage : PBGeneratedMessage {
58 | @private
59 | NSMutableDictionary* extensionMap;
60 | NSMutableDictionary* extensionRegistry;
61 | }
62 |
63 | @property (strong) NSMutableDictionary* extensionMap;
64 | @property (strong) NSMutableDictionary* extensionRegistry;
65 |
66 | - (BOOL) hasExtension:(id) extension;
67 | - (id) getExtension:(id) extension;
68 |
69 | //@protected
70 | - (BOOL) extensionsAreInitialized;
71 | - (SInt32) extensionsSerializedSize;
72 | - (void) writeExtensionsToCodedOutputStream:(PBCodedOutputStream*) output
73 | from:(SInt32) startInclusive
74 | to:(SInt32) endExclusive;
75 | - (void) writeExtensionDescriptionToMutableString:(NSMutableString*) output
76 | from:(SInt32) startInclusive
77 | to:(SInt32) endExclusive
78 | withIndent:(NSString*) indent;
79 | - (void) addExtensionDictionaryEntriesToMutableDictionary:(NSMutableDictionary*) output
80 | from:(int32_t) startInclusive
81 | to:(int32_t) endExclusive;
82 | - (BOOL) isEqualExtensionsInOther:(PBExtendableMessage*)otherMessage
83 | from:(SInt32) startInclusive
84 | to:(SInt32) endExclusive;
85 | - (NSUInteger) hashExtensionsFrom:(SInt32) startInclusive
86 | to:(SInt32) endExclusive;
87 |
88 |
89 |
90 | /* @internal */
91 | - (void) ensureExtensionIsRegistered:(id) extension;
92 |
93 | @end
94 |
--------------------------------------------------------------------------------
/Pod/Classes/Model/SKBlob.h:
--------------------------------------------------------------------------------
1 | //
2 | // SKBlob.h
3 | // SnapchatKit
4 | //
5 | // Created by Tanner Bennett on 6/13/15.
6 | // Copyright (c) 2015 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SnapchatKit-Constants.h"
11 |
12 | @class SKStory;
13 |
14 | extern NSData * SKThumbnailFromGCImage(CGImageRef image);
15 |
16 | /** A wrapper for the various kinds of data used throughout the API. */
17 | @interface SKBlob : NSObject
18 |
19 | /** Initializes a blob with the snap found at \c path.
20 | @discussion \c path can be a path to a folder (containing a video and overlay) or a single snap.
21 | @param path The path to a single snap or a folder containing a video and overlay.
22 | @return An initialized \c SKBlob object, or \c nil if there was a problem initializing it. If \c path is a directory, this method will look for the contents of unzipped media specifically. */
23 | + (instancetype)blobWithContentsOfPath:(NSString *)path;
24 | /** Initializes a blob with anonymous data. */
25 | + (instancetype)blobWithData:(NSData *)data;
26 | /** Initializes a blob with story data and passes it to the completion block.
27 | @discussion This method is specifically for story blobs, because they \e used to be CBC encrypted and possibly zipped if it's a video. Yes: stories are no longer encrypted. Get it together, Snapchat...
28 | @param blobData Pretty self explanatory.
29 | @param story The story you wish to retrieve.
30 | @param Whether the data is for a thumbnail or not.
31 | @param completion Takes an error, if any, and an \c SKBlob object. */
32 | + (void)blobWithStoryData:(NSData *)blobData forStory:(SKStory *)story isThumb:(BOOL)thumb completion:(ResponseBlock)completion;
33 |
34 | /** Used to unarchive blobs initialized with anonymous data.
35 | @param completion Takes an error, if any, and new \c SKBlob object. Returns immediately if the blob was not compressed. */
36 | - (void)decompress:(ResponseBlock)completion;
37 |
38 | /** Conveniently writes all data associated with the \c SKBlob object to the disk.
39 | @discussion If the blob has an overlay, this method will write the data and overlay to a folder as \c filename/filename.[jpg|mp4] and \c filename/filename.jpg.
40 | If not, only \c data is written to the specified file.
41 | @param path The \e directory to which to write the receiver's bytes. Pass the desired filename to \e filename. See \c -[NSData writeToFile:atomically:] for more information.
42 | @param filename The name to serialize the blob under.
43 | @param atomically See \c -[NSData writeToFile:atomically:]
44 | @return An array of strings paths to the written files. Overlay is always the second object if applicable. */
45 | - (NSArray *)writeToPath:(NSString *)directoryPath filename:(NSString *)filename atomically:(BOOL)atomically;
46 |
47 | /** The data for the image or video. */
48 | @property (nonatomic, readonly) NSData *data;
49 | /** The overlay for the video. \c nil if not applicable. */
50 | @property (nonatomic, readonly) NSData *overlay;
51 | /** Lazily initialized. The compressed data for the snap should it be uploaded. nil if not need be compressed. */
52 | @property (nonatomic, readonly) NSData *zipData;
53 | /** Lazily initialized.
54 | @discussion The thumbnail for the video to be uploaded. nil if not applicable.
55 | @note You may assign your own if you wish, and it will be used instead of the default one. */
56 | @property (nonatomic ) NSData *videoThumbnail;
57 | /** \c YES if the data is for a JPEG, \c NO if it's something other than a JPEG or PNG. */
58 | @property (nonatomic, readonly) BOOL isImage;
59 | /** \c YES if the data is for a MPEG4 video, \c NO if it's something else. */
60 | @property (nonatomic, readonly) BOOL isVideo;
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/Pod/Classes/Networking/SKClient+Stories.h:
--------------------------------------------------------------------------------
1 | //
2 | // SKClient+Stories.h
3 | // SnapchatKit
4 | //
5 | // Created by Tanner Bennett on 6/13/15.
6 | // Copyright (c) 2015 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "SKClient.h"
11 | #import "SKBlob.h"
12 |
13 | @class SKStory, SKUserStory, SKStoryCollection, SKStoryOptions;
14 |
15 |
16 | @interface SKClient (Stories)
17 |
18 | /** Posts a story with the given options.
19 | @param blob The \c SKBlob object containing the image or video data to send. Can be created with any \c NSData object.
20 | @param options The options for the story to post.
21 | @param completion Takes an error, if any. */
22 | - (void)postStory:(SKBlob *)blob options:(SKStoryOptions *)options completion:(ErrorBlock)completion;
23 | /** Posts a story with the given options.
24 | @param blob The \c SKBlob object containing the image or video data to send. Can be created with any \c NSData object.
25 | @param duration The length of the story. This value is ignored for video snaps.
26 | @param completion Takes an error, if any.
27 | @note Assumes camera not front facing. */
28 | - (void)postStory:(SKBlob *)blob for:(NSTimeInterval)duration completion:(ErrorBlock)completion;
29 |
30 | /** Downloads media for a story.
31 | @param story The story to download.
32 | @param completion Takes an error, if any, and an \c SKBlob object. */
33 | - (void)loadStoryBlob:(SKStory *)story completion:(ResponseBlock)completion;
34 | /** Downloads the thumbnail for a story.
35 | @param story The story whose thumbnail you wish to download.
36 | @param completion Takes an error, if any, and an \c SKBlob object. */
37 | - (void)loadStoryThumbnailBlob:(SKStory *)story completion:(ResponseBlock)completion;
38 |
39 | /** Batch loads media for a set of stories.
40 | @param stories An array of \c SKStory objects whose media you wish to download.
41 | @param completion Takes an error, if any, an array of \c SKStory objects with initialized \c blob properties, and an array of \c SKStory objects that could not be retrieved, if any. */
42 | - (void)loadStories:(NSArray *)stories completion:(CollectionResponseBlock)completion;
43 |
44 | /** Deletes a story of yours.
45 | @param completion Takes an error, if any. */
46 | - (void)deleteStory:(SKUserStory *)story completion:(ErrorBlock)completion;
47 |
48 | /** Marks a set of stories as opened.
49 | @param stories An array of \c SKStoryUpdater objects.
50 | @param completion Takes an error, if any. */
51 | - (void)markStoriesViewed:(NSArray *)stories completion:(ErrorBlock)completion;
52 | /** Marks a single story opened.
53 | @discussion To batch mark stories viewed, use \c -markStoriesViewed:completion:.
54 | @param story The story to mark as opened.
55 | @param sscount The number of times the story was screenshotted.
56 | @param completion Takes an error, if any. */
57 | - (void)markStoryViewed:(SKStory *)story screenshotCount:(NSUInteger)sscount completion:(ErrorBlock)completion;
58 |
59 | /** Hides a shared story from the story feed.
60 | @param completion Takes an error, if any. */
61 | - (void)hideSharedStory:(SKStoryCollection *)story completion:(ErrorBlock)completion;
62 |
63 | /** I forget what this is for. Does nothing if the story is not a shared story.
64 | @param sharedStory A shared story.
65 | @param completion Takes an error, if any. */
66 | - (void)provideSharedDescription:(SKStory *)sharedStory completion:(ErrorBlock)completion;
67 |
68 | /** Retrieves the description for a shared story.
69 | @param sharedStory A shared story.
70 | @param completion Takes an error, if any, and an \c SKSharedStoryDescription object. */
71 | - (void)getSharedDescriptionForStory:(SKUser *)sharedStory completion:(ResponseBlock)completion;
72 |
73 | @end
74 |
--------------------------------------------------------------------------------
/Pod/Classes/Model/SKStory.m:
--------------------------------------------------------------------------------
1 | //
2 | // SKStory.m
3 | // SnapchatKit
4 | //
5 | // Created by Tanner Bennett on 5/18/15.
6 | // Copyright (c) 2015 Tanner Bennett. All rights reserved.
7 | //
8 |
9 | #import "SKStory.h"
10 | #import "SKClient+Stories.h"
11 |
12 | @implementation SKStory
13 |
14 | - (NSString *)description {
15 | return [NSString stringWithFormat:@"<%@ shared=%d, zipped=%d, auth=%d, viewed=%d, duration=%lu, text=%@, time left=%lu>",
16 | NSStringFromClass(self.class), self.shared, self.zipped, self.needsAuth, self.viewed, (unsigned long)self.duration, self.text, (unsigned long)self.timeLeft];
17 | }
18 |
19 | #pragma mark - Mantle
20 |
21 | + (NSDictionary *)JSONKeyPathsByPropertyKey {
22 | return @{@"author": @"story.username",
23 | @"viewed": @"viewed",
24 | @"shared": @"story.is_shared",
25 | @"zipped": @"story.zipped",
26 | @"matureContent": @"story.mature_content",
27 | @"needsAuth": @"story.needs_auth",
28 | @"duration": @"story.time",
29 | @"identifier": @"story.id",
30 | @"text": @"story.caption_text_display",
31 | @"clientIdentifier": @"story.client_id",
32 | @"storyFilterIdentifier": @"story.story_filter_id",
33 | @"adCanFollow": @"story.ad_can_follow",
34 | @"mediaIdentifier": @"story.media_id",
35 | @"mediaIV": @"story.media_iv",
36 | @"mediaKey": @"story.media_key",
37 | @"mediaKind": @"story.media_type",
38 | @"mediaURL": @"story.media_url",
39 | @"thumbIV": @"story.thumbnail_iv",
40 | @"thumbURL": @"story.thumbnail_url",
41 | @"timeLeft": @"story.time_left",
42 | @"created": @"story.timestamp",
43 | @"submissionIdentifier": @"story.submission_id",
44 | @"unlockables": @"story.unlockables"};
45 | }
46 |
47 | MTLTransformPropertyURL(mediaURL)
48 | MTLTransformPropertyURL(thumbURL)
49 | MTLTransformPropertyDate(created)
50 |
51 | #pragma mark - Equality
52 |
53 | - (BOOL)isEqual:(id)object {
54 | if ([object isKindOfClass:[SKStory class]])
55 | return [self isEqualToStory:object];
56 |
57 | return [super isEqual:object];
58 | }
59 |
60 | - (BOOL)isEqualToStory:(SKStory *)story {
61 | return [story.identifier isEqualToString:self.identifier];
62 | }
63 |
64 | - (NSUInteger)hash {
65 | return self.identifier.hash;
66 | }
67 |
68 | @end
69 |
70 | @implementation SKStory (SKClient)
71 |
72 | - (void)load:(ErrorBlock)completion {
73 | NSParameterAssert(completion);
74 | [[SKClient sharedClient] loadStoryBlob:self completion:^(SKBlob *blob, NSError *error) {
75 | if (!error) {
76 | _blob = blob;
77 | completion(nil);
78 | } else {
79 | completion(error);
80 | }
81 | }];
82 | }
83 |
84 | - (void)loadThumbnail:(ErrorBlock)completion {
85 | NSParameterAssert(completion);
86 | [[SKClient sharedClient] loadStoryThumbnailBlob:self completion:^(SKBlob *blob, NSError *error) {
87 | if (!error) {
88 | _thumbnailBlob = blob;
89 | completion(nil);
90 | } else {
91 | completion(error);
92 | }
93 | }];
94 | }
95 |
96 | - (NSString *)suggestedFilename {
97 | if (!self.blob)
98 | return nil;
99 | if (self.blob.isImage)
100 | return [NSString stringWithFormat:@"%@.jpg", self.identifier];
101 | else if (self.blob.overlay)
102 | return self.identifier;
103 | else
104 | return [NSString stringWithFormat:@"%@.mp4", self.identifier];
105 | }
106 |
107 | @end
--------------------------------------------------------------------------------
/Pod/Dependencies/SSZipArchive.h:
--------------------------------------------------------------------------------
1 | //
2 | // SSZipArchive.h
3 | // SSZipArchive
4 | //
5 | // Created by Sam Soffes on 7/21/10.
6 | // Copyright (c) Sam Soffes 2010-2015. All rights reserved.
7 | //
8 |
9 | #ifndef _SSZIPARCHIVE_H
10 | #define _SSZIPARCHIVE_H
11 |
12 | #import
13 | #include "unzip.h"
14 |
15 | @protocol SSZipArchiveDelegate;
16 |
17 | @interface SSZipArchive : NSObject
18 |
19 | // Unzip
20 | + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination completion:(void (^)(NSString *path, BOOL succeeded, NSError *error))completion;
21 | + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination;
22 | + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination delegate:(id)delegate;
23 |
24 | + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error;
25 | + (BOOL)unzipFileAtPath:(NSString *)path toDestination:(NSString *)destination overwrite:(BOOL)overwrite password:(NSString *)password error:(NSError **)error delegate:(id)delegate;
26 |
27 | + (BOOL)unzipFileAtPath:(NSString *)path
28 | toDestination:(NSString *)destination
29 | progressHandler:(void (^)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler
30 | completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler;
31 |
32 | + (BOOL)unzipFileAtPath:(NSString *)path
33 | toDestination:(NSString *)destination
34 | overwrite:(BOOL)overwrite
35 | password:(NSString *)password
36 | progressHandler:(void (^)(NSString *entry, unz_file_info zipInfo, long entryNumber, long total))progressHandler
37 | completionHandler:(void (^)(NSString *path, BOOL succeeded, NSError *error))completionHandler;
38 |
39 | // Zip
40 | + (BOOL)createZipFileAtPath:(NSString *)path withFilesAtPaths:(NSArray *)filenames;
41 | + (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath;
42 | + (BOOL)createZipFileAtPath:(NSString *)path withContentsOfDirectory:(NSString *)directoryPath keepParentDirectory:(BOOL)keepParentDirectory;
43 |
44 | - (id)initWithPath:(NSString *)path;
45 | - (BOOL)open;
46 | - (BOOL)writeFile:(NSString *)path;
47 | - (BOOL)writeFileAtPath:(NSString *)path withFileName:(NSString *)fileName;
48 | - (BOOL)writeData:(NSData *)data filename:(NSString *)filename;
49 | - (BOOL)close;
50 |
51 | @end
52 |
53 | @protocol SSZipArchiveDelegate
54 |
55 | @optional
56 |
57 | - (void)zipArchiveWillUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo;
58 | - (void)zipArchiveDidUnzipArchiveAtPath:(NSString *)path zipInfo:(unz_global_info)zipInfo unzippedPath:(NSString *)unzippedPath;
59 |
60 | - (BOOL)zipArchiveShouldUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo;
61 | - (void)zipArchiveWillUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo;
62 | - (void)zipArchiveDidUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath fileInfo:(unz_file_info)fileInfo;
63 | - (void)zipArchiveDidUnzipFileAtIndex:(NSInteger)fileIndex totalFiles:(NSInteger)totalFiles archivePath:(NSString *)archivePath unzippedFilePath:(NSString *)unzippedFilePath;
64 |
65 | - (void)zipArchiveProgressEvent:(unsigned long long)loaded total:(unsigned long long)total;
66 | - (void)zipArchiveDidUnzipArchiveFile:(NSString *)zipFile entryPath:(NSString *)entryPath destPath:(NSString *)destPath;
67 |
68 | @end
69 |
70 | #endif /* _SSZIPARCHIVE_H */
71 |
--------------------------------------------------------------------------------
/Pod/Dependencies/protobuf/MutableField.m:
--------------------------------------------------------------------------------
1 | // Protocol Buffers for Objective C
2 | //
3 | // Copyright 2010 Booyah Inc.
4 | // Copyright 2008 Cyrus Najmabadi
5 | //
6 | // Licensed under the Apache License, Version 2.0 (the "License");
7 | // you may not use this file except in compliance with the License.
8 | // You may obtain a copy of the License at
9 | //
10 | // http://www.apache.org/licenses/LICENSE-2.0
11 | //
12 | // Unless required by applicable law or agreed to in writing, software
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | #import "MutableField.h"
19 |
20 | #import "Field.h"
21 | #import "PBArray.h"
22 |
23 | @implementation PBMutableField
24 |
25 |
26 | + (PBMutableField *)field {
27 | return [[PBMutableField alloc] init];
28 | }
29 |
30 | - (PBMutableField *)clear {
31 |
32 | _varintArray = nil;
33 | _fixed32Array = nil;
34 | _fixed64Array = nil;
35 | _lengthDelimitedArray = nil;
36 | _groupArray = nil;
37 |
38 | return self;
39 | }
40 |
41 | - (PBMutableField *)mergeFromField:(PBField *)other {
42 | if (other.varintArray.count > 0) {
43 | if (_varintArray == nil) {
44 | _varintArray = [other.varintArray copy];
45 | } else {
46 | [_varintArray appendArray:other.varintArray];
47 | }
48 | }
49 |
50 | if (other.fixed32Array.count > 0) {
51 | if (_fixed32Array == nil) {
52 | _fixed32Array = [other.fixed32Array copy];
53 | } else {
54 | [_fixed32Array appendArray:other.fixed32Array];
55 | }
56 | }
57 |
58 | if (other.fixed64Array.count > 0) {
59 | if (_fixed64Array == nil) {
60 | _fixed64Array = [other.fixed64Array copy];
61 | } else {
62 | [_fixed64Array appendArray:other.fixed64Array];
63 | }
64 | }
65 |
66 | if (other.lengthDelimitedArray.count > 0) {
67 | if (_lengthDelimitedArray == nil) {
68 | _lengthDelimitedArray = [other.lengthDelimitedArray copy];
69 | } else {
70 | [_lengthDelimitedArray addObjectsFromArray:other.lengthDelimitedArray];
71 | }
72 | }
73 |
74 | if (other.groupArray.count > 0) {
75 | if (_groupArray == nil) {
76 | _groupArray = [other.groupArray copy];
77 | } else {
78 | [_groupArray addObjectsFromArray:other.groupArray];
79 | }
80 | }
81 |
82 | return self;
83 | }
84 |
85 | - (PBMutableField *)addVarint:(SInt64)value {
86 | if (_varintArray == nil) {
87 | _varintArray = [[PBAppendableArray alloc] initWithValueType:PBArrayValueTypeInt64];
88 | }
89 | [_varintArray addInt64:value];
90 |
91 | return self;
92 | }
93 |
94 | - (PBMutableField *)addFixed32:(SInt32)value {
95 | if (_fixed32Array == nil) {
96 | _fixed32Array = [[PBAppendableArray alloc] initWithValueType:PBArrayValueTypeInt32];
97 | }
98 | [_fixed32Array addInt32:value];
99 |
100 | return self;
101 | }
102 |
103 | - (PBMutableField *)addFixed64:(SInt64)value {
104 | if (_fixed64Array == nil) {
105 | _fixed64Array = [[PBAppendableArray alloc] initWithValueType:PBArrayValueTypeInt64];
106 | }
107 | [_fixed64Array addInt64:value];
108 |
109 | return self;
110 | }
111 |
112 | - (PBMutableField *)addLengthDelimited:(NSData *)value {
113 | if (_lengthDelimitedArray == nil) {
114 | _lengthDelimitedArray = [[NSMutableArray alloc] init];
115 | }
116 | [_lengthDelimitedArray addObject:value];
117 |
118 | return self;
119 | }
120 |
121 | - (PBMutableField *)addGroup:(PBUnknownFieldSet *)value {
122 | if (_groupArray == nil) {
123 | _groupArray = [[NSMutableArray alloc] init];
124 | }
125 | [_groupArray addObject:value];
126 |
127 | return self;
128 | }
129 |
130 | @end
--------------------------------------------------------------------------------