0
# Direct Messages
1
2
Private messaging functionality for sending and receiving direct messages.
3
4
## Core Direct Message Operations
5
6
### Sending Direct Messages
7
8
Send private messages to other Twitter users.
9
10
```java { .api }
11
interface DirectMessagesResources {
12
/**
13
* Send direct message by user ID
14
* @param userId Recipient user ID
15
* @param text Message text (max 10,000 characters)
16
* @return Sent direct message
17
*/
18
DirectMessage sendDirectMessage(long userId, String text) throws TwitterException;
19
20
/**
21
* Send direct message by screen name
22
* @param screenName Recipient screen name (without @)
23
* @param text Message text (max 10,000 characters)
24
* @return Sent direct message
25
*/
26
DirectMessage sendDirectMessage(String screenName, String text) throws TwitterException;
27
28
/**
29
* Send direct message with quick reply options
30
* @param userId Recipient user ID
31
* @param text Message text
32
* @param quickReplies Quick reply options
33
* @return Sent direct message
34
*/
35
DirectMessage sendDirectMessage(long userId, String text, QuickReply... quickReplies) throws TwitterException;
36
37
/**
38
* Send direct message as quick reply response
39
* @param userId Recipient user ID
40
* @param text Message text
41
* @param quickReplyResponse Quick reply response metadata
42
* @return Sent direct message
43
*/
44
DirectMessage sendDirectMessage(long userId, String text, String quickReplyResponse) throws TwitterException;
45
46
/**
47
* Send direct message with media attachment
48
* @param userId Recipient user ID
49
* @param text Message text
50
* @param mediaId Media ID from uploadMedia() call
51
* @return Sent direct message
52
*/
53
DirectMessage sendDirectMessage(long userId, String text, long mediaId) throws TwitterException;
54
}
55
```
56
57
**Usage Examples:**
58
59
```java
60
TwitterV1 v1 = twitter.v1();
61
62
// Send simple text message
63
DirectMessage dm = v1.directMessages().sendDirectMessage("recipient_user",
64
"Hello! This is a direct message.");
65
66
// Send message by user ID
67
DirectMessage dmById = v1.directMessages().sendDirectMessage(12345L,
68
"Hello via user ID!");
69
70
// Send message with media
71
File image = new File("attachment.jpg");
72
UploadedMedia media = v1.tweets().uploadMedia(image);
73
DirectMessage dmWithMedia = v1.directMessages().sendDirectMessage(12345L,
74
"Check out this image!", media.getMediaId());
75
76
// Send message with quick reply options
77
QuickReply option1 = QuickReply.of("yes", "Yes");
78
QuickReply option2 = QuickReply.of("no", "No");
79
DirectMessage dmWithOptions = v1.directMessages().sendDirectMessage(12345L,
80
"Do you like Twitter4J?", option1, option2);
81
```
82
83
### Retrieving Direct Messages
84
85
Get direct message conversations and individual messages.
86
87
```java { .api }
88
interface DirectMessagesResources {
89
/**
90
* Get direct messages (both sent and received)
91
* @param count Number of messages to retrieve (max 50)
92
* @return List of direct messages
93
*/
94
DirectMessageList getDirectMessages(int count) throws TwitterException;
95
96
/**
97
* Get direct messages with cursor pagination
98
* @param count Number of messages to retrieve (max 50)
99
* @param cursor Pagination cursor
100
* @return List of direct messages
101
*/
102
DirectMessageList getDirectMessages(int count, String cursor) throws TwitterException;
103
104
/**
105
* Get specific direct message by ID
106
* @param id Direct message ID
107
* @return Direct message
108
*/
109
DirectMessage showDirectMessage(long id) throws TwitterException;
110
}
111
```
112
113
**Usage Examples:**
114
115
```java
116
// Get recent direct messages
117
DirectMessageList messages = v1.directMessages().getDirectMessages(20);
118
for (DirectMessage dm : messages.getList()) {
119
System.out.println("From: " + dm.getSenderScreenName());
120
System.out.println("Text: " + dm.getText());
121
System.out.println("Date: " + dm.getCreatedAt());
122
}
123
124
// Paginate through all messages
125
String cursor = null;
126
do {
127
DirectMessageList batch = v1.directMessages().getDirectMessages(50, cursor);
128
for (DirectMessage dm : batch.getList()) {
129
processDirectMessage(dm);
130
}
131
cursor = batch.getNextCursor();
132
} while (cursor != null);
133
134
// Get specific message
135
DirectMessage specificDM = v1.directMessages().showDirectMessage(987654321L);
136
```
137
138
### Deleting Direct Messages
139
140
Delete direct messages from conversations.
141
142
```java { .api }
143
interface DirectMessagesResources {
144
/**
145
* Delete a direct message
146
* @param id Direct message ID to delete
147
*/
148
void destroyDirectMessage(long id) throws TwitterException;
149
}
150
```
151
152
**Usage Example:**
153
154
```java
155
// Delete a direct message
156
v1.directMessages().destroyDirectMessage(987654321L);
157
System.out.println("Direct message deleted");
158
```
159
160
## Media in Direct Messages
161
162
### Retrieving Media Content
163
164
Download media attachments from direct messages.
165
166
```java { .api }
167
interface DirectMessagesResources {
168
/**
169
* Get direct message image as input stream
170
* @param url Media URL from DirectMessage
171
* @return InputStream of image data
172
*/
173
InputStream getDMImageAsStream(String url) throws TwitterException;
174
}
175
```
176
177
**Usage Example:**
178
179
```java
180
DirectMessage dm = v1.directMessages().showDirectMessage(messageId);
181
182
// Check if message has media
183
if (dm.getMediaEntities().length > 0) {
184
MediaEntity media = dm.getMediaEntities()[0];
185
186
// Download the media
187
try (InputStream mediaStream = v1.directMessages().getDMImageAsStream(media.getMediaURL())) {
188
// Save to file
189
Files.copy(mediaStream, Paths.get("dm_image.jpg"));
190
}
191
}
192
```
193
194
## Quick Replies
195
196
### Quick Reply Options
197
198
Add interactive quick reply buttons to direct messages.
199
200
```java { .api }
201
class QuickReply {
202
/**
203
* Create quick reply option
204
* @param value Value returned when selected
205
* @param label Display text for button
206
* @return QuickReply option
207
*/
208
static QuickReply of(String value, String label);
209
210
/**
211
* Create quick reply with description
212
* @param value Value returned when selected
213
* @param label Display text for button
214
* @param description Additional description text
215
* @return QuickReply option
216
*/
217
static QuickReply of(String value, String label, String description);
218
219
/**
220
* Create quick reply with media
221
* @param value Value returned when selected
222
* @param label Display text for button
223
* @param mediaUrl URL of media to display
224
* @return QuickReply option
225
*/
226
static QuickReply withMedia(String value, String label, String mediaUrl);
227
228
/**
229
* Get option value
230
*/
231
String getValue();
232
233
/**
234
* Get display label
235
*/
236
String getLabel();
237
238
/**
239
* Get description text
240
*/
241
String getDescription();
242
243
/**
244
* Get media URL
245
*/
246
String getMediaUrl();
247
}
248
```
249
250
**Quick Reply Examples:**
251
252
```java
253
// Simple yes/no options
254
QuickReply yes = QuickReply.of("confirm_yes", "Yes");
255
QuickReply no = QuickReply.of("confirm_no", "No");
256
257
v1.directMessages().sendDirectMessage(userId,
258
"Would you like to receive notifications?", yes, no);
259
260
// Options with descriptions
261
QuickReply basic = QuickReply.of("plan_basic", "Basic", "$9.99/month");
262
QuickReply premium = QuickReply.of("plan_premium", "Premium", "$19.99/month");
263
QuickReply enterprise = QuickReply.of("plan_enterprise", "Enterprise", "Contact sales");
264
265
v1.directMessages().sendDirectMessage(userId,
266
"Choose your plan:", basic, premium, enterprise);
267
268
// Options with media
269
QuickReply red = QuickReply.withMedia("color_red", "Red", "https://example.com/red.png");
270
QuickReply blue = QuickReply.withMedia("color_blue", "Blue", "https://example.com/blue.png");
271
272
v1.directMessages().sendDirectMessage(userId,
273
"Pick your favorite color:", red, blue);
274
```
275
276
## Direct Message Data Model
277
278
### DirectMessage Interface
279
280
Complete direct message data structure.
281
282
```java { .api }
283
interface DirectMessage extends TwitterResponse {
284
/**
285
* Message unique identifier
286
*/
287
long getId();
288
289
/**
290
* Message text content
291
*/
292
String getText();
293
294
/**
295
* Sender user ID
296
*/
297
long getSenderId();
298
299
/**
300
* Sender screen name
301
*/
302
String getSenderScreenName();
303
304
/**
305
* Recipient user ID
306
*/
307
long getRecipientId();
308
309
/**
310
* Recipient screen name
311
*/
312
String getRecipientScreenName();
313
314
/**
315
* Message creation timestamp
316
*/
317
LocalDateTime getCreatedAt();
318
319
/**
320
* Quick reply options attached to message
321
*/
322
QuickReply[] getQuickReplies();
323
324
/**
325
* Quick reply response metadata (if this is a response)
326
*/
327
String getQuickReplyResponse();
328
329
/**
330
* URL entities in message text
331
*/
332
URLEntity[] getURLEntities();
333
334
/**
335
* User mention entities in message text
336
*/
337
UserMentionEntity[] getUserMentionEntities();
338
339
/**
340
* Hashtag entities in message text
341
*/
342
HashtagEntity[] getHashtagEntities();
343
344
/**
345
* Media entities (images, videos) attached to message
346
*/
347
MediaEntity[] getMediaEntities();
348
349
/**
350
* Symbol entities (cashtags) in message text
351
*/
352
SymbolEntity[] getSymbolEntities();
353
}
354
```
355
356
### DirectMessageList
357
358
Paginated list of direct messages.
359
360
```java { .api }
361
interface DirectMessageList extends TwitterResponse {
362
/**
363
* List of direct messages
364
*/
365
List<DirectMessage> getList();
366
367
/**
368
* Next cursor for pagination (null if no more)
369
*/
370
String getNextCursor();
371
372
/**
373
* Previous cursor for pagination
374
*/
375
String getPreviousCursor();
376
}
377
```
378
379
## Direct Message Management Patterns
380
381
### Conversation Threading
382
383
```java
384
public class DMConversationManager {
385
private final TwitterV1 v1;
386
387
public Map<String, List<DirectMessage>> getConversationsByUser() throws TwitterException {
388
DirectMessageList allMessages = v1.directMessages().getDirectMessages(50);
389
390
return allMessages.getList().stream()
391
.collect(Collectors.groupingBy(
392
dm -> getConversationKey(dm),
393
Collectors.toList()
394
));
395
}
396
397
private String getConversationKey(DirectMessage dm) {
398
// Create unique key for conversation between two users
399
long currentUserId = getCurrentUserId(); // Your implementation
400
long otherUserId = (dm.getSenderId() == currentUserId) ?
401
dm.getRecipientId() : dm.getSenderId();
402
403
return Math.min(currentUserId, otherUserId) + "_" +
404
Math.max(currentUserId, otherUserId);
405
}
406
}
407
```
408
409
### Auto-Response System
410
411
```java
412
public class DMAutoResponder {
413
private final TwitterV1 v1;
414
private final Map<String, String> responses;
415
416
public DMAutoResponder(TwitterV1 v1) {
417
this.v1 = v1;
418
this.responses = Map.of(
419
"help", "Here are the available commands: help, status, info",
420
"status", "All systems operational!",
421
"info", "This is an automated response system."
422
);
423
}
424
425
public void processQuickReplyResponse(DirectMessage dm) throws TwitterException {
426
String response = dm.getQuickReplyResponse();
427
428
if (response != null && responses.containsKey(response)) {
429
v1.directMessages().sendDirectMessage(
430
dm.getSenderId(),
431
responses.get(response)
432
);
433
}
434
}
435
436
public void handleTextMessage(DirectMessage dm) throws TwitterException {
437
String text = dm.getText().toLowerCase().trim();
438
439
if (responses.containsKey(text)) {
440
v1.directMessages().sendDirectMessage(
441
dm.getSenderId(),
442
responses.get(text)
443
);
444
} else {
445
// Send help with quick reply options
446
QuickReply help = QuickReply.of("help", "Help");
447
QuickReply status = QuickReply.of("status", "Status");
448
449
v1.directMessages().sendDirectMessage(
450
dm.getSenderId(),
451
"I didn't understand that. How can I help?",
452
help, status
453
);
454
}
455
}
456
}
457
```
458
459
### Bulk Message Operations
460
461
```java
462
public class BulkDMOperations {
463
private final TwitterV1 v1;
464
465
public void sendBulkMessage(List<Long> userIds, String message) throws TwitterException {
466
for (long userId : userIds) {
467
try {
468
v1.directMessages().sendDirectMessage(userId, message);
469
470
// Rate limiting - DM endpoint allows 1000 requests per 24 hours
471
Thread.sleep(100); // Small delay between messages
472
473
} catch (TwitterException e) {
474
if (e.getStatusCode() == 403) {
475
System.err.println("Cannot send DM to user " + userId + ": " + e.getMessage());
476
} else {
477
throw e; // Re-throw other errors
478
}
479
} catch (InterruptedException e) {
480
Thread.currentThread().interrupt();
481
break;
482
}
483
}
484
}
485
486
public void deleteAllMessagesFromUser(long userId) throws TwitterException {
487
DirectMessageList messages = v1.directMessages().getDirectMessages(50);
488
489
List<DirectMessage> toDelete = messages.getList().stream()
490
.filter(dm -> dm.getSenderId() == userId || dm.getRecipientId() == userId)
491
.collect(Collectors.toList());
492
493
for (DirectMessage dm : toDelete) {
494
try {
495
v1.directMessages().destroyDirectMessage(dm.getId());
496
Thread.sleep(100); // Rate limiting
497
} catch (TwitterException e) {
498
System.err.println("Failed to delete message " + dm.getId() + ": " + e.getMessage());
499
} catch (InterruptedException e) {
500
Thread.currentThread().interrupt();
501
break;
502
}
503
}
504
}
505
}
506
```
507
508
## Error Handling
509
510
Direct message operations can fail for various reasons:
511
512
```java
513
try {
514
DirectMessage dm = v1.directMessages().sendDirectMessage("user", "Hello!");
515
} catch (TwitterException e) {
516
switch (e.getStatusCode()) {
517
case 403:
518
if (e.getErrorCode() == 150) {
519
System.out.println("Cannot send DM: user doesn't follow you");
520
} else if (e.getErrorCode() == 151) {
521
System.out.println("Cannot send DM: user has disabled DMs");
522
} else {
523
System.out.println("Forbidden: " + e.getMessage());
524
}
525
break;
526
case 404:
527
System.out.println("User not found or account suspended");
528
break;
529
case 429:
530
System.out.println("Rate limit exceeded - DM limit reached");
531
break;
532
default:
533
System.out.println("Error sending DM: " + e.getMessage());
534
}
535
}
536
```