2020-04-01 21:29:04 +00:00
|
|
|
__filename__ = "blog.py"
|
|
|
|
__author__ = "Bob Mottram"
|
|
|
|
__license__ = "AGPL3+"
|
2024-01-21 19:01:20 +00:00
|
|
|
__version__ = "1.5.0"
|
2020-04-01 21:29:04 +00:00
|
|
|
__maintainer__ = "Bob Mottram"
|
2021-09-10 16:14:50 +00:00
|
|
|
__email__ = "bob@libreserver.org"
|
2020-04-01 21:29:04 +00:00
|
|
|
__status__ = "Production"
|
2021-06-15 15:08:12 +00:00
|
|
|
__module_group__ = "ActivityPub"
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2020-02-25 13:35:41 +00:00
|
|
|
import os
|
|
|
|
|
2021-12-29 21:55:09 +00:00
|
|
|
from content import replace_emoji_from_tags
|
|
|
|
from webapp_utils import html_header_with_external_style
|
|
|
|
from webapp_utils import html_header_with_blog_markup
|
|
|
|
from webapp_utils import html_footer
|
|
|
|
from webapp_utils import get_post_attachments_as_html
|
|
|
|
from webapp_utils import edit_text_area
|
|
|
|
from webapp_media import add_embedded_elements
|
2024-08-08 17:23:33 +00:00
|
|
|
from utils import replace_strings
|
2024-05-12 12:35:26 +00:00
|
|
|
from utils import data_dir
|
2024-04-24 19:35:04 +00:00
|
|
|
from utils import remove_link_tracking
|
2023-12-09 14:18:24 +00:00
|
|
|
from utils import get_url_from_post
|
2023-11-20 22:27:58 +00:00
|
|
|
from utils import date_from_string_format
|
2023-09-26 20:25:53 +00:00
|
|
|
from utils import get_attributed_to
|
2022-06-21 11:58:50 +00:00
|
|
|
from utils import remove_eol
|
2022-06-10 11:43:33 +00:00
|
|
|
from utils import text_in_file
|
2021-12-26 10:19:59 +00:00
|
|
|
from utils import local_actor_url
|
2021-12-26 10:22:19 +00:00
|
|
|
from utils import get_actor_languages_list
|
2021-12-26 11:29:40 +00:00
|
|
|
from utils import get_base_content_from_post
|
2021-12-26 10:50:49 +00:00
|
|
|
from utils import get_content_from_post
|
2021-12-26 18:46:43 +00:00
|
|
|
from utils import is_account_dir
|
2021-12-27 15:43:22 +00:00
|
|
|
from utils import remove_html
|
2021-12-26 14:08:58 +00:00
|
|
|
from utils import get_config_param
|
2021-12-26 12:45:03 +00:00
|
|
|
from utils import get_full_domain
|
2021-12-27 15:56:15 +00:00
|
|
|
from utils import get_media_formats
|
2021-12-27 22:19:18 +00:00
|
|
|
from utils import get_nickname_from_actor
|
2021-12-27 19:05:25 +00:00
|
|
|
from utils import get_domain_from_actor
|
2021-12-26 20:36:08 +00:00
|
|
|
from utils import locate_post
|
2021-12-26 15:13:34 +00:00
|
|
|
from utils import load_json
|
2021-12-27 15:52:08 +00:00
|
|
|
from utils import first_paragraph_from_string
|
2021-12-26 18:22:20 +00:00
|
|
|
from utils import get_actor_property_url
|
2021-12-26 12:02:29 +00:00
|
|
|
from utils import acct_dir
|
2023-01-02 09:55:41 +00:00
|
|
|
from utils import escape_text
|
2021-12-29 21:55:09 +00:00
|
|
|
from posts import create_blogs_timeline
|
|
|
|
from newswire import rss2header
|
|
|
|
from newswire import rss2footer
|
|
|
|
from cache import get_person_from_cache
|
2020-02-25 13:35:41 +00:00
|
|
|
|
|
|
|
|
2021-12-29 21:55:09 +00:00
|
|
|
def _no_of_blog_replies(base_dir: str, http_prefix: str, translate: {},
|
|
|
|
nickname: str, domain: str, domain_full: str,
|
2024-05-01 10:41:43 +00:00
|
|
|
post_id: str, depth: int) -> int:
|
2020-02-25 20:31:37 +00:00
|
|
|
"""Returns the number of replies on the post
|
2020-02-26 10:03:09 +00:00
|
|
|
This is recursive, so can handle replies to replies
|
2020-02-25 20:31:37 +00:00
|
|
|
"""
|
2020-04-01 21:29:04 +00:00
|
|
|
if depth > 4:
|
2020-02-26 10:03:09 +00:00
|
|
|
return 0
|
2021-12-26 19:47:06 +00:00
|
|
|
if not post_id:
|
2020-02-25 20:31:37 +00:00
|
|
|
return 0
|
2020-02-26 10:10:16 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
try_post_box = ('tlblogs', 'inbox', 'outbox')
|
|
|
|
box_found = False
|
|
|
|
for post_box in try_post_box:
|
2021-12-26 23:41:34 +00:00
|
|
|
post_filename = \
|
2021-12-30 11:06:33 +00:00
|
|
|
acct_dir(base_dir, nickname, domain) + '/' + post_box + '/' + \
|
2021-12-26 19:47:06 +00:00
|
|
|
post_id.replace('/', '#') + '.replies'
|
2021-12-26 23:41:34 +00:00
|
|
|
if os.path.isfile(post_filename):
|
2021-12-30 11:06:33 +00:00
|
|
|
box_found = True
|
2020-02-26 10:10:16 +00:00
|
|
|
break
|
2021-12-30 11:06:33 +00:00
|
|
|
if not box_found:
|
2020-02-26 10:26:04 +00:00
|
|
|
# post may exist but has no replies
|
2021-12-30 11:06:33 +00:00
|
|
|
for post_box in try_post_box:
|
2021-12-26 23:41:34 +00:00
|
|
|
post_filename = \
|
2021-12-30 11:06:33 +00:00
|
|
|
acct_dir(base_dir, nickname, domain) + '/' + post_box + '/' + \
|
2021-12-26 19:47:06 +00:00
|
|
|
post_id.replace('/', '#')
|
2021-12-26 23:41:34 +00:00
|
|
|
if os.path.isfile(post_filename):
|
2020-02-26 10:26:04 +00:00
|
|
|
return 1
|
2020-02-25 20:31:37 +00:00
|
|
|
return 0
|
2020-02-26 10:10:16 +00:00
|
|
|
|
2020-05-18 09:42:02 +00:00
|
|
|
removals = []
|
2020-04-01 21:29:04 +00:00
|
|
|
replies = 0
|
2020-05-18 09:42:02 +00:00
|
|
|
lines = []
|
2021-11-26 12:28:20 +00:00
|
|
|
try:
|
2024-07-14 13:01:46 +00:00
|
|
|
with open(post_filename, 'r', encoding='utf-8') as fp_post:
|
|
|
|
lines = fp_post.readlines()
|
2021-11-26 12:28:20 +00:00
|
|
|
except OSError:
|
2021-12-26 23:41:34 +00:00
|
|
|
print('EX: failed to read blog ' + post_filename)
|
2021-11-26 12:28:20 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
for reply_post_id in lines:
|
2022-06-21 11:58:50 +00:00
|
|
|
reply_post_id = remove_eol(reply_post_id)
|
2021-12-30 11:06:33 +00:00
|
|
|
reply_post_id = reply_post_id.replace('.json', '')
|
|
|
|
if locate_post(base_dir, nickname, domain, reply_post_id):
|
|
|
|
reply_post_id = reply_post_id.replace('.replies', '')
|
2021-11-26 12:28:20 +00:00
|
|
|
replies += \
|
2021-12-29 21:55:09 +00:00
|
|
|
1 + _no_of_blog_replies(base_dir, http_prefix, translate,
|
|
|
|
nickname, domain, domain_full,
|
2021-12-30 11:06:33 +00:00
|
|
|
reply_post_id, depth+1)
|
2021-11-26 12:28:20 +00:00
|
|
|
else:
|
|
|
|
# remove post which no longer exists
|
2021-12-30 11:06:33 +00:00
|
|
|
removals.append(reply_post_id)
|
2020-05-18 09:42:02 +00:00
|
|
|
|
|
|
|
# remove posts from .replies file if they don't exist
|
|
|
|
if lines and removals:
|
2021-12-26 23:41:34 +00:00
|
|
|
print('Rewriting ' + post_filename + ' to remove ' +
|
2020-05-18 09:42:02 +00:00
|
|
|
str(len(removals)) + ' entries')
|
2021-11-25 18:42:38 +00:00
|
|
|
try:
|
2024-07-14 13:01:46 +00:00
|
|
|
with open(post_filename, 'w+', encoding='utf-8') as fp_post:
|
2021-12-30 11:06:33 +00:00
|
|
|
for reply_post_id in lines:
|
2022-06-21 11:58:50 +00:00
|
|
|
reply_post_id = remove_eol(reply_post_id)
|
2021-12-30 11:06:33 +00:00
|
|
|
if reply_post_id not in removals:
|
2024-07-14 13:01:46 +00:00
|
|
|
fp_post.write(reply_post_id + '\n')
|
2021-12-25 15:28:52 +00:00
|
|
|
except OSError as ex:
|
2021-11-25 22:22:54 +00:00
|
|
|
print('EX: unable to remove replies from post ' +
|
2021-12-26 23:41:34 +00:00
|
|
|
post_filename + ' ' + str(ex))
|
2020-05-18 09:42:02 +00:00
|
|
|
|
2020-02-26 10:03:09 +00:00
|
|
|
return replies
|
2020-02-25 20:31:37 +00:00
|
|
|
|
|
|
|
|
2021-12-29 21:55:09 +00:00
|
|
|
def _get_blog_replies(base_dir: str, http_prefix: str, translate: {},
|
|
|
|
nickname: str, domain: str, domain_full: str,
|
2024-05-01 10:41:43 +00:00
|
|
|
post_id: str, depth: int) -> str:
|
2020-05-18 14:00:47 +00:00
|
|
|
"""Returns a string containing html blog posts
|
2020-02-25 20:53:02 +00:00
|
|
|
"""
|
2020-04-01 21:29:04 +00:00
|
|
|
if depth > 4:
|
2020-02-26 10:03:09 +00:00
|
|
|
return ''
|
2021-12-26 19:47:06 +00:00
|
|
|
if not post_id:
|
2020-02-25 20:53:02 +00:00
|
|
|
return ''
|
2020-02-26 10:10:16 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
try_post_box = ('tlblogs', 'inbox', 'outbox')
|
|
|
|
box_found = False
|
|
|
|
for post_box in try_post_box:
|
2021-12-26 23:41:34 +00:00
|
|
|
post_filename = \
|
2021-12-30 11:06:33 +00:00
|
|
|
acct_dir(base_dir, nickname, domain) + '/' + post_box + '/' + \
|
2021-12-26 19:47:06 +00:00
|
|
|
post_id.replace('/', '#') + '.replies'
|
2021-12-26 23:41:34 +00:00
|
|
|
if os.path.isfile(post_filename):
|
2021-12-30 11:06:33 +00:00
|
|
|
box_found = True
|
2020-02-26 10:10:16 +00:00
|
|
|
break
|
2021-12-30 11:06:33 +00:00
|
|
|
if not box_found:
|
2020-02-26 10:26:04 +00:00
|
|
|
# post may exist but has no replies
|
2021-12-30 11:06:33 +00:00
|
|
|
for post_box in try_post_box:
|
2021-12-26 23:41:34 +00:00
|
|
|
post_filename = \
|
2021-12-30 11:06:33 +00:00
|
|
|
acct_dir(base_dir, nickname, domain) + '/' + post_box + '/' + \
|
2021-12-26 19:47:06 +00:00
|
|
|
post_id.replace('/', '#') + '.json'
|
2021-12-26 23:41:34 +00:00
|
|
|
if os.path.isfile(post_filename):
|
|
|
|
post_filename = acct_dir(base_dir, nickname, domain) + \
|
2020-04-01 21:29:04 +00:00
|
|
|
'/postcache/' + \
|
2021-12-26 19:47:06 +00:00
|
|
|
post_id.replace('/', '#') + '.html'
|
2021-12-26 23:41:34 +00:00
|
|
|
if os.path.isfile(post_filename):
|
2021-11-26 12:28:20 +00:00
|
|
|
try:
|
2022-06-09 14:46:30 +00:00
|
|
|
with open(post_filename, 'r',
|
2024-07-14 13:01:46 +00:00
|
|
|
encoding='utf-8') as fp_post:
|
|
|
|
return fp_post.read() + '\n'
|
2021-11-26 12:28:20 +00:00
|
|
|
except OSError:
|
2021-12-26 23:41:34 +00:00
|
|
|
print('EX: unable to read blog 3 ' + post_filename)
|
2020-02-25 20:53:02 +00:00
|
|
|
return ''
|
2020-02-26 10:10:16 +00:00
|
|
|
|
2021-11-26 12:28:20 +00:00
|
|
|
lines = []
|
|
|
|
try:
|
2024-07-14 13:01:46 +00:00
|
|
|
with open(post_filename, 'r', encoding='utf-8') as fp_post:
|
|
|
|
lines = fp_post.readlines()
|
2021-11-26 12:28:20 +00:00
|
|
|
except OSError:
|
2021-12-26 23:41:34 +00:00
|
|
|
print('EX: unable to read blog 4 ' + post_filename)
|
2021-11-26 12:28:20 +00:00
|
|
|
|
|
|
|
if lines:
|
2021-12-30 11:06:33 +00:00
|
|
|
replies_str = ''
|
|
|
|
for reply_post_id in lines:
|
2022-06-21 11:58:50 +00:00
|
|
|
reply_post_id = remove_eol(reply_post_id)
|
2024-08-08 17:23:33 +00:00
|
|
|
replacements = {
|
|
|
|
'.json': '',
|
|
|
|
'.replies': ''
|
|
|
|
}
|
|
|
|
reply_post_id = replace_strings(reply_post_id, replacements)
|
2021-12-26 23:41:34 +00:00
|
|
|
post_filename = acct_dir(base_dir, nickname, domain) + \
|
2020-04-01 21:29:04 +00:00
|
|
|
'/postcache/' + \
|
2021-12-30 11:06:33 +00:00
|
|
|
reply_post_id.replace('/', '#') + '.html'
|
2021-12-26 23:41:34 +00:00
|
|
|
if not os.path.isfile(post_filename):
|
2020-02-25 20:53:02 +00:00
|
|
|
continue
|
2021-11-26 12:28:20 +00:00
|
|
|
try:
|
2024-07-14 13:01:46 +00:00
|
|
|
with open(post_filename, 'r', encoding='utf-8') as fp_post:
|
|
|
|
replies_str += fp_post.read() + '\n'
|
2021-11-26 12:28:20 +00:00
|
|
|
except OSError:
|
2021-12-26 23:41:34 +00:00
|
|
|
print('EX: unable to read blog replies ' + post_filename)
|
2021-12-29 21:55:09 +00:00
|
|
|
rply = _get_blog_replies(base_dir, http_prefix, translate,
|
|
|
|
nickname, domain, domain_full,
|
2021-12-30 11:06:33 +00:00
|
|
|
reply_post_id, depth+1)
|
|
|
|
if rply not in replies_str:
|
|
|
|
replies_str += rply
|
2020-02-26 10:03:09 +00:00
|
|
|
|
|
|
|
# indicate the reply indentation level
|
2021-12-30 11:06:33 +00:00
|
|
|
indent_str = '>'
|
|
|
|
indent_level = 0
|
|
|
|
while indent_level < depth:
|
|
|
|
indent_str += ' >'
|
|
|
|
indent_level += 1
|
|
|
|
|
|
|
|
replies_str = replies_str.replace(translate['SHOW MORE'], indent_str)
|
|
|
|
return replies_str.replace('?tl=outbox', '?tl=tlblogs')
|
2020-02-25 20:53:02 +00:00
|
|
|
return ''
|
|
|
|
|
|
|
|
|
2021-12-28 22:22:09 +00:00
|
|
|
def _html_blog_post_content(debug: bool, session, authorized: bool,
|
|
|
|
base_dir: str, http_prefix: str, translate: {},
|
|
|
|
nickname: str, domain: str, domain_full: str,
|
|
|
|
post_json_object: {},
|
2021-12-30 11:06:33 +00:00
|
|
|
handle: str, restrict_to_domain: bool,
|
2021-12-28 22:22:09 +00:00
|
|
|
peertube_instances: [],
|
|
|
|
system_language: str,
|
|
|
|
person_cache: {},
|
2024-02-19 15:38:08 +00:00
|
|
|
blog_separator: str) -> str:
|
2020-02-25 13:35:41 +00:00
|
|
|
"""Returns the content for a single blog post
|
|
|
|
"""
|
2021-12-30 11:06:33 +00:00
|
|
|
linked_author = False
|
2020-04-01 21:29:04 +00:00
|
|
|
actor = ''
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str = ''
|
|
|
|
message_link = ''
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('id'):
|
2021-12-30 11:06:33 +00:00
|
|
|
message_link = \
|
2021-12-25 22:09:19 +00:00
|
|
|
post_json_object['object']['id'].replace('/statuses/', '/')
|
2021-12-30 11:06:33 +00:00
|
|
|
title_str = ''
|
|
|
|
article_added = False
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('summary'):
|
2021-12-30 11:06:33 +00:00
|
|
|
title_str = post_json_object['object']['summary']
|
|
|
|
blog_str += '<article><h1><a href="' + message_link + '">' + \
|
|
|
|
title_str + '</a></h1>\n'
|
|
|
|
article_added = True
|
2020-02-25 13:35:41 +00:00
|
|
|
|
|
|
|
# get the handle of the author
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('attributedTo'):
|
2021-12-30 11:06:33 +00:00
|
|
|
author_nickname = None
|
2023-09-26 20:25:53 +00:00
|
|
|
actor_str = \
|
|
|
|
get_attributed_to(post_json_object['object']['attributedTo'])
|
|
|
|
if actor_str:
|
|
|
|
actor = actor_str
|
2021-12-30 11:06:33 +00:00
|
|
|
author_nickname = get_nickname_from_actor(actor)
|
|
|
|
if author_nickname:
|
|
|
|
author_domain, _ = get_domain_from_actor(actor)
|
|
|
|
if author_domain:
|
2020-02-25 13:35:41 +00:00
|
|
|
# author must be from the given domain
|
2021-12-30 11:06:33 +00:00
|
|
|
if restrict_to_domain and author_domain != domain:
|
2020-02-25 13:35:41 +00:00
|
|
|
return ''
|
2021-12-30 11:06:33 +00:00
|
|
|
handle = author_nickname + '@' + author_domain
|
2020-02-25 13:35:41 +00:00
|
|
|
else:
|
|
|
|
# posts from the domain are expected to have an attributedTo field
|
2021-12-30 11:06:33 +00:00
|
|
|
if restrict_to_domain:
|
2020-02-25 13:35:41 +00:00
|
|
|
return ''
|
2020-03-22 21:16:02 +00:00
|
|
|
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('published'):
|
|
|
|
if 'T' in post_json_object['object']['published']:
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '<h3>' + \
|
2021-12-25 22:09:19 +00:00
|
|
|
post_json_object['object']['published'].split('T')[0]
|
2020-02-25 13:35:41 +00:00
|
|
|
if handle:
|
2020-04-01 21:29:04 +00:00
|
|
|
if handle.startswith(nickname + '@' + domain):
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += ' <a href="' + http_prefix + '://' + \
|
2021-12-26 10:00:46 +00:00
|
|
|
domain_full + \
|
2020-04-01 21:29:04 +00:00
|
|
|
'/users/' + nickname + '">' + handle + '</a>'
|
2021-12-30 11:06:33 +00:00
|
|
|
linked_author = True
|
2020-02-25 13:35:41 +00:00
|
|
|
else:
|
2020-04-01 21:29:04 +00:00
|
|
|
if actor:
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += ' <a href="' + actor + '">' + \
|
2020-04-01 21:29:04 +00:00
|
|
|
handle + '</a>'
|
2021-12-30 11:06:33 +00:00
|
|
|
linked_author = True
|
2020-02-25 13:35:41 +00:00
|
|
|
else:
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += ' ' + handle
|
|
|
|
blog_str += '</h3>\n'
|
|
|
|
|
|
|
|
avatar_link = ''
|
|
|
|
reply_str = ''
|
|
|
|
announce_str = ''
|
|
|
|
like_str = ''
|
|
|
|
bookmark_str = ''
|
|
|
|
delete_str = ''
|
|
|
|
mute_str = ''
|
2021-12-29 21:55:09 +00:00
|
|
|
is_muted = False
|
2021-12-30 11:06:33 +00:00
|
|
|
|
|
|
|
person_url = local_actor_url(http_prefix, nickname, domain_full)
|
2021-12-26 10:29:52 +00:00
|
|
|
actor_json = \
|
2022-06-09 16:54:44 +00:00
|
|
|
get_person_from_cache(base_dir, person_url, person_cache)
|
2021-12-26 10:52:54 +00:00
|
|
|
languages_understood = []
|
2021-12-26 10:29:52 +00:00
|
|
|
if actor_json:
|
2021-12-26 10:52:54 +00:00
|
|
|
languages_understood = get_actor_languages_list(actor_json)
|
2021-12-30 11:06:33 +00:00
|
|
|
json_content = get_content_from_post(post_json_object, system_language,
|
2024-02-19 20:54:46 +00:00
|
|
|
languages_understood, "content")
|
2022-11-13 18:54:11 +00:00
|
|
|
minimize_all_images = False
|
2022-06-11 17:34:11 +00:00
|
|
|
attachment_str, _ = \
|
|
|
|
get_post_attachments_as_html(base_dir, nickname, domain,
|
|
|
|
domain_full, post_json_object,
|
|
|
|
'tlblogs', translate,
|
|
|
|
is_muted, avatar_link,
|
|
|
|
reply_str, announce_str,
|
|
|
|
like_str, bookmark_str,
|
|
|
|
delete_str, mute_str,
|
2022-11-13 18:54:11 +00:00
|
|
|
json_content,
|
2023-01-23 14:45:53 +00:00
|
|
|
minimize_all_images,
|
|
|
|
system_language)
|
2022-06-11 17:34:11 +00:00
|
|
|
if attachment_str:
|
|
|
|
blog_str += '<br><center>' + attachment_str + '</center>'
|
2021-12-30 11:06:33 +00:00
|
|
|
if json_content:
|
|
|
|
content_str = add_embedded_elements(translate, json_content,
|
2022-10-08 14:22:05 +00:00
|
|
|
peertube_instances, domain_full)
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('tag'):
|
|
|
|
post_json_object_tags = post_json_object['object']['tag']
|
2021-12-30 11:06:33 +00:00
|
|
|
content_str = replace_emoji_from_tags(session, base_dir,
|
|
|
|
content_str,
|
|
|
|
post_json_object_tags,
|
2022-04-21 13:03:40 +00:00
|
|
|
'content', debug, True)
|
2021-12-30 11:06:33 +00:00
|
|
|
if article_added:
|
|
|
|
blog_str += '<br>' + content_str + '</article>\n'
|
2020-11-08 13:01:01 +00:00
|
|
|
else:
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '<br><article>' + content_str + '</article>\n'
|
2020-02-25 13:35:41 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
citations_str = ''
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('tag'):
|
2021-12-30 11:06:33 +00:00
|
|
|
for tag_json in post_json_object['object']['tag']:
|
|
|
|
if not isinstance(tag_json, dict):
|
2020-11-06 14:04:09 +00:00
|
|
|
continue
|
2021-12-30 11:06:33 +00:00
|
|
|
if not tag_json.get('type'):
|
2020-11-06 14:04:09 +00:00
|
|
|
continue
|
2021-12-30 11:06:33 +00:00
|
|
|
if tag_json['type'] != 'Article':
|
2020-11-06 14:04:09 +00:00
|
|
|
continue
|
2021-12-30 11:06:33 +00:00
|
|
|
if not tag_json.get('name'):
|
2020-11-06 14:04:09 +00:00
|
|
|
continue
|
2021-12-30 11:06:33 +00:00
|
|
|
if not tag_json.get('url'):
|
2020-11-06 14:04:09 +00:00
|
|
|
continue
|
2023-12-09 14:18:24 +00:00
|
|
|
url_str = get_url_from_post(tag_json['url'])
|
|
|
|
citation_url = remove_html(url_str)
|
2023-07-12 11:08:02 +00:00
|
|
|
citation_name = remove_html(tag_json['name'])
|
2021-12-30 11:06:33 +00:00
|
|
|
citations_str += \
|
2023-07-12 11:08:02 +00:00
|
|
|
'<li><a href="' + citation_url + '">' + \
|
|
|
|
'<cite>' + citation_name + '</cite></a></li>\n'
|
2021-12-30 11:06:33 +00:00
|
|
|
if citations_str:
|
|
|
|
citations_str = '<p><b>' + translate['Citations'] + \
|
2020-11-06 14:04:09 +00:00
|
|
|
':</b></p>' + \
|
2022-06-27 16:21:48 +00:00
|
|
|
'<u>\n' + citations_str + '</u>\n'
|
2020-11-06 14:04:09 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '<br>\n' + citations_str
|
2020-02-25 20:31:37 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
if not linked_author:
|
|
|
|
blog_str += '<p class="about"><a class="about" href="' + \
|
2021-12-26 10:19:59 +00:00
|
|
|
local_actor_url(http_prefix, nickname, domain_full) + \
|
2021-08-14 11:13:39 +00:00
|
|
|
'">' + translate['About the author'] + \
|
2020-04-01 21:29:04 +00:00
|
|
|
'</a></p>\n'
|
|
|
|
|
2021-12-29 21:55:09 +00:00
|
|
|
replies = _no_of_blog_replies(base_dir, http_prefix, translate,
|
|
|
|
nickname, domain, domain_full,
|
2024-05-01 10:41:43 +00:00
|
|
|
post_json_object['object']['id'], 0)
|
2020-05-18 11:32:28 +00:00
|
|
|
|
|
|
|
# separator between blogs should be centered
|
2021-12-30 11:06:33 +00:00
|
|
|
if '<center>' not in blog_separator:
|
|
|
|
blog_separator = '<center>' + blog_separator + '</center>'
|
2020-05-18 11:32:28 +00:00
|
|
|
|
|
|
|
if replies == 0:
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += blog_separator + '\n'
|
|
|
|
return blog_str
|
2020-05-18 11:32:28 +00:00
|
|
|
|
|
|
|
if not authorized:
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '<p class="blogreplies">' + \
|
2020-05-18 11:32:28 +00:00
|
|
|
translate['Replies'].lower() + ': ' + str(replies) + '</p>'
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '<br><br><br>' + blog_separator + '\n'
|
2020-05-18 11:32:28 +00:00
|
|
|
else:
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += blog_separator + '<h1>' + translate['Replies'] + '</h1>\n'
|
|
|
|
if not title_str:
|
|
|
|
blog_str += \
|
|
|
|
_get_blog_replies(base_dir, http_prefix, translate,
|
|
|
|
nickname, domain, domain_full,
|
2024-05-01 10:41:43 +00:00
|
|
|
post_json_object['object']['id'], 0)
|
2020-02-25 21:40:13 +00:00
|
|
|
else:
|
2021-12-29 21:55:09 +00:00
|
|
|
obj_id = post_json_object['object']['id']
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_replies_str = \
|
|
|
|
_get_blog_replies(base_dir, http_prefix,
|
|
|
|
translate, nickname,
|
2024-05-01 10:41:43 +00:00
|
|
|
domain, domain_full, obj_id, 0)
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += blog_replies_str.replace('>' + title_str + '<', '')
|
2020-05-18 11:32:28 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
return blog_str
|
2020-02-25 13:35:41 +00:00
|
|
|
|
|
|
|
|
2022-06-09 11:02:34 +00:00
|
|
|
def _html_blog_post_rss2(domain: str, post_json_object: {},
|
|
|
|
restrict_to_domain: bool,
|
2021-12-28 22:22:09 +00:00
|
|
|
system_language: str) -> str:
|
2020-05-23 09:10:26 +00:00
|
|
|
"""Returns the RSS version 2 feed for a single blog post
|
2020-02-27 20:23:27 +00:00
|
|
|
"""
|
2021-12-30 11:06:33 +00:00
|
|
|
rss_str = ''
|
|
|
|
message_link = ''
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('id'):
|
2021-12-30 11:06:33 +00:00
|
|
|
message_link = \
|
2021-12-25 22:09:19 +00:00
|
|
|
post_json_object['object']['id'].replace('/statuses/', '/')
|
2021-12-30 11:06:33 +00:00
|
|
|
if not restrict_to_domain or \
|
|
|
|
(restrict_to_domain and '/' + domain in message_link):
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('summary') and \
|
|
|
|
post_json_object['object'].get('published'):
|
|
|
|
published = post_json_object['object']['published']
|
2023-11-20 22:27:58 +00:00
|
|
|
pub_date = date_from_string_format(published,
|
|
|
|
["%Y-%m-%dT%H:%M:%S%z"])
|
2023-01-02 09:55:41 +00:00
|
|
|
title_str = escape_text(post_json_object['object']['summary'])
|
2021-12-30 11:06:33 +00:00
|
|
|
rss_date_str = pub_date.strftime("%a, %d %b %Y %H:%M:%S UT")
|
2021-07-20 13:33:27 +00:00
|
|
|
content = \
|
2021-12-26 11:29:40 +00:00
|
|
|
get_base_content_from_post(post_json_object,
|
|
|
|
system_language)
|
2021-12-27 15:52:08 +00:00
|
|
|
description = first_paragraph_from_string(content)
|
2023-01-02 09:55:41 +00:00
|
|
|
description = escape_text(description)
|
2021-12-30 11:06:33 +00:00
|
|
|
rss_str = ' <item>'
|
|
|
|
rss_str += ' <title>' + title_str + '</title>'
|
|
|
|
rss_str += ' <link>' + message_link + '</link>'
|
|
|
|
rss_str += \
|
2020-11-08 10:30:25 +00:00
|
|
|
' <description>' + description + '</description>'
|
2021-12-30 11:06:33 +00:00
|
|
|
rss_str += ' <pubDate>' + rss_date_str + '</pubDate>'
|
|
|
|
rss_str += ' </item>'
|
|
|
|
return rss_str
|
2020-02-27 20:23:27 +00:00
|
|
|
|
|
|
|
|
2022-06-09 11:02:34 +00:00
|
|
|
def _html_blog_post_rss3(domain: str, post_json_object: {},
|
|
|
|
restrict_to_domain: bool,
|
2021-12-28 22:22:09 +00:00
|
|
|
system_language: str) -> str:
|
2020-05-23 09:41:50 +00:00
|
|
|
"""Returns the RSS version 3 feed for a single blog post
|
|
|
|
"""
|
2021-12-30 11:06:33 +00:00
|
|
|
rss_str = ''
|
|
|
|
message_link = ''
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('id'):
|
2021-12-30 11:06:33 +00:00
|
|
|
message_link = \
|
2021-12-25 22:09:19 +00:00
|
|
|
post_json_object['object']['id'].replace('/statuses/', '/')
|
2021-12-30 11:06:33 +00:00
|
|
|
if not restrict_to_domain or \
|
|
|
|
(restrict_to_domain and '/' + domain in message_link):
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('summary') and \
|
|
|
|
post_json_object['object'].get('published'):
|
|
|
|
published = post_json_object['object']['published']
|
2023-11-20 22:27:58 +00:00
|
|
|
pub_date = date_from_string_format(published,
|
|
|
|
["%Y-%m-%dT%H:%M:%S%z"])
|
2021-12-30 11:06:33 +00:00
|
|
|
title_str = post_json_object['object']['summary']
|
|
|
|
rss_date_str = pub_date.strftime("%a, %d %b %Y %H:%M:%S UT")
|
2021-07-20 13:33:27 +00:00
|
|
|
content = \
|
2021-12-26 11:29:40 +00:00
|
|
|
get_base_content_from_post(post_json_object,
|
|
|
|
system_language)
|
2021-12-27 15:52:08 +00:00
|
|
|
description = first_paragraph_from_string(content)
|
2021-12-30 11:06:33 +00:00
|
|
|
rss_str = 'title: ' + title_str + '\n'
|
|
|
|
rss_str += 'link: ' + message_link + '\n'
|
|
|
|
rss_str += 'description: ' + description + '\n'
|
|
|
|
rss_str += 'created: ' + rss_date_str + '\n\n'
|
|
|
|
return rss_str
|
2020-05-23 09:41:50 +00:00
|
|
|
|
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
def _html_blog_remove_cw_button(blog_str: str, translate: {}) -> str:
|
2020-07-03 10:07:11 +00:00
|
|
|
"""Removes the CW button from blog posts, where the
|
|
|
|
summary field is instead used as the blog title
|
|
|
|
"""
|
2024-08-08 17:23:33 +00:00
|
|
|
replacements = {
|
|
|
|
'<details>': '<b>',
|
|
|
|
'</details>': '</b>',
|
|
|
|
'<summary>': '',
|
|
|
|
'</summary>': ''
|
|
|
|
}
|
|
|
|
blog_str = replace_strings(blog_str, replacements)
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str = blog_str.replace(translate['SHOW MORE'], '')
|
|
|
|
return blog_str
|
2020-07-03 10:07:11 +00:00
|
|
|
|
|
|
|
|
2021-12-29 21:55:09 +00:00
|
|
|
def _get_snippet_from_blog_content(post_json_object: {},
|
|
|
|
system_language: str) -> str:
|
2021-05-15 19:39:34 +00:00
|
|
|
"""Returns a snippet of text from the blog post as a preview
|
|
|
|
"""
|
2021-12-26 11:29:40 +00:00
|
|
|
content = get_base_content_from_post(post_json_object, system_language)
|
2021-05-15 19:39:34 +00:00
|
|
|
if '<p>' in content:
|
|
|
|
content = content.split('<p>', 1)[1]
|
|
|
|
if '</p>' in content:
|
|
|
|
content = content.split('</p>', 1)[0]
|
2021-12-27 15:43:22 +00:00
|
|
|
content = remove_html(content)
|
2021-05-15 19:43:42 +00:00
|
|
|
if '\n' in content:
|
|
|
|
content = content.split('\n')[0]
|
2021-05-15 19:39:34 +00:00
|
|
|
if len(content) >= 256:
|
|
|
|
content = content[:252] + '...'
|
|
|
|
return content
|
|
|
|
|
|
|
|
|
2021-12-28 22:22:09 +00:00
|
|
|
def html_blog_post(session, authorized: bool,
|
|
|
|
base_dir: str, http_prefix: str, translate: {},
|
|
|
|
nickname: str, domain: str, domain_full: str,
|
|
|
|
post_json_object: {},
|
|
|
|
peertube_instances: [],
|
|
|
|
system_language: str, person_cache: {},
|
|
|
|
debug: bool, content_license_url: str) -> str:
|
2020-02-25 13:35:41 +00:00
|
|
|
"""Returns a html blog post
|
|
|
|
"""
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str = ''
|
2020-02-25 13:35:41 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
css_filename = base_dir + '/epicyon-blog.css'
|
2021-12-25 16:17:53 +00:00
|
|
|
if os.path.isfile(base_dir + '/blog.css'):
|
2021-12-30 11:06:33 +00:00
|
|
|
css_filename = base_dir + '/blog.css'
|
|
|
|
instance_title = \
|
2021-12-26 14:08:58 +00:00
|
|
|
get_config_param(base_dir, 'instanceTitle')
|
2021-12-25 22:09:19 +00:00
|
|
|
published = post_json_object['object']['published']
|
2021-11-08 13:20:06 +00:00
|
|
|
modified = published
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('updated'):
|
|
|
|
modified = post_json_object['object']['updated']
|
|
|
|
title = post_json_object['object']['summary']
|
2021-11-08 13:20:06 +00:00
|
|
|
url = ''
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('url'):
|
2023-12-09 14:18:24 +00:00
|
|
|
url_str = get_url_from_post(post_json_object['object']['url'])
|
|
|
|
url = remove_html(url_str)
|
2021-12-29 21:55:09 +00:00
|
|
|
snippet = _get_snippet_from_blog_content(post_json_object,
|
|
|
|
system_language)
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str = html_header_with_blog_markup(css_filename, instance_title,
|
|
|
|
http_prefix, domain_full, nickname,
|
|
|
|
system_language, published,
|
2024-02-07 10:12:03 +00:00
|
|
|
modified, title, snippet, url,
|
2021-12-30 11:06:33 +00:00
|
|
|
content_license_url)
|
|
|
|
_html_blog_remove_cw_button(blog_str, translate)
|
|
|
|
|
|
|
|
blog_str += _html_blog_post_content(debug, session, authorized, base_dir,
|
|
|
|
http_prefix, translate,
|
|
|
|
nickname, domain,
|
|
|
|
domain_full, post_json_object,
|
|
|
|
None, False,
|
|
|
|
peertube_instances, system_language,
|
2024-02-19 15:38:08 +00:00
|
|
|
person_cache, '<hr>')
|
2020-02-28 14:51:44 +00:00
|
|
|
|
2020-11-12 16:05:45 +00:00
|
|
|
# show rss links
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '<p class="rssfeed">'
|
2020-05-23 09:41:50 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '<a href="' + http_prefix + '://' + \
|
2021-12-26 10:00:46 +00:00
|
|
|
domain_full + '/blog/' + nickname + '/rss.xml">'
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '<img style="width:3%;min-width:50px" ' + \
|
2022-03-28 08:47:53 +00:00
|
|
|
'loading="lazy" decoding="async" alt="RSS 2.0" ' + \
|
2020-11-12 16:05:45 +00:00
|
|
|
'title="RSS 2.0" src="/' + \
|
2020-12-09 13:08:26 +00:00
|
|
|
'icons/logorss.png" /></a>'
|
2020-05-23 09:41:50 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
# blog_str += '<a href="' + http_prefix + '://' + \
|
2021-12-26 10:00:46 +00:00
|
|
|
# domain_full + '/blog/' + nickname + '/rss.txt">'
|
2021-12-30 11:06:33 +00:00
|
|
|
# blog_str += '<img style="width:3%;min-width:50px" ' + \
|
2022-03-28 08:47:53 +00:00
|
|
|
# 'loading="lazy" decoding="async" alt="RSS 3.0" ' + \
|
2020-11-12 16:05:45 +00:00
|
|
|
# 'title="RSS 3.0" src="/' + \
|
2020-12-09 13:08:26 +00:00
|
|
|
# 'icons/rss3.png" /></a>'
|
2020-05-23 09:41:50 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '</p>'
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
return blog_str + html_footer()
|
2020-02-25 13:35:41 +00:00
|
|
|
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-28 22:22:09 +00:00
|
|
|
def html_blog_page(authorized: bool, session,
|
|
|
|
base_dir: str, http_prefix: str, translate: {},
|
|
|
|
nickname: str, domain: str, port: int,
|
2021-12-30 11:06:33 +00:00
|
|
|
no_of_items: int, page_number: int,
|
2021-12-28 22:22:09 +00:00
|
|
|
peertube_instances: [], system_language: str,
|
|
|
|
person_cache: {}, debug: bool) -> str:
|
2020-02-25 13:35:41 +00:00
|
|
|
"""Returns a html blog page containing posts
|
|
|
|
"""
|
2020-05-22 11:32:38 +00:00
|
|
|
if ' ' in nickname or '@' in nickname or \
|
|
|
|
'\n' in nickname or '\r' in nickname:
|
2020-02-25 13:35:41 +00:00
|
|
|
return None
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str = ''
|
2020-02-25 13:35:41 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
css_filename = base_dir + '/epicyon-profile.css'
|
2021-12-25 16:17:53 +00:00
|
|
|
if os.path.isfile(base_dir + '/epicyon.css'):
|
2021-12-30 11:06:33 +00:00
|
|
|
css_filename = base_dir + '/epicyon.css'
|
|
|
|
instance_title = \
|
2021-12-26 14:08:58 +00:00
|
|
|
get_config_param(base_dir, 'instanceTitle')
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str = \
|
|
|
|
html_header_with_external_style(css_filename, instance_title, None)
|
|
|
|
_html_blog_remove_cw_button(blog_str, translate)
|
2020-02-27 20:23:27 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blogs_index = acct_dir(base_dir, nickname, domain) + '/tlblogs.index'
|
|
|
|
if not os.path.isfile(blogs_index):
|
|
|
|
return blog_str + html_footer()
|
2020-02-25 13:35:41 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
timeline_json = \
|
2022-05-31 15:16:55 +00:00
|
|
|
create_blogs_timeline(base_dir,
|
2021-12-30 11:06:33 +00:00
|
|
|
nickname, domain, port, http_prefix,
|
2023-01-02 10:44:49 +00:00
|
|
|
no_of_items, False, page_number)
|
2020-11-12 16:05:45 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
if not timeline_json:
|
|
|
|
return blog_str + html_footer()
|
2020-11-12 16:05:45 +00:00
|
|
|
|
2021-12-26 12:45:03 +00:00
|
|
|
domain_full = get_full_domain(domain, port)
|
2020-02-25 13:35:41 +00:00
|
|
|
|
2020-11-12 16:05:45 +00:00
|
|
|
# show previous and next buttons
|
2021-12-30 11:06:33 +00:00
|
|
|
if page_number is not None:
|
|
|
|
navigate_str = '<p>'
|
|
|
|
if page_number > 1:
|
2020-11-12 16:05:45 +00:00
|
|
|
# show previous button
|
2021-12-30 11:06:33 +00:00
|
|
|
navigate_str += '<a href="' + http_prefix + '://' + \
|
2021-12-26 10:00:46 +00:00
|
|
|
domain_full + '/blog/' + \
|
2021-12-30 11:06:33 +00:00
|
|
|
nickname + '?page=' + str(page_number-1) + '">' + \
|
2022-03-28 08:47:53 +00:00
|
|
|
'<img loading="lazy" decoding="async" alt="<" title="<" ' + \
|
2020-12-09 13:08:26 +00:00
|
|
|
'src="/icons' + \
|
2020-11-12 16:05:45 +00:00
|
|
|
'/prev.png" class="buttonprev"/></a>\n'
|
2021-12-30 11:06:33 +00:00
|
|
|
if len(timeline_json['orderedItems']) >= no_of_items:
|
2020-11-12 16:05:45 +00:00
|
|
|
# show next button
|
2021-12-30 11:06:33 +00:00
|
|
|
navigate_str += '<a href="' + http_prefix + '://' + \
|
2021-12-26 10:00:46 +00:00
|
|
|
domain_full + '/blog/' + nickname + \
|
2021-12-30 11:06:33 +00:00
|
|
|
'?page=' + str(page_number + 1) + '">' + \
|
2022-03-28 08:47:53 +00:00
|
|
|
'<img loading="lazy" decoding="async" alt=">" title=">" ' + \
|
2020-12-09 13:08:26 +00:00
|
|
|
'src="/icons' + \
|
2020-11-12 16:05:45 +00:00
|
|
|
'/prev.png" class="buttonnext"/></a>\n'
|
2021-12-30 11:06:33 +00:00
|
|
|
navigate_str += '</p>'
|
|
|
|
blog_str += navigate_str
|
2020-11-12 16:05:45 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
for item in timeline_json['orderedItems']:
|
2020-11-12 16:05:45 +00:00
|
|
|
if item['type'] != 'Create':
|
|
|
|
continue
|
2020-02-25 18:19:43 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += \
|
|
|
|
_html_blog_post_content(debug, session, authorized,
|
|
|
|
base_dir, http_prefix, translate,
|
|
|
|
nickname, domain, domain_full, item,
|
|
|
|
None, True, peertube_instances,
|
2024-02-19 15:38:08 +00:00
|
|
|
system_language, person_cache,
|
|
|
|
'<hr>')
|
2020-05-23 09:50:10 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
if len(timeline_json['orderedItems']) >= no_of_items:
|
|
|
|
blog_str += navigate_str
|
2020-05-23 09:50:10 +00:00
|
|
|
|
2020-11-12 16:05:45 +00:00
|
|
|
# show rss link
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '<p class="rssfeed">'
|
2020-05-23 09:50:10 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '<a href="' + http_prefix + '://' + \
|
2021-12-26 10:00:46 +00:00
|
|
|
domain_full + '/blog/' + nickname + '/rss.xml">'
|
2022-03-28 08:47:53 +00:00
|
|
|
blog_str += '<img loading="lazy" decoding="async" alt="RSS 2.0" ' + \
|
2020-11-12 16:05:45 +00:00
|
|
|
'title="RSS 2.0" src="/' + \
|
2020-12-09 13:08:26 +00:00
|
|
|
'icons/logorss.png" /></a>'
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
# blog_str += '<a href="' + http_prefix + '://' + \
|
2021-12-26 10:00:46 +00:00
|
|
|
# domain_full + '/blog/' + nickname + '/rss.txt">'
|
2022-03-28 08:47:53 +00:00
|
|
|
# blog_str += '<img loading="lazy" decoding="async" alt="RSS 3.0" ' + \
|
2020-11-12 16:05:45 +00:00
|
|
|
# 'title="RSS 3.0" src="/' + \
|
2020-12-09 13:08:26 +00:00
|
|
|
# 'icons/rss3.png" /></a>'
|
2020-11-12 16:05:45 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '</p>'
|
|
|
|
return blog_str + html_footer()
|
2020-02-25 13:35:41 +00:00
|
|
|
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2022-06-09 11:02:34 +00:00
|
|
|
def html_blog_page_rss2(base_dir: str, http_prefix: str, translate: {},
|
2021-12-28 22:22:09 +00:00
|
|
|
nickname: str, domain: str, port: int,
|
2021-12-30 11:06:33 +00:00
|
|
|
no_of_items: int, page_number: int,
|
|
|
|
include_header: bool, system_language: str) -> str:
|
2020-05-23 09:10:26 +00:00
|
|
|
"""Returns an RSS version 2 feed containing posts
|
2020-02-27 20:23:27 +00:00
|
|
|
"""
|
2020-05-22 11:32:38 +00:00
|
|
|
if ' ' in nickname or '@' in nickname or \
|
|
|
|
'\n' in nickname or '\r' in nickname:
|
2020-02-27 20:23:27 +00:00
|
|
|
return None
|
|
|
|
|
2021-12-26 12:45:03 +00:00
|
|
|
domain_full = get_full_domain(domain, port)
|
2020-02-27 20:23:27 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_rss2 = ''
|
|
|
|
if include_header:
|
|
|
|
blog_rss2 = rss2header(http_prefix, nickname, domain_full,
|
|
|
|
'Blog', translate)
|
|
|
|
|
|
|
|
blogs_index = acct_dir(base_dir, nickname, domain) + '/tlblogs.index'
|
|
|
|
if not os.path.isfile(blogs_index):
|
|
|
|
if include_header:
|
|
|
|
return blog_rss2 + rss2footer()
|
|
|
|
return blog_rss2
|
|
|
|
|
2022-05-31 15:16:55 +00:00
|
|
|
timeline_json = create_blogs_timeline(base_dir,
|
2021-12-30 11:06:33 +00:00
|
|
|
nickname, domain, port,
|
|
|
|
http_prefix,
|
|
|
|
no_of_items, False,
|
2023-01-02 10:44:49 +00:00
|
|
|
page_number)
|
2021-12-30 11:06:33 +00:00
|
|
|
|
|
|
|
if not timeline_json:
|
|
|
|
if include_header:
|
|
|
|
return blog_rss2 + rss2footer()
|
|
|
|
return blog_rss2
|
|
|
|
|
|
|
|
if page_number is not None:
|
|
|
|
for item in timeline_json['orderedItems']:
|
2020-04-01 21:29:04 +00:00
|
|
|
if item['type'] != 'Create':
|
2020-02-27 20:23:27 +00:00
|
|
|
continue
|
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_rss2 += \
|
2022-06-09 11:02:34 +00:00
|
|
|
_html_blog_post_rss2(domain, item, True, system_language)
|
2020-02-27 20:23:27 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
if include_header:
|
|
|
|
return blog_rss2 + rss2footer()
|
|
|
|
return blog_rss2
|
2020-02-27 20:23:27 +00:00
|
|
|
|
2020-02-25 13:35:41 +00:00
|
|
|
|
2022-06-09 11:02:34 +00:00
|
|
|
def html_blog_page_rss3(base_dir: str, http_prefix: str,
|
2021-12-28 22:22:09 +00:00
|
|
|
nickname: str, domain: str, port: int,
|
2021-12-30 11:06:33 +00:00
|
|
|
no_of_items: int, page_number: int,
|
2021-12-28 22:22:09 +00:00
|
|
|
system_language: str) -> str:
|
2020-05-23 09:41:50 +00:00
|
|
|
"""Returns an RSS version 3 feed containing posts
|
|
|
|
"""
|
|
|
|
if ' ' in nickname or '@' in nickname or \
|
|
|
|
'\n' in nickname or '\r' in nickname:
|
|
|
|
return None
|
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_rss3 = ''
|
2020-05-23 09:41:50 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blogs_index = acct_dir(base_dir, nickname, domain) + '/tlblogs.index'
|
|
|
|
if not os.path.isfile(blogs_index):
|
|
|
|
return blog_rss3
|
2020-05-23 09:41:50 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
timeline_json = \
|
2022-05-31 15:16:55 +00:00
|
|
|
create_blogs_timeline(base_dir,
|
2021-12-30 11:06:33 +00:00
|
|
|
nickname, domain, port, http_prefix,
|
2023-01-02 10:44:49 +00:00
|
|
|
no_of_items, False, page_number)
|
2020-05-23 09:41:50 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
if not timeline_json:
|
|
|
|
return blog_rss3
|
2020-05-23 09:41:50 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
if page_number is not None:
|
|
|
|
for item in timeline_json['orderedItems']:
|
2020-05-23 09:41:50 +00:00
|
|
|
if item['type'] != 'Create':
|
|
|
|
continue
|
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_rss3 += \
|
2022-06-09 11:02:34 +00:00
|
|
|
_html_blog_post_rss3(domain, item, True, system_language)
|
2020-05-23 09:41:50 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
return blog_rss3
|
2020-05-23 09:41:50 +00:00
|
|
|
|
|
|
|
|
2021-12-29 21:55:09 +00:00
|
|
|
def _no_of_blog_accounts(base_dir: str) -> int:
|
2020-02-25 13:35:41 +00:00
|
|
|
"""Returns the number of blog accounts
|
|
|
|
"""
|
2020-04-01 21:29:04 +00:00
|
|
|
ctr = 0
|
2024-05-12 12:35:26 +00:00
|
|
|
dir_str = data_dir(base_dir)
|
|
|
|
for _, dirs, _ in os.walk(dir_str):
|
2020-02-25 13:35:41 +00:00
|
|
|
for acct in dirs:
|
2021-12-26 18:46:43 +00:00
|
|
|
if not is_account_dir(acct):
|
2020-02-25 13:35:41 +00:00
|
|
|
continue
|
2024-05-12 12:35:26 +00:00
|
|
|
account_dir = os.path.join(dir_str, acct)
|
2021-12-30 11:06:33 +00:00
|
|
|
blogs_index = account_dir + '/tlblogs.index'
|
|
|
|
if os.path.isfile(blogs_index):
|
2020-04-01 21:29:04 +00:00
|
|
|
ctr += 1
|
2020-12-13 22:13:45 +00:00
|
|
|
break
|
2020-02-25 13:35:41 +00:00
|
|
|
return ctr
|
|
|
|
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-29 21:55:09 +00:00
|
|
|
def _single_blog_account_nickname(base_dir: str) -> str:
|
2020-02-25 13:35:41 +00:00
|
|
|
"""Returns the nickname of a single blog account
|
|
|
|
"""
|
2024-05-12 12:35:26 +00:00
|
|
|
dir_str = data_dir(base_dir)
|
|
|
|
for _, dirs, _ in os.walk(dir_str):
|
2020-02-25 13:35:41 +00:00
|
|
|
for acct in dirs:
|
2021-12-26 18:46:43 +00:00
|
|
|
if not is_account_dir(acct):
|
2020-02-25 13:35:41 +00:00
|
|
|
continue
|
2024-05-12 12:35:26 +00:00
|
|
|
account_dir = os.path.join(dir_str, acct)
|
2021-12-30 11:06:33 +00:00
|
|
|
blogs_index = account_dir + '/tlblogs.index'
|
|
|
|
if os.path.isfile(blogs_index):
|
2020-02-25 13:35:41 +00:00
|
|
|
return acct.split('@')[0]
|
2020-12-13 22:13:45 +00:00
|
|
|
break
|
2020-02-25 13:35:41 +00:00
|
|
|
return None
|
|
|
|
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-28 22:22:09 +00:00
|
|
|
def html_blog_view(authorized: bool,
|
|
|
|
session, base_dir: str, http_prefix: str,
|
|
|
|
translate: {}, domain: str, port: int,
|
2021-12-30 11:06:33 +00:00
|
|
|
no_of_items: int,
|
2021-12-28 22:22:09 +00:00
|
|
|
peertube_instances: [], system_language: str,
|
|
|
|
person_cache: {}, debug: bool) -> str:
|
2020-02-25 13:35:41 +00:00
|
|
|
"""Show the blog main page
|
|
|
|
"""
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str = ''
|
2020-02-25 13:35:41 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
css_filename = base_dir + '/epicyon-profile.css'
|
2021-12-25 16:17:53 +00:00
|
|
|
if os.path.isfile(base_dir + '/epicyon.css'):
|
2021-12-30 11:06:33 +00:00
|
|
|
css_filename = base_dir + '/epicyon.css'
|
|
|
|
instance_title = \
|
2021-12-26 14:08:58 +00:00
|
|
|
get_config_param(base_dir, 'instanceTitle')
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str = \
|
|
|
|
html_header_with_external_style(css_filename, instance_title, None)
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-29 21:55:09 +00:00
|
|
|
if _no_of_blog_accounts(base_dir) <= 1:
|
|
|
|
nickname = _single_blog_account_nickname(base_dir)
|
2020-11-12 16:05:45 +00:00
|
|
|
if nickname:
|
2021-12-28 22:22:09 +00:00
|
|
|
return html_blog_page(authorized, session,
|
|
|
|
base_dir, http_prefix, translate,
|
|
|
|
nickname, domain, port,
|
2021-12-30 11:06:33 +00:00
|
|
|
no_of_items, 1, peertube_instances,
|
2021-12-28 22:22:09 +00:00
|
|
|
system_language, person_cache, debug)
|
2020-11-12 16:05:45 +00:00
|
|
|
|
2021-12-26 12:45:03 +00:00
|
|
|
domain_full = get_full_domain(domain, port)
|
2020-11-12 16:05:45 +00:00
|
|
|
|
2024-05-12 12:35:26 +00:00
|
|
|
dir_str = data_dir(base_dir)
|
|
|
|
for _, dirs, _ in os.walk(dir_str):
|
2020-11-12 16:05:45 +00:00
|
|
|
for acct in dirs:
|
2021-12-26 18:46:43 +00:00
|
|
|
if not is_account_dir(acct):
|
2020-11-12 16:05:45 +00:00
|
|
|
continue
|
2024-05-12 12:35:26 +00:00
|
|
|
account_dir = os.path.join(dir_str, acct)
|
2021-12-30 11:06:33 +00:00
|
|
|
blogs_index = account_dir + '/tlblogs.index'
|
|
|
|
if os.path.isfile(blogs_index):
|
|
|
|
blog_str += '<p class="blogaccount">'
|
|
|
|
blog_str += '<a href="' + \
|
2021-12-26 10:00:46 +00:00
|
|
|
http_prefix + '://' + domain_full + '/blog/' + \
|
2020-11-12 16:05:45 +00:00
|
|
|
acct.split('@')[0] + '">' + acct + '</a>'
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_str += '</p>'
|
2020-12-13 22:13:45 +00:00
|
|
|
break
|
2020-11-12 16:05:45 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
return blog_str + html_footer()
|
2020-02-29 20:34:44 +00:00
|
|
|
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-28 22:22:09 +00:00
|
|
|
def html_edit_blog(media_instance: bool, translate: {},
|
2022-06-09 11:02:34 +00:00
|
|
|
base_dir: str, path: str, page_number: int,
|
2021-12-28 22:22:09 +00:00
|
|
|
nickname: str, domain: str,
|
2021-12-30 11:06:33 +00:00
|
|
|
post_url: str, system_language: str) -> str:
|
2020-02-29 20:34:44 +00:00
|
|
|
"""Edit a blog post after it was created
|
|
|
|
"""
|
2021-12-30 11:06:33 +00:00
|
|
|
post_filename = locate_post(base_dir, nickname, domain, post_url)
|
2021-12-26 23:41:34 +00:00
|
|
|
if not post_filename:
|
2022-01-04 21:19:06 +00:00
|
|
|
print('Edit blog: filename not found for ' + post_url)
|
2020-03-01 12:33:20 +00:00
|
|
|
return None
|
|
|
|
|
2021-12-26 23:41:34 +00:00
|
|
|
post_json_object = load_json(post_filename)
|
2021-12-25 22:09:19 +00:00
|
|
|
if not post_json_object:
|
2021-12-26 23:41:34 +00:00
|
|
|
print('Edit blog: json not loaded for ' + post_filename)
|
2020-03-01 12:33:20 +00:00
|
|
|
return None
|
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_text = \
|
|
|
|
'<h1">' + translate['Write your post text below.'] + '</h1>'
|
2020-02-29 20:34:44 +00:00
|
|
|
|
2024-05-12 12:35:26 +00:00
|
|
|
dir_str = data_dir(base_dir)
|
|
|
|
if os.path.isfile(dir_str + '/newpost.txt'):
|
2021-11-26 12:28:20 +00:00
|
|
|
try:
|
2024-07-13 12:06:28 +00:00
|
|
|
with open(dir_str + '/newpost.txt', 'r',
|
|
|
|
encoding='utf-8') as fp_blog:
|
|
|
|
edit_blog_text = '<p>' + fp_blog.read() + '</p>'
|
2021-11-26 12:28:20 +00:00
|
|
|
except OSError:
|
2024-07-02 22:16:13 +00:00
|
|
|
print('EX: html_edit_blog unable to read ' +
|
|
|
|
dir_str + '/newpost.txt')
|
2020-02-29 20:34:44 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
css_filename = base_dir + '/epicyon-profile.css'
|
2021-12-25 16:17:53 +00:00
|
|
|
if os.path.isfile(base_dir + '/epicyon.css'):
|
2021-12-30 11:06:33 +00:00
|
|
|
css_filename = base_dir + '/epicyon.css'
|
2020-02-29 20:34:44 +00:00
|
|
|
|
|
|
|
if '?' in path:
|
2020-04-01 21:29:04 +00:00
|
|
|
path = path.split('?')[0]
|
2021-12-30 11:06:33 +00:00
|
|
|
path_base = path
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_image_section = ' <div class="container">'
|
|
|
|
edit_blog_image_section += ' <label class="labels">' + \
|
2020-04-01 21:29:04 +00:00
|
|
|
translate['Image description'] + '</label>'
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_image_section += \
|
|
|
|
' <input type="text" name="imageDescription">'
|
|
|
|
edit_blog_image_section += \
|
2020-04-05 09:33:23 +00:00
|
|
|
' <input type="file" id="attachpic" name="attachpic"'
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_image_section += \
|
2021-12-27 15:56:15 +00:00
|
|
|
' accept="' + get_media_formats() + '">'
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_image_section += ' </div>'
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
placeholder_message = translate['Write something'] + '...'
|
2020-04-01 21:29:04 +00:00
|
|
|
endpoint = 'editblogpost'
|
2021-12-30 11:06:33 +00:00
|
|
|
placeholder_subject = translate['Title']
|
|
|
|
scope_icon = 'scope_blog.png'
|
|
|
|
scope_description = translate['Blog']
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
date_and_location = ''
|
|
|
|
date_and_location = '<div class="container">'
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
date_and_location += \
|
2020-04-05 09:33:23 +00:00
|
|
|
'<p><input type="checkbox" class="profilecheckbox" ' + \
|
|
|
|
'name="schedulePost"><label class="labels">' + \
|
2020-04-01 21:29:04 +00:00
|
|
|
translate['This is a scheduled post.'] + '</label></p>'
|
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
date_and_location += \
|
2022-03-28 08:47:53 +00:00
|
|
|
'<p><img loading="lazy" decoding="async" alt="" title="" ' + \
|
2020-12-09 13:08:26 +00:00
|
|
|
'class="emojicalendar" src="/icons/calendar.png"/>'
|
2021-12-30 11:06:33 +00:00
|
|
|
date_and_location += \
|
2020-04-05 09:33:23 +00:00
|
|
|
'<label class="labels">' + translate['Date'] + ': </label>'
|
2021-12-30 11:06:33 +00:00
|
|
|
date_and_location += '<input type="date" name="eventDate">'
|
|
|
|
date_and_location += \
|
|
|
|
'<label class="labelsright">' + translate['Time'] + ':'
|
|
|
|
date_and_location += '<input type="time" name="eventTime"></label></p>'
|
|
|
|
date_and_location += '</div>'
|
|
|
|
date_and_location += '<div class="container">'
|
|
|
|
date_and_location += \
|
2020-04-05 09:33:23 +00:00
|
|
|
'<br><label class="labels">' + translate['Location'] + ': </label>'
|
2021-12-30 11:06:33 +00:00
|
|
|
date_and_location += '<input type="text" name="location">'
|
|
|
|
date_and_location += '</div>'
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
instance_title = \
|
2021-12-26 14:08:58 +00:00
|
|
|
get_config_param(base_dir, 'instanceTitle')
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_form = \
|
|
|
|
html_header_with_external_style(css_filename, instance_title, None)
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_form += \
|
2020-04-05 09:33:23 +00:00
|
|
|
'<form enctype="multipart/form-data" method="POST" ' + \
|
|
|
|
'accept-charset="UTF-8" action="' + \
|
2021-12-30 11:06:33 +00:00
|
|
|
path_base + '?' + endpoint + '?page=' + str(page_number) + '">'
|
|
|
|
edit_blog_form += \
|
|
|
|
' <input type="hidden" name="postUrl" value="' + post_url + '">'
|
|
|
|
edit_blog_form += \
|
2020-04-05 09:33:23 +00:00
|
|
|
' <input type="hidden" name="pageNumber" value="' + \
|
2021-12-30 11:06:33 +00:00
|
|
|
str(page_number) + '">'
|
|
|
|
edit_blog_form += ' <div class="vertical-center">'
|
|
|
|
edit_blog_form += \
|
|
|
|
' <label for="nickname"><b>' + edit_blog_text + '</b></label>'
|
|
|
|
edit_blog_form += ' <div class="container">'
|
|
|
|
|
|
|
|
edit_blog_form += ' <div class="dropbtn">'
|
|
|
|
edit_blog_form += \
|
2022-03-28 08:47:53 +00:00
|
|
|
' <img loading="lazy" decoding="async" ' + \
|
|
|
|
'alt="" title="" src="/icons' + \
|
2021-12-30 11:06:33 +00:00
|
|
|
'/' + scope_icon + '"/><b class="scope-desc">' + \
|
|
|
|
scope_description + '</b>'
|
|
|
|
edit_blog_form += ' </div>'
|
2020-04-01 21:29:04 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_form += ' <a href="' + path_base + \
|
2022-03-28 08:47:53 +00:00
|
|
|
'/searchemoji"><img loading="lazy" decoding="async" ' + \
|
2020-04-01 21:29:04 +00:00
|
|
|
'class="emojisearch" src="/emoji/1F601.png" title="' + \
|
|
|
|
translate['Search for emoji'] + '" alt="' + \
|
|
|
|
translate['Search for emoji'] + '"/></a>'
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_form += ' </div>'
|
|
|
|
edit_blog_form += ' <div class="container"><center>'
|
|
|
|
edit_blog_form += ' <a href="' + path_base + \
|
2020-04-01 21:29:04 +00:00
|
|
|
'/inbox"><button class="cancelbtn">' + \
|
|
|
|
translate['Cancel'] + '</button></a>'
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_form += \
|
|
|
|
' <input type="submit" name="submitPost" value="' + \
|
2022-05-23 18:48:45 +00:00
|
|
|
translate['Publish'] + '">'
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_form += ' </center></div>'
|
2021-12-25 20:25:07 +00:00
|
|
|
if media_instance:
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_form += edit_blog_image_section
|
|
|
|
edit_blog_form += \
|
|
|
|
' <label class="labels">' + placeholder_subject + '</label><br>'
|
|
|
|
title_str = ''
|
2021-12-25 22:09:19 +00:00
|
|
|
if post_json_object['object'].get('summary'):
|
2021-12-30 11:06:33 +00:00
|
|
|
title_str = post_json_object['object']['summary']
|
|
|
|
edit_blog_form += \
|
|
|
|
' <input type="text" name="subject" value="' + title_str + '">'
|
|
|
|
edit_blog_form += ''
|
|
|
|
edit_blog_form += ' <br>'
|
|
|
|
message_box_height = 800
|
|
|
|
|
|
|
|
content_str = get_base_content_from_post(post_json_object, system_language)
|
|
|
|
content_str = content_str.replace('<p>', '').replace('</p>', '\n')
|
|
|
|
|
|
|
|
edit_blog_form += \
|
2022-09-02 15:57:06 +00:00
|
|
|
edit_text_area(placeholder_message, None, 'message', content_str,
|
2021-12-30 11:06:33 +00:00
|
|
|
message_box_height, '', True)
|
|
|
|
edit_blog_form += date_and_location
|
2021-12-25 20:25:07 +00:00
|
|
|
if not media_instance:
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_form += edit_blog_image_section
|
|
|
|
edit_blog_form += ' </div>'
|
|
|
|
edit_blog_form += '</form>'
|
2020-02-29 20:34:44 +00:00
|
|
|
|
2021-12-30 11:06:33 +00:00
|
|
|
edit_blog_form += html_footer()
|
|
|
|
return edit_blog_form
|
2021-06-07 19:23:48 +00:00
|
|
|
|
|
|
|
|
2021-12-28 22:22:09 +00:00
|
|
|
def path_contains_blog_link(base_dir: str,
|
|
|
|
http_prefix: str, domain: str,
|
|
|
|
domain_full: str, path: str) -> (str, str):
|
2021-06-07 19:23:48 +00:00
|
|
|
"""If the path contains a blog entry then return its filename
|
|
|
|
"""
|
|
|
|
if '/users/' not in path:
|
|
|
|
return None, None
|
2021-12-30 11:06:33 +00:00
|
|
|
user_ending = path.split('/users/', 1)[1]
|
|
|
|
if '/' not in user_ending:
|
2021-06-07 19:23:48 +00:00
|
|
|
return None, None
|
2021-12-30 11:06:33 +00:00
|
|
|
user_ending2 = user_ending.split('/')
|
|
|
|
nickname = user_ending2[0]
|
|
|
|
if len(user_ending2) != 2:
|
2021-06-07 19:23:48 +00:00
|
|
|
return None, None
|
2021-12-30 11:06:33 +00:00
|
|
|
if len(user_ending2[1]) < 14:
|
2021-06-07 19:23:48 +00:00
|
|
|
return None, None
|
2021-12-30 11:06:33 +00:00
|
|
|
user_ending2[1] = user_ending2[1].strip()
|
|
|
|
if not user_ending2[1].isdigit():
|
2021-06-07 19:23:48 +00:00
|
|
|
return None, None
|
|
|
|
# check for blog posts
|
2021-12-30 11:06:33 +00:00
|
|
|
blog_index_filename = \
|
|
|
|
acct_dir(base_dir, nickname, domain) + '/tlblogs.index'
|
|
|
|
if not os.path.isfile(blog_index_filename):
|
2021-06-07 19:23:48 +00:00
|
|
|
return None, None
|
2022-06-10 11:43:33 +00:00
|
|
|
if not text_in_file('#' + user_ending2[1] + '.', blog_index_filename):
|
2021-06-07 19:23:48 +00:00
|
|
|
return None, None
|
2021-12-30 11:06:33 +00:00
|
|
|
message_id = local_actor_url(http_prefix, nickname, domain_full) + \
|
|
|
|
'/statuses/' + user_ending2[1]
|
2024-05-24 17:44:40 +00:00
|
|
|
filename = locate_post(base_dir, nickname, domain, message_id)
|
|
|
|
return filename, nickname
|
2021-06-26 11:16:41 +00:00
|
|
|
|
|
|
|
|
2021-12-28 22:22:09 +00:00
|
|
|
def get_blog_address(actor_json: {}) -> str:
|
2021-06-26 11:16:41 +00:00
|
|
|
"""Returns blog address for the given actor
|
|
|
|
"""
|
2023-04-01 09:42:19 +00:00
|
|
|
result = get_actor_property_url(actor_json, 'Blog')
|
|
|
|
if not result:
|
|
|
|
result = get_actor_property_url(actor_json, 'My Blog')
|
2024-04-24 19:35:04 +00:00
|
|
|
url = remove_html(result)
|
|
|
|
return remove_link_tracking(url)
|
2023-05-19 20:44:43 +00:00
|
|
|
|
|
|
|
|
|
|
|
def account_has_blog(base_dir: str, nickname: str, domain: str) -> bool:
|
|
|
|
"""Returns true if the given account has a blog
|
|
|
|
"""
|
|
|
|
blogs_dir = acct_dir(base_dir, nickname, domain) + '/tlblogs'
|
|
|
|
if os.path.isdir(blogs_dir):
|
|
|
|
for path in os.listdir(blogs_dir):
|
|
|
|
if path.endswith('.json'):
|
|
|
|
return True
|
|
|
|
return False
|