1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
import json
from typing import Optional
from django import urls
from django.contrib import admin
from django.http import HttpRequest
from django.utils.html import format_html
from .models import (
BotSetting,
DeletedMessage,
DocumentationLink,
Infraction,
LogEntry,
MessageDeletionContext,
Nomination,
OffTopicChannelName,
Role,
Tag,
User
)
class LogEntryAdmin(admin.ModelAdmin):
"""Allows viewing logs in the Django Admin without allowing edits."""
actions = None
list_display = ('timestamp', 'application', 'level', 'message')
fieldsets = (
('Overview', {'fields': ('timestamp', 'application', 'logger_name')}),
('Metadata', {'fields': ('level', 'module', 'line')}),
('Contents', {'fields': ('message',)})
)
list_filter = ('application', 'level', 'timestamp')
search_fields = ('message',)
readonly_fields = (
'application',
'logger_name',
'timestamp',
'level',
'module',
'line',
'message'
)
def has_add_permission(self, request: HttpRequest) -> bool:
"""Deny manual LogEntry creation."""
return False
def has_delete_permission(self, request: HttpRequest, obj: Optional[LogEntry] = None) -> bool:
"""Deny LogEntry deletion."""
return False
class DeletedMessageAdmin(admin.ModelAdmin):
"""Admin formatting for the DeletedMessage model."""
readonly_fields = (
"id",
"author",
"channel_id",
"content",
"embed_data",
"context",
"view_full_log"
)
exclude = ("embeds", "deletion_context")
search_fields = (
"id",
"content",
"author__name",
"author__id",
"deletion_context__actor__name",
"deletion_context__actor__id"
)
@staticmethod
def embed_data(instance: DeletedMessage) -> Optional[str]:
"""Format embed data in a code block for better readability."""
if instance.embeds:
return format_html(
"<pre><code>{0}</code></pre>",
json.dumps(instance.embeds, indent=4)
)
@staticmethod
def context(instance: DeletedMessage) -> str:
"""Provide full context info with a link through to context admin view."""
link = urls.reverse(
"admin:api_messagedeletioncontext_change",
args=[instance.deletion_context.id]
)
details = (
f"Deleted by {instance.deletion_context.actor} at "
f"{instance.deletion_context.creation}"
)
return format_html("<a href='{0}'>{1}</a>", link, details)
@staticmethod
def view_full_log(instance: DeletedMessage) -> str:
"""Provide a link to the message logs for the relevant context."""
return format_html(
"<a href='{0}'>Click to view full context log</a>",
instance.deletion_context.log_url
)
class MessageDeletionContextAdmin(admin.ModelAdmin):
"""Admin formatting for the MessageDeletionContext model."""
readonly_fields = ("actor", "creation", "message_log")
@staticmethod
def message_log(instance: MessageDeletionContext) -> str:
"""Provide a formatted link to the message logs for the context."""
return format_html(
"<a href='{0}'>Click to see deleted message log</a>",
instance.log_url
)
admin.site.register(BotSetting)
admin.site.register(DeletedMessage, DeletedMessageAdmin)
admin.site.register(DocumentationLink)
admin.site.register(Infraction)
admin.site.register(LogEntry, LogEntryAdmin)
admin.site.register(MessageDeletionContext, MessageDeletionContextAdmin)
admin.site.register(Nomination)
admin.site.register(OffTopicChannelName)
admin.site.register(Role)
admin.site.register(Tag)
admin.site.register(User)
|