2022-11-08 12:19:05 -06:00
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
import re
|
|
|
|
|
import arrow
|
|
|
|
|
import languageHandler
|
|
|
|
|
from string import Template
|
2022-11-12 11:20:16 -06:00
|
|
|
|
from . import utils, compose
|
2022-11-08 12:19:05 -06:00
|
|
|
|
|
|
|
|
|
# Define variables that would be available for all template objects.
|
|
|
|
|
# This will be used for the edit template dialog.
|
2022-11-16 13:28:45 -06:00
|
|
|
|
# Available variables for post objects.
|
|
|
|
|
# safe_text will be the content warning in case a post contains one, text will always be the full text, no matter if has a content warning or not.
|
|
|
|
|
post_variables = ["date", "display_name", "screen_name", "source", "lang", "safe_text", "text", "image_descriptions", "visibility"]
|
|
|
|
|
person_variables = ["display_name", "screen_name", "description", "followers", "following", "favorites", "posts", "created_at"]
|
|
|
|
|
conversation_variables = ["users", "last_post"]
|
2022-11-08 12:19:05 -06:00
|
|
|
|
|
|
|
|
|
# Default, translatable templates.
|
2022-11-16 13:28:45 -06:00
|
|
|
|
post_default_template = _("$display_name, $text $image_descriptions $date. $source")
|
2022-11-08 12:19:05 -06:00
|
|
|
|
dm_sent_default_template = _("Dm to $recipient_display_name, $text $date")
|
2022-11-16 13:28:45 -06:00
|
|
|
|
person_default_template = _("$display_name (@$screen_name). $followers followers, $following following, $posts posts. Joined $created_at.")
|
2022-11-08 12:19:05 -06:00
|
|
|
|
|
|
|
|
|
def process_date(field, relative_times=True, offset_hours=0):
|
|
|
|
|
original_date = arrow.get(field)
|
|
|
|
|
if relative_times == True:
|
|
|
|
|
ts = original_date.humanize(locale=languageHandler.curLang[:2])
|
|
|
|
|
else:
|
|
|
|
|
ts = original_date.shift(hours=offset_hours).format(_("dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.curLang[:2])
|
|
|
|
|
return ts
|
|
|
|
|
|
2022-11-16 13:28:45 -06:00
|
|
|
|
def process_text(post, safe=True):
|
2022-11-08 12:19:05 -06:00
|
|
|
|
# text = utils.clean_mentions(utils.StripChars(text))
|
2022-11-16 13:28:45 -06:00
|
|
|
|
if safe == True and post.sensitive == True and post.spoiler_text != "":
|
|
|
|
|
return _("Content warning: {}").format(post.spoiler_text)
|
|
|
|
|
return utils.html_filter(post.content)
|
2022-11-08 12:19:05 -06:00
|
|
|
|
|
2022-11-09 08:54:47 -06:00
|
|
|
|
def process_image_descriptions(media_attachments):
|
|
|
|
|
""" Attempt to extract information for image descriptions. """
|
|
|
|
|
image_descriptions = []
|
|
|
|
|
for media in media_attachments:
|
2022-11-11 15:51:16 -06:00
|
|
|
|
if media.get("description") != None and media.get("description") != "":
|
2022-11-09 08:54:47 -06:00
|
|
|
|
image_descriptions.append(media.get("description"))
|
|
|
|
|
idescriptions = ""
|
|
|
|
|
for image in image_descriptions:
|
2022-11-16 12:40:52 -06:00
|
|
|
|
idescriptions = idescriptions + _("Image description: {}").format(image) + "\n"
|
2022-11-09 08:54:47 -06:00
|
|
|
|
return idescriptions
|
|
|
|
|
|
2022-11-08 12:19:05 -06:00
|
|
|
|
def remove_unneeded_variables(template, variables):
|
|
|
|
|
for variable in variables:
|
|
|
|
|
template = re.sub("\$"+variable, "", template)
|
|
|
|
|
return template
|
|
|
|
|
|
2022-11-16 13:28:45 -06:00
|
|
|
|
def render_post(post, template, relative_times=False, offset_hours=0):
|
|
|
|
|
""" Renders any given post according to the passed template.
|
|
|
|
|
Available data for posts will be stored in the following variables:
|
2022-11-08 12:19:05 -06:00
|
|
|
|
$date: Creation date.
|
|
|
|
|
$display_name: User profile name.
|
|
|
|
|
$screen_name: User screen name, this is the same name used to reference the user in Twitter.
|
|
|
|
|
$ source: Source client from where the current tweet was sent.
|
|
|
|
|
$lang: Two letter code for the automatically detected language for the tweet. This detection is performed by Twitter.
|
2022-11-16 13:28:45 -06:00
|
|
|
|
$safe_text: Safe text to display. If a content warning is applied in posts, display those instead of the whole post.
|
2022-11-10 15:32:49 -06:00
|
|
|
|
$text: Toot text. This always displays the full text, even if there is a content warning present.
|
2022-11-08 12:19:05 -06:00
|
|
|
|
$image_descriptions: Information regarding image descriptions added by twitter users.
|
2022-11-16 13:28:45 -06:00
|
|
|
|
$visibility: post's visibility: public, not listed, followers only or direct.
|
2022-11-08 12:19:05 -06:00
|
|
|
|
"""
|
2022-11-16 13:28:45 -06:00
|
|
|
|
global post_variables
|
2022-11-08 12:19:05 -06:00
|
|
|
|
available_data = dict()
|
2022-11-16 13:28:45 -06:00
|
|
|
|
created_at = process_date(post.created_at, relative_times, offset_hours)
|
2022-11-08 12:19:05 -06:00
|
|
|
|
available_data.update(date=created_at)
|
|
|
|
|
# user.
|
2022-11-16 13:28:45 -06:00
|
|
|
|
display_name = post.account.display_name
|
2022-11-08 15:46:16 -06:00
|
|
|
|
if display_name == "":
|
2022-11-16 13:28:45 -06:00
|
|
|
|
display_name = post.account.username
|
|
|
|
|
available_data.update(display_name=display_name, screen_name=post.account.acct)
|
2022-11-08 12:19:05 -06:00
|
|
|
|
# Source client from where tweet was originated.
|
|
|
|
|
source = ""
|
2022-11-16 13:28:45 -06:00
|
|
|
|
if hasattr(post, "application") and post.application != None:
|
|
|
|
|
available_data.update(source=post.application.get("name"))
|
|
|
|
|
if post.reblog != None:
|
|
|
|
|
text = _("Boosted from @{}: {}").format(post.reblog.account.acct, process_text(post.reblog, safe=False), )
|
|
|
|
|
safe_text = _("Boosted from @{}: {}").format(post.reblog.account.acct, process_text(post.reblog), )
|
2022-11-08 12:19:05 -06:00
|
|
|
|
else:
|
2022-11-16 13:28:45 -06:00
|
|
|
|
text = process_text(post, safe=False)
|
|
|
|
|
safe_text = process_text(post)
|
2022-11-12 15:16:20 -06:00
|
|
|
|
visibility_settings = dict(public=_("Public"), unlisted=_("Not listed"), private=_("Followers only"), direct=_("Direct"))
|
2022-11-16 13:28:45 -06:00
|
|
|
|
visibility = visibility_settings.get(post.visibility)
|
|
|
|
|
available_data.update(lang=post.language, text=text, safe_text=safe_text, visibility=visibility)
|
2022-11-08 12:19:05 -06:00
|
|
|
|
# process image descriptions
|
|
|
|
|
image_descriptions = ""
|
2022-11-16 13:28:45 -06:00
|
|
|
|
if post.reblog != None:
|
|
|
|
|
image_descriptions = process_image_descriptions(post.reblog.media_attachments)
|
2022-11-09 08:54:47 -06:00
|
|
|
|
else:
|
2022-11-16 13:28:45 -06:00
|
|
|
|
image_descriptions = process_image_descriptions(post.media_attachments)
|
2022-11-09 08:54:47 -06:00
|
|
|
|
if image_descriptions != "":
|
|
|
|
|
available_data.update(image_descriptions=image_descriptions)
|
2022-11-08 12:19:05 -06:00
|
|
|
|
result = Template(_(template)).safe_substitute(**available_data)
|
2022-11-16 13:28:45 -06:00
|
|
|
|
result = remove_unneeded_variables(result, post_variables)
|
2022-11-08 12:19:05 -06:00
|
|
|
|
return result
|
|
|
|
|
|
2022-11-13 22:17:28 -06:00
|
|
|
|
def render_user(user, template, relative_times=True, offset_hours=0):
|
2022-11-08 12:19:05 -06:00
|
|
|
|
""" Renders persons by using the provided template.
|
|
|
|
|
Available data will be stored in the following variables:
|
|
|
|
|
$display_name: The name of the user, as they’ve defined it. Not necessarily a person’s name. Typically capped at 50 characters, but subject to change.
|
|
|
|
|
$screen_name: The screen name, handle, or alias that this user identifies themselves with.
|
|
|
|
|
$description: The user-defined UTF-8 string describing their account.
|
|
|
|
|
$followers: The number of followers this account currently has. This value might be inaccurate.
|
|
|
|
|
$following: The number of users this account is following (AKA their “followings”). This value might be inaccurate.
|
2022-11-16 13:28:45 -06:00
|
|
|
|
$posts: The number of Tweets (including retweets) issued by the user. This value might be inaccurate.
|
2022-11-08 12:19:05 -06:00
|
|
|
|
$created_at: The date and time that the user account was created on Twitter.
|
|
|
|
|
"""
|
|
|
|
|
global person_variables
|
2022-11-08 15:46:16 -06:00
|
|
|
|
display_name = user.display_name
|
|
|
|
|
if display_name == "":
|
|
|
|
|
display_name = user.username
|
2022-11-16 13:28:45 -06:00
|
|
|
|
available_data = dict(display_name=display_name, screen_name=user.acct, followers=user.followers_count, following=user.following_count, posts=user.statuses_count)
|
2022-11-08 12:19:05 -06:00
|
|
|
|
# Nullable values.
|
|
|
|
|
nullables = ["description"]
|
|
|
|
|
for nullable in nullables:
|
|
|
|
|
if hasattr(user, nullable) and getattr(user, nullable) != None:
|
|
|
|
|
available_data[nullable] = getattr(user, nullable)
|
|
|
|
|
created_at = process_date(user.created_at, relative_times=relative_times, offset_hours=offset_hours)
|
|
|
|
|
available_data.update(created_at=created_at)
|
|
|
|
|
result = Template(_(template)).safe_substitute(**available_data)
|
|
|
|
|
result = remove_unneeded_variables(result, person_variables)
|
2022-11-12 11:20:16 -06:00
|
|
|
|
return result
|
|
|
|
|
|
2022-11-16 13:28:45 -06:00
|
|
|
|
def render_conversation(conversation, template, post_template, relative_times=False, offset_hours=0):
|
2022-11-12 11:20:16 -06:00
|
|
|
|
users = []
|
|
|
|
|
for account in conversation.accounts:
|
|
|
|
|
if account.display_name != "":
|
|
|
|
|
users.append(account.display_name)
|
|
|
|
|
else:
|
|
|
|
|
users.append(account.username)
|
|
|
|
|
users = ", ".join(users)
|
2022-11-16 13:28:45 -06:00
|
|
|
|
last_post = render_post(conversation.last_status, post_template, relative_times=relative_times, offset_hours=offset_hours)
|
|
|
|
|
available_data = dict(users=users, last_post=last_post)
|
2022-11-12 11:20:16 -06:00
|
|
|
|
result = Template(_(template)).safe_substitute(**available_data)
|
|
|
|
|
result = remove_unneeded_variables(result, conversation_variables)
|
2022-11-08 12:19:05 -06:00
|
|
|
|
return result
|