Allow for the possibility of a v2 instance within the masto API

main
Bob Mottram 2023-10-02 19:56:22 +01:00
parent 2c0b8202c6
commit 7a5f06f28c
3 changed files with 171 additions and 172 deletions

View File

@ -13,7 +13,145 @@ from utils import get_config_param
from utils import acct_dir from utils import acct_dir
from utils import remove_html from utils import remove_html
from utils import get_attachment_property_value from utils import get_attachment_property_value
from metadata import meta_data_instance from utils import no_of_accounts
from utils import get_status_count
def _meta_data_instance_v1(show_accounts: bool,
instance_title: str,
instance_description_short: str,
instance_description: str,
http_prefix: str, base_dir: str,
admin_nickname: str, domain: str, domain_full: str,
registration: bool, system_language: str,
version: str) -> {}:
""" /api/v1/instance endpoint
"""
admin_actor_filename = \
base_dir + '/accounts/' + admin_nickname + '@' + domain + '.json'
if not os.path.isfile(admin_actor_filename):
return {}
admin_actor = load_json(admin_actor_filename, 0)
if not admin_actor:
print('WARN: json load exception _meta_data_instance_v1')
return {}
rules_list = []
rules_filename = \
base_dir + '/accounts/tos.md'
if os.path.isfile(rules_filename):
with open(rules_filename, 'r', encoding='utf-8') as fp_rules:
rules_lines = fp_rules.readlines()
rule_ctr = 1
for line in rules_lines:
line = line.strip()
if not line:
continue
if line.startswith('#'):
continue
rules_list.append({
'id': str(rule_ctr),
'text': line
})
rule_ctr += 1
is_bot = False
is_group = False
if admin_actor['type'] == 'Group':
is_group = True
elif admin_actor['type'] != 'Person':
is_bot = True
url = \
http_prefix + '://' + domain_full + '/@' + \
admin_actor['preferredUsername']
if show_accounts:
active_accounts = no_of_accounts(base_dir)
local_posts = get_status_count(base_dir)
else:
active_accounts = 1
local_posts = 1
created_at = ''
if admin_actor.get('published'):
created_at = admin_actor['published']
icon_url = remove_html(admin_actor['icon']['url'])
image_url = remove_html(admin_actor['image']['url'])
instance = {
'approval_required': False,
'invites_enabled': False,
'registrations': registration,
'contact_account': {
'acct': admin_actor['preferredUsername'],
'created_at': created_at,
'avatar': icon_url,
'avatar_static': icon_url,
'header': image_url,
'header_static': image_url,
'bot': is_bot,
'discoverable': True,
'group': is_group,
'display_name': admin_actor['name'],
'locked': admin_actor['manuallyApprovesFollowers'],
'note': '<p>Admin of ' + domain + '</p>',
'url': url,
'username': admin_actor['preferredUsername']
},
'description': instance_description,
'languages': [system_language],
'short_description': instance_description_short,
'stats': {
'domain_count': 2,
'status_count': local_posts,
'user_count': active_accounts
},
'thumbnail': http_prefix + '://' + domain_full + '/login.png',
'title': instance_title,
'uri': domain_full,
'urls': {},
'version': version,
'rules': rules_list,
'configuration': {
'statuses': {
'max_media_attachments': 1
},
'media_attachments': {
'supported_mime_types': [
'image/jpeg',
'image/jxl',
'image/png',
'image/gif',
'image/webp',
'image/avif',
'image/heic',
'image/svg+xml',
'video/webm',
'video/mp4',
'video/ogv',
'audio/ogg',
'audio/wav',
'audio/x-wav',
'audio/x-pn-wave',
'audio/vnd.wave',
'audio/opus',
'audio/speex',
'audio/x-speex',
'audio/flac',
'audio/mpeg'
],
'image_size_limit': 10485760,
'image_matrix_limit': 16777216,
'video_size_limit': 41943040,
'video_frame_rate_limit': 60,
'video_matrix_limit': 2304000
}
}
}
return instance
def _get_mast_api_v1id(path: str) -> int: def _get_mast_api_v1id(path: str) -> int:
@ -322,18 +460,18 @@ def masto_api_v1_response(path: str, calling_domain: str,
show_node_info_accounts = False show_node_info_accounts = False
send_json = \ send_json = \
meta_data_instance(show_node_info_accounts, _meta_data_instance_v1(show_node_info_accounts,
instance_title, instance_title,
instance_description_short, instance_description_short,
instance_description, instance_description,
http_prefix, http_prefix,
base_dir, base_dir,
admin_nickname, admin_nickname,
domain, domain,
domain_full, domain_full,
registration, registration,
system_language, system_language,
project_version) project_version)
send_json_str = 'masto API instance metadata sent ' + ua_str send_json_str = 'masto API instance metadata sent ' + ua_str
elif path.startswith('/api/v1/instance/peers'): elif path.startswith('/api/v1/instance/peers'):
# This is just a dummy result. # This is just a dummy result.

View File

@ -8,28 +8,9 @@ __status__ = "Production"
__module_group__ = "Metadata" __module_group__ = "Metadata"
import os import os
from utils import is_account_dir
from utils import load_json
from utils import no_of_accounts
from utils import no_of_active_accounts_monthly from utils import no_of_active_accounts_monthly
from utils import remove_html from utils import no_of_accounts
from utils import get_status_count
def _get_status_count(base_dir: str) -> int:
"""Get the total number of posts
"""
status_ctr = 0
accounts_dir = base_dir + '/accounts'
for _, dirs, _ in os.walk(accounts_dir):
for acct in dirs:
if not is_account_dir(acct):
continue
acct_dir = os.path.join(accounts_dir, acct + '/outbox')
for _, _, files2 in os.walk(acct_dir):
status_ctr += len(files2)
break
break
return status_ctr
def meta_data_node_info(base_dir: str, def meta_data_node_info(base_dir: str,
@ -52,7 +33,7 @@ def meta_data_node_info(base_dir: str,
active_accounts = no_of_accounts(base_dir) active_accounts = no_of_accounts(base_dir)
active_accounts_monthly = no_of_active_accounts_monthly(base_dir, 1) active_accounts_monthly = no_of_active_accounts_monthly(base_dir, 1)
active_accounts_half_year = no_of_active_accounts_monthly(base_dir, 6) active_accounts_half_year = no_of_active_accounts_monthly(base_dir, 6)
local_posts = _get_status_count(base_dir) local_posts = get_status_count(base_dir)
else: else:
active_accounts = 1 active_accounts = 1
active_accounts_monthly = 1 active_accounts_monthly = 1
@ -94,143 +75,6 @@ def meta_data_node_info(base_dir: str,
return nodeinfo return nodeinfo
def meta_data_instance(show_accounts: bool,
instance_title: str,
instance_description_short: str,
instance_description: str,
http_prefix: str, base_dir: str,
admin_nickname: str, domain: str, domain_full: str,
registration: bool, system_language: str,
version: str) -> {}:
""" /api/v1/instance endpoint
"""
admin_actor_filename = \
base_dir + '/accounts/' + admin_nickname + '@' + domain + '.json'
if not os.path.isfile(admin_actor_filename):
return {}
admin_actor = load_json(admin_actor_filename, 0)
if not admin_actor:
print('WARN: json load exception meta_data_instance')
return {}
rules_list = []
rules_filename = \
base_dir + '/accounts/tos.md'
if os.path.isfile(rules_filename):
with open(rules_filename, 'r', encoding='utf-8') as fp_rules:
rules_lines = fp_rules.readlines()
rule_ctr = 1
for line in rules_lines:
line = line.strip()
if not line:
continue
if line.startswith('#'):
continue
rules_list.append({
'id': str(rule_ctr),
'text': line
})
rule_ctr += 1
is_bot = False
is_group = False
if admin_actor['type'] == 'Group':
is_group = True
elif admin_actor['type'] != 'Person':
is_bot = True
url = \
http_prefix + '://' + domain_full + '/@' + \
admin_actor['preferredUsername']
if show_accounts:
active_accounts = no_of_accounts(base_dir)
local_posts = _get_status_count(base_dir)
else:
active_accounts = 1
local_posts = 1
created_at = ''
if admin_actor.get('published'):
created_at = admin_actor['published']
icon_url = remove_html(admin_actor['icon']['url'])
image_url = remove_html(admin_actor['image']['url'])
instance = {
'approval_required': False,
'invites_enabled': False,
'registrations': registration,
'contact_account': {
'acct': admin_actor['preferredUsername'],
'created_at': created_at,
'avatar': icon_url,
'avatar_static': icon_url,
'header': image_url,
'header_static': image_url,
'bot': is_bot,
'discoverable': True,
'group': is_group,
'display_name': admin_actor['name'],
'locked': admin_actor['manuallyApprovesFollowers'],
'note': '<p>Admin of ' + domain + '</p>',
'url': url,
'username': admin_actor['preferredUsername']
},
'description': instance_description,
'languages': [system_language],
'short_description': instance_description_short,
'stats': {
'domain_count': 2,
'status_count': local_posts,
'user_count': active_accounts
},
'thumbnail': http_prefix + '://' + domain_full + '/login.png',
'title': instance_title,
'uri': domain_full,
'urls': {},
'version': version,
'rules': rules_list,
'configuration': {
'statuses': {
'max_media_attachments': 1
},
'media_attachments': {
'supported_mime_types': [
'image/jpeg',
'image/jxl',
'image/png',
'image/gif',
'image/webp',
'image/avif',
'image/heic',
'image/svg+xml',
'video/webm',
'video/mp4',
'video/ogv',
'audio/ogg',
'audio/wav',
'audio/x-wav',
'audio/x-pn-wave',
'audio/vnd.wave',
'audio/opus',
'audio/speex',
'audio/x-speex',
'audio/flac',
'audio/mpeg'
],
'image_size_limit': 10485760,
'image_matrix_limit': 16777216,
'video_size_limit': 41943040,
'video_frame_rate_limit': 60,
'video_matrix_limit': 2304000
}
}
}
return instance
def metadata_custom_emoji(base_dir: str, def metadata_custom_emoji(base_dir: str,
http_prefix: str, domain_full: str) -> {}: http_prefix: str, domain_full: str) -> {}:
"""Returns the custom emoji """Returns the custom emoji

View File

@ -4624,3 +4624,20 @@ def binary_is_image(filename: str, media_binary) -> bool:
if '<svg' in str(media_binary): if '<svg' in str(media_binary):
bin_is_image = True bin_is_image = True
return bin_is_image return bin_is_image
def get_status_count(base_dir: str) -> int:
"""Get the total number of posts
"""
status_ctr = 0
accounts_dir = base_dir + '/accounts'
for _, dirs, _ in os.walk(accounts_dir):
for acct in dirs:
if not is_account_dir(acct):
continue
acct_dir = os.path.join(accounts_dir, acct + '/outbox')
for _, _, files2 in os.walk(acct_dir):
status_ctr += len(files2)
break
break
return status_ctr