import seaborn from django.shortcuts import render, get_object_or_404 from django.http import HttpResponseRedirect from django.urls import reverse from django.forms import modelformset_factory #from django.views import generic from django.contrib.auth.decorators import login_required, permission_required from website.settings import APPLICATION_NAME from rotbot.models import Network, Host, Channel, User, Message, Action, Notice, Join, Kick, CurseWord, CurseAdjective from rotbot.forms import CurseWordForm, CurseAdjectiveForm from rotbot.views.common import default_keywords, shorten_number, total_messages # Common def user_stats(name, event_stats, stats=False): if not stats: stats = {} if not event_stats: for stat in stats: stats[stat][name] = 0 for stat in event_stats: if not stat.channel.name in stats: stats[stat.channel.name] = {} stats[stat.channel.name][name] = stat.amount return stats def index(request): networks = Network.objects.all() hosts = Host.objects.all() channels = Channel.objects.all() users = User.objects.all() joins = Join.objects.all() kicks = Kick.objects.all() messages = Message.objects.all() actions = Action.objects.all() notices = Notice.objects.all() cursewords = CurseWord.objects.all() context = { 'title': 'RotBot', 'icon': 'hashtag', 'description': 'Index of RotBot', 'keywords': default_keywords('index'), 'total_networks':shorten_number(networks.count()), 'total_hosts':shorten_number(hosts.count()), 'total_channels':shorten_number(channels.count()), 'total_users':shorten_number(users.count()), 'total_joins':shorten_number(joins.count()), 'total_kicks':shorten_number(kicks.count()), 'total_messages':shorten_number(messages.count()), 'total_actions':shorten_number(actions.count()), 'total_notices':shorten_number(notices.count()), 'total_cursewords':shorten_number(cursewords.count()), } return render(request, 'rotbot/index.html', context) def user(request, user_slug): user = get_object_or_404(User, slug=user_slug) network = Network.objects.get(id=user.network.id) messages = Message.objects.filter(user=user) actions = Action.objects.filter(user=user) notices = Notice.objects.filter(user=user) joins = Join.objects.filter(user=user) kicks = Kick.objects.filter(kicker=user) kicked = Kick.objects.filter(kicked=user) if user.last_event_type == 'pm': last_event_type = 'speaking privately' if user.last_event_type == 'pa': last_event_type = 'sending a private action' if user.last_event_type == 'pn': last_event_type = 'sending a private notice' if user.last_event_type == 'cm': last_event_type = 'speaking publicly' if user.last_event_type == 'ca': last_event_type = 'sending a public action' if user.last_event_type == 'cn': last_event_type = 'sending a public notice' if user.last_event_type == 'ct': last_event_type = 'changing the topic' if user.last_event_type == 'ck': last_event_type = 'changing the password' if user.last_event_type == 'ci': last_event_type = 'inviting' if user.last_event_type == 'cj': last_event_type = 'joining' if user.last_event_type == 'cp': last_event_type == 'parting' if user.last_event_type == 'ck': last_event_type = 'kicking' if user.last_event_type == 'kd': last_event_type = 'getting kicked' if user.last_event_type == 'mc': last_event_type = 'changing modes' if user.last_event_type == 'nc': last_event_type = 'nick change' if user.last_event_type =='sq': last_event_type = 'quitting' stats_dict = None stats_dict = user_stats('joins', joins, stats=stats_dict) stats_dict = user_stats('messages', messages, stats=stats_dict) stats_dict = user_stats('actions', actions, stats=stats_dict) stats_dict = user_stats('notices', notices, stats=stats_dict) stats_dict = user_stats('kicks', kicks, stats=stats_dict) stats_dict = user_stats('kicked', kicked, stats=stats_dict) labels = list(list(stats_dict.values())[0].keys()) datasets = [] dicts_amount = len(stats_dict) color_palette = seaborn.color_palette("husl", dicts_amount * 5) i = 0 for color in color_palette: color_list = list(color) color_list[0] *= 255 color_list[1] *= 255 color_list[2] *= 255 color_palette[i] = tuple(color_list) i += 1 i = 0 for dict in stats_dict: color_gradient = linear_gradient(color_palette[i], n=87) print(color_gradient) datasets.append({ "label": dict, "data": list(stats_dict[dict].values()), "backgroundColor": 'rgba' + str(color_gradient[i]),#, 'rgba' + str(color_gradient[i]), 'rgba' + str(color_gradient[i]), 'rgba' + str(color_gradient[i]), 'rgba' + str(color_gradient[i]), 'rgba' + str(color_gradient[i]),], "borderColor": 'rgba' + str(color_gradient[i+1]),#, 'rgba' + str(color_gradient[i+1]), 'rgba' + str(color_gradient[i+1]), 'rgba' + str(color_gradient[i+1]), 'rgba' + str(color_gradient[i+1]), 'rgba' + str(color_gradient[i+1]),], #"pointBackgroundColor": ['rgba' + str(tuple(color_palette[i+1]))], #"pointBorderColor": ['rgba' + str(tuple(color_palette[i+3]))], #"pointStrokeColor": ['rgba' + str(tuple(color_palette[i+4]))], "hoverBackgroundColor": 'rgba' + str(color_palette[i+5]),#, 'rgba' + str(tuple(color_palette[i+2])), 'rgba' + str(tuple(color_palette[i+2])), 'rgba' + str(tuple(color_palette[i+2])), 'rgba' + str(tuple(color_palette[i+2])),], "hoverBorderColor": 'rgba' + str(color_palette[i+3]),#, 'rgba' + str(tuple(color_palette[i+3])), 'rgba' + str(tuple(color_palette[i+3])), 'rgba' + str(tuple(color_palette[i+3])), 'rgba' + str(tuple(color_palette[i+3])),], #"hoverWidth": 2, "borderWidth": 1, #"borderSkipped": False, }) i += 1 chart = { "type": "bar", "data": { "labels": labels, "datasets": datasets, }, "options": {}, } context = { 'parent_title': network.name, 'parent_url': reverse('rotbot:network', args=(network.slug,)), 'parent_icon': 'sitemap', 'title': user.name, 'icon': 'hashtag', 'description': 'Details of user %s on network %s' % (user.name, network.name), 'keywords': default_keywords() + '%s, %s' % (network.name, user.name), 'user': user, 'network': network, 'total_messages': shorten_number(total_messages(messages)), 'total_actions': shorten_number(total_messages(actions)), 'total_notices': shorten_number(total_messages(notices)), 'total_joins': shorten_number(joins.count()), 'total_kicks': shorten_number(kicked.count()), 'total_kicked': shorten_number(kicked.count()), 'last_event_type': last_event_type, 'stats': stats_dict, 'chart': chart, } return render(request, 'rotbot/user.html', context) def color_dict(gradient): ''' Takes in a list of RGB sub-lists and returns dictionary of colors in RGB and hex form for use in a graphing function defined later on ''' gradients = [] for RGB in gradient: gradients.append(tuple((RGB[0], RGB[1], RGB[2]))) return tuple(gradients) # { # "r":[RGB[0] for RGB in gradient], # "g":[RGB[1] for RGB in gradient], # "b":[RGB[2] for RGB in gradient]} def linear_gradient(start_rgb, finish_hex="#FFFFFF", n=10): ''' returns a gradient list of (n) colors between two hex colors. start_hex and finish_hex should be the full six-digit color string, inlcuding the number sign ("#FFFFFF") ''' # Starting and ending colors in RGB form #s = hex_to_RGB(start_hex) print(n) s = start_rgb f = hex_to_RGB(finish_hex) # Initilize a list of the output colors with the starting color RGB_list = [s] # Calcuate a color at each evenly spaced value of t from 1 to n for t in range(1, n): # Interpolate RGB vector for color at the current value of t curr_vector = [ int(s[j] + (float(t)/(n-1))*(f[j]-s[j])) for j in range(3) ] # Add it to our list of output colors RGB_list.append(curr_vector) return color_dict(RGB_list) def hex_to_RGB(hex): ''' "#FFFFFF" -> [255,255,255] ''' # Pass 16 to the integer function for change of base return [int(hex[i:i+2], 16) for i in range(1,6,2)] def RGB_to_hex(RGB): ''' [255,255,255] -> "#FFFFFF" ''' # Components need to be integers for hex to make sense RGB = [int(x) for x in RGB] return "#"+"".join(["0{0:x}".format(v) if v < 16 else "{0:x}".format(v) for v in RGB]) # from jchart import Chart # from jchart.config import DataSet # # class LineChart(Chart): # # chart_type = 'line' # # def get_datasets(self, channel_dict, **kwargs): # print(channel_dict) # data = [] # for channel in channel_dict: # print(channel) # print(channel_dict[channel]) # print(list(channel_dict[channel].values())) # print(channel_dict[channel].keys()) # list(channel_dict[channel].values()) # data.append(list(channel_dict[channel].values())) # print(data) # # a = DataSet( # data=data[0] # ) # foobar = [] # for d in data: # foobar.append(d) # return a # # [ # # DataSet( # # data=data, # # #color=(55,55,55), # # )] # # [ # # DataSet( # # data = [69, 30], # # #data = data # # color = (255,255,255) # # ), # # DataSet( # # data = [29, 70], # # #data = data # # color = (125,125,125) # # ), # # ] # # def get_labels(self, channel_dict, **kwargs): # # return ['Red', 'Blue'] @login_required @permission_required('rotbot.add_curseword', raise_exception=True) def add_curseword(request): CurseWordFormSet = modelformset_factory(CurseWord, form=CurseWordForm, extra=4) CurseAdjectiveFormSet = modelformset_factory(CurseAdjective, form=CurseAdjectiveForm, extra=4) if request.method == 'POST': curseword_formset = CurseWordFormSet(request.POST) curseadjective_formset = CurseAdjectiveFormSet(request.POST) if curseword_formset.is_valid() and curseadjective_formset.is_valid(): new_cursewords = curseword_formset.save(commit=False) new_curseadjectives = curseadjective_formset.save(commit=False) for record in new_cursewords: record.word = record.word.lower() record.save() for record in new_curseadjectives: record.word = record.word.lower() record.save() return HttpResponseRedirect(reverse('rotbot:networks')) else: curseword_formset = CurseWordFormSet(queryset=CurseWord.objects.none()) curseadjective_formset = CurseWordFormSet(queryset=CurseAdjective.objects.none()) else: # Not a POST request. curseword_formset = CurseWordFormSet(queryset=CurseWord.objects.none()) curseadjective_formset = CurseAdjectiveFormSet(queryset=CurseAdjective.objects.none()) context = { 'parent_title': 'RotBot', 'parent_url': reverse('rotbot:networks'), 'parent_icon': 'sitemap', 'title': 'Add curseword', 'icon': 'book dead', 'description': 'Add a curseword to RotBot\'s vocabulary.', 'keywords': default_keywords(), 'curseword_formset': curseword_formset, 'curseadjective_formset': curseadjective_formset, } return render(request, 'rotbot/add_curseword.html', context)