This commit is contained in:
0
mm_msg/__init__.py
Normal file
0
mm_msg/__init__.py
Normal file
12
mm_msg/admin.py
Normal file
12
mm_msg/admin.py
Normal file
@ -0,0 +1,12 @@
|
||||
from django.contrib import admin
|
||||
from .models import Message
|
||||
|
||||
admin.site.register(Message)
|
||||
|
||||
# @admin.register(Message)
|
||||
# class MessageAdmin(admin.ModelAdmin):
|
||||
# list_display = ('text', 'send_time', 'created_at') # 목록에 표시될 필드
|
||||
# search_fields = ('text',) # 검색 가능한 필드
|
||||
# list_filter = ('send_time', 'created_at') # 필터링 가능한 필드
|
||||
# ordering = ('-send_time',) # 정렬 기준
|
||||
# readonly_fields = ('created_at',) # 읽기 전용 필드
|
10
mm_msg/apps.py
Normal file
10
mm_msg/apps.py
Normal file
@ -0,0 +1,10 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class MmMsgConfig(AppConfig):
|
||||
default_auto_field = 'django.db.models.BigAutoField'
|
||||
name = 'mm_msg'
|
||||
|
||||
# 추가
|
||||
def ready(self):
|
||||
from .tasks import scheduler
|
10
mm_msg/forms.py
Normal file
10
mm_msg/forms.py
Normal file
@ -0,0 +1,10 @@
|
||||
from django import forms
|
||||
from .models import Message
|
||||
|
||||
class MessageForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Message
|
||||
fields = ['title', 'text', 'send_time']
|
||||
widgets = {
|
||||
'send_time': forms.DateTimeInput(attrs={'type': 'datetime-local'}),
|
||||
}
|
23
mm_msg/migrations/0001_initial.py
Normal file
23
mm_msg/migrations/0001_initial.py
Normal file
@ -0,0 +1,23 @@
|
||||
# Generated by Django 4.2.14 on 2024-11-25 23:44
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Message',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('text', models.TextField()),
|
||||
('send_time', models.DateTimeField()),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
),
|
||||
]
|
18
mm_msg/migrations/0002_message_title.py
Normal file
18
mm_msg/migrations/0002_message_title.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.14 on 2024-11-25 23:47
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mm_msg', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='message',
|
||||
name='title',
|
||||
field=models.CharField(max_length=100, null=True),
|
||||
),
|
||||
]
|
18
mm_msg/migrations/0003_message_is_sent.py
Normal file
18
mm_msg/migrations/0003_message_is_sent.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 4.2.14 on 2024-11-26 10:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mm_msg', '0002_message_title'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='message',
|
||||
name='is_sent',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
0
mm_msg/migrations/__init__.py
Normal file
0
mm_msg/migrations/__init__.py
Normal file
11
mm_msg/models.py
Normal file
11
mm_msg/models.py
Normal file
@ -0,0 +1,11 @@
|
||||
from django.db import models
|
||||
|
||||
class Message(models.Model):
|
||||
title = models.CharField(max_length=100, null=True) # 메시지 제목
|
||||
text = models.TextField()
|
||||
send_time = models.DateTimeField() # 메시지를 전송할 시간
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
is_sent = models.BooleanField(default=False) # 메시지 전송 여부
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.title} ::: Message scheduled at {self.send_time}"
|
46
mm_msg/tasks.py
Normal file
46
mm_msg/tasks.py
Normal file
@ -0,0 +1,46 @@
|
||||
import os
|
||||
import requests
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
from django.utils.timezone import now
|
||||
from .models import Message
|
||||
from django.db import transaction
|
||||
|
||||
def send_scheduled_messages():
|
||||
mm_url = os.getenv("MM_URL")
|
||||
# debug
|
||||
# print(mm_url)
|
||||
headers = {"Content-Type": "application/json"}
|
||||
# 트랜잭션 시작
|
||||
with transaction.atomic():
|
||||
# 현재 시간 이전의 메시지 중 is_sent가 False인 메시지를 잠금
|
||||
messages = Message.objects.filter(
|
||||
send_time__lte=now(), is_sent=False
|
||||
).select_for_update()
|
||||
|
||||
for message in messages:
|
||||
try:
|
||||
# 메시지 전송
|
||||
data = {"text": f"{message.title}\n{message.text}"}
|
||||
response = requests.post(mm_url, json=data, headers=headers)
|
||||
|
||||
# 성공적으로 전송되면 is_sent를 True로 업데이트
|
||||
if response.status_code == 200:
|
||||
message.is_sent = True
|
||||
message.save()
|
||||
print(
|
||||
f"Sent message: {message.title}, Response: {response.status_code}"
|
||||
)
|
||||
else:
|
||||
print(
|
||||
f"Failed to send message: {message.title}, Response: {response.status_code}"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error sending message: {message.title}, Error: {e}")
|
||||
|
||||
|
||||
scheduler = BackgroundScheduler()
|
||||
# scheduler.add_job(send_scheduled_messages, 'interval', minutes=1) # 1분마다 실행
|
||||
scheduler.add_job(send_scheduled_messages, "interval", seconds=30) # 30초마다 실행
|
||||
|
||||
scheduler.start()
|
72
mm_msg/templates/mm_msg/message_list.html
Normal file
72
mm_msg/templates/mm_msg/message_list.html
Normal file
@ -0,0 +1,72 @@
|
||||
{% extends "components/base.html" %}
|
||||
|
||||
{% block main_area %}
|
||||
<section class="pt-3">
|
||||
<h1>Message Scheduler</h1>
|
||||
|
||||
<!-- Add Message Button -->
|
||||
<button type="button" class="btn btn-primary mb-3" data-bs-toggle="modal" data-bs-target="#messageModal">
|
||||
Add Message
|
||||
</button>
|
||||
|
||||
<!-- Add Message Modal -->
|
||||
<div class="modal fade" id="messageModal" tabindex="-1" aria-labelledby="messageModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="messageModalLabel">Add New Message</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form method="post" action="{% url 'mm_msg:message_create' %}">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="sendTime" class="form-label">Send Time</label>
|
||||
<input type="datetime-local" id="sendTime" name="send_time" class="form-control" required="required">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="title" class="form-label">Title</label>
|
||||
<input type="text" id="title" name="title" class="form-control" placeholder="Enter the message title" required="required">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="text" class="form-label">Message Text</label>
|
||||
<textarea id="text" name="text" class="form-control" rows="4" placeholder="Enter the message text" required="required"></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary w-100">Save Message</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<!-- Scheduled Messages -->
|
||||
<h2>Scheduled Messages</h2>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Message</th>
|
||||
<th>Send Time</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for message in messages %}
|
||||
<tr>
|
||||
<td>{{ message.title }}</td>
|
||||
<td>{{ message.text }}</td>
|
||||
<td>{{ message.send_time }}</td>
|
||||
<td>{{ message.is_sent }}</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="4">No messages scheduled.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
{% endblock %}
|
3
mm_msg/tests.py
Normal file
3
mm_msg/tests.py
Normal file
@ -0,0 +1,3 @@
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
9
mm_msg/urls.py
Normal file
9
mm_msg/urls.py
Normal file
@ -0,0 +1,9 @@
|
||||
from django.urls import path
|
||||
from .views import message_list, message_create
|
||||
|
||||
app_name = 'mm_msg'
|
||||
|
||||
urlpatterns = [
|
||||
path('', message_list, name='message_list'),
|
||||
path('create/', message_create, name='message_create'),
|
||||
]
|
30
mm_msg/views.py
Normal file
30
mm_msg/views.py
Normal file
@ -0,0 +1,30 @@
|
||||
from django.shortcuts import render, redirect
|
||||
from .models import Message
|
||||
from .forms import MessageForm
|
||||
|
||||
def message_list(request):
|
||||
if request.method == 'POST':
|
||||
form = MessageForm(request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return redirect('mm_msg:message_list') # 저장 후 목록으로 리다이렉트
|
||||
else:
|
||||
form = MessageForm()
|
||||
|
||||
messages = Message.objects.all().order_by('send_time') # 시간순으로 정렬
|
||||
return render(request,
|
||||
'mm_msg/message_list.html',
|
||||
{
|
||||
'form': form,
|
||||
'messages': messages
|
||||
}
|
||||
)
|
||||
|
||||
def message_create(request):
|
||||
if request.method == "POST":
|
||||
title = request.POST.get('title')
|
||||
text = request.POST.get('text')
|
||||
send_time = request.POST.get('send_time')
|
||||
Message.objects.create(title=title, text=text, send_time=send_time)
|
||||
return redirect('mm_msg:message_list') # 메시지 목록 페이지로 리다이렉트
|
||||
return render(request, 'mm_msg/message_list.html')
|
Reference in New Issue
Block a user