view_model.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. from dataclasses import dataclass, asdict, replace
  2. from typing import List, Dict, Optional
  3. @dataclass
  4. class PublicMetrics:
  5. reply_count: Optional[int] = None
  6. quote_count: Optional[int] = None
  7. retweet_count: Optional[int] = None
  8. like_count: Optional[int] = None
  9. # may be video only
  10. view_count: Optional[int] = None
  11. def items (self):
  12. return asdict(self).items()
  13. @dataclass
  14. class NonPublicMetrics:
  15. impression_count: Optional[int] = None
  16. user_profile_clicks: Optional[int] = None
  17. url_link_clicks: Optional[int] = None
  18. def items (self):
  19. return asdict(self).items()
  20. @dataclass
  21. class MediaItem:
  22. type: str
  23. preview_image_url: str
  24. media_key: Optional[str] = None
  25. image_url: Optional[str] = None
  26. url: Optional[str] = None
  27. content_type: Optional[str] = None
  28. duration_ms: Optional[int] = None
  29. height: Optional[int] = None
  30. width: Optional[int] = None
  31. size: Optional[int] = None
  32. public_metrics: Optional[PublicMetrics] = None
  33. @dataclass
  34. class Card:
  35. display_url: Optional[str] = None
  36. source_url: Optional[str] = None
  37. content: Optional[str] = None
  38. title: Optional[str] = None
  39. @dataclass
  40. class FeedItemAction:
  41. route: str
  42. route_params: Dict
  43. @dataclass
  44. class FeedItemAttachment:
  45. name: str
  46. content_type: str
  47. url: Optional[str] = None
  48. content: Optional[object] = None
  49. size: Optional[int] = None
  50. @dataclass
  51. class FeedItem:
  52. id: str
  53. created_at: str
  54. display_name: str
  55. handle: str
  56. text: Optional[str] = None
  57. html: Optional[str] = None
  58. author_is_verified: Optional[bool] = None
  59. url: Optional[str] = None
  60. conversation_id: Optional[str] = None
  61. avi_icon_url: Optional[str] = None
  62. author_url: Optional[str] = None
  63. author_id: Optional[str] = None
  64. source_url: Optional[str] = None
  65. source_author_url: Optional[str] = None
  66. reply_depth: Optional[int] = 0
  67. is_marked: Optional[bool] = None
  68. card: Optional[Card] = None
  69. public_metrics: Optional[PublicMetrics] = None
  70. non_public_metrics: Optional[NonPublicMetrics] = None
  71. retweeted_tweet_id: Optional[str] = None
  72. source_retweeted_by_url: Optional[str] = None
  73. retweeted_by: Optional[str] = None
  74. retweeted_by_url: Optional[str] = None
  75. videos: Optional[List[MediaItem]] = None
  76. photos: Optional[List[MediaItem]] = None
  77. quoted_tweet_id: Optional[str] = None
  78. quoted_tweet: Optional['FeedItem'] = None
  79. replied_tweet_id: Optional[str] = None
  80. replied_tweet: Optional['FeedItem'] = None
  81. note: Optional[str] = None
  82. debug_source_data: Optional[Dict] = None
  83. attachments: Optional[List[FeedItemAttachment]] = None
  84. # At some point we may move to feed_item_actions when the set is known
  85. actions: Optional[Dict[str, FeedItemAction]] = None
  86. # tm = FeedItem(id="1", text="aa", created_at="fs", display_name="fda", handle="fdsafas")
  87. @dataclass
  88. class FeedServiceUser:
  89. id: str
  90. url: str
  91. name: str # display_name
  92. username: str # handle
  93. created_at: Optional[str] = None
  94. description: Optional[str] = None
  95. preview_image_url: Optional[str] = None
  96. website: Optional[str] = None
  97. actions: Optional[Dict[str, FeedItemAction]] = None
  98. source_url: Optional[str] = None
  99. @property
  100. def display_name (self) -> str:
  101. return self.name
  102. @property
  103. def handle (self) -> str:
  104. return self.username
  105. def cleandict(d):
  106. if isinstance(d, dict):
  107. return {k: cleandict(v) for k, v in d.items() if v is not None}
  108. elif isinstance(d, list):
  109. return [cleandict(v) for v in d]
  110. else:
  111. return d