123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- import { Injectable } from "@angular/core";
- import { TwitterApiProvider } from "../twitter-api/twitter-api";
- import { P2pDatabaseGunProvider } from "../p2p-database-gun/p2p-database-gun";
- import { P2pStorageIpfsProvider } from "../p2p-storage-ipfs/p2p-storage-ipfs";
- @Injectable()
- export class FeedProvider {
- friends;
- constructor(
- private twitter: TwitterApiProvider,
- private gun: P2pDatabaseGunProvider,
- private ipfs: P2pStorageIpfsProvider
- ) {}
- public async loadUserTimeline(
- userId,
- oldestPublicTweet?,
- oldestPrivateTweet?
- ) {
- const maxId = oldestPublicTweet ? oldestPublicTweet["id_str"] : undefined;
- // Fetch tweets from Twitter
- let tweets = await this.twitter.fetchUserTimeline(userId, maxId);
- tweets = tweets.filter(tweet => tweet.id_str != maxId);
- // Determine start and end of time interval to look for private tweets
- const intervalStart: Date = oldestPrivateTweet
- ? new Date(oldestPrivateTweet["created_at"])
- : new Date();
- const intervalEnd: Date = this.getOldestTweetTimestamp(tweets);
- // Fetch private tweet hashs from P2P DB for corresponding interval
- const privateTweetHashs: string[] = await this.gun.fetchPrivateTweetHashsForUserInInterval(
- userId,
- intervalStart,
- intervalEnd
- );
- if (privateTweetHashs.length) {
- const privateTweets = await this.fetchPrivateTweets(privateTweetHashs);
- // Combine and sort tweets
- return tweets
- .concat(privateTweets)
- .sort((a, b) => this.sortByDateAsc(a, b));
- } else {
- return tweets;
- }
- }
- public async loadHomeTimeline(
- userId,
- oldestPublicTweet?,
- oldestPrivateTweet?
- ) {
- // Fetch tweets from Twitter
- const maxId = oldestPublicTweet ? oldestPublicTweet["id_str"] : undefined;
- let tweets = await this.twitter.fetchHomeFeed(maxId);
- tweets = tweets.filter(tweet => tweet.id_str != maxId);
- // Determine start and end of time interval to look for private tweets
- const intervalStart: Date = oldestPrivateTweet
- ? new Date(oldestPrivateTweet["created_at"])
- : new Date();
- const intervalEnd: Date = this.getOldestTweetTimestamp(tweets);
- // Fetch user's friends
- const friends = await this.getCachedFriends(userId);
- let privateTweetHashs = [];
- friends.forEach(async friend => {
- privateTweetHashs = privateTweetHashs.concat(
- await this.gun.fetchPrivateTweetHashsForUserInInterval(
- friend.id_str,
- intervalStart,
- intervalEnd
- )
- );
- });
- // Add users private tweets
- privateTweetHashs = privateTweetHashs.concat(
- await this.gun.fetchPrivateTweetHashsForUserInInterval(
- userId,
- intervalStart,
- intervalEnd
- )
- );
- if (privateTweetHashs.length) {
- const privateTweets = await this.fetchPrivateTweets(privateTweetHashs);
- // Combine and sort tweets
- return tweets
- .concat(privateTweets)
- .sort((a, b) => this.sortByDateAsc(a, b));
- } else {
- return tweets;
- }
- }
- private async fetchPrivateTweets(privateTweetHashs) {
- // Load private tweets from P2P storage
- const privateTweets = await this.ipfs.fetchTweets(privateTweetHashs);
- // Add user object to private tweets
- return await Promise.all(
- privateTweets.map(async tweet => await this.addUserToTweet(tweet))
- );
- }
- private async addUserToTweet(tweet) {
- tweet.user = await this.twitter.fetchUser(tweet.user_id);
- return tweet;
- }
- private getOldestTweetTimestamp(tweets): Date {
- if (tweets.length < 15) {
- // End of timeline is reached - load all private tweets
- return new Date("2018-04-01T00:00:00");
- } else {
- const lastTweetTimestamp = tweets[tweets.length - 1].created_at;
- return new Date(lastTweetTimestamp);
- }
- }
- private sortByDateAsc(a, b) {
- const dateA = new Date(a.created_at);
- const dateB = new Date(b.created_at);
- if (dateA > dateB) {
- return -1;
- } else if (dateA < dateB) {
- return 1;
- } else {
- return 0;
- }
- }
- private async getCachedFriends(userId) {
- // Cache friends for 15 minutes to avoid unnecessary API calls
- if (!this.friends || (Date.now() - this.friends.lastUpdate) / 900000 > 15) {
- this.friends = {
- friendList: await this.twitter.fetchFriends(userId),
- lastUpdate: Date.now()
- };
- }
- return this.friends.friendList;
- }
- }
|