1 // OpenTween - Client of Twitter
2 // Copyright (c) 2014 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
5 // This file is part of OpenTween.
7 // This program is free software; you can redistribute it and/or modify it
8 // under the terms of the GNU General Public License as published by the Free
9 // Software Foundation; either version 3 of the License, or (at your option)
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 // You should have received a copy of the GNU General Public License along
18 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
19 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
20 // Boston, MA 02110-1301, USA.
23 using System.Collections.Generic;
25 using System.Runtime.Serialization;
27 using System.Threading.Tasks;
29 namespace OpenTween.Api.DataModel
31 // 参照: https://developer.twitter.com/en/docs/tweets/data-dictionary/overview/tweet-object
34 public class TwitterStatus
36 [DataMember(Name = "coordinates", IsRequired = false)]
37 public GeoJsonPoint Coordinates { get; set; }
39 [DataMember(Name = "created_at")]
40 public string CreatedAt { get; set; }
42 [DataMember(Name = "display_text_range")]
43 public int[] DisplayTextRange { get; set; }
45 [DataMember(Name = "entities")]
46 public TwitterEntities Entities { get; set; }
48 [DataMember(Name = "extended_entities", IsRequired = false)]
49 public TwitterEntities ExtendedEntities { get; set; }
51 [DataMember(Name = "favorite_count")]
52 public int? FavoriteCount { get; set; }
54 [DataMember(Name = "favorited")]
55 public bool? Favorited { get; set; }
57 [DataMember(Name = "filter_level")]
58 public string FilterLevel { get; set; }
60 [DataMember(Name = "full_text")]
61 public string FullText { get; set; }
63 [DataMember(Name = "id")]
64 public long Id { get; set; }
66 [DataMember(Name = "id_str")]
67 public string IdStr { get; set; }
69 [DataMember(Name = "in_reply_to_screen_name")]
70 public string InReplyToScreenName { get; set; } // Nullable
72 [DataMember(Name = "in_reply_to_status_id")]
73 public long? InReplyToStatusId { get; set; }
75 [DataMember(Name = "in_reply_to_status_id_str")]
76 public string InReplyToStatusIdStr { get; set; } // Nullable
78 [DataMember(Name = "in_reply_to_user_id")]
79 public long? InReplyToUserId { get; set; }
81 [DataMember(Name = "in_reply_to_user_id_str")]
82 public string InReplyToUserIdStr { get; set; } // Nullable
84 [DataMember(Name = "is_quote_status")]
85 public bool IsQuoteStatus { get; set; }
87 [DataMember(Name = "lang")]
88 public string Lang { get; set; } // Nullable
90 [DataMember(Name = "place", IsRequired = false)]
91 public TwitterPlace Place { get; set; }
93 [DataMember(Name = "possibly_sensitive")]
94 public bool? PossiblySensitive { get; set; }
96 [DataMember(Name = "quote_count")]
97 public int? QuoteCount { get; set; }
99 [DataMember(Name = "quoted_status_id", IsRequired = false)]
100 public long? QuotedStatusId { get; set; }
102 [DataMember(Name = "quoted_status_id_str", IsRequired = false)]
103 public string QuotedStatusIdStr { get; set; }
105 [DataMember(Name = "quoted_status", IsRequired = false)]
106 public TwitterStatus QuotedStatus { get; set; }
108 [DataMember(Name = "quoted_status_permalink", IsRequired = false)]
109 public TwitterQuotedStatusPermalink QuotedStatusPermalink { get; set; } // https://twittercommunity.com/t/105473
111 [DataMember(Name = "reply_count")]
112 public int ReplyCount { get; set; }
114 [DataMember(Name = "retweet_count")]
115 public int RetweetCount { get; set; }
117 [DataMember(Name = "retweeted")]
118 public bool Retweeted { get; set; }
120 [DataMember(Name = "retweeted_status", IsRequired = false)]
121 public TwitterStatus RetweetedStatus { get; set; }
123 [DataMember(Name = "source")]
124 public string Source { get; set; }
126 [DataMember(Name = "truncated")]
127 public bool Truncated { get; set; }
129 [DataMember(Name = "user")]
130 public TwitterUser User { get; set; }
132 [DataMember(Name = "withheld_copyright")]
133 public bool WithheldCopyright { get; set; }
135 [DataMember(Name = "withheld_in_countries")]
136 public string[] WithheldInCountries { get; set; }
138 [DataMember(Name = "withheld_scope")]
139 public string WithheldScope { get; set; }
142 /// Entities と ExtendedEntities をマージした状態のエンティティを返します
145 public TwitterEntities MergedEntities
149 if (this.ExtendedEntities == null)
150 return this.Entities;
152 return new TwitterEntities
154 Hashtags = this.Entities.Hashtags,
155 Media = this.ExtendedEntities.Media ?? this.Entities.Media,
156 Symbols = this.Entities.Symbols,
157 Urls = this.Entities.Urls,
158 UserMentions = this.Entities.UserMentions,
163 /// <exception cref="SerializationException"/>
164 public static TwitterStatus ParseJson(string json)
166 return MyCommon.CreateDataFromJson<TwitterStatus>(json);
169 /// <exception cref="SerializationException"/>
170 public static TwitterStatus[] ParseJsonArray(string json)
172 return MyCommon.CreateDataFromJson<TwitterStatus[]>(json);
177 public class TwitterQuotedStatusPermalink
179 [DataMember(Name = "url")]
180 public string Url { get; set; }
182 [DataMember(Name = "expanded")]
183 public string Expanded { get; set; }
185 [DataMember(Name = "display")]
186 public string Display { get; set; }
190 /// Streaming API または tweet_mode=compat の REST API から返されるツイート (Compatibility mode)
193 public class TwitterStatusCompat
195 [DataMember(Name = "coordinates", IsRequired = false)]
196 public GeoJsonPoint Coordinates { get; set; }
198 [DataMember(Name = "created_at")]
199 public string CreatedAt { get; set; }
201 [DataMember(Name = "entities")]
202 public TwitterEntities Entities { get; set; }
204 [DataMember(Name = "extended_entities", IsRequired = false)]
205 public TwitterEntities ExtendedEntities { get; set; }
207 [DataMember(Name = "extended_tweet", IsRequired = false)]
208 public TwitterStatusCompat.Extended ExtendedTweet { get; set; }
211 public class Extended
213 [DataMember(Name = "display_text_range")]
214 public int[] DisplayTextRange { get; set; }
216 [DataMember(Name = "entities")]
217 public TwitterEntities Entities { get; set; }
219 [DataMember(Name = "extended_entities", IsRequired = false)]
220 public TwitterEntities ExtendedEntities { get; set; }
222 [DataMember(Name = "full_text")]
223 public string FullText { get; set; }
226 [DataMember(Name = "favorite_count")]
227 public int? FavoriteCount { get; set; }
229 [DataMember(Name = "favorited")]
230 public bool? Favorited { get; set; }
232 [DataMember(Name = "filter_level")]
233 public string FilterLevel { get; set; }
235 [DataMember(Name = "id")]
236 public long Id { get; set; }
238 [DataMember(Name = "id_str")]
239 public string IdStr { get; set; }
241 [DataMember(Name = "in_reply_to_screen_name")]
242 public string InReplyToScreenName { get; set; } // Nullable
244 [DataMember(Name = "in_reply_to_status_id")]
245 public long? InReplyToStatusId { get; set; }
247 [DataMember(Name = "in_reply_to_status_id_str")]
248 public string InReplyToStatusIdStr { get; set; } // Nullable
250 [DataMember(Name = "in_reply_to_user_id")]
251 public long? InReplyToUserId { get; set; }
253 [DataMember(Name = "in_reply_to_user_id_str")]
254 public string InReplyToUserIdStr { get; set; } // Nullable
256 [DataMember(Name = "is_quote_status")]
257 public bool IsQuoteStatus { get; set; }
259 [DataMember(Name = "lang")]
260 public string Lang { get; set; } // Nullable
262 [DataMember(Name = "place", IsRequired = false)]
263 public TwitterPlace Place { get; set; }
265 [DataMember(Name = "possibly_sensitive")]
266 public bool? PossiblySensitive { get; set; }
268 [DataMember(Name = "quote_count")]
269 public int? QuoteCount { get; set; }
271 [DataMember(Name = "quoted_status_id", IsRequired = false)]
272 public long? QuotedStatusId { get; set; }
274 [DataMember(Name = "quoted_status_id_str", IsRequired = false)]
275 public string QuotedStatusIdStr { get; set; }
277 [DataMember(Name = "quoted_status", IsRequired = false)]
278 public TwitterStatusCompat QuotedStatus { get; set; }
280 [DataMember(Name = "quoted_status_permalink", IsRequired = false)]
281 public TwitterQuotedStatusPermalink QuotedStatusPermalink { get; set; } // https://twittercommunity.com/t/105473
283 [DataMember(Name = "reply_count")]
284 public int ReplyCount { get; set; }
286 [DataMember(Name = "retweet_count")]
287 public int RetweetCount { get; set; }
289 [DataMember(Name = "retweeted")]
290 public bool Retweeted { get; set; }
292 [DataMember(Name = "retweeted_status", IsRequired = false)]
293 public TwitterStatusCompat RetweetedStatus { get; set; }
295 [DataMember(Name = "source")]
296 public string Source { get; set; }
298 [DataMember(Name = "text")]
299 public string Text { get; set; }
301 [DataMember(Name = "truncated")]
302 public bool Truncated { get; set; }
304 [DataMember(Name = "user")]
305 public TwitterUser User { get; set; }
307 [DataMember(Name = "withheld_copyright")]
308 public bool WithheldCopyright { get; set; }
310 [DataMember(Name = "withheld_in_countries")]
311 public string[] WithheldInCountries { get; set; }
313 [DataMember(Name = "withheld_scope")]
314 public string WithheldScope { get; set; }
316 /// <summary>Compatibility Modeのツイートを<see cref="TwitterStatus"/>に変換します</summary>
317 public TwitterStatus Normalize()
319 var normalized = new TwitterStatus
321 Coordinates = this.Coordinates,
322 CreatedAt = this.CreatedAt,
323 FavoriteCount = this.FavoriteCount,
324 Favorited = this.Favorited,
325 FilterLevel = this.FilterLevel,
328 InReplyToScreenName = this.InReplyToScreenName,
329 InReplyToStatusId = this.InReplyToStatusId,
330 InReplyToStatusIdStr = this.InReplyToStatusIdStr,
331 InReplyToUserId = this.InReplyToUserId,
332 InReplyToUserIdStr = this.InReplyToUserIdStr,
333 IsQuoteStatus = this.IsQuoteStatus,
336 PossiblySensitive = this.PossiblySensitive,
337 QuoteCount = this.QuoteCount,
338 QuotedStatusId = this.QuotedStatusId,
339 QuotedStatusIdStr = this.QuotedStatusIdStr,
340 QuotedStatus = this.QuotedStatus?.Normalize(),
341 QuotedStatusPermalink = this.QuotedStatusPermalink,
342 ReplyCount = this.ReplyCount,
343 RetweetCount = this.RetweetCount,
344 Retweeted = this.Retweeted,
345 RetweetedStatus = this.RetweetedStatus?.Normalize(),
346 Source = this.Source,
348 WithheldCopyright = this.WithheldCopyright,
349 WithheldInCountries = this.WithheldInCountries,
350 WithheldScope = this.WithheldScope,
353 if (this.ExtendedTweet != null)
356 normalized.DisplayTextRange = this.ExtendedTweet.DisplayTextRange;
357 normalized.Entities = this.ExtendedTweet.Entities;
358 normalized.ExtendedEntities = this.ExtendedTweet.ExtendedEntities;
359 normalized.FullText = this.ExtendedTweet.FullText;
360 normalized.Truncated = false;
365 normalized.DisplayTextRange = new[] { 0, this.GetCodePointCount(this.Text) };
366 normalized.Entities = this.Entities;
367 normalized.ExtendedEntities = this.ExtendedEntities;
368 normalized.FullText = this.Text;
369 normalized.Truncated = this.Truncated;
375 /// <summary>Unicodeコードポイント単位の文字数を返します</summary>
376 private int GetCodePointCount(string text)
377 => text.Length - text.Sum(x => char.IsHighSurrogate(x) ? 1 : 0);
379 /// <exception cref="SerializationException"/>
380 public static TwitterStatusCompat ParseJson(string json)
382 return MyCommon.CreateDataFromJson<TwitterStatusCompat>(json);
385 /// <exception cref="SerializationException"/>
386 public static TwitterStatusCompat[] ParseJsonArray(string json)
388 return MyCommon.CreateDataFromJson<TwitterStatusCompat[]>(json);
393 public class TwitterDirectMessage
395 [DataMember(Name = "entities", IsRequired = false)]
396 public TwitterEntities Entities { get; set; }
398 [DataMember(Name = "created_at")]
399 public string CreatedAt { get; set; }
401 [DataMember(Name = "id")]
402 public long Id { get; set; }
404 [DataMember(Name = "id_str")]
405 public string IdStr { get; set; }
407 [DataMember(Name = "text")]
408 public string Text { get; set; }
410 [DataMember(Name = "sender_id")]
411 public long SenderId { get; set; }
413 [DataMember(Name = "sender_id_str")]
414 public string SenderIdStr { get; set; }
416 [DataMember(Name = "sender_screen_name")]
417 public string SenderScreenName { get; set; }
419 [DataMember(Name = "sender", IsRequired = false)]
420 public TwitterUser Sender { get; set; }
422 [DataMember(Name = "recipient_id")]
423 public long RecipientId { get; set; }
425 [DataMember(Name = "recipient_id_str")]
426 public string RecipientIdStr { get; set; }
428 [DataMember(Name = "recipient_screen_name")]
429 public string RecipientScreenName { get; set; }
431 [DataMember(Name = "recipient", IsRequired = false)]
432 public TwitterUser Recipient { get; set; }
434 /// <exception cref="SerializationException"/>
435 public static TwitterDirectMessage ParseJson(string json)
437 return MyCommon.CreateDataFromJson<TwitterDirectMessage>(json);
440 /// <exception cref="SerializationException"/>
441 public static TwitterDirectMessage[] ParseJsonArray(string json)
443 return MyCommon.CreateDataFromJson<TwitterDirectMessage[]>(json);