Graphe des relations d'ajout au groupe entre les membres du Million Project
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

facebook_schema.py 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. from datetime import datetime
  2. from typing import Any, List, Optional, Self
  3. from uuid import uuid4
  4. class AudioFile:
  5. uri: str
  6. creation_timestamp: int
  7. def __init__(self, uri: str, creation_timestamp: int):
  8. self.uri = uri
  9. self.creation_timestamp = creation_timestamp
  10. @classmethod
  11. def from_dict(cls, data: dict) -> Self:
  12. return cls(
  13. uri=data['uri'],
  14. creation_timestamp=data['creation_timestamp']
  15. )
  16. class Gif:
  17. uri: str
  18. def __init__(self, uri: str):
  19. self.uri = uri
  20. @classmethod
  21. def from_dict(cls, data: dict) -> Self:
  22. return cls(
  23. uri=data['uri']
  24. )
  25. class Photo:
  26. uri: str
  27. creation_timestamp: int
  28. def __init__(self, uri: str, creation_timestamp: int):
  29. self.uri = uri
  30. self.creation_timestamp = creation_timestamp
  31. @classmethod
  32. def from_dict(cls, data: dict) -> Self:
  33. return cls(
  34. uri=data['uri'],
  35. creation_timestamp=data['creation_timestamp']
  36. )
  37. class Reaction:
  38. reaction: str
  39. actor: str
  40. def __init__(self, reaction: str, actor: str):
  41. self.reaction = reaction
  42. self.actor = actor
  43. @classmethod
  44. def from_dict(cls, data: dict) -> Self:
  45. return cls(
  46. reaction=data['reaction'],
  47. actor=data['actor']
  48. )
  49. class Share:
  50. link: str
  51. share_text: str
  52. def __init__(self, link: str, share_text: str):
  53. self.link = link
  54. self.share_text = share_text
  55. @classmethod
  56. def from_dict(cls, data: dict) -> Self:
  57. return cls(
  58. link=data['link'],
  59. share_text=data['share_text']
  60. )
  61. class Sticker:
  62. uri: str
  63. ai_stickers: Optional[List[Any]]
  64. def __init__(self, uri: str, ai_stickers: Optional[List[Any]] = None):
  65. self.uri = uri
  66. self.ai_stickers = ai_stickers if ai_stickers is not None else []
  67. @classmethod
  68. def from_dict(cls, data: dict) -> Self:
  69. return cls(
  70. uri=data['uri'],
  71. ai_stickers=data.get('ai_stickers', [])
  72. )
  73. class Video:
  74. uri: str
  75. creation_timestamp: int
  76. def __init__(self, uri: str, creation_timestamp: int):
  77. self.uri = uri
  78. self.creation_timestamp = creation_timestamp
  79. @classmethod
  80. def from_dict(cls, data: dict) -> Self:
  81. return cls(
  82. uri=data['uri'],
  83. creation_timestamp=data['creation_timestamp']
  84. )
  85. class Message:
  86. sender_name: str
  87. date_time: datetime
  88. content: Optional[str]
  89. sticker: Optional[Sticker]
  90. share: Optional[Share]
  91. photos: Optional[List[Photo]]
  92. videos: Optional[List[Video]]
  93. gifs: Optional[List[Gif]]
  94. audio_files: Optional[List[AudioFile]]
  95. call_duration: Optional[int]
  96. reactions: Optional[List[Reaction]]
  97. is_unsent: Optional[bool]
  98. is_geoblocked_for_viewer: bool
  99. _id: str
  100. def __init__(self,
  101. sender_name: str,
  102. date_time: datetime,
  103. is_geoblocked_for_viewer: bool,
  104. content: Optional[str] = None,
  105. sticker: Optional[Sticker] = None,
  106. share: Optional[Share] = None,
  107. photos: Optional[List[Photo]] = None,
  108. videos: Optional[List[Video]] = None,
  109. gifs: Optional[List[Gif]] = None,
  110. audio_files: Optional[List[AudioFile]] = None,
  111. call_duration: Optional[int] = None,
  112. reactions: Optional[List[Reaction]] = None,
  113. is_unsent: Optional[bool] = None
  114. ):
  115. self.sender_name = sender_name
  116. self.date_time = date_time
  117. self.content = content
  118. self.sticker = sticker
  119. self.share = share
  120. self.photos = photos
  121. self.videos = videos
  122. self.gifs = gifs
  123. self.audio_files = audio_files
  124. self.call_duration = call_duration
  125. self.reactions = reactions
  126. self.is_unsent = is_unsent
  127. self.is_geoblocked_for_viewer = is_geoblocked_for_viewer
  128. self._id = str(uuid4())
  129. @property
  130. def message_id(self) -> str:
  131. return self._id
  132. @classmethod
  133. def from_dict(cls, data: dict) -> Self:
  134. _timestamp_ms = data.get('timestamp_ms')
  135. _sender_name = data.get('sender_name')
  136. _is_geoblocked_for_viewer = data.get('is_geoblocked_for_viewer')
  137. _content = data.get('content')
  138. _sticker_dict = data.get('sticker')
  139. _share_dict = data.get('share')
  140. _photos_dict = data.get('photos')
  141. _videos_dict = data.get('videos')
  142. _gifs_dict = data.get('gifs')
  143. _audio_files_dict = data.get('audio_files')
  144. _call_duration = data.get('call_duration')
  145. _reactions_dict = data.get('reactions')
  146. _is_unsent = data.get('is_unsent')
  147. _date_time = datetime.fromtimestamp(_timestamp_ms / 1000)
  148. _sticker = Sticker.from_dict(_sticker_dict) if _sticker_dict else None
  149. _share = Share.from_dict(_share_dict) if _share_dict else None
  150. _photos = [Photo.from_dict(photo) for photo in _photos_dict] if _photos_dict else None
  151. _videos = [Video.from_dict(video) for video in _videos_dict] if _videos_dict else None
  152. _gifs = [Gif.from_dict(gif) for gif in _gifs_dict] if _gifs_dict else None
  153. _audio_files = [AudioFile.from_dict(audio_file) for audio_file in _audio_files_dict] if _audio_files_dict else None
  154. _reactions = [Reaction.from_dict(reaction) for reaction in _reactions_dict] if _reactions_dict else None
  155. return cls(
  156. sender_name=_sender_name,
  157. date_time=_date_time,
  158. is_geoblocked_for_viewer=_is_geoblocked_for_viewer,
  159. content=_content,
  160. sticker=_sticker,
  161. share=_share,
  162. photos=_photos,
  163. videos=_videos,
  164. gifs=_gifs,
  165. audio_files=_audio_files,
  166. call_duration=_call_duration,
  167. reactions=_reactions,
  168. is_unsent=_is_unsent
  169. )
  170. class Image:
  171. creation_timestamp: int
  172. uri: str
  173. def __init__(self, creation_timestamp: int, uri: str):
  174. self.creation_timestamp = creation_timestamp
  175. self.uri = uri
  176. @classmethod
  177. def from_dict(cls, data: dict) -> Self:
  178. return cls(
  179. creation_timestamp=data['creation_timestamp'],
  180. uri=data['uri']
  181. )
  182. class JoinableMode:
  183. mode: int
  184. link: str
  185. def __init__(self, mode: int, link: str):
  186. self.mode = mode
  187. self.link = link
  188. @classmethod
  189. def from_dict(cls, data: dict) -> Self:
  190. return cls(
  191. mode=data['mode'],
  192. link=data['link']
  193. )
  194. class Participant:
  195. name: str
  196. def __init__(self, name: str) -> None:
  197. self.name = name
  198. @classmethod
  199. def from_dict(cls, data: dict) -> Self:
  200. return cls(
  201. name = data.get('name')
  202. )
  203. class FacebookExport:
  204. messages: List[Message]
  205. participants: List[Participant]
  206. title: str
  207. is_still_participant: bool
  208. thread_path: str
  209. magic_words: List[Any]
  210. image: Image
  211. joinable_mode: JoinableMode
  212. def __init__(self,
  213. messages: List[Message],
  214. participants: List[Participant],
  215. title: str,
  216. is_still_participant: bool,
  217. thread_path: str,
  218. magic_words: List[Any],
  219. image: Image,
  220. joinable_mode: JoinableMode):
  221. self.messages = messages
  222. self.participants = participants
  223. self.title = title
  224. self.is_still_participant = is_still_participant
  225. self.thread_path = thread_path
  226. self.magic_words = magic_words
  227. self.image = image
  228. self.joinable_mode = joinable_mode
  229. @classmethod
  230. def from_dict(cls, data: dict) -> Self:
  231. messages_data = data.get('messages', [])
  232. participants_data = data.get('participants', [])
  233. title = data['title']
  234. is_still_participant = data['is_still_participant']
  235. thread_path = data['thread_path']
  236. magic_words = data.get('magic_words', [])
  237. image = Image.from_dict(data['image'])
  238. joinable_mode = JoinableMode.from_dict(data['joinable_mode'])
  239. messages = [Message.from_dict(m) for m in messages_data]
  240. participants = {Participant.from_dict(p) for p in participants_data}
  241. return cls(
  242. messages=messages,
  243. participants=participants,
  244. title=title,
  245. is_still_participant=is_still_participant,
  246. thread_path=thread_path,
  247. magic_words=magic_words,
  248. image=image,
  249. joinable_mode=joinable_mode
  250. )