mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Scripting support for articles and basic article properties
Also, added support for accessing feeds directly from the top level container, essentially skipping account as a hierarchy level. With this change, a script like tell app “Evergreen” title of every article of feed "Six Colors" where read is true end tell produces the expected result.
This commit is contained in:
111
Evergreen/Scriptability/Article+Scriptability.swift
Normal file
111
Evergreen/Scriptability/Article+Scriptability.swift
Normal file
@@ -0,0 +1,111 @@
|
||||
//
|
||||
// Article+Scriptability.swift
|
||||
// Evergreen
|
||||
//
|
||||
// Created by Olof Hellman on 1/23/18.
|
||||
// Copyright © 2018 Olof Hellman. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Account
|
||||
import Data
|
||||
|
||||
@objc(ScriptableArticle)
|
||||
class ScriptableArticle: NSObject, UniqueIdScriptingObject {
|
||||
|
||||
let article:Article
|
||||
let container:ScriptingObjectContainer
|
||||
|
||||
init (_ article:Article, container:ScriptingObjectContainer) {
|
||||
self.article = article
|
||||
self.container = container
|
||||
}
|
||||
|
||||
@objc(objectSpecifier)
|
||||
override var objectSpecifier: NSScriptObjectSpecifier? {
|
||||
let scriptObjectSpecifier = self.container.makeFormUniqueIDScriptObjectSpecifier(forObject:self)
|
||||
return (scriptObjectSpecifier)
|
||||
}
|
||||
|
||||
// MARK: --- ScriptingObject protocol ---
|
||||
|
||||
var scriptingKey: String {
|
||||
return "articles"
|
||||
}
|
||||
|
||||
// MARK: --- UniqueIdScriptingObject protocol ---
|
||||
|
||||
// articles have id in the Evergreen database and id in the feed
|
||||
// article.uniqueID here is the feed unique id
|
||||
|
||||
var scriptingUniqueId:Any {
|
||||
return article.uniqueID
|
||||
}
|
||||
|
||||
// MARK: --- Scriptable properties ---
|
||||
|
||||
@objc(url)
|
||||
var url:String {
|
||||
return article.url ?? ""
|
||||
}
|
||||
|
||||
@objc(uniqueId)
|
||||
var uniqueId:String {
|
||||
return article.uniqueID
|
||||
}
|
||||
|
||||
@objc(title)
|
||||
var title:String {
|
||||
return article.title ?? ""
|
||||
}
|
||||
|
||||
@objc(contents)
|
||||
var contents:String {
|
||||
return article.contentText ?? ""
|
||||
}
|
||||
|
||||
@objc(html)
|
||||
var html:String {
|
||||
return article.contentHTML ?? ""
|
||||
}
|
||||
|
||||
@objc(summary)
|
||||
var summary:String {
|
||||
return article.summary ?? ""
|
||||
}
|
||||
|
||||
@objc(datePublished)
|
||||
var datePublished:Date? {
|
||||
return article.datePublished
|
||||
}
|
||||
|
||||
@objc(dateModified)
|
||||
var dateModified:Date? {
|
||||
return article.dateModified
|
||||
}
|
||||
|
||||
@objc(dateArrived)
|
||||
var dateArrived:Date {
|
||||
return article.status.dateArrived
|
||||
}
|
||||
|
||||
@objc(read)
|
||||
var read:Bool {
|
||||
return article.status.boolStatus(forKey:.read)
|
||||
}
|
||||
|
||||
@objc(starred)
|
||||
var starred:Bool {
|
||||
return article.status.boolStatus(forKey:.starred)
|
||||
}
|
||||
|
||||
@objc(deleted)
|
||||
var deleted:Bool {
|
||||
return article.status.boolStatus(forKey:.userDeleted)
|
||||
}
|
||||
|
||||
@objc(imageURL)
|
||||
var imageURL:String {
|
||||
return article.imageURL ?? ""
|
||||
}
|
||||
}
|
||||
@@ -90,5 +90,15 @@ class ScriptableFeed: NSObject, UniqueIdScriptingObject, ScriptingObjectContaine
|
||||
let feedAuthors = feed.authors ?? []
|
||||
return feedAuthors.map { ScriptableAuthor($0, container:self) } as NSArray
|
||||
}
|
||||
|
||||
@objc(articles)
|
||||
var articles:NSArray {
|
||||
let feedArticles = feed.fetchArticles()
|
||||
// the articles are a set, use the sorting algorithm from the viewer
|
||||
let sortedArticles = feedArticles.sorted(by:{
|
||||
return $0.logicalDatePublished > $1.logicalDatePublished
|
||||
})
|
||||
return sortedArticles.map { ScriptableArticle($0, container:self) } as NSArray
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import Cocoa
|
||||
import Account
|
||||
import Data
|
||||
|
||||
extension NSApplication : ScriptingObjectContainer {
|
||||
|
||||
@@ -25,6 +26,21 @@ extension NSApplication : ScriptingObjectContainer {
|
||||
return accounts.map { ScriptableAccount($0) } as NSArray
|
||||
}
|
||||
|
||||
/*
|
||||
accessing feeds from the application object skips the 'account' containment hierarchy
|
||||
this allows a script like 'articles of feed "The Shape of Everything"' as a shorthand
|
||||
for 'articles of feed "The Shape of Everything" of account "On My Mac"'
|
||||
*/
|
||||
@objc(feeds)
|
||||
func feeds() -> NSArray {
|
||||
let accounts = AccountManager.shared.accounts
|
||||
let emptyFeeds:[Feed] = []
|
||||
let feeds = accounts.reduce(emptyFeeds) { (result, nthAccount) -> [Feed] in
|
||||
let accountFeeds = nthAccount.children.flatMap { $0 as? Feed }
|
||||
return result + accountFeeds
|
||||
}
|
||||
return feeds.map { ScriptableFeed($0, container:self) } as NSArray
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user