You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
7.1KB

  1. #import "Narwhal.h"
  2. static BOOL isNarwhalEnabled;
  3. static CGFloat pushshiftRequestTimeoutValue;
  4. %group Narwhal
  5. BOOL shouldHaveUndeleteAction = NO;
  6. id tfComment;
  7. id tfController;
  8. void getUndeleteCommentData(id controller, id comment){
  9. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
  10. NSOperationQueue *queue = [[NSOperationQueue alloc] init];
  11. [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.pushshift.io/reddit/search/comment/?ids=%@&fields=author,body",[[comment fullName] componentsSeparatedByString:@"_"][1]]]];
  12. [request setHTTPMethod:@"GET"];
  13. [request setTimeoutInterval:pushshiftRequestTimeoutValue];
  14. [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
  15. NSString *author = @"[author]";
  16. NSString *body = @"[body]";
  17. if (data != nil && error == nil){
  18. id jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
  19. if ([[jsonData objectForKey:@"data"] count] != 0){
  20. author = [[jsonData objectForKey:@"data"][0] objectForKey:@"author"];
  21. body = [[jsonData objectForKey:@"data"][0] objectForKey:@"body"];
  22. if ([body isEqualToString:@"[deleted]"] || [body isEqualToString:@"[removed]"]){
  23. body = @"[pushshift was unable to archive this]";
  24. }
  25. } else {
  26. body = @"[pushshift has not archived this yet]";
  27. }
  28. } else if (error != nil || data == nil){
  29. body = [NSString stringWithFormat:@"[an error occured while attempting to contact pushshift api (%@)]", [error localizedDescription]];
  30. }
  31. [controller performSelectorOnMainThread:@selector(completeUndeleteComment:) withObject:@{@"body":body, @"author":author, @"comment":comment} waitUntilDone:NO];
  32. }];
  33. }
  34. %hook UIViewController
  35. -(void) presentViewController:(id) arg1 animated:(BOOL) arg2 completion:(id) arg3{
  36. if ([arg1 isKindOfClass:[UIAlertController class]] && shouldHaveUndeleteAction){
  37. UIAlertAction* undeleteAction;
  38. if (tfComment){
  39. undeleteAction = [UIAlertAction actionWithTitle:@"tf did that say?" style:nil handler:^(UIAlertAction* action){getUndeleteCommentData(tfController, tfComment);}];
  40. } else {
  41. undeleteAction = [UIAlertAction actionWithTitle:@"tf did that say?" style:nil handler:^(UIAlertAction* action){[tfController handleUndeletePostAction];}];
  42. }
  43. [arg1 addAction:undeleteAction];
  44. }
  45. %orig;
  46. }
  47. %end
  48. %hook NRTLinkViewController
  49. %new
  50. -(void) completeUndeleteComment:(id) data{
  51. id comment = data[@"comment"];
  52. if (comment){
  53. MSHookIvar<NSString*>(comment, "_author") = data[@"author"];
  54. MSHookIvar<NSString*>(comment, "_body") = data[@"body"];
  55. [[self commentsManager] updateComment:comment fromEdited:comment];
  56. }
  57. }
  58. %new
  59. -(void) completeUndeletePost:(id) data{
  60. id post = data[@"post"];
  61. MSHookIvar<NSString*>(post, "_author") = data[@"author"];
  62. NSAttributedString* postBodyAttributedString = [%c(NRTMarkdownManager) attributedStringFromMarkdown:data[@"body"] type:0];
  63. [self setLinkText:postBodyAttributedString];
  64. [[self tableView] reloadData];
  65. }
  66. %new
  67. -(void) handleUndeletePostAction{
  68. id post = [self link];
  69. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
  70. NSOperationQueue *queue = [[NSOperationQueue alloc] init];
  71. [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.pushshift.io/reddit/search/submission/?ids=%@&fields=author,selftext",[[post fullName] componentsSeparatedByString:@"_"][1]]]];
  72. [request setHTTPMethod:@"GET"];
  73. [request setTimeoutInterval:pushshiftRequestTimeoutValue];
  74. [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
  75. NSString *author = @"[author]";
  76. NSString *body = @"[body]";
  77. if (data != nil && error == nil){
  78. id jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
  79. if ([[jsonData objectForKey:@"data"] count] != 0){
  80. author = [[jsonData objectForKey:@"data"][0] objectForKey:@"author"];
  81. body = [[jsonData objectForKey:@"data"][0] objectForKey:@"selftext"];
  82. if ([body isEqualToString:@"[deleted]"] || [body isEqualToString:@"[removed]"]){
  83. body = @"[pushshift was unable to archive this]";
  84. }
  85. } else {
  86. body = @"[pushshift has not archived this yet]";
  87. }
  88. } else if (error != nil || data == nil){
  89. body = [NSString stringWithFormat:@"[an error occured while attempting to contact pushshift api (%@)]", [error localizedDescription]];
  90. }
  91. [self performSelectorOnMainThread:@selector(completeUndeletePost:) withObject:@{@"body":body, @"author":author, @"post":post} waitUntilDone:NO];
  92. }];
  93. }
  94. -(void) swipeCell:(id) arg1 didEndDragWithState:(NSUInteger) arg2{
  95. if (arg2 == 2){
  96. if ([arg1 isKindOfClass:[%c(NRTCommentTableViewCell) class]]) {
  97. tfComment = [arg1 comment];
  98. tfController = self;
  99. shouldHaveUndeleteAction = YES;
  100. }
  101. }
  102. %orig;
  103. shouldHaveUndeleteAction = NO;
  104. }
  105. -(void) _dotsButtonTouched:(id) arg1{
  106. if ([self linkTextOffscreenCell]){
  107. tfController = self;
  108. tfComment = nil;
  109. shouldHaveUndeleteAction = YES;
  110. }
  111. %orig;
  112. shouldHaveUndeleteAction = NO;
  113. }
  114. %end
  115. %hook NRTMediaTableViewDataSource
  116. %new
  117. -(void) completeUndeleteComment:(id) data{
  118. id comment = data[@"comment"];
  119. if (comment){
  120. MSHookIvar<NSString*>(comment, "_author") = data[@"author"];
  121. MSHookIvar<NSString*>(comment, "_body") = data[@"body"];
  122. [[self commentsManager] updateComment:comment fromEdited:comment];
  123. }
  124. }
  125. -(void) swipeCell:(id) arg1 didEndDragWithState:(NSUInteger) arg2{
  126. if (arg2 == 2){
  127. if ([arg1 isKindOfClass:[%c(NRTCommentTableViewCell) class]]) {
  128. tfComment = [arg1 comment];
  129. tfController = self;
  130. shouldHaveUndeleteAction = YES;
  131. }
  132. }
  133. %orig;
  134. shouldHaveUndeleteAction = NO;
  135. }
  136. %end
  137. %end
  138. static void loadPrefs(){
  139. NSMutableDictionary *prefs = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/User/Library/Preferences/com.lint.undelete.prefs.plist"];
  140. if (prefs){
  141. if ([prefs objectForKey:@"isNarwhalEnabled"] != nil){
  142. isNarwhalEnabled = [[prefs objectForKey:@"isNarwhalEnabled"] boolValue];
  143. } else {
  144. isNarwhalEnabled = YES;
  145. }
  146. if ([prefs objectForKey:@"requestTimeoutValue"] != nil){
  147. pushshiftRequestTimeoutValue = [[prefs objectForKey:@"requestTimeoutValue"] doubleValue];
  148. } else {
  149. pushshiftRequestTimeoutValue = 10;
  150. }
  151. } else {
  152. isNarwhalEnabled = YES;
  153. pushshiftRequestTimeoutValue = 10;
  154. }
  155. }
  156. static void prefsChanged(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef userInfo) {
  157. loadPrefs();
  158. }
  159. %ctor {
  160. loadPrefs();
  161. NSString* processName = [[NSProcessInfo processInfo] processName];
  162. if ([processName isEqualToString:@"narwhal"]){
  163. if (isNarwhalEnabled){
  164. CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, prefsChanged, CFSTR("com.lint.undelete.prefs.changed"), NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
  165. %init(Narwhal);
  166. }
  167. }
  168. }