No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

Apollo.xm 7.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #import "Apollo.h"
  2. %group Apollo
  3. %hook ApolloApolloButtonNode
  4. %end
  5. NSDictionary* apolloBodyAttributes = nil;
  6. %hook RKComment
  7. -(BOOL) isDeleted{
  8. return NO;
  9. }
  10. %end
  11. %hook MarkdownRenderer
  12. +(id) attributedStringFromHTML:(id)arg1 attributes:(id) arg2 compact:(BOOL) arg3{
  13. apolloBodyAttributes = [arg2 copy];
  14. return %orig;
  15. }
  16. %end
  17. %hook ApolloCommentCellNode
  18. %property(assign,nonatomic) id undeleteButton;
  19. %new
  20. -(void) didTapUndeleteButton{
  21. id bodyNode = MSHookIvar<id>(self, "bodyNode");
  22. id authorNode = MSHookIvar<id>(self, "authorNode");
  23. id authorTextNode = [authorNode subnodes][0];
  24. id comment = MSHookIvar<id>(self, "comment");
  25. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
  26. NSOperationQueue *queue = [[NSOperationQueue alloc] init];
  27. [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.pushshift.io/reddit/search/comment/?ids=%@&fields=author,body",[[comment fullName] componentsSeparatedByString:@"_"][1]]]];
  28. [request setHTTPMethod:@"GET"];
  29. [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
  30. NSString *author = @"[author]";
  31. NSString *body = @"[body]";
  32. if (data != nil && error == nil){
  33. id jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
  34. if ([[jsonData objectForKey:@"data"] count] != 0){
  35. author = [[jsonData objectForKey:@"data"][0] objectForKey:@"author"];
  36. body = [[jsonData objectForKey:@"data"][0] objectForKey:@"body"];
  37. if ([body isEqualToString:@"[deleted]"] || [body isEqualToString:@"[removed]"]){
  38. body = @"[pushshift was unable to archive this]";
  39. }
  40. } else {
  41. body = @"[pushshift has not archived this yet]";
  42. }
  43. } else if (error != nil || data == nil){
  44. body = @"[an error occured]";
  45. }
  46. id prevAuthorAttributedString = [authorTextNode attributedString];
  47. NSDictionary *authorStringAttributes = [prevAuthorAttributedString attributesAtIndex:0 longestEffectiveRange:nil inRange:NSMakeRange(0, [prevAuthorAttributedString length])];
  48. NSAttributedString* newAuthorAttributedString = [[NSAttributedString alloc] initWithString:author attributes:authorStringAttributes];
  49. [authorTextNode setAttributedText:newAuthorAttributedString];
  50. [authorTextNode setAttributedString:newAuthorAttributedString];
  51. [comment setAuthor:author];
  52. [bodyNode setAttributedString:[%c(MarkdownRenderer) attributedStringFromMarkdown:body withAttributes:apolloBodyAttributes]];
  53. }];
  54. }
  55. -(void) didLoad {
  56. %orig;
  57. CGFloat imageSize = 20.0f;
  58. UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
  59. [undeleteButton addTarget:self action:@selector(didTapUndeleteButton) forControlEvents:UIControlEventTouchUpInside];
  60. undeleteButton.frame = CGRectMake(0, 0, imageSize, imageSize);
  61. UIImage* undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"];
  62. [undeleteButton setImage:undeleteImage forState:UIControlStateNormal];
  63. [[self view] addSubview:undeleteButton];
  64. [self setUndeleteButton:undeleteButton];
  65. }
  66. -(void) _layoutSublayouts{
  67. %orig;
  68. CGFloat imageSize = 20.0f;
  69. id moreNode = MSHookIvar<id>(self, "moreOptionsNode");
  70. id ageNode = MSHookIvar<id>(self, "ageNode");
  71. CGRect nodeFrame = [moreNode frame];
  72. CGFloat centerHeight = (nodeFrame.size.height + nodeFrame.origin.y * 2) / 2.0f;
  73. CGFloat nodeSpacing =[ageNode frame].origin.x - nodeFrame.origin.x - nodeFrame.size.width;
  74. [[self undeleteButton] setFrame:CGRectMake(nodeFrame.origin.x - imageSize - nodeSpacing, centerHeight - (imageSize / 2), imageSize, imageSize)];
  75. }
  76. %end
  77. %hook ApolloCommentsHeaderCellNode
  78. %property(assign, nonatomic) id undeleteButton;
  79. %new
  80. -(void) didTapUndeleteButton{
  81. id bodyNode = MSHookIvar<id>(self, "bodyNode");
  82. id postInfoNode = MSHookIvar<id>(self, "postInfoNode");
  83. id authorNode = MSHookIvar<id>(postInfoNode, "authorButtonNode");
  84. id authorTextNode = [authorNode subnodes][0];
  85. id post = MSHookIvar<id>(self, "link");
  86. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
  87. NSOperationQueue *queue = [[NSOperationQueue alloc] init];
  88. [request setURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.pushshift.io/reddit/search/submission/?ids=%@&fields=author,selftext",[[post fullName] componentsSeparatedByString:@"_"][1]]]];
  89. [request setHTTPMethod:@"GET"];
  90. [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
  91. NSString *author = @"[author]";
  92. NSString *body = @"[body]";
  93. if (data != nil && error == nil){
  94. id jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
  95. if ([[jsonData objectForKey:@"data"] count] != 0){
  96. author = [[jsonData objectForKey:@"data"][0] objectForKey:@"author"];
  97. body = [[jsonData objectForKey:@"data"][0] objectForKey:@"selftext"];
  98. if ([body isEqualToString:@"[deleted]"] || [body isEqualToString:@"[removed]"]){
  99. body = @"[pushshift was unable to archive this]";
  100. }
  101. } else {
  102. body = @"[pushshift has not archived this yet]";
  103. }
  104. } else if (error != nil || data == nil){
  105. body = @"[an error occured]";
  106. }
  107. //MSHookIvar<NSString*>(post, "_author") = author; //Crashes when clicking on author name. You will have to search the author name to go find the profile.
  108. author = [NSString stringWithFormat:@"by %@", author];
  109. id prevAuthorAttributedString = [authorTextNode attributedString];
  110. NSDictionary *authorStringAttributes = [prevAuthorAttributedString attributesAtIndex:0 longestEffectiveRange:nil inRange:NSMakeRange(0, [prevAuthorAttributedString length])];
  111. NSAttributedString* newAuthorAttributedString = [[NSAttributedString alloc] initWithString:author attributes:authorStringAttributes];
  112. [authorTextNode setAttributedText:newAuthorAttributedString];
  113. [authorTextNode setAttributedString:newAuthorAttributedString];
  114. [bodyNode setAttributedString:[%c(MarkdownRenderer) attributedStringFromMarkdown:body withAttributes:apolloBodyAttributes]];
  115. }];
  116. }
  117. -(void) didLoad{
  118. %orig;
  119. if ([MSHookIvar<id>(self, "link") isSelfPost]){
  120. CGFloat imageSize = 20.0f;
  121. UIButton *undeleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
  122. [undeleteButton addTarget:self action:@selector(didTapUndeleteButton) forControlEvents:UIControlEventTouchUpInside];
  123. UIImage* undeleteImage = [UIImage imageWithContentsOfFile:@"/var/mobile/Library/Application Support/TFDidThatSay/eye160dark.png"];
  124. [undeleteButton setImage:undeleteImage forState:UIControlStateNormal];
  125. undeleteButton.frame = CGRectMake(0, 0, imageSize, imageSize);
  126. [[self view] addSubview:undeleteButton];
  127. [self setUndeleteButton:undeleteButton];
  128. }
  129. }
  130. -(void) _layoutSublayouts{
  131. %orig;
  132. if ([self undeleteButton]){
  133. CGFloat imageSize = 20.0f;
  134. id postInfoNode = MSHookIvar<id>(self, "postInfoNode");
  135. id ageNode = MSHookIvar<id>(postInfoNode, "ageButtonNode");
  136. CGFloat centerHeight = [postInfoNode frame].origin.y + ([ageNode frame].size.height + [ageNode frame].origin.y * 2) / 2.0f;
  137. CGFloat buttonXPos = [postInfoNode frame].origin.x + [postInfoNode frame].size.width - imageSize;
  138. [[self undeleteButton] setFrame:CGRectMake(buttonXPos, centerHeight - (imageSize / 2), imageSize, imageSize)];
  139. }
  140. }
  141. %end
  142. %end
  143. %ctor {
  144. NSString* processName = [[NSProcessInfo processInfo] processName];
  145. if ([processName isEqualToString:@"Apollo"]){
  146. %init(Apollo, ApolloCommentsHeaderCellNode = objc_getClass("Apollo.CommentsHeaderCellNode"), ApolloCommentCellNode = objc_getClass("Apollo.CommentCellNode"), ApolloApolloButtonNode = objc_getClass("Apollo.ApolloButtonNode"));
  147. }
  148. }