lib.itmens/social/views.py

262 lines
8 KiB
Python
Raw Normal View History

2023-07-20 21:59:49 -04:00
from django.contrib.auth.decorators import login_required
2023-09-03 20:11:46 +00:00
from django.shortcuts import redirect, render
from django.urls import reverse
2023-12-25 17:27:31 -05:00
from django.views.decorators.http import require_http_methods
2022-12-13 06:44:29 +00:00
2024-12-30 01:51:19 -05:00
from catalog.models import Edition, Item, ItemCategory, PodcastEpisode
from common.models.misc import int_
from journal.models import JournalIndex, JournalQueryParser, Piece, ShelfType
2024-12-30 01:51:19 -05:00
from takahe.models import Post, PostInteraction, TimelineEvent
2024-04-19 20:24:34 -04:00
from takahe.utils import Takahe
2024-12-30 01:51:19 -05:00
from users.models import APIdentity
2022-12-21 14:34:36 -05:00
PAGE_SIZE = 10
2024-12-30 01:51:19 -05:00
def _sidebar_context(user):
podcast_ids = [
p.item_id
for p in user.shelf_manager.get_latest_members(
ShelfType.PROGRESS, ItemCategory.Podcast
)
]
recent_podcast_episodes = PodcastEpisode.objects.filter(
program_id__in=podcast_ids
).order_by("-pub_date")[:10]
books_in_progress = Edition.objects.filter(
id__in=[
p.item_id
for p in user.shelf_manager.get_latest_members(
ShelfType.PROGRESS, ItemCategory.Book
)[:10]
]
)
tvshows_in_progress = Item.objects.filter(
id__in=[
p.item_id
for p in user.shelf_manager.get_latest_members(
ShelfType.PROGRESS, ItemCategory.TV
)[:10]
]
)
2024-12-30 01:51:19 -05:00
return {
"recent_podcast_episodes": recent_podcast_episodes,
"books_in_progress": books_in_progress,
"tvshows_in_progress": tvshows_in_progress,
}
def _add_interaction_to_events(events, identity_id):
interactions = PostInteraction.objects.filter(
identity_id=identity_id,
post_id__in=[event.subject_post_id for event in events],
type__in=["like", "boost"],
state__in=["new", "fanned_out"],
).values_list("post_id", "type")
for event in events:
if event.subject_post_id:
event.subject_post.liked_by_current_user = ( # type: ignore
event.subject_post_id,
"like",
) in interactions
event.subject_post.boosted_by_current_user = ( # type: ignore
event.subject_post_id,
"boost",
) in interactions
2024-12-30 01:51:19 -05:00
@require_http_methods(["GET"])
@login_required
def feed(request, typ=0):
if not request.user.registration_complete:
return redirect(reverse("users:register"))
user = request.user
data = _sidebar_context(user)
data["feed_type"] = typ
return render(request, "feed.html", data)
2022-12-21 14:34:36 -05:00
2024-06-18 17:26:58 -04:00
def focus(request):
return feed(request, typ=1)
2024-12-30 01:51:19 -05:00
@require_http_methods(["GET"])
@login_required
def search(request):
if not request.user.registration_complete:
return redirect(reverse("users:register"))
user = request.user
data = _sidebar_context(user)
return render(request, "search_feed.html", data)
2022-12-21 14:34:36 -05:00
@login_required
2023-12-25 17:27:31 -05:00
@require_http_methods(["GET"])
def search_data(request):
2024-06-18 12:18:31 -04:00
identity_id = request.user.identity.pk
page = int_(request.GET.get("lastpage")) + 1
q = JournalQueryParser(request.GET.get("q", default=""), page, page_size=PAGE_SIZE)
index = JournalIndex.instance()
q.filter("post_id", ">0")
q.filter("owner_id", identity_id)
q.sort(["created:desc"])
2024-12-30 01:51:19 -05:00
if q:
r = index.search(q)
2024-12-30 01:51:19 -05:00
events = [
SearchResultEvent(p)
for p in r.posts.select_related("author")
.prefetch_related("attachments")
.order_by("-id")
]
_add_interaction_to_events(events, identity_id)
2024-12-30 01:51:19 -05:00
else:
events = []
return render(
request,
"feed_events.html",
{"events": events, "page": page},
)
@login_required
@require_http_methods(["GET"])
def data(request):
since_id = int_(request.GET.get("last", 0))
typ = int_(request.GET.get("typ", 0))
identity_id = request.user.identity.pk
events = TimelineEvent.objects.filter(
identity_id=identity_id,
type__in=[TimelineEvent.Types.post, TimelineEvent.Types.boost],
)
match typ:
case 1:
events = events.filter(
subject_post__type_data__object__has_key="relatedWith"
2024-12-30 01:51:19 -05:00
)
case _: # default: no replies
events = events.filter(subject_post__in_reply_to__isnull=True)
if since_id:
events = events.filter(id__lt=since_id)
events = list(
events.select_related(
"subject_post",
"subject_post__author",
# "subject_post__author__domain",
"subject_identity",
# "subject_identity__domain",
"subject_post_interaction",
"subject_post_interaction__identity",
# "subject_post_interaction__identity__domain",
2024-06-18 09:11:06 -04:00
)
.prefetch_related(
"subject_post__attachments",
# "subject_post__mentions",
# "subject_post__emojis",
)
.order_by("-id")[:PAGE_SIZE]
)
_add_interaction_to_events(events, identity_id)
2024-12-30 01:51:19 -05:00
return render(
request,
"feed_events.html",
{"feed_type": typ, "events": events},
2024-12-30 01:51:19 -05:00
)
2024-06-18 00:10:31 -04:00
2024-04-19 20:24:34 -04:00
@require_http_methods(["GET"])
@login_required
def notification(request):
if not request.user.registration_complete:
return redirect(reverse("users:register"))
user = request.user
podcast_ids = [
p.item_id
for p in user.shelf_manager.get_latest_members(
ShelfType.PROGRESS, ItemCategory.Podcast
)
]
recent_podcast_episodes = PodcastEpisode.objects.filter(
program_id__in=podcast_ids
).order_by("-pub_date")[:10]
books_in_progress = Edition.objects.filter(
id__in=[
p.item_id
for p in user.shelf_manager.get_latest_members(
ShelfType.PROGRESS, ItemCategory.Book
)[:10]
]
)
tvshows_in_progress = Item.objects.filter(
id__in=[
p.item_id
for p in user.shelf_manager.get_latest_members(
ShelfType.PROGRESS, ItemCategory.TV
)[:10]
]
)
return render(
request,
"notification.html",
{
"recent_podcast_episodes": recent_podcast_episodes,
"books_in_progress": books_in_progress,
"tvshows_in_progress": tvshows_in_progress,
},
)
class NotificationEvent:
def __init__(self, tle) -> None:
self.event = tle
self.type = tle.type
self.template = tle.type
self.created = tle.created
self.identity = (
APIdentity.objects.filter(pk=tle.subject_identity.pk).first()
if tle.subject_identity
else None
)
self.post = tle.subject_post
if self.type == "mentioned":
# for reply, self.post is the original post
self.reply = self.post
self.replies = [self.post]
self.post = self.post.in_reply_to_post() if self.post else None
self.piece = Piece.get_by_post_id(self.post.id) if self.post else None
self.item = getattr(self.piece, "item") if hasattr(self.piece, "item") else None
2024-04-20 10:01:46 -04:00
if self.piece and self.template in ["liked", "boosted", "mentioned"]:
2024-04-19 20:24:34 -04:00
cls = self.piece.__class__.__name__.lower()
self.template += "_" + cls
2024-12-30 01:51:19 -05:00
class SearchResultEvent:
def __init__(self, post: Post):
self.type = "post"
self.subject_post = post
self.subject_post_id = post.id
self.created = post.created
self.published = post.published
self.identity = post.author
2024-04-19 20:24:34 -04:00
@login_required
@require_http_methods(["GET"])
def events(request):
2024-04-20 10:01:46 -04:00
match request.GET.get("type"):
case "follow":
types = ["followed", "follow_requested"]
case "mention":
types = ["mentioned"]
case _:
types = ["liked", "boosted", "mentioned", "followed", "follow_requested"]
es = Takahe.get_events(request.user.identity.pk, types)
2024-04-19 20:24:34 -04:00
last = request.GET.get("last")
if last:
es = es.filter(created__lt=last)
nes = [NotificationEvent(e) for e in es[:PAGE_SIZE]]
return render(
request,
"events.html",
{"events": nes},
)