Skip to content
This repository has been archived by the owner on Aug 10, 2024. It is now read-only.

Updated package to support media:content tag #71

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Sources/ObjC/RSParsedArticle.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

@import Foundation;

@class RSParsedMediaContent;
@class RSParsedEnclosure;
@class RSParsedAuthor;

Expand All @@ -25,6 +26,7 @@
@property (nonatomic, nullable) NSString *permalink;
@property (nonatomic, nullable) NSSet<RSParsedAuthor *> *authors;
@property (nonatomic, nullable) NSSet<RSParsedEnclosure *> *enclosures;
@property (nonatomic, nullable) RSParsedMediaContent *mediaContent;
@property (nonatomic, nullable) NSDate *datePublished;
@property (nonatomic, nullable) NSDate *dateModified;
@property (nonatomic, nonnull) NSDate *dateParsed;
Expand Down
3 changes: 1 addition & 2 deletions Sources/ObjC/RSParsedArticle.m
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#import "NSString+RSParser.h"
#import "RSParsedAuthor.h"
#import "RSParsedEnclosure.h"

#import "RSParsedMediaContent.h"


@implementation RSParsedArticle
Expand All @@ -35,7 +35,6 @@ - (instancetype)initWithFeedURL:(NSString *)feedURL {
return self;
}


#pragma mark - Enclosures

- (void)addEnclosure:(RSParsedEnclosure *)enclosure {
Expand Down
24 changes: 24 additions & 0 deletions Sources/ObjC/RSParsedMediaContent.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// RSParsedMediaContent.h
// RSParser
//
//
// Created by Marcelo Perretta on 07/04/2022.
//

@import Foundation;
#import "RSParsedMediaDescription.h"
#import "RSParsedMediaCredit.h"

NS_ASSUME_NONNULL_BEGIN

@interface RSParsedMediaContent : NSObject

@property (nonatomic) NSString *url;
@property (nonatomic, nullable) NSString *mimeType;
@property (nonatomic, nullable) RSParsedMediaDescription *mediaDescription;
@property (nonatomic, nullable) RSParsedMediaCredit *mediaCredit;

@end

NS_ASSUME_NONNULL_END
13 changes: 13 additions & 0 deletions Sources/ObjC/RSParsedMediaContent.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// RSParsedMediaContent.m
// RSParser
//
//
// Created by Marcelo Perretta on 07/04/2022.
//

#import "RSParsedMediaContent.h"

@implementation RSParsedMediaContent

@end
21 changes: 21 additions & 0 deletions Sources/ObjC/RSParsedMediaCredit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// RSParsedMediaCredit.h
// RSParser
//
//
// Created by Marcelo Perretta on 07/04/2022.
//

@import Foundation;

NS_ASSUME_NONNULL_BEGIN

@interface RSParsedMediaCredit : NSObject

@property (nonatomic, nullable) NSString *mediaCreditRole;
@property (nonatomic, nullable) NSString *mediaCreditScheme;
@property (nonatomic, nullable) NSString *mediaCreditDescription;

@end

NS_ASSUME_NONNULL_END
13 changes: 13 additions & 0 deletions Sources/ObjC/RSParsedMediaCredit.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// RSParsedMediaCredit.m
// RSParser
//
//
// Created by Marcelo Perretta on 07/04/2022.
//

#import "RSParsedMediaCredit.h"

@implementation RSParsedMediaCredit

@end
21 changes: 21 additions & 0 deletions Sources/ObjC/RSParsedMediaDescription.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// RSParsedMediaDescription.h
// RSParser
//
//
// Created by Marcelo Perretta on 07/04/2022.
//

@import Foundation;

NS_ASSUME_NONNULL_BEGIN

@interface RSParsedMediaDescription : NSObject

@property (nonatomic, nullable) NSString *mimeType;
@property (nonatomic, nullable) NSString *mediaDescription;

@end

NS_ASSUME_NONNULL_END

13 changes: 13 additions & 0 deletions Sources/ObjC/RSParsedMediaDescription.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// RSParsedMediaDescription.m
// RSParser
//
//
// Created by Marcelo Perretta on 07/04/2022.
//

#import "RSParsedMediaDescription.h"

@implementation RSParsedMediaDescription

@end
91 changes: 85 additions & 6 deletions Sources/ObjC/RSRSSParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#import "NSString+RSParser.h"
#import "RSDateParser.h"
#import "ParserData.h"
#import "RSParsedMediaContent.h"
#import "RSParsedEnclosure.h"
#import "RSParsedAuthor.h"

Expand All @@ -31,6 +32,7 @@ @interface RSRSSParser () <RSSAXParserDelegate>
@property (nonatomic) NSMutableArray *articles;
@property (nonatomic) BOOL parsingArticle;
@property (nonatomic) BOOL parsingAuthor;
@property (nonatomic) BOOL parsingMedia;
@property (nonatomic, readonly) RSParsedArticle *currentArticle;
@property (nonatomic) BOOL parsingChannelImage;
@property (nonatomic, readonly) NSDate *currentDate;
Expand Down Expand Up @@ -95,6 +97,8 @@ - (RSParsedFeed *)parseFeed {
static NSString *kDCDateKey = @"dc:date";
static NSString *kDCCreatorKey = @"dc:creator";
static NSString *kRDFAboutKey = @"rdf:about";
static NSString *kMediaCreditRole = @"role";
static NSString *kMediaCreditScheme = @"scheme";

static const char *kItem = "item";
static const NSInteger kItemLength = 5;
Expand Down Expand Up @@ -168,6 +172,12 @@ - (RSParsedFeed *)parseFeed {
static const char *kEnclosure = "enclosure";
static const NSInteger kEnclosureLength = 10;

static const char *kMediaContent = "media";
static const NSInteger kMediaContentLength = 10;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 10 should be 6 — m-e-d-i-a plus a null character is 6 characters.


static const char *kMediaCredit = "credit";
static const NSInteger kMediaCreditLengt = 10;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 10 should be 6.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kMediaCreditLengt is missing an h at the end — should be kMediaCreditLength


static const char *kLanguage = "language";
static const NSInteger kLanguageLength = 9;

Expand Down Expand Up @@ -254,6 +264,45 @@ - (void)addGuid {
}
}

- (void)addMediaContent {
NSDictionary *attributes = self.currentAttributes;
NSString *url = attributes[kURLKey];
if (!url || url.length < 1) {
return;
}

RSParsedMediaContent *mediaContent = [[RSParsedMediaContent alloc] init];
mediaContent.url = url;
mediaContent.mimeType = attributes[kTypeKey];

self.currentArticle.mediaContent = mediaContent;
}

- (void)addMediaDescription {

NSString *s = [self currentString];
if (!RSParserStringIsEmpty(s)) {
RSParsedMediaDescription *mediaDescription = [[RSParsedMediaDescription alloc] init];
mediaDescription.mediaDescription = s;
mediaDescription.mimeType = self.currentAttributes[kTypeKey];
self.currentArticle.mediaContent.mediaDescription = mediaDescription;
}
}

- (void)addMediaCredit {

NSDictionary *attributes = self.currentAttributes;
NSString *s = [self currentString];
if (!RSParserStringIsEmpty(s)) {
RSParsedMediaCredit *mediaCredit = [[RSParsedMediaCredit alloc] init];
mediaCredit.mediaCreditDescription = s;
mediaCredit.mediaCreditRole = attributes[kMediaCreditRole];
mediaCredit.mediaCreditScheme = attributes[kMediaCreditScheme];

self.currentArticle.mediaContent.mediaCredit = mediaCredit;
}
}

- (void)addEnclosure {

NSDictionary *attributes = self.currentAttributes;
Expand Down Expand Up @@ -340,6 +389,18 @@ - (void)addArticleElement:(const xmlChar *)localName prefix:(const xmlChar *)pre
return;
}


if (RSSAXEqualTags(prefix, kMediaContent, kMediaContentLength)) {
if (RSSAXEqualTags(localName, kDescription, kDescription)) {
[self addMediaDescription];
}
else if (RSSAXEqualTags(localName, kMediaCredit, kMediaContentLength)) {
[self addMediaCredit];
}

return;
}

if (prefix != NULL) {
return;
}
Expand Down Expand Up @@ -394,12 +455,17 @@ - (void)saxParser:(RSSAXParser *)SAXParser XMLStartElement:(const xmlChar *)loca
}

NSDictionary *xmlAttributes = nil;
if ((self.isRDF && RSSAXEqualTags(localName, kItem, kItemLength)) || RSSAXEqualTags(localName, kGuid, kGuidLength) || RSSAXEqualTags(localName, kEnclosure, kEnclosureLength)) {
xmlAttributes = [self.parser attributesDictionary:attributes numberOfAttributes:numberOfAttributes];
}
if (self.currentAttributes != xmlAttributes) {
self.currentAttributes = xmlAttributes;
}
if ((self.isRDF &&
RSSAXEqualTags(localName, kItem, kItemLength)) ||
RSSAXEqualTags(localName, kGuid, kGuidLength) ||
RSSAXEqualTags(localName, kEnclosure, kEnclosureLength) ||
RSSAXEqualTags(prefix, kMediaContent, kMediaContentLength)) {
xmlAttributes = [self.parser attributesDictionary:attributes numberOfAttributes:numberOfAttributes];
}

if (self.currentAttributes != xmlAttributes) {
self.currentAttributes = xmlAttributes;
}

if (!prefix && RSSAXEqualTags(localName, kItem, kItemLength)) {

Expand All @@ -420,6 +486,12 @@ - (void)saxParser:(RSSAXParser *)SAXParser XMLStartElement:(const xmlChar *)loca
self.parsingAuthor = true;
}
}
else if (prefix && RSSAXEqualTags(prefix, kMediaContent, kMediaContentLength)) {
if (self.parsingArticle && prefix && RSSAXEqualTags(localName, kContent, kContent)) {
[self addMediaContent];
self.parsingMedia = true;
}
}

if (!self.parsingChannelImage) {
[self.parser beginStoringCharacters];
Expand Down Expand Up @@ -449,6 +521,13 @@ - (void)saxParser:(RSSAXParser *)SAXParser XMLEndElement:(const xmlChar *)localN
self.parsingArticle = NO;
}

else if (self.parsingMedia) {
[self addArticleElement:localName prefix:prefix];
if (RSSAXEqualTags(localName, kContent, kContentLength) && RSSAXEqualTags(prefix, kMediaContent, kMediaContentLength)) {
self.parsingMedia = NO;
}
}

else if (self.parsingArticle) {
[self addArticleElement:localName prefix:prefix];
if (RSSAXEqualTags(localName, kAuthor, kAuthorLength)) {
Expand Down
1 change: 1 addition & 0 deletions Sources/ObjC/include/RSParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#import "../RSAtomParser.h"
#import "../RSParsedFeed.h"
#import "../RSParsedArticle.h"
#import "../RSParsedMediaContent.h"
#import "../RSParsedEnclosure.h"
#import "../RSParsedAuthor.h"

Expand Down
2 changes: 1 addition & 1 deletion Sources/Swift/Feeds/JSON/JSONFeedParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ private extension JSONFeedParser {
}
let attachments = parseAttachments(itemDictionary)

return ParsedItem(syncServiceID: nil, uniqueID: uniqueID, feedURL: feedURL, url: url, externalURL: externalURL, title: title, language: language, contentHTML: contentHTML, contentText: contentText, summary: summary, imageURL: imageURL, bannerImageURL: bannerImageURL, datePublished: datePublished, dateModified: dateModified, authors: authors, tags: tags, attachments: attachments)
return ParsedItem(syncServiceID: nil, uniqueID: uniqueID, feedURL: feedURL, url: url, externalURL: externalURL, title: title, language: language, contentHTML: contentHTML, contentText: contentText, summary: summary, imageURL: imageURL, bannerImageURL: bannerImageURL, datePublished: datePublished, dateModified: dateModified, mediaContent: nil, authors: authors, tags: tags, attachments: attachments)
}

static func parseTitle(_ itemDictionary: JSONDictionary, _ feedURL: String) -> String? {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Swift/Feeds/JSON/RSSInJSONParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ private extension RSSInJSONParser {
}

if let uniqueID = uniqueID {
return ParsedItem(syncServiceID: nil, uniqueID: uniqueID, feedURL: feedURL, url: nil, externalURL: externalURL, title: title, language: nil, contentHTML: contentHTML, contentText: contentText, summary: nil, imageURL: nil, bannerImageURL: nil, datePublished: datePublished, dateModified: nil, authors: authors, tags: tags, attachments: attachments)
return ParsedItem(syncServiceID: nil, uniqueID: uniqueID, feedURL: feedURL, url: nil, externalURL: externalURL, title: title, language: nil, contentHTML: contentHTML, contentText: contentText, summary: nil, imageURL: nil, bannerImageURL: nil, datePublished: datePublished, dateModified: nil, mediaContent: nil, authors: authors, tags: tags, attachments: attachments)
}
return nil
}
Expand Down
5 changes: 4 additions & 1 deletion Sources/Swift/Feeds/ParsedItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

import Foundation
import RSParserObjC

public struct ParsedItem: Hashable {

Expand All @@ -24,13 +25,14 @@ public struct ParsedItem: Hashable {
public let bannerImageURL: String?
public let datePublished: Date?
public let dateModified: Date?
public let mediaContent: RSParsedMediaContent?
public let authors: Set<ParsedAuthor>?
public let tags: Set<String>?
public let attachments: Set<ParsedAttachment>?

public init(syncServiceID: String?, uniqueID: String, feedURL: String, url: String?, externalURL: String?, title: String?,
language: String?, contentHTML: String?, contentText: String?, summary: String?, imageURL: String?,
bannerImageURL: String?,datePublished: Date?, dateModified: Date?, authors: Set<ParsedAuthor>?,
bannerImageURL: String?,datePublished: Date?, dateModified: Date?, mediaContent: RSParsedMediaContent?, authors: Set<ParsedAuthor>?,
tags: Set<String>?, attachments: Set<ParsedAttachment>?) {

self.syncServiceID = syncServiceID
Expand All @@ -48,6 +50,7 @@ public struct ParsedItem: Hashable {
self.datePublished = datePublished
self.dateModified = dateModified
self.authors = authors
self.mediaContent = mediaContent
self.tags = tags
self.attachments = attachments
}
Expand Down
25 changes: 13 additions & 12 deletions Sources/Swift/Feeds/XML/RSParsedFeedTransformer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ private extension RSParsedFeedTransformer {
let datePublished = parsedArticle.datePublished
let dateModified = parsedArticle.dateModified
let authors = parsedAuthors(parsedArticle.authors)
let attachments = parsedAttachments(parsedArticle.enclosures)
let mediaContent = parsedArticle.mediaContent
let attachments = parsedAttachments(parsedArticle.enclosures)

return ParsedItem(syncServiceID: nil, uniqueID: uniqueID, feedURL: parsedArticle.feedURL, url: url, externalURL: externalURL, title: title, language: language, contentHTML: contentHTML, contentText: nil, summary: nil, imageURL: nil, bannerImageURL: nil, datePublished: datePublished, dateModified: dateModified, authors: authors, tags: nil, attachments: attachments)
return ParsedItem(syncServiceID: nil, uniqueID: uniqueID, feedURL: parsedArticle.feedURL, url: url, externalURL: externalURL, title: title, language: language, contentHTML: contentHTML, contentText: nil, summary: nil, imageURL: nil, bannerImageURL: nil, datePublished: datePublished, dateModified: dateModified, mediaContent: mediaContent, authors: authors, tags: nil, attachments: attachments)
}

static func parsedAuthors(_ authors: Set<RSParsedAuthor>?) -> Set<ParsedAuthor>? {
Expand All @@ -63,18 +64,18 @@ private extension RSParsedFeedTransformer {
return transformedAuthors.isEmpty ? nil : Set(transformedAuthors)
}

static func parsedAttachments(_ enclosures: Set<RSParsedEnclosure>?) -> Set<ParsedAttachment>? {
static func parsedAttachments(_ enclosures: Set<RSParsedEnclosure>?) -> Set<ParsedAttachment>? {

guard let enclosures = enclosures, !enclosures.isEmpty else {
return nil
}
guard let enclosures = enclosures, !enclosures.isEmpty else {
return nil
}

let attachments = enclosures.compactMap { (enclosure) -> ParsedAttachment? in
let attachments = enclosures.compactMap { (enclosure) -> ParsedAttachment? in

let sizeInBytes = enclosure.length > 0 ? enclosure.length : nil
return ParsedAttachment(url: enclosure.url, mimeType: enclosure.mimeType, title: nil, sizeInBytes: sizeInBytes, durationInSeconds: nil)
}
let sizeInBytes = enclosure.length > 0 ? enclosure.length : nil
return ParsedAttachment(url: enclosure.url, mimeType: enclosure.mimeType, title: nil, sizeInBytes: sizeInBytes, durationInSeconds: nil)
}

return attachments.isEmpty ? nil : Set(attachments)
}
return attachments.isEmpty ? nil : Set(attachments)
}
}
Loading