···
from dataclasses import dataclass
from typing import Any, override
6
+
from cross.attachments import (
10
+
SensitiveAttachment,
12
+
from cross.post import Post
from cross.service import OutputService
from database.connection import DatabasePool
from mastodon.info import InstanceInfo, MastodonService, validate_and_transform
···
self.log.info("Getting %s configuration...", self.url)
response = self.fetch_instance_info()
self.instance_info: InstanceInfo = InstanceInfo.from_api(response)
51
+
def accept_post(self, service: str, user: str, post: Post):
52
+
new_root_id: int | None = None
53
+
new_parent_id: int | None = None
55
+
reply_ref: str | None = None
57
+
thread = self._find_mapped_thread(
58
+
post.parent_id, service, user, self.url, self.user_id
62
+
self.log.error("Failed to find thread tuple in the database!")
64
+
_, reply_ref, new_root_id, new_parent_id = thread
66
+
quote = post.attachments.get(QuoteAttachment)
68
+
if quote.quoted_user != user:
69
+
self.log.info("Quoted other user, skipping!")
72
+
quoted_post = self._get_post(service, user, quote.quoted_id)
74
+
self.log.error("Failed to find quoted post in the database!")
77
+
quoted_mappings = self._get_mappings(quoted_post["id"], self.url, self.user_id)
78
+
if not quoted_mappings:
79
+
self.log.error("Failed to find mappings for quoted post!")
82
+
quoted_local_id = quoted_mappings[-1][0]
83
+
# TODO resolve service identifier
85
+
post_tokens = post.tokens.copy()
87
+
remote_url = post.attachments.get(RemoteUrlAttachment)
88
+
if remote_url and remote_url.url and post.text_type == "text/x.misskeymarkdown":
92
+
raw_statuses = [] # TODO split tokens and media across posts
93
+
if not raw_statuses:
94
+
self.log.error("Failed to split post into statuses!")
97
+
langs = post.attachments.get(LanguagesAttachment)
98
+
sensitive = post.attachments.get(SensitiveAttachment)
100
+
if langs and langs.langs:
103
+
if sensitive and sensitive.sensitive:
106
+
def delete_post(self, service: str, user: str, post_id: str):
107
+
post = self._get_post(service, user, post_id)
109
+
self.log.info("Post not found in db, skipping delete..")
112
+
mappings = self._get_mappings(post["id"], self.url, self.user_id)
113
+
for mapping in mappings[::-1]:
114
+
self.log.info("Deleting '%s'...", mapping["identifier"])
116
+
f"{self.url}/api/v1/statuses/{mapping['identifier']}",
117
+
headers={"Authorization": f"Bearer {self._get_token()}"},
119
+
self._delete_post_by_id(mapping["id"])
121
+
def accept_repost(self, service: str, user: str, repost_id: str, reposted_id: str):
122
+
reposted = self._get_post(service, user, reposted_id)
124
+
self.log.info("Post not found in db, skipping repost..")
127
+
mappings = self._get_mappings(reposted["id"], self.url, self.user_id)
129
+
rsp = requests.post(
130
+
f"{self.url}/api/v1/statuses/{mappings[0]['identifier']}/reblog",
131
+
headers={"Authorization": f"Bearer {self._get_token()}"},
134
+
if rsp.status_code != 200:
136
+
"Failed to boost status! status_code: %s, msg: %s",
144
+
"user": self.user_id,
145
+
"service": self.url,
146
+
"identifier": rsp.json()["id"],
147
+
"reposted": mappings[0]["id"],
150
+
inserted = self._get_post(self.url, self.user_id, rsp.json()["id"])
152
+
raise ValueError("Inserted post not found!")
153
+
self._insert_post_mapping(reposted["id"], inserted["id"])
155
+
def delete_repost(self, service: str, user: str, repost_id: str):
156
+
repost = self._get_post(service, user, repost_id)
158
+
self.log.info("Repost not found in db, skipping delete..")
161
+
mappings = self._get_mappings(repost["id"], self.url, self.user_id)
162
+
rmappings = self._get_mappings(repost["reposted"], self.url, self.user_id)
164
+
if mappings and rmappings:
166
+
"Removing '%s' Repost of '%s'...",
167
+
mappings[0]["identifier"],
168
+
rmappings[0]["identifier"],
171
+
f"{self.url}/api/v1/statuses/{rmappings[0]['identifier']}/unreblog",
172
+
headers={"Authorization": f"Bearer {self._get_token()}"},
174
+
self._delete_post_by_id(mappings[0]["id"])
def _get_token(self) -> str: