-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
160 lines (143 loc) · 4.96 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
'use strict';
const snoowrap = require('snoowrap');
const Twit = require('twit');
const imgur = require('imgur');
const debug = true;
const blacklist = ['canarybot', 'TweetsInCommentsBot', 'TweetPoster'];
function body(name, url, text, images) {
var ret =
`[**${name}**](${url})
>${text}
`
if (images) ret +=
`>[[Imgur rehost]](${images})
`;
ret +=
`----
`;
return ret;
}
function footer() {
return `Beep boop I am a bot`;
}
// Set up accounts
// Reddit interaction
const snoo = new snoowrap({
user_agent: process.env.USER_AGENT,
client_id: process.env.SNOO_ID,
client_secret: process.env.SNOO_SECRET,
refresh_token: process.env.SNOO_REFRESH,
});
// Twitter interaction
const twit = new Twit({
consumer_key: process.env.TWIT_ID,
consumer_secret: process.env.TWIT_SECRET,
access_token: process.env.TWIT_AT,
access_token_secret: process.env.TWIT_ATS,
timeout_ms: 60*1000,
});
// Imgur interaction
imgur.setClientId(process.env.IMGUR_ID);
if(debug) console.log('Initialized accounts');
// Create treated comment registry
var cache = {};
// TODO: delete all cached entries older than x minutes (hours?)
console.time('Treat new comments');
// TODO: wrap this in setInterval
// Fetch all new comments in subreddit
var s = snoo.get_new_comments('test')
// Extract twitter links
.map(comment => {
//if(debug) console.log('Parsing '+comment.id);
comment.twitter_urls = comment.body.match(/https:\/\/twitter\.com\/(\w+)\/status*\/(\d+)/g);
return comment;
})
// Filter out comments without twitter links, those we already treated and the blacklist
.filter(comment => {
if (comment.twitter_urls
&& !cache[comment.id]
&& blacklist.indexOf(comment.author.name) != -1) {
if(debug) console.log('Adding comment '+comment.id+' to cache');
cache[comment.id] = new Date();
return true;
} else {
return false;
}
})
// Fetch tweet info
.map(comment => {
if(debug) console.log(comment.twitter_urls);
// Extract status ids from URLs
let tweets = comment.twitter_urls.map(url => {return url.substring(url.lastIndexOf('/')+1);});
// Add promise for tweets to comment
return (
tweets.length>1
? twit.get('statuses/lookup', {id: tweets.join(',')}).then(tweet=>tweet.data)
: twit.get('statuses/show/:id', {id: tweets[0]}).then(tweet=>[tweet.data])
)
.then(tweets=>{
comment.tweets = tweets;
return comment;
});
})
// Extract image url's, users and text from tweets
.map(comment => {
comment.tweets = comment.tweets.map(tweet => {
var ret = {
user : tweet.user.screen_name,
user_url : 'https://twitter.com/'+tweet.user.screen_name,
text : tweet.text
};
// Extract image urls; for videos/gifs, take thumbnail
var pictures = tweet.entities.media;
if (pictures) ret.pictures = pictures
.filter(media => media.type=='photo')
.map(photo => photo.media_url_https+':large');
// Replace all user mentions with links
var users = tweet.entities.user_mentions;
users.forEach(user => ret.text = ret.text.replace(new RegExp('@'+user.screen_name, 'g'), '[@'+user.screen_name+'](https://twitter.com/'+user.screen_name+')'));
// Replace all hashtags
var hashtags = tweet.entities.hashtags;
hashtags.forEach(hashtag => ret.text = ret.text.replace(new RegExp('#'+hashtag, 'g'), '[#'+hashtag+'](https://twitter.com/search?q=%23'+hashtag+')'));
// Replace all links with fully resolved ones
var urls = tweet.entities.urls;
urls.forEach(url => ret.text = ret.text.replace(new RegExp(url.url, 'g'), '['+url.display_url+']('+url.expanded_url+')'));
return ret;
});
if(debug) console.log(comment.tweets);
return comment;
})
// Rehost images on imgur
.map(comment => {
return Promise.all(
// Map tweets on promises of tweets
comment.tweets.map(tweet=>{
if (!tweet.pictures) return tweet;
// Create album, returns promise of tweet
return imgur.createAlbum()
// Save URL and hash
.then(json=>{tweet.album = 'http://imgur.com/a/'+json.data.id; return json.data.deletehash;})
// Upload images
.then(hash => imgur.uploadImages(tweet.pictures, 'Url', hash))
// Return tweet
.then(album => tweet);
})
)
.then(tweets=>{
if(debug) console.log('Rehosted images');
comment.tweets = tweets;
return comment;
});
})
// Post reply to reddit
.each(comment=> {
let reply = comment.tweets.map(tweet=>{
return body(tweet.user,
tweet.user_url,
tweet.text,
tweet.album);
}).join('') + footer();
if(debug) console.log(reply);
comment.reply(reply);
})
.then(comments=>{console.timeEnd('Treat new comments');});