add chat box

This commit is contained in:
Dinh 2020-01-27 14:37:52 -06:00
parent 15b0e06a4f
commit af61e8a8e8
15 changed files with 175 additions and 6 deletions

0
chat_box/__init__.py Normal file
View file

3
chat_box/admin.py Normal file
View file

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

5
chat_box/apps.py Normal file
View file

@ -0,0 +1,5 @@
from django.apps import AppConfig
class ChatBoxConfig(AppConfig):
name = 'chat_box'

47
chat_box/consumers.py Normal file
View file

@ -0,0 +1,47 @@
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = 'common'
self.room_group_name = 'chat_%s' % self.room_name
# Join room group
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name,
)
await self.accept()
async def disconnect(self, close_code):
# Leave room group
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name,
)
# Receive message from WebSocket
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': message,
},
)
# Receive message from room group
async def chat_message(self, event):
message = event['message']
# Send message to WebSocket
await self.send(text_data=json.dumps({
'message': message,
}))

View file

3
chat_box/models.py Normal file
View file

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

7
chat_box/routing.py Normal file
View file

@ -0,0 +1,7 @@
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/chat/', consumers.ChatConsumer),
]

3
chat_box/tests.py Normal file
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

8
chat_box/views.py Normal file
View file

@ -0,0 +1,8 @@
from django.shortcuts import render
from django.utils.translation import gettext as _
def chat(request):
return render(request, 'chat/chat.html', {
'title': _('Chat Box'),
})

13
dmoj/routing.py Normal file
View file

@ -0,0 +1,13 @@
import chat_box.routing
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AuthMiddlewareStack(
URLRouter(
chat_box.routing.websocket_urlpatterns,
),
),
})

View file

@ -236,6 +236,8 @@ INSTALLED_APPS += (
'statici18n',
'impersonate',
'django_jinja',
'chat_box',
'channels',
)
MIDDLEWARE = (
@ -500,3 +502,13 @@ TESTCASE_VISIBLE_LENGTH = 60
DATA_UPLOAD_MAX_NUMBER_FIELDS = 10240
DATA_UPLOAD_MAX_MEMORY_SIZE = 2621440
ASGI_APPLICATION = 'dmoj.routing.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('0.0.0.0', 6379)],
},
},
}

View file

@ -1,3 +1,4 @@
from chat_box.views import chat
from django.conf import settings
from django.conf.urls import include, url
from django.contrib import admin
@ -14,10 +15,9 @@ from judge.feed import AtomBlogFeed, AtomCommentFeed, AtomProblemFeed, BlogFeed,
from judge.forms import CustomAuthenticationForm
from judge.sitemap import BlogPostSitemap, ContestSitemap, HomePageSitemap, OrganizationSitemap, ProblemSitemap, \
SolutionSitemap, UrlSitemap, UserSitemap
from judge.views import TitledTemplateView, api, blog, comment, contests, language, license, mailgun, organization, \
preview, problem, problem_manage, ranked_submission, register, stats, status, submission, tasks, ticket, totp, \
user, widgets
from judge.views.about import about, custom_checker_sample
from judge.views import TitledTemplateView, about, api, blog, comment, contests, language, license, mailgun, \
organization, preview, problem, problem_manage, ranked_submission, register, stats, status, submission, tasks, \
ticket, totp, user, widgets
from judge.views.problem_data import ProblemDataView, ProblemSubmissionDiff, \
problem_data_file, problem_init_view
from judge.views.register import ActivationView, RegistrationView
@ -25,6 +25,7 @@ from judge.views.select2 import AssigneeSelect2View, CommentSelect2View, Contest
ContestUserSearchSelect2View, OrganizationSelect2View, ProblemSelect2View, TicketUserSelect2View, \
UserSearchSelect2View, UserSelect2View
admin.autodiscover()
register_patterns = [
@ -362,9 +363,11 @@ urlpatterns = [
url(r'^progress$', tasks.demo_progress),
])),
url(r'^about/', about, name='about'),
url(r'^about/', about.about, name='about'),
url(r'^custom_checker_sample', custom_checker_sample, name='custom_checker_sample'),
url(r'^custom_checker_sample/', about.custom_checker_sample, name='custom_checker_sample'),
url(r'chat/', chat, name='chat'),
]
favicon_paths = ['apple-touch-icon-180x180.png', 'apple-touch-icon-114x114.png', 'android-chrome-72x72.png',

View file

@ -0,0 +1,21 @@
# Generated by Django 2.2.9 on 2020-01-27 00:59
import django.core.validators
from django.db import migrations, models
import judge.models.problem_data
import judge.utils.problem_data
class Migration(migrations.Migration):
dependencies = [
('judge', '0099_custom_checker'),
]
operations = [
migrations.AlterField(
model_name='problemdata',
name='custom_checker',
field=models.FileField(blank=True, null=True, storage=judge.utils.problem_data.ProblemDataStorage(), upload_to=judge.models.problem_data.problem_directory_file, validators=[django.core.validators.FileExtensionValidator(allowed_extensions=['py'])], verbose_name='custom checker file'),
),
]

View file

@ -30,3 +30,7 @@ packaging
celery
-e git://github.com/DMOJ/ansi2html.git#egg=ansi2html
sqlparse
channels
channels-redis
docker

40
templates/chat/chat.html Normal file
View file

@ -0,0 +1,40 @@
{% extends "base.html" %}
{% block js_media %}
<script type="text/javascript">
var chatSocket = new WebSocket(
'ws://' + window.location.host +
'/ws/chat/');
</script>
<script type="text/javascript">
$(function() {
chatSocket.onmessage = function(e) {
var data = JSON.parse(e.data);
var message = data['message'];
$('#chat-log').append(message + '\n');
};
chatSocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly');
};
$('#chat-message-input').focus();
$('#chat-message-input').keyup(function(e) {
if (e.keyCode === 13) { // enter, return
$('#chat-message-submit').click();
}
});
$("#chat-message-submit").click(function() {
var message = "{{ request.user }}: " + $('input#chat-message-input').val();
chatSocket.send(JSON.stringify({
'message': message,
}));
$('input#chat-message-input').val('');
});
});
</script>
{% endblock js_media %}
{% block body %}
<textarea id="chat-log" cols="100" rows="20"></textarea><br/>
<input id="chat-message-input" type="text" size="100"/><br/>
<button id="chat-message-submit"> Send </button>
{% endblock body %}