Skip to content

Commit

Permalink
kammer
Browse files Browse the repository at this point in the history
  • Loading branch information
jhnnsrs committed Jun 23, 2024
1 parent c6ae47b commit 32ddf3f
Show file tree
Hide file tree
Showing 23 changed files with 652 additions and 0 deletions.
Binary file modified .DS_Store
Binary file not shown.
Empty file added kammer/__init__.py
Empty file.
8 changes: 8 additions & 0 deletions kammer/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.contrib import admin

from kammer import models

# Register your models here.
admin.site.register(models.Room)
admin.site.register(models.Agent)
admin.site.register(models.Structure)
6 changes: 6 additions & 0 deletions kammer/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class KammerConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "kammer"
3 changes: 3 additions & 0 deletions kammer/channels.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from ekke.channel import build_channel

mention_broadcast, mention_listen = build_channel("mention_broadcast")
19 changes: 19 additions & 0 deletions kammer/enums.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from enum import Enum
import strawberry
from django.db.models import TextChoices



@strawberry.enum(description="The Kind of a Descendant")
class DescendantKind(str, Enum):
"""The Kind of a Descendant
Determines the type of rich rendering that should be applied to the descendant
"""

LEAF = "LEAF"
MENTION = "MENTION"
PARAGRAPH = "PARAGRAPH"

17 changes: 17 additions & 0 deletions kammer/filters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import strawberry
from komment import models, scalars, enums
from strawberry import auto
from typing import Optional
from strawberry_django.filters import FilterLookup
import strawberry_django


@strawberry_django.filter(models.Comment)
class CommentFilter:
name: Optional[FilterLookup[str]] | None
ids: list[strawberry.ID] | None

def filter_ids(self, queryset, info):
if self.ids is None:
return queryset
return queryset.filter(id__in=self.ids)
1 change: 1 addition & 0 deletions kammer/graphql/mutations/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .comment import *
129 changes: 129 additions & 0 deletions kammer/graphql/mutations/comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
from ekke.types import Info
import strawberry_django
import strawberry
from komment import types, models, inputs, enums, scalars
import hashlib
import json
import logging
from typing import Dict, Tuple, List, Any

logger = logging.getLogger(__name__)
from komment import inputs
from django.contrib.auth import get_user_model


def recurse_parse_decendents(
variables: List[Dict[str, Any]],
) -> Tuple[Dict, List[str]]:
"""Parse Variables
Recursively traverse variables, applying the apply function to the value if the predicate
returns True.
Args:
variables (Dict): The dictionary to parse.
Returns:
Dict: The parsed dictionary.
Mentions: A list of mentions.
"""

mentions = []

def recurse_extract(obj, path: str = None):
"""
recursively traverse obj, doing a deepcopy, but
replacing any file-like objects with nulls and
shunting the originals off to the side.
"""

if isinstance(obj, list):
nulled_obj = []
for key, value in enumerate(obj):
value = recurse_extract(
value,
f"{path}.{key}" if path else key,
)
nulled_obj.append(value)
return nulled_obj
elif isinstance(obj, dict):
nulled_obj = {}
for key, value in obj.items():
if key == "kind" and value == "MENTION":
mentions.append(obj)
value = recurse_extract(value, f"{path}.{key}" if path else key)
nulled_obj[key] = value
return nulled_obj
else:
return obj

dicted_variables = recurse_extract(variables)

return dicted_variables, mentions


@strawberry.input
class CreateCommentInput:
descendants: list[inputs.DescendantInput]
identifier: scalars.Identifier
object: strawberry.ID
parent: strawberry.ID | None = None
notify: bool | None = False


def create_comment(info: Info, input: CreateCommentInput) -> types.Comment:
creator = info.context.request.user

serialized_descendants = strawberry.asdict(input)["descendants"]

dicted_variables, mentions = recurse_parse_decendents(serialized_descendants)

# TODO: Check if user is allowed to comment on these types of objects

exp = models.Comment.objects.create(
identifier=input.identifier,
object=input.object,
user=creator,
text="",
descendants=serialized_descendants,
parent_id=input.parent,
)

