bibliogram/src/lib/structures/Timeline.js

105 lines
3.1 KiB
JavaScript
Raw Permalink Normal View History

2020-02-18 00:39:20 +00:00
const {Feed} = require("feed")
2020-01-12 12:50:21 +00:00
const constants = require("../constants")
const db = require("../db")
const TimelineEntry = require("./TimelineEntry")
2020-01-18 15:38:14 +00:00
const InstaCache = require("../cache")
2020-01-12 12:50:21 +00:00
const collectors = require("../collectors")
2020-04-22 11:59:45 +00:00
const {getFeedSetup} = require("../utils/feed")
require("../testimports")(constants, collectors, TimelineEntry, InstaCache)
2020-01-12 12:50:21 +00:00
2020-01-14 14:38:33 +00:00
/** @param {any[]} edges */
2020-01-12 12:50:21 +00:00
function transformEdges(edges) {
return edges.map(e => {
/** @type {import("../types").TimelineEntryAll} */
const data = e.node
const entry = collectors.getOrCreateShortcode(data.shortcode)
entry.apply(data)
return entry
})
2020-01-12 12:50:21 +00:00
}
class Timeline {
/**
2020-02-02 13:24:14 +00:00
* @param {import("./User")|import("./ReelUser")} user
2020-06-24 14:58:01 +00:00
* @param {string} type
2020-01-12 12:50:21 +00:00
*/
2020-06-24 14:58:01 +00:00
constructor(user, type) {
2020-01-12 12:50:21 +00:00
this.user = user
2020-06-24 14:58:01 +00:00
/** one of: "timeline", "igtv" */
this.type = type
/** @type {import("./TimelineEntry")[][]} */
2020-01-12 12:50:21 +00:00
this.pages = []
2021-01-18 13:23:25 +00:00
this.entryCount = 0
if (this.type === "timeline") {
if (this.user.data.edge_owner_to_timeline_media) {
this.addPage(this.user.data.edge_owner_to_timeline_media)
}
} else if (this.type === "igtv") {
if (this.user.data.edge_felix_video_timeline) {
this.addPage(this.user.data.edge_felix_video_timeline)
}
2020-02-02 13:24:14 +00:00
}
2020-01-12 12:50:21 +00:00
}
hasNextPage() {
2020-06-24 14:58:01 +00:00
return !this.page_info || this.page_info.has_next_page
2020-01-12 12:50:21 +00:00
}
fetchNextPage() {
if (!this.hasNextPage()) return constants.symbols.NO_MORE_PAGES
2020-06-24 14:58:01 +00:00
const method =
this.type === "timeline" ? collectors.fetchTimelinePage
: this.type === "igtv" ? collectors.fetchIGTVPage
: null
const after = this.page_info ? this.page_info.end_cursor : ""
2020-07-22 12:58:21 +00:00
return method(this.user.data.id, after).then(({result: page, fromCache}) => {
const quotaUsed = fromCache ? 0 : 1
2020-01-12 12:50:21 +00:00
this.addPage(page)
2020-07-22 12:58:21 +00:00
return {page: this.pages.slice(-1)[0], quotaUsed}
2020-01-12 12:50:21 +00:00
})
}
async fetchUpToPage(index) {
2020-07-22 12:58:21 +00:00
let quotaUsed = 0
2020-01-12 12:50:21 +00:00
while (this.pages[index] === undefined && this.hasNextPage()) {
2020-07-22 12:58:21 +00:00
const result = await this.fetchNextPage()
if (typeof result !== "symbol") {
quotaUsed += result.quotaUsed
}
2020-01-12 12:50:21 +00:00
}
2020-07-22 12:58:21 +00:00
return quotaUsed
2020-01-12 12:50:21 +00:00
}
addPage(page) {
// update whether the user should be private
if (this.pages.length === 0 && page.count > 0) { // this is the first page, and user has posted
const shouldBePrivate = page.edges.length === 0
if (shouldBePrivate !== this.user.data.is_private) {
db.prepare("UPDATE Users SET is_private = ? WHERE user_id = ?").run(+shouldBePrivate, this.user.data.id)
this.user.data.is_private = shouldBePrivate
}
}
// add the page
2020-01-12 12:50:21 +00:00
this.pages.push(transformEdges(page.edges))
this.page_info = page.page_info
2021-01-18 13:23:25 +00:00
// update self post count
this.entryCount = page.count
// update user post count
if (this.type === "timeline") {
this.user.posts = page.count
}
2020-01-12 12:50:21 +00:00
}
2020-01-14 14:38:33 +00:00
2020-01-26 15:15:53 +00:00
async fetchFeed() {
2020-04-22 11:59:45 +00:00
const setup = getFeedSetup(this.user.data.username, this.user.data.biography, constants.website_origin+this.user.proxyProfilePicture, new Date(this.user.cachedAt))
const feed = new Feed(setup)
2020-01-14 14:38:33 +00:00
const page = this.pages[0] // only get posts from first page
2020-01-26 15:15:53 +00:00
await Promise.all(page.map(item =>
2020-02-18 00:39:20 +00:00
item.fetchFeedData().then(feedData => feed.addItem(feedData))
2020-01-26 15:15:53 +00:00
))
2020-01-14 14:38:33 +00:00
return feed
}
2020-01-12 12:50:21 +00:00
}
module.exports = Timeline