├── .eslintrc.json
├── .gitignore
├── README.md
├── app.js
├── censored-phrases.json
├── keys-example.json
├── lib
├── censor.js
├── get-reply-text.js
├── get-tweet.js
├── read-alt-text.js
└── send-tweet.js
├── package-lock.json
├── package.json
├── test-tweets.json
└── test
├── censor.js
└── get-reply-text.js
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "commonjs": true,
5 | "es2021": true
6 | },
7 | "extends": [
8 | "plugin:node/recommended",
9 | "eslint:recommended"
10 | ],
11 | "rules": {
12 | // allow import/require of local, unpublished modules
13 | "node/no-unpublished-require": "off"
14 | },
15 | "parserOptions": {
16 | "ecmaVersion": "latest"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | keys.json
2 | *.swp
3 | .DS_Store
4 | node_modules
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | @get_altText is a twitter bot that tweets image descriptions when mentioned in a tweet or a reply to a tweet containing media.
2 | For more information, see twitter.com/get_altText
3 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | const TwitterP = require('twitter')
2 | const keys = require('./keys')
3 | const sendTweet = require('./lib/send-tweet')
4 | const getReplyText = require('./lib/get-reply-text')
5 | const getTweet = require('./lib/get-tweet')
6 |
7 | const Twitter = new TwitterP(keys)
8 |
9 | Twitter.stream('statuses/filter', { track: '@get_altText' }, function (stream) {
10 | stream.on('data', (brokenTweet) => {
11 | const mentioningTweetId = brokenTweet.id_str
12 | const mentioningUsername = brokenTweet.user.screen_name
13 |
14 | getTweet(mentioningTweetId)
15 | .then(getReplyText)
16 | .then((reply) => {
17 | if (reply && reply.length > 0) {
18 | sendTweet(reply, mentioningTweetId, mentioningUsername)
19 | }
20 | })
21 | .catch((err) => console.error(err))
22 |
23 | stream.on('error', (err) => {
24 | console.log(err)
25 | })
26 | })
27 |
28 | stream.on('error', (err) => {
29 | console.log(err)
30 | })
31 | })
32 |
--------------------------------------------------------------------------------
/censored-phrases.json:
--------------------------------------------------------------------------------
1 | ["kill", "die", "rape"]
2 |
--------------------------------------------------------------------------------
/keys-example.json:
--------------------------------------------------------------------------------
1 | {
2 | "consumer_key": "CONSUMER_KEY",
3 | "consumer_secret": "CONSUMER_SECRET",
4 | "access_token_key": "ACCESS_TOKEN_KEY",
5 | "access_token_secret": "ACCESS_TOKEN_SECRET"
6 | }
--------------------------------------------------------------------------------
/lib/censor.js:
--------------------------------------------------------------------------------
1 | const censoredPhrases = require('../censored-phrases.json')
2 |
3 | module.exports = (text) => {
4 | let isCensored = false
5 |
6 | censoredPhrases.forEach((phrase) => {
7 | const regex = new RegExp(`\\b${phrase}\\b`, 'g')
8 | const censoredVersion = phrase.replace(/a|e|i|o|u/, '*')
9 |
10 | if (!isCensored) {
11 | isCensored = regex.test(text)
12 | }
13 |
14 | text = text.replace(regex, censoredVersion)
15 | })
16 |
17 | if (isCensored) {
18 | text +=
19 | "\n\n(Note from the bot: I had to censor a part of the description to avoid suspension from twitter, I'm sorry.)"
20 | }
21 |
22 | return text
23 | }
24 |
--------------------------------------------------------------------------------
/lib/get-reply-text.js:
--------------------------------------------------------------------------------
1 | const getTweet = require('./get-tweet')
2 | const readAltText = require('./read-alt-text')
3 |
4 | module.exports = async (tweet) => {
5 | const mentioningTweetId = tweet.id_str
6 | const mentioningUsername = tweet.user.screen_name
7 |
8 | let content = `@${mentioningUsername} `
9 |
10 | try {
11 | if (!tweet) {
12 | console.log('🚨This should not happen🚨')
13 | throw 'No tweet found'
14 | }
15 |
16 | // do not reply to retweets
17 | if (typeof tweet.retweeted_status !== 'undefined') {
18 | return
19 | }
20 |
21 | let originalTweetId = tweet.in_reply_to_status_id_str
22 | let originalUsername = tweet.in_reply_to_screen_name
23 |
24 | // ppl posting the pic and triggering the bot within the same tweet
25 | if (originalTweetId == null) {
26 | originalTweetId = mentioningTweetId
27 | originalUsername = mentioningUsername
28 | }
29 |
30 | // pls no loops of death!
31 | if (mentioningUsername == 'get_altText') {
32 | return
33 | }
34 |
35 | const originalTweet = await getTweet(originalTweetId)
36 |
37 | // media in the original tweet
38 | if (
39 | originalTweet.extended_entities &&
40 | originalTweet.extended_entities.media
41 | ) {
42 | content += readAltText(originalTweet, originalUsername)
43 | return content
44 | }
45 |
46 | // media in the triggering tweet
47 | if (tweet.extended_entities && tweet.extended_entities.media) {
48 | content += readAltText(tweet, mentioningUsername)
49 | return content
50 | }
51 |
52 | // in the quoted tweet?
53 | if (tweet.is_quote_status) {
54 | const quotedTweet = await getTweet(tweet.quoted_status_id_str)
55 | // media in the quoted tweet
56 | if (
57 | quotedTweet.extended_entities &&
58 | quotedTweet.extended_entities.media
59 | ) {
60 | content += readAltText(quotedTweet, quotedTweet.user.screen_name)
61 | return content
62 | } else {
63 | // no media in quoted tweet => no tweet
64 | return
65 | }
66 | }
67 |
68 | return
69 | } catch (err) {
70 | console.log(JSON.stringify(err))
71 | if (err.length === 1) {
72 | return content + err[0].message.replace('you are', 'I am')
73 | } else {
74 | return (
75 | content +
76 | 'There has been an error while trying to read the alt text, please try again later – @malfynnction, you should probably look into this!'
77 | )
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/lib/get-tweet.js:
--------------------------------------------------------------------------------
1 | const TwitterP = require('twitter')
2 | const keys = require('../keys')
3 |
4 | const Twitter = new TwitterP(keys)
5 |
6 | module.exports = async (id) => {
7 | return Twitter.get('statuses/show', {
8 | id: id,
9 | include_ext_alt_text: 'true',
10 | tweet_mode: 'extended',
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/lib/read-alt-text.js:
--------------------------------------------------------------------------------
1 | const censor = require('./censor')
2 |
3 | const altForMedium = (medium) =>
4 | medium.ext_alt_text === null
5 | ? "There is no alt text for this image, I'm sorry."
6 | : censor(medium.ext_alt_text)
7 |
8 | module.exports = (tweet) => {
9 | const media = tweet.extended_entities.media
10 |
11 | // unfortunately, it is impossible to add alt texts to videos
12 | const supportedMediaTypes = ['photo', 'animated_gif']
13 | const mediaType = media[0].type
14 |
15 | if (!supportedMediaTypes.includes(mediaType)) {
16 | return `This is a ${mediaType}. Unfortunately, twitter doesn't allow to add alt texts for ${mediaType}s yet.`
17 | } else if (media.length === 1) {
18 | return altForMedium(media[0])
19 | } else {
20 | return media.reduce(
21 | (alt, medium, i) => alt + `${i + 1}. Picture: ${altForMedium(medium)}\n`,
22 | ''
23 | )
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/send-tweet.js:
--------------------------------------------------------------------------------
1 | const TwitterP = require('twitter')
2 | const keys = require('../keys')
3 |
4 | const Twitter = new TwitterP(keys)
5 |
6 | const tweetThis = (content, inReplyToTweetId, mentioningUsername) => {
7 | if (content.length <= 280) {
8 | const reply = { status: content, in_reply_to_status_id: inReplyToTweetId }
9 | Twitter.post('statuses/update', reply, (err) => {
10 | if (err) {
11 | console.log(err)
12 | }
13 | })
14 | } else {
15 | const contentWords = content.split(' ')
16 | let part = ''
17 |
18 | while (
19 | contentWords.length > 0 &&
20 | part.length + contentWords[0].length <= 279
21 | ) {
22 | part += contentWords[0] + ' '
23 | contentWords.splice(0, 1)
24 | }
25 |
26 | const reply = { status: part, in_reply_to_status_id: inReplyToTweetId }
27 | Twitter.post('statuses/update', reply, function (err, tweet) {
28 | if (err) {
29 | console.log(err)
30 | } else {
31 | tweetThis(
32 | `@${mentioningUsername} ${contentWords.join(' ')}`,
33 | tweet.id_str,
34 | mentioningUsername
35 | )
36 | }
37 | })
38 | }
39 | }
40 |
41 | module.exports = tweetThis
42 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "get_alttext",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "app.js",
6 | "dependencies": {
7 | "twitter": "^1.7.1"
8 | },
9 | "devDependencies": {
10 | "ava": "^3.12.1",
11 | "eslint": "^8.9.0",
12 | "eslint-plugin-node": "^11.1.0"
13 | },
14 | "scripts": {
15 | "test": "ava",
16 | "lint": "eslint '*.js'"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/malfynnction/AltText-Tweeter.git"
21 | },
22 | "author": "",
23 | "license": "ISC",
24 | "bugs": {
25 | "url": "https://github.com/malfynnction/AltText-Tweeter/issues"
26 | },
27 | "homepage": "https://github.com/malfynnction/AltText-Tweeter#readme",
28 | "ava": {
29 | "files": [
30 | "test/**/*"
31 | ]
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/test-tweets.json:
--------------------------------------------------------------------------------
1 | {
2 | "1": {
3 | "created_at": "Wed Sep 12 15:57:03 +0000 2018",
4 | "id": 1039905741245689900,
5 | "id_str": "1039905741245689857",
6 | "full_text": "@get_altText",
7 | "truncated": false,
8 | "display_text_range": [0, 12],
9 | "entities": {
10 | "hashtags": [],
11 | "symbols": [],
12 | "user_mentions": [
13 | {
14 | "screen_name": "get_altText",
15 | "name": "Alt Text Reader",
16 | "id": 968802481856794600,
17 | "id_str": "968802481856794624",
18 | "indices": [0, 12]
19 | }
20 | ],
21 | "urls": []
22 | },
23 | "source": "Twitter for iPhone",
24 | "in_reply_to_status_id": 1039905540514701300,
25 | "in_reply_to_status_id_str": "1039905540514701312",
26 | "in_reply_to_user_id": 2977720848,
27 | "in_reply_to_user_id_str": "2977720848",
28 | "in_reply_to_screen_name": "SnoringDoggo",
29 | "user": {
30 | "id": 2977720848,
31 | "id_str": "2977720848",
32 | "name": "Noor (He) 💗☪️♿️",
33 | "screen_name": "SnoringDoggo",
34 | "location": "npervez@autisticadvocacy.org",
35 | "description": "Community Engagement Coordinator for ASAN, Accessibility Director @masjidalrabia, board @transstudent, MyLC @AdvocatesTweets, PLEASE LET ME PAT YOUR🐕",
36 | "url": "https://t.co/rxAM9J4tcI",
37 | "entities": {
38 | "url": {
39 | "urls": [
40 | {
41 | "url": "https://t.co/rxAM9J4tcI",
42 | "expanded_url": "https://paypal.me/NPervez",
43 | "display_url": "paypal.me/NPervez",
44 | "indices": [0, 23]
45 | }
46 | ]
47 | },
48 | "description": { "urls": [] }
49 | },
50 | "protected": false,
51 | "followers_count": 1576,
52 | "friends_count": 705,
53 | "listed_count": 24,
54 | "created_at": "Mon Jan 12 22:09:30 +0000 2015",
55 | "favourites_count": 30355,
56 | "utc_offset": null,
57 | "time_zone": null,
58 | "geo_enabled": false,
59 | "verified": false,
60 | "statuses_count": 23681,
61 | "lang": "en",
62 | "contributors_enabled": false,
63 | "is_translator": false,
64 | "is_translation_enabled": false,
65 | "profile_background_color": "000000",
66 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
67 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
68 | "profile_background_tile": false,
69 | "profile_image_url": "http://pbs.twimg.com/profile_images/1089685874256826368/RdzHOlj5_normal.jpg",
70 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/1089685874256826368/RdzHOlj5_normal.jpg",
71 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/2977720848/1546564383",
72 | "profile_image_extensions_alt_text": null,
73 | "profile_banner_extensions_alt_text": null,
74 | "profile_link_color": "19CF86",
75 | "profile_sidebar_border_color": "000000",
76 | "profile_sidebar_fill_color": "000000",
77 | "profile_text_color": "000000",
78 | "profile_use_background_image": false,
79 | "has_extended_profile": true,
80 | "default_profile": false,
81 | "default_profile_image": false,
82 | "following": false,
83 | "follow_request_sent": false,
84 | "notifications": false,
85 | "translator_type": "none"
86 | },
87 | "geo": null,
88 | "coordinates": null,
89 | "place": null,
90 | "contributors": null,
91 | "is_quote_status": false,
92 | "retweet_count": 0,
93 | "favorite_count": 0,
94 | "favorited": false,
95 | "retweeted": false,
96 | "lang": "und"
97 | },
98 | "2": {
99 | "created_at": "Sat Mar 02 22:34:38 +0000 2019",
100 | "id": 1101974120009556000,
101 | "id_str": "1101974120009555980",
102 | "full_text": "@IAStartingLine @get_altText",
103 | "truncated": false,
104 | "display_text_range": [16, 28],
105 | "entities": {
106 | "hashtags": [],
107 | "symbols": [],
108 | "user_mentions": [
109 | {
110 | "screen_name": "IAStartingLine",
111 | "name": "Iowa Starting Line",
112 | "id": 2940964728,
113 | "id_str": "2940964728",
114 | "indices": [0, 15]
115 | },
116 | {
117 | "screen_name": "get_altText",
118 | "name": "Alt Text Reader",
119 | "id": 968802481856794600,
120 | "id_str": "968802481856794624",
121 | "indices": [16, 28]
122 | }
123 | ],
124 | "urls": []
125 | },
126 | "source": "Twitter for iPhone",
127 | "in_reply_to_status_id": 1101921103289741300,
128 | "in_reply_to_status_id_str": "1101921103289741313",
129 | "in_reply_to_user_id": 2940964728,
130 | "in_reply_to_user_id_str": "2940964728",
131 | "in_reply_to_screen_name": "IAStartingLine",
132 | "user": {
133 | "id": 3058863267,
134 | "id_str": "3058863267",
135 | "name": "Kit ♿️",
136 | "screen_name": "solitaryrainbow",
137 | "location": "United Kingdom",
138 | "description": "they/them. queer AF. disabled/autistic/ADHD. wheelchair liberated. parent of three small humans and many cats. rapidly collecting tattoos.",
139 | "url": null,
140 | "entities": { "description": { "urls": [] } },
141 | "protected": false,
142 | "followers_count": 480,
143 | "friends_count": 915,
144 | "listed_count": 7,
145 | "created_at": "Tue Feb 24 13:11:51 +0000 2015",
146 | "favourites_count": 18772,
147 | "utc_offset": null,
148 | "time_zone": null,
149 | "geo_enabled": true,
150 | "verified": false,
151 | "statuses_count": 6053,
152 | "lang": "en",
153 | "contributors_enabled": false,
154 | "is_translator": false,
155 | "is_translation_enabled": false,
156 | "profile_background_color": "000000",
157 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
158 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
159 | "profile_background_tile": false,
160 | "profile_image_url": "http://pbs.twimg.com/profile_images/967836568349216769/8ujyFi8K_normal.jpg",
161 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/967836568349216769/8ujyFi8K_normal.jpg",
162 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/3058863267/1447185535",
163 | "profile_image_extensions_alt_text": null,
164 | "profile_banner_extensions_alt_text": null,
165 | "profile_link_color": "981CEB",
166 | "profile_sidebar_border_color": "000000",
167 | "profile_sidebar_fill_color": "000000",
168 | "profile_text_color": "000000",
169 | "profile_use_background_image": false,
170 | "has_extended_profile": false,
171 | "default_profile": false,
172 | "default_profile_image": false,
173 | "following": false,
174 | "follow_request_sent": false,
175 | "notifications": false,
176 | "translator_type": "none"
177 | },
178 | "geo": null,
179 | "coordinates": null,
180 | "place": null,
181 | "contributors": null,
182 | "is_quote_status": false,
183 | "retweet_count": 0,
184 | "favorite_count": 0,
185 | "favorited": false,
186 | "retweeted": false,
187 | "lang": "und"
188 | },
189 | "3": {
190 | "created_at": "Sat Sep 29 08:37:11 +0000 2018",
191 | "id": 1045955638898167800,
192 | "id_str": "1045955638898167808",
193 | "full_text": "Award-winning, Indian botanical illustrator Hemlata Pradhan #womensart https://t.co/IV7WmrdVJ8",
194 | "truncated": false,
195 | "display_text_range": [0, 70],
196 | "entities": {
197 | "hashtags": [{ "text": "womensart", "indices": [60, 70] }],
198 | "symbols": [],
199 | "user_mentions": [],
200 | "urls": [],
201 | "media": [
202 | {
203 | "id": 1045955538390065200,
204 | "id_str": "1045955538390065153",
205 | "indices": [71, 94],
206 | "media_url": "http://pbs.twimg.com/media/DoP7BTyXoAE8U2o.jpg",
207 | "media_url_https": "https://pbs.twimg.com/media/DoP7BTyXoAE8U2o.jpg",
208 | "url": "https://t.co/IV7WmrdVJ8",
209 | "display_url": "pic.twitter.com/IV7WmrdVJ8",
210 | "expanded_url": "https://twitter.com/womensart1/status/1045955638898167808/photo/1",
211 | "type": "photo",
212 | "sizes": {
213 | "thumb": { "w": 150, "h": 150, "resize": "crop" },
214 | "large": { "w": 787, "h": 564, "resize": "fit" },
215 | "small": { "w": 680, "h": 487, "resize": "fit" },
216 | "medium": { "w": 787, "h": 564, "resize": "fit" }
217 | }
218 | }
219 | ]
220 | },
221 | "extended_entities": {
222 | "media": [
223 | {
224 | "id": 1045955538390065200,
225 | "id_str": "1045955538390065153",
226 | "indices": [71, 94],
227 | "media_url": "http://pbs.twimg.com/media/DoP7BTyXoAE8U2o.jpg",
228 | "media_url_https": "https://pbs.twimg.com/media/DoP7BTyXoAE8U2o.jpg",
229 | "url": "https://t.co/IV7WmrdVJ8",
230 | "display_url": "pic.twitter.com/IV7WmrdVJ8",
231 | "expanded_url": "https://twitter.com/womensart1/status/1045955638898167808/photo/1",
232 | "type": "photo",
233 | "sizes": {
234 | "thumb": { "w": 150, "h": 150, "resize": "crop" },
235 | "large": { "w": 787, "h": 564, "resize": "fit" },
236 | "small": { "w": 680, "h": 487, "resize": "fit" },
237 | "medium": { "w": 787, "h": 564, "resize": "fit" }
238 | },
239 | "ext_alt_text": null
240 | }
241 | ]
242 | },
243 | "source": "Twitter Web Client",
244 | "in_reply_to_status_id": null,
245 | "in_reply_to_status_id_str": null,
246 | "in_reply_to_user_id": null,
247 | "in_reply_to_user_id_str": null,
248 | "in_reply_to_screen_name": null,
249 | "user": {
250 | "id": 4823705386,
251 | "id_str": "4823705386",
252 | "name": "#WOMENSART",
253 | "screen_name": "womensart1",
254 | "location": "",
255 | "description": "#womensart celebrating ♀'s art and creativity, created and curated by freelance writer/reviewer @PL_Henderson1 Images are © to their respective owners",
256 | "url": "https://t.co/gDV7wWbjgm",
257 | "entities": {
258 | "url": {
259 | "urls": [
260 | {
261 | "url": "https://t.co/gDV7wWbjgm",
262 | "expanded_url": "https://womensartblog.wordpress.com/",
263 | "display_url": "womensartblog.wordpress.com",
264 | "indices": [0, 23]
265 | }
266 | ]
267 | },
268 | "description": { "urls": [] }
269 | },
270 | "protected": false,
271 | "followers_count": 209749,
272 | "friends_count": 0,
273 | "listed_count": 2758,
274 | "created_at": "Mon Jan 18 10:32:28 +0000 2016",
275 | "favourites_count": 18350,
276 | "utc_offset": null,
277 | "time_zone": null,
278 | "geo_enabled": false,
279 | "verified": false,
280 | "statuses_count": 22943,
281 | "lang": "en",
282 | "contributors_enabled": false,
283 | "is_translator": false,
284 | "is_translation_enabled": false,
285 | "profile_background_color": "F5F8FA",
286 | "profile_background_image_url": null,
287 | "profile_background_image_url_https": null,
288 | "profile_background_tile": false,
289 | "profile_image_url": "http://pbs.twimg.com/profile_images/871701499335847936/jyeHvT9e_normal.jpg",
290 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/871701499335847936/jyeHvT9e_normal.jpg",
291 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/4823705386/1496667909",
292 | "profile_image_extensions_alt_text": null,
293 | "profile_banner_extensions_alt_text": null,
294 | "profile_link_color": "1DA1F2",
295 | "profile_sidebar_border_color": "C0DEED",
296 | "profile_sidebar_fill_color": "DDEEF6",
297 | "profile_text_color": "333333",
298 | "profile_use_background_image": true,
299 | "has_extended_profile": false,
300 | "default_profile": true,
301 | "default_profile_image": false,
302 | "following": false,
303 | "follow_request_sent": false,
304 | "notifications": false,
305 | "translator_type": "none"
306 | },
307 | "geo": null,
308 | "coordinates": null,
309 | "place": null,
310 | "contributors": null,
311 | "is_quote_status": false,
312 | "retweet_count": 157,
313 | "favorite_count": 615,
314 | "favorited": false,
315 | "retweeted": false,
316 | "possibly_sensitive": false,
317 | "possibly_sensitive_appealable": false,
318 | "lang": "en"
319 | },
320 | "4": {
321 | "created_at": "Fri Oct 05 20:25:32 +0000 2018",
322 | "id": 1048308227438510100,
323 | "id_str": "1048308227438510080",
324 | "full_text": "Heute abend weckt meine Timeline wieder jenes perlend funkelnde Twitfühl.* \n\nDanke euch allen! #Fuxknix\n\n#Bildbeschreibung #Bibesch #alt_text @get_altText \n\n*(Gesponserte Effekthaschereien mal ausgenommen, die sich anbiedern, als kennten sie all meine Neugierden...) https://t.co/vQtiUJYf8S",
325 | "truncated": false,
326 | "display_text_range": [0, 266],
327 | "entities": {
328 | "hashtags": [
329 | { "text": "Fuxknix", "indices": [95, 103] },
330 | { "text": "Bildbeschreibung", "indices": [105, 122] },
331 | { "text": "Bibesch", "indices": [123, 131] },
332 | { "text": "alt_text", "indices": [132, 141] }
333 | ],
334 | "symbols": [],
335 | "user_mentions": [
336 | {
337 | "screen_name": "get_altText",
338 | "name": "Alt Text Reader",
339 | "id": 968802481856794600,
340 | "id_str": "968802481856794624",
341 | "indices": [142, 154]
342 | }
343 | ],
344 | "urls": [],
345 | "media": [
346 | {
347 | "id": 1048305562415521800,
348 | "id_str": "1048305562415521798",
349 | "indices": [267, 290],
350 | "media_url": "http://pbs.twimg.com/media/DoxUWtfX4AYouTq.jpg",
351 | "media_url_https": "https://pbs.twimg.com/media/DoxUWtfX4AYouTq.jpg",
352 | "url": "https://t.co/vQtiUJYf8S",
353 | "display_url": "pic.twitter.com/vQtiUJYf8S",
354 | "expanded_url": "https://twitter.com/foxeen/status/1048308227438510080/photo/1",
355 | "type": "photo",
356 | "sizes": {
357 | "small": { "w": 640, "h": 480, "resize": "fit" },
358 | "thumb": { "w": 150, "h": 150, "resize": "crop" },
359 | "large": { "w": 640, "h": 480, "resize": "fit" },
360 | "medium": { "w": 640, "h": 480, "resize": "fit" }
361 | }
362 | }
363 | ]
364 | },
365 | "extended_entities": {
366 | "media": [
367 | {
368 | "id": 1048305562415521800,
369 | "id_str": "1048305562415521798",
370 | "indices": [267, 290],
371 | "media_url": "http://pbs.twimg.com/media/DoxUWtfX4AYouTq.jpg",
372 | "media_url_https": "https://pbs.twimg.com/media/DoxUWtfX4AYouTq.jpg",
373 | "url": "https://t.co/vQtiUJYf8S",
374 | "display_url": "pic.twitter.com/vQtiUJYf8S",
375 | "expanded_url": "https://twitter.com/foxeen/status/1048308227438510080/photo/1",
376 | "type": "photo",
377 | "sizes": {
378 | "small": { "w": 640, "h": 480, "resize": "fit" },
379 | "thumb": { "w": 150, "h": 150, "resize": "crop" },
380 | "large": { "w": 640, "h": 480, "resize": "fit" },
381 | "medium": { "w": 640, "h": 480, "resize": "fit" }
382 | },
383 | "ext_alt_text": "Winzige runde Tropfen entlang den fast unsichtbaren Fäden eines Spinnennetzes in Nahaufnahme - manche sind ganz scharf, manche unscharf, aber alle zusammen wirken wie feinste Perlen-Spitze, meisterlich geklöppelt."
384 | }
385 | ]
386 | },
387 | "source": "Twitter Web Client",
388 | "in_reply_to_status_id": null,
389 | "in_reply_to_status_id_str": null,
390 | "in_reply_to_user_id": null,
391 | "in_reply_to_user_id_str": null,
392 | "in_reply_to_screen_name": null,
393 | "user": {
394 | "id": 46904555,
395 | "id_str": "46904555",
396 | "name": "Füxin vong ab wegen *^~_~^*",
397 | "screen_name": "foxeen",
398 | "location": "Zweifel zu Werkzeugen.",
399 | "description": "Neugiertier. Gans verstohlen. #RefugeesWelcome Bilingomaniac of sorts. RT = for lack of better words. Caution: Bedenklicher Hang zum Komplizierten. #notjustsad",
400 | "url": "http://t.co/1ZFTBSq7jw",
401 | "entities": {
402 | "url": {
403 | "urls": [
404 | {
405 | "url": "http://t.co/1ZFTBSq7jw",
406 | "expanded_url": "http://www.textgruende.wordpress.com",
407 | "display_url": "textgruende.wordpress.com",
408 | "indices": [0, 22]
409 | }
410 | ]
411 | },
412 | "description": { "urls": [] }
413 | },
414 | "protected": false,
415 | "followers_count": 1553,
416 | "friends_count": 776,
417 | "listed_count": 232,
418 | "created_at": "Sat Jun 13 15:31:33 +0000 2009",
419 | "favourites_count": 135314,
420 | "utc_offset": null,
421 | "time_zone": null,
422 | "geo_enabled": false,
423 | "verified": false,
424 | "statuses_count": 65998,
425 | "lang": "de",
426 | "contributors_enabled": false,
427 | "is_translator": false,
428 | "is_translation_enabled": false,
429 | "profile_background_color": "5C5C5C",
430 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme4/bg.gif",
431 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme4/bg.gif",
432 | "profile_background_tile": true,
433 | "profile_image_url": "http://pbs.twimg.com/profile_images/714394259319824385/5RM06BOS_normal.jpg",
434 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/714394259319824385/5RM06BOS_normal.jpg",
435 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/46904555/1397410316",
436 | "profile_image_extensions_alt_text": null,
437 | "profile_banner_extensions_alt_text": null,
438 | "profile_link_color": "590606",
439 | "profile_sidebar_border_color": "000000",
440 | "profile_sidebar_fill_color": "705A55",
441 | "profile_text_color": "080808",
442 | "profile_use_background_image": true,
443 | "has_extended_profile": false,
444 | "default_profile": false,
445 | "default_profile_image": false,
446 | "following": false,
447 | "follow_request_sent": false,
448 | "notifications": false,
449 | "translator_type": "regular"
450 | },
451 | "geo": null,
452 | "coordinates": null,
453 | "place": null,
454 | "contributors": null,
455 | "is_quote_status": false,
456 | "retweet_count": 0,
457 | "favorite_count": 5,
458 | "favorited": false,
459 | "retweeted": false,
460 | "possibly_sensitive": false,
461 | "possibly_sensitive_appealable": false,
462 | "lang": "de"
463 | },
464 | "5": {
465 | "created_at": "Thu Mar 07 16:54:23 +0000 2019",
466 | "id": 1103700431648243700,
467 | "id_str": "1103700431648243712",
468 | "full_text": "#SehrysWho\n\nwe will try to keep track of this year’s reading in this thread, tagging with #SehrysReads ⬇️\n\nhttps://t.co/CYu8aSMRTj",
469 | "truncated": false,
470 | "display_text_range": [0, 130],
471 | "entities": {
472 | "hashtags": [
473 | { "text": "SehrysWho", "indices": [0, 10] },
474 | { "text": "SehrysReads", "indices": [90, 102] }
475 | ],
476 | "symbols": [],
477 | "user_mentions": [],
478 | "urls": [
479 | {
480 | "url": "https://t.co/CYu8aSMRTj",
481 | "expanded_url": "https://twitter.com/sehrysflausch/status/1103699905338634240?s=21",
482 | "display_url": "twitter.com/sehrysflausch/…",
483 | "indices": [107, 130]
484 | }
485 | ]
486 | },
487 | "source": "Twitter for iPhone",
488 | "in_reply_to_status_id": 1081636996827807700,
489 | "in_reply_to_status_id_str": "1081636996827807745",
490 | "in_reply_to_user_id": 890161666129834000,
491 | "in_reply_to_user_id_str": "890161666129833984",
492 | "in_reply_to_screen_name": "SehrysFlausch",
493 | "user": {
494 | "id": 890161666129834000,
495 | "id_str": "890161666129833984",
496 | "name": "Sehrys [ey/em | keins]",
497 | "screen_name": "SehrysFlausch",
498 | "location": "",
499 | "description": "[ey/em, plural they] queer, trans masc, fluidflux. neurodivergent, plural👥. white, fat. [tip us at: https://t.co/0AXhPwjVgX] #nsfw. pic by @coffeeandtheart",
500 | "url": "https://t.co/YkfgwS59sz",
501 | "entities": {
502 | "url": {
503 | "urls": [
504 | {
505 | "url": "https://t.co/YkfgwS59sz",
506 | "expanded_url": "https://www.amazon.de/registry/wishlist/W53W1S6W7NGG",
507 | "display_url": "amazon.de/registry/wishl…",
508 | "indices": [0, 23]
509 | }
510 | ]
511 | },
512 | "description": {
513 | "urls": [
514 | {
515 | "url": "https://t.co/0AXhPwjVgX",
516 | "expanded_url": "http://ko-fi.com/sehrys",
517 | "display_url": "ko-fi.com/sehrys",
518 | "indices": [100, 123]
519 | }
520 | ]
521 | }
522 | },
523 | "protected": false,
524 | "followers_count": 343,
525 | "friends_count": 303,
526 | "listed_count": 2,
527 | "created_at": "Wed Jul 26 10:47:34 +0000 2017",
528 | "favourites_count": 53088,
529 | "utc_offset": null,
530 | "time_zone": null,
531 | "geo_enabled": false,
532 | "verified": false,
533 | "statuses_count": 10492,
534 | "lang": "de",
535 | "contributors_enabled": false,
536 | "is_translator": false,
537 | "is_translation_enabled": false,
538 | "profile_background_color": "000000",
539 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
540 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
541 | "profile_background_tile": false,
542 | "profile_image_url": "http://pbs.twimg.com/profile_images/1082378840872235008/Js7Obz6k_normal.jpg",
543 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/1082378840872235008/Js7Obz6k_normal.jpg",
544 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/890161666129833984/1548150995",
545 | "profile_image_extensions_alt_text": null,
546 | "profile_banner_extensions_alt_text": null,
547 | "profile_link_color": "1DA1F2",
548 | "profile_sidebar_border_color": "000000",
549 | "profile_sidebar_fill_color": "000000",
550 | "profile_text_color": "000000",
551 | "profile_use_background_image": false,
552 | "has_extended_profile": true,
553 | "default_profile": false,
554 | "default_profile_image": false,
555 | "following": false,
556 | "follow_request_sent": false,
557 | "notifications": false,
558 | "translator_type": "none"
559 | },
560 | "geo": null,
561 | "coordinates": null,
562 | "place": null,
563 | "contributors": null,
564 | "is_quote_status": true,
565 | "quoted_status_id": 1103699905338634200,
566 | "quoted_status_id_str": "1103699905338634240",
567 | "quoted_status_permalink": {
568 | "url": "https://t.co/CYu8aSMRTj",
569 | "expanded": "https://twitter.com/sehrysflausch/status/1103699905338634240?s=21",
570 | "display": "twitter.com/sehrysflausch/…"
571 | },
572 | "quoted_status": {
573 | "created_at": "Thu Mar 07 16:52:17 +0000 2019",
574 | "id": 1103699905338634200,
575 | "id_str": "1103699905338634240",
576 | "full_text": "we will try and keep track of all the books we read this year, because we love when others do that\n\ngonna start this by trying to remember the past months,\n\ntagging with #SehrysReads \n\n✨#thread starter kitten included, because cats!✨ https://t.co/wzFDoEi0Af",
577 | "truncated": false,
578 | "display_text_range": [0, 233],
579 | "entities": {
580 | "hashtags": [
581 | { "text": "SehrysReads", "indices": [170, 182] },
582 | { "text": "thread", "indices": [186, 193] }
583 | ],
584 | "symbols": [],
585 | "user_mentions": [],
586 | "urls": [],
587 | "media": [
588 | {
589 | "id": 1103699898703188000,
590 | "id_str": "1103699898703187969",
591 | "indices": [234, 257],
592 | "media_url": "http://pbs.twimg.com/media/D1EhNdDWkAEJxoC.jpg",
593 | "media_url_https": "https://pbs.twimg.com/media/D1EhNdDWkAEJxoC.jpg",
594 | "url": "https://t.co/wzFDoEi0Af",
595 | "display_url": "pic.twitter.com/wzFDoEi0Af",
596 | "expanded_url": "https://twitter.com/SehrysFlausch/status/1103699905338634240/photo/1",
597 | "type": "photo",
598 | "sizes": {
599 | "medium": { "w": 900, "h": 1200, "resize": "fit" },
600 | "thumb": { "w": 150, "h": 150, "resize": "crop" },
601 | "small": { "w": 510, "h": 680, "resize": "fit" },
602 | "large": { "w": 1536, "h": 2048, "resize": "fit" }
603 | }
604 | }
605 | ]
606 | },
607 | "extended_entities": {
608 | "media": [
609 | {
610 | "id": 1103699898703188000,
611 | "id_str": "1103699898703187969",
612 | "indices": [234, 257],
613 | "media_url": "http://pbs.twimg.com/media/D1EhNdDWkAEJxoC.jpg",
614 | "media_url_https": "https://pbs.twimg.com/media/D1EhNdDWkAEJxoC.jpg",
615 | "url": "https://t.co/wzFDoEi0Af",
616 | "display_url": "pic.twitter.com/wzFDoEi0Af",
617 | "expanded_url": "https://twitter.com/SehrysFlausch/status/1103699905338634240/photo/1",
618 | "type": "photo",
619 | "sizes": {
620 | "medium": { "w": 900, "h": 1200, "resize": "fit" },
621 | "thumb": { "w": 150, "h": 150, "resize": "crop" },
622 | "small": { "w": 510, "h": 680, "resize": "fit" },
623 | "large": { "w": 1536, "h": 2048, "resize": "fit" }
624 | },
625 | "ext_alt_text": "a tabby cat (@skyescats #OhMyOllie) sits on a chair, with its head looking up over a kitchen table. on the table is an unfinished jigsaw puzzle, the picture also featuring two tabby cats."
626 | }
627 | ]
628 | },
629 | "source": "Twitter for iPhone",
630 | "in_reply_to_status_id": null,
631 | "in_reply_to_status_id_str": null,
632 | "in_reply_to_user_id": null,
633 | "in_reply_to_user_id_str": null,
634 | "in_reply_to_screen_name": null,
635 | "user": {
636 | "id": 890161666129834000,
637 | "id_str": "890161666129833984",
638 | "name": "Sehrys [ey/em | keins]",
639 | "screen_name": "SehrysFlausch",
640 | "location": "",
641 | "description": "[ey/em, plural they] queer, trans masc, fluidflux. neurodivergent, plural👥. white, fat. [tip us at: https://t.co/0AXhPwjVgX] #nsfw. pic by @coffeeandtheart",
642 | "url": "https://t.co/YkfgwS59sz",
643 | "entities": {
644 | "url": {
645 | "urls": [
646 | {
647 | "url": "https://t.co/YkfgwS59sz",
648 | "expanded_url": "https://www.amazon.de/registry/wishlist/W53W1S6W7NGG",
649 | "display_url": "amazon.de/registry/wishl…",
650 | "indices": [0, 23]
651 | }
652 | ]
653 | },
654 | "description": {
655 | "urls": [
656 | {
657 | "url": "https://t.co/0AXhPwjVgX",
658 | "expanded_url": "http://ko-fi.com/sehrys",
659 | "display_url": "ko-fi.com/sehrys",
660 | "indices": [100, 123]
661 | }
662 | ]
663 | }
664 | },
665 | "protected": false,
666 | "followers_count": 343,
667 | "friends_count": 303,
668 | "listed_count": 2,
669 | "created_at": "Wed Jul 26 10:47:34 +0000 2017",
670 | "favourites_count": 53088,
671 | "utc_offset": null,
672 | "time_zone": null,
673 | "geo_enabled": false,
674 | "verified": false,
675 | "statuses_count": 10492,
676 | "lang": "de",
677 | "contributors_enabled": false,
678 | "is_translator": false,
679 | "is_translation_enabled": false,
680 | "profile_background_color": "000000",
681 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
682 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
683 | "profile_background_tile": false,
684 | "profile_image_url": "http://pbs.twimg.com/profile_images/1082378840872235008/Js7Obz6k_normal.jpg",
685 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/1082378840872235008/Js7Obz6k_normal.jpg",
686 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/890161666129833984/1548150995",
687 | "profile_image_extensions_alt_text": null,
688 | "profile_banner_extensions_alt_text": null,
689 | "profile_link_color": "1DA1F2",
690 | "profile_sidebar_border_color": "000000",
691 | "profile_sidebar_fill_color": "000000",
692 | "profile_text_color": "000000",
693 | "profile_use_background_image": false,
694 | "has_extended_profile": true,
695 | "default_profile": false,
696 | "default_profile_image": false,
697 | "following": false,
698 | "follow_request_sent": false,
699 | "notifications": false,
700 | "translator_type": "none"
701 | },
702 | "geo": null,
703 | "coordinates": null,
704 | "place": null,
705 | "contributors": null,
706 | "is_quote_status": false,
707 | "retweet_count": 0,
708 | "favorite_count": 5,
709 | "favorited": false,
710 | "retweeted": false,
711 | "possibly_sensitive": false,
712 | "possibly_sensitive_appealable": false,
713 | "lang": "en"
714 | },
715 | "retweet_count": 0,
716 | "favorite_count": 0,
717 | "favorited": false,
718 | "retweeted": false,
719 | "possibly_sensitive": false,
720 | "possibly_sensitive_appealable": false,
721 | "lang": "en"
722 | },
723 | "6": {
724 | "created_at": "Sat Mar 09 16:47:17 +0000 2019",
725 | "id": 1104423422925422600,
726 | "id_str": "1104423422925422595",
727 | "full_text": "o https://t.co/nL5jHq9EX6",
728 | "truncated": false,
729 | "display_text_range": [0, 1],
730 | "entities": {
731 | "hashtags": [],
732 | "symbols": [],
733 | "user_mentions": [],
734 | "urls": [
735 | {
736 | "url": "https://t.co/nL5jHq9EX6",
737 | "expanded_url": "https://twitter.com/blurryechopilot/status/1104044949123796995",
738 | "display_url": "twitter.com/blurryechopilo…",
739 | "indices": [2, 25]
740 | }
741 | ]
742 | },
743 | "source": "Twitter for Android",
744 | "in_reply_to_status_id": null,
745 | "in_reply_to_status_id_str": null,
746 | "in_reply_to_user_id": null,
747 | "in_reply_to_user_id_str": null,
748 | "in_reply_to_screen_name": null,
749 | "user": {
750 | "id": 3262161021,
751 | "id_str": "3262161021",
752 | "name": "florian - mikkelslut",
753 | "screen_name": "_cumasyouare_",
754 | "location": "[he/him] Germany GER/ENG",
755 | "description": "| you should always eat the rude | Aristocrat of Evil | 18 | fandom trash content und aktivismus |\nhttps://t.co/fKzBVAL3j5",
756 | "url": "https://t.co/wlwmAbcYl5",
757 | "entities": {
758 | "url": {
759 | "urls": [
760 | {
761 | "url": "https://t.co/wlwmAbcYl5",
762 | "expanded_url": "https://curiouscat.me/cumasyouare",
763 | "display_url": "curiouscat.me/cumasyouare",
764 | "indices": [0, 23]
765 | }
766 | ]
767 | },
768 | "description": {
769 | "urls": [
770 | {
771 | "url": "https://t.co/fKzBVAL3j5",
772 | "expanded_url": "http://tellonym.me/omegaonmars",
773 | "display_url": "tellonym.me/omegaonmars",
774 | "indices": [99, 122]
775 | }
776 | ]
777 | }
778 | },
779 | "protected": false,
780 | "followers_count": 511,
781 | "friends_count": 244,
782 | "listed_count": 5,
783 | "created_at": "Sat May 16 17:45:14 +0000 2015",
784 | "favourites_count": 5154,
785 | "utc_offset": null,
786 | "time_zone": null,
787 | "geo_enabled": false,
788 | "verified": false,
789 | "statuses_count": 26162,
790 | "lang": "de",
791 | "contributors_enabled": false,
792 | "is_translator": false,
793 | "is_translation_enabled": false,
794 | "profile_background_color": "C0DEED",
795 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
796 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
797 | "profile_background_tile": false,
798 | "profile_image_url": "http://pbs.twimg.com/profile_images/1092849205511626752/oVwd1iqf_normal.jpg",
799 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/1092849205511626752/oVwd1iqf_normal.jpg",
800 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/3262161021/1544820020",
801 | "profile_image_extensions_alt_text": null,
802 | "profile_banner_extensions_alt_text": null,
803 | "profile_link_color": "1DA1F2",
804 | "profile_sidebar_border_color": "C0DEED",
805 | "profile_sidebar_fill_color": "DDEEF6",
806 | "profile_text_color": "333333",
807 | "profile_use_background_image": true,
808 | "has_extended_profile": true,
809 | "default_profile": true,
810 | "default_profile_image": false,
811 | "following": false,
812 | "follow_request_sent": false,
813 | "notifications": false,
814 | "translator_type": "none"
815 | },
816 | "geo": null,
817 | "coordinates": null,
818 | "place": null,
819 | "contributors": null,
820 | "is_quote_status": true,
821 | "quoted_status_id": 1104044949123797000,
822 | "quoted_status_id_str": "1104044949123796995",
823 | "quoted_status_permalink": {
824 | "url": "https://t.co/nL5jHq9EX6",
825 | "expanded": "https://twitter.com/blurryechopilot/status/1104044949123796995",
826 | "display": "twitter.com/blurryechopilo…"
827 | },
828 | "quoted_status": {
829 | "created_at": "Fri Mar 08 15:43:22 +0000 2019",
830 | "id": 1104044949123797000,
831 | "id_str": "1104044949123796995",
832 | "full_text": "i’ll start, oph t https://t.co/OOfatNoeC7",
833 | "truncated": false,
834 | "display_text_range": [0, 17],
835 | "entities": {
836 | "hashtags": [],
837 | "symbols": [],
838 | "user_mentions": [],
839 | "urls": [],
840 | "media": [
841 | {
842 | "id": 1104044942438133800,
843 | "id_str": "1104044942438133765",
844 | "indices": [18, 41],
845 | "media_url": "http://pbs.twimg.com/media/D1JbBpIXcAUXzvR.jpg",
846 | "media_url_https": "https://pbs.twimg.com/media/D1JbBpIXcAUXzvR.jpg",
847 | "url": "https://t.co/OOfatNoeC7",
848 | "display_url": "pic.twitter.com/OOfatNoeC7",
849 | "expanded_url": "https://twitter.com/blurryechopilot/status/1104044949123796995/photo/1",
850 | "type": "photo",
851 | "sizes": {
852 | "thumb": { "w": 150, "h": 150, "resize": "crop" },
853 | "small": { "w": 680, "h": 552, "resize": "fit" },
854 | "large": { "w": 1242, "h": 1009, "resize": "fit" },
855 | "medium": { "w": 1200, "h": 975, "resize": "fit" }
856 | }
857 | }
858 | ]
859 | },
860 | "extended_entities": {
861 | "media": [
862 | {
863 | "id": 1104044942438133800,
864 | "id_str": "1104044942438133765",
865 | "indices": [18, 41],
866 | "media_url": "http://pbs.twimg.com/media/D1JbBpIXcAUXzvR.jpg",
867 | "media_url_https": "https://pbs.twimg.com/media/D1JbBpIXcAUXzvR.jpg",
868 | "url": "https://t.co/OOfatNoeC7",
869 | "display_url": "pic.twitter.com/OOfatNoeC7",
870 | "expanded_url": "https://twitter.com/blurryechopilot/status/1104044949123796995/photo/1",
871 | "type": "photo",
872 | "sizes": {
873 | "thumb": { "w": 150, "h": 150, "resize": "crop" },
874 | "small": { "w": 680, "h": 552, "resize": "fit" },
875 | "large": { "w": 1242, "h": 1009, "resize": "fit" },
876 | "medium": { "w": 1200, "h": 975, "resize": "fit" }
877 | },
878 | "ext_alt_text": null
879 | }
880 | ]
881 | },
882 | "source": "Twitter for iPhone",
883 | "in_reply_to_status_id": null,
884 | "in_reply_to_status_id_str": null,
885 | "in_reply_to_user_id": null,
886 | "in_reply_to_user_id_str": null,
887 | "in_reply_to_screen_name": null,
888 | "user": {
889 | "id": 878193344605769700,
890 | "id_str": "878193344605769729",
891 | "name": "soph 🥵",
892 | "screen_name": "blurryechopilot",
893 | "location": "trench",
894 | "description": "+ 𝒻𝑜𝓇 𝓎𝑜𝓊, 𝒾 𝓌𝑜𝓊𝓁𝒹 𝑔𝑒𝓉 𝒷𝑒𝒶𝓉 𝓉𝑜 𝓈𝓂𝒾𝓉𝒽𝑒𝓇𝑒𝑒𝓃𝓈 5/3/19💛",
895 | "url": "https://t.co/dk4ZO2P0nr",
896 | "entities": {
897 | "url": {
898 | "urls": [
899 | {
900 | "url": "https://t.co/dk4ZO2P0nr",
901 | "expanded_url": "https://curiouscat.me/blurryechopilot",
902 | "display_url": "curiouscat.me/blurryechopilot",
903 | "indices": [0, 23]
904 | }
905 | ]
906 | },
907 | "description": { "urls": [] }
908 | },
909 | "protected": false,
910 | "followers_count": 2587,
911 | "friends_count": 2459,
912 | "listed_count": 21,
913 | "created_at": "Fri Jun 23 10:09:44 +0000 2017",
914 | "favourites_count": 1735,
915 | "utc_offset": null,
916 | "time_zone": null,
917 | "geo_enabled": true,
918 | "verified": false,
919 | "statuses_count": 2696,
920 | "lang": "en",
921 | "contributors_enabled": false,
922 | "is_translator": false,
923 | "is_translation_enabled": false,
924 | "profile_background_color": "000000",
925 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
926 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
927 | "profile_background_tile": false,
928 | "profile_image_url": "http://pbs.twimg.com/profile_images/1104332154845257729/bAc_0M9E_normal.jpg",
929 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/1104332154845257729/bAc_0M9E_normal.jpg",
930 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/878193344605769729/1552128279",
931 | "profile_image_extensions_alt_text": null,
932 | "profile_banner_extensions_alt_text": null,
933 | "profile_link_color": "E81C4F",
934 | "profile_sidebar_border_color": "000000",
935 | "profile_sidebar_fill_color": "000000",
936 | "profile_text_color": "000000",
937 | "profile_use_background_image": false,
938 | "has_extended_profile": true,
939 | "default_profile": false,
940 | "default_profile_image": false,
941 | "following": false,
942 | "follow_request_sent": false,
943 | "notifications": false,
944 | "translator_type": "none"
945 | },
946 | "geo": null,
947 | "coordinates": null,
948 | "place": null,
949 | "contributors": null,
950 | "is_quote_status": false,
951 | "retweet_count": 25,
952 | "favorite_count": 788,
953 | "favorited": false,
954 | "retweeted": false,
955 | "possibly_sensitive": false,
956 | "possibly_sensitive_appealable": false,
957 | "lang": "en"
958 | },
959 | "retweet_count": 0,
960 | "favorite_count": 2,
961 | "favorited": false,
962 | "retweeted": false,
963 | "possibly_sensitive": false,
964 | "possibly_sensitive_appealable": false,
965 | "lang": "und"
966 | },
967 | "7": {
968 | "created_at": "Sat Mar 02 06:52:43 +0000 2019",
969 | "id": 1101737078956666900,
970 | "id_str": "1101737078956666880",
971 | "full_text": "People who think Saturday 8am is a good time for an exam should be banned from ever holding an exam again.",
972 | "truncated": false,
973 | "display_text_range": [0, 106],
974 | "entities": {
975 | "hashtags": [],
976 | "symbols": [],
977 | "user_mentions": [],
978 | "urls": []
979 | },
980 | "source": "Tweetbot for iΟS",
981 | "in_reply_to_status_id": null,
982 | "in_reply_to_status_id_str": null,
983 | "in_reply_to_user_id": null,
984 | "in_reply_to_user_id_str": null,
985 | "in_reply_to_screen_name": null,
986 | "user": {
987 | "id": 1865110807,
988 | "id_str": "1865110807",
989 | "name": "φnn",
990 | "screen_name": "malfynnction",
991 | "location": "Berlin, Germany",
992 | "description": "Fynn | 21 | he/him | does things with computers, gender, and other queer stuff | knows how to fold a fitted sheet | ava by @_morre_",
993 | "url": null,
994 | "entities": { "description": { "urls": [] } },
995 | "protected": false,
996 | "followers_count": 927,
997 | "friends_count": 248,
998 | "listed_count": 34,
999 | "created_at": "Sat Sep 14 21:35:38 +0000 2013",
1000 | "favourites_count": 40125,
1001 | "utc_offset": null,
1002 | "time_zone": null,
1003 | "geo_enabled": true,
1004 | "verified": false,
1005 | "statuses_count": 38316,
1006 | "lang": "en-gb",
1007 | "contributors_enabled": false,
1008 | "is_translator": false,
1009 | "is_translation_enabled": false,
1010 | "profile_background_color": "000000",
1011 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme18/bg.gif",
1012 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme18/bg.gif",
1013 | "profile_background_tile": false,
1014 | "profile_image_url": "http://pbs.twimg.com/profile_images/1071082881831833601/uxR94Gp8_normal.jpg",
1015 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/1071082881831833601/uxR94Gp8_normal.jpg",
1016 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/1865110807/1496517525",
1017 | "profile_image_extensions_alt_text": null,
1018 | "profile_banner_extensions_alt_text": null,
1019 | "profile_link_color": "336699",
1020 | "profile_sidebar_border_color": "000000",
1021 | "profile_sidebar_fill_color": "000000",
1022 | "profile_text_color": "000000",
1023 | "profile_use_background_image": false,
1024 | "has_extended_profile": false,
1025 | "default_profile": false,
1026 | "default_profile_image": false,
1027 | "following": false,
1028 | "follow_request_sent": false,
1029 | "notifications": false,
1030 | "translator_type": "none"
1031 | },
1032 | "geo": null,
1033 | "coordinates": null,
1034 | "place": null,
1035 | "contributors": null,
1036 | "is_quote_status": false,
1037 | "retweet_count": 0,
1038 | "favorite_count": 17,
1039 | "favorited": false,
1040 | "retweeted": false,
1041 | "lang": "en"
1042 | },
1043 | "8": {
1044 | "created_at": "Sat Feb 16 19:05:10 +0000 2019",
1045 | "id": 1096847973919670300,
1046 | "id_str": "1096847973919670272",
1047 | "full_text": "@behindmypride “i was born and that was so viel” mood",
1048 | "truncated": false,
1049 | "display_text_range": [15, 53],
1050 | "entities": {
1051 | "hashtags": [],
1052 | "symbols": [],
1053 | "user_mentions": [
1054 | {
1055 | "screen_name": "behindmypride",
1056 | "name": "noah",
1057 | "id": 2388083673,
1058 | "id_str": "2388083673",
1059 | "indices": [0, 14]
1060 | }
1061 | ],
1062 | "urls": []
1063 | },
1064 | "source": "Tweetbot for Mac",
1065 | "in_reply_to_status_id": 1096831377440456700,
1066 | "in_reply_to_status_id_str": "1096831377440456704",
1067 | "in_reply_to_user_id": 2388083673,
1068 | "in_reply_to_user_id_str": "2388083673",
1069 | "in_reply_to_screen_name": "behindmypride",
1070 | "user": {
1071 | "id": 1865110807,
1072 | "id_str": "1865110807",
1073 | "name": "φnn",
1074 | "screen_name": "malfynnction",
1075 | "location": "Berlin, Germany",
1076 | "description": "Fynn | 21 | he/him | does things with computers, gender, and other queer stuff | knows how to fold a fitted sheet | ava by @_morre_",
1077 | "url": null,
1078 | "entities": { "description": { "urls": [] } },
1079 | "protected": false,
1080 | "followers_count": 927,
1081 | "friends_count": 248,
1082 | "listed_count": 34,
1083 | "created_at": "Sat Sep 14 21:35:38 +0000 2013",
1084 | "favourites_count": 40125,
1085 | "utc_offset": null,
1086 | "time_zone": null,
1087 | "geo_enabled": true,
1088 | "verified": false,
1089 | "statuses_count": 38316,
1090 | "lang": "en-gb",
1091 | "contributors_enabled": false,
1092 | "is_translator": false,
1093 | "is_translation_enabled": false,
1094 | "profile_background_color": "000000",
1095 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme18/bg.gif",
1096 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme18/bg.gif",
1097 | "profile_background_tile": false,
1098 | "profile_image_url": "http://pbs.twimg.com/profile_images/1071082881831833601/uxR94Gp8_normal.jpg",
1099 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/1071082881831833601/uxR94Gp8_normal.jpg",
1100 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/1865110807/1496517525",
1101 | "profile_image_extensions_alt_text": null,
1102 | "profile_banner_extensions_alt_text": null,
1103 | "profile_link_color": "336699",
1104 | "profile_sidebar_border_color": "000000",
1105 | "profile_sidebar_fill_color": "000000",
1106 | "profile_text_color": "000000",
1107 | "profile_use_background_image": false,
1108 | "has_extended_profile": false,
1109 | "default_profile": false,
1110 | "default_profile_image": false,
1111 | "following": false,
1112 | "follow_request_sent": false,
1113 | "notifications": false,
1114 | "translator_type": "none"
1115 | },
1116 | "geo": null,
1117 | "coordinates": null,
1118 | "place": null,
1119 | "contributors": null,
1120 | "is_quote_status": false,
1121 | "retweet_count": 0,
1122 | "favorite_count": 3,
1123 | "favorited": false,
1124 | "retweeted": false,
1125 | "lang": "en"
1126 | },
1127 | "9": {
1128 | "created_at": "Thu Jan 31 19:56:09 +0000 2019",
1129 | "id": 1091062601017163800,
1130 | "id_str": "1091062601017163776",
1131 | "full_text": "The blue one is still available! https://t.co/K8oTwlxKYV",
1132 | "truncated": false,
1133 | "display_text_range": [0, 32],
1134 | "entities": {
1135 | "hashtags": [],
1136 | "symbols": [],
1137 | "user_mentions": [],
1138 | "urls": [
1139 | {
1140 | "url": "https://t.co/K8oTwlxKYV",
1141 | "expanded_url": "https://twitter.com/malfynnction/status/1089123853681545217",
1142 | "display_url": "twitter.com/malfynnction/s…",
1143 | "indices": [33, 56]
1144 | }
1145 | ]
1146 | },
1147 | "source": "Tweetbot for iΟS",
1148 | "in_reply_to_status_id": 1089123853681545200,
1149 | "in_reply_to_status_id_str": "1089123853681545217",
1150 | "in_reply_to_user_id": 1865110807,
1151 | "in_reply_to_user_id_str": "1865110807",
1152 | "in_reply_to_screen_name": "malfynnction",
1153 | "user": {
1154 | "id": 1865110807,
1155 | "id_str": "1865110807",
1156 | "name": "φnn",
1157 | "screen_name": "malfynnction",
1158 | "location": "Berlin, Germany",
1159 | "description": "Fynn | 21 | he/him | does things with computers, gender, and other queer stuff | knows how to fold a fitted sheet | ava by @_morre_",
1160 | "url": null,
1161 | "entities": { "description": { "urls": [] } },
1162 | "protected": false,
1163 | "followers_count": 927,
1164 | "friends_count": 248,
1165 | "listed_count": 34,
1166 | "created_at": "Sat Sep 14 21:35:38 +0000 2013",
1167 | "favourites_count": 40125,
1168 | "utc_offset": null,
1169 | "time_zone": null,
1170 | "geo_enabled": true,
1171 | "verified": false,
1172 | "statuses_count": 38316,
1173 | "lang": "en-gb",
1174 | "contributors_enabled": false,
1175 | "is_translator": false,
1176 | "is_translation_enabled": false,
1177 | "profile_background_color": "000000",
1178 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme18/bg.gif",
1179 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme18/bg.gif",
1180 | "profile_background_tile": false,
1181 | "profile_image_url": "http://pbs.twimg.com/profile_images/1071082881831833601/uxR94Gp8_normal.jpg",
1182 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/1071082881831833601/uxR94Gp8_normal.jpg",
1183 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/1865110807/1496517525",
1184 | "profile_image_extensions_alt_text": null,
1185 | "profile_banner_extensions_alt_text": null,
1186 | "profile_link_color": "336699",
1187 | "profile_sidebar_border_color": "000000",
1188 | "profile_sidebar_fill_color": "000000",
1189 | "profile_text_color": "000000",
1190 | "profile_use_background_image": false,
1191 | "has_extended_profile": false,
1192 | "default_profile": false,
1193 | "default_profile_image": false,
1194 | "following": false,
1195 | "follow_request_sent": false,
1196 | "notifications": false,
1197 | "translator_type": "none"
1198 | },
1199 | "geo": null,
1200 | "coordinates": null,
1201 | "place": null,
1202 | "contributors": null,
1203 | "is_quote_status": true,
1204 | "quoted_status_id": 1089123853681545200,
1205 | "quoted_status_id_str": "1089123853681545217",
1206 | "quoted_status_permalink": {
1207 | "url": "https://t.co/K8oTwlxKYV",
1208 | "expanded": "https://twitter.com/malfynnction/status/1089123853681545217",
1209 | "display": "twitter.com/malfynnction/s…"
1210 | },
1211 | "quoted_status": {
1212 | "created_at": "Sat Jan 26 11:32:16 +0000 2019",
1213 | "id": 1089123853681545200,
1214 | "id_str": "1089123853681545217",
1215 | "full_text": "Does anybody need a binder?\n\ni have \n- gc2b half binder, blue, M\n- gc2b half binder, nude no. 4, M\n- danae half binder, black, M\nand would be happy to give them to ppl who need one",
1216 | "truncated": false,
1217 | "display_text_range": [0, 180],
1218 | "entities": {
1219 | "hashtags": [],
1220 | "symbols": [],
1221 | "user_mentions": [],
1222 | "urls": []
1223 | },
1224 | "source": "Tweetbot for Mac",
1225 | "in_reply_to_status_id": null,
1226 | "in_reply_to_status_id_str": null,
1227 | "in_reply_to_user_id": null,
1228 | "in_reply_to_user_id_str": null,
1229 | "in_reply_to_screen_name": null,
1230 | "user": {
1231 | "id": 1865110807,
1232 | "id_str": "1865110807",
1233 | "name": "φnn",
1234 | "screen_name": "malfynnction",
1235 | "location": "Berlin, Germany",
1236 | "description": "Fynn | 21 | he/him | does things with computers, gender, and other queer stuff | knows how to fold a fitted sheet | ava by @_morre_",
1237 | "url": null,
1238 | "entities": { "description": { "urls": [] } },
1239 | "protected": false,
1240 | "followers_count": 927,
1241 | "friends_count": 248,
1242 | "listed_count": 34,
1243 | "created_at": "Sat Sep 14 21:35:38 +0000 2013",
1244 | "favourites_count": 40125,
1245 | "utc_offset": null,
1246 | "time_zone": null,
1247 | "geo_enabled": true,
1248 | "verified": false,
1249 | "statuses_count": 38316,
1250 | "lang": "en-gb",
1251 | "contributors_enabled": false,
1252 | "is_translator": false,
1253 | "is_translation_enabled": false,
1254 | "profile_background_color": "000000",
1255 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme18/bg.gif",
1256 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme18/bg.gif",
1257 | "profile_background_tile": false,
1258 | "profile_image_url": "http://pbs.twimg.com/profile_images/1071082881831833601/uxR94Gp8_normal.jpg",
1259 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/1071082881831833601/uxR94Gp8_normal.jpg",
1260 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/1865110807/1496517525",
1261 | "profile_image_extensions_alt_text": null,
1262 | "profile_banner_extensions_alt_text": null,
1263 | "profile_link_color": "336699",
1264 | "profile_sidebar_border_color": "000000",
1265 | "profile_sidebar_fill_color": "000000",
1266 | "profile_text_color": "000000",
1267 | "profile_use_background_image": false,
1268 | "has_extended_profile": false,
1269 | "default_profile": false,
1270 | "default_profile_image": false,
1271 | "following": false,
1272 | "follow_request_sent": false,
1273 | "notifications": false,
1274 | "translator_type": "none"
1275 | },
1276 | "geo": null,
1277 | "coordinates": null,
1278 | "place": null,
1279 | "contributors": null,
1280 | "is_quote_status": false,
1281 | "retweet_count": 163,
1282 | "favorite_count": 71,
1283 | "favorited": false,
1284 | "retweeted": false,
1285 | "lang": "en"
1286 | },
1287 | "retweet_count": 5,
1288 | "favorite_count": 1,
1289 | "favorited": false,
1290 | "retweeted": false,
1291 | "possibly_sensitive": false,
1292 | "possibly_sensitive_appealable": false,
1293 | "lang": "en"
1294 | },
1295 | "10": {
1296 | "created_at": "Fri Sep 07 11:30:25 +0000 2018",
1297 | "id": 1038026699827564500,
1298 | "id_str": "1038026699827564545",
1299 | "full_text": "So, my health insurance has finally decided that they’re going to pay for my top surgery & hysto!! 🎉 https://t.co/hHTWpljKpp",
1300 | "truncated": false,
1301 | "display_text_range": [0, 104],
1302 | "entities": {
1303 | "hashtags": [],
1304 | "symbols": [],
1305 | "user_mentions": [],
1306 | "urls": [],
1307 | "media": [
1308 | {
1309 | "id": 1038026693380898800,
1310 | "id_str": "1038026693380898817",
1311 | "indices": [105, 128],
1312 | "media_url": "http://pbs.twimg.com/media/DmfPxyZXgAEyqGD.jpg",
1313 | "media_url_https": "https://pbs.twimg.com/media/DmfPxyZXgAEyqGD.jpg",
1314 | "url": "https://t.co/hHTWpljKpp",
1315 | "display_url": "pic.twitter.com/hHTWpljKpp",
1316 | "expanded_url": "https://twitter.com/malfynnction/status/1038026699827564545/photo/1",
1317 | "type": "photo",
1318 | "sizes": {
1319 | "small": { "w": 680, "h": 298, "resize": "fit" },
1320 | "thumb": { "w": 150, "h": 150, "resize": "crop" },
1321 | "large": { "w": 2048, "h": 897, "resize": "fit" },
1322 | "medium": { "w": 1200, "h": 526, "resize": "fit" }
1323 | }
1324 | }
1325 | ]
1326 | },
1327 | "extended_entities": {
1328 | "media": [
1329 | {
1330 | "id": 1038026693380898800,
1331 | "id_str": "1038026693380898817",
1332 | "indices": [105, 128],
1333 | "media_url": "http://pbs.twimg.com/media/DmfPxyZXgAEyqGD.jpg",
1334 | "media_url_https": "https://pbs.twimg.com/media/DmfPxyZXgAEyqGD.jpg",
1335 | "url": "https://t.co/hHTWpljKpp",
1336 | "display_url": "pic.twitter.com/hHTWpljKpp",
1337 | "expanded_url": "https://twitter.com/malfynnction/status/1038026699827564545/photo/1",
1338 | "type": "photo",
1339 | "sizes": {
1340 | "small": { "w": 680, "h": 298, "resize": "fit" },
1341 | "thumb": { "w": 150, "h": 150, "resize": "crop" },
1342 | "large": { "w": 2048, "h": 897, "resize": "fit" },
1343 | "medium": { "w": 1200, "h": 526, "resize": "fit" }
1344 | },
1345 | "ext_alt_text": "Letter from my health insurance, saying: “Sehr geehrter Herr Heintz, auf Ihren Antrag auf Kostenübernahme für eine geschlechtsangleichende Operation bei Transsexualität nehmen wir Bezug. Hinsichtlich der folgenden Maßnahmen sagen wir Ihnen die Kostenübernahne zu: 1. Mastektomie bds. 2. Hysterektomie 3. Adnektomie”"
1346 | }
1347 | ]
1348 | },
1349 | "source": "Twitter for iPhone",
1350 | "in_reply_to_status_id": 1014945233753256000,
1351 | "in_reply_to_status_id_str": "1014945233753255938",
1352 | "in_reply_to_user_id": 1865110807,
1353 | "in_reply_to_user_id_str": "1865110807",
1354 | "in_reply_to_screen_name": "malfynnction",
1355 | "user": {
1356 | "id": 1865110807,
1357 | "id_str": "1865110807",
1358 | "name": "φnn",
1359 | "screen_name": "malfynnction",
1360 | "location": "Berlin, Germany",
1361 | "description": "Fynn | 21 | he/him | does things with computers, gender, and other queer stuff | knows how to fold a fitted sheet | ava by @_morre_",
1362 | "url": null,
1363 | "entities": { "description": { "urls": [] } },
1364 | "protected": false,
1365 | "followers_count": 927,
1366 | "friends_count": 248,
1367 | "listed_count": 34,
1368 | "created_at": "Sat Sep 14 21:35:38 +0000 2013",
1369 | "favourites_count": 40125,
1370 | "utc_offset": null,
1371 | "time_zone": null,
1372 | "geo_enabled": true,
1373 | "verified": false,
1374 | "statuses_count": 38316,
1375 | "lang": "en-gb",
1376 | "contributors_enabled": false,
1377 | "is_translator": false,
1378 | "is_translation_enabled": false,
1379 | "profile_background_color": "000000",
1380 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme18/bg.gif",
1381 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme18/bg.gif",
1382 | "profile_background_tile": false,
1383 | "profile_image_url": "http://pbs.twimg.com/profile_images/1071082881831833601/uxR94Gp8_normal.jpg",
1384 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/1071082881831833601/uxR94Gp8_normal.jpg",
1385 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/1865110807/1496517525",
1386 | "profile_image_extensions_alt_text": null,
1387 | "profile_banner_extensions_alt_text": null,
1388 | "profile_link_color": "336699",
1389 | "profile_sidebar_border_color": "000000",
1390 | "profile_sidebar_fill_color": "000000",
1391 | "profile_text_color": "000000",
1392 | "profile_use_background_image": false,
1393 | "has_extended_profile": false,
1394 | "default_profile": false,
1395 | "default_profile_image": false,
1396 | "following": false,
1397 | "follow_request_sent": false,
1398 | "notifications": false,
1399 | "translator_type": "none"
1400 | },
1401 | "geo": null,
1402 | "coordinates": null,
1403 | "place": null,
1404 | "contributors": null,
1405 | "is_quote_status": false,
1406 | "retweet_count": 0,
1407 | "favorite_count": 53,
1408 | "favorited": false,
1409 | "retweeted": false,
1410 | "possibly_sensitive": false,
1411 | "possibly_sensitive_appealable": false,
1412 | "lang": "en"
1413 | },
1414 | "11": {
1415 | "created_at": "Sat Sep 29 10:43:03 +0000 2018",
1416 | "id": 1045987312516169700,
1417 | "id_str": "1045987312516169729",
1418 | "full_text": "Sorry, I've been asleep for a few days, but I'm back now \\o/",
1419 | "truncated": false,
1420 | "display_text_range": [0, 60],
1421 | "entities": {
1422 | "hashtags": [],
1423 | "symbols": [],
1424 | "user_mentions": [],
1425 | "urls": []
1426 | },
1427 | "source": "Twitter Web Client",
1428 | "in_reply_to_status_id": null,
1429 | "in_reply_to_status_id_str": null,
1430 | "in_reply_to_user_id": null,
1431 | "in_reply_to_user_id_str": null,
1432 | "in_reply_to_screen_name": null,
1433 | "user": {
1434 | "id": 968802481856794600,
1435 | "id_str": "968802481856794624",
1436 | "name": "Alt Text Reader",
1437 | "screen_name": "get_altText",
1438 | "location": "(If I'm broken, complain to @malfynnction)",
1439 | "description": "I read alt texts from images for you - just mention me in the reply to an image! (alt texts are a cool & accessible way to describe images - see pinned tweet)",
1440 | "url": "https://t.co/HVZ2T4ZpAW",
1441 | "entities": {
1442 | "url": {
1443 | "urls": [
1444 | {
1445 | "url": "https://t.co/HVZ2T4ZpAW",
1446 | "expanded_url": "https://github.com/malfynnction/AltText-Tweeter",
1447 | "display_url": "github.com/malfynnction/A…",
1448 | "indices": [0, 23]
1449 | }
1450 | ]
1451 | },
1452 | "description": { "urls": [] }
1453 | },
1454 | "protected": false,
1455 | "followers_count": 359,
1456 | "friends_count": 1,
1457 | "listed_count": 9,
1458 | "created_at": "Wed Feb 28 10:58:05 +0000 2018",
1459 | "favourites_count": 1,
1460 | "utc_offset": null,
1461 | "time_zone": null,
1462 | "geo_enabled": false,
1463 | "verified": false,
1464 | "statuses_count": 1159,
1465 | "lang": "en",
1466 | "contributors_enabled": false,
1467 | "is_translator": false,
1468 | "is_translation_enabled": false,
1469 | "profile_background_color": "F5F8FA",
1470 | "profile_background_image_url": null,
1471 | "profile_background_image_url_https": null,
1472 | "profile_background_tile": false,
1473 | "profile_image_url": "http://pbs.twimg.com/profile_images/968844589263151104/7GgGo_53_normal.jpg",
1474 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/968844589263151104/7GgGo_53_normal.jpg",
1475 | "profile_image_extensions_alt_text": null,
1476 | "profile_link_color": "1DA1F2",
1477 | "profile_sidebar_border_color": "C0DEED",
1478 | "profile_sidebar_fill_color": "DDEEF6",
1479 | "profile_text_color": "333333",
1480 | "profile_use_background_image": true,
1481 | "has_extended_profile": false,
1482 | "default_profile": true,
1483 | "default_profile_image": false,
1484 | "following": false,
1485 | "follow_request_sent": false,
1486 | "notifications": false,
1487 | "translator_type": "none"
1488 | },
1489 | "geo": null,
1490 | "coordinates": null,
1491 | "place": null,
1492 | "contributors": null,
1493 | "is_quote_status": false,
1494 | "retweet_count": 1,
1495 | "favorite_count": 3,
1496 | "favorited": false,
1497 | "retweeted": false,
1498 | "lang": "en"
1499 | },
1500 | "12": {
1501 | "created_at": "Mon Feb 18 10:26:22 +0000 2019",
1502 | "id": 1097442191264366600,
1503 | "id_str": "1097442191264366592",
1504 | "full_text": "@MalcolmMusic @pets4cats Rassismus als Abendunterhaltung zum Lachen u Niedlichfinden. 🤮",
1505 | "truncated": false,
1506 | "display_text_range": [25, 87],
1507 | "entities": {
1508 | "hashtags": [],
1509 | "symbols": [],
1510 | "user_mentions": [
1511 | {
1512 | "screen_name": "MalcolmMusic",
1513 | "name": "Malcolm Ohanwe",
1514 | "id": 341059687,
1515 | "id_str": "341059687",
1516 | "indices": [0, 13]
1517 | },
1518 | {
1519 | "screen_name": "pets4cats",
1520 | "name": "Happy Croc Inuidō 乾 道",
1521 | "id": 135250496,
1522 | "id_str": "135250496",
1523 | "indices": [14, 24]
1524 | }
1525 | ],
1526 | "urls": []
1527 | },
1528 | "source": "Twitter for iPad",
1529 | "in_reply_to_status_id": 1097438488696406000,
1530 | "in_reply_to_status_id_str": "1097438488696406017",
1531 | "in_reply_to_user_id": 341059687,
1532 | "in_reply_to_user_id_str": "341059687",
1533 | "in_reply_to_screen_name": "MalcolmMusic",
1534 | "user": {
1535 | "id": 839649983959818200,
1536 | "id_str": "839649983959818242",
1537 | "name": "Soup.",
1538 | "screen_name": "souplemur",
1539 | "location": "Berlin, Deutschland",
1540 | "description": "Kleener renitenter Homofürst aus der Hauptstadt.",
1541 | "url": null,
1542 | "entities": { "description": { "urls": [] } },
1543 | "protected": false,
1544 | "followers_count": 1294,
1545 | "friends_count": 732,
1546 | "listed_count": 21,
1547 | "created_at": "Thu Mar 09 01:32:10 +0000 2017",
1548 | "favourites_count": 65371,
1549 | "utc_offset": null,
1550 | "time_zone": null,
1551 | "geo_enabled": false,
1552 | "verified": false,
1553 | "statuses_count": 11520,
1554 | "lang": "de",
1555 | "contributors_enabled": false,
1556 | "is_translator": false,
1557 | "is_translation_enabled": false,
1558 | "profile_background_color": "000000",
1559 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
1560 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
1561 | "profile_background_tile": false,
1562 | "profile_image_url": "http://pbs.twimg.com/profile_images/1011889999619461121/_qY7bdb7_normal.jpg",
1563 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/1011889999619461121/_qY7bdb7_normal.jpg",
1564 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/839649983959818242/1489684295",
1565 | "profile_image_extensions_alt_text": null,
1566 | "profile_banner_extensions_alt_text": null,
1567 | "profile_link_color": "FAB81E",
1568 | "profile_sidebar_border_color": "000000",
1569 | "profile_sidebar_fill_color": "000000",
1570 | "profile_text_color": "000000",
1571 | "profile_use_background_image": false,
1572 | "has_extended_profile": true,
1573 | "default_profile": false,
1574 | "default_profile_image": false,
1575 | "following": false,
1576 | "follow_request_sent": false,
1577 | "notifications": false,
1578 | "translator_type": "none"
1579 | },
1580 | "geo": null,
1581 | "coordinates": null,
1582 | "place": null,
1583 | "contributors": null,
1584 | "is_quote_status": false,
1585 | "retweet_count": 4,
1586 | "favorite_count": 65,
1587 | "favorited": false,
1588 | "retweeted": false,
1589 | "lang": "de"
1590 | },
1591 | "13": {
1592 | "created_at": "Wed Mar 06 19:33:33 +0000 2019",
1593 | "id": 1103378101420081200,
1594 | "id_str": "1103378101420081153",
1595 | "full_text": "@ryanlcooper @get_altText",
1596 | "truncated": false,
1597 | "display_text_range": [13, 25],
1598 | "entities": {
1599 | "hashtags": [],
1600 | "symbols": [],
1601 | "user_mentions": [
1602 | {
1603 | "screen_name": "ryanlcooper",
1604 | "name": "ryan cooper",
1605 | "id": 214120461,
1606 | "id_str": "214120461",
1607 | "indices": [0, 12]
1608 | },
1609 | {
1610 | "screen_name": "get_altText",
1611 | "name": "Alt Text Reader",
1612 | "id": 968802481856794600,
1613 | "id_str": "968802481856794624",
1614 | "indices": [13, 25]
1615 | }
1616 | ],
1617 | "urls": []
1618 | },
1619 | "source": "Twitter for iPhone",
1620 | "in_reply_to_status_id": 1102617669537284100,
1621 | "in_reply_to_status_id_str": "1102617669537284098",
1622 | "in_reply_to_user_id": 214120461,
1623 | "in_reply_to_user_id_str": "214120461",
1624 | "in_reply_to_screen_name": "ryanlcooper",
1625 | "user": {
1626 | "id": 3058863267,
1627 | "id_str": "3058863267",
1628 | "name": "Kit ♿️",
1629 | "screen_name": "solitaryrainbow",
1630 | "location": "United Kingdom",
1631 | "description": "they/them. queer AF. disabled/autistic/ADHD. wheelchair liberated. parent of three small humans and many cats. rapidly collecting tattoos.",
1632 | "url": null,
1633 | "entities": { "description": { "urls": [] } },
1634 | "protected": false,
1635 | "followers_count": 480,
1636 | "friends_count": 915,
1637 | "listed_count": 7,
1638 | "created_at": "Tue Feb 24 13:11:51 +0000 2015",
1639 | "favourites_count": 18773,
1640 | "utc_offset": null,
1641 | "time_zone": null,
1642 | "geo_enabled": true,
1643 | "verified": false,
1644 | "statuses_count": 6055,
1645 | "lang": "en",
1646 | "contributors_enabled": false,
1647 | "is_translator": false,
1648 | "is_translation_enabled": false,
1649 | "profile_background_color": "000000",
1650 | "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
1651 | "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
1652 | "profile_background_tile": false,
1653 | "profile_image_url": "http://pbs.twimg.com/profile_images/967836568349216769/8ujyFi8K_normal.jpg",
1654 | "profile_image_url_https": "https://pbs.twimg.com/profile_images/967836568349216769/8ujyFi8K_normal.jpg",
1655 | "profile_banner_url": "https://pbs.twimg.com/profile_banners/3058863267/1447185535",
1656 | "profile_image_extensions_alt_text": null,
1657 | "profile_banner_extensions_alt_text": null,
1658 | "profile_link_color": "981CEB",
1659 | "profile_sidebar_border_color": "000000",
1660 | "profile_sidebar_fill_color": "000000",
1661 | "profile_text_color": "000000",
1662 | "profile_use_background_image": false,
1663 | "has_extended_profile": false,
1664 | "default_profile": false,
1665 | "default_profile_image": false,
1666 | "following": false,
1667 | "follow_request_sent": false,
1668 | "notifications": false,
1669 | "translator_type": "none"
1670 | },
1671 | "geo": null,
1672 | "coordinates": null,
1673 | "place": null,
1674 | "contributors": null,
1675 | "is_quote_status": false,
1676 | "retweet_count": 0,
1677 | "favorite_count": 0,
1678 | "favorited": false,
1679 | "retweeted": false,
1680 | "lang": "und"
1681 | }
1682 | }
1683 |
--------------------------------------------------------------------------------
/test/censor.js:
--------------------------------------------------------------------------------
1 | const test = require('ava')
2 | const censor = require('../lib/censor')
3 |
4 | test("it returns the original text when there's nothing to censor", (t) => {
5 | t.is(
6 | censor('No reason to change anything about me!'),
7 | 'No reason to change anything about me!'
8 | )
9 | })
10 |
11 | test("it ignores the word when it's part of another word", (t) => {
12 | t.is(censor('Medieval'), 'Medieval')
13 | })
14 |
15 | test('it replaces slurs & other ban-worthy words with a censored version', (t) => {
16 | t.is(
17 | censor('This is kill a normal sentence, nothing die to see kill here.'),
18 | "This is k*ll a normal sentence, nothing d*e to see k*ll here.\n\n(Note from the bot: I had to censor a part of the description to avoid suspension from twitter, I'm sorry.)"
19 | )
20 | })
21 |
--------------------------------------------------------------------------------
/test/get-reply-text.js:
--------------------------------------------------------------------------------
1 | const test = require('ava')
2 | const testTweets = require('../test-tweets.json')
3 | const getReplyText = require('../lib/get-reply-text')
4 |
5 | const noAltText = "There is no alt text for this image, I'm sorry."
6 | const video =
7 | "This is a video. Unfortunately, twitter doesn't allow to add alt texts for videos yet."
8 |
9 | test('classic flow, with alt text', async (t) => {
10 | const reply = getReplyText(testTweets[1])
11 | t.is(
12 | await reply,
13 | '@SnoringDoggo Athena the fluffy white and brown cat looks up innocently in front of a plush'
14 | )
15 | })
16 |
17 | test('classic flow, no alt text', async (t) => {
18 | const reply = getReplyText(testTweets[2])
19 | t.is(await reply, `@solitaryrainbow ${noAltText}`)
20 | })
21 |
22 | test('triggering = original, no alt text', async (t) => {
23 | const reply = getReplyText(testTweets[3])
24 | t.is(await reply, `@womensart1 ${noAltText}`)
25 | })
26 |
27 | test('triggering = original, with alt text', async (t) => {
28 | const reply = getReplyText(testTweets[4])
29 | t.is(
30 | await reply,
31 | '@foxeen Winzige runde Tropfen entlang den fast unsichtbaren Fäden eines Spinnennetzes in Nahaufnahme - manche sind ganz scharf, manche unscharf, aber alle zusammen wirken wie feinste Perlen-Spitze, meisterlich geklöppelt.'
32 | )
33 | })
34 |
35 | test('image in quote, alt text', async (t) => {
36 | const reply = getReplyText(testTweets[5])
37 | t.is(
38 | await reply,
39 | '@SehrysFlausch a tabby cat (@skyescats #OhMyOllie) sits on a chair, with its head looking up over a kitchen table. on the table is an unfinished jigsaw puzzle, the picture also featuring two tabby cats.'
40 | )
41 | })
42 |
43 | test('image in quote, no alt text', async (t) => {
44 | const reply = getReplyText(testTweets[6])
45 | t.is(await reply, `@_cumasyouare_ ${noAltText}`)
46 | })
47 |
48 | test('no quote, no reply, no image', async (t) => {
49 | const reply = getReplyText(testTweets[7])
50 | t.is(await reply, undefined)
51 | })
52 |
53 | test('reply, but no image anywhere', async (t) => {
54 | const reply = getReplyText(testTweets[8])
55 | t.is(await reply, undefined)
56 | })
57 |
58 | test('quote, but no image anywhere', async (t) => {
59 | const reply = getReplyText(testTweets[9])
60 | t.is(await reply, undefined)
61 | })
62 |
63 | test('image in triggering as well as original', async (t) => {
64 | const reply = getReplyText(testTweets[10])
65 | t.is(
66 | await reply,
67 | '@malfynnction My new ID, stating that my first name is Fynn and my second name is Julius, everything else - except the photo - is blacked out'
68 | )
69 | })
70 |
71 | test('tweet by bot itself', async (t) => {
72 | const reply = getReplyText(testTweets[11])
73 | t.is(await reply, undefined)
74 | })
75 |
76 | test('video', async (t) => {
77 | const reply = getReplyText(testTweets[12])
78 | t.is(await reply, `@souplemur ${video}`)
79 | })
80 |
81 | test('multiple images', async (t) => {
82 | const reply = getReplyText(testTweets[13])
83 | t.is(
84 | await reply,
85 | `@solitaryrainbow 1. Picture: ${noAltText}\n2. Picture: ${noAltText}\n3. Picture: ${noAltText}\n`
86 | )
87 | })
88 |
--------------------------------------------------------------------------------