users = [get_user_model().objects.get(id=m["user"]) for m in mentions]
if input.notify:
for user in users:
user.notify(
f"You have been mentioned in a comment by {creator.username}",
f"Comment on {input.identifier}",
)

print(users)
exp.mentions.set(users)
exp.save()

return exp

trace = models.User(name=input.user)
return trace


@strawberry.input
class ReplyToCommentInput:
descendants: list[inputs.DescendantInput]
parent: strawberry.ID | None
notify: bool | None


def reply_to(info: Info, input: ReplyToCommentInput) -> types.Comment:
raise NotImplementedError("TODO: Implement")


@strawberry.input
class ResolveCommentInput:
id: strawberry.ID
notify: bool | None


def resolve_comment(info: Info, input: ResolveCommentInput) -> types.Comment:
raise NotImplementedError("TODO: Implement")
1 change: 1 addition & 0 deletions kammer/graphql/queries/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .comment import *
21 changes: 21 additions & 0 deletions kammer/graphql/queries/comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import hashlib
import json
import logging

import strawberry
from ekke.types import Info
from komment import enums, inputs, models, scalars, types


def comment(info: Info, id: strawberry.ID) -> types.Comment:
return models.Comment.objects.get(id=id)


def comments_for(
info: Info, identifier: scalars.Identifier, object: strawberry.ID
) -> list[types.Comment]:
return models.Comment.objects.filter(identifier=identifier, object=object)


def my_mentions(info: Info) -> types.Comment:
return models.Comment.objects.filter(mentions__contains=info.context.request.user)
1 change: 1 addition & 0 deletions kammer/graphql/subscriptions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .comment import *
14 changes: 14 additions & 0 deletions kammer/graphql/subscriptions/comment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from ekke.types import Info
import strawberry_django
import strawberry
from komment import types, models, scalars
from typing import AsyncGenerator
from komment.channels import mention_listen


async def mentions(
self, info: Info
) -> AsyncGenerator[types.Comment, None]:
"""Join and subscribe to message sent to the given rooms."""
async for message in mention_listen(info, ["user-" + str(info.context.request.user.id)]):
yield await models.Comment.objects.aget(id=message)
28 changes: 28 additions & 0 deletions kammer/inputs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from komment import enums, scalars
import strawberry
from typing import Optional
from pydantic import BaseModel
from strawberry.experimental import pydantic
from typing import Any
from strawberry import LazyType


class DescendandInputModel(BaseModel):
kind: enums.DescendantKind
children: list["DescendandInputModel"] | None
user: str | None
bold: bool | None
italic: bool | None
code: bool | None
text: str | None


@pydantic.input(DescendandInputModel)
class DescendantInput:
kind: enums.DescendantKind
children: list[LazyType["DescendantInput", __name__]] | None
user: str | None
bold: bool | None
italic: bool | None
code: bool | None
text: str | None
72 changes: 72 additions & 0 deletions kammer/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Generated by Django 4.2.4 on 2023-09-05 16:53

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):
initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name="Comment",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("identifier", models.CharField(max_length=1000)),
("object", models.PositiveIntegerField()),
("text", models.TextField()),
("created_at", models.DateTimeField(auto_now_add=True)),
("descendents", models.JSONField(default=list)),
("resolved", models.DateTimeField(blank=True, null=True)),
(
"mentions",
models.ManyToManyField(
blank=True,
related_name="mentioned_in",
to=settings.AUTH_USER_MODEL,
),
),
(
"parent",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="children",
to="komment.comment",
),
),
(
"resolved_by",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="resolved_comments",
to=settings.AUTH_USER_MODEL,
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="comments",
to=settings.AUTH_USER_MODEL,
),
),
],
),
]
17 changes: 17 additions & 0 deletions kammer/migrations/0002_rename_descendents_comment_descendants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 4.2.4 on 2023-09-06 07:49

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("komment", "0001_initial"),
]

operations = [
migrations.RenameField(
model_name="comment",
old_name="descendents",
new_name="descendants",
),
]
Loading

0 comments on commit 32ddf3f

Please sign in to comment.