general.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. import seaborn
  2. from django.shortcuts import render, get_object_or_404
  3. from django.http import HttpResponseRedirect
  4. from django.urls import reverse
  5. from django.forms import modelformset_factory
  6. #from django.views import generic
  7. from django.contrib.auth.decorators import login_required, permission_required
  8. from website.settings import APPLICATION_NAME
  9. from rotbot.models import Network, Host, Channel, User, Message, Action, Notice, Join, Kick, CurseWord, Adjective, NickReplyMessage, NickReplyAction
  10. from rotbot.forms import CurseWordForm, AdjectiveForm
  11. from rotbot.views.common import default_keywords, shorten_number, total_messages
  12. # Common
  13. def user_stats(name, event_stats, stats=False):
  14. if not stats:
  15. stats = {}
  16. if not event_stats:
  17. for stat in stats:
  18. stats[stat][name] = 0
  19. for stat in event_stats:
  20. if not stat.channel.name in stats:
  21. stats[stat.channel.name] = {}
  22. stats[stat.channel.name][name] = stat.amount
  23. return stats
  24. def index(request):
  25. networks = Network.objects.all()
  26. hosts = Host.objects.all()
  27. channels = Channel.objects.all()
  28. users = User.objects.all()
  29. joins = Join.objects.all()
  30. kicks = Kick.objects.all()
  31. messages = Message.objects.all()
  32. actions = Action.objects.all()
  33. notices = Notice.objects.all()
  34. cursewords = CurseWord.objects.all()
  35. adjectives = Adjective.objects.all()
  36. nickreplymessages = NickReplyMessage.objects.all()
  37. nickreplyactions = NickReplyAction.objects.all()
  38. context = {
  39. 'title': 'RotBot',
  40. 'icon': 'robot',
  41. 'description': 'Index of RotBot',
  42. 'keywords': default_keywords('index'),
  43. 'total_networks':shorten_number(networks.count()),
  44. 'total_hosts':shorten_number(hosts.count()),
  45. 'total_channels':shorten_number(channels.count()),
  46. 'total_users':shorten_number(users.count()),
  47. 'total_joins':shorten_number(joins.count()),
  48. 'total_kicks':shorten_number(kicks.count()),
  49. 'total_messages':shorten_number(messages.count()),
  50. 'total_actions':shorten_number(actions.count()),
  51. 'total_notices':shorten_number(notices.count()),
  52. 'total_cursewords':shorten_number(cursewords.count()),
  53. 'total_adjectives':shorten_number(adjectives.count()),
  54. 'total_nickreplies':shorten_number(nickreplymessages.count() + nickreplyactions.count()),
  55. }
  56. return render(request, 'rotbot/index.html', context)
  57. def user(request, user_slug):
  58. user = get_object_or_404(User, slug=user_slug)
  59. network = Network.objects.get(id=user.network.id)
  60. messages = Message.objects.filter(user=user)
  61. actions = Action.objects.filter(user=user)
  62. notices = Notice.objects.filter(user=user)
  63. joins = Join.objects.filter(user=user)
  64. kicks = Kick.objects.filter(kicker=user)
  65. kicked = Kick.objects.filter(kicked=user)
  66. if user.last_event_type == 'pm':
  67. last_event_type = 'speaking privately'
  68. if user.last_event_type == 'pa':
  69. last_event_type = 'sending a private action'
  70. if user.last_event_type == 'pn':
  71. last_event_type = 'sending a private notice'
  72. if user.last_event_type == 'cm':
  73. last_event_type = 'speaking publicly'
  74. if user.last_event_type == 'ca':
  75. last_event_type = 'sending a public action'
  76. if user.last_event_type == 'cn':
  77. last_event_type = 'sending a public notice'
  78. if user.last_event_type == 'ct':
  79. last_event_type = 'changing the topic'
  80. if user.last_event_type == 'ck':
  81. last_event_type = 'changing the password'
  82. if user.last_event_type == 'ci':
  83. last_event_type = 'inviting'
  84. if user.last_event_type == 'cj':
  85. last_event_type = 'joining'
  86. if user.last_event_type == 'cp':
  87. last_event_type == 'parting'
  88. if user.last_event_type == 'ck':
  89. last_event_type = 'kicking'
  90. if user.last_event_type == 'kd':
  91. last_event_type = 'getting kicked'
  92. if user.last_event_type == 'mc':
  93. last_event_type = 'changing modes'
  94. if user.last_event_type == 'nc':
  95. last_event_type = 'nick change'
  96. if user.last_event_type =='sq':
  97. last_event_type = 'quitting'
  98. stats_dict = None
  99. stats_dict = user_stats('joins', joins, stats=stats_dict)
  100. stats_dict = user_stats('messages', messages, stats=stats_dict)
  101. stats_dict = user_stats('actions', actions, stats=stats_dict)
  102. stats_dict = user_stats('notices', notices, stats=stats_dict)
  103. stats_dict = user_stats('kicks', kicks, stats=stats_dict)
  104. stats_dict = user_stats('kicked', kicked, stats=stats_dict)
  105. labels = list(list(stats_dict.values())[0].keys())
  106. datasets = []
  107. dicts_amount = len(stats_dict)
  108. color_palette = seaborn.color_palette("husl", dicts_amount * 5)
  109. i = 0
  110. for color in color_palette:
  111. color_list = list(color)
  112. color_list[0] *= 255
  113. color_list[1] *= 255
  114. color_list[2] *= 255
  115. color_palette[i] = tuple(color_list)
  116. i += 1
  117. i = 0
  118. for dict in stats_dict:
  119. color_gradient = linear_gradient(color_palette[i], n=4)
  120. print(color_gradient)
  121. datasets.append({
  122. "label": dict,
  123. "data": list(stats_dict[dict].values()),
  124. "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]),],
  125. "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]),],
  126. #"pointBackgroundColor": ['rgba' + str(tuple(color_palette[i+1]))],
  127. #"pointBorderColor": ['rgba' + str(tuple(color_palette[i+3]))],
  128. #"pointStrokeColor": ['rgba' + str(tuple(color_palette[i+4]))],
  129. "hoverBackgroundColor": 'rgba' + str(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])), 'rgba' + str(tuple(color_palette[i+2])),],
  130. "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])),],
  131. #"hoverWidth": 2,
  132. "borderWidth": 1,
  133. #"borderSkipped": False,
  134. })
  135. i += 1
  136. chart = {
  137. "type": "bar",
  138. "data": {
  139. "labels": labels,
  140. "datasets": datasets,
  141. },
  142. "options": {},
  143. }
  144. context = {
  145. 'parent_title': network.name,
  146. 'parent_url': reverse('rotbot:network', args=(network.slug,)),
  147. 'parent_icon': 'sitemap',
  148. 'title': user.name,
  149. 'icon': 'user',
  150. 'description': 'Details of user %s on network %s' % (user.name, network.name),
  151. 'keywords': default_keywords() + '%s, %s' % (network.name, user.name),
  152. 'user': user,
  153. 'network': network,
  154. 'total_messages': shorten_number(total_messages(messages)),
  155. 'total_actions': shorten_number(total_messages(actions)),
  156. 'total_notices': shorten_number(total_messages(notices)),
  157. 'total_joins': shorten_number(joins.count()),
  158. 'total_kicks': shorten_number(kicked.count()),
  159. 'total_kicked': shorten_number(kicked.count()),
  160. 'last_event_type': last_event_type,
  161. 'stats': stats_dict,
  162. 'chart': chart,
  163. }
  164. return render(request, 'rotbot/user.html', context)
  165. def color_dict(gradient):
  166. ''' Takes in a list of RGB sub-lists and returns dictionary of
  167. colors in RGB and hex form for use in a graphing function
  168. defined later on '''
  169. gradients = []
  170. for RGB in gradient:
  171. gradients.append(tuple((RGB[0], RGB[1], RGB[2])))
  172. return tuple(gradients)
  173. # {
  174. # "r":[RGB[0] for RGB in gradient],
  175. # "g":[RGB[1] for RGB in gradient],
  176. # "b":[RGB[2] for RGB in gradient]}
  177. def linear_gradient(start_rgb, finish_hex="#FFFFFF", n=10):
  178. ''' returns a gradient list of (n) colors between
  179. two hex colors. start_hex and finish_hex
  180. should be the full six-digit color string,
  181. inlcuding the number sign ("#FFFFFF") '''
  182. # Starting and ending colors in RGB form
  183. #s = hex_to_RGB(start_hex)
  184. print(n)
  185. s = start_rgb
  186. f = hex_to_RGB(finish_hex)
  187. # Initilize a list of the output colors with the starting color
  188. RGB_list = [s]
  189. # Calcuate a color at each evenly spaced value of t from 1 to n
  190. for t in range(1, n):
  191. # Interpolate RGB vector for color at the current value of t
  192. curr_vector = [
  193. int(s[j] + (float(t)/(n-1))*(f[j]-s[j]))
  194. for j in range(3)
  195. ]
  196. # Add it to our list of output colors
  197. RGB_list.append(curr_vector)
  198. return color_dict(RGB_list)
  199. def hex_to_RGB(hex):
  200. ''' "#FFFFFF" -> [255,255,255] '''
  201. # Pass 16 to the integer function for change of base
  202. return [int(hex[i:i+2], 16) for i in range(1,6,2)]
  203. def RGB_to_hex(RGB):
  204. ''' [255,255,255] -> "#FFFFFF" '''
  205. # Components need to be integers for hex to make sense
  206. RGB = [int(x) for x in RGB]
  207. return "#"+"".join(["0{0:x}".format(v) if v < 16 else
  208. "{0:x}".format(v) for v in RGB])
  209. # from jchart import Chart
  210. # from jchart.config import DataSet
  211. #
  212. # class LineChart(Chart):
  213. #
  214. # chart_type = 'line'
  215. #
  216. # def get_datasets(self, channel_dict, **kwargs):
  217. # print(channel_dict)
  218. # data = []
  219. # for channel in channel_dict:
  220. # print(channel)
  221. # print(channel_dict[channel])
  222. # print(list(channel_dict[channel].values()))
  223. # print(channel_dict[channel].keys())
  224. # list(channel_dict[channel].values())
  225. # data.append(list(channel_dict[channel].values()))
  226. # print(data)
  227. #
  228. # a = DataSet(
  229. # data=data[0]
  230. # )
  231. # foobar = []
  232. # for d in data:
  233. # foobar.append(d)
  234. # return a
  235. # # [
  236. # # DataSet(
  237. # # data=data,
  238. # # #color=(55,55,55),
  239. # # )]
  240. # # [
  241. # # DataSet(
  242. # # data = [69, 30],
  243. # # #data = data
  244. # # color = (255,255,255)
  245. # # ),
  246. # # DataSet(
  247. # # data = [29, 70],
  248. # # #data = data
  249. # # color = (125,125,125)
  250. # # ),
  251. # # ]
  252. #
  253. # def get_labels(self, channel_dict, **kwargs):
  254. #
  255. # return ['Red', 'Blue']
  256. @login_required
  257. @permission_required('rotbot.add_curseword', raise_exception=True)
  258. def add_curseword(request):
  259. CurseWordFormSet = modelformset_factory(CurseWord, form=CurseWordForm, extra=4)
  260. AdjectiveFormSet = modelformset_factory(Adjective, form=AdjectiveForm, extra=4)
  261. if request.method == 'POST':
  262. curseword_formset = CurseWordFormSet(request.POST)
  263. Adjective_formset = AdjectiveFormSet(request.POST)
  264. if curseword_formset.is_valid() and Adjective_formset.is_valid():
  265. curseword_formset.save()
  266. Adjective_formset.save()
  267. return HttpResponseRedirect(reverse('rotbot:networks'))
  268. else:
  269. curseword_formset = CurseWordFormSet(queryset=CurseWord.objects.none())
  270. Adjective_formset = CurseWordFormSet(queryset=Adjective.objects.none())
  271. else: # Not a POST request.
  272. curseword_formset = CurseWordFormSet(queryset=CurseWord.objects.none())
  273. Adjective_formset = AdjectiveFormSet(queryset=Adjective.objects.none())
  274. context = {
  275. 'parent_title': 'RotBot',
  276. 'parent_url': reverse('rotbot:networks'),
  277. 'parent_icon': 'sitemap',
  278. 'title': 'Add curseword',
  279. 'icon': 'book dead',
  280. 'description': 'Add a curseword to RotBot\'s vocabulary.',
  281. 'keywords': default_keywords(),
  282. 'curseword_formset': curseword_formset,
  283. 'Adjective_formset': Adjective_formset,
  284. }
  285. return render(request, 'rotbot/add_curseword.html', context)