mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 11:26:56 -08:00
Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
bb9889cb63
21 changed files with 24 additions and 676 deletions
|
@ -420,6 +420,7 @@ def shared_inbox():
|
|||
object = request_json['object']
|
||||
if not 'actor' in object:
|
||||
missing_actor_in_announce_object = True
|
||||
log_incoming_ap(id, APLOG_ANNOUNCE, APLOG_MONITOR, request_json, 'Actor is missing in Announce object')
|
||||
if not 'id' in object or not 'type' in object or not 'object' in object:
|
||||
if 'type' in object and (object['type'] == 'Page' or object['type'] == 'Note'):
|
||||
log_incoming_ap(id, APLOG_ANNOUNCE, APLOG_IGNORED, saved_json, 'Intended for Mastodon')
|
||||
|
@ -541,6 +542,7 @@ def replay_inbox_request(request_json):
|
|||
object = request_json['object']
|
||||
if not 'actor' in object:
|
||||
missing_actor_in_announce_object = True
|
||||
log_incoming_ap(id, APLOG_ANNOUNCE, APLOG_MONITOR, request_json, 'REPLAY: Actor is missing in Announce object')
|
||||
if not 'id' in object or not 'type' in object or not 'object' in object:
|
||||
if 'type' in object and (object['type'] == 'Page' or object['type'] == 'Note'):
|
||||
log_incoming_ap(id, APLOG_ANNOUNCE, APLOG_IGNORED, request_json, 'REPLAY: Intended for Mastodon')
|
||||
|
|
|
@ -1001,35 +1001,34 @@ def make_image_sizes_async(file_id, thumbnail_width, medium_width, directory, to
|
|||
|
||||
|
||||
def find_reply_parent(in_reply_to: str) -> Tuple[int, int, int]:
|
||||
parent_comment = post = None
|
||||
post_id = parent_comment_id = root_id = None
|
||||
|
||||
# 'comment' is hint that in_reply_to was another comment
|
||||
if 'comment' in in_reply_to:
|
||||
parent_comment = PostReply.get_by_ap_id(in_reply_to)
|
||||
if not parent_comment:
|
||||
return (None, None, None)
|
||||
parent_comment_id = parent_comment.id
|
||||
post_id = parent_comment.post_id
|
||||
root_id = parent_comment.root_id
|
||||
elif 'post' in in_reply_to:
|
||||
parent_comment_id = None
|
||||
post = Post.get_by_ap_id(in_reply_to)
|
||||
if not post:
|
||||
return (None, None, None)
|
||||
post_id = post.id
|
||||
root_id = None
|
||||
else:
|
||||
parent_comment_id = None
|
||||
root_id = None
|
||||
post_id = None
|
||||
if parent_comment:
|
||||
parent_comment_id = parent_comment.id
|
||||
post_id = parent_comment.post_id
|
||||
root_id = parent_comment.root_id
|
||||
|
||||
# 'post' is hint that in_reply_to was a post
|
||||
if not parent_comment and 'post' in in_reply_to:
|
||||
post = Post.get_by_ap_id(in_reply_to)
|
||||
if post:
|
||||
post_id = post.id
|
||||
|
||||
# no hint in in_reply_to, or it was misleading (e.g. replies to nodebb comments have '/post/' in them)
|
||||
if not parent_comment and not post:
|
||||
parent_comment = PostReply.get_by_ap_id(in_reply_to)
|
||||
if parent_comment:
|
||||
parent_comment_id = parent_comment.id
|
||||
post_id = parent_comment.post_id
|
||||
root_id = parent_comment.root_id
|
||||
else:
|
||||
parent_comment = PostReply.get_by_ap_id(in_reply_to)
|
||||
if parent_comment:
|
||||
parent_comment_id = parent_comment.id
|
||||
post_id = parent_comment.post_id
|
||||
root_id = parent_comment.root_id
|
||||
else:
|
||||
return (None, None, None)
|
||||
post = Post.get_by_ap_id(in_reply_to)
|
||||
if post:
|
||||
post_id = post.id
|
||||
|
||||
return post_id, parent_comment_id, root_id
|
||||
|
||||
|
|
|
@ -496,79 +496,3 @@ def alpha_emoji():
|
|||
return jsonify({"error": "not_yet_implemented"}), 400
|
||||
|
||||
|
||||
# HTML routes
|
||||
from flask import abort, render_template
|
||||
from app.models import Community
|
||||
from app.utils import current_theme
|
||||
import os
|
||||
|
||||
@bp.route('/api/alpha/', methods=['GET'])
|
||||
def get_alpha():
|
||||
if not current_app.debug:
|
||||
abort(404)
|
||||
|
||||
template_name = "index.html"
|
||||
|
||||
theme = current_theme()
|
||||
if theme != '' and os.path.exists(f'app/templates/themes/{theme}/{template_name}'):
|
||||
return render_template(f'themes/{theme}/{template_name}')
|
||||
else:
|
||||
return render_template(template_name)
|
||||
|
||||
|
||||
@bp.route('/api/alpha/auth/login', methods=['GET'])
|
||||
def get_alpha_auth_login():
|
||||
if not current_app.debug:
|
||||
abort(404)
|
||||
|
||||
template_name = "auth/login.html"
|
||||
|
||||
theme = current_theme()
|
||||
if theme != '' and os.path.exists(f'app/templates/themes/{theme}/{template_name}'):
|
||||
return render_template(f'themes/{theme}/{template_name}')
|
||||
else:
|
||||
return render_template(template_name)
|
||||
|
||||
|
||||
@bp.route('/api/alpha/auth/logout', methods=['GET'])
|
||||
def get_alpha_auth_logout():
|
||||
if not current_app.debug:
|
||||
abort(404)
|
||||
|
||||
template_name = "auth/logout.html"
|
||||
|
||||
theme = current_theme()
|
||||
if theme != '' and os.path.exists(f'app/templates/themes/{theme}/{template_name}'):
|
||||
return render_template(f'themes/{theme}/{template_name}')
|
||||
else:
|
||||
return render_template(template_name)
|
||||
|
||||
|
||||
@bp.route('/api/alpha/communities', methods=['GET'])
|
||||
def get_alpha_communities():
|
||||
if not current_app.debug:
|
||||
abort(404)
|
||||
|
||||
template_name = "list_communities.html"
|
||||
|
||||
theme = current_theme()
|
||||
if theme != '' and os.path.exists(f'app/templates/themes/{theme}/{template_name}'):
|
||||
return render_template(f'themes/{theme}/{template_name}')
|
||||
else:
|
||||
return render_template(template_name)
|
||||
|
||||
|
||||
@bp.route('/api/alpha/c/<actor>', methods=['GET'])
|
||||
def community_profile(actor):
|
||||
if '@' in actor:
|
||||
community = Community.query.filter_by(ap_id=actor.lower(), banned=False).first()
|
||||
else:
|
||||
community = Community.query.filter_by(name=actor, ap_id=None).first()
|
||||
|
||||
template_name = "community.html"
|
||||
|
||||
theme = current_theme()
|
||||
if theme != '' and os.path.exists(f'app/templates/themes/{theme}/{template_name}'):
|
||||
return render_template(f'themes/{theme}/{template_name}', community_id=community.id)
|
||||
else:
|
||||
return render_template(template_name, community_id=community.id)
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
|
||||
{% block app_content %}
|
||||
<p class="mb-0" id="site_request"></p>
|
||||
<details><summary>JSON</summary><pre id="site_json"></pre></details>
|
||||
|
||||
<p class="mb-0">POST <code>/api/alpha/user/login</code></p>
|
||||
<details><summary>JSON</summary><pre id="login_json"></pre></details>
|
||||
|
||||
<hr />
|
||||
|
||||
<form id="login_form">
|
||||
<div class="form-floating">
|
||||
<input type="text" class="form-control" id="username" placeholder="Username">
|
||||
<label for="username">Username</label>
|
||||
</div>
|
||||
|
||||
<div class="form-floating my-2">
|
||||
<input type="password" class="form-control" id="password" placeholder="Password">
|
||||
<label for="password">Password</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check text-start my-3">
|
||||
<input class="form-check-input" type="checkbox" id="remember_me">
|
||||
<label class="form-check-label" for="remember_me">Remember me</label>
|
||||
</div>
|
||||
<button class="btn btn-primary w-100 py-2" type="submit">Sign in</button>
|
||||
</form>
|
||||
|
||||
<p class="mt-3">
|
||||
{{ _('New User?') }} <a href="{{ url_for('auth.register') }}">{{ _('Register new account') }}</a>
|
||||
</p>
|
||||
<p class="mt-0">
|
||||
{{ _('Forgot Your Password?') }} <a href="{{ url_for('auth.reset_password_request') }}">{{ _('Reset it') }}</a>
|
||||
</p>
|
||||
|
||||
<script src="{{ '/static/themes/' + theme() + '/js/login.js' }}"></script>
|
||||
{% endblock %}
|
|
@ -1,5 +0,0 @@
|
|||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
|
||||
{% block app_content %}
|
||||
<script src="{{ '/static/themes/' + theme() + '/js/logout.js' }}"></script>
|
||||
{% endblock %}
|
|
@ -1,114 +0,0 @@
|
|||
{% macro render_username(user, add_domain=True) -%}
|
||||
<span class="render_username">
|
||||
{% if user.deleted -%}
|
||||
[deleted]
|
||||
{% else -%}
|
||||
<a href="/u/{{ user.link() }}" title="{{ user.ap_id if user.ap_id != none else user.user_name }}" aria-label="{{ _('Author') }}">
|
||||
{{ user.display_name() }}{% if not user.is_local() %}<span class="text-muted">@{{ user.ap_domain }}</span>{% endif %}
|
||||
</a>
|
||||
{% if user.bot -%}
|
||||
<span class="fe fe-bot-account" title="Bot account"> </span>
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
</span>
|
||||
{% endmacro -%}
|
||||
|
||||
{% macro render_communityname(community, add_domain=True) -%}
|
||||
<span class="render_community">
|
||||
<a href="/c/{{ community.link() }}" aria-label="{{ _('Go to community %(name)s', name=community.name) }}">
|
||||
{{ community.title }}{% if not community.is_local() %}<span class="text-muted">@{{ community.ap_domain }}</span>{% endif %}
|
||||
</a>
|
||||
</span>
|
||||
{% endmacro -%}
|
||||
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en" data-bs-theme="auto">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title id="head_title"></title>
|
||||
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="HandheldFriendly" content="True">
|
||||
<meta name="MobileOptimized" content="320">
|
||||
<link rel="manifest" href="/static/manifest.json">
|
||||
|
||||
<link id="icon_152" rel="apple-touch-icon" sizes="152x152" href="">
|
||||
<link id="icon_32" rel="icon" type="image/png" sizes="32x32" href="">
|
||||
<link id="icon_16" rel="icon" type="image/png" sizes="16x16" href="">
|
||||
<link id="icon_shortcut" rel="shortcut icon" type="image/png" href="">
|
||||
<link rel='icon' type="image/x-icon" href="/static/images/favicon.ico">
|
||||
|
||||
{{ bootstrap.load_css() }}
|
||||
<link href="{{ '/static/themes/' + theme() + '/css/navbars.css' }}" rel="stylesheet">
|
||||
<link href="{{ '/static/themes/' + theme() + '/css/color-modes.css' }}" rel="stylesheet">
|
||||
|
||||
<script src="{{ '/static/themes/' + theme() + '/js/color-modes.js' }}"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="dropdown position-fixed bottom-0 end-0 mb-3 me-3 bd-mode-toggle">
|
||||
<button class="btn btn-bd-primary py-2 dropdown-toggle d-flex align-items-center" id="bd-theme" type="button" aria-expanded="false" data-bs-toggle="dropdown" aria-label="Toggle theme (auto)">
|
||||
<svg class="bi my-1 theme-icon-active" width="1em" height="1em"><use href="{{ '/static/themes/' + theme() + '/svg/color-modes.svg#circle-half' }}"></use></svg>
|
||||
<span class="visually-hidden" id="bd-theme-text">Toggle theme</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow" aria-labelledby="bd-theme-text">
|
||||
<li>
|
||||
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="light" aria-pressed="false">
|
||||
<svg class="bi me-2 opacity-50" width="1em" height="1em"><use href="{{ '/static/themes/' + theme() + '/svg/color-modes.svg#sun-fill' }}"></use></svg>
|
||||
Light
|
||||
<svg class="bi ms-auto d-none" width="1em" height="1em"><use href="{{ '/static/themes/' + theme() + '/svg/color-modes.svg#check2' }}"></use></svg>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="dark" aria-pressed="false">
|
||||
<svg class="bi me-2 opacity-50" width="1em" height="1em"><use href="{{ '/static/themes/' + theme() + '/svg/color-modes.svg#moon-stars-fill' }}"></use></svg>
|
||||
Dark
|
||||
<svg class="bi ms-auto d-none" width="1em" height="1em"><use href="{{ '/static/themes/' + theme() + '/svg/color-modes.svg#check2' }}"></use></svg>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<button type="button" class="dropdown-item d-flex align-items-center active" data-bs-theme-value="auto" aria-pressed="true">
|
||||
<svg class="bi me-2 opacity-50" width="1em" height="1em"><use href="{{ '/static/themes/' + theme() + '/svg/color-modes.svg#circle-half' }}"></use></svg>
|
||||
Auto
|
||||
<svg class="bi ms-auto d-none" width="1em" height="1em"><use href="{{ '/static/themes/' + theme() + '/svg/color-modes.svg#check2' }}"></use></svg>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<nav class="navbar navbar-expand-lg sticky-top bg-body-tertiary">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="/api/alpha" id="navbar_title"></a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0" id="navbar_items">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="container">
|
||||
{% block app_content %}{% endblock %}
|
||||
<hr />
|
||||
</main>
|
||||
|
||||
<footer class="text-center">
|
||||
<small>
|
||||
<a href="/donate">{{ _('Donate') }}</a><br />
|
||||
<a href="/about">{{ _('About') }}</a><br />
|
||||
<a href="/keyboard_shortcuts">{{ _('Keyboard shortcuts') }}</a><br/>
|
||||
<a href="https://codeberg.org/rimu/pyfedi">PieFed</a> is free and open source.<br />Please <a href="https://codeberg.org/rimu/pyfedi/issues">report bugs</a> or <a href="https://join.piefed.social/get-involved/">get involved</a>.<br />
|
||||
<a href="/privacy">Privacy policy</a>
|
||||
</small>
|
||||
</footer>
|
||||
|
||||
{{ bootstrap.load_js() }}
|
||||
<script src="{{ '/static/themes/' + theme() + '/js/site.js' }}" type="module"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,12 +0,0 @@
|
|||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
|
||||
{% block app_content %}
|
||||
<p class="mb-0" id="site_request"></p>
|
||||
<details><summary>JSON</summary><pre id="site_json"></pre></details>
|
||||
<p class="mb-0" id="community_request" data-value="{{ community_id }}">GET <code>/api/alpha/community?id={{ community_id }}</code></p>
|
||||
<details><summary>JSON</summary><pre id="community_json"></pre></details>
|
||||
<p class="mb-0" id="community_post_list_request">GET <code>/api/alpha/post/list?sort=Hot&page=1&community_id={{ community_id }}</code></p>
|
||||
<details><summary>JSON</summary><pre id="community_post_list_json"></pre></details>
|
||||
|
||||
<script src="{{ '/static/themes/' + theme() + '/js/community.js' }}" type="module" data-param1="{{ community_id }}"></script>
|
||||
{% endblock %}
|
|
@ -1,29 +0,0 @@
|
|||
.bi {
|
||||
vertical-align: -.125em;
|
||||
fill: currentColor;
|
||||
}
|
||||
|
||||
.btn-bd-primary {
|
||||
--bd-violet-bg: #712cf9;
|
||||
--bd-violet-rgb: 112.520718, 44.062154, 249.437846;
|
||||
|
||||
--bs-btn-font-weight: 600;
|
||||
--bs-btn-color: var(--bs-white);
|
||||
--bs-btn-bg: var(--bd-violet-bg);
|
||||
--bs-btn-border-color: var(--bd-violet-bg);
|
||||
--bs-btn-hover-color: var(--bs-white);
|
||||
--bs-btn-hover-bg: #6528e0;
|
||||
--bs-btn-hover-border-color: #6528e0;
|
||||
--bs-btn-focus-shadow-rgb: var(--bd-violet-rgb);
|
||||
--bs-btn-active-color: var(--bs-btn-hover-color);
|
||||
--bs-btn-active-bg: #5a23c8;
|
||||
--bs-btn-active-border-color: #5a23c8;
|
||||
}
|
||||
|
||||
.bd-mode-toggle {
|
||||
z-index: 1500;
|
||||
}
|
||||
|
||||
.bd-mode-toggle .dropdown-menu .active .bi {
|
||||
display: block !important;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
body {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
|
||||
{% block app_content %}
|
||||
<h1>{{ _('Donate') }}</h1>
|
||||
<p>PieFed is free and open-source software while operating without any advertising, monetization, or reliance on
|
||||
venture capital. Your contributions are vital in supporting the PieFed development effort,
|
||||
allowing us to expand and enhance PieFed with new features.</p>
|
||||
|
||||
<div class="btn-group btn-group-lg" role="group" aria-label="Donation options">
|
||||
<a type="button" class="btn btn-outline-primary" href="https://www.patreon.com/PieFed">Donate using Patreon</a>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,12 +0,0 @@
|
|||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
|
||||
{% block app_content %}
|
||||
<p class="mb-0" id="site_request"></p>
|
||||
<details><summary>JSON</summary><pre id="site_json"></pre></details>
|
||||
|
||||
<hr />
|
||||
|
||||
<p class="mb-0" id="post_list_request"></p>
|
||||
<details><summary>JSON</summary><pre id="post_list_json"></pre></details>
|
||||
|
||||
{% endblock%}
|
|
@ -1,81 +0,0 @@
|
|||
/*!
|
||||
* Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)
|
||||
* Copyright 2011-2024 The Bootstrap Authors
|
||||
* Licensed under the Creative Commons Attribution 3.0 Unported License.
|
||||
*/
|
||||
|
||||
(() => {
|
||||
'use strict'
|
||||
|
||||
const getStoredTheme = () => localStorage.getItem('theme')
|
||||
const setStoredTheme = theme => localStorage.setItem('theme', theme)
|
||||
|
||||
const getPreferredTheme = () => {
|
||||
const storedTheme = getStoredTheme()
|
||||
if (storedTheme) {
|
||||
return storedTheme
|
||||
}
|
||||
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||
}
|
||||
|
||||
const setTheme = theme => {
|
||||
if (theme === 'auto') {
|
||||
document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'))
|
||||
} else {
|
||||
document.documentElement.setAttribute('data-bs-theme', theme)
|
||||
}
|
||||
}
|
||||
|
||||
setTheme(getPreferredTheme())
|
||||
|
||||
const showActiveTheme = (theme, focus = false) => {
|
||||
const themeSwitcher = document.querySelector('#bd-theme')
|
||||
|
||||
if (!themeSwitcher) {
|
||||
return
|
||||
}
|
||||
|
||||
const themeSwitcherText = document.querySelector('#bd-theme-text')
|
||||
const activeThemeIcon = document.querySelector('.theme-icon-active use')
|
||||
const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`)
|
||||
const svgOfActiveBtn = btnToActive.querySelector('svg use').getAttribute('href')
|
||||
|
||||
document.querySelectorAll('[data-bs-theme-value]').forEach(element => {
|
||||
element.classList.remove('active')
|
||||
element.setAttribute('aria-pressed', 'false')
|
||||
})
|
||||
|
||||
btnToActive.classList.add('active')
|
||||
btnToActive.setAttribute('aria-pressed', 'true')
|
||||
activeThemeIcon.setAttribute('href', svgOfActiveBtn)
|
||||
const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})`
|
||||
themeSwitcher.setAttribute('aria-label', themeSwitcherLabel)
|
||||
|
||||
if (focus) {
|
||||
themeSwitcher.focus()
|
||||
}
|
||||
}
|
||||
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
|
||||
const storedTheme = getStoredTheme()
|
||||
if (storedTheme !== 'light' && storedTheme !== 'dark') {
|
||||
setTheme(getPreferredTheme())
|
||||
}
|
||||
})
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
showActiveTheme(getPreferredTheme())
|
||||
|
||||
document.querySelectorAll('[data-bs-theme-value]')
|
||||
.forEach(toggle => {
|
||||
toggle.addEventListener('click', () => {
|
||||
const theme = toggle.getAttribute('data-bs-theme-value')
|
||||
setStoredTheme(theme)
|
||||
setTheme(theme)
|
||||
showActiveTheme(theme, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})()
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
const element = document.getElementById('community_request');
|
||||
const community_id = element.getAttribute('data-value');
|
||||
|
||||
import { baseUrl } from './site.js';
|
||||
const community_api = baseUrl + '/api/alpha/community?id=' + community_id;
|
||||
const community_post_list_api = baseUrl + '/api/alpha/post/list?sort=Hot&page=1&community_id=' + community_id;
|
||||
|
||||
import { jwt } from './site.js';
|
||||
if (jwt != null) {
|
||||
var request = {method: "GET", headers: {Authorization: `Bearer ${jwt}`}};
|
||||
} else {
|
||||
var request = {method: "GET"};
|
||||
}
|
||||
|
||||
fetch(community_api, request)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.querySelector('#community_json').textContent = JSON.stringify(data, null, 2);
|
||||
})
|
||||
|
||||
|
||||
fetch(community_post_list_api, request)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.querySelector('#community_post_list_json').textContent = JSON.stringify(data, null, 2);
|
||||
})
|
|
@ -1,15 +0,0 @@
|
|||
import { baseUrl } from './site.js';
|
||||
const api = baseUrl + '/api/alpha/community/list';
|
||||
|
||||
import { jwt } from './site.js';
|
||||
if (jwt != null) {
|
||||
var request = {method: "GET", headers: {Authorization: `Bearer ${jwt}`}};
|
||||
} else {
|
||||
var request = {method: "GET"};
|
||||
}
|
||||
|
||||
fetch(api, request)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.querySelector('#community_list_json').textContent = JSON.stringify(data, null, 2);
|
||||
})
|
|
@ -1,38 +0,0 @@
|
|||
document.querySelector('#login_json').textContent = '{"username_or_email": "", "password": ""}'
|
||||
|
||||
const login_form = document.getElementById('login_form');
|
||||
const username = document.getElementById('username');
|
||||
const password = document.getElementById('password');
|
||||
const remember_me = document.getElementById('remember_me');
|
||||
|
||||
login_form.addEventListener('submit', async event => {
|
||||
event.preventDefault();
|
||||
|
||||
json_string = JSON.stringify({ username_or_email: username.value, password: password.value })
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
const baseUrl = `${url.protocol}//${url.host}`;
|
||||
const api = baseUrl + '/api/alpha/user/login';
|
||||
|
||||
try {
|
||||
const response = await fetch(api, {method: 'POST', body: json_string});
|
||||
if (!response.ok) {
|
||||
throw new Error(`Response status: ${response.status}`);
|
||||
}
|
||||
|
||||
const response_json = await response.json();
|
||||
|
||||
if (remember_me.checked == true) {
|
||||
localStorage.setItem('jwt', response_json['jwt']);
|
||||
} else {
|
||||
sessionStorage.setItem('jwt', response_json['jwt']);
|
||||
}
|
||||
|
||||
window.location.href = baseUrl;
|
||||
|
||||
} catch (error) {
|
||||
console.error(error.message);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
localStorage.removeItem('jwt');
|
||||
sessionStorage.removeItem('jwt');
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
const baseUrl = `${url.protocol}//${url.host}`;
|
||||
window.location.href = baseUrl;
|
|
@ -1,150 +0,0 @@
|
|||
const url = new URL(window.location.href);
|
||||
export const baseUrl = `${url.protocol}//${url.host}`;
|
||||
const api_site = baseUrl + '/api/alpha/site';
|
||||
|
||||
let jwt = null;
|
||||
let session_jwt = sessionStorage.getItem('jwt');
|
||||
if (session_jwt != null) {
|
||||
jwt = session_jwt;
|
||||
} else {
|
||||
let local_jwt = localStorage.getItem('jwt');
|
||||
if (local_jwt != null) {
|
||||
jwt = local_jwt;
|
||||
}
|
||||
}
|
||||
export { jwt };
|
||||
|
||||
const navbar = document.getElementById('navbar_items');
|
||||
if (jwt != null) {
|
||||
var request = {method: "GET", headers: {Authorization: `Bearer ${jwt}`}};
|
||||
} else {
|
||||
var request = {method: "GET"};
|
||||
navbar.innerHTML = '<li class="nav-item"><a class="nav-link" href="/api/alpha/auth/login">Log in (via API)</a></li>' +
|
||||
'<li class="nav-item dropdown">' +
|
||||
'<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">' +
|
||||
'Communities' +
|
||||
'</a>' +
|
||||
'<ul class="dropdown-menu">' +
|
||||
'<li><a class="dropdown-item" href="/api/alpha/communities">All communities</a></li>' +
|
||||
'</ul>' +
|
||||
'</li>' +
|
||||
'<li class="nav-item"><a class="nav-link" href="/user/settings">User settings</a></li>' +
|
||||
'<li class="nav-item"><a class="nav-link" href="/donate">Donate</a></li>';
|
||||
}
|
||||
|
||||
fetch(api_site, request)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// head
|
||||
document.querySelector('#head_title').textContent = data.site.name;
|
||||
document.querySelector('#icon_152').href = data.site.icon_152;
|
||||
document.querySelector('#icon_32').href = data.site.icon_32;
|
||||
document.querySelector('#icon_16').href = data.site.icon_16;
|
||||
document.querySelector('#icon_shortcut').href = data.site.icon_32;
|
||||
|
||||
// navbar
|
||||
document.querySelector('#navbar_title').innerHTML = '<img src="' + data.site.icon + '" alt="Logo" width="36" height="36" />' + ' ' + data.site.name;
|
||||
|
||||
if (jwt != null) {
|
||||
const all_communities_item = document.createElement('li');
|
||||
all_communities_item.innerHTML = '<a class="dropdown-item" href="/api/alpha/communities">All communities</a>'
|
||||
|
||||
const communities_menu = document.createElement('ul');
|
||||
communities_menu.className = 'dropdown-menu'
|
||||
communities_menu.appendChild(all_communities_item)
|
||||
|
||||
if (data.my_user.moderates.length > 0) {
|
||||
const dropdown_divider = document.createElement('li');
|
||||
dropdown_divider.innerHTML = '<hr class="dropdown-divider">'
|
||||
communities_menu.appendChild(dropdown_divider)
|
||||
const dropdown_header = document.createElement('li');
|
||||
dropdown_header.innerHTML = '<h6 class="dropdown-header">Moderating</h6>'
|
||||
communities_menu.appendChild(dropdown_header)
|
||||
|
||||
for (let mods of data.my_user.moderates) {
|
||||
let moderated_community_item = document.createElement('li');
|
||||
if (mods.community.local) {
|
||||
moderated_community_item.innerHTML = '<a class="dropdown-item" href="' + baseUrl + '/api/alpha/c/' + mods.community.name + '">' +
|
||||
mods.community.title + '<span class="text-body-secondary">' + ' (' + mods.community.ap_domain + ')</span>' +
|
||||
'</a>'
|
||||
} else {
|
||||
moderated_community_item.innerHTML = '<a class="dropdown-item" href="' + baseUrl + '/api/alpha/c/' + mods.community.name + '@' + mods.community.ap_domain + '">' +
|
||||
mods.community.title + '<span class="text-body-secondary">' + ' (' + mods.community.ap_domain + ')</span>' +
|
||||
'</a>'
|
||||
}
|
||||
communities_menu.appendChild(moderated_community_item)
|
||||
}
|
||||
}
|
||||
|
||||
if (data.my_user.follows.length > 0) {
|
||||
const dropdown_divider = document.createElement('li');
|
||||
dropdown_divider.innerHTML = '<hr class="dropdown-divider">'
|
||||
communities_menu.appendChild(dropdown_divider)
|
||||
const dropdown_header = document.createElement('li');
|
||||
dropdown_header.innerHTML = '<h6 class="dropdown-header">Joined Communities</h6>'
|
||||
communities_menu.appendChild(dropdown_header)
|
||||
|
||||
for (let follows of data.my_user.follows) {
|
||||
let followed_community_item = document.createElement('li');
|
||||
if (follows.community.local) {
|
||||
followed_community_item.innerHTML = '<a class="dropdown-item" href="' + baseUrl + '/api/alpha/c/' + follows.community.name + '">' +
|
||||
follows.community.title + '<span class="text-body-secondary">' + ' (' + follows.community.ap_domain + ')</span>' +
|
||||
'</a>'
|
||||
} else {
|
||||
followed_community_item.innerHTML = '<a class="dropdown-item" href="' + baseUrl + '/api/alpha/c/' + follows.community.name + '@' + follows.community.ap_domain + '">' +
|
||||
follows.community.title + '<span class="text-body-secondary">' + ' (' + follows.community.ap_domain + ')</span>' +
|
||||
'</a>'
|
||||
}
|
||||
communities_menu.appendChild(followed_community_item)
|
||||
}
|
||||
}
|
||||
|
||||
const communities_item = document.createElement('li')
|
||||
communities_item.className = 'nav-item dropdown'
|
||||
communities_item.innerHTML = '<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Communities</a>'
|
||||
communities_item.appendChild(communities_menu)
|
||||
navbar.appendChild(communities_item)
|
||||
|
||||
const user_settings_item = document.createElement('li')
|
||||
user_settings_item.className = 'nav-item'
|
||||
user_settings_item.innerHTML = '<a class="nav-link" href="/user/settings">User settings</a>';
|
||||
navbar.appendChild(user_settings_item)
|
||||
|
||||
const logout_item = document.createElement('li')
|
||||
logout_item.className = 'nav-item'
|
||||
logout_item.innerHTML = '<a class="nav-link" href="/api/alpha/auth/logout">Log out (via API)</a>';
|
||||
navbar.appendChild(logout_item)
|
||||
}
|
||||
|
||||
// site info
|
||||
let postlist = document.querySelector('#post_list_request')
|
||||
if (jwt != null) {
|
||||
document.querySelector('#site_request').innerHTML = 'GET <code>/api/alpha/site</code> [LOGGED IN]'
|
||||
if (postlist) {
|
||||
postlist.innerHTML = 'GET <code>/api/alpha/post/list?type_=Subscribed&sort=New&page=1</code></p>'
|
||||
}
|
||||
} else {
|
||||
document.querySelector('#site_request').innerHTML = 'GET <code>/api/alpha/site</code> [LOGGED OUT]'
|
||||
if (postlist) {
|
||||
postlist.innerHTML = 'GET <code>/api/alpha/post/list?type_=Popular&sort=Hot&page=1</code></p>'
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelector('#site_json').textContent = JSON.stringify(data, null, 2);
|
||||
})
|
||||
|
||||
|
||||
let postlist = document.querySelector('#post_list_request');
|
||||
if (postlist) {
|
||||
if (jwt != null) {
|
||||
var api_postlist = baseUrl + '/api/alpha/post/list?type_=Subscribed&sort=New&page=1';
|
||||
} else {
|
||||
var api_postlist = baseUrl + '/api/alpha/post/list?type_=Popular&sort=Hot&page=1';
|
||||
}
|
||||
|
||||
fetch(api_postlist, request)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.querySelector('#post_list_json').textContent = JSON.stringify(data, null, 2);
|
||||
})
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
{% extends 'themes/' + theme() + '/base.html' %}
|
||||
|
||||
{% block app_content %}
|
||||
<p class="mb-0" id="site_request"></p>
|
||||
<details><summary>JSON</summary><pre id="site_json"></pre></details>
|
||||
<p class="mb-0">GET <code>/api/alpha/community/list</code></p>
|
||||
<details><summary>JSON</summary><pre id="community_list_json"></pre></details>
|
||||
|
||||
<script src="{{ '/static/themes/' + theme() + '/js/list_communities.js' }}" type="module"></script>
|
||||
{% endblock %}
|
|
@ -1,15 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
|
||||
<symbol id="check2" viewBox="0 0 16 16">
|
||||
<path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/>
|
||||
</symbol>
|
||||
<symbol id="circle-half" viewBox="0 0 16 16">
|
||||
<path d="M8 15A7 7 0 1 0 8 1v14zm0 1A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"/>
|
||||
</symbol>
|
||||
<symbol id="moon-stars-fill" viewBox="0 0 16 16">
|
||||
<path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"/>
|
||||
<path d="M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.31 6.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L13.863.1z"/>
|
||||
</symbol>
|
||||
<symbol id="sun-fill" viewBox="0 0 16 16">
|
||||
<path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"/>
|
||||
</symbol>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.1 KiB |
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"name": "X API",
|
||||
"debug": true
|
||||
}
|
|
@ -1106,8 +1106,6 @@ def theme_list():
|
|||
for dir in dirs:
|
||||
if os.path.exists(f'app/templates/themes/{dir}/{dir}.json'):
|
||||
theme_settings = json.loads(file_get_contents(f'app/templates/themes/{dir}/{dir}.json'))
|
||||
if 'debug' in theme_settings and theme_settings['debug'] == True and not current_app.debug:
|
||||
continue
|
||||
result.append((dir, theme_settings['name']))
|
||||
return result
|
||||
|
||||
|
|
Loading…
Reference in a new issue