mirror of https://github.com/oxen-io/session-ios
Refactor
parent
b61b440063
commit
e21cced9bb
@ -0,0 +1,70 @@
|
|||||||
|
import FeedKit
|
||||||
|
|
||||||
|
@objc(LKRSSFeedPoller)
|
||||||
|
public final class LokiRSSFeedPoller : NSObject {
|
||||||
|
private let feed: LokiRSSFeed
|
||||||
|
private var timer: Timer? = nil
|
||||||
|
private var hasStarted = false
|
||||||
|
|
||||||
|
private let interval: TimeInterval = 8 * 60
|
||||||
|
|
||||||
|
@objc(initForFeed:)
|
||||||
|
public init(for feed: LokiRSSFeed) {
|
||||||
|
self.feed = feed
|
||||||
|
super.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc public func startIfNeeded() {
|
||||||
|
if hasStarted { return }
|
||||||
|
timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { [weak self] _ in self?.poll() }
|
||||||
|
poll() // Perform initial update
|
||||||
|
hasStarted = true
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc public func stop() {
|
||||||
|
timer?.invalidate()
|
||||||
|
hasStarted = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private func poll() {
|
||||||
|
let feed = self.feed
|
||||||
|
let url = URL(string: feed.server)!
|
||||||
|
FeedParser(URL: url).parseAsync { wrapper in
|
||||||
|
guard case .rss(let x) = wrapper, let items = x.items else { return print("[Loki] Failed to parse RSS feed for: \(feed.server).") }
|
||||||
|
items.reversed().forEach { item in
|
||||||
|
guard let title = item.title, let description = item.description, let date = item.pubDate else { return }
|
||||||
|
let timestamp = UInt64(date.timeIntervalSince1970 * 1000)
|
||||||
|
let urlRegex = try! NSRegularExpression(pattern: "<a\\s+(?:[^>]*?\\s+)?href=\"([^\"]*)\".*?>(.*?)<.*?\\/a>")
|
||||||
|
var bodyAsHTML = "\(title)<br>\(description)"
|
||||||
|
while true {
|
||||||
|
guard let match = urlRegex.firstMatch(in: bodyAsHTML, options: [], range: NSRange(location: 0, length: bodyAsHTML.utf16.count)) else { break }
|
||||||
|
let matchRange = match.range(at: 0)
|
||||||
|
let urlRange = match.range(at: 1)
|
||||||
|
let descriptionRange = match.range(at: 2)
|
||||||
|
let url = (bodyAsHTML as NSString).substring(with: urlRange)
|
||||||
|
let description = (bodyAsHTML as NSString).substring(with: descriptionRange)
|
||||||
|
bodyAsHTML = (bodyAsHTML as NSString).replacingCharacters(in: matchRange, with: "\(description) (\(url))") as String
|
||||||
|
}
|
||||||
|
guard let bodyAsData = bodyAsHTML.data(using: String.Encoding.unicode) else { return }
|
||||||
|
let options = [ NSAttributedString.DocumentReadingOptionKey.documentType : NSAttributedString.DocumentType.html ]
|
||||||
|
guard let body = try? NSAttributedString(data: bodyAsData, options: options, documentAttributes: nil).string else { return }
|
||||||
|
let id = feed.id.data(using: String.Encoding.utf8)!
|
||||||
|
let x1 = SSKProtoGroupContext.builder(id: id, type: .deliver)
|
||||||
|
x1.setName(feed.displayName)
|
||||||
|
let x2 = SSKProtoDataMessage.builder()
|
||||||
|
x2.setTimestamp(timestamp)
|
||||||
|
x2.setGroup(try! x1.build())
|
||||||
|
x2.setBody(body)
|
||||||
|
let x3 = SSKProtoContent.builder()
|
||||||
|
x3.setDataMessage(try! x2.build())
|
||||||
|
let x4 = SSKProtoEnvelope.builder(type: .ciphertext, timestamp: timestamp)
|
||||||
|
x4.setSource(NSLocalizedString("Loki", comment: ""))
|
||||||
|
x4.setSourceDevice(OWSDevicePrimaryDeviceId)
|
||||||
|
x4.setContent(try! x3.build().serializedData())
|
||||||
|
OWSPrimaryStorage.shared().dbReadWriteConnection.readWrite { transaction in
|
||||||
|
SSKEnvironment.shared.messageManager.throws_processEnvelope(try! x4.build(), plaintextData: try! x3.build().serializedData(), wasReceivedByUD: false, transaction: transaction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,48 +1,19 @@
|
|||||||
|
|
||||||
@objc(LKGroupChat)
|
@objc(LKGroupChat)
|
||||||
public final class LokiGroupChat : NSObject {
|
public final class LokiGroupChat : NSObject {
|
||||||
public let kind: Kind
|
@objc public let id: String
|
||||||
|
@objc public let serverID: UInt
|
||||||
@objc public let server: String
|
@objc public let server: String
|
||||||
@objc public let displayName: String
|
@objc public let displayName: String
|
||||||
@objc public let isDeletable: Bool
|
@objc public let isDeletable: Bool
|
||||||
|
|
||||||
@objc public var id: String {
|
@objc public init(serverID: UInt, server: String, displayName: String, isDeletable: Bool) {
|
||||||
switch kind {
|
self.id = "\(server).\(serverID)"
|
||||||
case .publicChat(let id): return "\(server).\(id)"
|
self.serverID = serverID
|
||||||
case .rss(let customID): return "rss://\(customID)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Convenience
|
|
||||||
@objc public var isPublicChat: Bool {
|
|
||||||
if case .publicChat(_) = kind { return true } else { return false }
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc public var isRSS: Bool {
|
|
||||||
if case .rss(_) = kind { return true } else { return false }
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Kind
|
|
||||||
public enum Kind { case publicChat(id: UInt), rss(customID: String) }
|
|
||||||
|
|
||||||
// MARK: Initialization
|
|
||||||
public init(kind: Kind, server: String, displayName: String, isDeletable: Bool) {
|
|
||||||
self.kind = kind
|
|
||||||
self.server = server
|
self.server = server
|
||||||
self.displayName = displayName
|
self.displayName = displayName
|
||||||
self.isDeletable = isDeletable
|
self.isDeletable = isDeletable
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc public convenience init(kindAsString: String, id: String, server: String, displayName: String, isDeletable: Bool) {
|
override public var description: String { return displayName }
|
||||||
let kind: Kind
|
|
||||||
switch kindAsString {
|
|
||||||
case "publicChat": kind = .publicChat(id: UInt(id)!)
|
|
||||||
case "rss": kind = .rss(customID: id)
|
|
||||||
default: preconditionFailure()
|
|
||||||
}
|
|
||||||
self.init(kind: kind, server: server, displayName: displayName, isDeletable: isDeletable)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Description
|
|
||||||
override public var description: String { return "\(id) (\(displayName))" }
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
@objc(LKRSSFeed)
|
||||||
|
public final class LokiRSSFeed : NSObject {
|
||||||
|
@objc public let id: String
|
||||||
|
@objc public let server: String
|
||||||
|
@objc public let displayName: String
|
||||||
|
@objc public let isDeletable: Bool
|
||||||
|
|
||||||
|
@objc public init(id: String, server: String, displayName: String, isDeletable: Bool) {
|
||||||
|
self.id = id
|
||||||
|
self.server = server
|
||||||
|
self.displayName = displayName
|
||||||
|
self.isDeletable = isDeletable
|
||||||
|
}
|
||||||
|
|
||||||
|
override public var description: String { return displayName }
|
||||||
|
}
|
Loading…
Reference in New Issue