From 69bdd06df2ad8c197be7c1ecf9bfa167a00600ee Mon Sep 17 00:00:00 2001 From: Kimura Youichi Date: Mon, 5 May 2014 19:53:25 +0900 Subject: [PATCH] =?utf8?q?TwitterDataModel.Entity=20=E9=96=A2=E9=80=A3?= =?utf8?q?=E3=81=AE=E3=82=AF=E3=83=A9=E3=82=B9=E3=82=92=20TwitterEntity=20?= =?utf8?q?=E3=81=AB=E7=A7=BB=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- OpenTween.Tests/TweenMainTest.cs | 8 +- OpenTween.Tests/TweetFormatterTest.cs | 46 +++++------ OpenTween/Api/TwitterDataModel.cs | 70 +--------------- OpenTween/Api/TwitterEntity.cs | 148 ++++++++++++++++++++++++++++++++++ OpenTween/OpenTween.csproj | 1 + OpenTween/TweetFormatter.cs | 53 ++++++------ OpenTween/Twitter.cs | 10 +-- 7 files changed, 207 insertions(+), 129 deletions(-) create mode 100644 OpenTween/Api/TwitterEntity.cs diff --git a/OpenTween.Tests/TweenMainTest.cs b/OpenTween.Tests/TweenMainTest.cs index e350e0a5..682772f5 100644 --- a/OpenTween.Tests/TweenMainTest.cs +++ b/OpenTween.Tests/TweenMainTest.cs @@ -137,21 +137,21 @@ namespace OpenTween // TweetFormatterでHTMLに整形 → CreateRetweetUnofficialで復元 までの動作が正しく行えているか var text = "#てすと @TwitterAPI \n http://t.co/KYi7vMZzRt"; - var entities = new TwitterDataModel.Entity[] + var entities = new TwitterEntity[] { - new TwitterDataModel.Hashtags + new TwitterEntityHashtag { Indices = new[] { 0, 4 }, Text = "てすと", }, - new TwitterDataModel.UserMentions + new TwitterEntityMention { Indices = new[] { 5, 16 }, Id = 6253282L, Name = "Twitter API", ScreenName = "twitterapi", }, - new TwitterDataModel.Urls + new TwitterEntityUrl { Indices = new[] { 19, 41 }, DisplayUrl = "twitter.com", diff --git a/OpenTween.Tests/TweetFormatterTest.cs b/OpenTween.Tests/TweetFormatterTest.cs index 4f3349bb..b09dd3f9 100644 --- a/OpenTween.Tests/TweetFormatterTest.cs +++ b/OpenTween.Tests/TweetFormatterTest.cs @@ -37,7 +37,7 @@ namespace OpenTween var text = "http://t.co/KYi7vMZzRt"; var entities = new[] { - new TwitterDataModel.Urls + new TwitterEntityUrl { Indices = new[] { 0, 22 }, DisplayUrl = "twitter.com", @@ -56,7 +56,7 @@ namespace OpenTween var text = "#OpenTween"; var entities = new[] { - new TwitterDataModel.Hashtags + new TwitterEntityHashtag { Indices = new[] { 0, 10 }, Text = "OpenTween", @@ -73,7 +73,7 @@ namespace OpenTween var text = "@TwitterAPI"; var entities = new[] { - new TwitterDataModel.UserMentions + new TwitterEntityMention { Indices = new[] { 0, 11 }, Id = 6253282L, @@ -92,15 +92,15 @@ namespace OpenTween var text = "http://t.co/h5dCr4ftN4"; var entities = new[] { - new TwitterDataModel.Media + new TwitterEntityMedia { Indices = new[] { 0, 22 }, - Sizes = new TwitterDataModel.Sizes + Sizes = new TwitterMediaSizes { - Large = new TwitterDataModel.SizeElement { Resize = "fit", h = 329, w = 1024 }, - Medium = new TwitterDataModel.SizeElement { Resize = "fit", h = 204, w = 600 }, - Small = new TwitterDataModel.SizeElement { Resize = "fit", h = 116, w = 340 }, - Thumb = new TwitterDataModel.SizeElement { Resize = "crop", h = 150, w = 150 }, + Large = new TwitterMediaSizes.Size { Resize = "fit", Height = 329, Width = 1024 }, + Medium = new TwitterMediaSizes.Size { Resize = "fit", Height = 204, Width = 600 }, + Small = new TwitterMediaSizes.Size { Resize = "fit", Height = 116, Width = 340 }, + Thumb = new TwitterMediaSizes.Size { Resize = "crop", Height = 150, Width = 150 }, }, Type = "photo", Id = 426404550379986940L, @@ -120,7 +120,7 @@ namespace OpenTween public void AutoLinkHtml_EntityNullTest() { var text = "てすとてすとー"; - TwitterDataModel.Entities entities = null; + TwitterEntities entities = null; var expected = "てすとてすとー"; Assert.Equal(expected, TweetFormatter.AutoLinkHtml(text, entities)); @@ -130,7 +130,7 @@ namespace OpenTween public void AutoLinkHtml_EntityNullTest2() { var text = "てすとてすとー"; - TwitterDataModel.Entities entities = new TwitterDataModel.Entities + TwitterEntities entities = new TwitterEntities { Urls = null, Hashtags = null, @@ -146,7 +146,7 @@ namespace OpenTween public void AutoLinkHtml_EntityNullTest3() { var text = "てすとてすとー"; - IEnumerable entities = null; + IEnumerable entities = null; var expected = "てすとてすとー"; Assert.Equal(expected, TweetFormatter.AutoLinkHtml(text, entities)); @@ -156,7 +156,7 @@ namespace OpenTween public void AutoLinkHtml_EntityNullTest4() { var text = "てすとてすとー"; - IEnumerable entities = new TwitterDataModel.Entity[] { null }; + IEnumerable entities = new TwitterEntity[] { null }; var expected = "てすとてすとー"; Assert.Equal(expected, TweetFormatter.AutoLinkHtml(text, entities)); @@ -169,7 +169,7 @@ namespace OpenTween var text = "\"\'@twitterapi\'\""; var entities = new[] { - new TwitterDataModel.UserMentions + new TwitterEntityMention { Indices = new[] { 2, 13 }, Id = 6253282L, @@ -189,7 +189,7 @@ namespace OpenTween var text = "<b> @twitterapi </b>"; var entities = new[] { - new TwitterDataModel.UserMentions + new TwitterEntityMention { Indices = new[] { 10, 21 }, Id = 6253282L, @@ -209,7 +209,7 @@ namespace OpenTween var text = " @twitterapi "; var entities = new[] { - new TwitterDataModel.UserMentions + new TwitterEntityMention { Indices = new[] { 4, 15 }, Id = 6253282L, @@ -229,7 +229,7 @@ namespace OpenTween var text = "#ぜんぶ雪のせいだ"; var entities = new[] { - new TwitterDataModel.Hashtags + new TwitterEntityHashtag { Indices = new[] { 0, 9 }, Text = "ぜんぶ雪のせいだ", @@ -248,7 +248,7 @@ namespace OpenTween var text = "🐬🐬 @irucame 🐬🐬"; var entities = new[] { - new TwitterDataModel.UserMentions + new TwitterEntityMention { Indices = new[] { 3, 11 }, Id = 89942943L, @@ -267,12 +267,12 @@ namespace OpenTween var text = "🐬🐬 #🐬🐬 🐬🐬 #🐬🐬 🐬🐬"; var entities = new[] { - new TwitterDataModel.Hashtags + new TwitterEntityHashtag { Indices = new[] { 3, 6 }, Text = "🐬🐬", }, - new TwitterDataModel.Hashtags + new TwitterEntityHashtag { Indices = new[] { 10, 13 }, Text = "🐬🐬", @@ -292,7 +292,7 @@ namespace OpenTween var text = "Caf\u00e9 #test"; var entities = new[] { - new TwitterDataModel.Hashtags + new TwitterEntityHashtag { Indices = new[] { 5, 10 }, Text = "test", @@ -311,7 +311,7 @@ namespace OpenTween var text = "Cafe\u0301 #test"; var entities = new[] { - new TwitterDataModel.Hashtags + new TwitterEntityHashtag { Indices = new[] { 6, 11 }, Text = "test", @@ -326,7 +326,7 @@ namespace OpenTween public void AutoLinkHtml_BreakLineTest() { var text = "てすと\nてすと\nてすと"; - TwitterDataModel.Entities entities = null; + TwitterEntities entities = null; var expected = "てすと
てすと
てすと"; Assert.Equal(expected, TweetFormatter.AutoLinkHtml(text, entities)); diff --git a/OpenTween/Api/TwitterDataModel.cs b/OpenTween/Api/TwitterDataModel.cs index c32a2228..e57ba128 100644 --- a/OpenTween/Api/TwitterDataModel.cs +++ b/OpenTween/Api/TwitterDataModel.cs @@ -42,70 +42,6 @@ namespace OpenTween.Api } [DataContract] - public class Entity - { - [DataMember(Name = "indices")] public int[] Indices = new int[3]; - } - - [DataContract] - public class SizeElement - { - [DataMember(Name = "w")] public int w; - [DataMember(Name = "h")] public int h; - [DataMember(Name = "resize")] public string Resize; - } - - [DataContract] - public class Sizes - { - [DataMember(Name = "large")] public SizeElement Large; - [DataMember(Name = "medium")] public SizeElement Medium; - [DataMember(Name = "small")] public SizeElement Small; - [DataMember(Name = "thumb")] public SizeElement Thumb; - } - - [DataContract] - public class Media : Urls - { - [DataMember(Name = "id")] public long Id; - [DataMember(Name = "media_url")] public string MediaUrl; - [DataMember(Name = "media_url_https")] public string MediaUrlHttps; - [DataMember(Name = "sizes")] public Sizes Sizes; - [DataMember(Name = "type")] public string Type; - } - - [DataContract] - public class Urls : Entity - { - [DataMember(Name = "url")] public string Url; - [DataMember(Name = "display_url")] public string DisplayUrl; - [DataMember(Name = "expanded_url")] public string ExpandedUrl; - } - - [DataContract] - public class Hashtags : Entity - { - [DataMember(Name = "text")] public string Text; - } - - [DataContract] - public class UserMentions : Entity - { - [DataMember(Name = "screen_name")] public string ScreenName; - [DataMember(Name = "name")] public string Name; - [DataMember(Name = "id")] public Int64 Id; - } - - [DataContract] - public class Entities - { - [DataMember(Name = "urls")] public Urls[] Urls; - [DataMember(Name = "hashtags")] public Hashtags[] Hashtags; - [DataMember(Name = "user_mentions")] public UserMentions[] UserMentions; - [DataMember(Name = "media", IsRequired = false)] public Media[] Media; - } - - [DataContract] public class Coordinates { [DataMember(Name = "type", IsRequired = false)] public string Type; @@ -157,7 +93,7 @@ namespace OpenTween.Api [DataMember(Name = "place", IsRequired = false)] public Place Place; [DataMember(Name = "in_reply_to_status_id")] public long? InReplyToStatusId; [DataMember(Name = "text")] public string Text; - [DataMember(Name = "entities", IsRequired = false)] public Entities Entities; + [DataMember(Name = "entities", IsRequired = false)] public TwitterEntities Entities; } [DataContract] @@ -182,7 +118,7 @@ namespace OpenTween.Api [DataMember(Name = "id")] public Int64 Id; [DataMember(Name = "favorited")] public bool Favorited; [DataMember(Name = "text")] public string Text; - [DataMember(Name = "entities", IsRequired = false)] public Entities Entities; + [DataMember(Name = "entities", IsRequired = false)] public TwitterEntities Entities; } [DataContract] @@ -212,7 +148,7 @@ namespace OpenTween.Api [DataMember(Name = "recipient_id")] public Int64 RecipientId; [DataMember(Name = "id")] public Int64 Id; [DataMember(Name = "text")] public string Text; - [DataMember(Name = "entities", IsRequired = false)] public Entities Entities; + [DataMember(Name = "entities", IsRequired = false)] public TwitterEntities Entities; } [DataContract] diff --git a/OpenTween/Api/TwitterEntity.cs b/OpenTween/Api/TwitterEntity.cs new file mode 100644 index 00000000..ed5453e3 --- /dev/null +++ b/OpenTween/Api/TwitterEntity.cs @@ -0,0 +1,148 @@ +// OpenTween - Client of Twitter +// Copyright (c) 2014 kim_upsilon (@kim_upsilon) +// All rights reserved. +// +// This file is part of OpenTween. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program. If not, see , or write to +// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +// Boston, MA 02110-1301, USA. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; + +namespace OpenTween.Api +{ + // 参照: https://dev.twitter.com/docs/platform-objects/entities + + [DataContract] + public class TwitterEntities + { + [DataMember(Name = "hashtags")] + public TwitterEntityHashtag[] Hashtags { get; set; } + + [DataMember(Name = "media", IsRequired = false)] + public TwitterEntityMedia[] Media { get; set; } + + [DataMember(Name = "urls")] + public TwitterEntityUrl[] Urls { get; set; } + + [DataMember(Name = "user_mentions")] + public TwitterEntityMention[] UserMentions { get; set; } + } + + [DataContract] + public abstract class TwitterEntity + { + [DataMember(Name = "indices")] + public int[] Indices { get; set; } + } + + [DataContract] + public class TwitterEntityHashtag : TwitterEntity + { + [DataMember(Name = "text")] + public string Text { get; set; } + } + + [DataContract] + public class TwitterEntityMedia : TwitterEntityUrl + { + [DataMember(Name = "id")] + public long Id { get; set; } + + [DataMember(Name = "id_str")] + public string IdStr { get; set; } + + [DataMember(Name = "media_url")] + public string MediaUrl { get; set; } + + [DataMember(Name = "media_url_https")] + public string MediaUrlHttps { get; set; } + + [DataMember(Name = "sizes")] + public TwitterMediaSizes Sizes { get; set; } + + [DataMember(Name = "source_status_id")] + public long SourceStatusId { get; set; } + + [DataMember(Name = "source_status_id_str")] + public string SourceStatusIdStr { get; set; } + + [DataMember(Name = "type")] + public string Type { get; set; } + } + + [DataContract] + public class TwitterMediaSizes + { + [DataMember(Name = "thumb")] + public TwitterMediaSizes.Size Thumb { get; set; } + + [DataMember(Name = "large")] + public TwitterMediaSizes.Size Large { get; set; } + + [DataMember(Name = "medium")] + public TwitterMediaSizes.Size Medium { get; set; } + + [DataMember(Name = "small")] + public TwitterMediaSizes.Size Small { get; set; } + + [DataContract] + public class Size + { + [DataMember(Name = "h")] + public int Height { get; set; } + + [DataMember(Name = "resize")] + public string Resize { get; set; } + + [DataMember(Name = "w")] + public int Width { get; set; } + } + } + + [DataContract] + public class TwitterEntityUrl : TwitterEntity + { + [DataMember(Name = "display_url")] + public string DisplayUrl { get; set; } + + [DataMember(Name = "expanded_url")] + public string ExpandedUrl { get; set; } + + [DataMember(Name = "url")] + public string Url { get; set; } + } + + [DataContract] + public class TwitterEntityMention : TwitterEntity + { + [DataMember(Name = "id")] + public long Id { get; set; } + + [DataMember(Name = "id_str")] + public string IdStr { get; set; } + + [DataMember(Name = "name")] + public string Name { get; set; } + + [DataMember(Name = "screen_name")] + public string ScreenName { get; set; } + } +} diff --git a/OpenTween/OpenTween.csproj b/OpenTween/OpenTween.csproj index d75f4313..e60505b8 100644 --- a/OpenTween/OpenTween.csproj +++ b/OpenTween/OpenTween.csproj @@ -62,6 +62,7 @@ + diff --git a/OpenTween/TweetFormatter.cs b/OpenTween/TweetFormatter.cs index c4f768f8..d181d3e4 100644 --- a/OpenTween/TweetFormatter.cs +++ b/OpenTween/TweetFormatter.cs @@ -33,37 +33,30 @@ namespace OpenTween /// public class TweetFormatter { - public static string AutoLinkHtml(string text, TwitterDataModel.Entities entities) + public static string AutoLinkHtml(string text, TwitterEntities entities) { if (entities == null) - return AutoLinkHtml(text, Enumerable.Empty()); + return AutoLinkHtml(text, Enumerable.Empty()); - if (entities.Urls == null) - entities.Urls = new TwitterDataModel.Urls[0]; + var urls = entities.Urls ?? new TwitterEntityUrl[0]; + var hashtags = entities.Hashtags ?? new TwitterEntityHashtag[0]; + var mentions = entities.UserMentions ?? new TwitterEntityMention[0]; + var media = entities.Media ?? new TwitterEntityMedia[0]; - if (entities.Hashtags == null) - entities.Hashtags = new TwitterDataModel.Hashtags[0]; - - if (entities.UserMentions == null) - entities.UserMentions = new TwitterDataModel.UserMentions[0]; - - if (entities.Media == null) - entities.Media = new TwitterDataModel.Media[0]; - - var entitiesQuery = entities.Urls.Cast() - .Concat(entities.Hashtags) - .Concat(entities.UserMentions) - .Concat(entities.Media) + var entitiesQuery = urls.Cast() + .Concat(hashtags) + .Concat(mentions) + .Concat(media) .Where(x => x != null) .Where(x => x.Indices != null && x.Indices.Length == 2); return string.Concat(AutoLinkHtmlInternal(text, entitiesQuery)); } - public static string AutoLinkHtml(string text, IEnumerable entities) + public static string AutoLinkHtml(string text, IEnumerable entities) { if (entities == null) - entities = Enumerable.Empty(); + entities = Enumerable.Empty(); var entitiesQuery = entities .Where(x => x != null) @@ -72,7 +65,7 @@ namespace OpenTween return string.Concat(AutoLinkHtmlInternal(text, entitiesQuery)); } - private static IEnumerable AutoLinkHtmlInternal(string text, IEnumerable entities) + private static IEnumerable AutoLinkHtmlInternal(string text, IEnumerable entities) { var curIndex = 0; @@ -95,12 +88,12 @@ namespace OpenTween var targetText = text.Substring(startIndex, endIndex - startIndex); - if (entity is TwitterDataModel.Urls) - yield return FormatUrlEntity(targetText, (TwitterDataModel.Urls)entity); - else if (entity is TwitterDataModel.Hashtags) - yield return FormatHashtagEntity(targetText, (TwitterDataModel.Hashtags)entity); - else if (entity is TwitterDataModel.UserMentions) - yield return FormatMentionEntity(targetText, (TwitterDataModel.UserMentions)entity); + if (entity is TwitterEntityUrl) + yield return FormatUrlEntity(targetText, (TwitterEntityUrl)entity); + else if (entity is TwitterEntityHashtag) + yield return FormatHashtagEntity(targetText, (TwitterEntityHashtag)entity); + else if (entity is TwitterEntityMention) + yield return FormatMentionEntity(targetText, (TwitterEntityMention)entity); else yield return t(e(targetText)); @@ -114,7 +107,7 @@ namespace OpenTween /// /// エンティティの Indices をサロゲートペアを考慮して調整します /// - private static IEnumerable FixEntityIndices(string text, IEnumerable entities) + private static IEnumerable FixEntityIndices(string text, IEnumerable entities) { var curIndex = 0; var indexOffset = 0; // サロゲートペアによる indices のズレを表す @@ -145,7 +138,7 @@ namespace OpenTween } } - private static string FormatUrlEntity(string targetText, TwitterDataModel.Urls entity) + private static string FormatUrlEntity(string targetText, TwitterEntityUrl entity) { string expandedUrl; @@ -161,12 +154,12 @@ namespace OpenTween return "" + t(e(entity.DisplayUrl)) + ""; } - private static string FormatHashtagEntity(string targetText, TwitterDataModel.Hashtags entity) + private static string FormatHashtagEntity(string targetText, TwitterEntityHashtag entity) { return "" + t(e(targetText)) + ""; } - private static string FormatMentionEntity(string targetText, TwitterDataModel.UserMentions entity) + private static string FormatMentionEntity(string targetText, TwitterEntityMention entity) { return "" + t(e(targetText)) + ""; } diff --git a/OpenTween/Twitter.cs b/OpenTween/Twitter.cs index a86b36ab..8d5eca3b 100644 --- a/OpenTween/Twitter.cs +++ b/OpenTween/Twitter.cs @@ -1525,7 +1525,7 @@ namespace OpenTween private PostClass CreatePostsFromStatusData(TwitterDataModel.Status status) { var post = new PostClass(); - TwitterDataModel.Entities entities; + TwitterEntities entities; post.StatusId = status.Id; if (status.RetweetedStatus != null) @@ -2189,7 +2189,7 @@ namespace OpenTween foreach (var status in item) { var post = new PostClass(); - TwitterDataModel.Entities entities; + TwitterEntities entities; try { @@ -2292,7 +2292,7 @@ namespace OpenTween return ""; } - private string ReplaceTextFromApi(string text, TwitterDataModel.Entities entities) + private string ReplaceTextFromApi(string text, TwitterEntities entities) { if (entities != null) { @@ -2909,7 +2909,7 @@ namespace OpenTween return retStr; } - public async Task CreateHtmlAnchorAsync(string text, List AtList, TwitterDataModel.Entities entities, Dictionary media) + public async Task CreateHtmlAnchorAsync(string text, List AtList, TwitterEntities entities, Dictionary media) { if (entities != null) { @@ -2959,7 +2959,7 @@ namespace OpenTween } [Obsolete] - public string CreateHtmlAnchor(string text, List AtList, TwitterDataModel.Entities entities, Dictionary media) + public string CreateHtmlAnchor(string text, List AtList, TwitterEntities entities, Dictionary media) { return this.CreateHtmlAnchorAsync(text, AtList, entities, media).Result; } -- 2.11.0