116 lines
3.4 KiB
Python
116 lines
3.4 KiB
Python
|
from typing import Optional, Literal, TYPE_CHECKING
|
||
|
from datetime import datetime, timedelta
|
||
|
from pydantic import BaseModel
|
||
|
import re
|
||
|
from bs4 import BeautifulSoup
|
||
|
|
||
|
if TYPE_CHECKING:
|
||
|
from vobject.icalendar import RecurringComponent
|
||
|
|
||
|
from masto_bridges.repo import Commit
|
||
|
from masto_bridges.models import Account
|
||
|
from masto_bridges.caldav import Event
|
||
|
|
||
|
class Status(BaseModel):
|
||
|
"""
|
||
|
Model of a toot on mastodon
|
||
|
|
||
|
See: https://mastodonpy.readthedocs.io/en/stable/#toot-dicts
|
||
|
"""
|
||
|
id: int
|
||
|
url: str
|
||
|
account: Account
|
||
|
content: str
|
||
|
visibility: Literal['public', 'unlisted', 'private', 'direct']
|
||
|
created_at:datetime
|
||
|
in_reply_to_id: Optional[int] = None
|
||
|
in_reply_to_account_id: Optional[int] = None
|
||
|
spoiler_text: Optional[str] = None
|
||
|
reblog: Optional['Status'] = None
|
||
|
|
||
|
def __init__(self, **kwargs):
|
||
|
if kwargs.get('url', None) is None:
|
||
|
# try using the uri
|
||
|
kwargs['url'] = kwargs['uri']
|
||
|
super(Status, self).__init__(**kwargs)
|
||
|
|
||
|
class Config:
|
||
|
extra='ignore'
|
||
|
|
||
|
class Post(BaseModel):
|
||
|
#timestamp: Optional[datetime] = None
|
||
|
text:str
|
||
|
status:Optional[Status] = None
|
||
|
commit:Optional[Commit] = None
|
||
|
cal_user:Optional[str] = None
|
||
|
cal_url:Optional[str] = None
|
||
|
|
||
|
@classmethod
|
||
|
def from_commit(cls, commit:Commit) -> 'Post':
|
||
|
text = '\n'.join([commit.subject, commit.body])
|
||
|
return Post(text=text, commit=commit)
|
||
|
|
||
|
@classmethod
|
||
|
def from_status(cls, status:Status) -> 'Post':
|
||
|
# if this is a boost, get the original status
|
||
|
if status.reblog:
|
||
|
date = status.created_at
|
||
|
status = status.reblog
|
||
|
status.created_at = date
|
||
|
|
||
|
soup = BeautifulSoup(status.content, 'lxml')
|
||
|
# replace with double line breaks
|
||
|
pars = [p.text for p in soup.find_all('p')]
|
||
|
text = '\n\n'.join(pars)
|
||
|
return Post(text=text, status=status)
|
||
|
|
||
|
@classmethod
|
||
|
def from_vevent(cls, event:'RecurringComponent'):
|
||
|
user=event.summary.value
|
||
|
text = event.description.value
|
||
|
try:
|
||
|
url = event.location.value
|
||
|
except AttributeError:
|
||
|
url = None
|
||
|
return Post(text=text, cal_user=user, cal_url=url)
|
||
|
|
||
|
|
||
|
def format_masto(self) -> str:
|
||
|
"""
|
||
|
Format a post to go from git -> masto.
|
||
|
|
||
|
Needs to have a :attr:`.commit` attribute!
|
||
|
|
||
|
Does not split the body text into multiple toots.
|
||
|
That should be handled in the posting action
|
||
|
|
||
|
Example:
|
||
|
|
||
|
git-social: https://{repo_url}/commits/{hash}
|
||
|
{subject line}
|
||
|
{body}
|
||
|
"""
|
||
|
if self.commit is not None:
|
||
|
return f"xpost from git-social: {self.commit.url}\n---\n{self.text}"""
|
||
|
elif self.cal_user is not None:
|
||
|
return f"xpost from a calendar\n---\n{self.text}"""
|
||
|
else:
|
||
|
return self.text
|
||
|
|
||
|
def format_commit(self) -> str:
|
||
|
"""
|
||
|
Add a link back to original masto post split by double lines
|
||
|
"""
|
||
|
return f"xpost from mastodon: {self.status.url}\n\n{self.text}"
|
||
|
|
||
|
def format_caldav(self) -> Event:
|
||
|
"""
|
||
|
Format a mastodon post for posting to CALDAV
|
||
|
"""
|
||
|
return Event(
|
||
|
dtstart=self.status.created_at,
|
||
|
dtend = self.status.created_at + timedelta(minutes=5),
|
||
|
location = self.status.url,
|
||
|
summary= self.status.account.acct,
|
||
|
description = self.text
|
||
|
)
|