""recipient_id"": ""12345""
},
""message_data"": {
- ""text"": ""hogehoge""
+ ""text"": ""hogehoge"",
+ ""attachment"": {
+ ""type"": ""media"",
+ ""media"": {
+ ""id"": ""67890""
+ }
+ }
}
}
}
twitterApi.apiConnection = mock.Object;
- await twitterApi.DirectMessagesEventsNew(recipientId: 12345L, text: "hogehoge")
+ await twitterApi.DirectMessagesEventsNew(recipientId: 12345L, text: "hogehoge", mediaId: 67890L)
.ConfigureAwait(false);
mock.VerifyAll();
{ "command", "INIT" },
{ "total_bytes", "123456" },
{ "media_type", "image/png" },
+ { "media_category", "dm_image" },
})
)
.ReturnsAsync(LazyJson.Create(new TwitterUploadMediaInit()));
twitterApi.apiConnection = mock.Object;
- await twitterApi.MediaUploadInit(totalBytes: 123456L, mediaType: "image/png")
+ await twitterApi.MediaUploadInit(totalBytes: 123456L, mediaType: "image/png", mediaCategory: "dm_image")
.IgnoreResponse()
.ConfigureAwait(false);
return this.apiConnection.PostLazyAsync<TwitterDirectMessage>(endpoint, param);
}
- public Task DirectMessagesEventsNew(long recipientId, string text)
+ public Task DirectMessagesEventsNew(long recipientId, string text, long? mediaId = null)
{
var endpoint = new Uri("direct_messages/events/new.json", UriKind.Relative);
+ var attachment = "";
+ if (mediaId != null)
+ {
+ attachment = "," + $@"
+ ""attachment"": {{
+ ""type"": ""media"",
+ ""media"": {{
+ ""id"": ""{EscapeJsonString(mediaId.ToString())}""
+ }}
+ }}";
+ }
+
var json = $@"{{
""event"": {{
""type"": ""message_create"",
""recipient_id"": ""{EscapeJsonString(recipientId.ToString())}""
}},
""message_data"": {{
- ""text"": ""{EscapeJsonString(text)}""
+ ""text"": ""{EscapeJsonString(text)}""{attachment}
}}
}}
}}
return this.apiConnection.GetAsync<TwitterConfiguration>(endpoint, null, "/help/configuration");
}
- public Task<LazyJson<TwitterUploadMediaInit>> MediaUploadInit(long totalBytes, string mediaType)
+ public Task<LazyJson<TwitterUploadMediaInit>> MediaUploadInit(long totalBytes, string mediaType, string mediaCategory = null)
{
var endpoint = new Uri("https://upload.twitter.com/1.1/media/upload.json");
var param = new Dictionary<string, string>
["media_type"] = mediaType,
};
+ if (mediaCategory != null)
+ param["media_category"] = mediaCategory;
+
return this.apiConnection.PostLazyAsync<TwitterUploadMediaInit>(endpoint, param);
}
throw new ArgumentException("Err:Media not found.");
}
- var uploadTasks = from m in mediaItems
- select this.UploadMediaItem(m);
+ long[] mediaIds;
- var mediaIds = await Task.WhenAll(uploadTasks)
- .ConfigureAwait(false);
+ if (Twitter.DMSendTextRegex.IsMatch(postParams.Text))
+ mediaIds = new[] { await this.UploadMediaForDM(mediaItems).ConfigureAwait(false) };
+ else
+ mediaIds = await this.UploadMediaForTweet(mediaItems).ConfigureAwait(false);
postParams.MediaIds = mediaIds;
public void UpdateTwitterConfiguration(TwitterConfiguration config)
=> this.twitterConfig = config;
- private async Task<long> UploadMediaItem(IMediaItem mediaItem)
+ private async Task<long[]> UploadMediaForTweet(IMediaItem[] mediaItems)
+ {
+ var uploadTasks = from m in mediaItems
+ select this.UploadMediaItem(m, mediaCategory: null);
+
+ var mediaIds = await Task.WhenAll(uploadTasks)
+ .ConfigureAwait(false);
+
+ return mediaIds;
+ }
+
+ private async Task<long> UploadMediaForDM(IMediaItem[] mediaItems)
+ {
+ if (mediaItems.Length > 1)
+ throw new InvalidOperationException("Err:Can't attach multiple media to DM.");
+
+ var mediaItem = mediaItems[0];
+
+ string mediaCategory;
+ switch (mediaItem.Extension)
+ {
+ case ".gif":
+ mediaCategory = "dm_gif";
+ break;
+ default:
+ mediaCategory = "dm_image";
+ break;
+ }
+
+ var mediaId = await this.UploadMediaItem(mediaItems[0], mediaCategory)
+ .ConfigureAwait(false);
+
+ return mediaId;
+ }
+
+ private async Task<long> UploadMediaItem(IMediaItem mediaItem, string mediaCategory)
{
- async Task<long> UploadInternal(IMediaItem media)
+ async Task<long> UploadInternal(IMediaItem media, string category)
{
- var mediaId = await this.tw.UploadMedia(media)
+ var mediaId = await this.tw.UploadMedia(media, category)
.ConfigureAwait(false);
if (!string.IsNullOrEmpty(media.AltText))
using (var newMediaItem = new MemoryImageMediaItem(newImage))
{
newMediaItem.AltText = mediaItem.AltText;
- return await UploadInternal(newMediaItem);
+ return await UploadInternal(newMediaItem, mediaCategory);
}
}
else
{
- return await UploadInternal(mediaItem);
+ return await UploadInternal(mediaItem, mediaCategory);
}
}
}
更新履歴
==== Ver 1.4.2-dev(xxxx/xx/xx)
+ * NEW: 画像を添付したDMの送信に対応しました
* NEW: システムのタイムゾーンの変更を検知して、ツイートの投稿日時などの表示を新しいタイムゾーンに同期します
* NEW: 5月中旬に予定されている引用ツイートに関する Twitter API の仕様変更に対応
* NEW: リプライ送信時にリプライ以外何も入力されていない状態であった場合は警告のダイアログを表示します
if (Twitter.DMSendTextRegex.IsMatch(param.Text))
{
- await this.SendDirectMessage(param.Text)
+ var mediaId = param.MediaIds != null && param.MediaIds.Any() ? param.MediaIds[0] : (long?)null;
+
+ await this.SendDirectMessage(param.Text, mediaId)
.ConfigureAwait(false);
return;
}
this.previousStatusId = status.Id;
}
- public async Task<long> UploadMedia(IMediaItem item)
+ public async Task<long> UploadMedia(IMediaItem item, string mediaCategory = null)
{
this.CheckAccountState();
break;
}
- var initResponse = await this.Api.MediaUploadInit(item.Size, mediaType)
+ var initResponse = await this.Api.MediaUploadInit(item.Size, mediaType, mediaCategory)
.ConfigureAwait(false);
var initMedia = await initResponse.LoadJsonAsync()
return media.MediaId;
}
- public async Task SendDirectMessage(string postStr)
+ public async Task SendDirectMessage(string postStr, long? mediaId = null)
{
this.CheckAccountState();
this.CheckAccessLevel(TwitterApiAccessLevel.ReadWriteAndDirectMessage);
var recipient = await this.Api.UsersShow(recipientName)
.ConfigureAwait(false);
- await this.Api.DirectMessagesEventsNew(recipient.Id, body)
+ await this.Api.DirectMessagesEventsNew(recipient.Id, body, mediaId)
.ConfigureAwait(false);
}