-
-
Notifications
You must be signed in to change notification settings - Fork 144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow an organization to connect to slack to receive daily sizzle time log check in alerts to a channel they choose #2973
Comments
Could you please provide some more description on how the flow of this feature should be like ? |
/assign |
Hello @apoorvapendse! You've been assigned to OWASP-BLT/BLT. You have 24 hours to complete a pull request. To place a bid and potentially earn some BCH, type /bid [amount in BCH] [BCH address]. |
This would be like an integration. If you are part of an organization, you can connect your organization to Slack and have a dedicated channel to receive messages from Blt. Those messages will be the daily stand-up items, and the user can have the option to subscribe to other alerts as well. |
⏰ This issue has been automatically unassigned due to 24 hours of inactivity. |
/assign |
Hello @krrish-sehgal! You've been assigned to OWASP-BLT/BLT. You have 24 hours to complete a pull request. To place a bid and potentially earn some BCH, type /bid [amount in BCH] [BCH address]. |
Hey @krrish-sehgal I am actively working on this. |
@apoorvapendse seems like your draft mentioned #2851 and is maybe a subset of this issue, could you confirm what all things from this issue you've implemented. |
yup, Its a WIP PR as mentioned in the PR message in #3003 #2851 is on the user side of things i.e to associate timelogs with an org, whereas this issue is to track the sizzle timelogs allocated by different users to the organization as per my understading |
I request you to kindly pick up some other issue. |
so you are saying your PR needs to be merged before i can start working on this correct ? |
I meant i am working on this. |
Yeah that's another dependency. |
The draft PR for this issue wasn't linked yesterday hence the github bot unassigned me. |
Sure , all yours :) |
/unassign |
/assign |
Hello @apoorvapendse! You've been assigned to OWASP-BLT/BLT. You have 24 hours to complete a pull request. To place a bid and potentially earn some BCH, type /bid [amount in BCH] [BCH address]. |
⏰ This issue has been automatically unassigned due to 24 hours of inactivity. |
⏰ This issue has been automatically unassigned due to 24 hours of inactivity. |
Certainly! Below is the code for a Django application that integrates with Slack to:
• Subscribe to daily scrum updates.
• Manage subscriptions for new bug alerts.
• Receive notifications when time is entered by workers.
This includes models, views, forms, URLs, templates, and utility functions for Slack integration. I’ve also included ways for a company to add, delete, or modify the integration.
First, create a new Django project and app:
django-admin startproject myproject
cd myproject
python manage.py startapp myapp
Add myapp to INSTALLED_APPS in myproject/settings.py:
INSTALLED_APPS = [
# ...
'myapp',
]
a. Subscription Model
Defines user subscriptions for different notification types.
from django.contrib.auth.models import User
from django.db import models
class Subscription(models.Model):
NOTIFICATION_CHOICES = [
('scrum', 'Daily Scrum Updates'),
('bug', 'New Bug Alerts'),
('time_entry', 'Time Entry Notifications'),
]
user = models.ForeignKey(User, on_delete=models.CASCADE)
notification_type = models.CharField(max_length=20, choices=NOTIFICATION_CHOICES)
is_subscribed = models.BooleanField(default=True)
b. ScrumUpdate Model
Stores daily scrum updates submitted by employees.
class ScrumUpdate(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateField(auto_now_add=True)
yesterday = models.TextField()
today = models.TextField()
blockers = models.TextField(blank=True)
c. Bug Model
Represents bugs reported within the system.
class Bug(models.Model):
title = models.CharField(max_length=255)
description = models.TextField()
reported_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
created_at = models.DateTimeField(auto_now_add=True)
d. TimeEntry Model
Records time entries logged by employees.
class TimeEntry(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateField()
hours = models.DecimalField(max_digits=5, decimal_places=2)
description = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
Defines forms for user input.
from django import forms
from .models import ScrumUpdate, TimeEntry, Bug
class ScrumUpdateForm(forms.ModelForm):
class Meta:
model = ScrumUpdate
fields = ['yesterday', 'today', 'blockers']
class TimeEntryForm(forms.ModelForm):
class Meta:
model = TimeEntry
fields = ['date', 'hours', 'description']
class BugForm(forms.ModelForm):
class Meta:
model = Bug
fields = ['title', 'description']
a. Subscription Management
Allows users to manage their notification preferences.
from django.shortcuts import render, redirect
from .models import Subscription
from django.contrib.auth.decorators import login_required
@login_required
def manage_subscriptions(request):
if request.method == 'POST':
for notification_type in ['scrum', 'bug', 'time_entry']:
is_subscribed = request.POST.get(notification_type) == 'on'
Subscription.objects.update_or_create(
user=request.user,
notification_type=notification_type,
defaults={'is_subscribed': is_subscribed}
)
return redirect('manage_subscriptions')
b. Submit Scrum Update
Allows employees to submit their daily scrum updates.
from .models import ScrumUpdate
from .forms import ScrumUpdateForm
@login_required
def submit_scrum_update(request):
if request.method == 'POST':
form = ScrumUpdateForm(request.POST)
if form.is_valid():
scrum_update = form.save(commit=False)
scrum_update.user = request.user
scrum_update.save()
return redirect('submit_scrum_update')
else:
form = ScrumUpdateForm()
return render(request, 'submit_scrum_update.html', {'form': form})
c. Log Time Entry
Allows employees to log their work hours.
from .models import TimeEntry
from .forms import TimeEntryForm
@login_required
def log_time_entry(request):
if request.method == 'POST':
form = TimeEntryForm(request.POST)
if form.is_valid():
time_entry = form.save(commit=False)
time_entry.user = request.user
time_entry.save()
return redirect('log_time_entry')
else:
form = TimeEntryForm()
return render(request, 'log_time_entry.html', {'form': form})
d. Report a Bug
Allows users to report bugs.
from .models import Bug
from .forms import BugForm
@login_required
def report_bug(request):
if request.method == 'POST':
form = BugForm(request.POST)
if form.is_valid():
bug = form.save(commit=False)
bug.reported_by = request.user
bug.save()
return redirect('report_bug')
else:
form = BugForm()
return render(request, 'report_bug.html', {'form': form})
Defines URL patterns for the app.
from django.urls import path
from . import views
urlpatterns = [
path('subscriptions/', views.manage_subscriptions, name='manage_subscriptions'),
path('scrum/', views.submit_scrum_update, name='submit_scrum_update'),
path('time-entry/', views.log_time_entry, name='log_time_entry'),
path('bug-report/', views.report_bug, name='report_bug'),
]
Include the app URLs in your project’s urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('myapp.urls')),
]
a. Base Template (base.html)
<title>MyApp</title> Manage Subscriptions | Submit Scrum Update | Log Time Entry | Report Bug{% block content %} {% endblock %}
b. Manage Subscriptions (manage_subscriptions.html)
{% extends 'base.html' %}
{% block content %}
Manage Subscriptions
{% csrf_token %} {% for choice, label in subscriptions.model.NOTIFICATION_CHOICES %} {{ label }}{% endfor %} Save Preferences {% endblock %}
Note: You might need a custom template filter get_item to access the subscription status.
c. Submit Scrum Update (submit_scrum_update.html)
{% extends 'base.html' %}
{% block content %}
Submit Daily Scrum Update
{% csrf_token %} {{ form.as_p }} Submit {% endblock %}d. Log Time Entry (log_time_entry.html)
{% extends 'base.html' %}
{% block content %}
Log Time Entry
{% csrf_token %} {{ form.as_p }} Log Time {% endblock %}e. Report Bug (report_bug.html)
{% extends 'base.html' %}
{% block content %}
Report a Bug
{% csrf_token %} {{ form.as_p }} Report Bug {% endblock %}a. Install Slack SDK
Install the Slack SDK for Python:
pip install slack-sdk
b. Utility Function to Send Messages
import os
from slack_sdk import WebClient
from slack_sdk.errors import SlackApiError
SLACK_BOT_TOKEN = os.environ.get('SLACK_BOT_TOKEN')
client = WebClient(token=SLACK_BOT_TOKEN)
def send_slack_message(channel_id, text):
try:
response = client.chat_postMessage(
channel=channel_id,
text=text
)
except SlackApiError as e:
print(f"Error sending message: {e.response['error']}")
Set up Celery for asynchronous task handling.
a. Configure Celery (myproject/celery.py)
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
app = Celery('myproject')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
b. Send Daily Scrum Updates Task
from celery import shared_task
from django.utils import timezone
from .models import ScrumUpdate, Subscription
from .utils import send_slack_message
@shared_task
def send_daily_scrum_updates():
today = timezone.now().date()
updates = ScrumUpdate.objects.filter(date=today)
if updates.exists():
message = "Daily Scrum Updates\n"
for update in updates:
message += f"{update.user.username}\n"
message += f"Yesterday: {update.yesterday}\n"
message += f"Today: {update.today}\n"
if update.blockers:
message += f"Blockers: {update.blockers}\n"
message += "\n"
c. Schedule the Task (myproject/settings.py)
from celery.schedules import crontab
CELERY_BEAT_SCHEDULE = {
'send-daily-scrum-updates': {
'task': 'myapp.tasks.send_daily_scrum_updates',
'schedule': crontab(hour=9, minute=0),
},
}
a. Company Model (myapp/models.py)
If you need to manage multiple companies:
class Company(models.Model):
name = models.CharField(max_length=255)
slack_channel_id = models.CharField(max_length=50) # Company's Slack channel
b. Company Forms (myapp/forms.py)
class CompanyForm(forms.ModelForm):
class Meta:
model = Company
fields = ['name', 'slack_channel_id']
c. Company Views (myapp/views.py)
from .models import Company
from .forms import CompanyForm
@login_required
def add_company(request):
if request.method == 'POST':
form = CompanyForm(request.POST)
if form.is_valid():
form.save()
return redirect('company_list')
else:
form = CompanyForm()
return render(request, 'add_company.html', {'form': form})
@login_required
def delete_company(request, company_id):
company = Company.objects.get(id=company_id)
if request.method == 'POST':
company.delete()
return redirect('company_list')
return render(request, 'delete_company.html', {'company': company})
@login_required
def modify_company(request, company_id):
company = Company.objects.get(id=company_id)
if request.method == 'POST':
form = CompanyForm(request.POST, instance=company)
if form.is_valid():
form.save()
return redirect('company_list')
else:
form = CompanyForm(instance=company)
return render(request, 'modify_company.html', {'form': form})
d. Company Templates
{% extends 'base.html' %}
{% block content %}
Add Company
{% csrf_token %} {{ form.as_p }} Add Company {% endblock %}{% extends 'base.html' %}
{% block content %}
Delete Company
Are you sure you want to delete {{ company.name }}?
{% csrf_token %} Delete {% endblock %}{% extends 'base.html' %}
{% block content %}
Modify Company
{% csrf_token %} {{ form.as_p }} Save Changes {% endblock %}e. URLs (myapp/urls.py)
urlpatterns += [
path('company/add/', views.add_company, name='add_company'),
path('company/int:company_id/delete/', views.delete_company, name='delete_company'),
path('company/int:company_id/modify/', views.modify_company, name='modify_company'),
]
How Companies Can Add/Delete/Modify the Integration
• Add Integration: Use the Add Company form to input the company name and Slack channel ID.
• Delete Integration: Use the Delete Company view to remove the company’s integration.
• Modify Integration: Use the Modify Company form to update company details or Slack channel ID.
Running Migrations
Apply the database migrations:
python manage.py makemigrations
python manage.py migrate
Run the development server:
python manage.py runserver
a. Environment Variables
Store sensitive information in environment variables:
• SLACK_BOT_TOKEN
• SLACK_CHANNEL_ID
• SLACK_SIGNING_SECRET (if using Slack events)
b. Setting Up Celery
Start the Celery worker and beat scheduler:
celery -A myproject worker --loglevel=info
celery -A myproject beat --loglevel=info
Notes
• Error Handling: Ensure proper error handling and validation in forms and views.
• Authentication: Use Django’s authentication system to manage user access.
• Permissions: Implement permissions to restrict access to company management views.
• Security: Protect against CSRF and other security vulnerabilities.
• Asynchronous Tasks: Use Celery for sending messages and scheduling tasks.
Conclusion
This code provides a functional Django application with Slack integration for:
• Subscribing to notifications.
• Managing daily scrum updates.
• Reporting bugs.
• Logging time entries.
• Managing company integrations.
Companies can easily add, delete, or modify their integration via the provided web interface.
Feel free to ask if you need further clarification or assistance with specific parts of the code.
The text was updated successfully, but these errors were encountered: