use announcement model from takahe
This commit is contained in:
parent
93b1dd403a
commit
05821eaac1
27 changed files with 203 additions and 355 deletions
|
@ -297,7 +297,6 @@ INSTALLED_APPS = [
|
|||
]
|
||||
|
||||
INSTALLED_APPS += [
|
||||
"management.apps.ManagementConfig",
|
||||
"mastodon.apps.MastodonConfig",
|
||||
"common.apps.CommonConfig",
|
||||
"users.apps.UsersConfig",
|
||||
|
|
|
@ -41,7 +41,6 @@ urlpatterns = [
|
|||
path("", include("catalog.urls")),
|
||||
path("", include("journal.urls")),
|
||||
path("timeline/", include("social.urls")),
|
||||
path("announcement/", include("management.urls")),
|
||||
path("hijack/", include("hijack.urls")),
|
||||
path("", include("common.urls")),
|
||||
path("", include("legacy.urls")),
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
rel="noopener"
|
||||
href="{{ link.url }}">{{ link.title }}</a>
|
||||
{% endfor %}
|
||||
<a class="footer__link" href="{% url 'management:list' %}">公告栏</a>
|
||||
<a class="footer__link" href="{% url 'users:announcements' %}">公告栏</a>
|
||||
<a class="footer__link" href="{% url 'oauth2_provider:developer' %}">应用开发</a>
|
||||
<a class="footer__link"
|
||||
title="{{ neodb_version }}"
|
||||
|
|
|
@ -12,23 +12,14 @@
|
|||
{% if request.user.unread_announcements %}
|
||||
<section class="announcement">
|
||||
<article>
|
||||
<h5>
|
||||
未读公告
|
||||
<small> | <a href="{% url 'management:list' %}">全部</a> </small>
|
||||
</h5>
|
||||
{% for ann in request.user.unread_announcements %}
|
||||
<details open>
|
||||
<summary>
|
||||
{{ ann.title }}
|
||||
<small>(<a href="{% url 'management:retrieve' ann.pk %}">{{ ann.created_time|date }}</a>)</small>
|
||||
</summary>
|
||||
<div class="tldr" _="on click toggle .tldr on me">{{ ann.get_html_content | safe }}</div>
|
||||
</details>
|
||||
{% endfor %}
|
||||
<summary>未读公告</summary>
|
||||
{% for ann in request.user.unread_announcements %}<div>{{ ann.html }}</div>{% endfor %}
|
||||
<form action="{% url 'users:mark_announcements_read' %}" method="post">
|
||||
{% csrf_token %}
|
||||
<input type="submit" class="secondary outline" value="{% trans '全部标为已读' %}">
|
||||
</form>
|
||||
</details>
|
||||
</article>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
Developer Console | <a href="{% url 'oauth2_provider:list' %}">{% trans "Your applications" %}</a>
|
||||
</h3>
|
||||
<p class="empty">
|
||||
By using our APIs, you agree to our <a href="{% url 'management:retrieve_slug' 'developer-term' %}">term</a> and <a href="{% url 'management:retrieve_slug' 'data-policy' %}">data policy</a>.
|
||||
By using our APIs, you agree to our <a href="/pages/terms">Terms of Service</a>.
|
||||
</p>
|
||||
<details {% if token %}open{% endif %}>
|
||||
<summary>
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from .models import *
|
||||
|
||||
admin.site.register(Announcement)
|
|
@ -1,5 +0,0 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ManagementConfig(AppConfig):
|
||||
name = "management"
|
|
@ -1,45 +0,0 @@
|
|||
# Generated by Django 3.2.16 on 2023-01-12 01:32
|
||||
|
||||
import markdownx.models
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Announcement",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("title", models.CharField(max_length=200)),
|
||||
("content", markdownx.models.MarkdownxField()),
|
||||
(
|
||||
"slug",
|
||||
models.SlugField(
|
||||
allow_unicode=True,
|
||||
blank=True,
|
||||
max_length=300,
|
||||
null=True,
|
||||
unique=True,
|
||||
),
|
||||
),
|
||||
("created_time", models.DateTimeField(auto_now_add=True)),
|
||||
("edited_time", models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Announcement",
|
||||
"verbose_name_plural": "Announcements",
|
||||
},
|
||||
),
|
||||
]
|
|
@ -1,44 +0,0 @@
|
|||
import re
|
||||
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from markdown import markdown
|
||||
from markdownx.models import MarkdownxField
|
||||
|
||||
RE_HTML_TAG = re.compile(r"<[^>]*>")
|
||||
|
||||
|
||||
class Announcement(models.Model):
|
||||
"""Model definition for Announcement."""
|
||||
|
||||
title = models.CharField(max_length=200)
|
||||
content = MarkdownxField()
|
||||
slug = models.SlugField(
|
||||
max_length=300, allow_unicode=True, unique=True, null=True, blank=True
|
||||
)
|
||||
created_time = models.DateTimeField(auto_now_add=True)
|
||||
edited_time = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta definition for Announcement."""
|
||||
|
||||
verbose_name = "Announcement"
|
||||
verbose_name_plural = "Announcements"
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse("management:retrieve", kwargs={"pk": self.pk})
|
||||
|
||||
def get_html_content(self):
|
||||
html = markdown(self.content)
|
||||
return html
|
||||
|
||||
def get_plain_content(self):
|
||||
"""
|
||||
Get plain text format content
|
||||
"""
|
||||
return RE_HTML_TAG.sub(" ", self.get_html_content())
|
||||
|
||||
def __str__(self):
|
||||
"""Unicode representation of Announcement."""
|
||||
return self.title
|
|
@ -1,32 +0,0 @@
|
|||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Create/Update Announcement</title>
|
||||
{% include "common_libs.html" %}
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Create/Update Announcement</h1>
|
||||
<article>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="Save">
|
||||
</form>
|
||||
{{ form.media }}
|
||||
</article>
|
||||
</div>
|
||||
<script>
|
||||
function convertToSlug(text) {
|
||||
// return encodeURI(text.toLowerCase().replace(/ +/g, '-'));
|
||||
return text.toLowerCase().replace(/[ ;\.\:\?\!@#\$%\^&\*\(\)\=\+\<\>`~·,。“”?!《》【】:;\\{}\[\]]+/g, '-');
|
||||
}
|
||||
document.getElementById("id_title").addEventListener('input', function (evt) {
|
||||
document.getElementById("id_slug").value = convertToSlug(this.value);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,24 +0,0 @@
|
|||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Delete Announcement</title>
|
||||
{% include "common_libs.html" %}
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
body {
|
||||
padding-top: 40px;
|
||||
}
|
||||
</style>
|
||||
<div class="container">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<p>Are you sure you want to delete "{{ object }}"?</p>
|
||||
<input type="submit" value="Confirm">
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,33 +0,0 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
{% include "common_libs.html" %}
|
||||
<title>{{ site_name }} - {{ object.title }}</title>
|
||||
</head>
|
||||
<body>
|
||||
{% include "_header.html" %}
|
||||
<main class="container">
|
||||
<article>
|
||||
<header>
|
||||
<h3>{{ object.title }}</h3>
|
||||
{{ object.created_time|date }}
|
||||
{% if request.user.is_superuser %}
|
||||
<span class="operations">
|
||||
<a href="{% url 'management:delete' object.pk %}">{% trans '删除' %}</a>
|
||||
<a href="{% url 'management:update' object.pk %}">{% trans '编辑' %}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
</header>
|
||||
<p>{{ object.get_html_content | safe }}</p>
|
||||
<footer>
|
||||
<a href="{% url 'management:list' %}">{% trans '返回公告栏' %}</a>
|
||||
</footer>
|
||||
</article>
|
||||
</main>
|
||||
{% include "_footer.html" %}
|
||||
</body>
|
||||
</html>
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,13 +0,0 @@
|
|||
from django.urls import path
|
||||
|
||||
from .views import *
|
||||
|
||||
app_name = "management"
|
||||
urlpatterns = [
|
||||
path("", AnnouncementListView.as_view(), name="list"),
|
||||
path("<int:pk>/", AnnouncementDetailView.as_view(), name="retrieve"),
|
||||
path("create/", AnnouncementCreateView.as_view(), name="create"),
|
||||
path("<str:slug>/", AnnouncementDetailView.as_view(), name="retrieve_slug"),
|
||||
path("<int:pk>/update/", AnnouncementUpdateView.as_view(), name="update"),
|
||||
path("<int:pk>/delete/", AnnouncementDeleteView.as_view(), name="delete"),
|
||||
]
|
|
@ -1,58 +0,0 @@
|
|||
from django.contrib.auth.decorators import login_required, user_passes_test
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils import timezone
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.generic import (
|
||||
CreateView,
|
||||
DeleteView,
|
||||
DetailView,
|
||||
ListView,
|
||||
UpdateView,
|
||||
)
|
||||
from django.views.generic.edit import ModelFormMixin
|
||||
|
||||
from .models import Announcement
|
||||
|
||||
# https://docs.djangoproject.com/en/3.1/topics/class-based-views/intro/
|
||||
decorators = [login_required, user_passes_test(lambda u: u.is_superuser)] # type:ignore
|
||||
|
||||
|
||||
class AnnouncementDetailView(DetailView, ModelFormMixin):
|
||||
model = Announcement
|
||||
fields = ["content"]
|
||||
template_name = "management/detail.html"
|
||||
|
||||
|
||||
class AnnouncementListView(ListView):
|
||||
model = Announcement
|
||||
# paginate_by = 1
|
||||
template_name = "management/list.html"
|
||||
|
||||
def get_queryset(self):
|
||||
return Announcement.objects.all().order_by("-pk")
|
||||
|
||||
|
||||
@method_decorator(decorators, name="dispatch")
|
||||
class AnnouncementDeleteView(DeleteView):
|
||||
model = Announcement
|
||||
success_url = reverse_lazy("management:list")
|
||||
template_name = "management/delete.html"
|
||||
|
||||
|
||||
@method_decorator(decorators, name="dispatch")
|
||||
class AnnouncementCreateView(CreateView):
|
||||
model = Announcement
|
||||
fields = "__all__"
|
||||
template_name = "management/create_update.html"
|
||||
|
||||
|
||||
@method_decorator(decorators, name="dispatch")
|
||||
class AnnouncementUpdateView(UpdateView):
|
||||
model = Announcement
|
||||
fields = "__all__"
|
||||
template_name = "management/create_update.html"
|
||||
|
||||
def form_valid(self, form):
|
||||
form.instance.edited_time = timezone.now()
|
||||
return super().form_valid(form)
|
|
@ -913,4 +913,49 @@ class Migration(migrations.Migration):
|
|||
"db_table": "users_relay",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Announcement",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"text",
|
||||
models.TextField(),
|
||||
),
|
||||
(
|
||||
"published",
|
||||
models.BooleanField(
|
||||
default=False,
|
||||
),
|
||||
),
|
||||
(
|
||||
"start",
|
||||
models.DateTimeField(
|
||||
blank=True,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"end",
|
||||
models.DateTimeField(
|
||||
blank=True,
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
("include_unauthenticated", models.BooleanField(default=False)),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
("updated", models.DateTimeField(auto_now=True)),
|
||||
("seen", models.ManyToManyField(blank=True, to="takahe.user")),
|
||||
],
|
||||
options={
|
||||
"db_table": "users_announcement",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1921,3 +1921,42 @@ class Relay(models.Model):
|
|||
class Meta:
|
||||
# managed = False
|
||||
db_table = "users_relay"
|
||||
|
||||
|
||||
class Announcement(models.Model):
|
||||
"""
|
||||
A server-wide announcement that users all see and can dismiss.
|
||||
"""
|
||||
|
||||
text = models.TextField()
|
||||
|
||||
published = models.BooleanField(
|
||||
default=False,
|
||||
)
|
||||
start = models.DateTimeField(
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
end = models.DateTimeField(
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
|
||||
include_unauthenticated = models.BooleanField(default=False)
|
||||
|
||||
# Note that this is against User, not Identity - it's one of the few places
|
||||
# where we want it to be per login.
|
||||
seen = models.ManyToManyField("User", blank=True)
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
|
||||
class Meta:
|
||||
# managed = False
|
||||
db_table = "users_announcement"
|
||||
|
||||
@property
|
||||
def html(self) -> str:
|
||||
from journal.models import render_md
|
||||
|
||||
return mark_safe(render_md(self.text))
|
||||
|
|
|
@ -891,3 +891,54 @@ class Takahe:
|
|||
return False
|
||||
invite = Invite.objects.filter(token=token).first()
|
||||
return invite and invite.valid
|
||||
|
||||
@staticmethod
|
||||
def get_announcements():
|
||||
now = timezone.now()
|
||||
return Announcement.objects.filter(
|
||||
models.Q(start__lte=now) | models.Q(start__isnull=True),
|
||||
models.Q(end__gte=now) | models.Q(end__isnull=True),
|
||||
published=True,
|
||||
).order_by("-start", "-created")
|
||||
|
||||
@staticmethod
|
||||
def get_announcements_for_user(u: "NeoUser"):
|
||||
identity = (
|
||||
Identity.objects.filter(pk=u.identity.pk, local=True).first()
|
||||
if u and u.is_authenticated and u.identity
|
||||
else None
|
||||
)
|
||||
user = identity.users.all().first() if identity else None
|
||||
if not user:
|
||||
return Announcement.objects.none()
|
||||
now = timezone.now()
|
||||
return (
|
||||
Announcement.objects.filter(
|
||||
models.Q(start__lte=now) | models.Q(start__isnull=True),
|
||||
models.Q(end__gte=now) | models.Q(end__isnull=True),
|
||||
published=True,
|
||||
)
|
||||
.order_by("-start", "-created")
|
||||
.exclude(seen=user)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def mark_announcements_seen(u: "NeoUser"):
|
||||
identity = (
|
||||
Identity.objects.filter(pk=u.identity.pk, local=True).first()
|
||||
if u and u.is_authenticated and u.identity
|
||||
else None
|
||||
)
|
||||
user = identity.users.all().first() if identity else None
|
||||
if not user:
|
||||
return
|
||||
now = timezone.now()
|
||||
for a in (
|
||||
Announcement.objects.filter(
|
||||
models.Q(start__lte=now) | models.Q(start__isnull=True),
|
||||
published=True,
|
||||
)
|
||||
.order_by("-start", "-created")
|
||||
.exclude(seen=user)
|
||||
):
|
||||
a.seen.add(user)
|
||||
|
|
|
@ -17,7 +17,6 @@ from django.utils.deconstruct import deconstructible
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from loguru import logger
|
||||
|
||||
from management.models import Announcement
|
||||
from mastodon.api import *
|
||||
from takahe.utils import Takahe
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ from django.utils.deconstruct import deconstructible
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from loguru import logger
|
||||
|
||||
from management.models import Announcement
|
||||
from mastodon.api import *
|
||||
from takahe.utils import Takahe
|
||||
|
||||
|
@ -382,12 +381,11 @@ class User(AbstractUser):
|
|||
self.sync_relationship()
|
||||
return True
|
||||
|
||||
@property
|
||||
@cached_property
|
||||
def unread_announcements(self):
|
||||
unread_announcements = Announcement.objects.filter(
|
||||
pk__gt=self.read_announcement_index
|
||||
).order_by("-pk")
|
||||
return unread_announcements
|
||||
from takahe.utils import Takahe
|
||||
|
||||
return Takahe.get_announcements_for_user(self)
|
||||
|
||||
@property
|
||||
def activity_manager(self):
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load humanize %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
|
@ -40,29 +41,18 @@
|
|||
{% if request.user.is_superuser %}🦹🏻{% endif %}
|
||||
{% if request.user.is_staff %}🧙🏻{% endif %}
|
||||
</h1>
|
||||
{% if request.user.is_superuser %}
|
||||
<a href="{% url 'management:create' %}" class="add">{% trans '发布新公告' %}</a>
|
||||
{% endif %}
|
||||
{% for announcement in object_list %}
|
||||
{% for announcement in announcements %}
|
||||
<article>
|
||||
<header>
|
||||
<a href="{{ announcement.get_absolute_url }}">
|
||||
<h4>{{ announcement.title }}</h4>
|
||||
</a>
|
||||
<span class="datetime">{{ announcement.created_time }}</span>
|
||||
{% if request.user.is_superuser %}
|
||||
<span class="operations">
|
||||
<a href="{% url 'management:update' announcement.pk %}">{% trans '编辑' %}</a>
|
||||
<a href="{% url 'management:delete' announcement.pk %}">{% trans '删除' %}</a>
|
||||
{{ announcement.html | safe }}
|
||||
<footer>
|
||||
<span class="action inline"><span><a>{{ announcement.created|default:announcement.created|naturaltime }}</a></span>
|
||||
</span>
|
||||
{% endif %}
|
||||
</header>
|
||||
<p>{{ announcement.get_html_content | safe }}</p>
|
||||
</footer>
|
||||
</article>
|
||||
{% empty %}
|
||||
<p>{% trans '暂无公告' %}</p>
|
||||
{% endfor %}
|
||||
</main>
|
||||
{% include "_footer.html" %}
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
|
@ -169,7 +169,7 @@
|
|||
</article>
|
||||
<footer>
|
||||
<br>
|
||||
<small>继续访问或注册视为同意本站<a href="{% url 'management:retrieve_slug' 'data-policy' %}">数据方针</a>及使用cookie提供必要功能</small>
|
||||
<small>继续访问或注册视为同意<a href="/pages/rules/">站规</a>与<a href="/pages/terms/">协议</a>,及使用cookie提供必要功能</small>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<p>
|
||||
{{ site_name }}还在不断完善中。
|
||||
丰富的内容需要大家共同创造,试图添加垃圾数据(如添加信息混乱或缺失的书籍、以推广为主要目的的评论)将会受到严肃处理。
|
||||
本站为非盈利站点,cookie和其它数据保管使用原则请参阅<a href="{% url 'management:retrieve_slug' 'data-policy' %}">站内公告</a>。
|
||||
本站为非盈利站点,cookie和其它数据保管使用原则请参阅<a href="/pages/terms">站内公告</a>。
|
||||
本站提供API和导出功能,请妥善备份您的数据,使用过程中遇到的问题或者错误欢迎向<a href="{{ support_link }}">维护者</a>提出。感谢理解和支持!
|
||||
</p>
|
||||
{% endif %}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from django.urls import path
|
||||
|
||||
from .account import *
|
||||
from .profile import *
|
||||
from .views import *
|
||||
|
||||
app_name = "users"
|
||||
|
@ -56,4 +58,9 @@ urlpatterns = [
|
|||
mark_announcements_read,
|
||||
name="mark_announcements_read",
|
||||
),
|
||||
path(
|
||||
"announcements/",
|
||||
announcements,
|
||||
name="announcements",
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import json
|
||||
|
||||
from discord import SyncWebhook
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import BadRequest, PermissionDenied
|
||||
from django.core.exceptions import BadRequest
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.shortcuts import redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
@ -14,14 +13,12 @@ from common.utils import (
|
|||
HTTPResponseHXRedirect,
|
||||
target_identity_required,
|
||||
)
|
||||
from management.models import Announcement
|
||||
from mastodon.api import *
|
||||
from takahe.utils import Takahe
|
||||
|
||||
from .account import *
|
||||
from .data import *
|
||||
from .models import APIdentity, Preference, User
|
||||
from .profile import account_info, account_profile
|
||||
from .models import APIdentity
|
||||
|
||||
|
||||
def render_user_not_found(request, user_name=""):
|
||||
|
@ -92,9 +89,8 @@ def fetch_refresh(request):
|
|||
|
||||
@login_required
|
||||
@target_identity_required
|
||||
@require_http_methods(["POST"])
|
||||
def follow(request: AuthedHttpRequest, user_name):
|
||||
if request.method != "POST":
|
||||
raise BadRequest()
|
||||
request.user.identity.follow(request.target_identity)
|
||||
return render(
|
||||
request,
|
||||
|
@ -105,9 +101,8 @@ def follow(request: AuthedHttpRequest, user_name):
|
|||
|
||||
@login_required
|
||||
@target_identity_required
|
||||
@require_http_methods(["POST"])
|
||||
def unfollow(request: AuthedHttpRequest, user_name):
|
||||
if request.method != "POST":
|
||||
raise BadRequest()
|
||||
request.user.identity.unfollow(request.target_identity)
|
||||
return render(
|
||||
request,
|
||||
|
@ -118,9 +113,8 @@ def unfollow(request: AuthedHttpRequest, user_name):
|
|||
|
||||
@login_required
|
||||
@target_identity_required
|
||||
@require_http_methods(["POST"])
|
||||
def mute(request: AuthedHttpRequest, user_name):
|
||||
if request.method != "POST":
|
||||
raise BadRequest()
|
||||
request.user.identity.mute(request.target_identity)
|
||||
return render(
|
||||
request,
|
||||
|
@ -131,9 +125,8 @@ def mute(request: AuthedHttpRequest, user_name):
|
|||
|
||||
@login_required
|
||||
@target_identity_required
|
||||
@require_http_methods(["POST"])
|
||||
def unmute(request: AuthedHttpRequest, user_name):
|
||||
if request.method != "POST":
|
||||
raise BadRequest()
|
||||
request.user.identity.unmute(request.target_identity)
|
||||
return render(
|
||||
request,
|
||||
|
@ -144,9 +137,8 @@ def unmute(request: AuthedHttpRequest, user_name):
|
|||
|
||||
@login_required
|
||||
@target_identity_required
|
||||
@require_http_methods(["POST"])
|
||||
def block(request: AuthedHttpRequest, user_name):
|
||||
if request.method != "POST":
|
||||
raise BadRequest()
|
||||
request.user.identity.block(request.target_identity)
|
||||
return render(
|
||||
request,
|
||||
|
@ -156,9 +148,8 @@ def block(request: AuthedHttpRequest, user_name):
|
|||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["POST"])
|
||||
def unblock(request: AuthedHttpRequest, user_name):
|
||||
if request.method != "POST":
|
||||
raise BadRequest()
|
||||
try:
|
||||
target = APIdentity.get_by_handle(user_name)
|
||||
except APIdentity.DoesNotExist:
|
||||
|
@ -176,9 +167,8 @@ def unblock(request: AuthedHttpRequest, user_name):
|
|||
|
||||
@login_required
|
||||
@target_identity_required
|
||||
@require_http_methods(["POST"])
|
||||
def accept_follow_request(request: AuthedHttpRequest, user_name):
|
||||
if request.method != "POST":
|
||||
raise BadRequest()
|
||||
request.user.identity.accept_follow_request(request.target_identity)
|
||||
return render(
|
||||
request,
|
||||
|
@ -189,9 +179,8 @@ def accept_follow_request(request: AuthedHttpRequest, user_name):
|
|||
|
||||
@login_required
|
||||
@target_identity_required
|
||||
@require_http_methods(["POST"])
|
||||
def reject_follow_request(request: AuthedHttpRequest, user_name):
|
||||
if request.method != "POST":
|
||||
raise BadRequest()
|
||||
request.user.identity.reject_follow_request(request.target_identity)
|
||||
return render(
|
||||
request,
|
||||
|
@ -201,8 +190,8 @@ def reject_follow_request(request: AuthedHttpRequest, user_name):
|
|||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["POST"])
|
||||
def set_layout(request: AuthedHttpRequest):
|
||||
if request.method == "POST":
|
||||
layout = json.loads(request.POST.get("layout", "{}"))
|
||||
if request.POST.get("name") == "profile":
|
||||
request.user.preference.profile_layout = layout
|
||||
|
@ -216,12 +205,15 @@ def set_layout(request: AuthedHttpRequest):
|
|||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["POST"])
|
||||
def mark_announcements_read(request: AuthedHttpRequest):
|
||||
if request.method == "POST":
|
||||
try:
|
||||
request.user.read_announcement_index = Announcement.objects.latest("pk").pk
|
||||
request.user.save(update_fields=["read_announcement_index"])
|
||||
except ObjectDoesNotExist:
|
||||
# when there is no annoucenment
|
||||
pass
|
||||
Takahe.mark_announcements_seen(request.user)
|
||||
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
|
||||
|
||||
|
||||
def announcements(request):
|
||||
return render(
|
||||
request,
|
||||
"users/announcements.html",
|
||||
{"announcements": Takahe.get_announcements()},
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue