OSDN Git Service

Merge pull request #251 from opentween/user-timeline
[opentween/open-tween.git] / OpenTween / Api / GraphQL / TwitterGraphqlUser.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2023 kim_upsilon (@kim_upsilon) <https://upsilo.net/~upsilon/>
3 // All rights reserved.
4 //
5 // This file is part of OpenTween.
6 //
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)
10 // any later version.
11 //
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
15 // for more details.
16 //
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.
21
22 #nullable enable
23
24 using System;
25 using System.Collections.Generic;
26 using System.Linq;
27 using System.Text;
28 using System.Threading.Tasks;
29 using System.Xml.Linq;
30 using System.Xml.XPath;
31 using OpenTween.Api.DataModel;
32
33 namespace OpenTween.Api.GraphQL
34 {
35     public class TwitterGraphqlUser
36     {
37         public const string TypeName = "User";
38
39         public XElement Element { get; }
40
41         public TwitterGraphqlUser(XElement element)
42         {
43             var typeName = element.Element("__typename")?.Value;
44             if (typeName != TypeName)
45                 throw new ArgumentException($"Invalid itemType: {typeName}", nameof(element));
46
47             this.Element = element;
48         }
49
50         public TwitterUser ToTwitterUser()
51         {
52             try
53             {
54                 return TwitterGraphqlUser.ParseUser(this.Element);
55             }
56             catch (WebApiException ex)
57             {
58                 ex.ResponseText = JsonUtils.JsonXmlToString(this.Element);
59                 MyCommon.TraceOut(ex);
60                 throw;
61             }
62         }
63
64         public static TwitterUser ParseUser(XElement userElm)
65         {
66             var userLegacyElm = userElm.Element("legacy") ?? throw CreateParseError();
67
68             static string GetText(XElement elm, string name)
69                 => elm.Element(name)?.Value ?? throw CreateParseError();
70
71             static string? GetTextOrNull(XElement elm, string name)
72                 => elm.Element(name)?.Value;
73
74             return new()
75             {
76                 Id = long.Parse(GetText(userElm, "rest_id")),
77                 IdStr = GetText(userElm, "rest_id"),
78                 Name = GetText(userLegacyElm, "name"),
79                 ProfileImageUrlHttps = GetText(userLegacyElm, "profile_image_url_https"),
80                 ScreenName = GetText(userLegacyElm, "screen_name"),
81                 Protected = GetTextOrNull(userLegacyElm, "protected") == "true",
82                 Verified = GetTextOrNull(userLegacyElm, "verified") == "true",
83                 CreatedAt = GetText(userLegacyElm, "created_at"),
84                 FollowersCount = int.Parse(GetText(userLegacyElm, "followers_count")),
85                 FriendsCount = int.Parse(GetText(userLegacyElm, "friends_count")),
86                 FavouritesCount = int.Parse(GetText(userLegacyElm, "favourites_count")),
87                 StatusesCount = int.Parse(GetText(userLegacyElm, "statuses_count")),
88                 Description = GetTextOrNull(userLegacyElm, "description"),
89                 Location = GetTextOrNull(userLegacyElm, "location"),
90                 Url = GetTextOrNull(userLegacyElm, "url"),
91                 Entities = new()
92                 {
93                     Description = new()
94                     {
95                         Urls = userLegacyElm.XPathSelectElements("entities/description/urls/item")
96                             .Select(x => new TwitterEntityUrl()
97                             {
98                                 Indices = x.XPathSelectElements("indices/item").Select(x => int.Parse(x.Value)).ToArray(),
99                                 DisplayUrl = GetText(x, "display_url"),
100                                 ExpandedUrl = GetText(x, "expanded_url"),
101                                 Url = GetText(x, "url"),
102                             })
103                             .ToArray(),
104                     },
105                     Url = new()
106                     {
107                         Urls = userLegacyElm.XPathSelectElements("entities/url/urls/item")
108                             .Select(x => new TwitterEntityUrl()
109                             {
110                                 Indices = x.XPathSelectElements("indices/item").Select(x => int.Parse(x.Value)).ToArray(),
111                                 DisplayUrl = GetText(x, "display_url"),
112                                 ExpandedUrl = GetText(x, "expanded_url"),
113                                 Url = GetText(x, "url"),
114                             })
115                             .ToArray(),
116                     },
117                 },
118             };
119         }
120
121         private static Exception CreateParseError()
122             => throw new WebApiException("Parse error on User");
123     }
124 }