Test Failed
Push — main ( 402e53...4169bc )
by Ehsan
03:02
created

Search.hasAlreadyReTweeted   A

Complexity

Conditions 3

Size

Total Lines 14
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 12
dl 0
loc 14
rs 9.8
c 0
b 0
f 0
1
import Twit from 'twit';
2
import Helper from '../Helper';
3
import Tweet from '../entities/Tweet';
4
import {AbstractAction, runArgs} from './Action';
5
6
interface runSearchArgs extends runArgs {
7
    searchParams: Twit.Params
8
}
9
10
export default class Search extends AbstractAction {
11
    async run(args: runSearchArgs): Promise<void> {
12
        const tweets = await this.search(args.searchParams);
13
14
        if (!Helper.objectExists(tweets) || tweets.length === 0) {
15
            this.debug('Found no tweets.');
16
            return;
17
        }
18
19
        this.debug(`Found '${tweets.length}' tweet(s).`);
20
21
        const retweetedTweets = await this.searchRetweetedTweets();
22
23
        let count = 0;
24
        for (const tweet of tweets) {
25
            count++;
26
27
            if (!tweet.isReTweetable()) {
28
                this.debug(`${count}. Tweet with id: '${tweet.rawTweet.id_str}' is not retweetable because: ${tweet.retweetError}.`);
29
                continue;
30
            }
31
32
            this.debug(`${count}. Tweet with id: '${tweet.rawTweet.id_str}' may be retweeted!`);
33
34
            if (this.hasAlreadyReTweeted(retweetedTweets, tweet)) {
35
                continue;
36
            }
37
38
            if (args.onSuccess) {
39
                args.onSuccess(tweet);
40
            }
41
        }
42
    }
43
44
    private async search(searchParams: Twit.Params): Promise<Tweet[]> {
45
        this.debug('Searching recent tweets with the following params ...');
46
        this.debug(searchParams);
47
48
        const result = await this.twit.get('search/tweets', searchParams);
49
50
        if (result.resp.statusCode === 200 && Helper.objectExists(result.data)) {
51
            this.debug('Search successfully completed!');
52
53
            const statuses = (result.data as Twit.Twitter.SearchResults).statuses;
54
55
            return this.toTweets(statuses);
56
        } else {
57
            this.debug('Cannot search recent tweets.');
58
            if (Helper.objectExists(result.resp.statusMessage)) {
59
                this.debug(result.resp.statusMessage);
60
            }
61
62
            throw new Error('Cannot search recent tweets');
63
        }
64
    }
65
66
    private async searchRetweetedTweets(): Promise<Tweet[]> {
67
        this.debug(`Searching recent retweets by user: '${this.config.screenName}' ...`);
68
69
        const result = await this.twit.get('statuses/user_timeline', {
70
            screen_name: this.config.screenName,
71
            // max allowed is 200
72
            count: 200,
73
            exclude_replies: true,
74
            include_rts: true
75
        });
76
77
        if (result.resp.statusCode === 200 && Helper.objectExists(result.data)) {
78
            const recentTweets = result.data as Twit.Twitter.Status[];
79
80
            const retweets = this.toTweets(recentTweets, true);
81
            this.debug(`Found '${retweets.length}' retweet(s).`);
82
83
            return retweets;
84
        } else {
85
            this.debug('Cannot search recent retweets.');
86
            if (Helper.objectExists(result.resp.statusMessage)) {
87
                this.debug(result.resp.statusMessage);
88
            }
89
90
            throw new Error('Cannot search recent retweets');
91
        }
92
    }
93
94
    private hasAlreadyReTweeted(retweetedTweets: Tweet[], tweet: Tweet): boolean {
95
        this.debug(`Checking to see if tweet with id: '${tweet.rawTweet.id_str}' has been already retweeted ...`);
96
97
        for (const recentTweet of retweetedTweets) {
98
            if (recentTweet.rawTweet.retweeted_status && recentTweet.rawTweet.retweeted_status.id_str === tweet.rawTweet.id_str) {
99
                this.debug(`Tweet with id: '${tweet.rawTweet.id_str}' has been already tweeted.`);
100
                return true;
101
            }
102
        }
103
104
        this.debug(`Tweet with id: '${tweet.rawTweet.id_str}' has NOT been tweeted.`);
105
106
        return false;
107
    }
108
109
    private toTweets(statuses: Twit.Twitter.Status[], onlyRetweets = false): Tweet[] {
110
        const tweets: Tweet[] = [];
111
112
        let tweet: Tweet;
113
        for (const status of statuses) {
114
            tweet = new Tweet(status, this.config.tweetConfig);
115
116
            if (onlyRetweets && !tweet.isRetweet()) {
117
                continue;
118
            }
119
120
            tweets.push(tweet);
121
        }
122
123
        return tweets;
124
    }
125
}